Merge ../linux-2.6 by hand
diff --git a/CREDITS b/CREDITS
index a347520..5b1edf3 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2247,6 +2247,12 @@
 S: Syracuse, New York 13206
 S: USA
 
+N: Kyle McMartin
+E: kyle@parisc-linux.org
+D: Linux/PARISC hacker
+D: AD1889 sound driver
+S: Ottawa, Canada
+
 N: Dirk Melchers
 E: dirk@merlin.nbg.sub.org
 D: 8 bit XT hard disk driver for OMTI5520
diff --git a/Documentation/Changes b/Documentation/Changes
index 27232be..783ddc3 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -65,7 +65,7 @@
 o  nfs-utils              1.0.5                   # showmount --version
 o  procps                 3.2.0                   # ps --version
 o  oprofile               0.9                     # oprofiled --version
-o  udev                   058                     # udevinfo -V
+o  udev                   071                     # udevinfo -V
 
 Kernel compilation
 ==================
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index d650ce3..4d9b66d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -286,7 +286,9 @@
  -->
 !Edrivers/pci/msi.c
 !Edrivers/pci/bus.c
-!Edrivers/pci/hotplug.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Edrivers/pci/hotplug.c
+-->
 !Edrivers/pci/probe.c
 !Edrivers/pci/rom.c
      </sect1>
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 375ae76..d260d92 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -415,6 +415,362 @@
      </sect1>
   </chapter>
 
+  <chapter id="libataEH">
+        <title>Error handling</title>
+
+	<para>
+	This chapter describes how errors are handled under libata.
+	Readers are advised to read SCSI EH
+	(Documentation/scsi/scsi_eh.txt) and ATA exceptions doc first.
+	</para>
+
+	<sect1><title>Origins of commands</title>
+	<para>
+	In libata, a command is represented with struct ata_queued_cmd
+	or qc.  qc's are preallocated during port initialization and
+	repetitively used for command executions.  Currently only one
+	qc is allocated per port but yet-to-be-merged NCQ branch
+	allocates one for each tag and maps each qc to NCQ tag 1-to-1.
+	</para>
+	<para>
+	libata commands can originate from two sources - libata itself
+	and SCSI midlayer.  libata internal commands are used for
+	initialization and error handling.  All normal blk requests
+	and commands for SCSI emulation are passed as SCSI commands
+	through queuecommand callback of SCSI host template.
+	</para>
+	</sect1>
+
+	<sect1><title>How commands are issued</title>
+
+	<variablelist>
+
+	<varlistentry><term>Internal commands</term>
+	<listitem>
+	<para>
+	First, qc is allocated and initialized using
+	ata_qc_new_init().  Although ata_qc_new_init() doesn't
+	implement any wait or retry mechanism when qc is not
+	available, internal commands are currently issued only during
+	initialization and error recovery, so no other command is
+	active and allocation is guaranteed to succeed.
+	</para>
+	<para>
+	Once allocated qc's taskfile is initialized for the command to
+	be executed.  qc currently has two mechanisms to notify
+	completion.  One is via qc->complete_fn() callback and the
+	other is completion qc->waiting.  qc->complete_fn() callback
+	is the asynchronous path used by normal SCSI translated
+	commands and qc->waiting is the synchronous (issuer sleeps in
+	process context) path used by internal commands.
+	</para>
+	<para>
+	Once initialization is complete, host_set lock is acquired
+	and the qc is issued.
+	</para>
+	</listitem>
+	</varlistentry>
+
+	<varlistentry><term>SCSI commands</term>
+	<listitem>
+	<para>
+	All libata drivers use ata_scsi_queuecmd() as
+	hostt->queuecommand callback.  scmds can either be simulated
+	or translated.  No qc is involved in processing a simulated
+	scmd.  The result is computed right away and the scmd is
+	completed.
+	</para>
+	<para>
+	For a translated scmd, ata_qc_new_init() is invoked to
+	allocate a qc and the scmd is translated into the qc.  SCSI
+	midlayer's completion notification function pointer is stored
+	into qc->scsidone.
+	</para>
+	<para>
+	qc->complete_fn() callback is used for completion
+	notification.  ATA commands use ata_scsi_qc_complete() while
+	ATAPI commands use atapi_qc_complete().  Both functions end up
+	calling qc->scsidone to notify upper layer when the qc is
+	finished.  After translation is completed, the qc is issued
+	with ata_qc_issue().
+	</para>
+	<para>
+	Note that SCSI midlayer invokes hostt->queuecommand while
+	holding host_set lock, so all above occur while holding
+	host_set lock.
+	</para>
+	</listitem>
+	</varlistentry>
+
+	</variablelist>
+	</sect1>
+
+	<sect1><title>How commands are processed</title>
+	<para>
+	Depending on which protocol and which controller are used,
+	commands are processed differently.  For the purpose of
+	discussion, a controller which uses taskfile interface and all
+	standard callbacks is assumed.
+	</para>
+	<para>
+	Currently 6 ATA command protocols are used.  They can be
+	sorted into the following four categories according to how
+	they are processed.
+	</para>
+
+	<variablelist>
+	   <varlistentry><term>ATA NO DATA or DMA</term>
+	   <listitem>
+	   <para>
+	   ATA_PROT_NODATA and ATA_PROT_DMA fall into this category.
+	   These types of commands don't require any software
+	   intervention once issued.  Device will raise interrupt on
+	   completion.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATA PIO</term>
+	   <listitem>
+	   <para>
+	   ATA_PROT_PIO is in this category.  libata currently
+	   implements PIO with polling.  ATA_NIEN bit is set to turn
+	   off interrupt and pio_task on ata_wq performs polling and
+	   IO.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATAPI NODATA or DMA</term>
+	   <listitem>
+	   <para>
+	   ATA_PROT_ATAPI_NODATA and ATA_PROT_ATAPI_DMA are in this
+	   category.  packet_task is used to poll BSY bit after
+	   issuing PACKET command.  Once BSY is turned off by the
+	   device, packet_task transfers CDB and hands off processing
+	   to interrupt handler.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATAPI PIO</term>
+	   <listitem>
+	   <para>
+	   ATA_PROT_ATAPI is in this category.  ATA_NIEN bit is set
+	   and, as in ATAPI NODATA or DMA, packet_task submits cdb.
+	   However, after submitting cdb, further processing (data
+	   transfer) is handed off to pio_task.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+	</variablelist>
+        </sect1>
+
+	<sect1><title>How commands are completed</title>
+	<para>
+	Once issued, all qc's are either completed with
+	ata_qc_complete() or time out.  For commands which are handled
+	by interrupts, ata_host_intr() invokes ata_qc_complete(), and,
+	for PIO tasks, pio_task invokes ata_qc_complete().  In error
+	cases, packet_task may also complete commands.
+	</para>
+	<para>
+	ata_qc_complete() does the following.
+	</para>
+
+	<orderedlist>
+
+	<listitem>
+	<para>
+	DMA memory is unmapped.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	ATA_QCFLAG_ACTIVE is clared from qc->flags.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	qc->complete_fn() callback is invoked.  If the return value of
+	the callback is not zero.  Completion is short circuited and
+	ata_qc_complete() returns.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	__ata_qc_complete() is called, which does
+	   <orderedlist>
+
+	   <listitem>
+	   <para>
+	   qc->flags is cleared to zero.
+	   </para>
+	   </listitem>
+
+	   <listitem>
+	   <para>
+	   ap->active_tag and qc->tag are poisoned.
+	   </para>
+	   </listitem>
+
+	   <listitem>
+	   <para>
+	   qc->waiting is claread &amp; completed (in that order).
+	   </para>
+	   </listitem>
+
+	   <listitem>
+	   <para>
+	   qc is deallocated by clearing appropriate bit in ap->qactive.
+	   </para>
+	   </listitem>
+
+	   </orderedlist>
+	</para>
+	</listitem>
+
+	</orderedlist>
+
+	<para>
+	So, it basically notifies upper layer and deallocates qc.  One
+	exception is short-circuit path in #3 which is used by
+	atapi_qc_complete().
+	</para>
+	<para>
+	For all non-ATAPI commands, whether it fails or not, almost
+	the same code path is taken and very little error handling
+	takes place.  A qc is completed with success status if it
+	succeeded, with failed status otherwise.
+	</para>
+	<para>
+	However, failed ATAPI commands require more handling as
+	REQUEST SENSE is needed to acquire sense data.  If an ATAPI
+	command fails, ata_qc_complete() is invoked with error status,
+	which in turn invokes atapi_qc_complete() via
+	qc->complete_fn() callback.
+	</para>
+	<para>
+	This makes atapi_qc_complete() set scmd->result to
+	SAM_STAT_CHECK_CONDITION, complete the scmd and return 1.  As
+	the sense data is empty but scmd->result is CHECK CONDITION,
+	SCSI midlayer will invoke EH for the scmd, and returning 1
+	makes ata_qc_complete() to return without deallocating the qc.
+	This leads us to ata_scsi_error() with partially completed qc.
+	</para>
+
+	</sect1>
+
+	<sect1><title>ata_scsi_error()</title>
+	<para>
+	ata_scsi_error() is the current hostt->eh_strategy_handler()
+	for libata.  As discussed above, this will be entered in two
+	cases - timeout and ATAPI error completion.  This function
+	calls low level libata driver's eng_timeout() callback, the
+	standard callback for which is ata_eng_timeout().  It checks
+	if a qc is active and calls ata_qc_timeout() on the qc if so.
+	Actual error handling occurs in ata_qc_timeout().
+	</para>
+	<para>
+	If EH is invoked for timeout, ata_qc_timeout() stops BMDMA and
+	completes the qc.  Note that as we're currently in EH, we
+	cannot call scsi_done.  As described in SCSI EH doc, a
+	recovered scmd should be either retried with
+	scsi_queue_insert() or finished with scsi_finish_command().
+	Here, we override qc->scsidone with scsi_finish_command() and
+	calls ata_qc_complete().
+	</para>
+	<para>
+	If EH is invoked due to a failed ATAPI qc, the qc here is
+	completed but not deallocated.  The purpose of this
+	half-completion is to use the qc as place holder to make EH
+	code reach this place.  This is a bit hackish, but it works.
+	</para>
+	<para>
+	Once control reaches here, the qc is deallocated by invoking
+	__ata_qc_complete() explicitly.  Then, internal qc for REQUEST
+	SENSE is issued.  Once sense data is acquired, scmd is
+	finished by directly invoking scsi_finish_command() on the
+	scmd.  Note that as we already have completed and deallocated
+	the qc which was associated with the scmd, we don't need
+	to/cannot call ata_qc_complete() again.
+	</para>
+
+	</sect1>
+
+	<sect1><title>Problems with the current EH</title>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	Error representation is too crude.  Currently any and all
+	error conditions are represented with ATA STATUS and ERROR
+	registers.  Errors which aren't ATA device errors are treated
+	as ATA device errors by setting ATA_ERR bit.  Better error
+	descriptor which can properly represent ATA and other
+	errors/exceptions is needed.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	When handling timeouts, no action is taken to make device
+	forget about the timed out command and ready for new commands.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	EH handling via ata_scsi_error() is not properly protected
+	from usual command processing.  On EH entrance, the device is
+	not in quiescent state.  Timed out commands may succeed or
+	fail any time.  pio_task and atapi_task may still be running.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Too weak error recovery.  Devices / controllers causing HSM
+	mismatch errors and other errors quite often require reset to
+	return to known state.  Also, advanced error handling is
+	necessary to support features like NCQ and hotplug.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	ATA errors are directly handled in the interrupt handler and
+	PIO errors in pio_task.  This is problematic for advanced
+	error handling for the following reasons.
+	</para>
+	<para>
+	First, advanced error handling often requires context and
+	internal qc execution.
+	</para>
+	<para>
+	Second, even a simple failure (say, CRC error) needs
+	information gathering and could trigger complex error handling
+	(say, resetting &amp; reconfiguring).  Having multiple code
+	paths to gather information, enter EH and trigger actions
+	makes life painful.
+	</para>
+	<para>
+	Third, scattered EH code makes implementing low level drivers
+	difficult.  Low level drivers override libata callbacks.  If
+	EH is scattered over several places, each affected callbacks
+	should perform its part of error handling.  This can be error
+	prone and painful.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+	</sect1>
+  </chapter>
+
   <chapter id="libataExt">
      <title>libata Library</title>
 !Edrivers/scsi/libata-core.c
@@ -431,6 +787,722 @@
 !Idrivers/scsi/libata-scsi.c
   </chapter>
 
+  <chapter id="ataExceptions">
+     <title>ATA errors &amp; exceptions</title>
+
+  <para>
+  This chapter tries to identify what error/exception conditions exist
+  for ATA/ATAPI devices and describe how they should be handled in
+  implementation-neutral way.
+  </para>
+
+  <para>
+  The term 'error' is used to describe conditions where either an
+  explicit error condition is reported from device or a command has
+  timed out.
+  </para>
+
+  <para>
+  The term 'exception' is either used to describe exceptional
+  conditions which are not errors (say, power or hotplug events), or
+  to describe both errors and non-error exceptional conditions.  Where
+  explicit distinction between error and exception is necessary, the
+  term 'non-error exception' is used.
+  </para>
+
+  <sect1 id="excat">
+     <title>Exception categories</title>
+     <para>
+     Exceptions are described primarily with respect to legacy
+     taskfile + bus master IDE interface.  If a controller provides
+     other better mechanism for error reporting, mapping those into
+     categories described below shouldn't be difficult.
+     </para>
+
+     <para>
+     In the following sections, two recovery actions - reset and
+     reconfiguring transport - are mentioned.  These are described
+     further in <xref linkend="exrec"/>.
+     </para>
+
+     <sect2 id="excatHSMviolation">
+        <title>HSM violation</title>
+        <para>
+        This error is indicated when STATUS value doesn't match HSM
+        requirement during issuing or excution any ATA/ATAPI command.
+        </para>
+
+	<itemizedlist>
+	<title>Examples</title>
+
+        <listitem>
+	<para>
+	ATA_STATUS doesn't contain !BSY &amp;&amp; DRDY &amp;&amp; !DRQ while trying
+	to issue a command.
+        </para>
+	</listitem>
+
+        <listitem>
+	<para>
+	!BSY &amp;&amp; !DRQ during PIO data transfer.
+        </para>
+	</listitem>
+
+        <listitem>
+	<para>
+	DRQ on command completion.
+        </para>
+	</listitem>
+
+        <listitem>
+	<para>
+	!BSY &amp;&amp; ERR after CDB tranfer starts but before the
+        last byte of CDB is transferred.  ATA/ATAPI standard states
+        that &quot;The device shall not terminate the PACKET command
+        with an error before the last byte of the command packet has
+        been written&quot; in the error outputs description of PACKET
+        command and the state diagram doesn't include such
+        transitions.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	In these cases, HSM is violated and not much information
+	regarding the error can be acquired from STATUS or ERROR
+	register.  IOW, this error can be anything - driver bug,
+	faulty device, controller and/or cable.
+	</para>
+
+	<para>
+	As HSM is violated, reset is necessary to restore known state.
+	Reconfiguring transport for lower speed might be helpful too
+	as transmission errors sometimes cause this kind of errors.
+	</para>
+     </sect2>
+     
+     <sect2 id="excatDevErr">
+        <title>ATA/ATAPI device error (non-NCQ / non-CHECK CONDITION)</title>
+
+	<para>
+	These are errors detected and reported by ATA/ATAPI devices
+	indicating device problems.  For this type of errors, STATUS
+	and ERROR register values are valid and describe error
+	condition.  Note that some of ATA bus errors are detected by
+	ATA/ATAPI devices and reported using the same mechanism as
+	device errors.  Those cases are described later in this
+	section.
+	</para>
+
+	<para>
+	For ATA commands, this type of errors are indicated by !BSY
+	&amp;&amp; ERR during command execution and on completion.
+	</para>
+
+	<para>For ATAPI commands,</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	!BSY &amp;&amp; ERR &amp;&amp; ABRT right after issuing PACKET
+	indicates that PACKET command is not supported and falls in
+	this category.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	!BSY &amp;&amp; ERR(==CHK) &amp;&amp; !ABRT after the last
+	byte of CDB is transferred indicates CHECK CONDITION and
+	doesn't fall in this category.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	!BSY &amp;&amp; ERR(==CHK) &amp;&amp; ABRT after the last byte
+        of CDB is transferred *probably* indicates CHECK CONDITION and
+        doesn't fall in this category.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	Of errors detected as above, the followings are not ATA/ATAPI
+	device errors but ATA bus errors and should be handled
+	according to <xref linkend="excatATAbusErr"/>.
+	</para>
+
+	<variablelist>
+
+	   <varlistentry>
+	   <term>CRC error during data transfer</term>
+	   <listitem>
+	   <para>
+	   This is indicated by ICRC bit in the ERROR register and
+	   means that corruption occurred during data transfer.  Upto
+	   ATA/ATAPI-7, the standard specifies that this bit is only
+	   applicable to UDMA transfers but ATA/ATAPI-8 draft revision
+	   1f says that the bit may be applicable to multiword DMA and
+	   PIO.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry>
+	   <term>ABRT error during data transfer or on completion</term>
+	   <listitem>
+	   <para>
+	   Upto ATA/ATAPI-7, the standard specifies that ABRT could be
+	   set on ICRC errors and on cases where a device is not able
+	   to complete a command.  Combined with the fact that MWDMA
+	   and PIO transfer errors aren't allowed to use ICRC bit upto
+	   ATA/ATAPI-7, it seems to imply that ABRT bit alone could
+	   indicate tranfer errors.
+	   </para>
+	   <para>
+	   However, ATA/ATAPI-8 draft revision 1f removes the part
+	   that ICRC errors can turn on ABRT.  So, this is kind of
+	   gray area.  Some heuristics are needed here.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	</variablelist>
+
+	<para>
+	ATA/ATAPI device errors can be further categorized as follows.
+	</para>
+
+	<variablelist>
+
+	   <varlistentry>
+	   <term>Media errors</term>
+	   <listitem>
+	   <para>
+	   This is indicated by UNC bit in the ERROR register.  ATA
+	   devices reports UNC error only after certain number of
+	   retries cannot recover the data, so there's nothing much
+	   else to do other than notifying upper layer.
+	   </para>
+	   <para>
+	   READ and WRITE commands report CHS or LBA of the first
+	   failed sector but ATA/ATAPI standard specifies that the
+	   amount of transferred data on error completion is
+	   indeterminate, so we cannot assume that sectors preceding
+	   the failed sector have been transferred and thus cannot
+	   complete those sectors successfully as SCSI does.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry>
+	   <term>Media changed / media change requested error</term>
+	   <listitem>
+	   <para>
+	   &lt;&lt;TODO: fill here&gt;&gt;
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>Address error</term>
+	   <listitem>
+	   <para>
+	   This is indicated by IDNF bit in the ERROR register.
+	   Report to upper layer.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>Other errors</term>
+	   <listitem>
+	   <para>
+	   This can be invalid command or parameter indicated by ABRT
+	   ERROR bit or some other error condition.  Note that ABRT
+	   bit can indicate a lot of things including ICRC and Address
+	   errors.  Heuristics needed.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	</variablelist>
+
+	<para>
+	Depending on commands, not all STATUS/ERROR bits are
+	applicable.  These non-applicable bits are marked with
+	&quot;na&quot; in the output descriptions but upto ATA/ATAPI-7
+	no definition of &quot;na&quot; can be found.  However,
+	ATA/ATAPI-8 draft revision 1f describes &quot;N/A&quot; as
+	follows.
+	</para>
+
+	<blockquote>
+	<variablelist>
+	   <varlistentry><term>3.2.3.3a N/A</term>
+	   <listitem>
+	   <para>
+	   A keyword the indicates a field has no defined value in
+	   this standard and should not be checked by the host or
+	   device. N/A fields should be cleared to zero.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+	</variablelist>
+	</blockquote>
+
+	<para>
+	So, it seems reasonable to assume that &quot;na&quot; bits are
+	cleared to zero by devices and thus need no explicit masking.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatATAPIcc">
+        <title>ATAPI device CHECK CONDITION</title>
+
+	<para>
+	ATAPI device CHECK CONDITION error is indicated by set CHK bit
+	(ERR bit) in the STATUS register after the last byte of CDB is
+	transferred for a PACKET command.  For this kind of errors,
+	sense data should be acquired to gather information regarding
+	the errors.  REQUEST SENSE packet command should be used to
+	acquire sense data.
+	</para>
+
+	<para>
+	Once sense data is acquired, this type of errors can be
+	handled similary to other SCSI errors.  Note that sense data
+	may indicate ATA bus error (e.g. Sense Key 04h HARDWARE ERROR
+	&amp;&amp; ASC/ASCQ 47h/00h SCSI PARITY ERROR).  In such
+	cases, the error should be considered as an ATA bus error and
+	handled according to <xref linkend="excatATAbusErr"/>.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatNCQerr">
+        <title>ATA device error (NCQ)</title>
+
+	<para>
+	NCQ command error is indicated by cleared BSY and set ERR bit
+	during NCQ command phase (one or more NCQ commands
+	outstanding).  Although STATUS and ERROR registers will
+	contain valid values describing the error, READ LOG EXT is
+	required to clear the error condition, determine which command
+	has failed and acquire more information.
+	</para>
+
+	<para>
+	READ LOG EXT Log Page 10h reports which tag has failed and
+	taskfile register values describing the error.  With this
+	information the failed command can be handled as a normal ATA
+	command error as in <xref linkend="excatDevErr"/> and all
+	other in-flight commands must be retried.  Note that this
+	retry should not be counted - it's likely that commands
+	retried this way would have completed normally if it were not
+	for the failed command.
+	</para>
+
+	<para>
+	Note that ATA bus errors can be reported as ATA device NCQ
+	errors.  This should be handled as described in <xref
+	linkend="excatATAbusErr"/>.
+	</para>
+
+	<para>
+	If READ LOG EXT Log Page 10h fails or reports NQ, we're
+	thoroughly screwed.  This condition should be treated
+	according to <xref linkend="excatHSMviolation"/>.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatATAbusErr">
+        <title>ATA bus error</title>
+
+	<para>
+	ATA bus error means that data corruption occurred during
+	transmission over ATA bus (SATA or PATA).  This type of errors
+	can be indicated by
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	ICRC or ABRT error as described in <xref linkend="excatDevErr"/>.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Controller-specific error completion with error information
+	indicating transmission error.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	On some controllers, command timeout.  In this case, there may
+	be a mechanism to determine that the timeout is due to
+	transmission error.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Unknown/random errors, timeouts and all sorts of weirdities.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	As described above, transmission errors can cause wide variety
+	of symptoms ranging from device ICRC error to random device
+	lockup, and, for many cases, there is no way to tell if an
+	error condition is due to transmission error or not;
+	therefore, it's necessary to employ some kind of heuristic
+	when dealing with errors and timeouts.  For example,
+	encountering repetitive ABRT errors for known supported
+	command is likely to indicate ATA bus error.
+	</para>
+
+	<para>
+	Once it's determined that ATA bus errors have possibly
+	occurred, lowering ATA bus transmission speed is one of
+	actions which may alleviate the problem.  See <xref
+	linkend="exrecReconf"/> for more information.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatPCIbusErr">
+        <title>PCI bus error</title>
+
+	<para>
+	Data corruption or other failures during transmission over PCI
+	(or other system bus).  For standard BMDMA, this is indicated
+	by Error bit in the BMDMA Status register.  This type of
+	errors must be logged as it indicates something is very wrong
+	with the system.  Resetting host controller is recommended.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatLateCompletion">
+        <title>Late completion</title>
+
+	<para>
+	This occurs when timeout occurs and the timeout handler finds
+	out that the timed out command has completed successfully or
+	with error.  This is usually caused by lost interrupts.  This
+	type of errors must be logged.  Resetting host controller is
+	recommended.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatUnknown">
+        <title>Unknown error (timeout)</title>
+
+	<para>
+	This is when timeout occurs and the command is still
+	processing or the host and device are in unknown state.  When
+	this occurs, HSM could be in any valid or invalid state.  To
+	bring the device to known state and make it forget about the
+	timed out command, resetting is necessary.  The timed out
+	command may be retried.
+	</para>
+
+	<para>
+	Timeouts can also be caused by transmission errors.  Refer to
+	<xref linkend="excatATAbusErr"/> for more details.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatHoplugPM">
+        <title>Hotplug and power management exceptions</title>
+
+	<para>
+	&lt;&lt;TODO: fill here&gt;&gt;
+	</para>
+
+     </sect2>
+
+  </sect1>
+
+  <sect1 id="exrec">
+     <title>EH recovery actions</title>
+
+     <para>
+     This section discusses several important recovery actions.
+     </para>
+
+     <sect2 id="exrecClr">
+        <title>Clearing error condition</title>
+
+	<para>
+	Many controllers require its error registers to be cleared by
+	error handler.  Different controllers may have different
+	requirements.
+	</para>
+
+	<para>
+	For SATA, it's strongly recommended to clear at least SError
+	register during error handling.
+	</para>
+     </sect2>
+
+     <sect2 id="exrecRst">
+        <title>Reset</title>
+
+	<para>
+	During EH, resetting is necessary in the following cases.
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	HSM is in unknown or invalid state
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	HBA is in unknown or invalid state
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	EH needs to make HBA/device forget about in-flight commands
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	HBA/device behaves weirdly
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	Resetting during EH might be a good idea regardless of error
+	condition to improve EH robustness.  Whether to reset both or
+	either one of HBA and device depends on situation but the
+	following scheme is recommended.
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	When it's known that HBA is in ready state but ATA/ATAPI
+	device in in unknown state, reset only device.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	If HBA is in unknown state, reset both HBA and device.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	HBA resetting is implementation specific.  For a controller
+	complying to taskfile/BMDMA PCI IDE, stopping active DMA
+	transaction may be sufficient iff BMDMA state is the only HBA
+	context.  But even mostly taskfile/BMDMA PCI IDE complying
+	controllers may have implementation specific requirements and
+	mechanism to reset themselves.  This must be addressed by
+	specific drivers.
+	</para>
+
+	<para>
+	OTOH, ATA/ATAPI standard describes in detail ways to reset
+	ATA/ATAPI devices.
+	</para>
+
+	<variablelist>
+
+	   <varlistentry><term>PATA hardware reset</term>
+	   <listitem>
+	   <para>
+	   This is hardware initiated device reset signalled with
+	   asserted PATA RESET- signal.  There is no standard way to
+	   initiate hardware reset from software although some
+	   hardware provides registers that allow driver to directly
+	   tweak the RESET- signal.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>Software reset</term>
+	   <listitem>
+	   <para>
+	   This is achieved by turning CONTROL SRST bit on for at
+	   least 5us.  Both PATA and SATA support it but, in case of
+	   SATA, this may require controller-specific support as the
+	   second Register FIS to clear SRST should be transmitted
+	   while BSY bit is still set.  Note that on PATA, this resets
+	   both master and slave devices on a channel.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>EXECUTE DEVICE DIAGNOSTIC command</term>
+	   <listitem>
+	   <para>
+	   Although ATA/ATAPI standard doesn't describe exactly, EDD
+	   implies some level of resetting, possibly similar level
+	   with software reset.  Host-side EDD protocol can be handled
+	   with normal command processing and most SATA controllers
+	   should be able to handle EDD's just like other commands.
+	   As in software reset, EDD affects both devices on a PATA
+	   bus.
+	   </para>
+	   <para>
+	   Although EDD does reset devices, this doesn't suit error
+	   handling as EDD cannot be issued while BSY is set and it's
+	   unclear how it will act when device is in unknown/weird
+	   state.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATAPI DEVICE RESET command</term>
+	   <listitem>
+	   <para>
+	   This is very similar to software reset except that reset
+	   can be restricted to the selected device without affecting
+	   the other device sharing the cable.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>SATA phy reset</term>
+	   <listitem>
+	   <para>
+	   This is the preferred way of resetting a SATA device.  In
+	   effect, it's identical to PATA hardware reset.  Note that
+	   this can be done with the standard SCR Control register.
+	   As such, it's usually easier to implement than software
+	   reset.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	</variablelist>
+
+	<para>
+	One more thing to consider when resetting devices is that
+	resetting clears certain configuration parameters and they
+	need to be set to their previous or newly adjusted values
+	after reset.
+	</para>
+
+	<para>
+	Parameters affected are.
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	CHS set up with INITIALIZE DEVICE PARAMETERS (seldomly used)
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Parameters set with SET FEATURES including transfer mode setting
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Block count set with SET MULTIPLE MODE
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Other parameters (SET MAX, MEDIA LOCK...)
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	ATA/ATAPI standard specifies that some parameters must be
+	maintained across hardware or software reset, but doesn't
+	strictly specify all of them.  Always reconfiguring needed
+	parameters after reset is required for robustness.  Note that
+	this also applies when resuming from deep sleep (power-off).
+	</para>
+
+	<para>
+	Also, ATA/ATAPI standard requires that IDENTIFY DEVICE /
+	IDENTIFY PACKET DEVICE is issued after any configuration
+	parameter is updated or a hardware reset and the result used
+	for further operation.  OS driver is required to implement
+	revalidation mechanism to support this.
+	</para>
+
+     </sect2>
+
+     <sect2 id="exrecReconf">
+        <title>Reconfigure transport</title>
+
+	<para>
+	For both PATA and SATA, a lot of corners are cut for cheap
+	connectors, cables or controllers and it's quite common to see
+	high transmission error rate.  This can be mitigated by
+	lowering transmission speed.
+	</para>
+
+	<para>
+	The following is a possible scheme Jeff Garzik suggested.
+	</para>
+
+	<blockquote>
+	<para>
+	If more than $N (3?) transmission errors happen in 15 minutes,
+	</para>	
+	<itemizedlist>
+	<listitem>
+	<para>
+	if SATA, decrease SATA PHY speed.  if speed cannot be decreased,
+	</para>
+	</listitem>
+	<listitem>
+	<para>
+	decrease UDMA xfer speed.  if at UDMA0, switch to PIO4,
+	</para>
+	</listitem>
+	<listitem>
+	<para>
+	decrease PIO xfer speed.  if at PIO3, complain, but continue
+	</para>
+	</listitem>
+	</itemizedlist>
+	</blockquote>
+
+     </sect2>
+
+  </sect1>
+
+  </chapter>
+
   <chapter id="PiixInt">
      <title>ata_piix Internals</title>
 !Idrivers/scsi/ata_piix.c
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 705c442..15ce0f2 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -291,7 +291,7 @@
 
 !Edrivers/usb/core/hcd.c
 !Edrivers/usb/core/hcd-pci.c
-!Edrivers/usb/core/buffer.c
+!Idrivers/usb/core/buffer.c
     </chapter>
 
     <chapter>
diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl
index 51f3bfb..008a341 100644
--- a/Documentation/DocBook/writing_usb_driver.tmpl
+++ b/Documentation/DocBook/writing_usb_driver.tmpl
@@ -345,8 +345,7 @@
   <programlisting>
 static inline void skel_delete (struct usb_skel *dev)
 {
-    if (dev->bulk_in_buffer != NULL)
-        kfree (dev->bulk_in_buffer);
+    kfree (dev->bulk_in_buffer);
     if (dev->bulk_out_buffer != NULL)
         usb_buffer_free (dev->udev, dev->bulk_out_size,
             dev->bulk_out_buffer,
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
new file mode 100644
index 0000000..e4c3815
--- /dev/null
+++ b/Documentation/RCU/torture.txt
@@ -0,0 +1,122 @@
+RCU Torture Test Operation
+
+
+CONFIG_RCU_TORTURE_TEST
+
+The CONFIG_RCU_TORTURE_TEST config option is available for all RCU
+implementations.  It creates an rcutorture kernel module that can
+be loaded to run a torture test.  The test periodically outputs
+status messages via printk(), which can be examined via the dmesg
+command (perhaps grepping for "rcutorture").  The test is started
+when the module is loaded, and stops when the module is unloaded.
+
+However, actually setting this config option to "y" results in the system
+running the test immediately upon boot, and ending only when the system
+is taken down.  Normally, one will instead want to build the system
+with CONFIG_RCU_TORTURE_TEST=m and to use modprobe and rmmod to control
+the test, perhaps using a script similar to the one shown at the end of
+this document.  Note that you will need CONFIG_MODULE_UNLOAD in order
+to be able to end the test.
+
+
+MODULE PARAMETERS
+
+This module has the following parameters:
+
+nreaders	This is the number of RCU reading threads supported.
+		The default is twice the number of CPUs.  Why twice?
+		To properly exercise RCU implementations with preemptible
+		read-side critical sections.
+
+stat_interval	The number of seconds between output of torture
+		statistics (via printk()).  Regardless of the interval,
+		statistics are printed when the module is unloaded.
+		Setting the interval to zero causes the statistics to
+		be printed -only- when the module is unloaded, and this
+		is the default.
+
+verbose		Enable debug printk()s.  Default is disabled.
+
+
+OUTPUT
+
+The statistics output is as follows:
+
+	rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
+	rcutorture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
+	rcutorture: Reader Pipe:  1466408 9747 0 0 0 0 0 0 0 0 0
+	rcutorture: Reader Batch:  1464477 11678 0 0 0 0 0 0 0 0
+	rcutorture: Free-Block Circulation:  1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
+	rcutorture: --- End of test
+
+The command "dmesg | grep rcutorture:" will extract this information on
+most systems.  On more esoteric configurations, it may be necessary to
+use other commands to access the output of the printk()s used by
+the RCU torture test.  The printk()s use KERN_ALERT, so they should
+be evident.  ;-)
+
+The entries are as follows:
+
+o	"ggp": The number of counter flips (or batches) since boot.
+
+o	"rtc": The hexadecimal address of the structure currently visible
+	to readers.
+
+o	"ver": The number of times since boot that the rcutw writer task
+	has changed the structure visible to readers.
+
+o	"tfle": If non-zero, indicates that the "torture freelist"
+	containing structure to be placed into the "rtc" area is empty.
+	This condition is important, since it can fool you into thinking
+	that RCU is working when it is not.  :-/
+
+o	"rta": Number of structures allocated from the torture freelist.
+
+o	"rtaf": Number of allocations from the torture freelist that have
+	failed due to the list being empty.
+
+o	"rtf": Number of frees into the torture freelist.
+
+o	"Reader Pipe": Histogram of "ages" of structures seen by readers.
+	If any entries past the first two are non-zero, RCU is broken.
+	And rcutorture prints the error flag string "!!!" to make sure
+	you notice.  The age of a newly allocated structure is zero,
+	it becomes one when removed from reader visibility, and is
+	incremented once per grace period subsequently -- and is freed
+	after passing through (RCU_TORTURE_PIPE_LEN-2) grace periods.
+
+	The output displayed above was taken from a correctly working
+	RCU.  If you want to see what it looks like when broken, break
+	it yourself.  ;-)
+
+o	"Reader Batch": Another histogram of "ages" of structures seen
+	by readers, but in terms of counter flips (or batches) rather
+	than in terms of grace periods.  The legal number of non-zero
+	entries is again two.  The reason for this separate view is
+	that it is easier to get the third entry to show up in the
+	"Reader Batch" list than in the "Reader Pipe" list.
+
+o	"Free-Block Circulation": Shows the number of torture structures
+	that have reached a given point in the pipeline.  The first element
+	should closely correspond to the number of structures allocated,
+	the second to the number that have been removed from reader view,
+	and all but the last remaining to the corresponding number of
+	passes through a grace period.  The last entry should be zero,
+	as it is only incremented if a torture structure's counter
+	somehow gets incremented farther than it should.
+
+
+USAGE
+
+The following script may be used to torture RCU:
+
+	#!/bin/sh
+
+	modprobe rcutorture
+	sleep 100
+	rmmod rcutorture
+	dmesg | grep rcutorture:
+
+The output can be manually inspected for the error flag of "!!!".
+One could of course create a more elaborate script that automatically
+checked for such errors.
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 6dd274d..2d65c21 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -906,9 +906,20 @@
 
 
 4. The I/O scheduler
-I/O schedulers are now per queue. They should be runtime switchable and modular
-but aren't yet. Jens has most bits to do this, but the sysfs implementation is
-missing.
+I/O scheduler, a.k.a. elevator, is implemented in two layers.  Generic dispatch
+queue and specific I/O schedulers.  Unless stated otherwise, elevator is used
+to refer to both parts and I/O scheduler to specific I/O schedulers.
+
+Block layer implements generic dispatch queue in ll_rw_blk.c and elevator.c.
+The generic dispatch queue is responsible for properly ordering barrier
+requests, requeueing, handling non-fs requests and all other subtleties.
+
+Specific I/O schedulers are responsible for ordering normal filesystem
+requests.  They can also choose to delay certain requests to improve
+throughput or whatever purpose.  As the plural form indicates, there are
+multiple I/O schedulers.  They can be built as modules but at least one should
+be built inside the kernel.  Each queue can choose different one and can also
+change to another one dynamically.
 
 A block layer call to the i/o scheduler follows the convention elv_xxx(). This
 calls elevator_xxx_fn in the elevator switch (drivers/block/elevator.c). Oh,
@@ -921,44 +932,36 @@
 The functions an elevator may implement are: (* are mandatory)
 elevator_merge_fn		called to query requests for merge with a bio
 
-elevator_merge_req_fn		" " "  with another request
+elevator_merge_req_fn		called when two requests get merged. the one
+				which gets merged into the other one will be
+				never seen by I/O scheduler again. IOW, after
+				being merged, the request is gone.
 
 elevator_merged_fn		called when a request in the scheduler has been
 				involved in a merge. It is used in the deadline
 				scheduler for example, to reposition the request
 				if its sorting order has changed.
 
-*elevator_next_req_fn		returns the next scheduled request, or NULL
-				if there are none (or none are ready).
+elevator_dispatch_fn		fills the dispatch queue with ready requests.
+				I/O schedulers are free to postpone requests by
+				not filling the dispatch queue unless @force
+				is non-zero.  Once dispatched, I/O schedulers
+				are not allowed to manipulate the requests -
+				they belong to generic dispatch queue.
 
-*elevator_add_req_fn		called to add a new request into the scheduler
+elevator_add_req_fn		called to add a new request into the scheduler
 
 elevator_queue_empty_fn		returns true if the merge queue is empty.
 				Drivers shouldn't use this, but rather check
 				if elv_next_request is NULL (without losing the
 				request if one exists!)
 
-elevator_remove_req_fn		This is called when a driver claims ownership of
-				the target request - it now belongs to the
-				driver. It must not be modified or merged.
-				Drivers must not lose the request! A subsequent
-				call of elevator_next_req_fn must  return the
-				_next_ request.
-
-elevator_requeue_req_fn		called to add a request to the scheduler. This
-				is used when the request has alrnadebeen
-				returned by elv_next_request, but hasn't
-				completed. If this is not implemented then
-				elevator_add_req_fn is called instead.
-
 elevator_former_req_fn
 elevator_latter_req_fn		These return the request before or after the
 				one specified in disk sort order. Used by the
 				block layer to find merge possibilities.
 
-elevator_completed_req_fn	called when a request is completed. This might
-				come about due to being merged with another or
-				when the device completes the request.
+elevator_completed_req_fn	called when a request is completed.
 
 elevator_may_queue_fn		returns true if the scheduler wants to allow the
 				current context to queue a new request even if
@@ -967,13 +970,33 @@
 
 elevator_set_req_fn
 elevator_put_req_fn		Must be used to allocate and free any elevator
-				specific storate for a request.
+				specific storage for a request.
+
+elevator_activate_req_fn	Called when device driver first sees a request.
+				I/O schedulers can use this callback to
+				determine when actual execution of a request
+				starts.
+elevator_deactivate_req_fn	Called when device driver decides to delay
+				a request by requeueing it.
 
 elevator_init_fn
 elevator_exit_fn		Allocate and free any elevator specific storage
 				for a queue.
 
-4.2 I/O scheduler implementation
+4.2 Request flows seen by I/O schedulers
+All requests seens by I/O schedulers strictly follow one of the following three
+flows.
+
+ set_req_fn ->
+
+ i.   add_req_fn -> (merged_fn ->)* -> dispatch_fn -> activate_req_fn ->
+      (deactivate_req_fn -> activate_req_fn ->)* -> completed_req_fn
+ ii.  add_req_fn -> (merged_fn ->)* -> merge_req_fn
+ iii. [none]
+
+ -> put_req_fn
+
+4.3 I/O scheduler implementation
 The generic i/o scheduler algorithm attempts to sort/merge/batch requests for
 optimal disk scan and request servicing performance (based on generic
 principles and device capabilities), optimized for:
@@ -993,18 +1016,7 @@
 This arrangement is not a generic block layer characteristic however, so
 elevators may implement queues as they please.
 
-ii. Last merge hint
-The last merge hint is part of the generic queue layer. I/O schedulers must do
-some management on it. For the most part, the most important thing is to make
-sure q->last_merge is cleared (set to NULL) when the request on it is no longer
-a candidate for merging (for example if it has been sent to the driver).
-
-The last merge performed is cached as a hint for the subsequent request. If
-sequential data is being submitted, the hint is used to perform merges without
-any scanning. This is not sufficient when there are multiple processes doing
-I/O though, so a "merge hash" is used by some schedulers.
-
-iii. Merge hash
+ii. Merge hash
 AS and deadline use a hash table indexed by the last sector of a request. This
 enables merging code to quickly look up "back merge" candidates, even when
 multiple I/O streams are being performed at once on one disk.
@@ -1013,29 +1025,8 @@
 are far less common than "back merges" due to the nature of most I/O patterns.
 Front merges are handled by the binary trees in AS and deadline schedulers.
 
-iv. Handling barrier cases
-A request with flags REQ_HARDBARRIER or REQ_SOFTBARRIER must not be ordered
-around. That is, they must be processed after all older requests, and before
-any newer ones. This includes merges!
-
-In AS and deadline schedulers, barriers have the effect of flushing the reorder
-queue. The performance cost of this will vary from nothing to a lot depending
-on i/o patterns and device characteristics. Obviously they won't improve
-performance, so their use should be kept to a minimum.
-
-v. Handling insertion position directives
-A request may be inserted with a position directive. The directives are one of
-ELEVATOR_INSERT_BACK, ELEVATOR_INSERT_FRONT, ELEVATOR_INSERT_SORT.
-
-ELEVATOR_INSERT_SORT is a general directive for non-barrier requests.
-ELEVATOR_INSERT_BACK is used to insert a barrier to the back of the queue.
-ELEVATOR_INSERT_FRONT is used to insert a barrier to the front of the queue, and
-overrides the ordering requested by any previous barriers. In practice this is
-harmless and required, because it is used for SCSI requeueing. This does not
-require flushing the reorder queue, so does not impose a performance penalty.
-
-vi. Plugging the queue to batch requests in anticipation of opportunities for
-  merge/sort optimizations
+iii. Plugging the queue to batch requests in anticipation of opportunities for
+     merge/sort optimizations
 
 This is just the same as in 2.4 so far, though per-device unplugging
 support is anticipated for 2.5. Also with a priority-based i/o scheduler,
@@ -1069,7 +1060,7 @@
   blk_kick_queue() to unplug a specific queue (right away ?)
   or optionally, all queues, is in the plan.
 
-4.3 I/O contexts
+4.4 I/O contexts
 I/O contexts provide a dynamically allocated per process data area. They may
 be used in I/O schedulers, and in the block layer (could be used for IO statis,
 priorities for example). See *io_context in drivers/block/ll_rw_blk.c, and
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index e132fb1..7eb715e 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -49,9 +49,6 @@
 	page table operations such as what happens during
 	fork, and exec.
 
-	Platform developers note that generic code will always
-	invoke this interface without mm->page_table_lock held.
-
 3) void flush_tlb_range(struct vm_area_struct *vma,
 			unsigned long start, unsigned long end)
 
@@ -72,9 +69,6 @@
 	call flush_tlb_page (see below) for each entry which may be
 	modified.
 
-	Platform developers note that generic code will always
-	invoke this interface with mm->page_table_lock held.
-
 4) void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
 
 	This time we need to remove the PAGE_SIZE sized translation
@@ -93,9 +87,6 @@
 
 	This is used primarily during fault processing.
 
-	Platform developers note that generic code will always
-	invoke this interface with mm->page_table_lock held.
-
 5) void flush_tlb_pgtables(struct mm_struct *mm,
 			   unsigned long start, unsigned long end)
 
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index d17b7d2..a09a8eb 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -94,7 +94,7 @@
 But larger systems, which benefit more from careful processor and
 memory placement to reduce memory access times and contention,
 and which typically represent a larger investment for the customer,
-can benefit from explictly placing jobs on properly sized subsets of
+can benefit from explicitly placing jobs on properly sized subsets of
 the system.
 
 This can be especially valuable on:
diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
index fabaca1..59806c9 100644
--- a/Documentation/driver-model/driver.txt
+++ b/Documentation/driver-model/driver.txt
@@ -14,8 +14,8 @@
         int     (*probe)        (struct device * dev);
         int     (*remove)       (struct device * dev);
 
-        int     (*suspend)      (struct device * dev, pm_message_t state, u32 level);
-        int     (*resume)       (struct device * dev, u32 level);
+        int     (*suspend)      (struct device * dev, pm_message_t state);
+        int     (*resume)       (struct device * dev);
 };
 
 
@@ -194,69 +194,13 @@
 If the device is still present, it should quiesce the device and place
 it into a supported low-power state.
 
-	int	(*suspend)	(struct device * dev, pm_message_t state, u32 level);
+	int	(*suspend)	(struct device * dev, pm_message_t state);
 
-suspend is called to put the device in a low power state. There are
-several stages to successfully suspending a device, which is denoted in
-the @level parameter. Breaking the suspend transition into several
-stages affords the platform flexibility in performing device power
-management based on the requirements of the system and the
-user-defined policy.
+suspend is called to put the device in a low power state.
 
-SUSPEND_NOTIFY notifies the device that a suspend transition is about
-to happen. This happens on system power state transitions to verify
-that all devices can successfully suspend.
+	int	(*resume)	(struct device * dev);
 
-A driver may choose to fail on this call, which should cause the
-entire suspend transition to fail. A driver should fail only if it
-knows that the device will not be able to be resumed properly when the
-system wakes up again. It could also fail if it somehow determines it
-is in the middle of an operation too important to stop.
-
-SUSPEND_DISABLE tells the device to stop I/O transactions. When it
-stops transactions, or what it should do with unfinished transactions
-is a policy of the driver. After this call, the driver should not
-accept any other I/O requests.
-
-SUSPEND_SAVE_STATE tells the device to save the context of the
-hardware. This includes any bus-specific hardware state and
-device-specific hardware state. A pointer to this saved state can be
-stored in the device's saved_state field.
-
-SUSPEND_POWER_DOWN tells the driver to place the device in the low
-power state requested. 
-
-Whether suspend is called with a given level is a policy of the
-platform. Some levels may be omitted; drivers must not assume the
-reception of any level. However, all levels must be called in the
-order above; i.e. notification will always come before disabling;
-disabling the device will come before suspending the device.
-
-All calls are made with interrupts enabled, except for the
-SUSPEND_POWER_DOWN level.
-
-	int	(*resume)	(struct device * dev, u32 level);
-
-Resume is used to bring a device back from a low power state. Like the
-suspend transition, it happens in several stages. 
-
-RESUME_POWER_ON tells the driver to set the power state to the state
-before the suspend call (The device could have already been in a low
-power state before the suspend call to put in a lower power state). 
-
-RESUME_RESTORE_STATE tells the driver to restore the state saved by
-the SUSPEND_SAVE_STATE suspend call. 
-
-RESUME_ENABLE tells the driver to start accepting I/O transactions
-again. Depending on driver policy, the device may already have pending
-I/O requests. 
-
-RESUME_POWER_ON is called with interrupts disabled. The other resume
-levels are called with interrupts enabled. 
-
-As with the various suspend stages, the driver must not assume that
-any other resume calls have been or will be made. Each call should be
-self-contained and not dependent on any external state.
+Resume is used to bring a device back from a low power state.
 
 
 Attributes
diff --git a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt
index ff2fef2..98b233c 100644
--- a/Documentation/driver-model/porting.txt
+++ b/Documentation/driver-model/porting.txt
@@ -350,7 +350,7 @@
 over. bus->match() is called for each device that is not already
 claimed by a driver. 
 
-When a device is successfully bound to a device, device->driver is
+When a device is successfully bound to a driver, device->driver is
 set, the device is added to a per-driver list of devices, and a
 symlink is created in the driver's sysfs directory that points to the
 device's physical directory:
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index 4bef8c2..d3ad2c2 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/string.h>
 
 #include "linux/firmware.h"
 
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 09eab2f..57b956a 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -14,6 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/firmware.h>
 
 
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 0d01950..7f42e44 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -4,18 +4,18 @@
 Supported chips:
   * IT8705F
     Prefix: 'it87'
-    Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
                http://www.ite.com.tw/
   * IT8712F
     Prefix: 'it8712'
     Addresses scanned: I2C 0x28 - 0x2f
-                       from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+                       from Super I/O config space (8 I/O ports)
     Datasheet: Publicly available at the ITE website
                http://www.ite.com.tw/
   * SiS950   [clone of IT8705F]
-    Prefix: 'sis950'
-    Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Prefix: 'it87'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: No longer be available
 
 Author: Christophe Gauthron <chrisg@0-in.com>
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 2c4cf39..438cb24 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -24,14 +24,14 @@
                http://www.national.com/pf/LM/LM86.html
   * Analog Devices ADM1032
     Prefix: 'adm1032'
-    Addresses scanned: I2C 0x4c
+    Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the Analog Devices website
-               http://products.analog.com/products/info.asp?product=ADM1032
+               http://www.analog.com/en/prod/0,2877,ADM1032,00.html
   * Analog Devices ADT7461
     Prefix: 'adt7461'
-    Addresses scanned: I2C 0x4c
+    Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the Analog Devices website
-               http://products.analog.com/products/info.asp?product=ADT7461
+               http://www.analog.com/en/prod/0,2877,ADT7461,00.html
     Note: Only if in ADM1032 compatibility mode
   * Maxim MAX6657
     Prefix: 'max6657'
@@ -71,8 +71,8 @@
 
 The different chipsets of the family are not strictly identical, although
 very similar. This driver doesn't handle any specific feature for now,
-but could if there ever was a need for it. For reference, here comes a
-non-exhaustive list of specific features:
+with the exception of SMBus PEC. For reference, here comes a non-exhaustive
+list of specific features:
 
 LM90:
   * Filter and alert configuration register at 0xBF.
@@ -91,6 +91,7 @@
   * Conversion averaging.
   * Up to 64 conversions/s.
   * ALERT is triggered by open remote sensor.
+  * SMBus PEC support for Write Byte and Receive Byte transactions.
 
 ADT7461
   * Extended temperature range (breaks compatibility)
@@ -119,3 +120,37 @@
 other second; reading them more often will do no harm, but will return
 'old' values.
 
+PEC Support
+-----------
+
+The ADM1032 is the only chip of the family which supports PEC. It does
+not support PEC on all transactions though, so some care must be taken.
+
+When reading a register value, the PEC byte is computed and sent by the
+ADM1032 chip. However, in the case of a combined transaction (SMBus Read
+Byte), the ADM1032 computes the CRC value over only the second half of
+the message rather than its entirety, because it thinks the first half
+of the message belongs to a different transaction. As a result, the CRC
+value differs from what the SMBus master expects, and all reads fail.
+
+For this reason, the lm90 driver will enable PEC for the ADM1032 only if
+the bus supports the SMBus Send Byte and Receive Byte transaction types.
+These transactions will be used to read register values, instead of
+SMBus Read Byte, and PEC will work properly.
+
+Additionally, the ADM1032 doesn't support SMBus Send Byte with PEC.
+Instead, it will try to write the PEC value to the register (because the
+SMBus Send Byte transaction with PEC is similar to a Write Byte transaction
+without PEC), which is not what we want. Thus, PEC is explicitely disabled
+on SMBus Send Byte transactions in the lm90 driver.
+
+PEC on byte data transactions represents a significant increase in bandwidth
+usage (+33% for writes, +25% for reads) in normal conditions. With the need
+to use two SMBus transaction for reads, this overhead jumps to +50%. Worse,
+two transactions will typically mean twice as much delay waiting for
+transaction completion, effectively doubling the register cache refresh time.
+I guess reliability comes at a price, but it's quite expensive this time.
+
+So, as not everyone might enjoy the slowdown, PEC can be disabled through
+sysfs. Just write 0 to the "pec" file and PEC will be disabled. Write 1
+to that file to enable PEC again.
diff --git a/Documentation/hwmon/smsc47b397 b/Documentation/hwmon/smsc47b397
index da9d80c..20682f1 100644
--- a/Documentation/hwmon/smsc47b397
+++ b/Documentation/hwmon/smsc47b397
@@ -3,6 +3,7 @@
 
 Supported chips:
   * SMSC LPC47B397-NC
+  * SMSC SCH5307-NS
     Prefix: 'smsc47b397'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: In this file
@@ -12,11 +13,14 @@
 
 November 23, 2004
 
-The following specification describes the SMSC LPC47B397-NC sensor chip
+The following specification describes the SMSC LPC47B397-NC[1] sensor chip
 (for which there is no public datasheet available). This document was
 provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
 by Mark M. Hoffman <mhoffman@lightlink.com>.
 
+[1] And SMSC SCH5307-NS, which has a different device ID but is otherwise
+compatible.
+
 * * * * *
 
 Methods for detecting the HP SIO and reading the thermal data on a dc7100.
@@ -127,7 +131,7 @@
 The registers of interest for identifying the SIO on the dc7100 are Device ID
 (0x20) and Device Rev  (0x21).
 
-The Device ID will read 0X6F
+The Device ID will read 0x6F (for SCH5307-NS, 0x81)
 The Device Rev currently reads 0x01
 
 Obtaining the HWM Base Address.
diff --git a/Documentation/hwmon/smsc47m1 b/Documentation/hwmon/smsc47m1
index 34e6478..c15bbe6 100644
--- a/Documentation/hwmon/smsc47m1
+++ b/Documentation/hwmon/smsc47m1
@@ -12,6 +12,10 @@
         http://www.smsc.com/main/datasheets/47m14x.pdf
         http://www.smsc.com/main/tools/discontinued/47m15x.pdf
         http://www.smsc.com/main/datasheets/47m192.pdf
+  * SMSC LPC47M997
+    Addresses scanned: none, address read from Super I/O config space
+    Prefix: 'smsc47m1'
+    Datasheet: none
 
 Authors:
         Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -30,6 +34,9 @@
 in addition to the fan monitoring and control. The hardware monitoring
 block is not supported by the driver.
 
+No documentation is available for the 47M997, but it has the same device
+ID as the 47M15x and 47M192 chips and seems to be compatible.
+
 Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
 triggered if the rotation speed has dropped below a programmable limit. Fan
 readings can be divided by a programmable divider (1, 2, 4 or 8) to give
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index 3464005..764cdc5 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -272,3 +272,6 @@
 
 eeprom		Raw EEPROM data in binary form.
 		Read only.
+
+pec		Enable or disable PEC (SMBus only)
+		Read/Write
diff --git a/Documentation/hwmon/via686a b/Documentation/hwmon/via686a
index b82014c..a936fb3 100644
--- a/Documentation/hwmon/via686a
+++ b/Documentation/hwmon/via686a
@@ -18,8 +18,9 @@
 Module Parameters
 -----------------
 
-force_addr=0xaddr       Set the I/O base address. Useful for Asus A7V boards
-                        that don't set the address in the BIOS. Does not do a
+force_addr=0xaddr       Set the I/O base address. Useful for boards that
+                        don't set the address in the BIOS. Look for a BIOS
+                        upgrade before resorting to this. Does not do a
                         PCI force; the via686a must still be present in lspci.
                         Don't use this unless the driver complains that the
                         base address is not set.
@@ -63,3 +64,15 @@
 
 The driver only updates its values each 1.5 seconds; reading it more often
 will do no harm, but will return 'old' values.
+
+Known Issues
+------------
+
+This driver handles sensors integrated in some VIA south bridges. It is
+possible that a motherboard maker used a VT82C686A/B chip as part of a
+product design but was not interested in its hardware monitoring features,
+in which case the sensor inputs will not be wired. This is the case of
+the Asus K7V, A7V and A7V133 motherboards, to name only a few of them.
+So, if you need the force_addr parameter, and end up with values which
+don't seem to make any sense, don't look any further: your chip is simply
+not wired for hardware monitoring.
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
index 0544eb3..83c3b97 100644
--- a/Documentation/i2c/busses/i2c-i810
+++ b/Documentation/i2c/busses/i2c-i810
@@ -2,6 +2,7 @@
 
 Supported adapters:
   * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
+  * Intel 82845G (GMCH)
 
 Authors: 
 	Frodo Looijaard <frodol@dds.nl>, 
diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro
index 702f5ac..9363b8b 100644
--- a/Documentation/i2c/busses/i2c-viapro
+++ b/Documentation/i2c/busses/i2c-viapro
@@ -4,17 +4,18 @@
   * VIA Technologies, Inc. VT82C596A/B
     Datasheet: Sometimes available at the VIA website
 
-  * VIA Technologies, Inc. VT82C686A/B 
+  * VIA Technologies, Inc. VT82C686A/B
     Datasheet: Sometimes available at the VIA website
 
   * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237
     Datasheet: available on request from Via
 
 Authors:
-	Frodo Looijaard <frodol@dds.nl>,  
-	Philip Edelbrock <phil@netroedge.com>, 
-	Kyösti Mälkki <kmalkki@cc.hut.fi>, 
-	Mark D. Studebaker <mdsxyz123@yahoo.com> 
+	Frodo Looijaard <frodol@dds.nl>,
+	Philip Edelbrock <phil@netroedge.com>,
+	Kyösti Mälkki <kmalkki@cc.hut.fi>,
+	Mark D. Studebaker <mdsxyz123@yahoo.com>,
+	Jean Delvare <khali@linux-fr.org>
 
 Module Parameters
 -----------------
@@ -28,20 +29,22 @@
 -----------
 
 i2c-viapro is a true SMBus host driver for motherboards with one of the
-supported VIA southbridges.
+supported VIA south bridges.
 
 Your lspci -n listing must show one of these :
 
- device 1106:3050   (VT82C596 function 3)
- device 1106:3051   (VT82C596 function 3)
+ device 1106:3050   (VT82C596A function 3)
+ device 1106:3051   (VT82C596B function 3)
  device 1106:3057   (VT82C686 function 4)
  device 1106:3074   (VT8233)
  device 1106:3147   (VT8233A)
- device 1106:8235   (VT8231)
- devide 1106:3177   (VT8235)
- devide 1106:3227   (VT8237)
+ device 1106:8235   (VT8231 function 4)
+ device 1106:3177   (VT8235)
+ device 1106:3227   (VT8237R)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.
 
-
+Except for the oldest chips (VT82C596A/B, VT82C686A and most probably
+VT8231), this driver supports I2C block transactions. Such transactions
+are mainly useful to read from and write to EEPROMs.
diff --git a/Documentation/i2c/chips/x1205 b/Documentation/i2c/chips/x1205
new file mode 100644
index 0000000..09407c9
--- /dev/null
+++ b/Documentation/i2c/chips/x1205
@@ -0,0 +1,38 @@
+Kernel driver x1205
+===================
+
+Supported chips:
+  * Xicor X1205 RTC
+    Prefix: 'x1205'
+    Addresses scanned: none
+    Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
+
+Authors:
+	Karen Spearel <kas11@tampabay.rr.com>,
+	Alessandro Zummo <a.zummo@towertech.it>
+
+Description
+-----------
+
+This module aims to provide complete access to the Xicor X1205 RTC.
+Recently Xicor has merged with Intersil, but the chip is
+still sold under the Xicor brand.
+
+This chip is located at address 0x6f and uses a 2-byte register addressing.
+Two bytes need to be written to read a single register, while most
+other chips just require one and take the second one as the data
+to be written. To prevent corrupting unknown chips, the user must
+explicitely set the probe parameter.
+
+example:
+
+modprobe x1205 probe=0,0x6f
+
+The module supports one more option, hctosys, which is used to set the
+software clock from the x1205. On systems where the x1205 is the
+only hardware rtc, this parameter could be used to achieve a correct
+date/time earlier in the system boot sequence.
+
+example:
+
+modprobe x1205 probe=0,0x6f hctosys=1
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
index 41ffefb..60cca24 100644
--- a/Documentation/i2c/functionality
+++ b/Documentation/i2c/functionality
@@ -17,9 +17,10 @@
   I2C_FUNC_I2C                    Plain i2c-level commands (Pure SMBus
                                   adapters typically can not do these)
   I2C_FUNC_10BIT_ADDR             Handles the 10-bit address extensions
-  I2C_FUNC_PROTOCOL_MANGLING      Knows about the I2C_M_REV_DIR_ADDR,
-                                  I2C_M_REV_DIR_ADDR and I2C_M_REV_DIR_NOSTART
-                                  flags (which modify the i2c protocol!)
+  I2C_FUNC_PROTOCOL_MANGLING      Knows about the I2C_M_IGNORE_NAK,
+                                  I2C_M_REV_DIR_ADDR, I2C_M_NOSTART and
+                                  I2C_M_NO_RD_ACK flags (which modify the
+                                  I2C protocol!)
   I2C_FUNC_SMBUS_QUICK            Handles the SMBus write_quick command
   I2C_FUNC_SMBUS_READ_BYTE        Handles the SMBus read_byte command
   I2C_FUNC_SMBUS_WRITE_BYTE       Handles the SMBus write_byte command
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index 4849dfd..184fac2 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -82,7 +82,7 @@
   exit and exit_free. For i2c+isa drivers, labels should be named
   ERROR0, ERROR1 and ERROR2. Don't forget to properly set err before
   jumping to error labels. By the way, labels should be left-aligned.
-  Use memset to fill the client and data area with 0x00.
+  Use kzalloc instead of kmalloc.
   Use i2c_set_clientdata to set the client data (as opposed to
   a direct access to client->data).
   Use strlcpy instead of strcpy to copy the client name.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 0772757..cff7b65 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -33,8 +33,8 @@
 	.command	= &foo_command /* may be NULL */
 }
  
-The name can be chosen freely, and may be upto 40 characters long. Please
-use something descriptive here.
+The name field must match the driver name, including the case. It must not
+contain spaces, and may be up to 31 characters long.
 
 Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
 means that your driver will be notified when new adapters are found.
@@ -43,9 +43,6 @@
 All other fields are for call-back functions which will be explained 
 below.
 
-There use to be two additional fields in this structure, inc_use et dec_use,
-for module usage count, but these fields were obsoleted and removed.
-
 
 Extra client data
 =================
@@ -58,6 +55,7 @@
 An example structure is below.
 
   struct foo_data {
+    struct i2c_client client;
     struct semaphore lock; /* For ISA access in `sensors' drivers. */
     int sysctl_id;         /* To keep the /proc directory entry for 
                               `sensors' drivers. */
@@ -275,6 +273,7 @@
     if (is_isa) {
 
       /* Discard immediately if this ISA range is already used */
+      /* FIXME: never use check_region(), only request_region() */
       if (check_region(address,FOO_EXTENT))
         goto ERROR0;
 
@@ -310,22 +309,15 @@
        client structure, even though we cannot fill it completely yet.
        But it allows us to access several i2c functions safely */
     
-    /* Note that we reserve some space for foo_data too. If you don't
-       need it, remove it. We do it here to help to lessen memory
-       fragmentation. */
-    if (! (new_client = kmalloc(sizeof(struct i2c_client) + 
-                                sizeof(struct foo_data),
-                                GFP_KERNEL))) {
+    if (!(data = kzalloc(sizeof(struct foo_data), GFP_KERNEL))) {
       err = -ENOMEM;
       goto ERROR0;
     }
 
-    /* This is tricky, but it will set the data to the right value. */
-    client->data = new_client + 1;
-    data = (struct foo_data *) (client->data);
+    new_client = &data->client;
+    i2c_set_clientdata(new_client, data);
 
     new_client->addr = address;
-    new_client->data = data;
     new_client->adapter = adapter;
     new_client->driver = &foo_driver;
     new_client->flags = 0;
@@ -451,7 +443,7 @@
       release_region(client->addr,LM78_EXTENT);
     /* HYBRID SENSORS CHIP ONLY END */
 
-    kfree(client); /* Frees client data too, if allocated at the same time */
+    kfree(data);
     return 0;
   }
 
@@ -576,12 +568,12 @@
   extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                         u8 command, u8 length,
                                         u8 *values);
+  extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
+                                           u8 command, u8 *values);
 
 These ones were removed in Linux 2.6.10 because they had no users, but could
 be added back later if needed:
 
-  extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
-                                           u8 command, u8 *values);
   extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
                                        u8 command, u8 *values);
   extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
diff --git a/Documentation/input/yealink.txt b/Documentation/input/yealink.txt
index 85f095a..0962c5c 100644
--- a/Documentation/input/yealink.txt
+++ b/Documentation/input/yealink.txt
@@ -2,7 +2,6 @@
 
 0. Status
 ~~~~~~~~~
-
 The p1k is a relatively cheap usb 1.1 phone with:
   - keyboard		full support, yealink.ko / input event API
   - LCD			full support, yealink.ko / sysfs API
@@ -17,9 +16,8 @@
 
 1. Compilation (stand alone version)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
 Currently only kernel 2.6.x.y versions are supported.
-In order to build the yealink.ko module do:
+In order to build the yealink.ko module do
 
   make
 
@@ -28,6 +26,21 @@
 are located, default /usr/src/linux.
 
 
+1.1 Troubleshooting
+~~~~~~~~~~~~~~~~~~~
+Q: Module yealink compiled and installed without any problem but phone
+   is not initialized and does not react to any actions.
+A: If you see something like:
+   hiddev0: USB HID v1.00 Device [Yealink Network Technology Ltd. VOIP USB Phone
+   in dmesg, it means that the hid driver has grabbed the device first. Try to
+   load module yealink before any other usb hid driver. Please see the
+   instructions provided by your distribution on module configuration.
+
+Q: Phone is working now (displays version and accepts keypad input) but I can't
+   find the sysfs files.
+A: The sysfs files are located on the particular usb endpoint. On most
+   distributions you can do: "find /sys/ -name get_icons" for a hint.
+
 
 2. keyboard features
 ~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 971589a..5dffcfe 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1460,8 +1460,6 @@
 	stifb=		[HW]
 			Format: bpp:<bpp1>[:<bpp2>[:<bpp3>...]]
 
-	stram_swap=	[HW,M68k]
-
 	swiotlb=	[IA-64] Number of I/O TLB slabs
 
 	switches=	[HW,M68k]
@@ -1517,8 +1515,6 @@
 	uart6850=	[HW,OSS]
 			Format: <io>,<irq>
 
-	usb-handoff	[HW] Enable early USB BIOS -> OS handoff
-
 	usbhid.mousepoll=
 			[USBHID] The interval which mice are to be polled at.
 
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 4afe03a..3115488 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -196,7 +196,7 @@
 
 Keys have an owner user ID, a group access ID, and a permissions mask. The mask
 has up to eight bits each for possessor, user, group and other access. Only
-five of each set of eight bits are defined. These permissions granted are:
+six of each set of eight bits are defined. These permissions granted are:
 
  (*) View
 
@@ -224,6 +224,10 @@
      keyring to a key, a process must have Write permission on the keyring and
      Link permission on the key.
 
+ (*) Set Attribute
+
+     This permits a key's UID, GID and permissions mask to be changed.
+
 For changing the ownership, group ID or permissions mask, being the owner of
 the key or having the sysadmin capability is sufficient.
 
@@ -242,15 +246,15 @@
      this way:
 
 	SERIAL   FLAGS  USAGE EXPY PERM     UID   GID   TYPE      DESCRIPTION: SUMMARY
-	00000001 I-----    39 perm 1f1f0000     0     0 keyring   _uid_ses.0: 1/4
-	00000002 I-----     2 perm 1f1f0000     0     0 keyring   _uid.0: empty
-	00000007 I-----     1 perm 1f1f0000     0     0 keyring   _pid.1: empty
-	0000018d I-----     1 perm 1f1f0000     0     0 keyring   _pid.412: empty
-	000004d2 I--Q--     1 perm 1f1f0000    32    -1 keyring   _uid.32: 1/4
-	000004d3 I--Q--     3 perm 1f1f0000    32    -1 keyring   _uid_ses.32: empty
+	00000001 I-----    39 perm 1f3f0000     0     0 keyring   _uid_ses.0: 1/4
+	00000002 I-----     2 perm 1f3f0000     0     0 keyring   _uid.0: empty
+	00000007 I-----     1 perm 1f3f0000     0     0 keyring   _pid.1: empty
+	0000018d I-----     1 perm 1f3f0000     0     0 keyring   _pid.412: empty
+	000004d2 I--Q--     1 perm 1f3f0000    32    -1 keyring   _uid.32: 1/4
+	000004d3 I--Q--     3 perm 1f3f0000    32    -1 keyring   _uid_ses.32: empty
 	00000892 I--QU-     1 perm 1f000000     0     0 user      metal:copper: 0
-	00000893 I--Q-N     1  35s 1f1f0000     0     0 user      metal:silver: 0
-	00000894 I--Q--     1  10h 001f0000     0     0 user      metal:gold: 0
+	00000893 I--Q-N     1  35s 1f3f0000     0     0 user      metal:silver: 0
+	00000894 I--Q--     1  10h 003f0000     0     0 user      metal:gold: 0
 
      The flags are:
 
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt
index e191baa..d5d3f06 100644
--- a/Documentation/m68k/kernel-options.txt
+++ b/Documentation/m68k/kernel-options.txt
@@ -626,7 +626,7 @@
     can be performed in optimal order. Not all SCSI devices support
     tagged queuing (:-().
 
-4.6 switches=
+4.5 switches=
 -------------
 
 Syntax: switches=<list of switches>
@@ -661,28 +661,6 @@
 earlier initialization ("ov_"-less) takes precedence. But the
 switching-off on reset still happens in this case.
 
-4.5) stram_swap=
-----------------
-
-Syntax: stram_swap=<do_swap>[,<max_swap>]
-
-  This option is available only if the kernel has been compiled with
-CONFIG_STRAM_SWAP enabled. Normally, the kernel then determines
-dynamically whether to actually use ST-RAM as swap space. (Currently,
-the fraction of ST-RAM must be less or equal 1/3 of total memory to
-enable this swapping.) You can override the kernel's decision by
-specifying this option. 1 for <do_swap> means always enable the swap,
-even if you have less alternate RAM. 0 stands for never swap to
-ST-RAM, even if it's small enough compared to the rest of memory.
-
-  If ST-RAM swapping is enabled, the kernel usually uses all free
-ST-RAM as swap "device". If the kernel resides in ST-RAM, the region
-allocated by it is obviously never used for swapping :-) You can also
-limit this amount by specifying the second parameter, <max_swap>, if
-you want to use parts of ST-RAM as normal system memory. <max_swap> is
-in kBytes and the number should be a multiple of 4 (otherwise: rounded
-down).
-
 5) Options for Amiga Only:
 ==========================
 
diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/AU1xxx_IDE.README
new file mode 100644
index 0000000..a7e4c4e
--- /dev/null
+++ b/Documentation/mips/AU1xxx_IDE.README
@@ -0,0 +1,168 @@
+README for MIPS AU1XXX IDE driver - Released 2005-07-15
+
+ABOUT
+-----
+This file describes the 'drivers/ide/mips/au1xxx-ide.c', related files and the
+services they provide.
+
+If you are short in patience and just want to know how to add your hard disc to
+the white or black list, go to the 'ADD NEW HARD DISC TO WHITE OR BLACK LIST'
+section.
+
+
+LICENSE
+-------
+
+Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions
+
+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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+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.
+
+Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
+      Interface and Linux Device Driver" Application Note.
+
+
+FILES, CONFIGS AND COMPATABILITY
+--------------------------------
+
+Two files are introduced:
+
+  a) 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
+     containes : struct _auide_hwif
+                 struct drive_list_entry dma_white_list
+                 struct drive_list_entry dma_black_list
+                 timing parameters for PIO mode 0/1/2/3/4
+                 timing parameters for MWDMA 0/1/2
+
+  b) 'drivers/ide/mips/au1xxx-ide.c'
+     contains the functionality of the AU1XXX IDE driver
+
+Four configs variables are introduced:
+
+  CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA    - enable the PIO+DBDMA mode
+  CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA  - enable the MWDMA mode
+  CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON - set Burstable FIFO in DBDMA
+                                           controler
+  CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - maximum transfer size
+                                           per descriptor
+
+If MWDMA is enabled and the connected hard disc is not on the white list, the
+kernel switches to a "safe mwdma mode" at boot time. In this mode the IDE
+performance is substantial slower then in full speed mwdma. In this case
+please add your hard disc to the white list (follow instruction from 'ADD NEW
+HARD DISC TO WHITE OR BLACK LIST' section).
+
+
+SUPPORTED IDE MODES
+-------------------
+
+The AU1XXX IDE driver supported all PIO modes - PIO mode 0/1/2/3/4 - and all
+MWDMA modes - MWDMA 0/1/2 -. There is no support for SWDMA and UDMA mode.
+
+To change the PIO mode use the program hdparm with option -p, e.g.
+'hdparm -p0 [device]' for PIO mode 0. To enable the MWDMA mode use the option
+-X, e.g. 'hdparm -X32 [device]' for MWDMA mode 0.
+
+
+PERFORMANCE CONFIGURATIONS
+--------------------------
+
+If the used system doesn't need USB support enable the following kernel configs:
+
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDE_AU1XXX=y
+CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y
+CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON=y
+CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ=128
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
+
+If the used system need the USB support enable the following kernel configs for
+high IDE to USB throughput.
+
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDE_AU1XXX=y
+CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y
+CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ=128
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
+
+
+ADD NEW HARD DISC TO WHITE OR BLACK LIST
+----------------------------------------
+
+Step 1 : detect the model name of your hard disc
+
+  a) connect your hard disc to the AU1XXX
+
+  b) boot your kernel and get the hard disc model.
+
+     Example boot log:
+
+     --snipped--
+     Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
+     ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
+     Au1xxx IDE(builtin) configured for MWDMA2
+     Probing IDE interface ide0...
+     hda: Maxtor 6E040L0, ATA DISK drive
+     ide0 at 0xac800000-0xac800007,0xac8001c0 on irq 64
+     hda: max request size: 64KiB
+     hda: 80293248 sectors (41110 MB) w/2048KiB Cache, CHS=65535/16/63, (U)DMA
+     --snipped--
+
+     In this example 'Maxtor 6E040L0'.
+
+Step  2 : edit 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
+
+  Add your hard disc to the dma_white_list or dma_black_list structur.
+
+Step 3 : Recompile the kernel
+
+  Enable MWDMA support in the kernel configuration. Recompile the kernel and
+  reboot.
+
+Step 4 : Tests
+
+  If you have add a hard disc to the white list, please run some stress tests
+  for verification.
+
+
+ACKNOWLEDGMENTS
+---------------
+
+These drivers wouldn't have been done without the base of kernel 2.4.x AU1XXX
+IDE driver from AMD.
+
+Additional input also from:
+Matthias Lenk <matthias.lenk@amd.com>
+
+Happy hacking!
+Enrico Walther <enrico.walther@amd.com>
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index a55f0f9..b0fe41d 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -777,7 +777,7 @@
 Manually" section, below.
 
 	NOTE: It has been observed that some Red Hat supplied kernels
-are apparently unable to rename modules at load time (the "-obonding1"
+are apparently unable to rename modules at load time (the "-o bond1"
 part).  Attempts to pass that option to modprobe will produce an
 "Operation not permitted" error.  This has been reported on some
 Fedora Core kernels, and has been seen on RHEL 4 as well.  On kernels
@@ -883,7 +883,8 @@
 its options.  In that case, the second options line can be substituted
 as follows:
 
-install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50
+install bond1 /sbin/modprobe --ignore-install bonding -o bond1 \
+	mode=balance-alb miimon=50
 
 	This may be repeated any number of times, specifying a new and
 unique name in place of bond1 for each subsequent instance.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index b433c8a..65895bb 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -309,7 +309,7 @@
        can be consumed by a single TSO frame.
        The setting of this parameter is a choice between burstiness and
        building larger TSO frames.
-       Default: 8
+       Default: 3
 
 tcp_frto - BOOLEAN
 	Enables F-RTO, an enhanced recovery algorithm for TCP retransmission
diff --git a/MAINTAINERS b/MAINTAINERS
index 767fb61..983f9e9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -116,12 +116,6 @@
 L:	linux-hams@vger.kernel.org
 S:	Maintained
 
-YEALINK PHONE DRIVER
-P:	Henk Vergonet
-M:	Henk.Vergonet@gmail.com
-L:	usbb2k-api-dev@nongnu.org
-S:	Maintained
-
 8139CP 10/100 FAST ETHERNET DRIVER
 P:	Jeff Garzik
 M:	jgarzik@pobox.com
@@ -197,6 +191,15 @@
 W:	http://linux.thorsten-knabe.de
 S:	Maintained
 
+AD1889 SOUND DRIVER
+P:	Kyle McMartin
+M:	kyle@parisc-linux.org
+P:	Thibaut Varene
+M:	T-Bone@parisc-linux.org
+W:	http://wiki.parisc-linux.org/AD1889
+L:	parisc-linux@lists.parisc-linux.org
+S:	Maintained
+
 ADM1025 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
@@ -1640,7 +1643,7 @@
 MIPS
 P:	Ralf Baechle
 M:	ralf@linux-mips.org
-W:	http://oss.sgi.com/mips/mips-howto.html
+W:	http://www.linux-mips.org/
 L:	linux-mips@linux-mips.org
 S:	Maintained
 
@@ -1942,6 +1945,14 @@
 L:	netdev@vger.kernel.org
 S:	Supported
 
+POWERPC 4xx EMAC DRIVER
+P:	Eugene Surovegin
+M:	ebs@ebshome.net
+W:	http://kernel.ebshome.net/emac/
+L:	linuxppc-embedded@ozlabs.org
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 PNP SUPPORT
 P:	Adam Belay
 M:	ambx1@neo.rr.com
@@ -2275,6 +2286,11 @@
 L:	tpmdd-devel@lists.sourceforge.net
 S:	Maintained
 
+Telecom Clock Driver for MCPL0010
+P: Mark Gross
+M: mark.gross@intel.com
+S: Supported
+
 TENSILICA XTENSA PORT (xtensa):
 P:	Chris Zankel
 M:	chris@zankel.net
@@ -2486,14 +2502,6 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Supported
 
-USB BLUETOOTH TTY CONVERTER DRIVER
-P:	Greg Kroah-Hartman
-M:	greg@kroah.com
-L:	linux-usb-users@lists.sourceforge.net
-L:	linux-usb-devel@lists.sourceforge.net
-S:	Maintained
-W:	http://www.kroah.com/linux-usb/
-
 USB CDC ETHERNET DRIVER
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
@@ -2727,6 +2735,12 @@
 M:	rl@hellgate.ch
 S:	Maintained
 
+VIAPRO SMBUS DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 UCLINUX (AND M68KNOMMU)
 P:	Greg Ungerer
 M:	gerg@uclinux.org
@@ -2848,6 +2862,12 @@
 L:	linux-hams@vger.kernel.org
 S:	Maintained
 
+YEALINK PHONE DRIVER
+P:	Henk Vergonet
+M:	Henk.Vergonet@gmail.com
+L:	usbb2k-api-dev@nongnu.org
+S:	Maintained
+
 YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
 P:	Pete Zaitcev
 M:	zaitcev@yahoo.com
diff --git a/Makefile b/Makefile
index 1fa7e53..7960132 100644
--- a/Makefile
+++ b/Makefile
@@ -334,7 +334,7 @@
 PERL		= perl
 CHECK		= sparse
 
-CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ $(CF)
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
 MODFLAGS	= -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -371,8 +371,8 @@
 
 # Files to ignore in find ... statements
 
-RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o
-export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
+RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
+export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
 
 # ===========================================================================
 # Rules shared between *config targets and build targets
diff --git a/README b/README
index d1edcc7..4ee7dda 100644
--- a/README
+++ b/README
@@ -54,6 +54,10 @@
 
 		gzip -cd linux-2.6.XX.tar.gz | tar xvf -
 
+   or
+		bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf -
+
+
    Replace "XX" with the version number of the latest kernel.
 
    Do NOT use the /usr/src/linux area! This area has a (usually
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 582a3519f..9903e3a 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -154,7 +154,7 @@
 
 void *
 dma_alloc_coherent(struct device *dev, size_t size,
-		   dma_addr_t *dma_handle, int gfp)
+		   dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret;
 
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 7cb23f1..c468e31 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -397,7 +397,7 @@
 {
 	void *cpu_addr;
 	long order = get_order(size);
-	int gfp = GFP_ATOMIC;
+	gfp_t gfp = GFP_ATOMIC;
 
 try_again:
 	cpu_addr = (void *)__get_free_pages(gfp, order);
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 67be50b..6b2921b 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -55,10 +55,6 @@
 #include "proto.h"
 #include "irq_impl.h"
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 extern unsigned long wall_jiffies;	/* kernel/timer.c */
 
 static int set_rtc_mmss(unsigned long);
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index c7481d5..6d52512 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -371,6 +371,8 @@
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_online_node(nid) {
+		unsigned long flags;
+		pgdat_resize_lock(NODE_DATA(nid), &flags);
 		i = node_spanned_pages(nid);
 		while (i-- > 0) {
 			struct page *page = nid_page_nr(nid, i);
@@ -384,6 +386,7 @@
 			else
 				shared += page_count(page) - 1;
 		}
+		pgdat_resize_unlock(NODE_DATA(nid), &flags);
 	}
 	printk("%ld pages of RAM\n",total);
 	printk("%ld free pages\n",free);
diff --git a/arch/alpha/mm/remap.c b/arch/alpha/mm/remap.c
index 19817ad..a78356c 100644
--- a/arch/alpha/mm/remap.c
+++ b/arch/alpha/mm/remap.c
@@ -2,7 +2,6 @@
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 
-/* called with the page_table_lock held */
 static inline void 
 remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, 
 	       unsigned long phys_addr, unsigned long flags)
@@ -31,7 +30,6 @@
 	} while (address && (address < end));
 }
 
-/* called with the page_table_lock held */
 static inline int 
 remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, 
 	       unsigned long phys_addr, unsigned long flags)
@@ -46,7 +44,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, 
@@ -70,7 +68,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd;
 		pmd = pmd_alloc(&init_mm, dir, address);
@@ -84,7 +81,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	return error;
 }
 
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 11fff04..682367b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -204,6 +204,7 @@
 
 config ARCH_AAEC2000
 	bool "Agilent AAEC-2000 based"
+	select ARM_AMBA
 	help
 	  This enables support for systems based on the Agilent AAEC-2000
 
@@ -687,7 +688,8 @@
 
 if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
 	|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
-	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
+	|| MACH_MP1000
 source "drivers/ide/Kconfig"
 endif
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 299bc04..64cf480 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -8,7 +8,7 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p --no-undefined -X
-CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+CPPFLAGS_vmlinux.lds = -DKERNEL_RAM_ADDR=$(TEXTADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
 #CFLAGS		+=-pipe
@@ -108,27 +108,19 @@
 endif
 
 TEXTADDR := $(textaddr-y)
-ifeq ($(CONFIG_XIP_KERNEL),y)
-  DATAADDR := $(TEXTADDR)
-  xipaddr-$(CONFIG_ARCH_CO285) := 0x5f000000
-  xipaddr-y ?= 0xbf000000
-  # Replace phys addr with virt addr while keeping offset from base.
-  TEXTADDR := $(shell echo $(CONFIG_XIP_PHYS_ADDR) $(xipaddr-y) | \
-                      awk --non-decimal-data '/[:xdigit:]/ \
-                          { printf("0x%x\n", and($$1, 0x000fffff) + $$2) }' )
-endif
 
 ifeq ($(incdir-y),)
 incdir-y := $(machine-y)
 endif
 INCDIR   := arch-$(incdir-y)
+
 ifneq ($(machine-y),)
 MACHINE  := arch/arm/mach-$(machine-y)/
 else
 MACHINE  :=
 endif
   
-export	TEXTADDR DATAADDR GZFLAGS
+export	TEXTADDR GZFLAGS
 
 # Do we have FASTFPE?
 FASTFPE		:=arch/arm/fastfpe
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 7c7f475..a54d2eb 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -39,7 +39,8 @@
     defined(CONFIG_ARCH_IXP4XX) || \
     defined(CONFIG_ARCH_IXP2000) || \
     defined(CONFIG_ARCH_LH7A40X) || \
-    defined(CONFIG_ARCH_OMAP)
+    defined(CONFIG_ARCH_OMAP) || \
+    defined(CONFIG_MACH_MP1000)
 		.macro	loadsp,	rb
 		addruart \rb
 		.endm
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 23434b5..50f13ee 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -30,7 +30,7 @@
 #define putstr icedcc_putstr
 #define putc icedcc_putc
 
-extern void idedcc_putc(int ch);
+extern void icedcc_putc(int ch);
 
 static void
 icedcc_putstr(const char *ptr)
diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c
index c6beb75..e101311 100644
--- a/arch/arm/common/amba.c
+++ b/arch/arm/common/amba.c
@@ -10,6 +10,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index cbf2165..ad6c89a 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -33,8 +33,8 @@
 #include <asm/cacheflush.h>
 
 #undef DEBUG
-
 #undef STATS
+
 #ifdef STATS
 #define DO_STATS(X) do { X ; } while (0)
 #else
@@ -52,26 +52,31 @@
 	int		direction;
 
 	/* safe buffer info */
-	struct dma_pool *pool;
+	struct dmabounce_pool *pool;
 	void		*safe;
 	dma_addr_t	safe_dma_addr;
 };
 
+struct dmabounce_pool {
+	unsigned long	size;
+	struct dma_pool	*pool;
+#ifdef STATS
+	unsigned long	allocs;
+#endif
+};
+
 struct dmabounce_device_info {
 	struct list_head node;
 
 	struct device *dev;
-	struct dma_pool *small_buffer_pool;
-	struct dma_pool *large_buffer_pool;
 	struct list_head safe_buffers;
-	unsigned long small_buffer_size, large_buffer_size;
 #ifdef STATS
-	unsigned long sbp_allocs;
-	unsigned long lbp_allocs;
 	unsigned long total_allocs;
 	unsigned long map_op_count;
 	unsigned long bounce_count;
 #endif
+	struct dmabounce_pool	small;
+	struct dmabounce_pool	large;
 };
 
 static LIST_HEAD(dmabounce_devs);
@@ -82,9 +87,9 @@
 	printk(KERN_INFO
 		"%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
 		device_info->dev->bus_id,
-		device_info->sbp_allocs, device_info->lbp_allocs,
-		device_info->total_allocs - device_info->sbp_allocs -
-			device_info->lbp_allocs,
+		device_info->small.allocs, device_info->large.allocs,
+		device_info->total_allocs - device_info->small.allocs -
+			device_info->large.allocs,
 		device_info->total_allocs);
 }
 #endif
@@ -106,18 +111,22 @@
 /* allocate a 'safe' buffer and keep track of it */
 static inline struct safe_buffer *
 alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
-			size_t size, enum dma_data_direction dir)
+		  size_t size, enum dma_data_direction dir)
 {
 	struct safe_buffer *buf;
-	struct dma_pool *pool;
+	struct dmabounce_pool *pool;
 	struct device *dev = device_info->dev;
-	void *safe;
-	dma_addr_t safe_dma_addr;
 
 	dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n",
 		__func__, ptr, size, dir);
 
-	DO_STATS ( device_info->total_allocs++ );
+	if (size <= device_info->small.size) {
+		pool = &device_info->small;
+	} else if (size <= device_info->large.size) {
+		pool = &device_info->large;
+	} else {
+		pool = NULL;
+	}
 
 	buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
 	if (buf == NULL) {
@@ -125,41 +134,35 @@
 		return NULL;
 	}
 
-	if (size <= device_info->small_buffer_size) {
-		pool = device_info->small_buffer_pool;
-		safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
+	buf->ptr = ptr;
+	buf->size = size;
+	buf->direction = dir;
+	buf->pool = pool;
 
-		DO_STATS ( device_info->sbp_allocs++ );
-	} else if (size <= device_info->large_buffer_size) {
-		pool = device_info->large_buffer_pool;
-		safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
-
-		DO_STATS ( device_info->lbp_allocs++ );
+	if (pool) {
+		buf->safe = dma_pool_alloc(pool->pool, GFP_ATOMIC,
+					   &buf->safe_dma_addr);
 	} else {
-		pool = NULL;
-		safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC);
+		buf->safe = dma_alloc_coherent(dev, size, &buf->safe_dma_addr,
+					       GFP_ATOMIC);
 	}
 
-	if (safe == NULL) {
-		dev_warn(device_info->dev,
-			"%s: could not alloc dma memory (size=%d)\n",
-		       __func__, size);
+	if (buf->safe == NULL) {
+		dev_warn(dev,
+			 "%s: could not alloc dma memory (size=%d)\n",
+			 __func__, size);
 		kfree(buf);
 		return NULL;
 	}
 
 #ifdef STATS
+	if (pool)
+		pool->allocs++;
+	device_info->total_allocs++;
 	if (device_info->total_allocs % 1000 == 0)
 		print_alloc_stats(device_info);
 #endif
 
-	buf->ptr = ptr;
-	buf->size = size;
-	buf->direction = dir;
-	buf->pool = pool;
-	buf->safe = safe;
-	buf->safe_dma_addr = safe_dma_addr;
-
 	list_add(&buf->node, &device_info->safe_buffers);
 
 	return buf;
@@ -186,7 +189,7 @@
 	list_del(&buf->node);
 
 	if (buf->pool)
-		dma_pool_free(buf->pool, buf->safe, buf->safe_dma_addr);
+		dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
 	else
 		dma_free_coherent(device_info->dev, buf->size, buf->safe,
 				    buf->safe_dma_addr);
@@ -197,12 +200,10 @@
 /* ************************************************** */
 
 #ifdef STATS
-
 static void print_map_stats(struct dmabounce_device_info *device_info)
 {
-	printk(KERN_INFO
-		"%s: dmabounce: map_op_count=%lu, bounce_count=%lu\n",
-		device_info->dev->bus_id,
+	dev_info(device_info->dev,
+		"dmabounce: map_op_count=%lu, bounce_count=%lu\n",
 		device_info->map_op_count, device_info->bounce_count);
 }
 #endif
@@ -258,13 +259,13 @@
 				__func__, ptr, buf->safe, size);
 			memcpy(buf->safe, ptr, size);
 		}
-		consistent_sync(buf->safe, size, dir);
+		ptr = buf->safe;
 
 		dma_addr = buf->safe_dma_addr;
-	} else {
-		consistent_sync(ptr, size, dir);
 	}
 
+	consistent_sync(ptr, size, dir);
+
 	return dma_addr;
 }
 
@@ -278,7 +279,7 @@
 	/*
 	 * Trying to unmap an invalid mapping
 	 */
-	if (dma_addr == ~0) {
+	if (dma_mapping_error(dma_addr)) {
 		dev_err(dev, "Trying to unmap invalid mapping\n");
 		return;
 	}
@@ -570,11 +571,25 @@
 	local_irq_restore(flags);
 }
 
+static int
+dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev, const char *name,
+		    unsigned long size)
+{
+	pool->size = size;
+	DO_STATS(pool->allocs = 0);
+	pool->pool = dma_pool_create(name, dev, size,
+				     0 /* byte alignment */,
+				     0 /* no page-crossing issues */);
+
+	return pool->pool ? 0 : -ENOMEM;
+}
+
 int
 dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
 			unsigned long large_buffer_size)
 {
 	struct dmabounce_device_info *device_info;
+	int ret;
 
 	device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
 	if (!device_info) {
@@ -584,45 +599,31 @@
 		return -ENOMEM;
 	}
 
-	device_info->small_buffer_pool =
-		dma_pool_create("small_dmabounce_pool",
-				dev,
-				small_buffer_size,
-				0 /* byte alignment */,
-				0 /* no page-crossing issues */);
-	if (!device_info->small_buffer_pool) {
-		printk(KERN_ERR
-			"dmabounce: could not allocate small DMA pool for %s\n",
-			dev->bus_id);
-		kfree(device_info);
-		return -ENOMEM;
+	ret = dmabounce_init_pool(&device_info->small, dev,
+				  "small_dmabounce_pool", small_buffer_size);
+	if (ret) {
+		dev_err(dev,
+			"dmabounce: could not allocate DMA pool for %ld byte objects\n",
+			small_buffer_size);
+		goto err_free;
 	}
 
 	if (large_buffer_size) {
-		device_info->large_buffer_pool =
-			dma_pool_create("large_dmabounce_pool",
-					dev,
-					large_buffer_size,
-					0 /* byte alignment */,
-					0 /* no page-crossing issues */);
-		if (!device_info->large_buffer_pool) {
-		printk(KERN_ERR
-			"dmabounce: could not allocate large DMA pool for %s\n",
-			dev->bus_id);
-			dma_pool_destroy(device_info->small_buffer_pool);
-
-			return -ENOMEM;
+		ret = dmabounce_init_pool(&device_info->large, dev,
+					  "large_dmabounce_pool",
+					  large_buffer_size);
+		if (ret) {
+			dev_err(dev,
+				"dmabounce: could not allocate DMA pool for %ld byte objects\n",
+				large_buffer_size);
+			goto err_destroy;
 		}
 	}
 
 	device_info->dev = dev;
-	device_info->small_buffer_size = small_buffer_size;
-	device_info->large_buffer_size = large_buffer_size;
 	INIT_LIST_HEAD(&device_info->safe_buffers);
 
 #ifdef STATS
-	device_info->sbp_allocs = 0;
-	device_info->lbp_allocs = 0;
 	device_info->total_allocs = 0;
 	device_info->map_op_count = 0;
 	device_info->bounce_count = 0;
@@ -634,6 +635,12 @@
 		dev->bus_id, dev->bus->name);
 
 	return 0;
+
+ err_destroy:
+	dma_pool_destroy(device_info->small.pool);
+ err_free:
+	kfree(device_info);
+	return ret;
 }
 
 void
@@ -655,10 +662,10 @@
 		BUG();
 	}
 
-	if (device_info->small_buffer_pool)
-		dma_pool_destroy(device_info->small_buffer_pool);
-	if (device_info->large_buffer_pool)
-		dma_pool_destroy(device_info->large_buffer_pool);
+	if (device_info->small.pool)
+		dma_pool_destroy(device_info->small.pool);
+	if (device_info->large.pool)
+		dma_pool_destroy(device_info->large.pool);
 
 #ifdef STATS
 	print_alloc_stats(device_info);
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index e8053d1..5cdb412 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -550,15 +550,12 @@
 	u16	LCM_SPIMD;
 };
 
-static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
+static int locomo_suspend(struct device *dev, pm_message_t state)
 {
 	struct locomo *lchip = dev_get_drvdata(dev);
 	struct locomo_save_data *save;
 	unsigned long flags;
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
 	if (!save)
 		return -ENOMEM;
@@ -597,16 +594,13 @@
 	return 0;
 }
 
-static int locomo_resume(struct device *dev, u32 level)
+static int locomo_resume(struct device *dev)
 {
 	struct locomo *lchip = dev_get_drvdata(dev);
 	struct locomo_save_data *save;
 	unsigned long r;
 	unsigned long flags;
 	
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	save = (struct locomo_save_data *) dev->power.saved_state;
 	if (!save)
 		return 0;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 1a47fbf9c..21e2a51 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -801,7 +801,7 @@
 
 #ifdef CONFIG_PM
 
-static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1111_suspend(struct device *dev, pm_message_t state)
 {
 	struct sa1111 *sachip = dev_get_drvdata(dev);
 	struct sa1111_save_data *save;
@@ -809,9 +809,6 @@
 	unsigned int val;
 	void __iomem *base;
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
 	if (!save)
 		return -ENOMEM;
@@ -856,23 +853,19 @@
 /*
  *	sa1111_resume - Restore the SA1111 device state.
  *	@dev: device to restore
- *	@level: resume level
  *
  *	Restore the general state of the SA1111; clock control and
  *	interrupt controller.  Other parts of the SA1111 must be
  *	restored by their respective drivers, and must be called
  *	via LDM after this function.
  */
-static int sa1111_resume(struct device *dev, u32 level)
+static int sa1111_resume(struct device *dev)
 {
 	struct sa1111 *sachip = dev_get_drvdata(dev);
 	struct sa1111_save_data *save;
 	unsigned long flags, id;
 	void __iomem *base;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	save = (struct sa1111_save_data *)dev->power.saved_state;
 	if (!save)
 		return 0;
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 9e5245c..4af0cf5 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -12,6 +12,9 @@
  */
 
 #include <linux/device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
 #include <asm/io.h>
 #include <asm/hardware/scoop.h>
 
@@ -102,26 +105,24 @@
 }
 
 #ifdef CONFIG_PM
-static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int scoop_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		struct scoop_dev *sdev = dev_get_drvdata(dev);
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
 
-		check_scoop_reg(sdev);
-  		sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
-		SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
-	}
+	check_scoop_reg(sdev);
+	sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
+	SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
+
 	return 0;
 }
 
-static int scoop_resume(struct device *dev, uint32_t level)
+static int scoop_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		struct scoop_dev *sdev = dev_get_drvdata(dev);
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
 
-		check_scoop_reg(sdev);
-		SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
-	}
+	check_scoop_reg(sdev);
+	SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
+
 	return 0;
 }
 #else
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 678720f..ddeb9f9 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -559,7 +559,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_NR_UARTS=1
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index 261e234..81d3a06 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -559,7 +559,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_NR_UARTS=1
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
diff --git a/arch/arm/configs/mp1000_defconfig b/arch/arm/configs/mp1000_defconfig
new file mode 100644
index 0000000..d2cbc6f
--- /dev/null
+++ b/arch/arm/configs/mp1000_defconfig
@@ -0,0 +1,897 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc1
+# Fri Sep 16 15:48:13 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+CONFIG_ARCH_CLPS711X=y
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 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_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CEIVA is not set
+# CONFIG_ARCH_CLEP7312 is not set
+# CONFIG_ARCH_EDB7211 is not set
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+CONFIG_MACH_MP1000=y
+CONFIG_MP1000_90MHZ=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+# 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_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyCL,38400 root=/dev/discs/disc0/part1 ip=any cs89x0_media=rj45"
+# CONFIG_XIP_KERNEL 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=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# 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_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=m
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x0000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_EDB7312=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_MP1000=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+CONFIG_IDE_ARM=y
+CONFIG_BLK_DEV_IDE_MP1000=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# 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_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+CONFIG_CS89x0=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVBUG=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CLPS711X=y
+CONFIG_SERIAL_CLPS711X_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+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 is not set
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# 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=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 3e1b032..c11169b 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+AFLAGS_head.o := -DKERNEL_RAM_ADDR=$(TEXTADDR)
 
 # Object file lists.
 
diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c
index a418dad..0ee2e98 100644
--- a/arch/arm/kernel/arthur.c
+++ b/arch/arm/kernel/arthur.c
@@ -18,6 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/signal.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <asm/ptrace.h>
 
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index c1ff4d1..04d3082 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -94,7 +94,6 @@
   DEFINE(VM_EXEC,	       	VM_EXEC);
   BLANK();
   DEFINE(PAGE_SZ,	       	PAGE_SIZE);
-  DEFINE(VIRT_OFFSET,		PAGE_OFFSET);
   BLANK();
   DEFINE(SYS_ERROR0,		0x9f0000);
   BLANK();
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 93b5e8e..be439ca 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -15,6 +15,7 @@
  */
 #include <linux/config.h>
 
+#include <asm/memory.h>
 #include <asm/glue.h>
 #include <asm/vfpmacros.h>
 #include <asm/hardware.h>		/* should be moved into entry-macro.S */
@@ -310,7 +311,7 @@
 
 #if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
 	@ make sure our user space atomic helper is aborted
-	cmp	r2, #VIRT_OFFSET
+	cmp	r2, #TASK_SIZE
 	bichs	r3, r3, #PSR_Z_BIT
 #endif
 
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 5396263..8d87484 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -21,6 +21,7 @@
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
+#include <asm/memory.h>
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
@@ -33,52 +34,28 @@
 #define MACHINFO_PGOFFIO	12
 #define MACHINFO_NAME		16
 
-#ifndef CONFIG_XIP_KERNEL
 /*
- * We place the page tables 16K below TEXTADDR.  Therefore, we must make sure
- * that TEXTADDR is correctly set.  Currently, we expect the least significant
- * 16 bits to be 0x8000, but we could probably relax this restriction to
- * TEXTADDR >= PAGE_OFFSET + 0x4000
- *
- * Note that swapper_pg_dir is the virtual address of the page tables, and
- * pgtbl gives us a position-independent reference to these tables.  We can
- * do this because stext == TEXTADDR
+ * swapper_pg_dir is the virtual address of the initial page table.
+ * We place the page tables 16K below KERNEL_RAM_ADDR.  Therefore, we must
+ * make sure that KERNEL_RAM_ADDR is correctly set.  Currently, we expect
+ * the least significant 16 bits to be 0x8000, but we could probably
+ * relax this restriction to KERNEL_RAM_ADDR >= PAGE_OFFSET + 0x4000.
  */
-#if (TEXTADDR & 0xffff) != 0x8000
-#error TEXTADDR must start at 0xXXXX8000
+#if (KERNEL_RAM_ADDR & 0xffff) != 0x8000
+#error KERNEL_RAM_ADDR must start at 0xXXXX8000
 #endif
 
 	.globl	swapper_pg_dir
-	.equ	swapper_pg_dir, TEXTADDR - 0x4000
+	.equ	swapper_pg_dir, KERNEL_RAM_ADDR - 0x4000
 
-	.macro	pgtbl, rd, phys
-	adr	\rd, stext
-	sub	\rd, \rd, #0x4000
+	.macro	pgtbl, rd
+	ldr	\rd, =(__virt_to_phys(KERNEL_RAM_ADDR - 0x4000))
 	.endm
+
+#ifdef CONFIG_XIP_KERNEL
+#define TEXTADDR  XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
 #else
-/*
- * XIP Kernel:
- *
- * We place the page tables 16K below DATAADDR.  Therefore, we must make sure
- * that DATAADDR is correctly set.  Currently, we expect the least significant
- * 16 bits to be 0x8000, but we could probably relax this restriction to
- * DATAADDR >= PAGE_OFFSET + 0x4000
- *
- * Note that pgtbl is meant to return the physical address of swapper_pg_dir.
- * We can't make it relative to the kernel position in this case since
- * the kernel can physically be anywhere.
- */
-#if (DATAADDR & 0xffff) != 0x8000
-#error DATAADDR must start at 0xXXXX8000
-#endif
-
-	.globl	swapper_pg_dir
-	.equ	swapper_pg_dir, DATAADDR - 0x4000
-
-	.macro	pgtbl, rd, phys
-	ldr	\rd, =((DATAADDR - 0x4000) - VIRT_OFFSET)
-	add	\rd, \rd, \phys
-	.endm
+#define TEXTADDR  KERNEL_RAM_ADDR
 #endif
 
 /*
@@ -279,7 +256,7 @@
 	.type	__create_page_tables, %function
 __create_page_tables:
 	ldr	r5, [r8, #MACHINFO_PHYSRAM]	@ physram
-	pgtbl	r4, r5				@ page table address
+	pgtbl	r4				@ page table address
 
 	/*
 	 * Clear the 16K level 1 swapper page table
@@ -324,7 +301,7 @@
 	/*
 	 * Then map first 1MB of ram in case it contains our boot params.
 	 */
-	add	r0, r4, #VIRT_OFFSET >> 18
+	add	r0, r4, #PAGE_OFFSET >> 18
 	orr	r6, r5, r7
 	str	r6, [r0]
 
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 1a85cfd..6055e14 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -11,6 +11,7 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleloader.h>
 #include <linux/kernel.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index cd99b83..9bd8609 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -782,7 +782,7 @@
 	return ret;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a94d75f..a917e3d 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -139,93 +139,33 @@
 	unsigned long	storage[0x98/4];
 };
 
-static int page_present(struct mm_struct *mm, void __user *uptr, int wr)
-{
-	unsigned long addr = (unsigned long)uptr;
-	pgd_t *pgd = pgd_offset(mm, addr);
-	if (pgd_present(*pgd)) {
-		pmd_t *pmd = pmd_offset(pgd, addr);
-		if (pmd_present(*pmd)) {
-			pte_t *pte = pte_offset_map(pmd, addr);
-			return (pte_present(*pte) && (!wr || pte_write(*pte)));
-		}
-	}
-	return 0;
-}
-
-static int copy_locked(void __user *uptr, void *kptr, size_t size, int write,
-		       void (*copyfn)(void *, void __user *))
-{
-	unsigned char v, __user *userptr = uptr;
-	int err = 0;
-
-	do {
-		struct mm_struct *mm;
-
-		if (write) {
-			__put_user_error(0, userptr, err);
-			__put_user_error(0, userptr + size - 1, err);
-		} else {
-			__get_user_error(v, userptr, err);
-			__get_user_error(v, userptr + size - 1, err);
-		}
-
-		if (err)
-			break;
-
-		mm = current->mm;
-		spin_lock(&mm->page_table_lock);
-		if (page_present(mm, userptr, write) &&
-		    page_present(mm, userptr + size - 1, write)) {
-		    	copyfn(kptr, uptr);
-		} else
-			err = 1;
-		spin_unlock(&mm->page_table_lock);
-	} while (err);
-
-	return err;
-}
-
 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 {
-	int err = 0;
+	char kbuf[sizeof(*frame) + 8];
+	struct iwmmxt_sigframe *kframe;
 
 	/* the iWMMXt context must be 64 bit aligned */
-	WARN_ON((unsigned long)frame & 7);
-
-	__put_user_error(IWMMXT_MAGIC0, &frame->magic0, err);
-	__put_user_error(IWMMXT_MAGIC1, &frame->magic1, err);
-
-	/*
-	 * iwmmxt_task_copy() doesn't check user permissions.
-	 * Let's do a dummy write on the upper boundary to ensure
-	 * access to user mem is OK all way up.
-	 */
-	err |= copy_locked(&frame->storage, current_thread_info(),
-			   sizeof(frame->storage), 1, iwmmxt_task_copy);
-	return err;
+	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
+	kframe->magic0 = IWMMXT_MAGIC0;
+	kframe->magic1 = IWMMXT_MAGIC1;
+	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
+	return __copy_to_user(frame, kframe, sizeof(*frame));
 }
 
 static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 {
-	unsigned long magic0, magic1;
-	int err = 0;
+	char kbuf[sizeof(*frame) + 8];
+	struct iwmmxt_sigframe *kframe;
 
-	/* the iWMMXt context is 64 bit aligned */
-	WARN_ON((unsigned long)frame & 7);
-
-	/*
-	 * Validate iWMMXt context signature.
-	 * Also, iwmmxt_task_restore() doesn't check user permissions.
-	 * Let's do a dummy write on the upper boundary to ensure
-	 * access to user mem is OK all way up.
-	 */
-	__get_user_error(magic0, &frame->magic0, err);
-	__get_user_error(magic1, &frame->magic1, err);
-	if (!err && magic0 == IWMMXT_MAGIC0 && magic1 == IWMMXT_MAGIC1)
-		err = copy_locked(&frame->storage, current_thread_info(),
-				  sizeof(frame->storage), 0, iwmmxt_task_restore);
-	return err;
+	/* the iWMMXt context must be 64 bit aligned */
+	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
+	if (__copy_from_user(kframe, frame, sizeof(*frame)))
+		return -1;
+	if (kframe->magic0 != IWMMXT_MAGIC0 ||
+	    kframe->magic1 != IWMMXT_MAGIC1)
+		return -1;
+	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
+	return 0;
 }
 
 #endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 69449a8..fc47291 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -36,10 +36,6 @@
 #include <asm/thread_info.h>
 #include <asm/mach/time.h>
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 /*
  * Our system timer.
  */
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index f6de76e..45e9ea6 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -198,25 +198,16 @@
 	barrier();
 }
 
-DEFINE_SPINLOCK(die_lock);
-
-/*
- * This function is protected against re-entrancy.
- */
-NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
+static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 {
-	struct task_struct *tsk = current;
+	struct task_struct *tsk = thread->task;
 	static int die_counter;
 
-	console_verbose();
-	spin_lock_irq(&die_lock);
-	bust_spinlocks(1);
-
 	printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
 	print_modules();
 	__show_regs(regs);
 	printk("Process %s (pid: %d, stack limit = 0x%p)\n",
-		tsk->comm, tsk->pid, tsk->thread_info + 1);
+		tsk->comm, tsk->pid, thread + 1);
 
 	if (!user_mode(regs) || in_interrupt()) {
 		dump_mem("Stack: ", regs->ARM_sp,
@@ -224,7 +215,21 @@
 		dump_backtrace(regs, tsk);
 		dump_instr(regs);
 	}
+}
 
+DEFINE_SPINLOCK(die_lock);
+
+/*
+ * This function is protected against re-entrancy.
+ */
+NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
+{
+	struct thread_info *thread = current_thread_info();
+
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+	__die(str, err, thread, regs);
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
@@ -345,7 +350,9 @@
 	struct thread_info *thread = current_thread_info();
 	siginfo_t info;
 
-	if (current->personality != PER_LINUX && thread->exec_domain->handler) {
+	if (current->personality != PER_LINUX &&
+	    current->personality != PER_LINUX_32BIT &&
+	    thread->exec_domain->handler) {
 		thread->exec_domain->handler(n, regs);
 		return regs->ARM_r0;
 	}
@@ -481,29 +488,33 @@
 		unsigned long addr = regs->ARM_r2;
 		struct mm_struct *mm = current->mm;
 		pgd_t *pgd; pmd_t *pmd; pte_t *pte;
+		spinlock_t *ptl;
 
 		regs->ARM_cpsr &= ~PSR_C_BIT;
-		spin_lock(&mm->page_table_lock);
+		down_read(&mm->mmap_sem);
 		pgd = pgd_offset(mm, addr);
 		if (!pgd_present(*pgd))
 			goto bad_access;
 		pmd = pmd_offset(pgd, addr);
 		if (!pmd_present(*pmd))
 			goto bad_access;
-		pte = pte_offset_map(pmd, addr);
-		if (!pte_present(*pte) || !pte_write(*pte))
+		pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+		if (!pte_present(*pte) || !pte_write(*pte)) {
+			pte_unmap_unlock(pte, ptl);
 			goto bad_access;
+		}
 		val = *(unsigned long *)addr;
 		val -= regs->ARM_r0;
 		if (val == 0) {
 			*(unsigned long *)addr = regs->ARM_r1;
 			regs->ARM_cpsr |= PSR_C_BIT;
 		}
-		spin_unlock(&mm->page_table_lock);
+		pte_unmap_unlock(pte, ptl);
+		up_read(&mm->mmap_sem);
 		return val;
 
 		bad_access:
-		spin_unlock(&mm->page_table_lock);
+		up_read(&mm->mmap_sem);
 		/* simulate a write access fault */
 		do_DataAbort(addr, 15 + (1 << 11), regs);
 		return -1;
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 0d5db52..80c8e4c 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -6,14 +6,23 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <linux/config.h>
 #include <asm/thread_info.h>
+#include <asm/memory.h>
 	
 OUTPUT_ARCH(arm)
 ENTRY(stext)
+
 #ifndef __ARMEB__
 jiffies = jiffies_64;
 #else
 jiffies = jiffies_64 + 4;
 #endif
+
+#ifdef CONFIG_XIP_KERNEL
+#define TEXTADDR  XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+#else
+#define TEXTADDR  KERNEL_RAM_ADDR
+#endif
+
 SECTIONS
 {
 	. = TEXTADDR;
@@ -95,7 +104,7 @@
 
 #ifdef CONFIG_XIP_KERNEL
 	__data_loc = ALIGN(4);		/* location in binary */
-	. = DATAADDR;
+	. = KERNEL_RAM_ADDR;
 #else
 	. = ALIGN(THREAD_SIZE);
 	__data_loc = .;
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 8725d63..71e5b99 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -11,7 +11,7 @@
 		   strnlen_user.o strchr.o strrchr.o testchangebit.o  \
 		   testclearbit.o testsetbit.o uaccess.o getuser.o    \
 		   putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o   \
-		   ucmpdi2.o lib1funcs.o div64.o	              \
+		   ucmpdi2.o lib1funcs.o div64.o sha1.o               \
 		   io-readsb.o io-writesb.o io-readsl.o io-writesl.o
 
 ifeq ($(CONFIG_CPU_32v3),y)
diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S
new file mode 100644
index 0000000..561e207
--- /dev/null
+++ b/arch/arm/lib/ashldi3.S
@@ -0,0 +1,48 @@
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+This file 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file 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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#include <linux/linkage.h>
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+ENTRY(__ashldi3)
+
+	subs	r3, r2, #32
+	rsb	ip, r2, #32
+	movmi	ah, ah, lsl r2
+	movpl	ah, al, lsl r3
+	orrmi	ah, ah, al, lsr ip
+	mov	al, al, lsl r2
+	mov	pc, lr
+
diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c
deleted file mode 100644
index b62875c..0000000
--- a/arch/arm/lib/ashldi3.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* More subroutines needed by GCC output code on some machines.  */
-/* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.
- */
-/* support functions required by the kernel. based on code from gcc-2.95.3 */
-/* I Molton	29/07/01 */
-
-#include "gcclib.h"
-
-s64 __ashldi3(s64 u, int b)
-{
-	DIunion w;
-	int bm;
-	DIunion uu;
-
-	if (b == 0)
-		return u;
-
-	uu.ll = u;
-
-	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
-	if (bm <= 0) {
-		w.s.low = 0;
-		w.s.high = (u32) uu.s.low << -bm;
-	} else {
-		u32 carries = (u32) uu.s.low >> bm;
-		w.s.low = (u32) uu.s.low << b;
-		w.s.high = ((u32) uu.s.high << b) | carries;
-	}
-
-	return w.ll;
-}
diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S
new file mode 100644
index 0000000..86fb2a9
--- /dev/null
+++ b/arch/arm/lib/ashrdi3.S
@@ -0,0 +1,48 @@
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+This file 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file 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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#include <linux/linkage.h>
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+ENTRY(__ashrdi3)
+
+	subs	r3, r2, #32
+	rsb	ip, r2, #32
+	movmi	al, al, lsr r2
+	movpl	al, ah, asr r3
+	orrmi	al, al, ah, lsl ip
+	mov	ah, ah, asr r2
+	mov	pc, lr
+
diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c
deleted file mode 100644
index 9a8600a..0000000
--- a/arch/arm/lib/ashrdi3.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* More subroutines needed by GCC output code on some machines.  */
-/* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.
- */
-/* support functions required by the kernel. based on code from gcc-2.95.3 */
-/* I Molton     29/07/01 */
-
-#include "gcclib.h"
-
-s64 __ashrdi3(s64 u, int b)
-{
-	DIunion w;
-	int bm;
-	DIunion uu;
-
-	if (b == 0)
-		return u;
-
-	uu.ll = u;
-
-	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
-	if (bm <= 0) {
-		/* w.s.high = 1..1 or 0..0 */
-		w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
-		w.s.low = uu.s.high >> -bm;
-	} else {
-		u32 carries = (u32) uu.s.high << bm;
-		w.s.high = uu.s.high >> b;
-		w.s.low = ((u32) uu.s.low >> b) | carries;
-	}
-
-	return w.ll;
-}
diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h
deleted file mode 100644
index 8b6dcc6..0000000
--- a/arch/arm/lib/gcclib.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
-/* I Molton     29/07/01 */
-
-#include <linux/types.h>
-
-#define BITS_PER_UNIT	8
-#define SI_TYPE_SIZE	(sizeof(s32) * BITS_PER_UNIT)
-
-#ifdef __ARMEB__
-struct DIstruct {
-	s32 high, low;
-};
-#else
-struct DIstruct {
-	s32 low, high;
-};
-#endif
-
-typedef union {
-	struct DIstruct s;
-	s64 ll;
-} DIunion;
diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S
new file mode 100644
index 0000000..46c2ed1
--- /dev/null
+++ b/arch/arm/lib/lshrdi3.S
@@ -0,0 +1,48 @@
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+This file 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file 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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#include <linux/linkage.h>
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+ENTRY(__lshrdi3)
+
+	subs	r3, r2, #32
+	rsb	ip, r2, #32
+	movmi	al, al, lsr r2
+	movpl	al, ah, lsr r3
+	orrmi	al, al, ah, lsl ip
+	mov	ah, ah, lsr r2
+	mov	pc, lr
+
diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c
deleted file mode 100644
index 3681f49..0000000
--- a/arch/arm/lib/lshrdi3.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* More subroutines needed by GCC output code on some machines.  */
-/* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.
- */
-/* support functions required by the kernel. based on code from gcc-2.95.3 */
-/* I Molton     29/07/01 */
-
-#include "gcclib.h"
-
-s64 __lshrdi3(s64 u, int b)
-{
-	DIunion w;
-	int bm;
-	DIunion uu;
-
-	if (b == 0)
-		return u;
-
-	uu.ll = u;
-
-	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
-	if (bm <= 0) {
-		w.s.high = 0;
-		w.s.low = (u32) uu.s.high >> -bm;
-	} else {
-		u32 carries = (u32) uu.s.high << bm;
-		w.s.high = (u32) uu.s.high >> b;
-		w.s.low = ((u32) uu.s.low >> b) | carries;
-	}
-
-	return w.ll;
-}
diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S
new file mode 100644
index 0000000..c7fbdf0
--- /dev/null
+++ b/arch/arm/lib/muldi3.S
@@ -0,0 +1,44 @@
+/*
+ *  linux/arch/arm/lib/muldi3.S
+ *
+ *  Author:     Nicolas Pitre
+ *  Created:    Oct 19, 2005
+ *  Copyright:  Monta Vista 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/linkage.h>
+
+#ifdef __ARMEB__
+#define xh r0
+#define xl r1
+#define yh r2
+#define yl r3
+#else
+#define xl r0
+#define xh r1
+#define yl r2
+#define yh r3
+#endif
+
+ENTRY(__muldi3)
+
+	mul	xh, yl, xh
+	mla	xh, xl, yh, xh
+	mov	ip, xl, asr #16
+	mov	yh, yl, asr #16
+	bic	xl, xl, ip, lsl #16
+	bic	yl, yl, yh, lsl #16
+	mla	xh, yh, ip, xh
+	mul	yh, xl, yh
+	mul	xl, yl, xl
+	mul	ip, yl, ip
+	adds	xl, xl, yh, lsl #16
+	adc	xh, xh, yh, lsr #16
+	adds	xl, xl, ip, lsl #16
+	adc	xh, xh, ip, lsr #16
+	mov	pc, lr
+
diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c
deleted file mode 100644
index 0a3b933..0000000
--- a/arch/arm/lib/muldi3.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* More subroutines needed by GCC output code on some machines.  */
-/* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.
- */
-/* support functions required by the kernel. based on code from gcc-2.95.3 */
-/* I Molton     29/07/01 */
-
-#include "gcclib.h"
-
-#define umul_ppmm(xh, xl, a, b) \
-{register u32 __t0, __t1, __t2;                                     \
-  __asm__ ("%@ Inlined umul_ppmm					\n\
-        mov     %2, %5, lsr #16						\n\
-        mov     %0, %6, lsr #16						\n\
-        bic     %3, %5, %2, lsl #16					\n\
-        bic     %4, %6, %0, lsl #16					\n\
-        mul     %1, %3, %4						\n\
-        mul     %4, %2, %4						\n\
-        mul     %3, %0, %3						\n\
-        mul     %0, %2, %0						\n\
-        adds    %3, %4, %3						\n\
-        addcs   %0, %0, #65536						\n\
-        adds    %1, %1, %3, lsl #16					\n\
-        adc     %0, %0, %3, lsr #16"                                    \
-           : "=&r" ((u32) (xh)),                                    \
-             "=r" ((u32) (xl)),                                     \
-             "=&r" (__t0), "=&r" (__t1), "=r" (__t2)                    \
-           : "r" ((u32) (a)),                                       \
-             "r" ((u32) (b)));}
-
-#define __umulsidi3(u, v) \
-  ({DIunion __w;                                                        \
-    umul_ppmm (__w.s.high, __w.s.low, u, v);                            \
-    __w.ll; })
-
-s64 __muldi3(s64 u, s64 v)
-{
-	DIunion w;
-	DIunion uu, vv;
-
-	uu.ll = u, vv.ll = v;
-
-	w.ll = __umulsidi3(uu.s.low, vv.s.low);
-	w.s.high += ((u32) uu.s.low * (u32) vv.s.high
-		     + (u32) uu.s.high * (u32) vv.s.low);
-
-	return w.ll;
-}
diff --git a/arch/arm/lib/sha1.S b/arch/arm/lib/sha1.S
new file mode 100644
index 0000000..ff6ece4
--- /dev/null
+++ b/arch/arm/lib/sha1.S
@@ -0,0 +1,206 @@
+/*
+ *  linux/arch/arm/lib/sha1.S
+ *
+ *  SHA transform optimized for ARM
+ *
+ *  Copyright:	(C) 2005 by Nicolas Pitre <nico@cam.org>
+ *  Created:	September 17, 2005
+ *
+ *  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.
+ *
+ *  The reference implementation for this code is linux/lib/sha1.c
+ */
+
+#include <linux/linkage.h>
+
+	.text
+
+
+/*
+ * void sha_transform(__u32 *digest, const char *in, __u32 *W)
+ *
+ * Note: the "in" ptr may be unaligned.
+ */
+
+ENTRY(sha_transform)
+
+	stmfd	sp!, {r4 - r8, lr}
+
+	@ for (i = 0; i < 16; i++)
+	@         W[i] = be32_to_cpu(in[i]); */
+
+#ifdef __ARMEB__
+	mov	r4, r0
+	mov	r0, r2
+	mov	r2, #64
+	bl	memcpy
+	mov	r2, r0
+	mov	r0, r4
+#else
+	mov	r3, r2
+	mov	lr, #16
+1:	ldrb	r4, [r1], #1
+	ldrb	r5, [r1], #1
+	ldrb	r6, [r1], #1
+	ldrb	r7, [r1], #1
+	subs	lr, lr, #1
+	orr	r5, r5, r4, lsl #8
+	orr	r6, r6, r5, lsl #8
+	orr	r7, r7, r6, lsl #8
+	str	r7, [r3], #4
+	bne	1b
+#endif
+
+	@ for (i = 0; i < 64; i++)
+	@         W[i+16] = ror(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 31);
+
+	sub	r3, r2, #4
+	mov	lr, #64
+2:	ldr	r4, [r3, #4]!
+	subs	lr, lr, #1
+	ldr	r5, [r3, #8]
+	ldr	r6, [r3, #32]
+	ldr	r7, [r3, #52]
+	eor	r4, r4, r5
+	eor	r4, r4, r6
+	eor	r4, r4, r7
+	mov	r4, r4, ror #31
+	str	r4, [r3, #64]
+	bne	2b
+
+	/*
+	 * The SHA functions are:
+	 *
+	 * f1(B,C,D) = (D ^ (B & (C ^ D)))
+	 * f2(B,C,D) = (B ^ C ^ D)
+	 * f3(B,C,D) = ((B & C) | (D & (B | C)))
+	 *
+	 * Then the sub-blocks are processed as follows:
+	 *
+	 * A' = ror(A, 27) + f(B,C,D) + E + K + *W++
+	 * B' = A
+	 * C' = ror(B, 2)
+	 * D' = C
+	 * E' = D
+	 *
+	 * We therefore unroll each loop 5 times to avoid register shuffling.
+	 * Also the ror for C (and also D and E which are successivelyderived
+	 * from it) is applied in place to cut on an additional mov insn for
+	 * each round.
+	 */
+
+	.macro	sha_f1, A, B, C, D, E
+	ldr	r3, [r2], #4
+	eor	ip, \C, \D
+	add	\E, r1, \E, ror #2
+	and	ip, \B, ip, ror #2
+	add	\E, \E, \A, ror #27
+	eor	ip, ip, \D, ror #2
+	add	\E, \E, r3
+	add	\E, \E, ip
+	.endm
+
+	.macro	sha_f2, A, B, C, D, E
+	ldr	r3, [r2], #4
+	add	\E, r1, \E, ror #2
+	eor	ip, \B, \C, ror #2
+	add	\E, \E, \A, ror #27
+	eor	ip, ip, \D, ror #2
+	add	\E, \E, r3
+	add	\E, \E, ip
+	.endm
+
+	.macro	sha_f3, A, B, C, D, E
+	ldr	r3, [r2], #4
+	add	\E, r1, \E, ror #2
+	orr	ip, \B, \C, ror #2
+	add	\E, \E, \A, ror #27
+	and	ip, ip, \D, ror #2
+	add	\E, \E, r3
+	and	r3, \B, \C, ror #2
+	orr	ip, ip, r3
+	add	\E, \E, ip
+	.endm
+
+	ldmia	r0, {r4 - r8}
+
+	mov	lr, #4
+	ldr	r1, .L_sha_K + 0
+
+	/* adjust initial values */
+	mov	r6, r6, ror #30
+	mov	r7, r7, ror #30
+	mov	r8, r8, ror #30
+
+3:	subs	lr, lr, #1
+	sha_f1	r4, r5, r6, r7, r8
+	sha_f1	r8, r4, r5, r6, r7
+	sha_f1	r7, r8, r4, r5, r6
+	sha_f1	r6, r7, r8, r4, r5
+	sha_f1	r5, r6, r7, r8, r4
+	bne	3b
+
+	ldr	r1, .L_sha_K + 4
+	mov	lr, #4
+
+4:	subs	lr, lr, #1
+	sha_f2	r4, r5, r6, r7, r8
+	sha_f2	r8, r4, r5, r6, r7
+	sha_f2	r7, r8, r4, r5, r6
+	sha_f2	r6, r7, r8, r4, r5
+	sha_f2	r5, r6, r7, r8, r4
+	bne	4b
+
+	ldr	r1, .L_sha_K + 8
+	mov	lr, #4
+
+5:	subs	lr, lr, #1
+	sha_f3	r4, r5, r6, r7, r8
+	sha_f3	r8, r4, r5, r6, r7
+	sha_f3	r7, r8, r4, r5, r6
+	sha_f3	r6, r7, r8, r4, r5
+	sha_f3	r5, r6, r7, r8, r4
+	bne	5b
+
+	ldr	r1, .L_sha_K + 12
+	mov	lr, #4
+
+6:	subs	lr, lr, #1
+	sha_f2	r4, r5, r6, r7, r8
+	sha_f2	r8, r4, r5, r6, r7
+	sha_f2	r7, r8, r4, r5, r6
+	sha_f2	r6, r7, r8, r4, r5
+	sha_f2	r5, r6, r7, r8, r4
+	bne	6b
+
+	ldmia	r0, {r1, r2, r3, ip, lr}
+	add	r4, r1, r4
+	add	r5, r2, r5
+	add	r6, r3, r6, ror #2
+	add	r7, ip, r7, ror #2
+	add	r8, lr, r8, ror #2
+	stmia	r0, {r4 - r8}
+
+	ldmfd	sp!, {r4 - r8, pc}
+
+.L_sha_K:
+	.word	0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
+
+
+/*
+ * void sha_init(__u32 *buf)
+ */
+
+.L_sha_initial_digest:
+	.word	0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
+
+ENTRY(sha_init)
+
+	str	lr, [sp, #-4]!
+	adr	r1, .L_sha_initial_digest
+	ldmia	r1, {r1, r2, r3, ip, lr}
+	stmia	r0, {r1, r2, r3, ip, lr}
+	ldr	pc, [sp], #4
+
diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S
new file mode 100644
index 0000000..112630f
--- /dev/null
+++ b/arch/arm/lib/ucmpdi2.S
@@ -0,0 +1,35 @@
+/*
+ *  linux/arch/arm/lib/ucmpdi2.S
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Oct 19, 2005
+ *  Copyright:	Monta Vista 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/linkage.h>
+
+#ifdef __ARMEB__
+#define xh r0
+#define xl r1
+#define yh r2
+#define yl r3
+#else
+#define xl r0
+#define xh r1
+#define yl r2
+#define yh r3
+#endif
+
+ENTRY(__ucmpdi2)
+
+	cmp	xh, yh
+	cmpeq	xl, yl
+	movlo	r0, #0
+	moveq	r0, #1
+	movhi	r0, #2
+	mov	pc, lr
+
diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c
deleted file mode 100644
index 57f3f2d..0000000
--- a/arch/arm/lib/ucmpdi2.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* More subroutines needed by GCC output code on some machines.  */
-/* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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.
-
-GNU CC 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.
- */
-/* support functions required by the kernel. based on code from gcc-2.95.3 */
-/* I Molton     29/07/01 */
-
-#include "gcclib.h"
-
-int __ucmpdi2(s64 a, s64 b)
-{
-	DIunion au, bu;
-
-	au.ll = a, bu.ll = b;
-
-	if ((u32) au.s.high < (u32) bu.s.high)
-		return 0;
-	else if ((u32) au.s.high > (u32) bu.s.high)
-		return 2;
-	if ((u32) au.s.low < (u32) bu.s.low)
-		return 0;
-	else if ((u32) au.s.low > (u32) bu.s.low)
-		return 2;
-	return 1;
-}
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile
index 20ec838..a8e462f 100644
--- a/arch/arm/mach-aaec2000/Makefile
+++ b/arch/arm/mach-aaec2000/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support (must be linked before board specific support)
-obj-y += core.o
+obj-y += core.o clock.o
 
 # Specific board support
 obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index c9d8998..f5ef697 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -27,16 +27,65 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/aaed2000.h>
+
 #include "core.h"
 
+static void aaed2000_clcd_disable(struct clcd_fb *fb)
+{
+	AAED_EXT_GPIO &= ~AAED_EGPIO_LCD_PWR_EN;
+}
+
+static void aaed2000_clcd_enable(struct clcd_fb *fb)
+{
+	AAED_EXT_GPIO |= AAED_EGPIO_LCD_PWR_EN;
+}
+
+struct aaec2000_clcd_info clcd_info = {
+	.enable = aaed2000_clcd_enable,
+	.disable = aaed2000_clcd_disable,
+	.panel = {
+		.mode	= {
+			.name		= "Sharp",
+			.refresh	= 60,
+			.xres		= 640,
+			.yres		= 480,
+			.pixclock	= 39721,
+			.left_margin	= 20,
+			.right_margin	= 44,
+			.upper_margin	= 21,
+			.lower_margin	= 34,
+			.hsync_len	= 96,
+			.vsync_len	= 2,
+			.sync		= 0,
+			.vmode	= FB_VMODE_NONINTERLACED,
+		},
+		.width	= -1,
+		.height	= -1,
+		.tim2	= TIM2_IVS | TIM2_IHS,
+		.cntl	= CNTL_LCDTFT,
+		.bpp	= 16,
+	},
+};
+
 static void __init aaed2000_init_irq(void)
 {
 	aaec2000_init_irq();
 }
 
+static void __init aaed2000_init(void)
+{
+	aaec2000_set_clcd_plat_data(&clcd_info);
+}
+
+static struct map_desc aaed2000_io_desc[] __initdata = {
+  { EXT_GPIO_VBASE, EXT_GPIO_PBASE, EXT_GPIO_LENGTH, MT_DEVICE }, /* Ext GPIO */
+};
+
 static void __init aaed2000_map_io(void)
 {
 	aaec2000_map_io();
+	iotable_init(aaed2000_io_desc, ARRAY_SIZE(aaed2000_io_desc));
 }
 
 MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
@@ -47,4 +96,5 @@
 	.map_io		= aaed2000_map_io,
 	.init_irq	= aaed2000_init_irq,
 	.timer		= &aaec2000_timer,
+	.init_machine	= aaed2000_init,
 MACHINE_END
diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c
new file mode 100644
index 0000000..99e0191
--- /dev/null
+++ b/arch/arm/mach-aaec2000/clock.c
@@ -0,0 +1,110 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/clock.c
+ *
+ *  Copyright (C) 2005 Nicolas Bellido Y Ortega
+ *
+ *  Based on linux/arch/arm/mach-integrator/clock.c
+ *
+ * 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/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware/clock.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+	down(&clocks_sem);
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up(&clocks_sem);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_add(&clk->node, &clocks);
+	up(&clocks_sem);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_del(&clk->node);
+	up(&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init(void)
+{
+	return 0;
+}
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-aaec2000/clock.h b/arch/arm/mach-aaec2000/clock.h
new file mode 100644
index 0000000..d4bb74f
--- /dev/null
+++ b/arch/arm/mach-aaec2000/clock.h
@@ -0,0 +1,23 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/clock.h
+ *
+ *  Copyright (C) 2005 Nicolas Bellido Y Ortega
+ *
+ *  Based on linux/arch/arm/mach-integrator/clock.h
+ *
+ * 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.
+ */
+struct module;
+
+struct clk {
+	struct list_head	node;
+	unsigned long		rate;
+	struct module		*owner;
+	const char		*name;
+	void			*data;
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index aece0cd..0c53dab 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -13,19 +13,27 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/device.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/signal.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/hardware/amba.h>
 
+#include <asm/mach/flash.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
+#include "core.h"
+#include "clock.h"
+
 /*
  * Common I/O mapping:
  *
@@ -40,9 +48,17 @@
  * default mapping provided here.
  */
 static struct map_desc standard_io_desc[] __initdata = {
- /* virtual         physical       length           type */
-  { VIO_APB_BASE,   PIO_APB_BASE,  IO_APB_LENGTH,   MT_DEVICE },
-  { VIO_AHB_BASE,   PIO_AHB_BASE,  IO_AHB_LENGTH,   MT_DEVICE }
+	{
+		.virtual	= VIO_APB_BASE,
+		.physical	= __phys_to_pfn(PIO_APB_BASE),
+		.length		= IO_APB_LENGTH,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= VIO_AHB_BASE,
+		.physical	= __phys_to_pfn(PIO_AHB_BASE),
+		.length		= IO_AHB_LENGTH,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init aaec2000_map_io(void)
@@ -155,3 +171,116 @@
 	.offset		= aaec2000_gettimeoffset,
 };
 
+static struct clcd_panel mach_clcd_panel;
+
+static int aaec2000_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel = &mach_clcd_panel;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, SZ_1M,
+			&dma, GFP_KERNEL);
+
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = SZ_1M;
+
+	return 0;
+}
+
+static int aaec2000_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+			fb->fb.screen_base,
+			fb->fb.fix.smem_start,
+			fb->fb.fix.smem_len);
+}
+
+static void aaec2000_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_plat_data = {
+	.name	= "AAEC-2000",
+	.check	= clcdfb_check,
+	.decode	= clcdfb_decode,
+	.setup	= aaec2000_clcd_setup,
+	.mmap	= aaec2000_clcd_mmap,
+	.remove	= aaec2000_clcd_remove,
+};
+
+static struct amba_device clcd_device = {
+	.dev		= {
+		.bus_id			= "mb:16",
+		.coherent_dma_mask	= ~0,
+		.platform_data		= &clcd_plat_data,
+	},
+	.res		= {
+		.start			= AAEC_CLCD_PHYS,
+		.end			= AAEC_CLCD_PHYS + SZ_4K - 1,
+		.flags			= IORESOURCE_MEM,
+	},
+	.irq		= { INT_LCD, NO_IRQ },
+	.periphid	= 0x41110,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+	&clcd_device,
+};
+
+static struct clk aaec2000_clcd_clk = {
+	.name = "CLCDCLK",
+};
+
+void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *clcd)
+{
+	clcd_plat_data.enable = clcd->enable;
+	clcd_plat_data.disable = clcd->disable;
+	memcpy(&mach_clcd_panel, &clcd->panel, sizeof(struct clcd_panel));
+}
+
+static struct flash_platform_data aaec2000_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 4,
+};
+
+static struct resource aaec2000_flash_resource = {
+	.start		= AAEC_FLASH_BASE,
+	.end		= AAEC_FLASH_BASE + AAEC_FLASH_SIZE,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device aaec2000_flash_device = {
+	.name		= "armflash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &aaec2000_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &aaec2000_flash_resource,
+};
+
+static int __init aaec2000_init(void)
+{
+	int i;
+
+	clk_register(&aaec2000_clcd_clk);
+
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+
+	platform_device_register(&aaec2000_flash_device);
+
+	return 0;
+};
+arch_initcall(aaec2000_init);
+
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
index 91893d8..daefc0e 100644
--- a/arch/arm/mach-aaec2000/core.h
+++ b/arch/arm/mach-aaec2000/core.h
@@ -9,8 +9,19 @@
  *
  */
 
+#include <asm/hardware/amba_clcd.h>
+
 struct sys_timer;
 
 extern struct sys_timer aaec2000_timer;
 extern void __init aaec2000_map_io(void);
 extern void __init aaec2000_init_irq(void);
+
+struct aaec2000_clcd_info {
+	struct clcd_panel panel;
+	void (*disable)(struct clcd_fb *);
+	void (*enable)(struct clcd_fb *);
+};
+
+extern void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *);
+
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index 0793dcf..d5c1550 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -69,6 +69,17 @@
 
 	  You almost surely want to say N here.
 
+config MACH_MP1000
+	bool "MACH_MP1000"
+	help
+	  Say Y if you intend to run the kernel on the Comdial MP1000 platform.
+
+config MP1000_90MHZ
+	bool "MP1000_90MHZ"
+	depends on MACH_MP1000
+	help
+	  Say Y if you have the MP1000 configured to be set at 90MHZ rather than 74MHZ
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-clps711x/Makefile b/arch/arm/mach-clps711x/Makefile
index 4a19731..8a6dc1c 100644
--- a/arch/arm/mach-clps711x/Makefile
+++ b/arch/arm/mach-clps711x/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o
 obj-$(CONFIG_ARCH_EDB7211)  += edb7211-arch.o edb7211-mm.o
 obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o
+obj-$(CONFIG_MACH_MP1000)   += mp1000-mach.o mp1000-mm.o mp1000-seprom.o
 obj-$(CONFIG_ARCH_P720T)    += p720t.o
 leds-$(CONFIG_ARCH_P720T)   += p720t-leds.o
 obj-$(CONFIG_LEDS)          += $(leds-y)
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index dc73feb..43b9423 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -46,10 +46,14 @@
 */
 
 static struct map_desc autcpu12_io_desc[] __initdata = {
- /* virtual, physical, length, type */
- /* memory-mapped extra io and CS8900A Ethernet chip */
- /* ethernet chip */
- 	{ AUTCPU12_VIRT_CS8900A, AUTCPU12_PHYS_CS8900A, SZ_1M, MT_DEVICE }
+	/* memory-mapped extra io and CS8900A Ethernet chip */
+ 	/* ethernet chip */
+ 	{
+		.virtual	= AUTCPU12_VIRT_CS8900A,
+		.pfn		= __phys_to_pfn(AUTCPU12_PHYS_CS8900A),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init autcpu12_map_io(void)
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
index a46c82c..cba7be5 100644
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -39,7 +39,12 @@
  * ethernet driver, perhaps.
  */
 static struct map_desc cdb89712_io_desc[] __initdata = {
-	{ ETHER_BASE, ETHER_START, ETHER_SIZE, MT_DEVICE }
+	{
+		.virtual	= ETHER_BASE,
+		.pfn		=__phys_to_pfn(ETHER_START),
+		.length		= ETHER_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init cdb89712_map_io(void)
diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 780d918..35d51a7 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -37,11 +37,13 @@
 #include "common.h"
 
 static struct map_desc ceiva_io_desc[] __initdata = {
- /* virtual, physical, length, type */
-
- /* SED1355 controlled video RAM & registers */
- { CEIVA_VIRT_SED1355, CEIVA_PHYS_SED1355, SZ_2M, MT_DEVICE }
-
+ 	/* SED1355 controlled video RAM & registers */
+ 	{
+		.virtual	= CEIVA_VIRT_SED1355,
+		.pfn		= __phys_to_pfn(CEIVA_PHYS_SED1355),
+		.length		= SZ_2M,
+		.type		= MT_DEVICE
+	}
 };
 
 
diff --git a/arch/arm/mach-clps711x/edb7211-mm.c b/arch/arm/mach-clps711x/edb7211-mm.c
index 7fd7b01..72f8bb0 100644
--- a/arch/arm/mach-clps711x/edb7211-mm.c
+++ b/arch/arm/mach-clps711x/edb7211-mm.c
@@ -51,15 +51,27 @@
  *     happens).
  */
 static struct map_desc edb7211_io_desc[] __initdata = {
- /* virtual, physical, length, type */
-
- /* memory-mapped extra keyboard row and CS8900A Ethernet chip */
- { EP7211_VIRT_EXTKBD,  EP7211_PHYS_EXTKBD,  SZ_1M, MT_DEVICE }, 
- { EP7211_VIRT_CS8900A, EP7211_PHYS_CS8900A, SZ_1M, MT_DEVICE },
-
- /* flash banks */
- { EP7211_VIRT_FLASH1,  EP7211_PHYS_FLASH1,  SZ_8M, MT_DEVICE },
- { EP7211_VIRT_FLASH2,  EP7211_PHYS_FLASH2,  SZ_8M, MT_DEVICE }
+ 	{	/* memory-mapped extra keyboard row */
+	 	.virtual 	= EP7211_VIRT_EXTKBD,
+		.pfn		= __phys_to_pfn(EP7211_PHYS_EXTKBD),
+		.length		= SZ_1M,
+		.type		- MT_DEVICE
+	}, {	/* and CS8900A Ethernet chip */
+		.virtual	= EP7211_VIRT_CS8900A,
+		.pfn		= __phys_to_pfn(EP7211_PHYS_CS8900A),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}, { 	/* flash banks */
+		.virtual	= EP7211_VIRT_FLASH1,
+		.pfn		= __phys_to_pfn(EP7211_PHYS_FLASH1),
+		.length		= SZ_8M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= EP7211_VIRT_FLASH2,
+		.pfn		= __phys_to_pfn(EP7211_PHYS_FLASH2),
+		.length		= SZ_8M,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init edb7211_map_io(void)
diff --git a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c
index 120b7ca..a00f77ef 100644
--- a/arch/arm/mach-clps711x/mm.c
+++ b/arch/arm/mach-clps711x/mm.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 
+#include <asm/sizes.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -34,7 +35,12 @@
  * This maps the generic CLPS711x registers
  */
 static struct map_desc clps711x_io_desc[] __initdata = {
- { CLPS7111_VIRT_BASE,	CLPS7111_PHYS_BASE,	1048576, MT_DEVICE }
+	{
+		.virtual	= CLPS7111_VIRT_BASE,
+		.pfn		= __phys_to_pfn(CLPS7111_PHYS_BASE),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init clps711x_map_io(void)
diff --git a/arch/arm/mach-clps711x/mp1000-mach.c b/arch/arm/mach-clps711x/mp1000-mach.c
new file mode 100644
index 0000000..c2816bc
--- /dev/null
+++ b/arch/arm/mach-clps711x/mp1000-mach.c
@@ -0,0 +1,49 @@
+/*
+ *  linux/arch/arm/mach-mp1000/mp1000.c
+ *
+ *  Copyright (C) 2005 Comdial 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/mp1000-seprom.h>
+
+#include "common.h"
+
+extern void mp1000_map_io(void);
+
+static void __init mp1000_init(void)
+{
+    seprom_init();
+}
+
+MACHINE_START(MP1000, "Comdial MP1000")
+	/* Maintainer: Jon Ringle */
+	.phys_ram	= 0xc0000000,
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xff000000) >> 18) & 0xfffc,
+	.boot_params	= 0xc0015100,
+	.map_io		= mp1000_map_io,
+	.init_irq	= clps711x_init_irq,
+	.init_machine	= mp1000_init,
+	.timer		= &clps711x_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-clps711x/mp1000-mm.c b/arch/arm/mach-clps711x/mp1000-mm.c
new file mode 100644
index 0000000..20e810b
--- /dev/null
+++ b/arch/arm/mach-clps711x/mp1000-mm.c
@@ -0,0 +1,47 @@
+/*
+ *  linux/arch/arm/mach-mp1000/mm.c
+ *
+ *  Extra MM routines for the MP1000
+ *
+ *  Copyright (C) 2005 Comdial 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/map.h>
+
+extern void clps711x_map_io(void);
+
+static struct map_desc mp1000_io_desc[] __initdata = {
+    { MP1000_EIO_BASE,	MP1000_EIO_START,	MP1000_EIO_SIZE, MT_DEVICE },
+    { MP1000_FIO_BASE,	MP1000_FIO_START,	MP1000_FIO_SIZE, MT_DEVICE },
+    { MP1000_LIO_BASE,	MP1000_LIO_START,	MP1000_LIO_SIZE, MT_DEVICE },
+    { MP1000_NIO_BASE,	MP1000_NIO_START,	MP1000_NIO_SIZE, MT_DEVICE },
+    { MP1000_IDE_BASE,	MP1000_IDE_START,	MP1000_IDE_SIZE, MT_DEVICE },
+    { MP1000_DSP_BASE,	MP1000_DSP_START,	MP1000_DSP_SIZE, MT_DEVICE }
+};
+
+void __init mp1000_map_io(void)
+{
+	clps711x_map_io();
+	iotable_init(mp1000_io_desc, ARRAY_SIZE(mp1000_io_desc));
+}
diff --git a/arch/arm/mach-clps711x/mp1000-seprom.c b/arch/arm/mach-clps711x/mp1000-seprom.c
new file mode 100644
index 0000000..b22d0be
--- /dev/null
+++ b/arch/arm/mach-clps711x/mp1000-seprom.c
@@ -0,0 +1,195 @@
+/*`
+ * mp1000-seprom.c
+ *
+ *  This file contains the Serial EEPROM code for the MP1000 board
+ *
+ *  Copyright (C) 2005 Comdial 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/hardware/clps7111.h>
+#include <asm/arch/mp1000-seprom.h>
+
+/* If SepromInit() can initialize and checksum the seprom successfully, */
+/* then it will point seprom_data_ptr at the shadow copy.  */
+
+static eeprom_struct seprom_data;			/* shadow copy of seprom content */
+
+eeprom_struct *seprom_data_ptr = 0;		/* 0 => not initialized */
+
+/*
+ * Port D Bit 5 is Chip Select for EEPROM
+ * Port E Bit 0 is Input, Data out from EEPROM
+ * Port E Bit 1 is Output, Data in to EEPROM
+ * Port E Bit 2 is Output, CLK to EEPROM
+ */
+
+static char *port_d_ptr = (char *)(CLPS7111_VIRT_BASE + PDDR);
+static char *port_e_ptr = (char *)(CLPS7111_VIRT_BASE + PEDR);
+
+#define NO_OF_SHORTS	64	// Device is 64 x 16 bits
+#define ENABLE_RW	0
+#define DISABLE_RW	1
+
+static inline void toggle_seprom_clock(void)
+{
+	*port_e_ptr |= HwPortESepromCLK;
+	*port_e_ptr &= ~(HwPortESepromCLK);
+}
+
+static inline void select_eeprom(void)
+{
+	*port_d_ptr |= HwPortDEECS;
+	*port_e_ptr &= ~(HwPortESepromCLK);
+}
+
+static inline void deselect_eeprom(void)
+{
+	*port_d_ptr &= ~(HwPortDEECS);
+	*port_e_ptr &= ~(HwPortESepromDIn);
+}
+
+/*
+ * GetSepromDataPtr - returns pointer to shadow (RAM) copy of seprom
+ *                    and returns 0 if seprom is not initialized or
+ *                    has a checksum error.
+ */
+
+eeprom_struct* get_seprom_ptr(void)
+{
+	return seprom_data_ptr;
+}
+
+unsigned char* get_eeprom_mac_address(void)
+{
+	return seprom_data_ptr->variant.eprom_struct.mac_Address;
+}
+
+/*
+ * ReadSProm, Physically reads data from the Serial PROM
+ */
+static void read_sprom(short address, int length, eeprom_struct *buffer)
+{
+	short data = COMMAND_READ | (address & 0x3F);
+	short bit;
+	int i;
+
+	select_eeprom();
+
+	// Clock in 9 bits of the command
+	for (i = 0, bit = 0x100; i < 9; i++, bit >>= 1) {
+		if (data & bit)
+			*port_e_ptr |= HwPortESepromDIn;
+		else
+			*port_e_ptr &= ~(HwPortESepromDIn);
+
+		toggle_seprom_clock();
+	}
+
+	//
+	// Now read one or more shorts of data from the Seprom
+	//
+	while (length-- > 0) {
+		data = 0;
+
+		// Read 16 bits at a time
+		for (i = 0; i < 16; i++) {
+			data <<= 1;
+			toggle_seprom_clock();
+			data |= *port_e_ptr & HwPortESepromDOut;
+
+		}
+
+		buffer->variant.eprom_short_data[address++] = data;
+	}
+
+	deselect_eeprom();
+
+	return;
+}
+
+
+
+/*
+ * ReadSerialPROM
+ *
+ * Input: Pointer to array of 64 x 16 Bits
+ *
+ * Output: if no problem reading data is filled in
+ */
+static void read_serial_prom(eeprom_struct *data)
+{
+	read_sprom(0, 64, data);
+}
+
+
+//
+// Compute Serial EEPROM checksum
+//
+// Input: Pointer to struct with Eprom data
+//
+// Output: The computed Eprom checksum
+//
+static short compute_seprom_checksum(eeprom_struct *data)
+{
+	short checksum = 0;
+	int i;
+
+	for (i = 0; i < 126; i++) {
+		checksum += (short)data->variant.eprom_byte_data[i];
+	}
+
+	return((short)(0x5555 - (checksum & 0xFFFF)));
+}
+
+//
+// Make sure the data port bits for the SEPROM are correctly initialised
+//
+
+void __init seprom_init(void)
+{
+	short checksum;
+
+	// Init Port D
+	*(char *)(CLPS7111_VIRT_BASE + PDDDR) = 0x0;
+	*(char *)(CLPS7111_VIRT_BASE + PDDR) = 0x15;
+
+	// Init Port E
+	*(int *)(CLPS7111_VIRT_BASE + PEDDR) = 0x06;
+	*(int *)(CLPS7111_VIRT_BASE + PEDR) = 0x04;
+
+	//
+	// Make sure that EEPROM struct size never exceeds 128 bytes
+	//
+	if (sizeof(eeprom_struct) > 128) {
+		panic("Serial PROM struct size > 128, aborting read\n");
+	}
+
+	read_serial_prom(&seprom_data);
+
+	checksum = compute_seprom_checksum(&seprom_data);
+
+	if (checksum != seprom_data.variant.eprom_short_data[63]) {
+		panic("Serial EEPROM checksum failed\n");
+	}
+
+	seprom_data_ptr = &seprom_data;
+}
+
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index 5bdb90e..a1acb94 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -29,6 +29,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/setup.h>
+#include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -42,8 +43,17 @@
  * We map both here.
  */
 static struct map_desc p720t_io_desc[] __initdata = {
-	{ SYSPLD_VIRT_BASE,	SYSPLD_PHYS_BASE, 1048576, MT_DEVICE },
-	{ 0xfe400000,		0x10400000,	  1048576, MT_DEVICE }
+	{
+		.virtual	= SYSPLD_VIRT_BASE,
+		.pfn		= __phys_to_pfn(SYSPLD_PHYS_BASE),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= 0xfe400000,
+		.pfn		= __phys_to_pfn(0x10400000),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index e216ab8..0364ba4 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -259,10 +259,27 @@
 }
 
 static struct map_desc cl7500_io_desc[] __initdata = {
-	{ IO_BASE,	IO_START,	IO_SIZE,    MT_DEVICE },	/* IO space	*/
-	{ ISA_BASE,	ISA_START,	ISA_SIZE,   MT_DEVICE },	/* ISA space	*/
-	{ FLASH_BASE,	FLASH_START,	FLASH_SIZE, MT_DEVICE },	/* Flash	*/
-	{ LED_BASE,	LED_START,	LED_SIZE,   MT_DEVICE } 	/* LED		*/
+	{ 	/* IO space	*/
+		.virtual	= IO_BASE,
+		.pfn		= __phys_to_pfn(IO_START),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* ISA space	*/
+		.virtual	= ISA_BASE,
+		.pfn		= __phys_to_pfn(ISA_START),
+		.length		= ISA_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* Flash	*/
+		.virtual	= FLASH_BASE,
+		.pfn		= __phys_to_pfn(FLASH_START),
+		.length		= FLASH_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* LED		*/
+		.virtual	= LED_BASE,
+		.pfn		= __phys_to_pfn(LED_START),
+		.length		= LED_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init clps7500_map_io(void)
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index 5aeadfd..1526164 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -76,16 +76,42 @@
 	/*
 	 * sparse external-decode ISAIO space
 	 */
-	{ IRQ_STAT,    TRICK4_PHYS, PGDIR_SIZE,  MT_DEVICE }, /* IRQ_STAT/IRQ_MCLR */
-	{ IRQ_MASK,    TRICK3_PHYS, PGDIR_SIZE,  MT_DEVICE }, /* IRQ_MASK/IRQ_MSET */
-	{ SOFT_BASE,   TRICK1_PHYS, PGDIR_SIZE,  MT_DEVICE }, /* SOFT_BASE */
-	{ PIT_BASE,    TRICK0_PHYS, PGDIR_SIZE,  MT_DEVICE }, /* PIT_BASE */
+	{	/* IRQ_STAT/IRQ_MCLR */
+		.virtual	= IRQ_STAT,
+		.pfn		= __phys_to_pfn(TRICK4_PHYS),
+		.length		= PGDIR_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* IRQ_MASK/IRQ_MSET */
+		.virtual	= IRQ_MASK,
+		.pfn		= __phys_to_pfn(TRICK3_PHYS),
+		.length		= PGDIR_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* SOFT_BASE */
+		.virtual	= SOFT_BASE,
+		.pfn		= __phys_to_pfn(TRICK1_PHYS),
+		.length		= PGDIR_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* PIT_BASE */
+		.virtual	= PIT_BASE,
+		.pfn		= __phys_to_pfn(TRICK0_PHYS),
+		.length		= PGDIR_SIZE,
+		.type		= MT_DEVICE
+	},
 
 	/*
 	 * self-decode ISAIO space
 	 */
-	{ ISAIO_BASE,  ISAIO_PHYS,  ISAIO_SIZE,  MT_DEVICE },
-	{ ISAMEM_BASE, ISAMEM_PHYS, ISAMEM_SIZE, MT_DEVICE }
+	{
+		.virtual	= ISAIO_BASE,
+		.pfn		= __phys_to_pfn(ISAIO_PHYS),
+		.length		= ISAIO_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= ISAMEM_BASE,
+		.pfn		= __phys_to_pfn(ISAMEM_PHYS),
+		.length		= ISAMEM_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init ebsa110_map_io(void)
diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c
index ef7eb5d..c648bfb 100644
--- a/arch/arm/mach-ebsa110/io.c
+++ b/arch/arm/mach-ebsa110/io.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+#include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/page.h>
 
diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c
index 2aa57fa..e8832d0 100644
--- a/arch/arm/mach-epxa10db/mm.c
+++ b/arch/arm/mach-epxa10db/mm.c
@@ -31,12 +31,37 @@
 /* Page table mapping for I/O region */
  
 static struct map_desc epxa10db_io_desc[] __initdata = {
- { IO_ADDRESS(EXC_REGISTERS_BASE),   EXC_REGISTERS_BASE,    SZ_16K, MT_DEVICE }, 
- { IO_ADDRESS(EXC_PLD_BLOCK0_BASE),  EXC_PLD_BLOCK0_BASE,   SZ_16K, MT_DEVICE }, 
- { IO_ADDRESS(EXC_PLD_BLOCK1_BASE),  EXC_PLD_BLOCK1_BASE,   SZ_16K, MT_DEVICE }, 
- { IO_ADDRESS(EXC_PLD_BLOCK2_BASE),  EXC_PLD_BLOCK2_BASE,   SZ_16K, MT_DEVICE }, 
- { IO_ADDRESS(EXC_PLD_BLOCK3_BASE),  EXC_PLD_BLOCK3_BASE,   SZ_16K, MT_DEVICE }, 
- { FLASH_VADDR(EXC_EBI_BLOCK0_BASE), EXC_EBI_BLOCK0_BASE,   SZ_16M, MT_DEVICE }
+	{
+		.virtual	= IO_ADDRESS(EXC_REGISTERS_BASE),
+		.pfn		= __phys_to_pfn(EXC_REGISTERS_BASE),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(EXC_PLD_BLOCK0_BASE),
+		.pfn		= __phys_to_pfn(EXC_PLD_BLOCK0_BASE),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(EXC_PLD_BLOCK1_BASE),
+		.pfn		=__phys_to_pfn(EXC_PLD_BLOCK1_BASE),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(EXC_PLD_BLOCK2_BASE),
+		.physical	= __phys_to_pfn(EXC_PLD_BLOCK2_BASE),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(EXC_PLD_BLOCK3_BASE),
+		.pfn		= __phys_to_pfn(EXC_PLD_BLOCK3_BASE),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= FLASH_VADDR(EXC_EBI_BLOCK0_BASE),
+		.pfn		= __phys_to_pfn(EXC_EBI_BLOCK0_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init epxa10db_map_io(void)
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
index eb8238c..dc09fd2 100644
--- a/arch/arm/mach-footbridge/common.c
+++ b/arch/arm/mach-footbridge/common.c
@@ -130,8 +130,17 @@
  * it means that we have extra bullet protection on our feet.
  */
 static struct map_desc fb_common_io_desc[] __initdata = {
- { ARMCSR_BASE,	 DC21285_ARMCSR_BASE,	    ARMCSR_SIZE,  MT_DEVICE },
- { XBUS_BASE,    0x40000000,		    XBUS_SIZE,    MT_DEVICE }
+	{
+		.virtual	= ARMCSR_BASE,
+		.pfn		= DC21285_ARMCSR_BASE,
+		.length		= ARMCSR_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= XBUS_BASE,
+		.pfn		= __phys_to_pfn(0x40000000),
+		.length		= XBUS_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 /*
@@ -140,11 +149,32 @@
  */
 static struct map_desc ebsa285_host_io_desc[] __initdata = {
 #if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
- { PCIMEM_BASE,  DC21285_PCI_MEM,	    PCIMEM_SIZE,  MT_DEVICE },
- { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, MT_DEVICE },
- { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, MT_DEVICE },
- { PCIIACK_BASE, DC21285_PCI_IACK,	    PCIIACK_SIZE, MT_DEVICE },
- { PCIO_BASE,    DC21285_PCI_IO,	    PCIO_SIZE,	  MT_DEVICE }
+	{
+		.virtual	= PCIMEM_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_MEM),
+		.length		= PCIMEM_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCICFG0_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG),
+		.length		= PCICFG0_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCICFG1_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG),
+		.length		= PCICFG1_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCIIACK_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_IACK),
+		.length		= PCIIACK_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCIO_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_IO),
+		.length		= PCIO_SIZE,
+		.type		= MT_DEVICE
+	}
 #endif
 };
 
@@ -153,8 +183,17 @@
  */
 static struct map_desc co285_io_desc[] __initdata = {
 #ifdef CONFIG_ARCH_CO285
- { PCIO_BASE,	 DC21285_PCI_IO,	    PCIO_SIZE,    MT_DEVICE },
- { PCIMEM_BASE,	 DC21285_PCI_MEM,	    PCIMEM_SIZE,  MT_DEVICE }
+	{
+		.virtual	= PCIO_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_IO),
+		.length		= PCIO_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCIMEM_BASE,
+		.pfn		= __phys_to_pfn(DC21285_PCI_MEM),
+		.length		= PCIMEM_SIZE,
+		.type		= MT_DEVICE
+	}
 #endif
 };
 
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
index 5110e2e..c096b45 100644
--- a/arch/arm/mach-h720x/common.c
+++ b/arch/arm/mach-h720x/common.c
@@ -237,7 +237,12 @@
 }
 
 static struct map_desc h720x_io_desc[] __initdata = {
-	{ IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	},
 };
 
 /* Initialize io tables */
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index f8a742b..837d7f0 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -26,6 +26,8 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/string.h>
+
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
@@ -273,8 +275,12 @@
 };
 
 static struct map_desc imx_io_desc[] __initdata = {
-	/* virtual     physical    length      type */
-	{IMX_IO_BASE, IMX_IO_PHYS, IMX_IO_SIZE, MT_DEVICE},
+	{
+		.virtual	= IMX_IO_BASE,
+		.pfn		= __phys_to_pfn(IMX_IO_PHYS),
+		.length		= IMX_IO_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index a7511dd..4cbdc1f 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -61,13 +61,37 @@
 }
 
 static struct map_desc mx1ads_io_desc[] __initdata = {
-	/* virtual     physical    length      type */
-	{IMX_CS0_VIRT, IMX_CS0_PHYS, IMX_CS0_SIZE, MT_DEVICE},
-	{IMX_CS1_VIRT, IMX_CS1_PHYS, IMX_CS1_SIZE, MT_DEVICE},
-	{IMX_CS2_VIRT, IMX_CS2_PHYS, IMX_CS2_SIZE, MT_DEVICE},
-	{IMX_CS3_VIRT, IMX_CS3_PHYS, IMX_CS3_SIZE, MT_DEVICE},
-	{IMX_CS4_VIRT, IMX_CS4_PHYS, IMX_CS4_SIZE, MT_DEVICE},
-	{IMX_CS5_VIRT, IMX_CS5_PHYS, IMX_CS5_SIZE, MT_DEVICE},
+	{
+		.virtual	= IMX_CS0_VIRT,
+		.pfn		= __phys_to_pfn(IMX_CS0_PHYS),
+		.length		= IMX_CS0_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IMX_CS1_VIRT,
+		.pfn		= __phys_to_pfn(IMX_CS1_PHYS),
+		.length		= IMX_CS1_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IMX_CS2_VIRT,
+		.pfn		= __phys_to_pfn(IMX_CS2_PHYS),
+		.length		= IMX_CS2_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IMX_CS3_VIRT,
+		.pfn		= __phys_to_pfn(IMX_CS3_PHYS),
+		.length		= IMX_CS3_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IMX_CS4_VIRT,
+		.pfn		= __phys_to_pfn(IMX_CS4_PHYS),
+		.length		= IMX_CS4_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IMX_CS5_VIRT,
+		.pfn		= __phys_to_pfn(IMX_CS5_PHYS),
+		.length		= IMX_CS5_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init
diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
index 5620059..73c3606 100644
--- a/arch/arm/mach-integrator/clock.c
+++ b/arch/arm/mach-integrator/clock.c
@@ -13,6 +13,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/string.h>
 
 #include <asm/semaphore.h>
 #include <asm/hardware/clock.h>
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 36e2b6e..764ceb4 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -30,6 +30,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
+#include <asm/param.h>		/* HZ */
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_kmi.h>
@@ -75,19 +76,72 @@
  */
 
 static struct map_desc ap_io_desc[] __initdata = {
- { IO_ADDRESS(INTEGRATOR_HDR_BASE),   INTEGRATOR_HDR_BASE,   SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_SC_BASE),    INTEGRATOR_SC_BASE,    SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_EBI_BASE),   INTEGRATOR_EBI_BASE,   SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_CT_BASE),    INTEGRATOR_CT_BASE,    SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_IC_BASE),    INTEGRATOR_IC_BASE,    SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_DBG_BASE),   INTEGRATOR_DBG_BASE,   SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_GPIO_BASE),  INTEGRATOR_GPIO_BASE,  SZ_4K,  MT_DEVICE },
- { PCI_MEMORY_VADDR,                  PHYS_PCI_MEM_BASE,     SZ_16M, MT_DEVICE },
- { PCI_CONFIG_VADDR,                  PHYS_PCI_CONFIG_BASE,  SZ_16M, MT_DEVICE },
- { PCI_V3_VADDR,                      PHYS_PCI_V3_BASE,      SZ_64K, MT_DEVICE },
- { PCI_IO_VADDR,                      PHYS_PCI_IO_BASE,      SZ_64K, MT_DEVICE }
+	{
+		.virtual	= IO_ADDRESS(INTEGRATOR_HDR_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_HDR_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_CT_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_CT_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_IC_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_IC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_UART0_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_GPIO_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_GPIO_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCI_MEMORY_VADDR,
+		.pfn		= __phys_to_pfn(PHYS_PCI_MEM_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCI_CONFIG_VADDR,
+		.pfn		= __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCI_V3_VADDR,
+		.pfn		= __phys_to_pfn(PHYS_PCI_V3_BASE),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= PCI_IO_VADDR,
+		.pfn		= __phys_to_pfn(PHYS_PCI_IO_BASE),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init ap_map_io(void)
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 2be5c03..aa34c58 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -74,17 +74,62 @@
  */
 
 static struct map_desc intcp_io_desc[] __initdata = {
- { IO_ADDRESS(INTEGRATOR_HDR_BASE),   INTEGRATOR_HDR_BASE,   SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_SC_BASE),    INTEGRATOR_SC_BASE,    SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_EBI_BASE),   INTEGRATOR_EBI_BASE,   SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_CT_BASE),    INTEGRATOR_CT_BASE,    SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_IC_BASE),    INTEGRATOR_IC_BASE,    SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_DBG_BASE),   INTEGRATOR_DBG_BASE,   SZ_4K,  MT_DEVICE },
- { IO_ADDRESS(INTEGRATOR_GPIO_BASE),  INTEGRATOR_GPIO_BASE,  SZ_4K,  MT_DEVICE },
- { 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
- { 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
+	{
+		.virtual	= IO_ADDRESS(INTEGRATOR_HDR_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_HDR_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_CT_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_CT_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_IC_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_IC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_UART0_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(INTEGRATOR_GPIO_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_GPIO_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= 0xfca00000,
+		.pfn		= __phys_to_pfn(0xca000000),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= 0xfcb00000,
+		.pfn		= __phys_to_pfn(0xcb000000),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init intcp_map_io(void)
diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c
index c5f19d1..5b41e3a 100644
--- a/arch/arm/mach-integrator/lm.c
+++ b/arch/arm/mach-integrator/lm.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/slab.h>
 
 #include <asm/arch/lm.h>
 
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
index 0f921ba..bb50912 100644
--- a/arch/arm/mach-iop3xx/iop321-setup.c
+++ b/arch/arm/mach-iop3xx/iop321-setup.c
@@ -38,13 +38,17 @@
  * Standard IO mapping for all IOP321 based systems
  */
 static struct map_desc iop321_std_desc[] __initdata = {
- /* virtual     physical      length      type */
-
- /* mem mapped registers */
- { IOP321_VIRT_MEM_BASE,  IOP321_PHYS_MEM_BASE,   0x00002000,  MT_DEVICE },
-
- /* PCI IO space */
- { IOP321_PCI_LOWER_IO_VA,  IOP321_PCI_LOWER_IO_PA,   IOP321_PCI_IO_WINDOW_SIZE,  MT_DEVICE }
+	 {	/* mem mapped registers */
+		.virtual	= IOP321_VIRT_MEM_BASE,
+		.pfn		= __phys_to_pfn(IOP321_PHYS_MEM_BASE),
+		.length		= 0x00002000,
+		.type		= MT_DEVICE
+	 }, {	/* PCI IO space */
+		.virtual	= IOP321_PCI_LOWER_IO_VA,
+		.pfn		= __phys_to_pfn(IOP321_PCI_LOWER_IO_PA),
+		.length		= IOP321_PCI_IO_WINDOW_SIZE,
+		.type		= MT_DEVICE
+	 }
 };
 
 #ifdef CONFIG_ARCH_IQ80321
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
index fc74b72..a2533c3 100644
--- a/arch/arm/mach-iop3xx/iop331-setup.c
+++ b/arch/arm/mach-iop3xx/iop331-setup.c
@@ -37,13 +37,17 @@
  * Standard IO mapping for all IOP331 based systems
  */
 static struct map_desc iop331_std_desc[] __initdata = {
- /* virtual     physical      length      type */
-
- /* mem mapped registers */
- { IOP331_VIRT_MEM_BASE,  IOP331_PHYS_MEM_BASE,   0x00002000,  MT_DEVICE },
-
- /* PCI IO space */
- { IOP331_PCI_LOWER_IO_VA,  IOP331_PCI_LOWER_IO_PA,   IOP331_PCI_IO_WINDOW_SIZE,  MT_DEVICE }
+	{	/* mem mapped registers */
+		.virtual	= IOP331_VIRT_MEM_BASE,
+		.pfn		= __phys_to_pfn(IOP331_PHYS_MEM_BASE),
+		.length		= 0x00002000,
+		.type		= MT_DEVICE
+	}, {	/* PCI IO space */
+		.virtual	= IOP331_PCI_LOWER_IO_VA,
+		.pfn		= __phys_to_pfn(IOP331_PCI_LOWER_IO_PA),
+		.length		= IOP331_PCI_IO_WINDOW_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static struct uart_port iop331_serial_ports[] = {
diff --git a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c
index 55992ab..e874b54 100644
--- a/arch/arm/mach-iop3xx/iq31244-mm.c
+++ b/arch/arm/mach-iop3xx/iq31244-mm.c
@@ -29,10 +29,12 @@
  * We use RedBoot's setup for the onboard devices.
  */
 static struct map_desc iq31244_io_desc[] __initdata = {
- /* virtual     physical      length        type */
-
- /* on-board devices */
- { IQ31244_UART, IQ31244_UART,   0x00100000,   MT_DEVICE }
+	{	/* on-board devices */
+		.virtual	= IQ31244_UART,
+		.pfn		= __phys_to_pfn(IQ31244_UART),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init iq31244_map_io(void)
diff --git a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c
index f997daa..c6a973b 100644
--- a/arch/arm/mach-iop3xx/iq31244-pci.c
+++ b/arch/arm/mach-iop3xx/iq31244-pci.c
@@ -14,6 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
diff --git a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c
index bb3e9e5..d9cac5e 100644
--- a/arch/arm/mach-iop3xx/iq80321-mm.c
+++ b/arch/arm/mach-iop3xx/iq80321-mm.c
@@ -29,10 +29,12 @@
  * We use RedBoot's setup for the onboard devices.
  */
 static struct map_desc iq80321_io_desc[] __initdata = {
- /* virtual     physical      length        type */
-
- /* on-board devices */
- { IQ80321_UART, IQ80321_UART,   0x00100000,   MT_DEVICE }
+ 	{	/* on-board devices */
+		.virtual	= IQ80321_UART,
+		.pfn		= __phys_to_pfn(IQ80321_UART),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init iq80321_map_io(void)
diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c
index 79fea3d..802f6d0 100644
--- a/arch/arm/mach-iop3xx/iq80321-pci.c
+++ b/arch/arm/mach-iop3xx/iq80321-pci.c
@@ -14,6 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
diff --git a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c
index f37a0e2..654e450a 100644
--- a/arch/arm/mach-iop3xx/iq80331-pci.c
+++ b/arch/arm/mach-iop3xx/iq80331-pci.c
@@ -13,6 +13,8 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
diff --git a/arch/arm/mach-iop3xx/iq80332-pci.c b/arch/arm/mach-iop3xx/iq80332-pci.c
index b9807aa..65951ff 100644
--- a/arch/arm/mach-iop3xx/iq80332-pci.c
+++ b/arch/arm/mach-iop3xx/iq80332-pci.c
@@ -13,6 +13,8 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index f4d7f1f..01c393c 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -83,42 +83,42 @@
 static struct map_desc ixp2000_io_desc[] __initdata = {
 	{
 		.virtual	= IXP2000_CAP_VIRT_BASE,
-		.physical	= IXP2000_CAP_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_CAP_PHYS_BASE),
 		.length		= IXP2000_CAP_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_INTCTL_VIRT_BASE,
-		.physical	= IXP2000_INTCTL_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE),
 		.length		= IXP2000_INTCTL_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_PCI_CREG_VIRT_BASE,
-		.physical	= IXP2000_PCI_CREG_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE),
 		.length		= IXP2000_PCI_CREG_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_PCI_CSR_VIRT_BASE,
-		.physical	= IXP2000_PCI_CSR_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE),
 		.length		= IXP2000_PCI_CSR_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_MSF_VIRT_BASE,
-		.physical	= IXP2000_MSF_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_MSF_PHYS_BASE),
 		.length		= IXP2000_MSF_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_PCI_IO_VIRT_BASE,
-		.physical	= IXP2000_PCI_IO_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE),
 		.length		= IXP2000_PCI_IO_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_PCI_CFG0_VIRT_BASE,
-		.physical	= IXP2000_PCI_CFG0_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE),
 		.length		= IXP2000_PCI_CFG0_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_PCI_CFG1_VIRT_BASE,
-		.physical	= IXP2000_PCI_CFG1_PHYS_BASE,
+		.pfn		= __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE),
 		.length		= IXP2000_PCI_CFG1_SIZE,
 		.type		= MT_DEVICE
 	}
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 63ba019..8b4a839 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -176,7 +176,7 @@
  *************************************************************************/
 static struct map_desc ixdp2x00_io_desc __initdata = {
 	.virtual	= IXDP2X00_VIRT_CPLD_BASE, 
-	.physical	= IXDP2X00_PHYS_CPLD_BASE,
+	.pfn		= __phys_to_pfn(IXDP2X00_PHYS_CPLD_BASE),
 	.length		= IXDP2X00_CPLD_SIZE,
 	.type		= MT_DEVICE
 };
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 7a51099..fee1d7b 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -136,7 +136,7 @@
  *************************************************************************/
 static struct map_desc ixdp2x01_io_desc __initdata = {
 	.virtual	= IXDP2X01_VIRT_CPLD_BASE, 
-	.physical	= IXDP2X01_PHYS_CPLD_BASE,
+	.pfn		= __phys_to_pfn(IXDP2X01_PHYS_CPLD_BASE),
 	.length		= IXDP2X01_CPLD_REGION_SIZE,
 	.type		= MT_DEVICE
 };
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 36b6045..6c39644 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -44,24 +44,24 @@
 static struct map_desc ixp4xx_io_desc[] __initdata = {
 	{	/* UART, Interrupt ctrl, GPIO, timers, NPEs, MACs, USB .... */
 		.virtual	= IXP4XX_PERIPHERAL_BASE_VIRT,
-		.physical	= IXP4XX_PERIPHERAL_BASE_PHYS,
+		.pfn		= __phys_to_pfn(IXP4XX_PERIPHERAL_BASE_PHYS),
 		.length		= IXP4XX_PERIPHERAL_REGION_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* Expansion Bus Config Registers */
 		.virtual	= IXP4XX_EXP_CFG_BASE_VIRT,
-		.physical	= IXP4XX_EXP_CFG_BASE_PHYS,
+		.pfn		= __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
 		.length		= IXP4XX_EXP_CFG_REGION_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* PCI Registers */
 		.virtual	= IXP4XX_PCI_CFG_BASE_VIRT,
-		.physical	= IXP4XX_PCI_CFG_BASE_PHYS,
+		.pfn		= __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
 		.length		= IXP4XX_PCI_CFG_REGION_SIZE,
 		.type		= MT_DEVICE
 	},
 #ifdef CONFIG_DEBUG_LL
 	{	/* Debug UART mapping */
 		.virtual	= IXP4XX_DEBUG_UART_BASE_VIRT,
-		.physical	= IXP4XX_DEBUG_UART_BASE_PHYS,
+		.pfn		= __phys_to_pfn(IXP4XX_DEBUG_UART_BASE_PHYS),
 		.length		= IXP4XX_DEBUG_UART_REGION_SIZE,
 		.type		= MT_DEVICE
 	}
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index cb3dcd3..19f2fa2 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -26,8 +26,17 @@
       /* This function calls the board specific IRQ initialization function. */
 
 static struct map_desc kev7a400_io_desc[] __initdata = {
-	{ IO_VIRT,    IO_PHYS,    IO_SIZE,    MT_DEVICE },
-	{ CPLD_VIRT,  CPLD_PHYS,  CPLD_SIZE,  MT_DEVICE },
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD_VIRT,
+		.pfn		= __phys_to_pfn(CPLD_PHYS),
+		.length		= CPLD_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init kev7a400_map_io(void)
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 6eb61a1..a20eabc 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -227,23 +227,79 @@
 }
 
 static struct map_desc lpd7a400_io_desc[] __initdata = {
-	{     IO_VIRT,	    IO_PHYS,	    IO_SIZE,	MT_DEVICE },
-	/* Mapping added to work around chip select problems */
-	{ IOBARRIER_VIRT, IOBARRIER_PHYS, IOBARRIER_SIZE, MT_DEVICE },
-	{ CF_VIRT,	CF_PHYS,	CF_SIZE,	MT_DEVICE },
+	{
+		.virtual	=     IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= 	    IO_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* Mapping added to work around chip select problems */
+		.virtual	= IOBARRIER_VIRT,
+		.pfn		= __phys_to_pfn(IOBARRIER_PHYS),
+		.length		= IOBARRIER_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CF_VIRT,
+		.pfn		= __phys_to_pfn(CF_PHYS),
+		.length		= 	CF_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD02_VIRT,
+		.pfn		= __phys_to_pfn(CPLD02_PHYS),
+		.length		= 	CPLD02_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD06_VIRT,
+		.pfn		= __phys_to_pfn(CPLD06_PHYS),
+		.length		= 	CPLD06_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD08_VIRT,
+		.pfn		= __phys_to_pfn(CPLD08_PHYS),
+		.length		= 	CPLD08_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD0C_VIRT,
+		.pfn		= __phys_to_pfn(CPLD0C_PHYS),
+		.length		= 	CPLD0C_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD0E_VIRT,
+		.pfn		= __phys_to_pfn(CPLD0E_PHYS),
+		.length		= 	CPLD0E_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD10_VIRT,
+		.pfn		= __phys_to_pfn(CPLD10_PHYS),
+		.length		= 	CPLD10_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD12_VIRT,
+		.pfn		= __phys_to_pfn(CPLD12_PHYS),
+		.length		= 	CPLD12_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD14_VIRT,
+		.pfn		= __phys_to_pfn(CPLD14_PHYS),
+		.length		= 	CPLD14_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD16_VIRT,
+		.pfn		= __phys_to_pfn(CPLD16_PHYS),
+		.length		= 	CPLD16_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD18_VIRT,
+		.pfn		= __phys_to_pfn(CPLD18_PHYS),
+		.length		= 	CPLD18_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= CPLD1A_VIRT,
+		.pfn		= __phys_to_pfn(CPLD1A_PHYS),
+		.length		= 	CPLD1A_SIZE,
+		.type		= MT_DEVICE
+	},
 	/* This mapping is redundant since the smc driver performs another. */
 /*	{ CPLD00_VIRT,  CPLD00_PHYS,	CPLD00_SIZE,	MT_DEVICE }, */
-	{ CPLD02_VIRT,  CPLD02_PHYS,	CPLD02_SIZE,	MT_DEVICE },
-	{ CPLD06_VIRT,  CPLD06_PHYS,	CPLD06_SIZE,	MT_DEVICE },
-	{ CPLD08_VIRT,	CPLD08_PHYS,	CPLD08_SIZE,	MT_DEVICE },
-	{ CPLD0C_VIRT,	CPLD0C_PHYS,	CPLD0C_SIZE,	MT_DEVICE },
-	{ CPLD0E_VIRT,	CPLD0E_PHYS,	CPLD0E_SIZE,	MT_DEVICE },
-	{ CPLD10_VIRT,	CPLD10_PHYS,	CPLD10_SIZE,	MT_DEVICE },
-	{ CPLD12_VIRT,	CPLD12_PHYS,	CPLD12_SIZE,	MT_DEVICE },
-	{ CPLD14_VIRT,	CPLD14_PHYS,	CPLD14_SIZE,	MT_DEVICE },
-	{ CPLD16_VIRT,	CPLD16_PHYS,	CPLD16_SIZE,	MT_DEVICE },
-	{ CPLD18_VIRT,	CPLD18_PHYS,	CPLD18_SIZE,	MT_DEVICE },
-	{ CPLD1A_VIRT,	CPLD1A_PHYS,	CPLD1A_SIZE,	MT_DEVICE },
 };
 
 void __init
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index df0312b..fd9183f 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -103,8 +103,12 @@
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc innovator1510_io_desc[] __initdata = {
-{ OMAP1510_FPGA_BASE, OMAP1510_FPGA_START, OMAP1510_FPGA_SIZE,
-	MT_DEVICE },
+	{
+		.virtual	= OMAP1510_FPGA_BASE,
+		.pfn		= __phys_to_pfn(OMAP1510_FPGA_START),
+		.length		= OMAP1510_FPGA_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static struct resource innovator1510_smc91x_resources[] = {
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 107c68c..2ba26e2 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -134,8 +134,12 @@
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
-	{H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE,
-	 MT_DEVICE},
+	{
+		.virtual	= H2P2_DBG_FPGA_BASE,
+		.pfn		= __phys_to_pfn(H2P2_DBG_FPGA_START),
+		.length		= H2P2_DBG_FPGA_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init omap_perseus2_map_io(void)
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index eb8261d..79fb865 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -26,27 +26,59 @@
  * default mapping provided here.
  */
 static struct map_desc omap_io_desc[] __initdata = {
- { IO_VIRT,      	IO_PHYS,             IO_SIZE,        	   MT_DEVICE },
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct map_desc omap730_io_desc[] __initdata = {
- { OMAP730_DSP_BASE,    OMAP730_DSP_START,    OMAP730_DSP_SIZE,    MT_DEVICE },
- { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
+	{
+		.virtual	= OMAP730_DSP_BASE,
+		.pfn		= __phys_to_pfn(OMAP730_DSP_START),
+		.length		= OMAP730_DSP_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= OMAP730_DSPREG_BASE,
+		.pfn		= __phys_to_pfn(OMAP730_DSPREG_START),
+		.length		= OMAP730_DSPREG_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 #endif
 
 #ifdef CONFIG_ARCH_OMAP1510
 static struct map_desc omap1510_io_desc[] __initdata = {
- { OMAP1510_DSP_BASE,    OMAP1510_DSP_START,    OMAP1510_DSP_SIZE,    MT_DEVICE },
- { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
+	{
+		.virtual	= OMAP1510_DSP_BASE,
+		.pfn		= __phys_to_pfn(OMAP1510_DSP_START),
+		.length		= OMAP1510_DSP_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= OMAP1510_DSPREG_BASE,
+		.pfn		= __phys_to_pfn(OMAP1510_DSPREG_START),
+		.length		= OMAP1510_DSPREG_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 #endif
 
 #if defined(CONFIG_ARCH_OMAP16XX)
 static struct map_desc omap16xx_io_desc[] __initdata = {
- { OMAP16XX_DSP_BASE,    OMAP16XX_DSP_START,    OMAP16XX_DSP_SIZE,    MT_DEVICE },
- { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
+	{
+		.virtual	= OMAP16XX_DSP_BASE,
+		.pfn		= __phys_to_pfn(OMAP16XX_DSP_START),
+		.length		= OMAP16XX_DSP_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= OMAP16XX_DSPREG_BASE,
+		.pfn		= __phys_to_pfn(OMAP16XX_DSPREG_START),
+		.length		= OMAP16XX_DSPREG_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 #endif
 
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 60c8b9d..656f73b 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -33,6 +33,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/irq.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/corgi.h>
@@ -224,6 +225,22 @@
 };
 
 
+/*
+ * Irda
+ */
+static void corgi_irda_transceiver_mode(struct device *dev, int mode)
+{
+	if (mode & IR_OFF)
+		GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
+	else
+		GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
+}
+
+static struct pxaficp_platform_data corgi_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_OFF,
+	.transceiver_mode = corgi_irda_transceiver_mode,
+};
+
 
 /*
  * USB Device Controller
@@ -269,10 +286,13 @@
 
 	corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
 
+	pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+
  	pxa_set_udc_info(&udc_info);
 	pxa_set_mci_info(&corgi_mci_platform_data);
+	pxa_set_ficp_info(&corgi_ficp_platform_data);
 
 	scoop_num = 1;
 	scoop_devs = &corgi_pcmcia_scoop[0];
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 0ef4282..136c269 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -222,24 +222,22 @@
 	return 0;
 }
 
-static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
+static int corgi_ssp_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		ssp_flush(&corgi_ssp_dev);
-		ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
-	}
+	ssp_flush(&corgi_ssp_dev);
+	ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
+
 	return 0;
 }
 
-static int corgi_ssp_resume(struct device *dev, u32 level)
+static int corgi_ssp_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
-		GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
-		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
-		ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
-		ssp_enable(&corgi_ssp_dev);
-	}
+	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
+	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
+	ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
+	ssp_enable(&corgi_ssp_dev);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 1d767766..9c02893 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -23,6 +23,7 @@
 #include <linux/device.h>
 #include <linux/ioport.h>
 #include <linux/pm.h>
+#include <linux/string.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -34,6 +35,7 @@
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
 #include "generic.h"
@@ -92,14 +94,42 @@
  *         and cache flush area.
  */
 static struct map_desc standard_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xf2000000, 0x40000000, 0x02000000, MT_DEVICE }, /* Devs */
-  { 0xf4000000, 0x44000000, 0x00100000, MT_DEVICE }, /* LCD */
-  { 0xf6000000, 0x48000000, 0x00100000, MT_DEVICE }, /* Mem Ctl */
-  { 0xf8000000, 0x4c000000, 0x00100000, MT_DEVICE }, /* USB host */
-  { 0xfa000000, 0x50000000, 0x00100000, MT_DEVICE }, /* Camera */
-  { 0xfe000000, 0x58000000, 0x00100000, MT_DEVICE }, /* IMem ctl */
-  { 0xff000000, 0x00000000, 0x00100000, MT_DEVICE }  /* UNCACHED_PHYS_0 */
+  	{	/* Devs */
+		.virtual	=  0xf2000000,
+		.pfn		= __phys_to_pfn(0x40000000),
+		.length		= 0x02000000,
+		.type		= MT_DEVICE
+	}, {	/* LCD */
+		.virtual	=  0xf4000000,
+		.pfn		= __phys_to_pfn(0x44000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* Mem Ctl */
+		.virtual	=  0xf6000000,
+		.pfn		= __phys_to_pfn(0x48000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* USB host */
+		.virtual	=  0xf8000000,
+		.pfn		= __phys_to_pfn(0x4c000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* Camera */
+		.virtual	=  0xfa000000,
+		.pfn		= __phys_to_pfn(0x50000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* IMem ctl */
+		.virtual	=  0xfe000000,
+		.pfn		= __phys_to_pfn(0x58000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* UNCACHED_PHYS_0 */
+		.virtual	= 0xff000000,
+		.pfn		= __phys_to_pfn(0x00000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init pxa_map_io(void)
@@ -225,6 +255,10 @@
 	.name		= "pxa2xx-uart",
 	.id		= 2,
 };
+static struct platform_device hwuart_device = {
+	.name		= "pxa2xx-uart",
+	.id		= 3,
+};
 
 static struct resource i2c_resources[] = {
 	{
@@ -265,10 +299,26 @@
 static struct platform_device i2s_device = {
 	.name		= "pxa2xx-i2s",
 	.id		= -1,
-	.resource	= i2c_resources,
+	.resource	= i2s_resources,
 	.num_resources	= ARRAY_SIZE(i2s_resources),
 };
 
+static u64 pxaficp_dmamask = ~(u32)0;
+
+static struct platform_device pxaficp_device = {
+	.name		= "pxa2xx-ir",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &pxaficp_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+};
+
+void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
+{
+	pxaficp_device.dev.platform_data = info;
+}
+
 static struct platform_device *devices[] __initdata = {
 	&pxamci_device,
 	&udc_device,
@@ -276,13 +326,26 @@
 	&ffuart_device,
 	&btuart_device,
 	&stuart_device,
+	&pxaficp_device,
 	&i2c_device,
 	&i2s_device,
 };
 
 static int __init pxa_init(void)
 {
-	return platform_add_devices(devices, ARRAY_SIZE(devices));
+	int cpuid, ret;
+
+	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+	if (ret)
+		return ret;
+
+	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+	cpuid = read_cpuid(CPUID_ID);
+	if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
+	    ((cpuid >> 4) & 0xfff) == 0x290)
+		ret = platform_device_register(&hwuart_device);
+
+	return ret;
 }
 
 subsys_initcall(pxa_init);
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 386e107..01a83ab 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -152,16 +152,17 @@
 }
 
 static struct map_desc idp_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-
-  { IDP_COREVOLT_VIRT,
-    IDP_COREVOLT_PHYS,
-    IDP_COREVOLT_SIZE,
-    MT_DEVICE },
-  { IDP_CPLD_VIRT,
-    IDP_CPLD_PHYS,
-    IDP_CPLD_SIZE,
-    MT_DEVICE }
+  	{
+		.virtual	=  IDP_COREVOLT_VIRT,
+		.pfn		= __phys_to_pfn(IDP_COREVOLT_PHYS),
+		.length		= IDP_COREVOLT_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  IDP_CPLD_VIRT,
+		.pfn		= __phys_to_pfn(IDP_CPLD_PHYS),
+		.length		= IDP_CPLD_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init idp_map_io(void)
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 1f38033..beccf45 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -35,6 +35,7 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
 
@@ -237,16 +238,40 @@
 	.init 		= lubbock_mci_init,
 };
 
+static void lubbock_irda_transceiver_mode(struct device *dev, int mode)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (mode & IR_SIRMODE) {
+		LUB_MISC_WR &= ~(1 << 4);
+	} else if (mode & IR_FIRMODE) {
+		LUB_MISC_WR |= 1 << 4;
+	}
+	local_irq_restore(flags);
+}
+
+static struct pxaficp_platform_data lubbock_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_FIRMODE,
+	.transceiver_mode = lubbock_irda_transceiver_mode,
+};
+
 static void __init lubbock_init(void)
 {
 	pxa_set_udc_info(&udc_info);
 	set_pxa_fb_info(&sharp_lm8v31);
 	pxa_set_mci_info(&lubbock_mci_platform_data);
+	pxa_set_ficp_info(&lubbock_ficp_platform_data);
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 static struct map_desc lubbock_io_desc[] __initdata = {
-  { LUBBOCK_FPGA_VIRT, LUBBOCK_FPGA_PHYS, 0x00100000, MT_DEVICE }, /* CPLD */
+  	{	/* CPLD */
+		.virtual	=  LUBBOCK_FPGA_VIRT,
+		.pfn		= __phys_to_pfn(LUBBOCK_FPGA_PHYS),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init lubbock_map_io(void)
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 85fdb5b..a48c640 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -37,6 +37,7 @@
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
 
 #include "generic.h"
 
@@ -294,6 +295,29 @@
 	.exit		= mainstone_mci_exit,
 };
 
+static void mainstone_irda_transceiver_mode(struct device *dev, int mode)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (mode & IR_SIRMODE) {
+		MST_MSCWR1 &= ~MST_MSCWR1_IRDA_FIR;
+	} else if (mode & IR_FIRMODE) {
+		MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
+	}
+	if (mode & IR_OFF) {
+		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
+	} else {
+		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_FULL;
+	}
+	local_irq_restore(flags);
+}
+
+static struct pxaficp_platform_data mainstone_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_FIRMODE | IR_OFF,
+	.transceiver_mode = mainstone_irda_transceiver_mode,
+};
+
 static void __init mainstone_init(void)
 {
 	/*
@@ -313,11 +337,17 @@
 		set_pxa_fb_info(&toshiba_ltm035a776c);
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);
+	pxa_set_ficp_info(&mainstone_ficp_platform_data);
 }
 
 
 static struct map_desc mainstone_io_desc[] __initdata = {
-  { MST_FPGA_VIRT, MST_FPGA_PHYS, 0x00100000, MT_DEVICE }, /* CPLD */
+  	{	/* CPLD */
+		.virtual	=  MST_FPGA_VIRT,
+		.pfn		= __phys_to_pfn(MST_FPGA_PHYS),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init mainstone_map_io(void)
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index f256388..6d413f6 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -32,6 +32,7 @@
 #include <asm/arch/irq.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/poodle.h>
 #include <asm/arch/pxafb.h>
 
@@ -152,6 +153,24 @@
 
 
 /*
+ * Irda
+ */
+static void poodle_irda_transceiver_mode(struct device *dev, int mode)
+{
+	if (mode & IR_OFF) {
+		GPSR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON);
+	} else {
+		GPCR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON);
+	}
+}
+
+static struct pxaficp_platform_data poodle_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_OFF,
+	.transceiver_mode = poodle_irda_transceiver_mode,
+};
+
+
+/*
  * USB Device Controller
  */
 static void poodle_udc_command(int cmd)
@@ -244,8 +263,10 @@
 
 	set_pxa_fb_info(&poodle_fb_info);
 	pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT);
+	pxa_gpio_mode(POODLE_GPIO_IR_ON | GPIO_OUT);
 	pxa_set_udc_info(&udc_info);
 	pxa_set_mci_info(&poodle_mci_platform_data);
+	pxa_set_ficp_info(&poodle_ficp_platform_data);
 
 	scoop_num = 1;
 	scoop_devs = &poodle_pcmcia_scoop[0];
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 7869c3b..573a575 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -129,7 +129,7 @@
 	case PM_SUSPEND_MEM:
 		/* set resume return address */
 		PSPR = virt_to_phys(pxa_cpu_resume);
-		pxa_cpu_suspend(3);
+		pxa_cpu_suspend(PWRMODE_SLEEP);
 		break;
 	}
 }
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 9a791b0..09a5d59 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -157,7 +157,7 @@
 	case PM_SUSPEND_MEM:
 		/* set resume return address */
 		PSPR = virt_to_phys(pxa_cpu_resume);
-		pxa_cpu_suspend(3);
+		pxa_cpu_suspend(PWRMODE_SLEEP);
 		break;
 	}
 }
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 5786cca..c986268 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -28,7 +28,9 @@
 /*
  * pxa_cpu_suspend()
  *
- * Forces CPU into sleep state
+ * Forces CPU into sleep state.
+ *
+ * r0 = value for PWRMODE M field for desired sleep state
  */
 
 ENTRY(pxa_cpu_suspend)
@@ -53,6 +55,7 @@
 	mov	r10, sp
 	stmfd	sp!, {r3 - r10}
 
+	mov r5, r0				@ save sleep mode
 	@ preserve phys address of stack
 	mov	r0, sp
 	bl	sleep_phys_sp
@@ -66,7 +69,7 @@
 	@ (also workaround for sighting 28071)
 
 	@ prepare value for sleep mode
-	mov	r1, #3				@ sleep mode
+	mov	r1, r5				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index d0ab428..b838842 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -34,6 +34,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/irq.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
@@ -277,6 +278,23 @@
 
 
 /*
+ * Irda
+ */
+static void spitz_irda_transceiver_mode(struct device *dev, int mode)
+{
+	if (mode & IR_OFF)
+		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
+	else
+		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
+}
+
+static struct pxaficp_platform_data spitz_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_OFF,
+	.transceiver_mode = spitz_irda_transceiver_mode,
+};
+
+
+/*
  * Spitz PXA Framebuffer
  */
 static struct pxafb_mach_info spitz_pxafb_info __initdata = {
@@ -326,6 +344,7 @@
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 	pxa_set_mci_info(&spitz_mci_platform_data);
+	pxa_set_ficp_info(&spitz_ficp_platform_data);
 	set_pxa_fb_parent(&spitzssp_device.dev);
 	set_pxa_fb_info(&spitz_pxafb_info);
 }
diff --git a/arch/arm/mach-pxa/standby.S b/arch/arm/mach-pxa/standby.S
index 8a3f27b..6f6dbbd 100644
--- a/arch/arm/mach-pxa/standby.S
+++ b/arch/arm/mach-pxa/standby.S
@@ -21,7 +21,7 @@
 ENTRY(pxa_cpu_standby)
 	ldr	r0, =PSSR
 	mov	r1, #(PSSR_PH | PSSR_STS)
-	mov	r2, #2
+	mov	r2, #PWRMODE_STANDBY
 	mov	r3, #UNCACHED_PHYS_0	@ Read mem context in.
 	ldr	ip, [r3]
 	b	1f
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index e3587ef..5c4ac1c 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -61,9 +61,22 @@
 __tagtable(ATAG_ACORN, parse_tag_acorn);
 
 static struct map_desc rpc_io_desc[] __initdata = {
- { SCREEN_BASE,	SCREEN_START,	2*1048576, MT_DEVICE }, /* VRAM		*/
- { (u32)IO_BASE, IO_START,	IO_SIZE	 , MT_DEVICE }, /* IO space	*/
- { EASI_BASE,	EASI_START,	EASI_SIZE, MT_DEVICE }  /* EASI space	*/
+ 	{	/* VRAM		*/
+		.virtual	=  SCREEN_BASE,
+		.pfn		= __phys_to_pfn(SCREEN_START),
+		.length		= 	2*1048576,
+		.type		= MT_DEVICE
+	}, {	/* IO space	*/
+		.virtual	=  (u32)IO_BASE,
+		.pfn		= __phys_to_pfn(IO_START),
+		.length		= 	IO_SIZE	 ,
+		.type		= MT_DEVICE
+	}, {	/* EASI space	*/
+		.virtual	= EASI_BASE,
+		.pfn		= __phys_to_pfn(EASI_START),
+		.length		= EASI_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init rpc_map_io(void)
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index 478c15c..9cbe5ee 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -21,7 +21,7 @@
 
 /* todo - fix when rmk changes iodescs to use `void __iomem *` */
 
-#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C2410_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
 #define MHZ (1000*1000)
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index 0077937..08bc7d9 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -47,7 +47,7 @@
 static struct resource s3c_usb_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_USBHOST,
-		.end   = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST,
+		.end   = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -77,7 +77,7 @@
 static struct resource s3c_lcd_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_LCD,
-		.end   = S3C2410_PA_LCD + S3C24XX_SZ_LCD,
+		.end   = S3C2410_PA_LCD + S3C24XX_SZ_LCD - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -103,21 +103,25 @@
 
 EXPORT_SYMBOL(s3c_device_lcd);
 
-static struct s3c2410fb_mach_info s3c2410fb_info;
-
-void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info)
+void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
 {
-	memcpy(&s3c2410fb_info,hard_s3c2410fb_info,sizeof(struct s3c2410fb_mach_info));
-	s3c_device_lcd.dev.platform_data = &s3c2410fb_info;
+	struct s3c2410fb_mach_info *npd;
+
+	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+	if (npd) {
+		memcpy(npd, pd, sizeof(*npd));
+		s3c_device_lcd.dev.platform_data = npd;
+	} else {
+		printk(KERN_ERR "no memory for LCD platform data\n");
+	}
 }
-EXPORT_SYMBOL(set_s3c2410fb_info);
 
 /* NAND Controller */
 
 static struct resource s3c_nand_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_NAND,
-		.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND,
+		.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,
 		.flags = IORESOURCE_MEM,
 	}
 };
@@ -136,7 +140,7 @@
 static struct resource s3c_usbgadget_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_USBDEV,
-		.end   = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV,
+		.end   = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -161,7 +165,7 @@
 static struct resource s3c_wdt_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_WATCHDOG,
-		.end   = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG,
+		.end   = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -186,7 +190,7 @@
 static struct resource s3c_i2c_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_IIC,
-		.end   = S3C2410_PA_IIC + S3C24XX_SZ_IIC,
+		.end   = S3C2410_PA_IIC + S3C24XX_SZ_IIC - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -211,7 +215,7 @@
 static struct resource s3c_iis_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_IIS,
-		.end   = S3C2410_PA_IIS + S3C24XX_SZ_IIS,
+		.end   = S3C2410_PA_IIS + S3C24XX_SZ_IIS -1,
 		.flags = IORESOURCE_MEM,
 	}
 };
@@ -265,7 +269,7 @@
 static struct resource s3c_adc_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_ADC,
-		.end   = S3C2410_PA_ADC + S3C24XX_SZ_ADC,
+		.end   = S3C2410_PA_ADC + S3C24XX_SZ_ADC - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -288,7 +292,7 @@
 static struct resource s3c_sdi_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_SDI,
-		.end   = S3C2410_PA_SDI + S3C24XX_SZ_SDI,
+		.end   = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -465,7 +469,7 @@
 static struct resource s3c_camif_resource[] = {
 	[0] = {
 		.start = S3C2440_PA_CAMIF,
-		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF,
+		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index 94f1776..23ea3d5 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -30,6 +30,7 @@
  *	04-Oct-2004  BJD  Added irq filter controls for GPIO
  *	05-Nov-2004  BJD  EXPORT_SYMBOL() added for all code
  *	13-Mar-2005  BJD  Updates for __iomem
+ *	26-Oct-2005  BJD  Added generic configuration types
  */
 
 
@@ -58,6 +59,27 @@
 		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
 	}
 
+	switch (function) {
+	case S3C2410_GPIO_LEAVE:
+		mask = 0;
+		function = 0;
+		break;
+
+	case S3C2410_GPIO_INPUT:
+	case S3C2410_GPIO_OUTPUT:
+	case S3C2410_GPIO_SFN2:
+	case S3C2410_GPIO_SFN3:
+		if (pin < S3C2410_GPIO_BANKB) {
+			function &= 1;
+			function <<= S3C2410_GPIO_OFFSET(pin);
+		} else {
+			function &= 3;
+			function <<= S3C2410_GPIO_OFFSET(pin)*2;
+		}
+	}
+
+	/* modify the specified register wwith IRQs off */
+
 	local_irq_save(flags);
 
 	con  = __raw_readl(base + 0x00);
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 7b51bfd..c1b5c63 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -32,6 +32,7 @@
  *     25-Jul-2005 BJD  Removed ASIX static mappings
  *     27-Jul-2005 BJD  Ensure maximum frequency of i2c bus
  *     20-Sep-2005 BJD  Added static to non-exported items
+ *     26-Oct-2005 BJD  Added FB platform data
 */
 
 #include <linux/kernel.h>
@@ -61,8 +62,10 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-lcd.h>
+
 #include <asm/arch/nand.h>
 #include <asm/arch/iic.h>
+#include <asm/arch/fb.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -399,6 +402,38 @@
 	.max_freq	= 130*1000,
 };
 
+
+static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
+	.width		= 640,
+	.height		= 480,
+
+	.xres		= {
+		.min		= 320,
+		.max		= 1024,
+		.defval		= 640,
+	},
+
+	.yres		= {
+		.min		= 240,
+		.max	        = 600,
+		.defval		= 480,
+	},
+
+	.bpp		= {
+		.min		= 4,
+		.max		= 16,
+		.defval		= 8,
+	},
+
+	.regs		= {
+		.lcdcon1	= 0x00000176,
+		.lcdcon2	= 0x1d77c7c2,
+		.lcdcon3	= 0x013a7f13,
+		.lcdcon4	= 0x00000057,
+		.lcdcon5	= 0x00014b02,
+	}
+};
+
 /* Standard BAST devices */
 
 static struct platform_device *bast_devices[] __initdata = {
@@ -454,6 +489,10 @@
 	usb_simtec_init();
 }
 
+static void __init bast_init(void)
+{
+	s3c24xx_fb_set_platdata(&bast_lcd_info);
+}
 
 MACHINE_START(BAST, "Simtec-BAST")
 	/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
@@ -463,5 +502,6 @@
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= bast_map_io,
 	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= bast_init,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index fb3cb01..7efeaaa 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -25,6 +25,7 @@
  *     14-Jan-2005 BJD  Added clock init
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     20-Sep-2005 BJD  Added static to non-exported items
+ *     26-Oct-2005 BJD  Changed name of fb init call
 */
 
 #include <linux/kernel.h>
@@ -164,7 +165,7 @@
 
 static void __init h1940_init(void)
 {
-	set_s3c2410fb_info(&h1940_lcdcfg);
+	s3c24xx_fb_set_platdata(&h1940_lcdcfg);
 }
 
 MACHINE_START(H1940, "IPAQ-H1940")
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index 722ef46..6950e61 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -19,6 +19,7 @@
  *	10-Mar-2005 LCVR  Replaced S3C2410_VA by S3C24XX_VA
  *	14-Mar-2005 BJD	  void __iomem fixes
  *	20-Sep-2005 BJD   Added static to non-exported items
+ *	26-Oct-2005 BJD   Added framebuffer data
 */
 
 #include <linux/kernel.h>
@@ -41,7 +42,10 @@
 //#include <asm/debug-ll.h>
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
 #include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
 
 #include "s3c2410.h"
 #include "s3c2440.h"
@@ -86,6 +90,70 @@
 	}
 };
 
+/* LCD driver info */
+
+static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
+	.regs	= {
+
+		.lcdcon1	= S3C2410_LCDCON1_TFT16BPP |
+				  S3C2410_LCDCON1_TFT |
+				  S3C2410_LCDCON1_CLKVAL(0x04),
+
+		.lcdcon2	= S3C2410_LCDCON2_VBPD(7) |
+				  S3C2410_LCDCON2_LINEVAL(319) |
+				  S3C2410_LCDCON2_VFPD(6) |
+				  S3C2410_LCDCON2_VSPW(3),
+
+		.lcdcon3	= S3C2410_LCDCON3_HBPD(19) |
+				  S3C2410_LCDCON3_HOZVAL(239) |
+				  S3C2410_LCDCON3_HFPD(7),
+
+		.lcdcon4	= S3C2410_LCDCON4_MVAL(0) |
+				  S3C2410_LCDCON4_HSPW(3),
+
+		.lcdcon5	= S3C2410_LCDCON5_FRM565 |
+				  S3C2410_LCDCON5_INVVLINE |
+				  S3C2410_LCDCON5_INVVFRAME |
+				  S3C2410_LCDCON5_PWREN |
+				  S3C2410_LCDCON5_HWSWP,
+	},
+
+#if 0
+	/* currently setup by downloader */
+	.gpccon		= 0xaa940659,
+	.gpccon_mask	= 0xffffffff,
+	.gpcup		= 0x0000ffff,
+	.gpcup_mask	= 0xffffffff,
+	.gpdcon		= 0xaa84aaa0,
+	.gpdcon_mask	= 0xffffffff,
+	.gpdup		= 0x0000faff,
+	.gpdup_mask	= 0xffffffff,
+#endif
+
+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
+
+	.width		= 240,
+	.height		= 320,
+
+	.xres		= {
+		.min	= 240,
+		.max	= 240,
+		.defval	= 240,
+	},
+
+	.yres		= {
+		.min	= 320,
+		.max	= 320,
+		.defval = 320,
+	},
+
+	.bpp		= {
+		.min	= 16,
+		.max	= 16,
+		.defval = 16,
+	},
+};
+
 static struct platform_device *smdk2440_devices[] __initdata = {
 	&s3c_device_usb,
 	&s3c_device_lcd,
@@ -121,6 +189,8 @@
 	s3c2410_gpio_setpin(S3C2410_GPF6, 0);
 	s3c2410_gpio_setpin(S3C2410_GPF7, 0);
 
+	s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
+
 	s3c2410_pm_init();
 }
 
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 24687f5..75efb5d 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -388,9 +388,17 @@
 };
 
 static struct map_desc assabet_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xf1000000, 0x12000000, 0x00100000, MT_DEVICE }, /* Board Control Register */
-  { 0xf2800000, 0x4b800000, 0x00800000, MT_DEVICE }  /* MQ200 */
+  	{	/* Board Control Register */
+		.virtual	=  0xf1000000,
+		.pfn		= __phys_to_pfn(0x12000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* MQ200 */
+		.virtual	=  0xf2800000,
+		.pfn		= __phys_to_pfn(0x4b800000),
+		.length		= 0x00800000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init assabet_map_io(void)
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index b6169cb..c92cebf 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -254,10 +254,22 @@
 
 
 static struct map_desc badge4_io_desc[] __initdata = {
-  /*  virtual    physical    length    type */
-  {0xf1000000, 0x08000000, 0x00100000, MT_DEVICE },/* SRAM  bank 1 */
-  {0xf2000000, 0x10000000, 0x00100000, MT_DEVICE },/* SRAM  bank 2 */
-  {0xf4000000, 0x48000000, 0x00100000, MT_DEVICE } /* SA-1111      */
+  	{	/* SRAM  bank 1 */
+		.virtual	= 0xf1000000,
+		.pfn		= __phys_to_pfn(0x08000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* SRAM  bank 2 */
+		.virtual	= 0xf2000000,
+		.pfn		= __phys_to_pfn(0x10000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* SA-1111      */
+		.virtual	= 0xf4000000,
+		.pfn		= __phys_to_pfn(0x48000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 9484be7..23cb748 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -100,8 +100,12 @@
 }
 
 static struct map_desc cerf_io_desc[] __initdata = {
-  /* virtual	 physical    length	 type */
-  { 0xf0000000, 0x08000000, 0x00100000, MT_DEVICE }  /* Crystal Ethernet Chip */
+  	{	/* Crystal Ethernet Chip */
+		.virtual	=  0xf0000000,
+		.pfn		= __phys_to_pfn(0x08000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init cerf_map_io(void)
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 6ecab7e..7fd6e29 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -171,9 +171,17 @@
 }
 
 static struct map_desc collie_io_desc[] __initdata = {
-	/* virtual     physical    length      type */
-	{0xe8000000, 0x00000000, 0x02000000, MT_DEVICE},	/* 32M main flash (cs0) */
-	{0xea000000, 0x08000000, 0x02000000, MT_DEVICE},	/* 32M boot flash (cs1) */
+	{	/* 32M main flash (cs0) */
+		.virtual	= 0xe8000000,
+		.pfn		= __phys_to_pfn(0x00000000),
+		.length		= 0x02000000,
+		.type		= MT_DEVICE
+	}, {	/* 32M boot flash (cs1) */
+		.virtual	= 0xea000000,
+		.pfn		= __phys_to_pfn(0x08000000),
+		.length		= 0x02000000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init collie_map_io(void)
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 3f1e358..83eba8b 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -17,12 +17,14 @@
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
+#include <linux/sched.h>	/* just for sched_clock() - funny that */
 
 #include <asm/div64.h>
 #include <asm/hardware.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <asm/mach/flash.h>
 #include <asm/irq.h>
 
 #include "generic.h"
@@ -283,6 +285,7 @@
 void sa11x0_set_flash_data(struct flash_platform_data *flash,
 			   struct resource *res, int nr)
 {
+	flash->name = "sa1100";
 	sa11x0mtd_device.dev.platform_data = flash;
 	sa11x0mtd_device.resource = res;
 	sa11x0mtd_device.num_resources = nr;
@@ -369,11 +372,27 @@
  */
 
 static struct map_desc standard_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xf8000000, 0x80000000, 0x00100000, MT_DEVICE }, /* PCM */
-  { 0xfa000000, 0x90000000, 0x00100000, MT_DEVICE }, /* SCM */
-  { 0xfc000000, 0xa0000000, 0x00100000, MT_DEVICE }, /* MER */
-  { 0xfe000000, 0xb0000000, 0x00200000, MT_DEVICE }  /* LCD + DMA */
+  	{	/* PCM */
+		.virtual	=  0xf8000000,
+		.pfn		= __phys_to_pfn(0x80000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* SCM */
+		.virtual	=  0xfa000000,
+		.pfn		= __phys_to_pfn(0x90000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* MER */
+		.virtual	=  0xfc000000,
+		.pfn		= __phys_to_pfn(0xa0000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* LCD + DMA */
+		.virtual	=  0xfe000000,
+		.pfn		= __phys_to_pfn(0xb0000000),
+		.length		= 0x00200000,
+		.type		= MT_DEVICE
+	},
 };
 
 void __init sa1100_map_io(void)
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index e7aa2681..e8352b7 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -223,10 +223,22 @@
 }
 
 static struct map_desc h3600_io_desc[] __initdata = {
- /* virtual	       physical 	  length      type */
-  { H3600_BANK_2_VIRT, SA1100_CS2_PHYS,   0x02800000, MT_DEVICE }, /* static memory bank 2  CS#2 */
-  { H3600_BANK_4_VIRT, SA1100_CS4_PHYS,   0x00800000, MT_DEVICE }, /* static memory bank 4  CS#4 */
-  { H3600_EGPIO_VIRT,  H3600_EGPIO_PHYS,  0x01000000, MT_DEVICE }, /* EGPIO 0		CS#5 */
+  	{	/* static memory bank 2  CS#2 */
+		.virtual	=  H3600_BANK_2_VIRT,
+		.pfn		= __phys_to_pfn(SA1100_CS2_PHYS),
+		.length		= 0x02800000,
+		.type		= MT_DEVICE
+	}, {	/* static memory bank 4  CS#4 */
+		.virtual	=  H3600_BANK_4_VIRT,
+		.pfn		= __phys_to_pfn(SA1100_CS4_PHYS),
+		.length		= 0x00800000,
+		.type		= MT_DEVICE
+	}, {	/* EGPIO 0		CS#5 */
+		.virtual	=  H3600_EGPIO_VIRT,
+		.pfn		= __phys_to_pfn(H3600_EGPIO_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	}
 };
 
 /*
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index 502d65c..c922e04 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -57,8 +57,12 @@
  */
 
 static struct map_desc hackkit_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xe8000000, 0x00000000, 0x01000000, MT_DEVICE } /* Flash bank 0 */
+	{	/* Flash bank 0 */
+		.virtual	=  0xe8000000,
+		.pfn		= __phys_to_pfn(0x00000000),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	},
 };
 
 static struct sa1100_port_fns hackkit_port_fns __initdata = {
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 2f49711..89af0c8 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -8,6 +8,8 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 
 #include <asm/hardware.h>
 #include <asm/hardware/sa1111.h>
@@ -16,6 +18,7 @@
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
 
@@ -81,10 +84,22 @@
 arch_initcall(jornada720_init);
 
 static struct map_desc jornada720_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xf0000000, 0x48000000, 0x00100000, MT_DEVICE }, /* Epson registers */
-  { 0xf1000000, 0x48200000, 0x00100000, MT_DEVICE }, /* Epson frame buffer */
-  { 0xf4000000, 0x40000000, 0x00100000, MT_DEVICE }  /* SA-1111 */
+	{	/* Epson registers */
+		.virtual	=  0xf0000000,
+		.pfn		= __phys_to_pfn(0x48000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* Epson frame buffer */
+		.virtual	=  0xf1000000,
+		.pfn		= __phys_to_pfn(0x48200000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}, {	/* SA-1111 */
+		.virtual	=  0xf4000000,
+		.pfn		= __phys_to_pfn(0x40000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init jornada720_map_io(void)
@@ -96,6 +111,66 @@
 	sa1100_register_uart(1, 1);
 }
 
+static struct mtd_partition jornada720_partitions[] = {
+	{
+		.name		= "JORNADA720 boot firmware",
+		.size		= 0x00040000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
+	}, {
+		.name		= "JORNADA720 kernel",
+		.size		= 0x000c0000,
+		.offset		= 0x00040000,
+	}, {
+		.name		= "JORNADA720 params",
+		.size		= 0x00040000,
+		.offset		= 0x00100000,
+	}, {
+		.name		= "JORNADA720 initrd",
+		.size		= 0x00100000,
+		.offset		= 0x00140000,
+	}, {
+		.name		= "JORNADA720 root cramfs",
+		.size		= 0x00300000,
+		.offset		= 0x00240000,
+	}, {
+		.name		= "JORNADA720 usr cramfs",
+		.size		= 0x00800000,
+		.offset		= 0x00540000,
+	}, {
+		.name		= "JORNADA720 usr local",
+		.size		= 0,  /* will expand to the end of the flash */
+		.offset		= 0x00d00000,
+	}
+};
+
+static void jornada720_set_vpp(int vpp)
+{
+	if (vpp)
+		PPSR |= 0x80;
+	else
+		PPSR &= ~0x80;
+	PPDR |= 0x80;
+}
+
+static struct flash_platform_data jornada720_flash_data = {
+	.map_name	= "cfi_probe",
+	.set_vpp	= jornada720_set_vpp,
+	.parts		= jornada720_partitions,
+	.nr_parts	= ARRAY_SIZE(jornada720_partitions),
+};
+
+static struct resource jornada720_flash_resource = {
+	.start		= SA1100_CS0_PHYS,
+	.end		= SA1100_CS0_PHYS + SZ_32M - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static void __init jornada720_mach_init(void)
+{
+	sa11x0_set_flash_data(&jornada720_flash_data, &jornada720_flash_resource, 1);
+}
+
 MACHINE_START(JORNADA720, "HP Jornada 720")
 	/* Maintainer: Michael Gernoth <michael@gernoth.net> */
 	.phys_ram	= 0xc0000000,
@@ -105,4 +180,5 @@
 	.map_io		= jornada720_map_io,
 	.init_irq	= sa1100_init_irq,
 	.timer		= &sa1100_timer,
+	.init_machine	= jornada720_mach_init,
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index ed6744d..8c9e3dd 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -31,9 +31,17 @@
 }
 
 static struct map_desc lart_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xe8000000, 0x00000000, 0x00400000, MT_DEVICE }, /* main flash memory */
-  { 0xec000000, 0x08000000, 0x00400000, MT_DEVICE }  /* main flash, alternative location */
+	{	/* main flash memory */
+		.virtual	=  0xe8000000,
+		.pfn		= __phys_to_pfn(0x00000000),
+		.length		= 0x00400000,
+		.type		= MT_DEVICE
+	}, {	/* main flash, alternative location */
+		.virtual	=  0xec000000,
+		.pfn		= __phys_to_pfn(0x08000000),
+		.length		= 0x00400000,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init lart_map_io(void)
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index fc06164..052e4ca 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -178,33 +178,27 @@
 /*
  * LDM power management.
  */
-static int neponset_suspend(struct device *dev, pm_message_t state, u32 level)
+static int neponset_suspend(struct device *dev, pm_message_t state)
 {
 	/*
 	 * Save state.
 	 */
-	if (level == SUSPEND_SAVE_STATE ||
-	    level == SUSPEND_DISABLE ||
-	    level == SUSPEND_POWER_DOWN) {
-		if (!dev->power.saved_state)
-			dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
-		if (!dev->power.saved_state)
-			return -ENOMEM;
+	if (!dev->power.saved_state)
+		dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
+	if (!dev->power.saved_state)
+		return -ENOMEM;
 
-		*(unsigned int *)dev->power.saved_state = NCR_0;
-	}
+	*(unsigned int *)dev->power.saved_state = NCR_0;
 
 	return 0;
 }
 
-static int neponset_resume(struct device *dev, u32 level)
+static int neponset_resume(struct device *dev)
 {
-	if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) {
-		if (dev->power.saved_state) {
-			NCR_0 = *(unsigned int *)dev->power.saved_state;
-			kfree(dev->power.saved_state);
-			dev->power.saved_state = NULL;
-		}
+	if (dev->power.saved_state) {
+		NCR_0 = *(unsigned int *)dev->power.saved_state;
+		kfree(dev->power.saved_state);
+		dev->power.saved_state = NULL;
 	}
 
 	return 0;
@@ -331,9 +325,17 @@
 subsys_initcall(neponset_init);
 
 static struct map_desc neponset_io_desc[] __initdata = {
- /* virtual     physical    length type */
-  { 0xf3000000, 0x10000000, SZ_1M, MT_DEVICE }, /* System Registers */
-  { 0xf4000000, 0x40000000, SZ_1M, MT_DEVICE }  /* SA-1111 */
+	{	/* System Registers */
+		.virtual	=  0xf3000000,
+		.pfn		= __phys_to_pfn(0x10000000),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}, {	/* SA-1111 */
+		.virtual	=  0xf4000000,
+		.pfn		= __phys_to_pfn(0x40000000),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	}
 };
 
 void __init neponset_map_io(void)
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 07f6d5f..cfb6658 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -60,11 +60,17 @@
 EXPORT_SYMBOL(clear_cs3_bit);
 
 static struct map_desc simpad_io_desc[] __initdata = {
-        /* virtual	physical    length	type */
-	/* MQ200 */
-	{ 0xf2800000, 0x4b800000, 0x00800000, MT_DEVICE },
-	/* Paules CS3, write only */
-	{ 0xf1000000, 0x18000000, 0x00100000, MT_DEVICE },
+	{	/* MQ200 */
+		.virtual	=  0xf2800000,
+		.pfn		= __phys_to_pfn(0x4b800000),
+		.length		= 0x00800000,
+		.type		= MT_DEVICE
+	}, {	/* Paules CS3, write only */
+		.virtual	=  0xf1000000,
+		.pfn		= __phys_to_pfn(0x18000000),
+		.length		= 0x00100000,
+		.type		= MT_DEVICE
+	},
 };
 
 
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 946c0d1..2d428b6 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -62,7 +62,12 @@
 extern void shark_init_irq(void);
 
 static struct map_desc shark_io_desc[] __initdata = {
-	{ IO_BASE	, IO_START	, IO_SIZE	, MT_DEVICE }
+	{
+		.virtual	= IO_BASE,
+		.pfn		= __phys_to_pfn(IO_START),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	}
 };
 
 static void __init shark_map_io(void)
diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
index 48025c2..b96a2ea 100644
--- a/arch/arm/mach-versatile/clock.c
+++ b/arch/arm/mach-versatile/clock.c
@@ -13,6 +13,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/string.h>
 
 #include <asm/semaphore.h>
 #include <asm/hardware/clock.h>
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index a30e045..7e4bdd0 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -186,25 +186,82 @@
 }
 
 static struct map_desc versatile_io_desc[] __initdata = {
- { IO_ADDRESS(VERSATILE_SYS_BASE),   VERSATILE_SYS_BASE,   SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_SIC_BASE),   VERSATILE_SIC_BASE,   SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_VIC_BASE),   VERSATILE_VIC_BASE,   SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_SCTL_BASE),  VERSATILE_SCTL_BASE,  SZ_4K * 9,  MT_DEVICE },
+	{
+		.virtual	=  IO_ADDRESS(VERSATILE_SYS_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_SYS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  IO_ADDRESS(VERSATILE_SIC_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_SIC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  IO_ADDRESS(VERSATILE_VIC_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_VIC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  IO_ADDRESS(VERSATILE_SCTL_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_SCTL_BASE),
+		.length		= SZ_4K * 9,
+		.type		= MT_DEVICE
+	},
 #ifdef CONFIG_MACH_VERSATILE_AB
- { IO_ADDRESS(VERSATILE_GPIO0_BASE), VERSATILE_GPIO0_BASE, SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_IB2_BASE),   VERSATILE_IB2_BASE,   SZ_64M,     MT_DEVICE },
+ 	{
+		.virtual	=  IO_ADDRESS(VERSATILE_GPIO0_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_GPIO0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  IO_ADDRESS(VERSATILE_IB2_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_IB2_BASE),
+		.length		= SZ_64M,
+		.type		= MT_DEVICE
+	},
 #endif
 #ifdef CONFIG_DEBUG_LL
- { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K,      MT_DEVICE },
+ 	{
+		.virtual	=  IO_ADDRESS(VERSATILE_UART0_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	},
 #endif
 #ifdef CONFIG_PCI
- { IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
- { VERSATILE_PCI_VIRT_BASE,          VERSATILE_PCI_BASE,   VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
- { VERSATILE_PCI_CFG_VIRT_BASE,      VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
+ 	{
+		.virtual	=  IO_ADDRESS(VERSATILE_PCI_CORE_BASE),
+		.pfn		= __phys_to_pfn(VERSATILE_PCI_CORE_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  VERSATILE_PCI_VIRT_BASE,
+		.pfn		= __phys_to_pfn(VERSATILE_PCI_BASE),
+		.length		= VERSATILE_PCI_BASE_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  VERSATILE_PCI_CFG_VIRT_BASE,
+		.pfn		= __phys_to_pfn(VERSATILE_PCI_CFG_BASE),
+		.length		= VERSATILE_PCI_CFG_BASE_SIZE,
+		.type		= MT_DEVICE
+	},
 #if 0
- { VERSATILE_PCI_VIRT_MEM_BASE0,     VERSATILE_PCI_MEM_BASE0, SZ_16M,  MT_DEVICE },
- { VERSATILE_PCI_VIRT_MEM_BASE1,     VERSATILE_PCI_MEM_BASE1, SZ_16M,  MT_DEVICE },
- { VERSATILE_PCI_VIRT_MEM_BASE2,     VERSATILE_PCI_MEM_BASE2, SZ_16M,  MT_DEVICE },
+ 	{
+		.virtual	=  VERSATILE_PCI_VIRT_MEM_BASE0,
+		.pfn		= __phys_to_pfn(VERSATILE_PCI_MEM_BASE0),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  VERSATILE_PCI_VIRT_MEM_BASE1,
+		.pfn		= __phys_to_pfn(VERSATILE_PCI_MEM_BASE1),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	=  VERSATILE_PCI_VIRT_MEM_BASE2,
+		.pfn		= __phys_to_pfn(VERSATILE_PCI_MEM_BASE2),
+		.length		= SZ_16M,
+		.type		= MT_DEVICE
+	},
 #endif
 #endif
 };
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 26356ce..47b0b76 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -75,7 +75,7 @@
 };
 
 static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, int gfp)
+vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
 {
 	unsigned long addr = head->vm_start, end = head->vm_end - size;
 	unsigned long flags;
@@ -133,7 +133,7 @@
 #endif
 
 static void *
-__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
+__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
 	    pgprot_t prot)
 {
 	struct page *page;
@@ -251,7 +251,7 @@
  * virtual and bus address for that space.
  */
 void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
 	return __dma_alloc(dev, size, handle, gfp,
 			   pgprot_noncached(pgprot_kernel));
@@ -263,7 +263,7 @@
  * dma_alloc_coherent above.
  */
 void *
-dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
 	return __dma_alloc(dev, size, handle, gfp,
 			   pgprot_writecombine(pgprot_kernel));
@@ -397,8 +397,6 @@
 	pte_t *pte;
 	int ret = 0;
 
-	spin_lock(&init_mm.page_table_lock);
-
 	do {
 		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
 		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
@@ -409,7 +407,7 @@
 		}
 		WARN_ON(!pmd_none(*pmd));
 
-		pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+		pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
 		if (!pte) {
 			printk(KERN_ERR "%s: no pte tables\n", __func__);
 			ret = -ENOMEM;
@@ -419,8 +417,6 @@
 		consistent_pte = pte;
 	} while (0);
 
-	spin_unlock(&init_mm.page_table_lock);
-
 	return ret;
 }
 
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 27d0415..269ce69 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -22,9 +22,7 @@
 #endif
 
 #define from_address	(0xffff8000)
-#define from_pgprot	PAGE_KERNEL
 #define to_address	(0xffffc000)
-#define to_pgprot	PAGE_KERNEL
 
 #define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
 
@@ -34,7 +32,7 @@
  * Copy the user page.  No aliasing to deal with so we can just
  * attack the kernel's existing mapping of these pages.
  */
-void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr)
+static void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
 	copy_page(kto, kfrom);
 }
@@ -43,7 +41,7 @@
  * Clear the user page.  No aliasing to deal with so we can just
  * attack the kernel's existing mapping of this page.
  */
-void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
+static void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
 {
 	clear_page(kaddr);
 }
@@ -51,7 +49,7 @@
 /*
  * Copy the page, taking account of the cache colour.
  */
-void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
+static void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
 	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long from, to;
@@ -72,8 +70,8 @@
 	 */
 	spin_lock(&v6_lock);
 
-	set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
-	set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
+	set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, PAGE_KERNEL));
+	set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, PAGE_KERNEL));
 
 	from = from_address + (offset << PAGE_SHIFT);
 	to   = to_address + (offset << PAGE_SHIFT);
@@ -91,7 +89,7 @@
  * so remap the kernel page into the same cache colour as the user
  * page.
  */
-void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
+static void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
 	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long to = to_address + (offset << PAGE_SHIFT);
@@ -112,7 +110,7 @@
 	 */
 	spin_lock(&v6_lock);
 
-	set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
+	set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, PAGE_KERNEL));
 	flush_tlb_kernel_page(to);
 	clear_page((void *)to);
 
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index be4ab3d..7fc1b35 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -26,6 +26,11 @@
 /*
  * We take the easy way out of this problem - we make the
  * PTE uncacheable.  However, we leave the write buffer on.
+ *
+ * Note that the pte lock held when calling update_mmu_cache must also
+ * guard the pte (somewhere else in the same mm) that we modify here.
+ * Therefore those configurations which might call adjust_pte (those
+ * without CONFIG_CPU_CACHE_VIPT) cannot support split page_table_lock.
  */
 static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
 {
@@ -127,7 +132,7 @@
  *  2. If we have multiple shared mappings of the same space in
  *     an object, we need to deal with the cache aliasing issues.
  *
- * Note that the page_table_lock will be held.
+ * Note that the pte lock will be held.
  */
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 {
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index edffa47..fd079ff 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mm/init.c
  *
- *  Copyright (C) 1995-2002 Russell King
+ *  Copyright (C) 1995-2005 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
@@ -86,14 +86,19 @@
 	printk("%d pages swap cached\n", cached);
 }
 
-struct node_info {
-	unsigned int start;
-	unsigned int end;
-	int bootmap_pages;
-};
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+	return pmd_offset(pgd, virt);
+}
 
-#define O_PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-#define O_PFN_UP(x)	(PAGE_ALIGN(x) >> PAGE_SHIFT)
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+	return pmd_off(pgd_offset_k(virt), virt);
+}
+
+#define for_each_nodebank(iter,mi,no)			\
+	for (iter = 0; iter < mi->nr_banks; iter++)	\
+		if (mi->bank[iter].node == no)
 
 /*
  * FIXME: We really want to avoid allocating the bootmap bitmap
@@ -106,15 +111,12 @@
 {
 	unsigned int start_pfn, bank, bootmap_pfn;
 
-	start_pfn   = O_PFN_UP(__pa(&_end));
+	start_pfn   = PAGE_ALIGN(__pa(&_end)) >> PAGE_SHIFT;
 	bootmap_pfn = 0;
 
-	for (bank = 0; bank < mi->nr_banks; bank ++) {
+	for_each_nodebank(bank, mi, node) {
 		unsigned int start, end;
 
-		if (mi->bank[bank].node != node)
-			continue;
-
 		start = mi->bank[bank].start >> PAGE_SHIFT;
 		end   = (mi->bank[bank].size +
 			 mi->bank[bank].start) >> PAGE_SHIFT;
@@ -140,92 +142,6 @@
 	return bootmap_pfn;
 }
 
-/*
- * Scan the memory info structure and pull out:
- *  - the end of memory
- *  - the number of nodes
- *  - the pfn range of each node
- *  - the number of bootmem bitmap pages
- */
-static unsigned int __init
-find_memend_and_nodes(struct meminfo *mi, struct node_info *np)
-{
-	unsigned int i, bootmem_pages = 0, memend_pfn = 0;
-
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		np[i].start = -1U;
-		np[i].end = 0;
-		np[i].bootmap_pages = 0;
-	}
-
-	for (i = 0; i < mi->nr_banks; i++) {
-		unsigned long start, end;
-		int node;
-
-		if (mi->bank[i].size == 0) {
-			/*
-			 * Mark this bank with an invalid node number
-			 */
-			mi->bank[i].node = -1;
-			continue;
-		}
-
-		node = mi->bank[i].node;
-
-		/*
-		 * Make sure we haven't exceeded the maximum number of nodes
-		 * that we have in this configuration.  If we have, we're in
-		 * trouble.  (maybe we ought to limit, instead of bugging?)
-		 */
-		if (node >= MAX_NUMNODES)
-			BUG();
-		node_set_online(node);
-
-		/*
-		 * Get the start and end pfns for this bank
-		 */
-		start = mi->bank[i].start >> PAGE_SHIFT;
-		end   = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
-
-		if (np[node].start > start)
-			np[node].start = start;
-
-		if (np[node].end < end)
-			np[node].end = end;
-
-		if (memend_pfn < end)
-			memend_pfn = end;
-	}
-
-	/*
-	 * Calculate the number of pages we require to
-	 * store the bootmem bitmaps.
-	 */
-	for_each_online_node(i) {
-		if (np[i].end == 0)
-			continue;
-
-		np[i].bootmap_pages = bootmem_bootmap_pages(np[i].end -
-							    np[i].start);
-		bootmem_pages += np[i].bootmap_pages;
-	}
-
-	high_memory = __va(memend_pfn << PAGE_SHIFT);
-
-	/*
-	 * This doesn't seem to be used by the Linux memory
-	 * manager any more.  If we can get rid of it, we
-	 * also get rid of some of the stuff above as well.
-	 *
-	 * Note: max_low_pfn and max_pfn reflect the number
-	 * of _pages_ in the system, not the maximum PFN.
-	 */
-	max_low_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET);
-	max_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET);
-
-	return bootmem_pages;
-}
-
 static int __init check_initrd(struct meminfo *mi)
 {
 	int initrd_node = -2;
@@ -266,9 +182,8 @@
 /*
  * Reserve the various regions of node 0
  */
-static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages)
+static __init void reserve_node_zero(pg_data_t *pgdat)
 {
-	pg_data_t *pgdat = NODE_DATA(0);
 	unsigned long res_size = 0;
 
 	/*
@@ -289,13 +204,6 @@
 			     PTRS_PER_PGD * sizeof(pgd_t));
 
 	/*
-	 * And don't forget to reserve the allocator bitmap,
-	 * which will be freed later.
-	 */
-	reserve_bootmem_node(pgdat, bootmap_pfn << PAGE_SHIFT,
-			     bootmap_pages << PAGE_SHIFT);
-
-	/*
 	 * Hmm... This should go elsewhere, but we really really need to
 	 * stop things allocating the low memory; ideally we need a better
 	 * implementation of GFP_DMA which does not assume that DMA-able
@@ -324,93 +232,264 @@
 		reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size);
 }
 
-/*
- * Register all available RAM in this node with the bootmem allocator.
- */
-static inline void free_bootmem_node_bank(int node, struct meminfo *mi)
+void __init build_mem_type_table(void);
+void __init create_mapping(struct map_desc *md);
+
+static unsigned long __init
+bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
 {
-	pg_data_t *pgdat = NODE_DATA(node);
-	int bank;
+	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
+	unsigned long start_pfn, end_pfn, boot_pfn;
+	unsigned int boot_pages;
+	pg_data_t *pgdat;
+	int i;
 
-	for (bank = 0; bank < mi->nr_banks; bank++)
-		if (mi->bank[bank].node == node)
-			free_bootmem_node(pgdat, mi->bank[bank].start,
-					  mi->bank[bank].size);
-}
-
-/*
- * Initialise the bootmem allocator for all nodes.  This is called
- * early during the architecture specific initialisation.
- */
-static void __init bootmem_init(struct meminfo *mi)
-{
-	struct node_info node_info[MAX_NUMNODES], *np = node_info;
-	unsigned int bootmap_pages, bootmap_pfn, map_pg;
-	int node, initrd_node;
-
-	bootmap_pages = find_memend_and_nodes(mi, np);
-	bootmap_pfn   = find_bootmap_pfn(0, mi, bootmap_pages);
-	initrd_node   = check_initrd(mi);
-
-	map_pg = bootmap_pfn;
+	start_pfn = -1UL;
+	end_pfn = 0;
 
 	/*
-	 * Initialise the bootmem nodes.
-	 *
-	 * What we really want to do is:
-	 *
-	 *   unmap_all_regions_except_kernel();
-	 *   for_each_node_in_reverse_order(node) {
-	 *     map_node(node);
-	 *     allocate_bootmem_map(node);
-	 *     init_bootmem_node(node);
-	 *     free_bootmem_node(node);
-	 *   }
-	 *
-	 * but this is a 2.5-type change.  For now, we just set
-	 * the nodes up in reverse order.
-	 *
-	 * (we could also do with rolling bootmem_init and paging_init
-	 * into one generic "memory_init" type function).
+	 * Calculate the pfn range, and map the memory banks for this node.
 	 */
-	np += num_online_nodes() - 1;
-	for (node = num_online_nodes() - 1; node >= 0; node--, np--) {
-		/*
-		 * If there are no pages in this node, ignore it.
-		 * Note that node 0 must always have some pages.
-		 */
-		if (np->end == 0 || !node_online(node)) {
-			if (node == 0)
-				BUG();
-			continue;
-		}
+	for_each_nodebank(i, mi, node) {
+		unsigned long start, end;
+		struct map_desc map;
 
-		/*
-		 * Initialise the bootmem allocator.
-		 */
-		init_bootmem_node(NODE_DATA(node), map_pg, np->start, np->end);
-		free_bootmem_node_bank(node, mi);
-		map_pg += np->bootmap_pages;
+		start = mi->bank[i].start >> PAGE_SHIFT;
+		end = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
 
-		/*
-		 * If this is node 0, we need to reserve some areas ASAP -
-		 * we may use bootmem on node 0 to setup the other nodes.
-		 */
-		if (node == 0)
-			reserve_node_zero(bootmap_pfn, bootmap_pages);
+		if (start_pfn > start)
+			start_pfn = start;
+		if (end_pfn < end)
+			end_pfn = end;
+
+		map.pfn = __phys_to_pfn(mi->bank[i].start);
+		map.virtual = __phys_to_virt(mi->bank[i].start);
+		map.length = mi->bank[i].size;
+		map.type = MT_MEMORY;
+
+		create_mapping(&map);
 	}
 
+	/*
+	 * If there is no memory in this node, ignore it.
+	 */
+	if (end_pfn == 0)
+		return end_pfn;
+
+	/*
+	 * Allocate the bootmem bitmap page.
+	 */
+	boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+	boot_pfn = find_bootmap_pfn(node, mi, boot_pages);
+
+	/*
+	 * Initialise the bootmem allocator for this node, handing the
+	 * memory banks over to bootmem.
+	 */
+	node_set_online(node);
+	pgdat = NODE_DATA(node);
+	init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn);
+
+	for_each_nodebank(i, mi, node)
+		free_bootmem_node(pgdat, mi->bank[i].start, mi->bank[i].size);
+
+	/*
+	 * Reserve the bootmem bitmap for this node.
+	 */
+	reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
+			     boot_pages << PAGE_SHIFT);
 
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (phys_initrd_size && initrd_node >= 0) {
-		reserve_bootmem_node(NODE_DATA(initrd_node), phys_initrd_start,
+	/*
+	 * If the initrd is in this node, reserve its memory.
+	 */
+	if (node == initrd_node) {
+		reserve_bootmem_node(pgdat, phys_initrd_start,
 				     phys_initrd_size);
 		initrd_start = __phys_to_virt(phys_initrd_start);
 		initrd_end = initrd_start + phys_initrd_size;
 	}
 #endif
 
-	BUG_ON(map_pg != bootmap_pfn + bootmap_pages);
+	/*
+	 * Finally, reserve any node zero regions.
+	 */
+	if (node == 0)
+		reserve_node_zero(pgdat);
+
+	/*
+	 * initialise the zones within this node.
+	 */
+	memset(zone_size, 0, sizeof(zone_size));
+	memset(zhole_size, 0, sizeof(zhole_size));
+
+	/*
+	 * The size of this node has already been determined.  If we need
+	 * to do anything fancy with the allocation of this memory to the
+	 * zones, now is the time to do it.
+	 */
+	zone_size[0] = end_pfn - start_pfn;
+
+	/*
+	 * For each bank in this node, calculate the size of the holes.
+	 *  holes = node_size - sum(bank_sizes_in_node)
+	 */
+	zhole_size[0] = zone_size[0];
+	for_each_nodebank(i, mi, node)
+		zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT;
+
+	/*
+	 * Adjust the sizes according to any special requirements for
+	 * this machine type.
+	 */
+	arch_adjust_zones(node, zone_size, zhole_size);
+
+	free_area_init_node(node, pgdat, zone_size, start_pfn, zhole_size);
+
+	return end_pfn;
+}
+
+static void __init bootmem_init(struct meminfo *mi)
+{
+	unsigned long addr, memend_pfn = 0;
+	int node, initrd_node, i;
+
+	/*
+	 * Invalidate the node number for empty or invalid memory banks
+	 */
+	for (i = 0; i < mi->nr_banks; i++)
+		if (mi->bank[i].size == 0 || mi->bank[i].node >= MAX_NUMNODES)
+			mi->bank[i].node = -1;
+
+	memcpy(&meminfo, mi, sizeof(meminfo));
+
+	/*
+	 * Clear out all the mappings below the kernel image.
+	 */
+	for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+#ifdef CONFIG_XIP_KERNEL
+	/* The XIP kernel is mapped in the module area -- skip over it */
+	addr = ((unsigned long)&_etext + PGDIR_SIZE - 1) & PGDIR_MASK;
+#endif
+	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Clear out all the kernel space mappings, except for the first
+	 * memory bank, up to the end of the vmalloc region.
+	 */
+	for (addr = __phys_to_virt(mi->bank[0].start + mi->bank[0].size);
+	     addr < VMALLOC_END; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Locate which node contains the ramdisk image, if any.
+	 */
+	initrd_node = check_initrd(mi);
+
+	/*
+	 * Run through each node initialising the bootmem allocator.
+	 */
+	for_each_node(node) {
+		unsigned long end_pfn;
+
+		end_pfn = bootmem_init_node(node, initrd_node, mi);
+
+		/*
+		 * Remember the highest memory PFN.
+		 */
+		if (end_pfn > memend_pfn)
+			memend_pfn = end_pfn;
+	}
+
+	high_memory = __va(memend_pfn << PAGE_SHIFT);
+
+	/*
+	 * This doesn't seem to be used by the Linux memory manager any
+	 * more, but is used by ll_rw_block.  If we can get rid of it, we
+	 * also get rid of some of the stuff above as well.
+	 *
+	 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
+	 * the system, not the maximum PFN.
+	 */
+	max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET;
+}
+
+/*
+ * Set up device the mappings.  Since we clear out the page tables for all
+ * mappings above VMALLOC_END, we will remove any debug device mappings.
+ * This means you have to be careful how you debug this function, or any
+ * called function.  (Do it by code inspection!)
+ */
+static void __init devicemaps_init(struct machine_desc *mdesc)
+{
+	struct map_desc map;
+	unsigned long addr;
+	void *vectors;
+
+	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Map the kernel if it is XIP.
+	 * It is always first in the modulearea.
+	 */
+#ifdef CONFIG_XIP_KERNEL
+	map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & PGDIR_MASK);
+	map.virtual = MODULE_START;
+	map.length = ((unsigned long)&_etext - map.virtual + ~PGDIR_MASK) & PGDIR_MASK;
+	map.type = MT_ROM;
+	create_mapping(&map);
+#endif
+
+	/*
+	 * Map the cache flushing regions.
+	 */
+#ifdef FLUSH_BASE
+	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
+	map.virtual = FLUSH_BASE;
+	map.length = PGDIR_SIZE;
+	map.type = MT_CACHECLEAN;
+	create_mapping(&map);
+#endif
+#ifdef FLUSH_BASE_MINICACHE
+	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + PGDIR_SIZE);
+	map.virtual = FLUSH_BASE_MINICACHE;
+	map.length = PGDIR_SIZE;
+	map.type = MT_MINICLEAN;
+	create_mapping(&map);
+#endif
+
+	flush_cache_all();
+	local_flush_tlb_all();
+
+	vectors = alloc_bootmem_low_pages(PAGE_SIZE);
+	BUG_ON(!vectors);
+
+	/*
+	 * Create a mapping for the machine vectors at the high-vectors
+	 * location (0xffff0000).  If we aren't using high-vectors, also
+	 * create a mapping at the low-vectors virtual address.
+	 */
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.virtual = 0xffff0000;
+	map.length = PAGE_SIZE;
+	map.type = MT_HIGH_VECTORS;
+	create_mapping(&map);
+
+	if (!vectors_high()) {
+		map.virtual = 0;
+		map.type = MT_LOW_VECTORS;
+		create_mapping(&map);
+	}
+
+	/*
+	 * Ask the machine support to map in the statically mapped devices.
+	 * After this point, we can start to touch devices again.
+	 */
+	if (mdesc->map_io)
+		mdesc->map_io();
 }
 
 /*
@@ -420,87 +499,17 @@
 void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
 {
 	void *zero_page;
-	int node;
 
+	build_mem_type_table();
 	bootmem_init(mi);
+	devicemaps_init(mdesc);
 
-	memcpy(&meminfo, mi, sizeof(meminfo));
+	top_pmd = pmd_off_k(0xffff0000);
 
 	/*
 	 * allocate the zero page.  Note that we count on this going ok.
 	 */
 	zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
-
-	/*
-	 * initialise the page tables.
-	 */
-	memtable_init(mi);
-	if (mdesc->map_io)
-		mdesc->map_io();
-	local_flush_tlb_all();
-
-	/*
-	 * initialise the zones within each node
-	 */
-	for_each_online_node(node) {
-		unsigned long zone_size[MAX_NR_ZONES];
-		unsigned long zhole_size[MAX_NR_ZONES];
-		struct bootmem_data *bdata;
-		pg_data_t *pgdat;
-		int i;
-
-		/*
-		 * Initialise the zone size information.
-		 */
-		for (i = 0; i < MAX_NR_ZONES; i++) {
-			zone_size[i]  = 0;
-			zhole_size[i] = 0;
-		}
-
-		pgdat = NODE_DATA(node);
-		bdata = pgdat->bdata;
-
-		/*
-		 * The size of this node has already been determined.
-		 * If we need to do anything fancy with the allocation
-		 * of this memory to the zones, now is the time to do
-		 * it.
-		 */
-		zone_size[0] = bdata->node_low_pfn -
-				(bdata->node_boot_start >> PAGE_SHIFT);
-
-		/*
-		 * If this zone has zero size, skip it.
-		 */
-		if (!zone_size[0])
-			continue;
-
-		/*
-		 * For each bank in this node, calculate the size of the
-		 * holes.  holes = node_size - sum(bank_sizes_in_node)
-		 */
-		zhole_size[0] = zone_size[0];
-		for (i = 0; i < mi->nr_banks; i++) {
-			if (mi->bank[i].node != node)
-				continue;
-
-			zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT;
-		}
-
-		/*
-		 * Adjust the sizes according to any special
-		 * requirements for this machine type.
-		 */
-		arch_adjust_zones(node, zone_size, zhole_size);
-
-		free_area_init_node(node, pgdat, zone_size,
-				bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
-	}
-
-	/*
-	 * finish off the bad pages once
-	 * the mem_map is initialised
-	 */
 	memzero(zero_page, PAGE_SIZE);
 	empty_zero_page = virt_to_page(zero_page);
 	flush_dcache_page(empty_zero_page);
@@ -562,10 +571,7 @@
 	 * may not be the case, especially if the user has provided the
 	 * information on the command line.
 	 */
-	for (i = 0; i < mi->nr_banks; i++) {
-		if (mi->bank[i].size == 0 || mi->bank[i].node != node)
-			continue;
-
+	for_each_nodebank(i, mi, node) {
 		bank_start = mi->bank[i].start >> PAGE_SHIFT;
 		if (bank_start < prev_bank_end) {
 			printk(KERN_ERR "MEM: unordered memory banks.  "
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 7110e54..0f128c2 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -26,6 +26,7 @@
 #include <linux/vmalloc.h>
 
 #include <asm/cacheflush.h>
+#include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 
@@ -74,7 +75,7 @@
 
 	pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
@@ -96,7 +97,6 @@
 	phys_addr -= address;
 	dir = pgd_offset(&init_mm, address);
 	BUG_ON(address >= end);
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
 		if (!pmd) {
@@ -113,7 +113,6 @@
 		dir++;
 	} while (address && (address < end));
 
-	spin_unlock(&init_mm.page_table_lock);
 	flush_cache_vmap(start, end);
 	return err;
 }
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index d125a3d..1221fdd 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mm/mm-armv.c
  *
- *  Copyright (C) 1998-2002 Russell King
+ *  Copyright (C) 1998-2005 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
@@ -180,11 +180,6 @@
 
 	if (!vectors_high()) {
 		/*
-		 * This lock is here just to satisfy pmd_alloc and pte_lock
-		 */
-		spin_lock(&mm->page_table_lock);
-
-		/*
 		 * On ARM, first page must always be allocated since it
 		 * contains the machine vectors.
 		 */
@@ -201,23 +196,14 @@
 		set_pte(new_pte, *init_pte);
 		pte_unmap_nested(init_pte);
 		pte_unmap(new_pte);
-
-		spin_unlock(&mm->page_table_lock);
 	}
 
 	return new_pgd;
 
 no_pte:
-	spin_unlock(&mm->page_table_lock);
 	pmd_free(new_pmd);
-	free_pages((unsigned long)new_pgd, 2);
-	return NULL;
-
 no_pmd:
-	spin_unlock(&mm->page_table_lock);
 	free_pages((unsigned long)new_pgd, 2);
-	return NULL;
-
 no_pgd:
 	return NULL;
 }
@@ -243,6 +229,7 @@
 	pte = pmd_page(*pmd);
 	pmd_clear(pmd);
 	dec_page_state(nr_page_table_pages);
+	pte_lock_deinit(pte);
 	pte_free(pte);
 	pmd_free(pmd);
 free:
@@ -305,16 +292,6 @@
 	set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
 }
 
-/*
- * Clear any PGD mapping.  On a two-level page table system,
- * the clearance is done by the middle-level functions (pmd)
- * rather than the top-level (pgd) functions.
- */
-static inline void clear_mapping(unsigned long virt)
-{
-	pmd_clear(pmd_off_k(virt));
-}
-
 struct mem_types {
 	unsigned int	prot_pte;
 	unsigned int	prot_l1;
@@ -373,7 +350,7 @@
 /*
  * Adjust the PMD section entries according to the CPU in use.
  */
-static void __init build_mem_type_table(void)
+void __init build_mem_type_table(void)
 {
 	struct cachepolicy *cp;
 	unsigned int cr = get_cr();
@@ -483,25 +460,25 @@
  * offsets, and we take full advantage of sections and
  * supersections.
  */
-static void __init create_mapping(struct map_desc *md)
+void __init create_mapping(struct map_desc *md)
 {
 	unsigned long virt, length;
 	int prot_sect, prot_l1, domain;
 	pgprot_t prot_pte;
-	long off;
+	unsigned long off = (u32)__pfn_to_phys(md->pfn);
 
 	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
 		printk(KERN_WARNING "BUG: not creating mapping for "
-		       "0x%08lx at 0x%08lx in user region\n",
-		       md->physical, md->virtual);
+		       "0x%016llx at 0x%08lx in user region\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
 		return;
 	}
 
 	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
 	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
-		printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx "
+		printk(KERN_WARNING "BUG: mapping for 0x%016llx at 0x%08lx "
 		       "overlaps vmalloc space\n",
-		       md->physical, md->virtual);
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
 	}
 
 	domain	  = mem_types[md->type].domain;
@@ -509,15 +486,40 @@
 	prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain);
 	prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
 
+	/*
+	 * Catch 36-bit addresses
+	 */
+	if(md->pfn >= 0x100000) {
+		if(domain) {
+			printk(KERN_ERR "MM: invalid domain in supersection "
+				"mapping for 0x%016llx at 0x%08lx\n",
+				__pfn_to_phys((u64)md->pfn), md->virtual);
+			return;
+		}
+		if((md->virtual | md->length | __pfn_to_phys(md->pfn))
+			& ~SUPERSECTION_MASK) {
+			printk(KERN_ERR "MM: cannot create mapping for "
+				"0x%016llx at 0x%08lx invalid alignment\n",
+				__pfn_to_phys((u64)md->pfn), md->virtual);
+			return;
+		}
+
+		/*
+		 * Shift bits [35:32] of address into bits [23:20] of PMD
+		 * (See ARMv6 spec).
+		 */
+		off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
+	}
+
 	virt   = md->virtual;
-	off    = md->physical - virt;
+	off   -= virt;
 	length = md->length;
 
 	if (mem_types[md->type].prot_l1 == 0 &&
 	    (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) {
 		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
 		       "be mapped using pages, ignoring.\n",
-		       md->physical, md->virtual);
+		       __pfn_to_phys(md->pfn), md->virtual);
 		return;
 	}
 
@@ -535,13 +537,22 @@
 	 *	of the actual domain assignments in use.
 	 */
 	if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
-		/* Align to supersection boundary */
-		while ((virt & ~SUPERSECTION_MASK || (virt + off) &
-			~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) {
-			alloc_init_section(virt, virt + off, prot_sect);
+		/*
+		 * Align to supersection boundary if !high pages.
+		 * High pages have already been checked for proper
+		 * alignment above and they will fail the SUPSERSECTION_MASK
+		 * check because of the way the address is encoded into
+		 * offset.
+		 */
+		if (md->pfn <= 0x100000) {
+			while ((virt & ~SUPERSECTION_MASK ||
+			        (virt + off) & ~SUPERSECTION_MASK) &&
+				length >= (PGDIR_SIZE / 2)) {
+				alloc_init_section(virt, virt + off, prot_sect);
 
-			virt   += (PGDIR_SIZE / 2);
-			length -= (PGDIR_SIZE / 2);
+				virt   += (PGDIR_SIZE / 2);
+				length -= (PGDIR_SIZE / 2);
+			}
 		}
 
 		while (length >= SUPERSECTION_SIZE) {
@@ -601,100 +612,6 @@
 	}
 }
 
-extern void _stext, _etext;
-
-/*
- * Setup initial mappings.  We use the page we allocated for zero page to hold
- * the mappings, which will get overwritten by the vectors in traps_init().
- * The mappings must be in virtual address order.
- */
-void __init memtable_init(struct meminfo *mi)
-{
-	struct map_desc *init_maps, *p, *q;
-	unsigned long address = 0;
-	int i;
-
-	build_mem_type_table();
-
-	init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE);
-
-#ifdef CONFIG_XIP_KERNEL
-	p->physical   = CONFIG_XIP_PHYS_ADDR & PMD_MASK;
-	p->virtual    = (unsigned long)&_stext & PMD_MASK;
-	p->length     = ((unsigned long)&_etext - p->virtual + ~PMD_MASK) & PMD_MASK;
-	p->type       = MT_ROM;
-	p ++;
-#endif
-
-	for (i = 0; i < mi->nr_banks; i++) {
-		if (mi->bank[i].size == 0)
-			continue;
-
-		p->physical   = mi->bank[i].start;
-		p->virtual    = __phys_to_virt(p->physical);
-		p->length     = mi->bank[i].size;
-		p->type       = MT_MEMORY;
-		p ++;
-	}
-
-#ifdef FLUSH_BASE
-	p->physical   = FLUSH_BASE_PHYS;
-	p->virtual    = FLUSH_BASE;
-	p->length     = PGDIR_SIZE;
-	p->type       = MT_CACHECLEAN;
-	p ++;
-#endif
-
-#ifdef FLUSH_BASE_MINICACHE
-	p->physical   = FLUSH_BASE_PHYS + PGDIR_SIZE;
-	p->virtual    = FLUSH_BASE_MINICACHE;
-	p->length     = PGDIR_SIZE;
-	p->type       = MT_MINICLEAN;
-	p ++;
-#endif
-
-	/*
-	 * Go through the initial mappings, but clear out any
-	 * pgdir entries that are not in the description.
-	 */
-	q = init_maps;
-	do {
-		if (address < q->virtual || q == p) {
-			clear_mapping(address);
-			address += PGDIR_SIZE;
-		} else {
-			create_mapping(q);
-
-			address = q->virtual + q->length;
-			address = (address + PGDIR_SIZE - 1) & PGDIR_MASK;
-
-			q ++;
-		}
-	} while (address != 0);
-
-	/*
-	 * Create a mapping for the machine vectors at the high-vectors
-	 * location (0xffff0000).  If we aren't using high-vectors, also
-	 * create a mapping at the low-vectors virtual address.
-	 */
-	init_maps->physical   = virt_to_phys(init_maps);
-	init_maps->virtual    = 0xffff0000;
-	init_maps->length     = PAGE_SIZE;
-	init_maps->type       = MT_HIGH_VECTORS;
-	create_mapping(init_maps);
-
-	if (!vectors_high()) {
-		init_maps->virtual = 0;
-		init_maps->type = MT_LOW_VECTORS;
-		create_mapping(init_maps);
-	}
-
-	flush_cache_all();
-	local_flush_tlb_all();
-
-	top_pmd = pmd_off_k(0xffff0000);
-}
-
 /*
  * Create the architecture specific mappings
  */
diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile
index 8ffb523..6a94e54 100644
--- a/arch/arm/oprofile/Makefile
+++ b/arch/arm/oprofile/Makefile
@@ -6,6 +6,6 @@
 		oprofilefs.o oprofile_stats.o \
 		timer_int.o )
 
-oprofile-y				:= $(DRIVER_OBJS) init.o backtrace.o
-oprofile-$(CONFIG_CPU_XSCALE)		+= common.o op_model_xscale.o
+oprofile-y				:= $(DRIVER_OBJS) common.o backtrace.o
+oprofile-$(CONFIG_CPU_XSCALE)		+= op_model_xscale.o
 
diff --git a/arch/arm/oprofile/backtrace.c b/arch/arm/oprofile/backtrace.c
index df35c45..7c22c1261 100644
--- a/arch/arm/oprofile/backtrace.c
+++ b/arch/arm/oprofile/backtrace.c
@@ -49,42 +49,22 @@
 
 static struct frame_tail* user_backtrace(struct frame_tail *tail)
 {
-	struct frame_tail buftail;
+	struct frame_tail buftail[2];
 
-	/* hardware pte might not be valid due to dirty/accessed bit emulation
-	 * so we use copy_from_user and benefit from exception fixups */
-	if (copy_from_user(&buftail, tail, sizeof(struct frame_tail)))
+	/* Also check accessibility of one struct frame_tail beyond */
+	if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
+		return NULL;
+	if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail)))
 		return NULL;
 
-	oprofile_add_trace(buftail.lr);
+	oprofile_add_trace(buftail[0].lr);
 
 	/* frame pointers should strictly progress back up the stack
 	 * (towards higher addresses) */
-	if (tail >= buftail.fp)
+	if (tail >= buftail[0].fp)
 		return NULL;
 
-	return buftail.fp-1;
-}
-
-/* Compare two addresses and see if they're on the same page */
-#define CMP_ADDR_EQUAL(x,y,offset) ((((unsigned long) x) >> PAGE_SHIFT) \
-	== ((((unsigned long) y) + offset) >> PAGE_SHIFT))
-
-/* check that the page(s) containing the frame tail are present */
-static int pages_present(struct frame_tail *tail)
-{
-	struct mm_struct * mm = current->mm;
-
-	if (!check_user_page_readable(mm, (unsigned long)tail))
-		return 0;
-
-	if (CMP_ADDR_EQUAL(tail, tail, 8))
-		return 1;
-
-	if (!check_user_page_readable(mm, ((unsigned long)tail) + 8))
-		return 0;
-
-	return 1;
+	return buftail[0].fp-1;
 }
 
 /*
@@ -118,7 +98,6 @@
 void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
 	struct frame_tail *tail;
-	unsigned long last_address = 0;
 
 	tail = ((struct frame_tail *) regs->ARM_fp) - 1;
 
@@ -132,13 +111,6 @@
 		return;
 	}
 
-	while (depth-- && tail && !((unsigned long) tail & 3)) {
-		if ((!CMP_ADDR_EQUAL(last_address, tail, 0)
-			|| !CMP_ADDR_EQUAL(last_address, tail, 8))
-				&& !pages_present(tail))
-			return;
-		last_address = (unsigned long) tail;
+	while (depth-- && tail && !((unsigned long) tail & 3))
 		tail = user_backtrace(tail);
-	}
 }
-
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index e57dde8..1415930 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -10,40 +10,94 @@
 #include <linux/init.h>
 #include <linux/oprofile.h>
 #include <linux/errno.h>
-#include <asm/semaphore.h>
 #include <linux/sysdev.h>
+#include <asm/semaphore.h>
 
 #include "op_counter.h"
 #include "op_arm_model.h"
 
-static struct op_arm_model_spec *pmu_model;
-static int pmu_enabled;
-static struct semaphore pmu_sem;
+static struct op_arm_model_spec *op_arm_model;
+static int op_arm_enabled;
+static struct semaphore op_arm_sem;
 
-static int pmu_start(void);
-static int pmu_setup(void);
-static void pmu_stop(void);
-static int pmu_create_files(struct super_block *, struct dentry *);
+struct op_counter_config counter_config[OP_MAX_COUNTER];
 
-#ifdef CONFIG_PM
-static int pmu_suspend(struct sys_device *dev, pm_message_t state)
+static int op_arm_create_files(struct super_block *sb, struct dentry *root)
 {
-	if (pmu_enabled)
-		pmu_stop();
+	unsigned int i;
+
+	for (i = 0; i < op_arm_model->num_counters; i++) {
+		struct dentry *dir;
+		char buf[2];
+
+		snprintf(buf, sizeof buf, "%d", i);
+		dir = oprofilefs_mkdir(sb, root, buf);
+		oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
+		oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
+		oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
+		oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
+		oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
+		oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+	}
+
 	return 0;
 }
 
-static int pmu_resume(struct sys_device *dev)
+static int op_arm_setup(void)
 {
-	if (pmu_enabled)
-		pmu_start();
+	int ret;
+
+	spin_lock(&oprofilefs_lock);
+	ret = op_arm_model->setup_ctrs();
+	spin_unlock(&oprofilefs_lock);
+	return ret;
+}
+
+static int op_arm_start(void)
+{
+	int ret = -EBUSY;
+
+	down(&op_arm_sem);
+	if (!op_arm_enabled) {
+		ret = op_arm_model->start();
+		op_arm_enabled = !ret;
+	}
+	up(&op_arm_sem);
+	return ret;
+}
+
+static void op_arm_stop(void)
+{
+	down(&op_arm_sem);
+	if (op_arm_enabled)
+		op_arm_model->stop();
+	op_arm_enabled = 0;
+	up(&op_arm_sem);
+}
+
+#ifdef CONFIG_PM
+static int op_arm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	down(&op_arm_sem);
+	if (op_arm_enabled)
+		op_arm_model->stop();
+	up(&op_arm_sem);
+	return 0;
+}
+
+static int op_arm_resume(struct sys_device *dev)
+{
+	down(&op_arm_sem);
+	if (op_arm_enabled && op_arm_model->start())
+		op_arm_enabled = 0;
+	up(&op_arm_sem);
 	return 0;
 }
 
 static struct sysdev_class oprofile_sysclass = {
 	set_kset_name("oprofile"),
-	.resume		= pmu_resume,
-	.suspend	= pmu_suspend,
+	.resume		= op_arm_resume,
+	.suspend	= op_arm_suspend,
 };
 
 static struct sys_device device_oprofile = {
@@ -71,86 +125,41 @@
 #define exit_driverfs() do { } while (0)
 #endif /* CONFIG_PM */
 
-struct op_counter_config counter_config[OP_MAX_COUNTER];
-
-static int pmu_create_files(struct super_block *sb, struct dentry *root)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
-	unsigned int i;
+	struct op_arm_model_spec *spec = NULL;
+	int ret = -ENODEV;
 
-	for (i = 0; i < pmu_model->num_counters; i++) {
-		struct dentry *dir;
-		char buf[2];
+#ifdef CONFIG_CPU_XSCALE
+	spec = &op_xscale_spec;
+#endif
 
-		snprintf(buf, sizeof buf, "%d", i);
-		dir = oprofilefs_mkdir(sb, root, buf);
-		oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
-		oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
-		oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
-		oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
-		oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
-		oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+	if (spec) {
+		init_MUTEX(&op_arm_sem);
+
+		if (spec->init() < 0)
+			return -ENODEV;
+
+		op_arm_model = spec;
+		init_driverfs();
+		ops->create_files = op_arm_create_files;
+		ops->setup = op_arm_setup;
+		ops->shutdown = op_arm_stop;
+		ops->start = op_arm_start;
+		ops->stop = op_arm_stop;
+		ops->cpu_type = op_arm_model->name;
+		ops->backtrace = arm_backtrace;
+		printk(KERN_INFO "oprofile: using %s\n", spec->name);
 	}
 
-	return 0;
-}
-
-static int pmu_setup(void)
-{
-	int ret;
-
-	spin_lock(&oprofilefs_lock);
-	ret = pmu_model->setup_ctrs();
-	spin_unlock(&oprofilefs_lock);
 	return ret;
 }
 
-static int pmu_start(void)
+void oprofile_arch_exit(void)
 {
-	int ret = -EBUSY;
-
-	down(&pmu_sem);
-	if (!pmu_enabled) {
-		ret = pmu_model->start();
-		pmu_enabled = !ret;
-	}
-	up(&pmu_sem);
-	return ret;
-}
-
-static void pmu_stop(void)
-{
-	down(&pmu_sem);
-	if (pmu_enabled)
-		pmu_model->stop();
-	pmu_enabled = 0;
-	up(&pmu_sem);
-}
-
-int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec)
-{
-	init_MUTEX(&pmu_sem);
-
-	if (spec->init() < 0)
-		return -ENODEV;
-
-	pmu_model = spec;
-	init_driverfs();
-	ops->create_files = pmu_create_files;
-	ops->setup = pmu_setup;
-	ops->shutdown = pmu_stop;
-	ops->start = pmu_start;
-	ops->stop = pmu_stop;
-	ops->cpu_type = pmu_model->name;
-	printk(KERN_INFO "oprofile: using %s PMU\n", spec->name);
-
-	return 0;
-}
-
-void pmu_exit(void)
-{
-	if (pmu_model) {
+	if (op_arm_model) {
 		exit_driverfs();
-		pmu_model = NULL;
+		op_arm_model = NULL;
 	}
 }
 
diff --git a/arch/arm/oprofile/init.c b/arch/arm/oprofile/init.c
deleted file mode 100644
index d315a3a..0000000
--- a/arch/arm/oprofile/init.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * @file init.c
- *
- * @remark Copyright 2004 Oprofile Authors
- * @remark Read the file COPYING
- *
- * @author Zwane Mwaikambo
- */
-
-#include <linux/oprofile.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include "op_arm_model.h"
-
-int __init oprofile_arch_init(struct oprofile_operations *ops)
-{
-	int ret = -ENODEV;
-
-#ifdef CONFIG_CPU_XSCALE
-	ret = pmu_init(ops, &op_xscale_spec);
-#endif
-
-	ops->backtrace = arm_backtrace;
-
-	return ret;
-}
-
-void oprofile_arch_exit(void)
-{
-#ifdef CONFIG_CPU_XSCALE
-	pmu_exit();
-#endif
-}
diff --git a/arch/arm/oprofile/op_arm_model.h b/arch/arm/oprofile/op_arm_model.h
index 2148d07..38c6ad1 100644
--- a/arch/arm/oprofile/op_arm_model.h
+++ b/arch/arm/oprofile/op_arm_model.h
@@ -26,6 +26,6 @@
 
 extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);
 
-extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
-extern void pmu_exit(void);
+extern int __init op_arm_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
+extern void op_arm_exit(void);
 #endif /* OP_ARM_MODEL_H */
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 52a58b2..a020fe1 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -13,6 +13,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/string.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 7719a40..7ad69f1 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -59,7 +59,11 @@
 }
 
 static struct map_desc omap_sram_io_desc[] __initdata = {
-	{ OMAP1_SRAM_BASE, OMAP1_SRAM_START, 0, MT_DEVICE }
+	{	/* .length gets filled in at runtime */
+		.virtual	= OMAP1_SRAM_BASE,
+		.pfn		= __phys_to_pfn(OMAP1_SRAM_START),
+		.type		= MT_DEVICE
+	}
 };
 
 /*
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 8a52124..cf7e977 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -665,7 +665,7 @@
 	return ret;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret;
diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
index e66aedd..3355253 100644
--- a/arch/arm26/kernel/time.c
+++ b/arch/arm26/kernel/time.c
@@ -34,10 +34,6 @@
 #include <asm/irq.h>
 #include <asm/ioc.h>
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 extern unsigned long wall_jiffies;
 
 /* this needs a better home */
diff --git a/arch/arm26/mm/memc.c b/arch/arm26/mm/memc.c
index 8e8a2bb2..34def63 100644
--- a/arch/arm26/mm/memc.c
+++ b/arch/arm26/mm/memc.c
@@ -79,12 +79,6 @@
 		goto no_pgd;
 
 	/*
-	 * This lock is here just to satisfy pmd_alloc and pte_lock
-         * FIXME: I bet we could avoid taking it pretty much altogether
-	 */
-	spin_lock(&mm->page_table_lock);
-
-	/*
 	 * On ARM, first page must always be allocated since it contains
 	 * the machine vectors.
 	 */
@@ -92,7 +86,7 @@
 	if (!new_pmd)
 		goto no_pmd;
 
-	new_pte = pte_alloc_kernel(mm, new_pmd, 0);
+	new_pte = pte_alloc_map(mm, new_pmd, 0);
 	if (!new_pte)
 		goto no_pte;
 
@@ -101,6 +95,7 @@
 	init_pte = pte_offset(init_pmd, 0);
 
 	set_pte(new_pte, *init_pte);
+	pte_unmap(new_pte);
 
 	/*
 	 * the page table entries are zeroed
@@ -112,23 +107,14 @@
 	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
 		(PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
 
-	spin_unlock(&mm->page_table_lock);
-
 	/* update MEMC tables */
 	cpu_memc_update_all(new_pgd);
 	return new_pgd;
 
 no_pte:
-	spin_unlock(&mm->page_table_lock);
 	pmd_free(new_pmd);
-	free_pgd_slow(new_pgd);
-	return NULL;
-
 no_pmd:
-	spin_unlock(&mm->page_table_lock);
 	free_pgd_slow(new_pgd);
-	return NULL;
-
 no_pgd:
 	return NULL;
 }
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index 11ab383..56b038c 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -140,6 +140,7 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/concat.h>
 #include <linux/mtd/map.h>
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 78ed52b..b679f98 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/concat.h>
 #include <linux/mtd/map.h>
diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c
index 8233406..b08a28b 100644
--- a/arch/cris/arch-v32/mm/tlb.c
+++ b/arch/cris/arch-v32/mm/tlb.c
@@ -175,6 +175,8 @@
 	return 0;
 }
 
+static DEFINE_SPINLOCK(mmu_context_lock);
+
 /* Called in schedule() just before actually doing the switch_to. */
 void
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
@@ -183,10 +185,10 @@
 	int cpu = smp_processor_id();
 
 	/* Make sure there is a MMU context. */
-	spin_lock(&next->page_table_lock);
+	spin_lock(&mmu_context_lock);
 	get_mmu_context(next);
 	cpu_set(cpu, next->cpu_vm_mask);
-	spin_unlock(&next->page_table_lock);
+	spin_unlock(&mmu_context_lock);
 
 	/*
 	 * Remember the pgd for the fault handlers. Keep a seperate copy of it
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index a2d99b4..66ba889 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -31,10 +31,7 @@
 #include <linux/timex.h>
 #include <linux/init.h>
 #include <linux/profile.h>
-
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
+#include <linux/sched.h>	/* just for sched_clock() - funny that */
 
 int have_rtc;  /* used to remember if we have an RTC or not */;
 
diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c
index ebba11e..a92ac98 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -52,7 +52,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, prot);
@@ -74,7 +74,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pud_t *pud;
 		pmd_t *pmd;
@@ -94,7 +93,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return error;
 }
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index cbe03cb..cb335a1 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -106,7 +106,7 @@
 	child->thread.frame0->__status |= REG__STATUS_STEP;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	unsigned long tmp;
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 8d6558b..2e97412 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -34,9 +34,6 @@
 
 extern unsigned long wall_jiffies;
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-EXPORT_SYMBOL(jiffies_64);
-
 unsigned long __nongprelbss __clkin_clock_speed_HZ;
 unsigned long __nongprelbss __ext_bus_clock_speed_HZ;
 unsigned long __nongprelbss __res_bus_clock_speed_HZ;
@@ -221,6 +218,7 @@
 	clock_was_set();
 	return 0;
 }
+EXPORT_SYMBOL(do_settimeofday);
 
 /*
  * Scheduler clock - returns current time in nanosec units.
diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c
index 819895c..2082a96 100644
--- a/arch/frv/mb93090-mb00/pci-dma-nommu.c
+++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c
@@ -33,7 +33,7 @@
 static DEFINE_SPINLOCK(dma_alloc_lock);
 static LIST_HEAD(dma_alloc_list);
 
-void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
 {
 	struct dma_alloc_record *new;
 	struct list_head *this = &dma_alloc_list;
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 27eb120..86fbdad 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -17,7 +17,7 @@
 #include <linux/highmem.h>
 #include <asm/io.h>
 
-void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, int gfp)
+void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret;
 
diff --git a/arch/frv/mm/dma-alloc.c b/arch/frv/mm/dma-alloc.c
index 4b38d45..342823a 100644
--- a/arch/frv/mm/dma-alloc.c
+++ b/arch/frv/mm/dma-alloc.c
@@ -55,21 +55,18 @@
 	pte_t *pte;
 	int err = -ENOMEM;
 
-	spin_lock(&init_mm.page_table_lock);
-
 	/* Use upper 10 bits of VA to index the first level map */
 	pge = pgd_offset_k(va);
 	pue = pud_offset(pge, va);
 	pme = pmd_offset(pue, va);
 
 	/* Use middle 10 bits of VA to index the second-level map */
-	pte = pte_alloc_kernel(&init_mm, pme, va);
+	pte = pte_alloc_kernel(pme, va);
 	if (pte != 0) {
 		err = 0;
 		set_pte(pte, mk_pte_phys(pa & PAGE_MASK, prot));
 	}
 
-	spin_unlock(&init_mm.page_table_lock);
 	return err;
 }
 
@@ -81,7 +78,7 @@
  * portions of the kernel with single large page TLB entries, and
  * still get unique uncached pages for consistent DMA.
  */
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
 {
 	struct vm_struct *area;
 	unsigned long page, va, pa;
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 4eaec0f..2c67dfe 100644
--- a/arch/frv/mm/pgalloc.c
+++ b/arch/frv/mm/pgalloc.c
@@ -87,14 +87,14 @@
 	if (pgd_list)
 		pgd_list->private = (unsigned long) &page->index;
 	pgd_list = page;
-	page->private = (unsigned long) &pgd_list;
+	set_page_private(page, (unsigned long)&pgd_list);
 }
 
 static inline void pgd_list_del(pgd_t *pgd)
 {
 	struct page *next, **pprev, *page = virt_to_page(pgd);
 	next = (struct page *) page->index;
-	pprev = (struct page **) page->private;
+	pprev = (struct page **)page_private(page);
 	*pprev = next;
 	if (next)
 		next->private = (unsigned long) pprev;
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 05c15e8..a569fe4 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -57,7 +57,7 @@
 	h8300_disable_trace(child);
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret;
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index af8c5d2..688a510 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -32,10 +32,6 @@
 
 #define	TICK_SIZE (tick_nsec / 1000)
 
-u64 jiffies_64;
-
-EXPORT_SYMBOL(jiffies_64);
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index d2703cd..5383e5e 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -5,7 +5,7 @@
 
 mainmenu "Linux Kernel Configuration"
 
-config X86
+config X86_32
 	bool
 	default y
 	help
@@ -18,6 +18,10 @@
 	bool
 	default y
 
+config X86
+	bool
+	default y
+
 config MMU
 	bool
 	default y
@@ -151,304 +155,7 @@
 	default y
 	depends on SMP && X86_ES7000 && MPENTIUMIII
 
-if !X86_ELAN
-
-choice
-	prompt "Processor family"
-	default M686
-
-config M386
-	bool "386"
-	---help---
-	  This is the processor type of your CPU. This information is used for
-	  optimizing purposes. In order to compile a kernel that can run on
-	  all x86 CPU types (albeit not optimally fast), you can specify
-	  "386" here.
-
-	  The kernel will not necessarily run on earlier architectures than
-	  the one you have chosen, e.g. a Pentium optimized kernel will run on
-	  a PPro, but not necessarily on a i486.
-
-	  Here are the settings recommended for greatest speed:
-	  - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
-	  486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
-	  will run on a 386 class machine.
-	  - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
-	  SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
-	  - "586" for generic Pentium CPUs lacking the TSC
-	  (time stamp counter) register.
-	  - "Pentium-Classic" for the Intel Pentium.
-	  - "Pentium-MMX" for the Intel Pentium MMX.
-	  - "Pentium-Pro" for the Intel Pentium Pro.
-	  - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron.
-	  - "Pentium-III" for the Intel Pentium III or Coppermine Celeron.
-	  - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron.
-	  - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
-	  - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
-	  - "Crusoe" for the Transmeta Crusoe series.
-	  - "Efficeon" for the Transmeta Efficeon series.
-	  - "Winchip-C6" for original IDT Winchip.
-	  - "Winchip-2" for IDT Winchip 2.
-	  - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
-	  - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
-	  - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
-	  - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
-
-	  If you don't know what to do, choose "386".
-
-config M486
-	bool "486"
-	help
-	  Select this for a 486 series processor, either Intel or one of the
-	  compatible processors from AMD, Cyrix, IBM, or Intel.  Includes DX,
-	  DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or
-	  U5S.
-
-config M586
-	bool "586/K5/5x86/6x86/6x86MX"
-	help
-	  Select this for an 586 or 686 series processor such as the AMD K5,
-	  the Cyrix 5x86, 6x86 and 6x86MX.  This choice does not
-	  assume the RDTSC (Read Time Stamp Counter) instruction.
-
-config M586TSC
-	bool "Pentium-Classic"
-	help
-	  Select this for a Pentium Classic processor with the RDTSC (Read
-	  Time Stamp Counter) instruction for benchmarking.
-
-config M586MMX
-	bool "Pentium-MMX"
-	help
-	  Select this for a Pentium with the MMX graphics/multimedia
-	  extended instructions.
-
-config M686
-	bool "Pentium-Pro"
-	help
-	  Select this for Intel Pentium Pro chips.  This enables the use of
-	  Pentium Pro extended instructions, and disables the init-time guard
-	  against the f00f bug found in earlier Pentiums.
-
-config MPENTIUMII
-	bool "Pentium-II/Celeron(pre-Coppermine)"
-	help
-	  Select this for Intel chips based on the Pentium-II and
-	  pre-Coppermine Celeron core.  This option enables an unaligned
-	  copy optimization, compiles the kernel with optimization flags
-	  tailored for the chip, and applies any applicable Pentium Pro
-	  optimizations.
-
-config MPENTIUMIII
-	bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon"
-	help
-	  Select this for Intel chips based on the Pentium-III and
-	  Celeron-Coppermine core.  This option enables use of some
-	  extended prefetch instructions in addition to the Pentium II
-	  extensions.
-
-config MPENTIUMM
-	bool "Pentium M"
-	help
-	  Select this for Intel Pentium M (not Pentium-4 M)
-	  notebook chips.
-
-config MPENTIUM4
-	bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon"
-	help
-	  Select this for Intel Pentium 4 chips.  This includes the
-	  Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
-	  (not Pentium M) chips.  This option enables compile flags
-	  optimized for the chip, uses the correct cache shift, and
-	  applies any applicable Pentium III optimizations.
-
-config MK6
-	bool "K6/K6-II/K6-III"
-	help
-	  Select this for an AMD K6-family processor.  Enables use of
-	  some extended instructions, and passes appropriate optimization
-	  flags to GCC.
-
-config MK7
-	bool "Athlon/Duron/K7"
-	help
-	  Select this for an AMD Athlon K7-family processor.  Enables use of
-	  some extended instructions, and passes appropriate optimization
-	  flags to GCC.
-
-config MK8
-	bool "Opteron/Athlon64/Hammer/K8"
-	help
-	  Select this for an AMD Opteron or Athlon64 Hammer-family processor.  Enables
-	  use of some extended instructions, and passes appropriate optimization
-	  flags to GCC.
-
-config MCRUSOE
-	bool "Crusoe"
-	help
-	  Select this for a Transmeta Crusoe processor.  Treats the processor
-	  like a 586 with TSC, and sets some GCC optimization flags (like a
-	  Pentium Pro with no alignment requirements).
-
-config MEFFICEON
-	bool "Efficeon"
-	help
-	  Select this for a Transmeta Efficeon processor.
-
-config MWINCHIPC6
-	bool "Winchip-C6"
-	help
-	  Select this for an IDT Winchip C6 chip.  Linux and GCC
-	  treat this chip as a 586TSC with some extended instructions
-	  and alignment requirements.
-
-config MWINCHIP2
-	bool "Winchip-2"
-	help
-	  Select this for an IDT Winchip-2.  Linux and GCC
-	  treat this chip as a 586TSC with some extended instructions
-	  and alignment requirements.
-
-config MWINCHIP3D
-	bool "Winchip-2A/Winchip-3"
-	help
-	  Select this for an IDT Winchip-2A or 3.  Linux and GCC
-	  treat this chip as a 586TSC with some extended instructions
-	  and alignment reqirements.  Also enable out of order memory
-	  stores for this CPU, which can increase performance of some
-	  operations.
-
-config MGEODEGX1
-	bool "GeodeGX1"
-	help
-	  Select this for a Geode GX1 (Cyrix MediaGX) chip.
-
-config MCYRIXIII
-	bool "CyrixIII/VIA-C3"
-	help
-	  Select this for a Cyrix III or C3 chip.  Presently Linux and GCC
-	  treat this chip as a generic 586. Whilst the CPU is 686 class,
-	  it lacks the cmov extension which gcc assumes is present when
-	  generating 686 code.
-	  Note that Nehemiah (Model 9) and above will not boot with this
-	  kernel due to them lacking the 3DNow! instructions used in earlier
-	  incarnations of the CPU.
-
-config MVIAC3_2
-	bool "VIA C3-2 (Nehemiah)"
-	help
-	  Select this for a VIA C3 "Nehemiah". Selecting this enables usage
-	  of SSE and tells gcc to treat the CPU as a 686.
-	  Note, this kernel will not boot on older (pre model 9) C3s.
-
-endchoice
-
-config X86_GENERIC
-       bool "Generic x86 support"
-       help
-	  Instead of just including optimizations for the selected
-	  x86 variant (e.g. PII, Crusoe or Athlon), include some more
-	  generic optimizations as well. This will make the kernel
-	  perform better on x86 CPUs other than that selected.
-
-	  This is really intended for distributors who need more
-	  generic optimizations.
-
-endif
-
-#
-# Define implied options from the CPU selection here
-#
-config X86_CMPXCHG
-	bool
-	depends on !M386
-	default y
-
-config X86_XADD
-	bool
-	depends on !M386
-	default y
-
-config X86_L1_CACHE_SHIFT
-	int
-	default "7" if MPENTIUM4 || X86_GENERIC
-	default "4" if X86_ELAN || M486 || M386
-	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
-	default "6" if MK7 || MK8 || MPENTIUMM
-
-config RWSEM_GENERIC_SPINLOCK
-	bool
-	depends on M386
-	default y
-
-config RWSEM_XCHGADD_ALGORITHM
-	bool
-	depends on !M386
-	default y
-
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
-config X86_PPRO_FENCE
-	bool
-	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1
-	default y
-
-config X86_F00F_BUG
-	bool
-	depends on M586MMX || M586TSC || M586 || M486 || M386
-	default y
-
-config X86_WP_WORKS_OK
-	bool
-	depends on !M386
-	default y
-
-config X86_INVLPG
-	bool
-	depends on !M386
-	default y
-
-config X86_BSWAP
-	bool
-	depends on !M386
-	default y
-
-config X86_POPAD_OK
-	bool
-	depends on !M386
-	default y
-
-config X86_ALIGNMENT_16
-	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
-	default y
-
-config X86_GOOD_APIC
-	bool
-	depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON
-	default y
-
-config X86_INTEL_USERCOPY
-	bool
-	depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON
-	default y
-
-config X86_USE_PPRO_CHECKSUM
-	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
-	default y
-
-config X86_USE_3DNOW
-	bool
-	depends on MCYRIXIII || MK7
-	default y
-
-config X86_OOSTORE
-	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
-	default y
+source "arch/i386/Kconfig.cpu"
 
 config HPET_TIMER
 	bool "HPET Timer Support"
@@ -561,11 +268,6 @@
 	depends on X86_VISWS
 	default y
 
-config X86_TSC
-	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
-	default y
-
 config X86_MCE
 	bool "Machine Check Exception"
 	depends on !X86_VOYAGER
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
new file mode 100644
index 0000000..53bbb3c
--- /dev/null
+++ b/arch/i386/Kconfig.cpu
@@ -0,0 +1,309 @@
+# Put here option for CPU selection and depending optimization
+if !X86_ELAN
+
+choice
+	prompt "Processor family"
+	default M686
+
+config M386
+	bool "386"
+	---help---
+	  This is the processor type of your CPU. This information is used for
+	  optimizing purposes. In order to compile a kernel that can run on
+	  all x86 CPU types (albeit not optimally fast), you can specify
+	  "386" here.
+
+	  The kernel will not necessarily run on earlier architectures than
+	  the one you have chosen, e.g. a Pentium optimized kernel will run on
+	  a PPro, but not necessarily on a i486.
+
+	  Here are the settings recommended for greatest speed:
+	  - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
+	  486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
+	  will run on a 386 class machine.
+	  - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
+	  SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
+	  - "586" for generic Pentium CPUs lacking the TSC
+	  (time stamp counter) register.
+	  - "Pentium-Classic" for the Intel Pentium.
+	  - "Pentium-MMX" for the Intel Pentium MMX.
+	  - "Pentium-Pro" for the Intel Pentium Pro.
+	  - "Pentium-II" for the Intel Pentium II or pre-Coppermine Celeron.
+	  - "Pentium-III" for the Intel Pentium III or Coppermine Celeron.
+	  - "Pentium-4" for the Intel Pentium 4 or P4-based Celeron.
+	  - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
+	  - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
+	  - "Crusoe" for the Transmeta Crusoe series.
+	  - "Efficeon" for the Transmeta Efficeon series.
+	  - "Winchip-C6" for original IDT Winchip.
+	  - "Winchip-2" for IDT Winchip 2.
+	  - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+	  - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
+	  - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
+	  - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
+
+	  If you don't know what to do, choose "386".
+
+config M486
+	bool "486"
+	help
+	  Select this for a 486 series processor, either Intel or one of the
+	  compatible processors from AMD, Cyrix, IBM, or Intel.  Includes DX,
+	  DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or
+	  U5S.
+
+config M586
+	bool "586/K5/5x86/6x86/6x86MX"
+	help
+	  Select this for an 586 or 686 series processor such as the AMD K5,
+	  the Cyrix 5x86, 6x86 and 6x86MX.  This choice does not
+	  assume the RDTSC (Read Time Stamp Counter) instruction.
+
+config M586TSC
+	bool "Pentium-Classic"
+	help
+	  Select this for a Pentium Classic processor with the RDTSC (Read
+	  Time Stamp Counter) instruction for benchmarking.
+
+config M586MMX
+	bool "Pentium-MMX"
+	help
+	  Select this for a Pentium with the MMX graphics/multimedia
+	  extended instructions.
+
+config M686
+	bool "Pentium-Pro"
+	help
+	  Select this for Intel Pentium Pro chips.  This enables the use of
+	  Pentium Pro extended instructions, and disables the init-time guard
+	  against the f00f bug found in earlier Pentiums.
+
+config MPENTIUMII
+	bool "Pentium-II/Celeron(pre-Coppermine)"
+	help
+	  Select this for Intel chips based on the Pentium-II and
+	  pre-Coppermine Celeron core.  This option enables an unaligned
+	  copy optimization, compiles the kernel with optimization flags
+	  tailored for the chip, and applies any applicable Pentium Pro
+	  optimizations.
+
+config MPENTIUMIII
+	bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon"
+	help
+	  Select this for Intel chips based on the Pentium-III and
+	  Celeron-Coppermine core.  This option enables use of some
+	  extended prefetch instructions in addition to the Pentium II
+	  extensions.
+
+config MPENTIUMM
+	bool "Pentium M"
+	help
+	  Select this for Intel Pentium M (not Pentium-4 M)
+	  notebook chips.
+
+config MPENTIUM4
+	bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon"
+	help
+	  Select this for Intel Pentium 4 chips.  This includes the
+	  Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
+	  (not Pentium M) chips.  This option enables compile flags
+	  optimized for the chip, uses the correct cache shift, and
+	  applies any applicable Pentium III optimizations.
+
+config MK6
+	bool "K6/K6-II/K6-III"
+	help
+	  Select this for an AMD K6-family processor.  Enables use of
+	  some extended instructions, and passes appropriate optimization
+	  flags to GCC.
+
+config MK7
+	bool "Athlon/Duron/K7"
+	help
+	  Select this for an AMD Athlon K7-family processor.  Enables use of
+	  some extended instructions, and passes appropriate optimization
+	  flags to GCC.
+
+config MK8
+	bool "Opteron/Athlon64/Hammer/K8"
+	help
+	  Select this for an AMD Opteron or Athlon64 Hammer-family processor.  Enables
+	  use of some extended instructions, and passes appropriate optimization
+	  flags to GCC.
+
+config MCRUSOE
+	bool "Crusoe"
+	help
+	  Select this for a Transmeta Crusoe processor.  Treats the processor
+	  like a 586 with TSC, and sets some GCC optimization flags (like a
+	  Pentium Pro with no alignment requirements).
+
+config MEFFICEON
+	bool "Efficeon"
+	help
+	  Select this for a Transmeta Efficeon processor.
+
+config MWINCHIPC6
+	bool "Winchip-C6"
+	help
+	  Select this for an IDT Winchip C6 chip.  Linux and GCC
+	  treat this chip as a 586TSC with some extended instructions
+	  and alignment requirements.
+
+config MWINCHIP2
+	bool "Winchip-2"
+	help
+	  Select this for an IDT Winchip-2.  Linux and GCC
+	  treat this chip as a 586TSC with some extended instructions
+	  and alignment requirements.
+
+config MWINCHIP3D
+	bool "Winchip-2A/Winchip-3"
+	help
+	  Select this for an IDT Winchip-2A or 3.  Linux and GCC
+	  treat this chip as a 586TSC with some extended instructions
+	  and alignment reqirements.  Also enable out of order memory
+	  stores for this CPU, which can increase performance of some
+	  operations.
+
+config MGEODEGX1
+	bool "GeodeGX1"
+	help
+	  Select this for a Geode GX1 (Cyrix MediaGX) chip.
+
+config MCYRIXIII
+	bool "CyrixIII/VIA-C3"
+	help
+	  Select this for a Cyrix III or C3 chip.  Presently Linux and GCC
+	  treat this chip as a generic 586. Whilst the CPU is 686 class,
+	  it lacks the cmov extension which gcc assumes is present when
+	  generating 686 code.
+	  Note that Nehemiah (Model 9) and above will not boot with this
+	  kernel due to them lacking the 3DNow! instructions used in earlier
+	  incarnations of the CPU.
+
+config MVIAC3_2
+	bool "VIA C3-2 (Nehemiah)"
+	help
+	  Select this for a VIA C3 "Nehemiah". Selecting this enables usage
+	  of SSE and tells gcc to treat the CPU as a 686.
+	  Note, this kernel will not boot on older (pre model 9) C3s.
+
+endchoice
+
+config X86_GENERIC
+       bool "Generic x86 support"
+       help
+	  Instead of just including optimizations for the selected
+	  x86 variant (e.g. PII, Crusoe or Athlon), include some more
+	  generic optimizations as well. This will make the kernel
+	  perform better on x86 CPUs other than that selected.
+
+	  This is really intended for distributors who need more
+	  generic optimizations.
+
+endif
+
+#
+# Define implied options from the CPU selection here
+#
+config X86_CMPXCHG
+	bool
+	depends on !M386
+	default y
+
+config X86_XADD
+	bool
+	depends on !M386
+	default y
+
+config X86_L1_CACHE_SHIFT
+	int
+	default "7" if MPENTIUM4 || X86_GENERIC
+	default "4" if X86_ELAN || M486 || M386
+	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
+	default "6" if MK7 || MK8 || MPENTIUMM
+
+config RWSEM_GENERIC_SPINLOCK
+	bool
+	depends on M386
+	default y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+	depends on !M386
+	default y
+
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
+config X86_PPRO_FENCE
+	bool
+	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1
+	default y
+
+config X86_F00F_BUG
+	bool
+	depends on M586MMX || M586TSC || M586 || M486 || M386
+	default y
+
+config X86_WP_WORKS_OK
+	bool
+	depends on !M386
+	default y
+
+config X86_INVLPG
+	bool
+	depends on !M386
+	default y
+
+config X86_BSWAP
+	bool
+	depends on !M386
+	default y
+
+config X86_POPAD_OK
+	bool
+	depends on !M386
+	default y
+
+config X86_CMPXCHG64
+	bool
+	depends on !M386 && !M486
+	default y
+
+config X86_ALIGNMENT_16
+	bool
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
+	default y
+
+config X86_GOOD_APIC
+	bool
+	depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON
+	default y
+
+config X86_INTEL_USERCOPY
+	bool
+	depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON
+	default y
+
+config X86_USE_PPRO_CHECKSUM
+	bool
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
+	default y
+
+config X86_USE_3DNOW
+	bool
+	depends on MCYRIXIII || MK7
+	default y
+
+config X86_OOSTORE
+	bool
+	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
+	default y
+
+config X86_TSC
+	bool
+	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
+	default y
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 0995199..d121ea1 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -34,35 +34,8 @@
 # prevent gcc from keeping the stack 16 byte aligned
 CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
 
-align := $(cc-option-align)
-cflags-$(CONFIG_M386)		+= -march=i386
-cflags-$(CONFIG_M486)		+= -march=i486
-cflags-$(CONFIG_M586)		+= -march=i586
-cflags-$(CONFIG_M586TSC)	+= -march=i586
-cflags-$(CONFIG_M586MMX)	+= $(call cc-option,-march=pentium-mmx,-march=i586)
-cflags-$(CONFIG_M686)		+= -march=i686
-cflags-$(CONFIG_MPENTIUMII)	+= -march=i686 $(call cc-option,-mtune=pentium2)
-cflags-$(CONFIG_MPENTIUMIII)	+= -march=i686 $(call cc-option,-mtune=pentium3)
-cflags-$(CONFIG_MPENTIUMM)	+= -march=i686 $(call cc-option,-mtune=pentium3)
-cflags-$(CONFIG_MPENTIUM4)	+= -march=i686 $(call cc-option,-mtune=pentium4)
-cflags-$(CONFIG_MK6)		+= -march=k6
-# Please note, that patches that add -march=athlon-xp and friends are pointless.
-# They make zero difference whatsosever to performance at this time.
-cflags-$(CONFIG_MK7)		+= $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)
-cflags-$(CONFIG_MK8)		+= $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4))
-cflags-$(CONFIG_MCRUSOE)	+= -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MEFFICEON)	+= -march=i686 $(call cc-option,-mtune=pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MWINCHIPC6)	+= $(call cc-option,-march=winchip-c6,-march=i586)
-cflags-$(CONFIG_MWINCHIP2)	+= $(call cc-option,-march=winchip2,-march=i586)
-cflags-$(CONFIG_MWINCHIP3D)	+= $(call cc-option,-march=winchip2,-march=i586)
-cflags-$(CONFIG_MCYRIXIII)	+= $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MVIAC3_2)	+= $(call cc-option,-march=c3-2,-march=i686)
-
-# AMD Elan support
-cflags-$(CONFIG_X86_ELAN)	+= -march=i486
-
-# Geode GX1 support
-cflags-$(CONFIG_MGEODEGX1)		+= $(call cc-option,-march=pentium-mmx,-march=i486)
+# CPU-specific tuning. Anything which can be shared with UML should go here.
+include $(srctree)/arch/i386/Makefile.cpu
 
 # -mregparm=3 works ok on gcc-3.0 and later
 #
diff --git a/arch/i386/Makefile.cpu b/arch/i386/Makefile.cpu
new file mode 100644
index 0000000..8e51456
--- /dev/null
+++ b/arch/i386/Makefile.cpu
@@ -0,0 +1,41 @@
+# CPU tuning section - shared with UML.
+# Must change only cflags-y (or [yn]), not CFLAGS! That makes a difference for UML.
+
+#-mtune exists since gcc 3.4, and some -mcpu flavors didn't exist in gcc 2.95.
+HAS_MTUNE	:= $(call cc-option-yn, -mtune=i386)
+ifeq ($(HAS_MTUNE),y)
+tune		= $(call cc-option,-mtune=$(1),)
+else
+tune		= $(call cc-option,-mcpu=$(1),)
+endif
+
+align := $(cc-option-align)
+cflags-$(CONFIG_M386)		+= -march=i386
+cflags-$(CONFIG_M486)		+= -march=i486
+cflags-$(CONFIG_M586)		+= -march=i586
+cflags-$(CONFIG_M586TSC)	+= -march=i586
+cflags-$(CONFIG_M586MMX)	+= $(call cc-option,-march=pentium-mmx,-march=i586)
+cflags-$(CONFIG_M686)		+= -march=i686
+cflags-$(CONFIG_MPENTIUMII)	+= -march=i686 $(call tune,pentium2)
+cflags-$(CONFIG_MPENTIUMIII)	+= -march=i686 $(call tune,pentium3)
+cflags-$(CONFIG_MPENTIUMM)	+= -march=i686 $(call tune,pentium3)
+cflags-$(CONFIG_MPENTIUM4)	+= -march=i686 $(call tune,pentium4)
+cflags-$(CONFIG_MK6)		+= -march=k6
+# Please note, that patches that add -march=athlon-xp and friends are pointless.
+# They make zero difference whatsosever to performance at this time.
+cflags-$(CONFIG_MK7)		+= $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)
+cflags-$(CONFIG_MK8)		+= $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4))
+cflags-$(CONFIG_MCRUSOE)	+= -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
+cflags-$(CONFIG_MEFFICEON)	+= -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
+cflags-$(CONFIG_MWINCHIPC6)	+= $(call cc-option,-march=winchip-c6,-march=i586)
+cflags-$(CONFIG_MWINCHIP2)	+= $(call cc-option,-march=winchip2,-march=i586)
+cflags-$(CONFIG_MWINCHIP3D)	+= $(call cc-option,-march=winchip2,-march=i586)
+cflags-$(CONFIG_MCYRIXIII)	+= $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
+cflags-$(CONFIG_MVIAC3_2)	+= $(call cc-option,-march=c3-2,-march=i686)
+
+# AMD Elan support
+cflags-$(CONFIG_X86_ELAN)	+= -march=i486
+
+# Geode GX1 support
+cflags-$(CONFIG_MGEODEGX1)		+= $(call cc-option,-march=pentium-mmx,-march=i486)
+
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 5546dde..9204be6 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -803,6 +803,7 @@
 
 void __init init_apic_mappings(void)
 {
+	unsigned int orig_apicid;
 	unsigned long apic_phys;
 
 	/*
@@ -824,8 +825,11 @@
 	 * Fetch the APIC ID of the BSP in case we have a
 	 * default configuration (or the MP table is broken).
 	 */
-	if (boot_cpu_physical_apicid == -1U)
-		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+	orig_apicid = boot_cpu_physical_apicid;
+	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+	if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid))
+		printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)",
+			orig_apicid, boot_cpu_physical_apicid);
 
 #ifdef CONFIG_X86_IO_APIC
 	{
@@ -1046,10 +1050,11 @@
 
 void __init setup_boot_APIC_clock(void)
 {
+	unsigned long flags;
 	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
 	using_apic_timer = 1;
 
-	local_irq_disable();
+	local_irq_save(flags);
 
 	calibration_result = calibrate_APIC_clock();
 	/*
@@ -1057,7 +1062,7 @@
 	 */
 	setup_APIC_timer(calibration_result);
 
-	local_irq_enable();
+	local_irq_restore(flags);
 }
 
 void __devinit setup_secondary_APIC_clock(void)
@@ -1254,40 +1259,81 @@
 }
 
 /*
- * This initializes the IO-APIC and APIC hardware if this is
- * a UP kernel.
+ * This initializes the IO-APIC and APIC hardware.
  */
-int __init APIC_init_uniprocessor (void)
+int __init APIC_init(void)
 {
-	if (enable_local_apic < 0)
-		clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-
-	if (!smp_found_config && !cpu_has_apic)
+	if (enable_local_apic < 0) {
+		printk(KERN_INFO "APIC disabled\n");
 		return -1;
+	}
+
+	/* See if we have a SMP configuration or have forced enabled
+	 * the local apic.
+	 */
+	if (!smp_found_config && !acpi_lapic && !cpu_has_apic) {
+		enable_local_apic = -1;
+		return -1;
+	}
 
 	/*
-	 * Complain if the BIOS pretends there is one.
+	 * Complain if the BIOS pretends there is an apic.
+	 * Then get out because we don't have an a local apic.
 	 */
 	if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
 		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
 			boot_cpu_physical_apicid);
+		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+		enable_local_apic = -1;
 		return -1;
 	}
 
 	verify_local_APIC();
 
+	/*
+	 * Should not be necessary because the MP table should list the boot
+	 * CPU too, but we do it for the sake of robustness anyway.
+	 * Makes no sense to do this check in clustered apic mode, so skip it
+	 */
+	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
+		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+				boot_cpu_physical_apicid);
+		physid_set(boot_cpu_physical_apicid, phys_cpu_present_map);
+	}
+
+	/*
+	 * Switch from PIC to APIC mode.
+	 */
 	connect_bsp_APIC();
-
-	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
-
 	setup_local_APIC();
 
 #ifdef CONFIG_X86_IO_APIC
-	if (smp_found_config)
-		if (!skip_ioapic_setup && nr_ioapics)
-			setup_IO_APIC();
+	/*
+	 * Now start the IO-APICs
+	 */
+	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
+		setup_IO_APIC();
+#endif
+	return 0;
+}
+
+void __init APIC_late_time_init(void)
+{
+	/* Improve our loops per jiffy estimate */
+	loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz;
+	boot_cpu_data.loops_per_jiffy = loops_per_jiffy;
+	cpu_data[0].loops_per_jiffy = loops_per_jiffy;
+
+	/* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is
+	 * initialized.  So redo it here to ensure the boot cpu is setup
+	 * properly.
+	 */
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		setup_apic_nmi_watchdog();
+
+#ifdef CONFIG_X86_IO_APIC
+	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
+		IO_APIC_late_time_init();
 #endif
 	setup_boot_APIC_clock();
-
-	return 0;
 }
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index d7811c4..d2ef0c2 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -597,12 +597,14 @@
 	cpumask_t		cpus;
 	int			cpu;
 	struct desc_struct	save_desc_40;
+	struct desc_struct	*gdt;
 
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
-	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
-	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
+	gdt = get_cpu_gdt_table(cpu);
+	save_desc_40 = gdt[0x40 / 8];
+	gdt[0x40 / 8] = bad_bios_desc;
 
 	local_save_flags(flags);
 	APM_DO_CLI;
@@ -610,7 +612,7 @@
 	apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
 	APM_DO_RESTORE_SEGS;
 	local_irq_restore(flags);
-	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = save_desc_40;
+	gdt[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
 	
@@ -639,13 +641,14 @@
 	cpumask_t		cpus;
 	int			cpu;
 	struct desc_struct	save_desc_40;
-
+	struct desc_struct	*gdt;
 
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
-	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
-	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
+	gdt = get_cpu_gdt_table(cpu);
+	save_desc_40 = gdt[0x40 / 8];
+	gdt[0x40 / 8] = bad_bios_desc;
 
 	local_save_flags(flags);
 	APM_DO_CLI;
@@ -653,7 +656,7 @@
 	error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
 	APM_DO_RESTORE_SEGS;
 	local_irq_restore(flags);
-	__get_cpu_var(cpu_gdt_table)[0x40 / 8] = save_desc_40;
+	gdt[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
 	return error;
@@ -2295,35 +2298,36 @@
 	apm_bios_entry.segment = APM_CS;
 
 	for (i = 0; i < NR_CPUS; i++) {
-		set_base(per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
+		struct desc_struct *gdt = get_cpu_gdt_table(i);
+		set_base(gdt[APM_CS >> 3],
 			 __va((unsigned long)apm_info.bios.cseg << 4));
-		set_base(per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
+		set_base(gdt[APM_CS_16 >> 3],
 			 __va((unsigned long)apm_info.bios.cseg_16 << 4));
-		set_base(per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
+		set_base(gdt[APM_DS >> 3],
 			 __va((unsigned long)apm_info.bios.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
 		if (apm_info.bios.version == 0x100) {
 #endif
 			/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
 			/* For some unknown machine. */
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
 			/* For the DEC Hinote Ultra CT475 (and others?) */
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
 #ifndef APM_RELAX_SEGMENTS
 		} else {
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
+			_set_limit((char *)&gdt[APM_CS >> 3],
 				(apm_info.bios.cseg_len - 1) & 0xffff);
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
+			_set_limit((char *)&gdt[APM_CS_16 >> 3],
 				(apm_info.bios.cseg_16_len - 1) & 0xffff);
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
+			_set_limit((char *)&gdt[APM_DS >> 3],
 				(apm_info.bios.dseg_len - 1) & 0xffff);
 		      /* workaround for broken BIOSes */
 	                if (apm_info.bios.cseg_len <= apm_info.bios.offset)
-        	                _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 -1);
+        	                _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1);
                        if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
                         	/* for the BIOS that assumes granularity = 1 */
-                        	per_cpu(cpu_gdt_table, i)[APM_DS >> 3].b |= 0x800000;
+                        	gdt[APM_DS >> 3].b |= 0x800000;
                         	printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
         	        }
 		}
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 9ad43be..74145a3 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -573,6 +573,7 @@
 	int cpu = smp_processor_id();
 	struct tss_struct * t = &per_cpu(init_tss, cpu);
 	struct thread_struct *thread = &current->thread;
+	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
 	__u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
 
 	if (cpu_test_and_set(cpu, cpu_initialized)) {
@@ -594,24 +595,16 @@
 	 * Initialize the per-CPU GDT with the boot GDT,
 	 * and set up the GDT descriptor:
 	 */
-	memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
-	       GDT_SIZE);
+ 	memcpy(gdt, cpu_gdt_table, GDT_SIZE);
 
 	/* Set up GDT entry for 16bit stack */
-	*(__u64 *)&(per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_ESPFIX_SS]) |=
+ 	*(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
 		((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
 		((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
 		(CPU_16BIT_STACK_SIZE - 1);
 
 	cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
-	cpu_gdt_descr[cpu].address =
-	    (unsigned long)&per_cpu(cpu_gdt_table, cpu);
-
-	/*
-	 * Set up the per-thread TLS descriptor cache:
-	 */
-	memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
-		GDT_ENTRY_TLS_ENTRIES * 8);
+ 	cpu_gdt_descr[cpu].address = (unsigned long)gdt;
 
 	load_gdt(&cpu_gdt_descr[cpu]);
 	load_idt(&idt_descr);
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 822c8ce..caa9f77 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -32,6 +32,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/compiler.h>
+#include <linux/sched.h>	/* current */
 #include <asm/io.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index aa622d5..270f218 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -28,6 +28,7 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/cpumask.h>
+#include <linux/sched.h>	/* current / set_cpus_allowed() */
 
 #include <asm/processor.h> 
 #include <asm/msr.h>
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 58ca98f..2d5c9ad 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/cpumask.h>
+#include <linux/sched.h>	/* for current / set_cpus_allowed() */
 
 #include <asm/msr.h>
 #include <asm/io.h>
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index c397b62..1465974 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/config.h>
+#include <linux/sched.h>	/* current */
 #include <linux/delay.h>
 #include <linux/compiler.h>
 
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index 9e0d5f8..4dc42a1 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -3,6 +3,7 @@
  *
  *      Changes:
  *      Venkatesh Pallipadi	: Adding cache identification through cpuid(4)
+ *		Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
  */
 
 #include <linux/init.h>
@@ -10,6 +11,7 @@
 #include <linux/device.h>
 #include <linux/compiler.h>
 #include <linux/cpu.h>
+#include <linux/sched.h>
 
 #include <asm/processor.h>
 #include <asm/smp.h>
@@ -28,7 +30,7 @@
 };
 
 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
-static struct _cache_table cache_table[] __devinitdata =
+static struct _cache_table cache_table[] __cpuinitdata =
 {
 	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
@@ -117,10 +119,9 @@
 	cpumask_t shared_cpu_map;
 };
 
-#define MAX_CACHE_LEAVES		4
 static unsigned short			num_cache_leaves;
 
-static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
 {
 	unsigned int		eax, ebx, ecx, edx;
 	union _cpuid4_leaf_eax	cache_eax;
@@ -144,23 +145,18 @@
 {
 	unsigned int		eax, ebx, ecx, edx;
 	union _cpuid4_leaf_eax	cache_eax;
-	int 			i;
-	int 			retval;
+	int 			i = -1;
 
-	retval = MAX_CACHE_LEAVES;
-	/* Do cpuid(4) loop to find out num_cache_leaves */
-	for (i = 0; i < MAX_CACHE_LEAVES; i++) {
+	do {
+		++i;
+		/* Do cpuid(4) loop to find out num_cache_leaves */
 		cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
 		cache_eax.full = eax;
-		if (cache_eax.split.type == CACHE_TYPE_NULL) {
-			retval = i;
-			break;
-		}
-	}
-	return retval;
+	} while (cache_eax.split.type != CACHE_TYPE_NULL);
+	return i;
 }
 
-unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
+unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 {
 	unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
 	unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
@@ -284,13 +280,7 @@
 		if ( l3 )
 			printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
 
-		/*
-		 * This assumes the L3 cache is shared; it typically lives in
-		 * the northbridge.  The L1 caches are included by the L2
-		 * cache, and so should not be included for the purpose of
-		 * SMP switching weights.
-		 */
-		c->x86_cache_size = l2 ? l2 : (l1i+l1d);
+		c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
 	}
 
 	return l2;
@@ -301,7 +291,7 @@
 #define CPUID4_INFO_IDX(x,y)    (&((cpuid4_info[x])[y]))
 
 #ifdef CONFIG_SMP
-static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
 {
 	struct _cpuid4_info	*this_leaf;
 	unsigned long num_threads_sharing;
@@ -334,7 +324,7 @@
 	cpuid4_info[cpu] = NULL;
 }
 
-static int __devinit detect_cache_attributes(unsigned int cpu)
+static int __cpuinit detect_cache_attributes(unsigned int cpu)
 {
 	struct _cpuid4_info	*this_leaf;
 	unsigned long 		j;
@@ -511,7 +501,7 @@
 	free_cache_attributes(cpu);
 }
 
-static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu)
+static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
 {
 
 	if (num_cache_leaves == 0)
@@ -542,7 +532,7 @@
 }
 
 /* Add/Remove cache interface for CPU device */
-static int __devinit cache_add_dev(struct sys_device * sys_dev)
+static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
 {
 	unsigned int cpu = sys_dev->id;
 	unsigned long i, j;
@@ -579,7 +569,7 @@
 	return retval;
 }
 
-static int __devexit cache_remove_dev(struct sys_device * sys_dev)
+static void __cpuexit cache_remove_dev(struct sys_device * sys_dev)
 {
 	unsigned int cpu = sys_dev->id;
 	unsigned long i;
@@ -588,24 +578,49 @@
 		kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
 	kobject_unregister(cache_kobject[cpu]);
 	cpuid4_cache_sysfs_exit(cpu);
-	return 0;
+	return;
 }
 
-static struct sysdev_driver cache_sysdev_driver = {
-	.add = cache_add_dev,
-	.remove = __devexit_p(cache_remove_dev),
+static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+	struct sys_device *sys_dev;
+
+	sys_dev = get_cpu_sysdev(cpu);
+	switch (action) {
+	case CPU_ONLINE:
+		cache_add_dev(sys_dev);
+		break;
+	case CPU_DEAD:
+		cache_remove_dev(sys_dev);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cacheinfo_cpu_notifier =
+{
+    .notifier_call = cacheinfo_cpu_callback,
 };
 
-/* Register/Unregister the cpu_cache driver */
-static int __devinit cache_register_driver(void)
+static int __cpuinit cache_sysfs_init(void)
 {
+	int i;
+
 	if (num_cache_leaves == 0)
 		return 0;
 
-	return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver);
+	register_cpu_notifier(&cacheinfo_cpu_notifier);
+
+	for_each_online_cpu(i) {
+		cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE,
+			(void *)(long)i);
+	}
+
+	return 0;
 }
 
-device_initcall(cache_register_driver);
+device_initcall(cache_sysfs_init);
 
 #endif
-
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c
index 3c035b8..979b18b 100644
--- a/arch/i386/kernel/cpu/mcheck/p6.c
+++ b/arch/i386/kernel/cpu/mcheck/p6.c
@@ -102,11 +102,16 @@
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 	nr_mce_banks = l & 0xff;
 
-	/* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
-	for (i=1; i<nr_mce_banks; i++) {
+	/*
+	 * Following the example in IA-32 SDM Vol 3:
+	 * - MC0_CTL should not be written
+	 * - Status registers on all banks should be cleared on reset
+	 */
+	for (i=1; i<nr_mce_banks; i++)
 		wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+
+	for (i=0; i<nr_mce_banks; i++)
 		wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
-	}
 
 	set_in_cr4 (X86_CR4_MCE);
 	printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c
index 1923e0a..cf39e20 100644
--- a/arch/i386/kernel/cpu/mtrr/if.c
+++ b/arch/i386/kernel/cpu/mtrr/if.c
@@ -149,60 +149,89 @@
 	return -EINVAL;
 }
 
-static int
-mtrr_ioctl(struct inode *inode, struct file *file,
-	   unsigned int cmd, unsigned long __arg)
+static long
+mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
 {
-	int err;
+	int err = 0;
 	mtrr_type type;
 	struct mtrr_sentry sentry;
 	struct mtrr_gentry gentry;
 	void __user *arg = (void __user *) __arg;
 
 	switch (cmd) {
+	case MTRRIOC_ADD_ENTRY:
+	case MTRRIOC_SET_ENTRY:
+	case MTRRIOC_DEL_ENTRY:
+	case MTRRIOC_KILL_ENTRY:
+	case MTRRIOC_ADD_PAGE_ENTRY:
+	case MTRRIOC_SET_PAGE_ENTRY:
+	case MTRRIOC_DEL_PAGE_ENTRY:
+	case MTRRIOC_KILL_PAGE_ENTRY:
+		if (copy_from_user(&sentry, arg, sizeof sentry))
+			return -EFAULT;
+		break;
+	case MTRRIOC_GET_ENTRY:
+	case MTRRIOC_GET_PAGE_ENTRY:
+		if (copy_from_user(&gentry, arg, sizeof gentry))
+			return -EFAULT;
+		break;
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_ADD_ENTRY:
+	case MTRRIOC32_SET_ENTRY:
+	case MTRRIOC32_DEL_ENTRY:
+	case MTRRIOC32_KILL_ENTRY:
+	case MTRRIOC32_ADD_PAGE_ENTRY:
+	case MTRRIOC32_SET_PAGE_ENTRY:
+	case MTRRIOC32_DEL_PAGE_ENTRY:
+	case MTRRIOC32_KILL_PAGE_ENTRY: {
+		struct mtrr_sentry32 __user *s32 = (struct mtrr_sentry32 __user *)__arg;
+		err = get_user(sentry.base, &s32->base);
+		err |= get_user(sentry.size, &s32->size);
+		err |= get_user(sentry.type, &s32->type);
+		if (err)
+			return err;
+		break;
+	}
+	case MTRRIOC32_GET_ENTRY:
+	case MTRRIOC32_GET_PAGE_ENTRY: {
+		struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)__arg;
+		err = get_user(gentry.regnum, &g32->regnum);
+		err |= get_user(gentry.base, &g32->base);
+		err |= get_user(gentry.size, &g32->size);
+		err |= get_user(gentry.type, &g32->type);
+		if (err)
+			return err;
+		break;
+	}
+#endif
+	}
+
+	switch (cmd) {
 	default:
 		return -ENOTTY;
 	case MTRRIOC_ADD_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err =
 		    mtrr_file_add(sentry.base, sentry.size, sentry.type, 1,
 				  file, 0);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_SET_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err = mtrr_add(sentry.base, sentry.size, sentry.type, 0);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_DEL_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err = mtrr_file_del(sentry.base, sentry.size, file, 0);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_KILL_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err = mtrr_del(-1, sentry.base, sentry.size);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_GET_ENTRY:
-		if (copy_from_user(&gentry, arg, sizeof gentry))
-			return -EFAULT;
 		if (gentry.regnum >= num_var_ranges)
 			return -EINVAL;
 		mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type);
@@ -217,60 +246,59 @@
 			gentry.type = type;
 		}
 
-		if (copy_to_user(arg, &gentry, sizeof gentry))
-			return -EFAULT;
 		break;
 	case MTRRIOC_ADD_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err =
 		    mtrr_file_add(sentry.base, sentry.size, sentry.type, 1,
 				  file, 1);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_SET_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_DEL_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err = mtrr_file_del(sentry.base, sentry.size, file, 1);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_KILL_PAGE_ENTRY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (copy_from_user(&sentry, arg, sizeof sentry))
-			return -EFAULT;
 		err = mtrr_del_page(-1, sentry.base, sentry.size);
-		if (err < 0)
-			return err;
 		break;
 	case MTRRIOC_GET_PAGE_ENTRY:
-		if (copy_from_user(&gentry, arg, sizeof gentry))
-			return -EFAULT;
 		if (gentry.regnum >= num_var_ranges)
 			return -EINVAL;
 		mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type);
 		gentry.type = type;
-
-		if (copy_to_user(arg, &gentry, sizeof gentry))
-			return -EFAULT;
 		break;
 	}
-	return 0;
+
+	if (err)
+		return err;
+
+	switch(cmd) {
+	case MTRRIOC_GET_ENTRY:
+	case MTRRIOC_GET_PAGE_ENTRY:
+		if (copy_to_user(arg, &gentry, sizeof gentry))
+			err = -EFAULT;
+		break;
+#ifdef CONFIG_COMPAT
+	case MTRRIOC32_GET_ENTRY:
+	case MTRRIOC32_GET_PAGE_ENTRY: {
+		struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)__arg;
+		err = put_user(gentry.base, &g32->base);
+		err |= put_user(gentry.size, &g32->size);
+		err |= put_user(gentry.regnum, &g32->regnum);
+		err |= put_user(gentry.type, &g32->type);
+		break;
+	}
+#endif
+	}
+	return err;
 }
 
 static int
@@ -310,7 +338,8 @@
 	.read    = seq_read,
 	.llseek  = seq_lseek,
 	.write   = mtrr_write,
-	.ioctl   = mtrr_ioctl,
+	.unlocked_ioctl = mtrr_ioctl,
+	.compat_ioctl = mtrr_ioctl,
 	.release = mtrr_close,
 };
 
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 8bd77d9..41b871e 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -44,7 +44,7 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
-		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
+		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", NULL, "est",
 		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 4647db4..13bae79 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -163,7 +163,7 @@
 	int err = 0;
 	struct class_device *class_err;
 
-	class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
+	class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
 	if (IS_ERR(class_err))
 		err = PTR_ERR(class_err);
 	return err;
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index 0248e08..af809cc 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -21,7 +21,6 @@
 #include <asm/hardirq.h>
 #include <asm/nmi.h>
 #include <asm/hw_irq.h>
-#include <asm/apic.h>
 #include <mach_ipi.h>
 
 
@@ -148,7 +147,6 @@
 		regs = &fixed_regs;
 	}
 	crash_save_this_cpu(regs, cpu);
-	disable_local_APIC();
 	atomic_dec(&waiting_for_crash_ipi);
 	/* Assume hlt works */
 	halt();
@@ -188,7 +186,6 @@
 	}
 
 	/* Leave the nmi callback set */
-	disable_local_APIC();
 }
 #else
 static void nmi_shootdown_cpus(void)
@@ -213,9 +210,5 @@
 	/* Make a note of crashing cpu. Will be used in NMI callback.*/
 	crashing_cpu = smp_processor_id();
 	nmi_shootdown_cpus();
-	lapic_shutdown();
-#if defined(CONFIG_X86_IO_APIC)
-	disable_IO_APIC();
-#endif
 	crash_save_self(regs);
 }
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 323ef8a..d86f249 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -435,4 +435,8 @@
 		setup_irq(FPU_IRQ, &fpu_irq);
 
 	irq_ctx_init(smp_processor_id());
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	APIC_init();
+#endif
 }
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index fb3991e..5a77c52 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -46,6 +46,9 @@
 int (*ioapic_renumber_irq)(int ioapic, int irq);
 atomic_t irq_mis_count;
 
+/* Where if anywhere is the i8259 connect in external int mode */
+static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+
 static DEFINE_SPINLOCK(ioapic_lock);
 
 /*
@@ -738,7 +741,7 @@
 /*
  * Find the pin to which IRQ[irq] (ISA) is connected
  */
-static int find_isa_irq_pin(int irq, int type)
+static int __init find_isa_irq_pin(int irq, int type)
 {
 	int i;
 
@@ -758,6 +761,33 @@
 	return -1;
 }
 
+static int __init find_isa_irq_apic(int irq, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].mpc_srcbus;
+
+		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
+		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98
+		    ) &&
+		    (mp_irqs[i].mpc_irqtype == type) &&
+		    (mp_irqs[i].mpc_srcbusirq == irq))
+			break;
+	}
+	if (i < mp_irq_entries) {
+		int apic;
+		for(apic = 0; apic < nr_ioapics; apic++) {
+			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
+				return apic;
+		}
+	}
+
+	return -1;
+}
+
 /*
  * Find a specific PCI IRQ entry.
  * Not an __init, possibly needed by modules
@@ -1253,7 +1283,7 @@
 /*
  * Set up the 8259A-master output pin:
  */
-static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
+static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
 {
 	struct IO_APIC_route_entry entry;
 	unsigned long flags;
@@ -1287,8 +1317,8 @@
 	 * Add it to the IO-APIC irq-routing table:
 	 */
 	spin_lock_irqsave(&ioapic_lock, flags);
-	io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
-	io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+	io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+	io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	enable_8259A_irq(0);
@@ -1595,7 +1625,8 @@
 static void __init enable_IO_APIC(void)
 {
 	union IO_APIC_reg_01 reg_01;
-	int i;
+	int i8259_apic, i8259_pin;
+	int i, apic;
 	unsigned long flags;
 
 	for (i = 0; i < PIN_MAP_SIZE; i++) {
@@ -1609,11 +1640,52 @@
 	/*
 	 * The number of IO-APIC IRQ registers (== #pins):
 	 */
-	for (i = 0; i < nr_ioapics; i++) {
+	for (apic = 0; apic < nr_ioapics; apic++) {
 		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_01.raw = io_apic_read(i, 1);
+		reg_01.raw = io_apic_read(apic, 1);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
-		nr_ioapic_registers[i] = reg_01.bits.entries+1;
+		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+	}
+	for(apic = 0; apic < nr_ioapics; apic++) {
+		int pin;
+		/* See if any of the pins is in ExtINT mode */
+		for(pin = 0; pin < nr_ioapic_registers[i]; pin++) {
+			struct IO_APIC_route_entry entry;
+			spin_lock_irqsave(&ioapic_lock, flags);
+			*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+			*(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+			spin_unlock_irqrestore(&ioapic_lock, flags);
+
+
+			/* If the interrupt line is enabled and in ExtInt mode
+			 * I have found the pin where the i8259 is connected.
+			 */
+			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+				ioapic_i8259.apic = apic;
+				ioapic_i8259.pin  = pin;
+				goto found_i8259;
+			}
+		}
+	}
+ found_i8259:
+	/* Look to see what if the MP table has reported the ExtINT */
+	/* If we could not find the appropriate pin by looking at the ioapic
+	 * the i8259 probably is not connected the ioapic but give the
+	 * mptable a chance anyway.
+	 */
+	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
+	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+	/* Trust the MP table if nothing is setup in the hardware */
+	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
+		ioapic_i8259.pin  = i8259_pin;
+		ioapic_i8259.apic = i8259_apic;
+	}
+	/* Complain if the MP table and the hardware disagree */
+	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
+		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+	{
+		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
 	}
 
 	/*
@@ -1627,7 +1699,6 @@
  */
 void disable_IO_APIC(void)
 {
-	int pin;
 	/*
 	 * Clear the IO-APIC before rebooting:
 	 */
@@ -1638,8 +1709,7 @@
 	 * Put that IOAPIC in virtual wire mode
 	 * so legacy interrupts can be delivered.
 	 */
-	pin = find_isa_irq_pin(0, mp_ExtINT);
-	if (pin != -1) {
+	if (ioapic_i8259.pin != -1) {
 		struct IO_APIC_route_entry entry;
 		unsigned long flags;
 
@@ -1650,7 +1720,7 @@
 		entry.polarity        = 0; /* High */
 		entry.delivery_status = 0;
 		entry.dest_mode       = 0; /* Physical */
-		entry.delivery_mode   = 7; /* ExtInt */
+		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
 		entry.vector          = 0;
 		entry.dest.physical.physical_dest = 0;
 
@@ -1659,11 +1729,13 @@
 		 * Add it to the IO-APIC irq-routing table:
 		 */
 		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
-		io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+		io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
+			*(((int *)&entry)+1));
+		io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
+			*(((int *)&entry)+0));
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 	}
-	disconnect_bsp_APIC(pin != -1);
+	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
 /*
@@ -2113,20 +2185,21 @@
  */
 static inline void unlock_ExtINT_logic(void)
 {
-	int pin, i;
+	int apic, pin, i;
 	struct IO_APIC_route_entry entry0, entry1;
 	unsigned char save_control, save_freq_select;
 	unsigned long flags;
 
-	pin = find_isa_irq_pin(8, mp_INT);
+	pin  = find_isa_irq_pin(8, mp_INT);
+	apic = find_isa_irq_apic(8, mp_INT);
 	if (pin == -1)
 		return;
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	*(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
-	*(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
+	*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+	*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
-	clear_IO_APIC_pin(0, pin);
+	clear_IO_APIC_pin(apic, pin);
 
 	memset(&entry1, 0, sizeof(entry1));
 
@@ -2139,8 +2212,8 @@
 	entry1.vector = 0;
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
-	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	save_control = CMOS_READ(RTC_CONTROL);
@@ -2158,11 +2231,11 @@
 
 	CMOS_WRITE(save_control, RTC_CONTROL);
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-	clear_IO_APIC_pin(0, pin);
+	clear_IO_APIC_pin(apic, pin);
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
-	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -2174,7 +2247,7 @@
  */
 static inline void check_timer(void)
 {
-	int pin1, pin2;
+	int apic1, pin1, apic2, pin2;
 	int vector;
 
 	/*
@@ -2196,10 +2269,13 @@
 	timer_ack = 1;
 	enable_8259A_irq(0);
 
-	pin1 = find_isa_irq_pin(0, mp_INT);
-	pin2 = find_isa_irq_pin(0, mp_ExtINT);
+	pin1  = find_isa_irq_pin(0, mp_INT);
+	apic1 = find_isa_irq_apic(0, mp_INT);
+	pin2  = ioapic_i8259.pin;
+	apic2 = ioapic_i8259.apic;
 
-	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
+	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+		vector, apic1, pin1, apic2, pin2);
 
 	if (pin1 != -1) {
 		/*
@@ -2216,8 +2292,9 @@
 				clear_IO_APIC_pin(0, pin1);
 			return;
 		}
-		clear_IO_APIC_pin(0, pin1);
-		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
+		clear_IO_APIC_pin(apic1, pin1);
+		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
+				"IO-APIC\n");
 	}
 
 	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
@@ -2226,13 +2303,13 @@
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
-		setup_ExtINT_IRQ0_pin(pin2, vector);
+		setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
 		if (timer_irq_works()) {
 			printk("works.\n");
 			if (pin1 != -1)
-				replace_pin_at_irq(0, 0, pin1, 0, pin2);
+				replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
 			else
-				add_pin_to_irq(0, 0, pin2);
+				add_pin_to_irq(0, apic2, pin2);
 			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
 			}
@@ -2241,7 +2318,7 @@
 		/*
 		 * Cleanup, just in case ...
 		 */
-		clear_IO_APIC_pin(0, pin2);
+		clear_IO_APIC_pin(apic2, pin2);
 	}
 	printk(" failed.\n");
 
@@ -2310,11 +2387,15 @@
 	sync_Arb_IDs();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
-	check_timer();
 	if (!acpi_ioapic)
 		print_IO_APIC();
 }
 
+void __init IO_APIC_late_time_init(void)
+{
+	check_timer();
+}
+
 /*
  *	Called after all the initialization is done. If we didnt find any
  *	APIC bugs then we can allow the modify fast path
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index ce66dcc..1a201a9 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -218,7 +218,7 @@
 
 	if (i == 0) {
 		seq_printf(p, "           ");
-		for_each_cpu(j)
+		for_each_online_cpu(j)
 			seq_printf(p, "CPU%d       ",j);
 		seq_putc(p, '\n');
 	}
@@ -232,7 +232,7 @@
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for_each_cpu(j)
+		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -246,12 +246,12 @@
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "NMI: ");
-		for_each_cpu(j)
+		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", nmi_count(j));
 		seq_putc(p, '\n');
 #ifdef CONFIG_X86_LOCAL_APIC
 		seq_printf(p, "LOC: ");
-		for_each_cpu(j)
+		for_each_online_cpu(j)
 			seq_printf(p, "%10u ",
 				per_cpu(irq_stat,j).apic_timer_irqs);
 		seq_putc(p, '\n');
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 27aabfc..8f767d9 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -69,7 +69,7 @@
 /* Processor that is doing the boot up */
 unsigned int boot_cpu_physical_apicid = -1U;
 /* Internal processor count */
-static unsigned int __initdata num_processors;
+static unsigned int __devinitdata num_processors;
 
 /* Bitmask of physically existing CPUs */
 physid_mask_t phys_cpu_present_map;
@@ -119,7 +119,7 @@
 }
 #endif
 
-static void __init MP_processor_info (struct mpc_config_processor *m)
+static void __devinit MP_processor_info (struct mpc_config_processor *m)
 {
  	int ver, apicid;
 	physid_mask_t phys_cpu;
@@ -182,17 +182,6 @@
 		boot_cpu_physical_apicid = m->mpc_apicid;
 	}
 
-	if (num_processors >= NR_CPUS) {
-		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
-			"  Processor ignored.\n", NR_CPUS); 
-		return;
-	}
-
-	if (num_processors >= maxcpus) {
-		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
-			" Processor ignored.\n", maxcpus); 
-		return;
-	}
 	ver = m->mpc_apicver;
 
 	if (!MP_valid_apicid(apicid, ver)) {
@@ -201,11 +190,6 @@
 		return;
 	}
 
-	cpu_set(num_processors, cpu_possible_map);
-	num_processors++;
-	phys_cpu = apicid_to_cpu_present(apicid);
-	physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
-
 	/*
 	 * Validate version
 	 */
@@ -216,6 +200,25 @@
 		ver = 0x10;
 	}
 	apic_version[m->mpc_apicid] = ver;
+
+	phys_cpu = apicid_to_cpu_present(apicid);
+	physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+
+	if (num_processors >= NR_CPUS) {
+		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+			"  Processor ignored.\n", NR_CPUS);
+		return;
+	}
+
+	if (num_processors >= maxcpus) {
+		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+			" Processor ignored.\n", maxcpus);
+		return;
+	}
+
+	cpu_set(num_processors, cpu_possible_map);
+	num_processors++;
+
 	if ((num_processors > 8) &&
 	    APIC_XAPIC(ver) &&
 	    (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
@@ -834,7 +837,7 @@
 }
 
 
-void __init mp_register_lapic (
+void __devinit mp_register_lapic (
 	u8			id, 
 	u8			enabled)
 {
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 03100d6..44470fe 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -246,7 +246,7 @@
 	int err = 0;
 	struct class_device *class_err;
 
-	class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
+	class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
 	if (IS_ERR(class_err)) 
 		err = PTR_ERR(class_err);
 	return err;
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 72515b8..d661703 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -100,16 +100,44 @@
 	(P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
 	 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
 
+#ifdef CONFIG_SMP
+/* The performance counters used by NMI_LOCAL_APIC don't trigger when
+ * the CPU is idle. To make sure the NMI watchdog really ticks on all
+ * CPUs during the test make them busy.
+ */
+static __init void nmi_cpu_busy(void *data)
+{
+	volatile int *endflag = data;
+	local_irq_enable();
+	/* Intentionally don't use cpu_relax here. This is
+	   to make sure that the performance counter really ticks,
+	   even if there is a simulator or similar that catches the
+	   pause instruction. On a real HT machine this is fine because
+	   all other CPUs are busy with "useless" delay loops and don't
+	   care if they get somewhat less cycles. */
+	while (*endflag == 0)
+		barrier();
+}
+#endif
+
 static int __init check_nmi_watchdog(void)
 {
-	unsigned int prev_nmi_count[NR_CPUS];
+	volatile int endflag = 0;
+	unsigned int *prev_nmi_count;
 	int cpu;
 
 	if (nmi_watchdog == NMI_NONE)
 		return 0;
 
+	prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
+	if (!prev_nmi_count)
+		return -1;
+
 	printk(KERN_INFO "Testing NMI watchdog ... ");
 
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
+
 	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
 	local_irq_enable();
@@ -123,12 +151,18 @@
 			continue;
 #endif
 		if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) {
-			printk("CPU#%d: NMI appears to be stuck!\n", cpu);
+			endflag = 1;
+			printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
+				cpu,
+				prev_nmi_count[cpu],
+				nmi_count(cpu));
 			nmi_active = 0;
 			lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
+			kfree(prev_nmi_count);
 			return -1;
 		}
 	}
+	endflag = 1;
 	printk("OK.\n");
 
 	/* now that we know it works we can reduce NMI frequency to
@@ -136,6 +170,7 @@
 	if (nmi_watchdog == NMI_LOCAL_APIC)
 		nmi_hz = 1;
 
+	kfree(prev_nmi_count);
 	return 0;
 }
 /* This needs to happen later in boot so counters are working */
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 7b6368b..efd11f0 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -354,7 +354,7 @@
 	return 0;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	struct user * dummy = NULL;
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 1b183b3..c9b8733 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -44,7 +44,7 @@
 
 	for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) {
 		cur = &(fixups_table[i]);
-		dev = pci_get_device(cur->vendor, cur->device, 0);
+		dev = pci_get_device(cur->vendor, cur->device, NULL);
 		if (!dev)
 			continue;
 
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 9b8c8a1..b48ac63 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -389,14 +389,24 @@
 		}
 	}
 	for (i = 0; i < e820.nr_map; i++) {
-		if (e820.map[i].type == E820_RAM) {
-			current_addr = e820.map[i].addr + e820.map[i].size;
-			if (current_addr >= size) {
-				e820.map[i].size -= current_addr-size;
-				e820.nr_map = i + 1;
-				return;
-			}
+		current_addr = e820.map[i].addr + e820.map[i].size;
+		if (current_addr < size)
+			continue;
+
+		if (e820.map[i].type != E820_RAM)
+			continue;
+
+		if (e820.map[i].addr >= size) {
+			/*
+			 * This region starts past the end of the
+			 * requested size, skip it completely.
+			 */
+			e820.nr_map = i;
+		} else {
+			e820.nr_map = i + 1;
+			e820.map[i].size -= current_addr - size;
 		}
+		return;
 	}
 }
 
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 1fb26d0..5a2bbe0 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -87,7 +87,11 @@
 cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
 EXPORT_SYMBOL(cpu_callout_map);
+#ifdef CONFIG_HOTPLUG_CPU
+cpumask_t cpu_possible_map = CPU_MASK_ALL;
+#else
 cpumask_t cpu_possible_map;
+#endif
 EXPORT_SYMBOL(cpu_possible_map);
 static cpumask_t smp_commenced_mask;
 
@@ -1074,6 +1078,16 @@
 EXPORT_SYMBOL(xquad_portio);
 #endif
 
+/*
+ * Fall back to non SMP mode after errors.
+ *
+ */
+static __init void disable_smp(void)
+{
+	cpu_set(0, cpu_sibling_map[0]);
+	cpu_set(0, cpu_core_map[0]);
+}
+
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
 	int apicid, cpu, bit, kicked;
@@ -1086,7 +1100,6 @@
 	printk("CPU%d: ", 0);
 	print_cpu_info(&cpu_data[0]);
 
-	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 	boot_cpu_logical_apicid = logical_smp_processor_id();
 	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 
@@ -1098,68 +1111,27 @@
 	cpus_clear(cpu_core_map[0]);
 	cpu_set(0, cpu_core_map[0]);
 
+	map_cpu_to_logical_apicid();
+
 	/*
 	 * If we couldn't find an SMP configuration at boot time,
 	 * get out of here now!
 	 */
 	if (!smp_found_config && !acpi_lapic) {
 		printk(KERN_NOTICE "SMP motherboard not detected.\n");
-		smpboot_clear_io_apic_irqs();
-		phys_cpu_present_map = physid_mask_of_physid(0);
-		if (APIC_init_uniprocessor())
-			printk(KERN_NOTICE "Local APIC not detected."
-					   " Using dummy APIC emulation.\n");
-		map_cpu_to_logical_apicid();
-		cpu_set(0, cpu_sibling_map[0]);
-		cpu_set(0, cpu_core_map[0]);
+		disable_smp();
 		return;
 	}
 
 	/*
-	 * Should not be necessary because the MP table should list the boot
-	 * CPU too, but we do it for the sake of robustness anyway.
-	 * Makes no sense to do this check in clustered apic mode, so skip it
-	 */
-	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
-		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
-				boot_cpu_physical_apicid);
-		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
-	}
-
-	/*
-	 * If we couldn't find a local APIC, then get out of here now!
-	 */
-	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
-		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
-			boot_cpu_physical_apicid);
-		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
-		smpboot_clear_io_apic_irqs();
-		phys_cpu_present_map = physid_mask_of_physid(0);
-		cpu_set(0, cpu_sibling_map[0]);
-		cpu_set(0, cpu_core_map[0]);
-		return;
-	}
-
-	verify_local_APIC();
-
-	/*
 	 * If SMP should be disabled, then really disable it!
 	 */
-	if (!max_cpus) {
-		smp_found_config = 0;
-		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
-		smpboot_clear_io_apic_irqs();
-		phys_cpu_present_map = physid_mask_of_physid(0);
-		cpu_set(0, cpu_sibling_map[0]);
-		cpu_set(0, cpu_core_map[0]);
+	if (!max_cpus || (enable_local_apic < 0)) {
+		printk(KERN_INFO "SMP mode deactivated.\n");
+		disable_smp();
 		return;
 	}
 
-	connect_bsp_APIC();
-	setup_local_APIC();
-	map_cpu_to_logical_apicid();
-
-
 	setup_portio_remap();
 
 	/*
@@ -1240,10 +1212,6 @@
 	cpu_set(0, cpu_sibling_map[0]);
 	cpu_set(0, cpu_core_map[0]);
 
-	smpboot_setup_io_apic();
-
-	setup_boot_APIC_clock();
-
 	/*
 	 * Synchronize the TSC with the AP
 	 */
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 516bf56..8de658d 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -327,7 +327,12 @@
 	int tables = 0;
 	int i = 0;
 
-	acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING, rsdp_address);
+	if (ACPI_FAILURE(acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING,
+						rsdp_address))) {
+		printk("%s: System description tables not found\n",
+		       __FUNCTION__);
+		goto out_err;
+	}
 
 	if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) {
 		printk("%s: assigning address to rsdp\n", __FUNCTION__);
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 2883a4d..07471bb 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -74,10 +74,6 @@
 
 #include "do_timer.h"
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
 EXPORT_SYMBOL(cpu_khz);
 
@@ -444,8 +440,8 @@
 
 device_initcall(time_init_device);
 
-#ifdef CONFIG_HPET_TIMER
 extern void (*late_time_init)(void);
+#ifdef CONFIG_HPET_TIMER
 /* Duplicate of time_init() below, with hpet_enable part added */
 static void __init hpet_time_init(void)
 {
@@ -462,6 +458,11 @@
 	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
 
 	time_init_hook();
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (enable_local_apic >= 0)
+		APIC_late_time_init();
+#endif
 }
 #endif
 
@@ -486,4 +487,9 @@
 	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
 
 	time_init_hook();
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (enable_local_apic >= 0)
+		late_time_init = APIC_late_time_init;
+#endif
 }
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 658c062..9caeaa3 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -275,6 +275,7 @@
 static unsigned long PIE_count;
 
 static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
+static unsigned int hpet_t1_cmp; /* cached comparator register */
 
 /*
  * Timer 1 for RTC, we do not use periodic interrupt feature,
@@ -306,10 +307,12 @@
 	cnt = hpet_readl(HPET_COUNTER);
 	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
 	hpet_writel(cnt, HPET_T1_CMP);
+	hpet_t1_cmp = cnt;
 	local_irq_restore(flags);
 
 	cfg = hpet_readl(HPET_T1_CFG);
-	cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT;
+	cfg &= ~HPET_TN_PERIODIC;
+	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
 	hpet_writel(cfg, HPET_T1_CFG);
 
 	return 1;
@@ -319,8 +322,12 @@
 {
 	unsigned int cfg, cnt;
 
-	if (!(PIE_on | AIE_on | UIE_on))
+	if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
+		cfg = hpet_readl(HPET_T1_CFG);
+		cfg &= ~HPET_TN_ENABLE;
+		hpet_writel(cfg, HPET_T1_CFG);
 		return;
+	}
 
 	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
 		hpet_rtc_int_freq = PIE_freq;
@@ -328,15 +335,10 @@
 		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
 
 	/* It is more accurate to use the comparator value than current count.*/
-	cnt = hpet_readl(HPET_T1_CMP);
+	cnt = hpet_t1_cmp;
 	cnt += hpet_tick*HZ/hpet_rtc_int_freq;
 	hpet_writel(cnt, HPET_T1_CMP);
-
-	cfg = hpet_readl(HPET_T1_CFG);
-	cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T1_CFG);
-
-	return;
+	hpet_t1_cmp = cnt;
 }
 
 /*
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index d973a8b..be24272 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -30,23 +30,28 @@
  *  basic equation:
  *		ns = cycles / (freq / ns_per_sec)
  *		ns = cycles * (ns_per_sec / freq)
- *		ns = cycles * (10^9 / (cpu_mhz * 10^6))
- *		ns = cycles * (10^3 / cpu_mhz)
+ *		ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *		ns = cycles * (10^6 / cpu_khz)
  *
  *	Then we use scaling math (suggested by george@mvista.com) to get:
- *		ns = cycles * (10^3 * SC / cpu_mhz) / SC
+ *		ns = cycles * (10^6 * SC / cpu_khz) / SC
  *		ns = cycles * cyc2ns_scale / SC
  *
  *	And since SC is a constant power of two, we can convert the div
  *  into a shift.
+ *
+ *  We can use khz divisor instead of mhz to keep a better percision, since
+ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
+ *  (mathieu.desnoyers@polymtl.ca)
+ *
  *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
  */
 static unsigned long cyc2ns_scale;
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
-static inline void set_cyc2ns_scale(unsigned long cpu_mhz)
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
 {
-	cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
+	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
 }
 
 static inline unsigned long long cycles_2_ns(unsigned long long cyc)
@@ -163,7 +168,7 @@
 				printk("Detected %u.%03u MHz processor.\n",
 					cpu_khz / 1000, cpu_khz % 1000);
 			}
-			set_cyc2ns_scale(cpu_khz/1000);
+			set_cyc2ns_scale(cpu_khz);
 		}
 		/* set this only when cpu_has_tsc */
 		timer_hpet.read_timer = read_timer_tsc;
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 6dd470c..d395e3b 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -49,23 +49,28 @@
  *  basic equation:
  *		ns = cycles / (freq / ns_per_sec)
  *		ns = cycles * (ns_per_sec / freq)
- *		ns = cycles * (10^9 / (cpu_mhz * 10^6))
- *		ns = cycles * (10^3 / cpu_mhz)
+ *		ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *		ns = cycles * (10^6 / cpu_khz)
  *
  *	Then we use scaling math (suggested by george@mvista.com) to get:
- *		ns = cycles * (10^3 * SC / cpu_mhz) / SC
+ *		ns = cycles * (10^6 * SC / cpu_khz) / SC
  *		ns = cycles * cyc2ns_scale / SC
  *
  *	And since SC is a constant power of two, we can convert the div
- *  into a shift.   
+ *  into a shift.
+ *
+ *  We can use khz divisor instead of mhz to keep a better percision, since
+ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
+ *  (mathieu.desnoyers@polymtl.ca)
+ *
  *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
  */
 static unsigned long cyc2ns_scale; 
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
-static inline void set_cyc2ns_scale(unsigned long cpu_mhz)
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
 {
-	cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
+	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
 }
 
 static inline unsigned long long cycles_2_ns(unsigned long long cyc)
@@ -286,7 +291,7 @@
 		if (use_tsc) {
 			if (!(freq->flags & CPUFREQ_CONST_LOOPS)) {
 				fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
-				set_cyc2ns_scale(cpu_khz/1000);
+				set_cyc2ns_scale(cpu_khz);
 			}
 		}
 #endif
@@ -536,7 +541,7 @@
 				printk("Detected %u.%03u MHz processor.\n",
 					cpu_khz / 1000, cpu_khz % 1000);
 			}
-			set_cyc2ns_scale(cpu_khz/1000);
+			set_cyc2ns_scale(cpu_khz);
 			return 0;
 		}
 	}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 19e90bd..c34d1bf 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -488,6 +488,7 @@
 				tss->io_bitmap_max - thread->io_bitmap_max);
 		tss->io_bitmap_max = thread->io_bitmap_max;
 		tss->io_bitmap_base = IO_BITMAP_OFFSET;
+		tss->io_bitmap_owner = thread;
 		put_cpu();
 		return;
 	}
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 16b4850..fc19935 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -134,17 +134,16 @@
 	return ret;
 }
 
-static void mark_screen_rdonly(struct task_struct * tsk)
+static void mark_screen_rdonly(struct mm_struct *mm)
 {
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
-	pte_t *pte, *mapped;
+	pte_t *pte;
+	spinlock_t *ptl;
 	int i;
 
-	preempt_disable();
-	spin_lock(&tsk->mm->page_table_lock);
-	pgd = pgd_offset(tsk->mm, 0xA0000);
+	pgd = pgd_offset(mm, 0xA0000);
 	if (pgd_none_or_clear_bad(pgd))
 		goto out;
 	pud = pud_offset(pgd, 0xA0000);
@@ -153,16 +152,14 @@
 	pmd = pmd_offset(pud, 0xA0000);
 	if (pmd_none_or_clear_bad(pmd))
 		goto out;
-	pte = mapped = pte_offset_map(pmd, 0xA0000);
+	pte = pte_offset_map_lock(mm, pmd, 0xA0000, &ptl);
 	for (i = 0; i < 32; i++) {
 		if (pte_present(*pte))
 			set_pte(pte, pte_wrprotect(*pte));
 		pte++;
 	}
-	pte_unmap(mapped);
+	pte_unmap_unlock(pte, ptl);
 out:
-	spin_unlock(&tsk->mm->page_table_lock);
-	preempt_enable();
 	flush_tlb();
 }
 
@@ -306,7 +303,7 @@
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
 	if (info->flags & VM86_SCREEN_BITMAP)
-		mark_screen_rdonly(tsk);
+		mark_screen_rdonly(tsk->mm);
 	__asm__ __volatile__(
 		"xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t"
 		"movl %0,%%esp\n\t"
diff --git a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h
index 898ed90..f1e3204 100644
--- a/arch/i386/mach-es7000/es7000.h
+++ b/arch/i386/mach-es7000/es7000.h
@@ -24,6 +24,15 @@
  * http://www.unisys.com
  */
 
+/*
+ * ES7000 chipsets
+ */
+
+#define NON_UNISYS		0
+#define ES7000_CLASSIC		1
+#define ES7000_ZORRO		2
+
+
 #define	MIP_REG			1
 #define	MIP_PSAI_REG		4
 
@@ -106,6 +115,6 @@
 
 extern int parse_unisys_oem (char *oemptr);
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
-extern void setup_unisys ();
+extern void setup_unisys(void);
 extern int es7000_start_cpu(int cpu, unsigned long eip);
 extern void es7000_sw_apic(void);
diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
index dc66605..a9ab064 100644
--- a/arch/i386/mach-es7000/es7000plat.c
+++ b/arch/i386/mach-es7000/es7000plat.c
@@ -62,6 +62,9 @@
 static int
 es7000_rename_gsi(int ioapic, int gsi)
 {
+	if (es7000_plat == ES7000_ZORRO)
+		return gsi;
+
 	if (!base) {
 		int i;
 		for (i = 0; i < nr_ioapics; i++)
@@ -76,7 +79,7 @@
 #endif	/* (CONFIG_X86_IO_APIC) && (CONFIG_ACPI) */
 
 void __init
-setup_unisys ()
+setup_unisys(void)
 {
 	/*
 	 * Determine the generation of the ES7000 currently running.
@@ -86,9 +89,9 @@
 	 *
 	 */
 	if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
-		es7000_plat = 2;
+		es7000_plat = ES7000_ZORRO;
 	else
-		es7000_plat = 1;
+		es7000_plat = ES7000_CLASSIC;
 	ioapic_renumber_irq = es7000_rename_gsi;
 }
 
@@ -151,7 +154,7 @@
 	}
 
 	if (success < 2) {
-		es7000_plat = 0;
+		es7000_plat = NON_UNISYS;
 	} else
 		setup_unisys();
 	return es7000_plat;
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 244d8ec..c4af963 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -98,7 +98,7 @@
 
 extern unsigned long find_max_low_pfn(void);
 extern void find_max_pfn(void);
-extern void one_highpage_init(struct page *, int, int);
+extern void add_one_highpage_init(struct page *, int, int);
 
 extern struct e820map e820;
 extern unsigned long init_pg_tables_end;
@@ -427,7 +427,7 @@
 			if (!pfn_valid(node_pfn))
 				continue;
 			page = pfn_to_page(node_pfn);
-			one_highpage_init(page, node_pfn, bad_ppro);
+			add_one_highpage_init(page, node_pfn, bad_ppro);
 		}
 	}
 	totalram_pages += totalhigh_pages;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 9edd448..cf572d9 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -108,7 +108,7 @@
 		desc = (void *)desc + (seg & ~7);
 	} else {
 		/* Must disable preemption while reading the GDT. */
-		desc = (u32 *)&per_cpu(cpu_gdt_table, get_cpu());
+ 		desc = (u32 *)get_cpu_gdt_table(get_cpu());
 		desc = (void *)desc + (seg & ~7);
 	}
 
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 2ebaf75..542d929 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/efi.h>
+#include <linux/memory_hotplug.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -266,17 +267,46 @@
 	pkmap_page_table = pte;	
 }
 
-void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
+void __devinit free_new_highpage(struct page *page)
+{
+	set_page_count(page, 1);
+	__free_page(page);
+	totalhigh_pages++;
+}
+
+void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
 {
 	if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
 		ClearPageReserved(page);
-		set_page_count(page, 1);
-		__free_page(page);
-		totalhigh_pages++;
+		free_new_highpage(page);
 	} else
 		SetPageReserved(page);
 }
 
+static int add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+{
+	free_new_highpage(page);
+	totalram_pages++;
+#ifdef CONFIG_FLATMEM
+	max_mapnr = max(pfn, max_mapnr);
+#endif
+	num_physpages++;
+	return 0;
+}
+
+/*
+ * Not currently handling the NUMA case.
+ * Assuming single node and all memory that
+ * has been added dynamically that would be
+ * onlined here is in HIGHMEM
+ */
+void online_page(struct page *page)
+{
+	ClearPageReserved(page);
+	add_one_highpage_hotplug(page, page_to_pfn(page));
+}
+
+
 #ifdef CONFIG_NUMA
 extern void set_highmem_pages_init(int);
 #else
@@ -284,7 +314,7 @@
 {
 	int pfn;
 	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
-		one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
+		add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
 	totalram_pages += totalhigh_pages;
 }
 #endif /* CONFIG_FLATMEM */
@@ -615,6 +645,28 @@
 #endif
 }
 
+/*
+ * this is for the non-NUMA, single node SMP system case.
+ * Specifically, in the case of x86, we will always add
+ * memory to the highmem for now.
+ */
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+int add_memory(u64 start, u64 size)
+{
+	struct pglist_data *pgdata = &contig_page_data;
+	struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1;
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+
+	return __add_pages(zone, start_pfn, nr_pages);
+}
+
+int remove_memory(u64 start, u64 size)
+{
+	return -EINVAL;
+}
+#endif
+
 kmem_cache_t *pgd_cache;
 kmem_cache_t *pmd_cache;
 
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index f379b8d..5d09de8 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -28,7 +28,7 @@
 	unsigned long pfn;
 
 	pfn = phys_addr >> PAGE_SHIFT;
-	pte = pte_alloc_kernel(&init_mm, pmd, addr);
+	pte = pte_alloc_kernel(pmd, addr);
 	if (!pte)
 		return -ENOMEM;
 	do {
@@ -87,14 +87,12 @@
 	flush_cache_all();
 	phys_addr -= addr;
 	pgd = pgd_offset_k(addr);
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		next = pgd_addr_end(addr, end);
 		err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, flags);
 		if (err)
 			break;
 	} while (pgd++, addr = next, addr != end);
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return err;
 }
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index dcdce2c..9db3242 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -31,11 +31,13 @@
 	pg_data_t *pgdat;
 	unsigned long i;
 	struct page_state ps;
+	unsigned long flags;
 
 	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas();
 	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
+		pgdat_resize_lock(pgdat, &flags);
 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
 			page = pgdat_page_nr(pgdat, i);
 			total++;
@@ -48,6 +50,7 @@
 			else if (page_count(page))
 				shared += page_count(page) - 1;
 		}
+		pgdat_resize_unlock(pgdat, &flags);
 	}
 	printk(KERN_INFO "%d pages of RAM\n", total);
 	printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
@@ -188,19 +191,19 @@
 	struct page *page = virt_to_page(pgd);
 	page->index = (unsigned long)pgd_list;
 	if (pgd_list)
-		pgd_list->private = (unsigned long)&page->index;
+		set_page_private(pgd_list, (unsigned long)&page->index);
 	pgd_list = page;
-	page->private = (unsigned long)&pgd_list;
+	set_page_private(page, (unsigned long)&pgd_list);
 }
 
 static inline void pgd_list_del(pgd_t *pgd)
 {
 	struct page *next, **pprev, *page = virt_to_page(pgd);
 	next = (struct page *)page->index;
-	pprev = (struct page **)page->private;
+	pprev = (struct page **)page_private(page);
 	*pprev = next;
 	if (next)
-		next->private = (unsigned long)pprev;
+		set_page_private(next, (unsigned long)pprev);
 }
 
 void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c
index 65dfd2e..21654be 100644
--- a/arch/i386/oprofile/backtrace.c
+++ b/arch/i386/oprofile/backtrace.c
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <asm/ptrace.h>
+#include <asm/uaccess.h>
 
 struct frame_head {
 	struct frame_head * ebp;
@@ -21,26 +22,22 @@
 static struct frame_head *
 dump_backtrace(struct frame_head * head)
 {
-	oprofile_add_trace(head->ret);
+	struct frame_head bufhead[2];
+
+	/* Also check accessibility of one struct frame_head beyond */
+	if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
+		return NULL;
+	if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+		return NULL;
+
+	oprofile_add_trace(bufhead[0].ret);
 
 	/* frame pointers should strictly progress back up the stack
 	 * (towards higher addresses) */
-	if (head >= head->ebp)
+	if (head >= bufhead[0].ebp)
 		return NULL;
 
-	return head->ebp;
-}
-
-/* check that the page(s) containing the frame head are present */
-static int pages_present(struct frame_head * head)
-{
-	struct mm_struct * mm = current->mm;
-
-	/* FIXME: only necessary once per page */
-	if (!check_user_page_readable(mm, (unsigned long)head))
-		return 0;
-
-	return check_user_page_readable(mm, (unsigned long)(head + 1));
+	return bufhead[0].ebp;
 }
 
 /*
@@ -97,15 +94,6 @@
 		return;
 	}
 
-#ifdef CONFIG_SMP
-	if (!spin_trylock(&current->mm->page_table_lock))
-		return;
-#endif
-
-	while (depth-- && head && pages_present(head))
+	while (depth-- && head)
 		head = dump_backtrace(head);
-
-#ifdef CONFIG_SMP
-	spin_unlock(&current->mm->page_table_lock);
-#endif
 }
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index 8e8e895..330fd2b 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -2,6 +2,8 @@
  * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
  */
 
+#include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include "pci.h"
@@ -384,3 +386,60 @@
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+
+/*
+ * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
+ *
+ * We pretend to bring them out of full D3 state, and restore the proper
+ * IRQ, PCI cache line size, and BARs, otherwise the device won't function
+ * properly.  In some cases, the device will generate an interrupt on
+ * the wrong IRQ line, causing any devices sharing the the line it's
+ * *supposed* to use to be disabled by the kernel's IRQ debug code.
+ */
+static u16 toshiba_line_size;
+
+static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = {
+	{
+		.ident = "Toshiba PS5 based laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"),
+		},
+	},
+	{
+		.ident = "Toshiba PSM4 based laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
+		},
+	},
+	{ }
+};
+
+static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
+{
+	if (!dmi_check_system(toshiba_ohci1394_dmi_table))
+		return; /* only applies to certain Toshibas (so far) */
+
+	dev->current_state = PCI_D3cold;
+	pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
+			 pci_pre_fixup_toshiba_ohci1394);
+
+static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
+{
+	if (!dmi_check_system(toshiba_ohci1394_dmi_table))
+		return; /* only applies to certain Toshibas (so far) */
+
+	/* Restore config space on Toshiba laptops */
+	mdelay(10);
+	pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
+	pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+			       pci_resource_start(dev, 0));
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
+			       pci_resource_start(dev, 1));
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
+			 pci_post_fixup_toshiba_ohci1394);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index cddafe3..19e6f48 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -547,31 +547,48 @@
 	return 0;
 }
 
-static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+static __init int via_router_probe(struct irq_router *r,
+				struct pci_dev *router, u16 device)
 {
 	/* FIXME: We should move some of the quirk fixup stuff here */
 
-	if (router->device == PCI_DEVICE_ID_VIA_82C686 &&
-			device == PCI_DEVICE_ID_VIA_82C586_0) {
-		/* Asus k7m bios wrongly reports 82C686A as 586-compatible */
-		device = PCI_DEVICE_ID_VIA_82C686;
+	/*
+	 * work arounds for some buggy BIOSes
+	 */
+	if (device == PCI_DEVICE_ID_VIA_82C586_0) {
+		switch(router->device) {
+		case PCI_DEVICE_ID_VIA_82C686:
+			/*
+			 * Asus k7m bios wrongly reports 82C686A
+			 * as 586-compatible
+			 */
+			device = PCI_DEVICE_ID_VIA_82C686;
+			break;
+		case PCI_DEVICE_ID_VIA_8235:
+			/**
+			 * Asus a7v-x bios wrongly reports 8235
+			 * as 586-compatible
+			 */
+			device = PCI_DEVICE_ID_VIA_8235;
+			break;
+		}
 	}
 
-	switch(device)
-	{
-		case PCI_DEVICE_ID_VIA_82C586_0:
-			r->name = "VIA";
-			r->get = pirq_via586_get;
-			r->set = pirq_via586_set;
-			return 1;
-		case PCI_DEVICE_ID_VIA_82C596:
-		case PCI_DEVICE_ID_VIA_82C686:
-		case PCI_DEVICE_ID_VIA_8231:
+	switch(device) {
+	case PCI_DEVICE_ID_VIA_82C586_0:
+		r->name = "VIA";
+		r->get = pirq_via586_get;
+		r->set = pirq_via586_set;
+		return 1;
+	case PCI_DEVICE_ID_VIA_82C596:
+	case PCI_DEVICE_ID_VIA_82C686:
+	case PCI_DEVICE_ID_VIA_8231:
+	case PCI_DEVICE_ID_VIA_8235:
 		/* FIXME: add new ones for 8233/5 */
-			r->name = "VIA";
-			r->get = pirq_via_get;
-			r->set = pirq_via_set;
-			return 1;
+		r->name = "VIA";
+		r->get = pirq_via_get;
+		r->set = pirq_via_set;
+		return 1;
 	}
 	return 0;
 }
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index b27c5ac..1f15726 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -51,16 +51,14 @@
 	__save_processor_state(&saved_context);
 }
 
-static void
-do_fpu_end(void)
+static void do_fpu_end(void)
 {
-        /* restore FPU regs if necessary */
-	/* Do it out of line so that gcc does not move cr0 load to some stupid place */
-        kernel_fpu_end();
-	mxcsr_feature_mask_init();
+	/*
+	 * Restore FPU regs if necessary.
+	 */
+	kernel_fpu_end();
 }
 
-
 static void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 945c15a..1642375 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -63,8 +63,6 @@
 	select ACPI
 	select NUMA
 	select ACPI_NUMA
-	select VIRTUAL_MEM_MAP
-	select DISCONTIGMEM
 	help
 	  This selects the system type of your hardware.  A "generic" kernel
 	  will run on any supported IA-64 system.  However, if you configure
@@ -176,40 +174,6 @@
 	default "6" if ITANIUM
 
 # align cache-sensitive data to 64 bytes
-config NUMA
-	bool "NUMA support"
-	depends on !IA64_HP_SIM
-	default y if IA64_SGI_SN2
-	select ACPI_NUMA
-	help
-	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
-	  Access).  This option is for configuring high-end multiprocessor
-	  server systems.  If in doubt, say N.
-
-config VIRTUAL_MEM_MAP
-	bool "Virtual mem map"
-	default y if !IA64_HP_SIM
-	help
-	  Say Y to compile the kernel with support for a virtual mem map.
-	  This code also only takes effect if a memory hole of greater than
-	  1 Gb is found during boot.  You must turn this option on if you
-	  require the DISCONTIGMEM option for your machine. If you are
-	  unsure, say Y.
-
-config HOLES_IN_ZONE
-	bool
-	default y if VIRTUAL_MEM_MAP
-
-config ARCH_DISCONTIGMEM_ENABLE
-	bool "Discontiguous memory support"
-	depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP
-	default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA
-	help
-	  Say Y to support efficient handling of discontiguous physical memory,
-	  for architectures which are either NUMA (Non-Uniform Memory Access)
-	  or have huge holes in the physical address space for other reasons.
-	  See <file:Documentation/vm/numa> for more.
-
 config IA64_CYCLONE
 	bool "Cyclone (EXA) Time Source support"
 	help
@@ -232,8 +196,10 @@
 	  based on a network adapter and DMA messaging.
 
 config FORCE_MAX_ZONEORDER
-	int
-	default "18"
+	int "MAX_ORDER (11 - 17)"  if !HUGETLB_PAGE
+	range 11 17  if !HUGETLB_PAGE
+	default "17" if HUGETLB_PAGE
+	default "11"
 
 config SMP
 	bool "Symmetric multi-processing support"
@@ -254,8 +220,8 @@
 	  If you don't know what to do here, say N.
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-512)"
-	range 2 512
+	int "Maximum number of CPUs (2-1024)"
+	range 2 1024
 	depends on SMP
 	default "64"
 	help
@@ -298,6 +264,58 @@
 
 source "mm/Kconfig"
 
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool y
+	help
+	  Say Y to support efficient handling of discontiguous physical memory,
+	  for architectures which are either NUMA (Non-Uniform Memory Access)
+	  or have huge holes in the physical address space for other reasons.
+ 	  See <file:Documentation/vm/numa> for more.
+
+config ARCH_FLATMEM_ENABLE
+	def_bool y
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	depends on ARCH_DISCONTIGMEM_ENABLE
+
+config ARCH_DISCONTIGMEM_DEFAULT
+	def_bool y if (IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB)
+	depends on ARCH_DISCONTIGMEM_ENABLE
+
+config NUMA
+	bool "NUMA support"
+	depends on !IA64_HP_SIM && !FLATMEM
+	default y if IA64_SGI_SN2
+	help
+	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+	  Access).  This option is for configuring high-end multiprocessor
+	  server systems.  If in doubt, say N.
+
+# VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
+# VIRTUAL_MEM_MAP has been retained for historical reasons.
+config VIRTUAL_MEM_MAP
+	bool "Virtual mem map"
+	depends on !SPARSEMEM
+	default y if !IA64_HP_SIM
+	help
+	  Say Y to compile the kernel with support for a virtual mem map.
+	  This code also only takes effect if a memory hole of greater than
+	  1 Gb is found during boot.  You must turn this option on if you
+	  require the DISCONTIGMEM option for your machine. If you are
+	  unsure, say Y.
+
+config HOLES_IN_ZONE
+	bool
+	default y if VIRTUAL_MEM_MAP
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+	def_bool y
+	depends on NEED_MULTIPLE_NODES
+
 config IA32_SUPPORT
 	bool "Support for Linux/x86 binaries"
 	help
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
index 3b65cbb..b40672b 100644
--- a/arch/ia64/configs/bigsur_defconfig
+++ b/arch/ia64/configs/bigsur_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Mon Nov 29 13:27:48 2004
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:18:49 2005
 #
 
 #
@@ -10,34 +10,40 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -58,12 +64,15 @@
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 # CONFIG_IA64_GENERIC is not set
 CONFIG_IA64_DIG=y
 # CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_HP_SIM is not set
 CONFIG_ITANIUM=y
@@ -72,17 +81,30 @@
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
 CONFIG_IA64_BRL_EMU=y
 CONFIG_IA64_L1_CACHE_SHIFT=6
 # CONFIG_NUMA is not set
 # CONFIG_VIRTUAL_MEM_MAP is not set
 # CONFIG_IA64_CYCLONE is not set
 CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 # CONFIG_HOTPLUG_CPU is not set
+# CONFIG_SCHED_SMT is not set
 CONFIG_PREEMPT=y
+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_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -95,6 +117,7 @@
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 
@@ -102,18 +125,26 @@
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
 
 #
 # Bus options (PCI, PCMCIA)
@@ -122,7 +153,7 @@
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCI Hotplug Support
@@ -135,8 +166,70 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
+# Networking
 #
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# 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 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_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -151,6 +244,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -163,7 +261,13 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -172,14 +276,15 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -189,6 +294,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -211,7 +317,8 @@
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -233,6 +340,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=m
+# 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 is not set
@@ -250,6 +358,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -261,6 +370,7 @@
 # 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
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -274,6 +384,8 @@
 #
 CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -288,18 +400,13 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLOGIC_1280_1040 is not set
@@ -309,7 +416,8 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -332,11 +440,14 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -349,72 +460,14 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP 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_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
@@ -422,6 +475,11 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -443,7 +501,6 @@
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -465,13 +522,17 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -496,6 +557,8 @@
 # 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
@@ -525,18 +588,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -554,6 +605,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -571,7 +633,6 @@
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -579,6 +640,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -603,14 +665,22 @@
 #
 CONFIG_AGP=m
 CONFIG_AGP_I460=m
-CONFIG_DRM=y
+CONFIG_DRM=m
 # CONFIG_DRM_TDFX is not set
 CONFIG_DRM_R128=m
 # CONFIG_DRM_RADEON is not set
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -635,7 +705,7 @@
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
-# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -651,41 +721,16 @@
 # CONFIG_I2C_PCA_ISA is not set
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # 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_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -697,10 +742,55 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 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_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D 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
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -752,11 +842,12 @@
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
 
 #
 # PCI devices
 #
-CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -768,6 +859,8 @@
 # CONFIG_SND_CS46XX is not set
 CONFIG_SND_CS4281=m
 # CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
 # CONFIG_SND_KORG1212 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -775,9 +868,10 @@
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
 # CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_AD1889 is not set
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
@@ -791,13 +885,14 @@
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_SONICVIBES is not set
 # CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
 
 #
 # USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
 
 #
 # Open Sound System
@@ -807,6 +902,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -818,35 +915,38 @@
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_OHCI_HCD is not set
 CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
 #
-CONFIG_USB_AUDIO=m
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_BLUETOOTH_TTY=m
-CONFIG_USB_MIDI=m
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -863,19 +963,23 @@
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -894,6 +998,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -909,7 +1014,6 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -918,10 +1022,12 @@
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -930,10 +1036,25 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -945,17 +1066,20 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=y
-# CONFIG_XFS_RT is not set
+CONFIG_XFS_EXPORT=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -982,14 +1106,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1013,15 +1134,18 @@
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1031,9 +1155,11 @@
 CONFIG_CIFS_STATS=y
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # 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
@@ -1103,8 +1229,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Profiling support
@@ -1115,14 +1245,20 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
 # CONFIG_IA64_GRANULE_16MB is not set
 CONFIG_IA64_GRANULE_64MB=y
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1149,6 +1285,7 @@
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -1164,3 +1301,7 @@
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
new file mode 100644
index 0000000..80f8663
--- /dev/null
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -0,0 +1,1319 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Wed Sep 28 08:27:29 2005
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
+CONFIG_FORCE_MAX_ZONEORDER=17
+CONFIG_SMP=y
+CONFIG_NR_CPUS=512
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NUMA=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_IA64_MCA_RECOVERY=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=m
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HOTPLUG_PCI_SGI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+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 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# 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=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK 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
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# 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 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SGIIOC4=y
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_MV is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+CONFIG_SCSI_SATA_VITESSE=y
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_QLOGIC_1280_1040 is not set
+CONFIG_SCSI_QLA2XXX=y
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_HP100 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=m
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# 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=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+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
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_FM801 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_SGI_L1_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_SGI_IOC4=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 is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_I460=m
+CONFIG_AGP_HP_ZX1=m
+CONFIG_AGP_SGI_TIOCA=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_MMTIMER=y
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_GENERIC_DRIVER=y
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS4281=m
+CONFIG_SND_EMU10K1=m
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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=m
+# 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
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_MON=y
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+# CONFIG_INFINIBAND_USER_MAD is not set
+# CONFIG_INFINIBAND_USER_ACCESS is not set
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# 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
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index d452e18..9bc8bca 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6-tiger-smp
-# Wed Aug 17 10:19:51 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:17:57 2005
 #
 
 #
@@ -16,6 +16,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -27,6 +28,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
@@ -103,6 +105,7 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -115,6 +118,7 @@
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 
@@ -122,20 +126,27 @@
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
-# CONFIG_ACPI_HOTPLUG_CPU is not set
+CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_CONTAINER is not set
+CONFIG_ACPI_CONTAINER=m
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
 
 #
 # Bus options (PCI, PCMCIA)
@@ -144,7 +155,6 @@
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -188,14 +198,19 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
 #
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
@@ -218,9 +233,11 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -235,6 +252,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -247,7 +269,13 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -266,7 +294,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -299,7 +326,8 @@
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -339,6 +367,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -366,6 +395,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -454,6 +484,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
@@ -461,6 +492,11 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -481,6 +517,7 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -512,6 +549,7 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -521,6 +559,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -618,6 +657,7 @@
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
@@ -675,6 +715,7 @@
 CONFIG_DRM_MGA=m
 CONFIG_DRM_SIS=m
 # CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
@@ -691,7 +732,6 @@
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -702,6 +742,7 @@
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -709,6 +750,10 @@
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -800,9 +845,11 @@
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -902,16 +949,12 @@
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 CONFIG_XFS_FS=y
 CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
@@ -919,6 +962,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -947,13 +991,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1003,6 +1045,7 @@
 # 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
@@ -1072,10 +1115,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Profiling support
@@ -1089,6 +1134,7 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 80b0e9e..0856ca6 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6
-# Wed Aug 17 10:02:43 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:15:01 2005
 #
 
 #
@@ -18,6 +18,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -29,6 +30,7 @@
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
@@ -103,6 +105,7 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -115,6 +118,7 @@
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
@@ -122,28 +126,34 @@
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
 CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
 # CONFIG_ACPI_CONTAINER is not set
 
 #
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
 # Bus options (PCI, PCMCIA)
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -187,8 +197,8 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 
@@ -204,7 +214,6 @@
 # IP: Netfilter Configuration
 #
 # CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
 # CONFIG_IP_NF_QUEUE is not set
 # CONFIG_IP_NF_IPTABLES is not set
 CONFIG_IP_NF_ARPTABLES=y
@@ -212,6 +221,11 @@
 # CONFIG_IP_NF_ARP_MANGLE is not set
 
 #
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
@@ -234,9 +248,11 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -251,6 +267,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -263,7 +284,13 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -282,7 +309,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -315,7 +341,8 @@
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -354,6 +381,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -381,6 +409,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -457,6 +486,7 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
@@ -464,6 +494,11 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -485,6 +520,7 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -516,6 +552,7 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -525,6 +562,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -650,12 +688,12 @@
 CONFIG_AGP_HP_ZX1=y
 CONFIG_DRM=y
 # CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_GAMMA is not set
 # CONFIG_DRM_R128 is not set
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 # CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HPET is not set
 # CONFIG_HANGCHECK_TIMER is not set
@@ -689,7 +727,6 @@
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_ISA is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -703,7 +740,6 @@
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Miscellaneous I2C Chip support
@@ -730,12 +766,17 @@
 # Hardware Monitoring support
 #
 # CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
 
 #
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 CONFIG_VIDEO_DEV=y
@@ -806,6 +847,7 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_PM3 is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -862,11 +904,12 @@
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
 
 #
 # PCI devices
 #
-CONFIG_SND_AC97_CODEC=y
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -890,7 +933,7 @@
 # CONFIG_SND_HDSPM is not set
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_AD1889 is not set
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
@@ -952,9 +995,8 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -971,6 +1013,7 @@
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -987,9 +1030,11 @@
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -1088,10 +1133,6 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1100,6 +1141,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1126,13 +1168,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1177,6 +1217,7 @@
 # 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
@@ -1246,10 +1287,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Profiling support
@@ -1263,6 +1306,7 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 5da2081..6e3f147 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12
-# Tue Jun 21 11:30:42 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 15:13:03 2005
 #
 
 #
@@ -16,6 +16,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -27,6 +28,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
@@ -80,6 +82,10 @@
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
 CONFIG_IA64_L1_CACHE_SHIFT=7
 CONFIG_NUMA=y
 CONFIG_VIRTUAL_MEM_MAP=y
@@ -87,12 +93,21 @@
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_IA64_CYCLONE=y
 CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
+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_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -105,6 +120,7 @@
 #
 CONFIG_EFI_VARS=y
 CONFIG_EFI_PCDP=y
+# CONFIG_DELL_RBU is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 
@@ -112,30 +128,36 @@
 # Power management and ACPI
 #
 CONFIG_PM=y
-CONFIG_ACPI=y
+# CONFIG_PM_DEBUG is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
+CONFIG_ACPI=y
 CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_THERMAL=m
 CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
 CONFIG_ACPI_CONTAINER=m
 
 #
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
 # Bus options (PCI, PCMCIA)
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -147,6 +169,7 @@
 # CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_HOTPLUG_PCI_SGI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -154,6 +177,73 @@
 # CONFIG_PCCARD is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+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 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
 # Device Drivers
 #
 
@@ -162,10 +252,15 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -178,7 +273,13 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
 
 #
 # Block devices
@@ -197,7 +298,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -230,7 +330,8 @@
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -252,6 +353,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# 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 is not set
@@ -270,6 +372,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -297,6 +400,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -314,6 +418,7 @@
 # CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 # CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
@@ -335,7 +440,6 @@
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLOGIC_1280_1040 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -344,6 +448,7 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -390,74 +495,14 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_ARPD=y
-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 is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
 
 #
 # ARCnet devices
@@ -465,6 +510,11 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -485,6 +535,7 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -516,6 +567,7 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -525,6 +577,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -549,6 +602,10 @@
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -607,9 +664,7 @@
 # CONFIG_GAMEPORT_NS558 is not set
 # CONFIG_GAMEPORT_L4 is not set
 # CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
 # CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461X is not set
 
 #
 # Character devices
@@ -620,6 +675,7 @@
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
@@ -641,7 +697,6 @@
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -650,8 +705,8 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
-CONFIG_SERIAL_SGI_IOC4=y
 # CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_SGI_IOC4=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -684,6 +739,8 @@
 CONFIG_DRM_RADEON=m
 CONFIG_DRM_MGA=m
 CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_HPET=y
 # CONFIG_HPET_RTC_IRQ is not set
@@ -708,10 +765,21 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -753,6 +821,7 @@
 CONFIG_SND_SEQUENCER_OSS=y
 CONFIG_SND_VERBOSE_PRINTK=y
 # CONFIG_SND_DEBUG is not set
+CONFIG_SND_GENERIC_DRIVER=y
 
 #
 # Generic devices
@@ -764,11 +833,12 @@
 CONFIG_SND_MTPAV=m
 CONFIG_SND_SERIAL_U16550=m
 CONFIG_SND_MPU401=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
 
 #
 # PCI devices
 #
-CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -790,9 +860,10 @@
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
 # CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_AD1889 is not set
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_ENS1370 is not set
 # CONFIG_SND_ENS1371 is not set
@@ -844,6 +915,7 @@
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
@@ -853,9 +925,8 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -888,12 +959,17 @@
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -918,7 +994,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=m
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -944,10 +1020,11 @@
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -964,6 +1041,8 @@
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
+# CONFIG_INFINIBAND_USER_MAD is not set
+# CONFIG_INFINIBAND_USER_ACCESS is not set
 CONFIG_INFINIBAND_MTHCA=m
 # CONFIG_INFINIBAND_MTHCA_DEBUG is not set
 CONFIG_INFINIBAND_IPOIB=m
@@ -981,6 +1060,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -996,22 +1076,20 @@
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 CONFIG_XFS_FS=y
 CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1040,14 +1118,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1071,15 +1146,18 @@
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1094,6 +1172,7 @@
 # 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
@@ -1163,10 +1242,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # HP Simulator drivers
@@ -1187,6 +1268,7 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=20
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1194,6 +1276,7 @@
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_KPROBES is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1215,7 +1298,7 @@
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 80f8ef0..a5a5637 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -17,7 +17,7 @@
 #include <asm/machvec.h>
 
 /* swiotlb declarations & definitions: */
-extern void swiotlb_init_with_default_size (size_t size);
+extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent	swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent	swiotlb_free_coherent;
 extern ia64_mv_dma_map_single		swiotlb_map_single;
@@ -67,11 +67,20 @@
 hwsw_init (void)
 {
 	/* default to a smallish 2MB sw I/O TLB */
-	swiotlb_init_with_default_size (2 * (1<<20));
+	if (swiotlb_late_init_with_default_size (2 * (1<<20)) != 0) {
+#ifdef CONFIG_IA64_GENERIC
+		/* Better to have normal DMA than panic */
+		printk(KERN_WARNING "%s: Failed to initialize software I/O TLB,"
+		       " reverting to hpzx1 platform vector\n", __FUNCTION__);
+		machvec_init("hpzx1");
+#else
+		panic("Unable to initialize software I/O TLB services");
+#endif
+	}
 }
 
 void *
-hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
+hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
 {
 	if (use_swiotlb(dev))
 		return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 1195759..bdccd0b 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1076,7 +1076,7 @@
  * See Documentation/DMA-mapping.txt
  */
 void *
-sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
+sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
 {
 	struct ioc *ioc;
 	void *addr;
@@ -2028,10 +2028,41 @@
 static int __init
 sba_init(void)
 {
-	acpi_bus_register_driver(&acpi_sba_ioc_driver);
-	if (!ioc_list)
+	if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
 		return 0;
 
+	acpi_bus_register_driver(&acpi_sba_ioc_driver);
+	if (!ioc_list) {
+#ifdef CONFIG_IA64_GENERIC
+		extern int swiotlb_late_init_with_default_size (size_t size);
+
+		/*
+		 * If we didn't find something sba_iommu can claim, we
+		 * need to setup the swiotlb and switch to the dig machvec.
+		 */
+		if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
+			panic("Unable to find SBA IOMMU or initialize "
+			      "software I/O TLB: Try machvec=dig boot option");
+		machvec_init("dig");
+#else
+		panic("Unable to find SBA IOMMU: Try a generic or DIG kernel");
+#endif
+		return 0;
+	}
+
+#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
+	/*
+	 * hpzx1_swiotlb needs to have a fairly small swiotlb bounce
+	 * buffer setup to support devices with smaller DMA masks than
+	 * sba_iommu can handle.
+	 */
+	if (ia64_platform_is("hpzx1_swiotlb")) {
+		extern void hwsw_init(void);
+
+		hwsw_init();
+	}
+#endif
+
 #ifdef CONFIG_PCI
 	{
 		struct pci_bus *b = NULL;
@@ -2048,18 +2079,6 @@
 
 subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */
 
-extern void dig_setup(char**);
-/*
- * MAX_DMA_ADDRESS needs to be setup prior to paging_init to do any good,
- * so we use the platform_setup hook to fix it up.
- */
-void __init
-sba_setup(char **cmdline_p)
-{
-	MAX_DMA_ADDRESS = ~0UL;
-	dig_setup(cmdline_p);
-}
-
 static int __init
 nosbagart(char *str)
 {
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index a18983a..a3fe975 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -205,10 +205,11 @@
 	char buf[512];
 
 	/*
-	 * This is a bit kludgey: the simulator doesn't provide a direct way of determining
-	 * the disk size, so we do a binary search, assuming a maximum disk size of 4GB.
+	 * This is a bit kludgey: the simulator doesn't provide a
+	 * direct way of determining the disk size, so we do a binary
+	 * search, assuming a maximum disk size of 128GB.
 	 */
-	for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) {
+	for (bit = (128UL << 30)/512; bit != 0; bit >>= 1) {
 		req.addr = __pa(&buf);
 		req.len = sizeof(buf);
 		ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
@@ -225,8 +226,10 @@
 {
 	unsigned long offset;
 
-	offset = (  (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16)
-		  | (sc->cmnd[4] <<  8) | (sc->cmnd[5] <<  0))*512;
+	offset = (((unsigned long)sc->cmnd[2] << 24) 
+		| ((unsigned long)sc->cmnd[3] << 16)
+		| ((unsigned long)sc->cmnd[4] <<  8) 
+		| ((unsigned long)sc->cmnd[5] <<  0))*512UL;
 	if (sc->use_sg > 0)
 		simscsi_sg_readwrite(sc, mode, offset);
 	else
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 3fa67ec..dc28271 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -36,6 +36,7 @@
 #include <linux/uio.h>
 #include <linux/nfs_fs.h>
 #include <linux/quota.h>
+#include <linux/syscalls.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 7e92647..9ad94dd 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -838,7 +838,7 @@
 #endif				/* CONFIG_ACPI_HOTPLUG_CPU */
 
 #ifdef CONFIG_ACPI_NUMA
-acpi_status __devinit
+static acpi_status __devinit
 acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -890,7 +890,16 @@
 	map_iosapic_to_node(gsi_base, node);
 	return AE_OK;
 }
-#endif				/* CONFIG_NUMA */
+
+static int __init
+acpi_map_iosapics (void)
+{
+	acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
+	return 0;
+}
+
+fs_initcall(acpi_map_iosapics);
+#endif				/* CONFIG_ACPI_NUMA */
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index 768c7e4..6ade379 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -2,6 +2,7 @@
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/errno.h>
+#include <linux/timex.h>
 #include <asm/io.h>
 
 /* IBM Summit (EXA) Cyclone counter code*/
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 179f230..f72ea6a 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -239,57 +239,30 @@
 	return 0;
 }
 
-/*
- * Trim descriptor MD so its starts at address START_ADDR.  If the descriptor covers
- * memory that is normally available to the kernel, issue a warning that some memory
- * is being ignored.
- */
-static void
-trim_bottom (efi_memory_desc_t *md, u64 start_addr)
-{
-	u64 num_skipped_pages;
+typedef struct kern_memdesc {
+	u64 attribute;
+	u64 start;
+	u64 num_pages;
+} kern_memdesc_t;
 
-	if (md->phys_addr >= start_addr || !md->num_pages)
-		return;
-
-	num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
-	if (num_skipped_pages > md->num_pages)
-		num_skipped_pages = md->num_pages;
-
-	if (is_available_memory(md))
-		printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
-		       "at 0x%lx\n", __FUNCTION__,
-		       (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
-		       md->phys_addr, start_addr - IA64_GRANULE_SIZE);
-	/*
-	 * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
-	 * descriptor list to become unsorted.  In such a case, md->num_pages will be
-	 * zero, so the Right Thing will happen.
-	 */
-	md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
-	md->num_pages -= num_skipped_pages;
-}
+static kern_memdesc_t *kern_memmap;
 
 static void
-trim_top (efi_memory_desc_t *md, u64 end_addr)
+walk (efi_freemem_callback_t callback, void *arg, u64 attr)
 {
-	u64 num_dropped_pages, md_end_addr;
+	kern_memdesc_t *k;
+	u64 start, end, voff;
 
-	md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
-
-	if (md_end_addr <= end_addr || !md->num_pages)
-		return;
-
-	num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
-	if (num_dropped_pages > md->num_pages)
-		num_dropped_pages = md->num_pages;
-
-	if (is_available_memory(md))
-		printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
-		       "at 0x%lx\n", __FUNCTION__,
-		       (num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
-		       md->phys_addr, end_addr);
-	md->num_pages -= num_dropped_pages;
+	voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET;
+	for (k = kern_memmap; k->start != ~0UL; k++) {
+		if (k->attribute != attr)
+			continue;
+		start = PAGE_ALIGN(k->start);
+		end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK;
+		if (start < end)
+			if ((*callback)(start + voff, end + voff, arg) < 0)
+				return;
+	}
 }
 
 /*
@@ -299,148 +272,19 @@
 void
 efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
 {
-	int prev_valid = 0;
-	struct range {
-		u64 start;
-		u64 end;
-	} prev, curr;
-	void *efi_map_start, *efi_map_end, *p, *q;
-	efi_memory_desc_t *md, *check_md;
-	u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0;
-	unsigned long total_mem = 0;
-
-	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;
-
-		/* skip over non-WB memory descriptors; that's all we're interested in... */
-		if (!(md->attribute & EFI_MEMORY_WB))
-			continue;
-
-		/*
-		 * granule_addr is the base of md's first granule.
-		 * [granule_addr - first_non_wb_addr) is guaranteed to
-		 * be contiguous WB memory.
-		 */
-		granule_addr = GRANULEROUNDDOWN(md->phys_addr);
-		first_non_wb_addr = max(first_non_wb_addr, granule_addr);
-
-		if (first_non_wb_addr < md->phys_addr) {
-			trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
-			granule_addr = GRANULEROUNDDOWN(md->phys_addr);
-			first_non_wb_addr = max(first_non_wb_addr, granule_addr);
-		}
-
-		for (q = p; q < efi_map_end; q += efi_desc_size) {
-			check_md = q;
-
-			if ((check_md->attribute & EFI_MEMORY_WB) &&
-			    (check_md->phys_addr == first_non_wb_addr))
-				first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
-			else
-				break;		/* non-WB or hole */
-		}
-
-		last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr);
-		if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
-			trim_top(md, last_granule_addr);
-
-		if (is_available_memory(md)) {
-			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) {
-				if (md->phys_addr >= max_addr)
-					continue;
-				md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
-				first_non_wb_addr = max_addr;
-			}
-
-			if (total_mem >= mem_limit)
-				continue;
-
-			if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
-				unsigned long limit_addr = md->phys_addr;
-
-				limit_addr += mem_limit - total_mem;
-				limit_addr = GRANULEROUNDDOWN(limit_addr);
-
-				if (md->phys_addr > limit_addr)
-					continue;
-
-				md->num_pages = (limit_addr - md->phys_addr) >>
-				                EFI_PAGE_SHIFT;
-				first_non_wb_addr = max_addr = md->phys_addr +
-				              (md->num_pages << EFI_PAGE_SHIFT);
-			}
-			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
-
-			if (md->num_pages == 0)
-				continue;
-
-			curr.start = PAGE_OFFSET + md->phys_addr;
-			curr.end   = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
-
-			if (!prev_valid) {
-				prev = curr;
-				prev_valid = 1;
-			} else {
-				if (curr.start < prev.start)
-					printk(KERN_ERR "Oops: EFI memory table not ordered!\n");
-
-				if (prev.end == curr.start) {
-					/* merge two consecutive memory ranges */
-					prev.end = curr.end;
-				} else {
-					start = PAGE_ALIGN(prev.start);
-					end = prev.end & PAGE_MASK;
-					if ((end > start) && (*callback)(start, end, arg) < 0)
-						return;
-					prev = curr;
-				}
-			}
-		}
-	}
-	if (prev_valid) {
-		start = PAGE_ALIGN(prev.start);
-		end = prev.end & PAGE_MASK;
-		if (end > start)
-			(*callback)(start, end, arg);
-	}
+	walk(callback, arg, EFI_MEMORY_WB);
 }
 
 /*
- * Walk the EFI memory map to pull out leftover pages in the lower
- * memory regions which do not end up in the regular memory map and
- * stick them into the uncached allocator
- *
- * The regular walk function is significantly more complex than the
- * uncached walk which means it really doesn't make sense to try and
- * marge the two.
+ * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
+ * has memory that is available for uncached allocator.
  */
-void __init
-efi_memmap_walk_uc (efi_freemem_callback_t callback)
+void
+efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
 {
-	void *efi_map_start, *efi_map_end, *p;
-	efi_memory_desc_t *md;
-	u64 efi_desc_size, start, end;
-
-	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 (md->attribute == EFI_MEMORY_UC) {
-			start = PAGE_ALIGN(md->phys_addr);
-			end = PAGE_ALIGN((md->phys_addr+(md->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK);
-			if ((*callback)(start, end, NULL) < 0)
-				return;
-		}
-	}
+	walk(callback, arg, EFI_MEMORY_UC);
 }
 
-
 /*
  * Look for the PAL_CODE region reported by EFI and maps it using an
  * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
@@ -862,3 +706,307 @@
 	printk(KERN_ERR "Malformed %s value\n", name);
 	return 0;
 }
+
+#define efi_md_size(md)	(md->num_pages << EFI_PAGE_SHIFT)
+
+static inline u64
+kmd_end(kern_memdesc_t *kmd)
+{
+	return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT));
+}
+
+static inline u64
+efi_md_end(efi_memory_desc_t *md)
+{
+	return (md->phys_addr + efi_md_size(md));
+}
+
+static inline int
+efi_wb(efi_memory_desc_t *md)
+{
+	return (md->attribute & EFI_MEMORY_WB);
+}
+
+static inline int
+efi_uc(efi_memory_desc_t *md)
+{
+	return (md->attribute & EFI_MEMORY_UC);
+}
+
+/*
+ * Look for the first granule aligned memory descriptor memory
+ * that is big enough to hold EFI memory map. Make sure this
+ * descriptor is atleast granule sized so it does not get trimmed
+ */
+struct kern_memdesc *
+find_memmap_space (void)
+{
+	u64	contig_low=0, contig_high=0;
+	u64	as = 0, ae;
+	void *efi_map_start, *efi_map_end, *p, *q;
+	efi_memory_desc_t *md, *pmd = NULL, *check_md;
+	u64	space_needed, efi_desc_size;
+	unsigned long total_mem = 0;
+
+	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;
+
+	/*
+	 * Worst case: we need 3 kernel descriptors for each efi descriptor
+	 * (if every entry has a WB part in the middle, and UC head and tail),
+	 * plus one for the end marker.
+	 */
+	space_needed = sizeof(kern_memdesc_t) *
+		(3 * (ia64_boot_param->efi_memmap_size/efi_desc_size) + 1);
+
+	for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
+		md = p;
+		if (!efi_wb(md)) {
+			continue;
+		}
+		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) {
+				check_md = q;
+				if (!efi_wb(check_md))
+					break;
+				if (contig_high != check_md->phys_addr)
+					break;
+				contig_high = efi_md_end(check_md);
+			}
+			contig_high = GRANULEROUNDDOWN(contig_high);
+		}
+		if (!is_available_memory(md) || md->type == EFI_LOADER_DATA)
+			continue;
+
+		/* Round ends inward to granule boundaries */
+		as = max(contig_low, md->phys_addr);
+		ae = min(contig_high, efi_md_end(md));
+
+		/* keep within max_addr= command line arg */
+		ae = min(ae, max_addr);
+		if (ae <= as)
+			continue;
+
+		/* avoid going over mem= command line arg */
+		if (total_mem + (ae - as) > mem_limit)
+			ae -= total_mem + (ae - as) - mem_limit;
+
+		if (ae <= as)
+			continue;
+
+		if (ae - as > space_needed)
+			break;
+	}
+	if (p >= efi_map_end)
+		panic("Can't allocate space for kernel memory descriptors");
+
+	return __va(as);
+}
+
+/*
+ * Walk the EFI memory map and gather all memory available for kernel
+ * to use.  We can allocate partial granules only if the unavailable
+ * parts exist, and are WB.
+ */
+void
+efi_memmap_init(unsigned long *s, unsigned long *e)
+{
+	struct kern_memdesc *k, *prev = 0;
+	u64	contig_low=0, contig_high=0;
+	u64	as, ae, lim;
+	void *efi_map_start, *efi_map_end, *p, *q;
+	efi_memory_desc_t *md, *pmd = NULL, *check_md;
+	u64	efi_desc_size;
+	unsigned long total_mem = 0;
+
+	k = kern_memmap = find_memmap_space();
+
+	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; 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)) {
+				k->attribute = EFI_MEMORY_UC;
+				k->start = md->phys_addr;
+				k->num_pages = md->num_pages;
+				k++;
+			}
+			continue;
+		}
+		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) {
+				check_md = q;
+				if (!efi_wb(check_md))
+					break;
+				if (contig_high != check_md->phys_addr)
+					break;
+				contig_high = efi_md_end(check_md);
+			}
+			contig_high = GRANULEROUNDDOWN(contig_high);
+		}
+		if (!is_available_memory(md))
+			continue;
+
+		/*
+		 * Round ends inward to granule boundaries
+		 * Give trimmings to uncached allocator
+		 */
+		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 &&
+				    kmd_end(k-1) == md->phys_addr) {
+					(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++;
+				}
+			}
+			as = contig_low;
+		} else
+			as = md->phys_addr;
+
+		if (efi_md_end(md) > contig_high) {
+			lim = max(md->phys_addr, contig_high);
+			if (efi_uc(md)) {
+				if (lim == md->phys_addr && k > kern_memmap &&
+				    (k-1)->attribute == EFI_MEMORY_UC &&
+				    kmd_end(k-1) == md->phys_addr) {
+					(k-1)->num_pages += md->num_pages;
+				} else {
+					k->attribute = EFI_MEMORY_UC;
+					k->start = lim;
+					k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT;
+					k++;
+				}
+			}
+			ae = contig_high;
+		} else
+			ae = efi_md_end(md);
+
+		/* keep within max_addr= command line arg */
+		ae = min(ae, max_addr);
+		if (ae <= as)
+			continue;
+
+		/* avoid going over mem= command line arg */
+		if (total_mem + (ae - as) > mem_limit)
+			ae -= total_mem + (ae - as) - mem_limit;
+
+		if (ae <= as)
+			continue;
+		if (prev && kmd_end(prev) == md->phys_addr) {
+			prev->num_pages += (ae - as) >> EFI_PAGE_SHIFT;
+			total_mem += ae - as;
+			continue;
+		}
+		k->attribute = EFI_MEMORY_WB;
+		k->start = as;
+		k->num_pages = (ae - as) >> EFI_PAGE_SHIFT;
+		total_mem += ae - as;
+		prev = k++;
+	}
+	k->start = ~0L; /* end-marker */
+
+	/* reserve the memory we are using for kern_memmap */
+	*s = (u64)kern_memmap;
+	*e = (u64)++k;
+}
+
+void
+efi_initialize_iomem_resources(struct resource *code_resource,
+			       struct resource *data_resource)
+{
+	struct resource *res;
+	void *efi_map_start, *efi_map_end, *p;
+	efi_memory_desc_t *md;
+	u64 efi_desc_size;
+	char *name;
+	unsigned long flags;
+
+	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;
+
+	res = NULL;
+
+	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+		md = p;
+
+		if (md->num_pages == 0) /* should not happen */
+			continue;
+
+		flags = IORESOURCE_MEM;
+		switch (md->type) {
+
+			case EFI_MEMORY_MAPPED_IO:
+			case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+				continue;
+
+			case EFI_LOADER_CODE:
+			case EFI_LOADER_DATA:
+			case EFI_BOOT_SERVICES_DATA:
+			case EFI_BOOT_SERVICES_CODE:
+			case EFI_CONVENTIONAL_MEMORY:
+				if (md->attribute & EFI_MEMORY_WP) {
+					name = "System ROM";
+					flags |= IORESOURCE_READONLY;
+				} else {
+					name = "System RAM";
+				}
+				break;
+
+			case EFI_ACPI_MEMORY_NVS:
+				name = "ACPI Non-volatile Storage";
+				flags |= IORESOURCE_BUSY;
+				break;
+
+			case EFI_UNUSABLE_MEMORY:
+				name = "reserved";
+				flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED;
+				break;
+
+			case EFI_RESERVED_TYPE:
+			case EFI_RUNTIME_SERVICES_CODE:
+			case EFI_RUNTIME_SERVICES_DATA:
+			case EFI_ACPI_RECLAIM_MEMORY:
+			default:
+				name = "reserved";
+				flags |= IORESOURCE_BUSY;
+				break;
+		}
+
+		if ((res = kcalloc(1, sizeof(struct resource), GFP_KERNEL)) == NULL) {
+			printk(KERN_ERR "failed to alocate resource for iomem\n");
+			return;
+		}
+
+		res->name = name;
+		res->start = md->phys_addr;
+		res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+		res->flags = flags;
+
+		if (insert_resource(&iomem_resource, res) < 0)
+			kfree(res);
+		else {
+			/*
+			 * We don't know which region contains
+			 * kernel data so we try it repeatedly and
+			 * let the resource manager test it.
+			 */
+			insert_resource(res, code_resource);
+			insert_resource(res, data_resource);
+		}
+	}
+}
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 205d980..d33244c 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -57,9 +57,9 @@
 
 	if (i == 0) {
 		seq_printf(p, "           ");
-		for (j=0; j<NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%d       ",j);
+		for_each_online_cpu(j) {
+			seq_printf(p, "CPU%d       ",j);
+		}
 		seq_putc(p, '\n');
 	}
 
@@ -72,9 +72,9 @@
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		for_each_online_cpu(j) {
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		}
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %s", action->name);
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index d0a5106..52c47da 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -508,9 +508,7 @@
 	int cpu;
 
 	/* Clear the Rendez checkin flag for all cpus */
-	for(cpu = 0; cpu < NR_CPUS; cpu++) {
-		if (!cpu_online(cpu))
-			continue;
+	for_each_online_cpu(cpu) {
 		if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)
 			ia64_mca_wakeup(cpu);
 	}
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index f1aca7c..7a2f0a7 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -947,8 +947,8 @@
 percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
 {
 	unsigned int i;
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_possible(i))
-			memcpy(pcpudst + __per_cpu_offset[i], src, size);
+	for_each_cpu(i) {
+		memcpy(pcpudst + __per_cpu_offset[i], src, size);
+	}
 }
 #endif /* CONFIG_SMP */
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
index 367804a..6a4ac7d 100644
--- a/arch/ia64/kernel/patch.c
+++ b/arch/ia64/kernel/patch.c
@@ -64,22 +64,30 @@
 void
 ia64_patch_imm64 (u64 insn_addr, u64 val)
 {
-	ia64_patch(insn_addr,
+	/* The assembler may generate offset pointing to either slot 1
+	   or slot 2 for a long (2-slot) instruction, occupying slots 1
+	   and 2.  */
+  	insn_addr &= -16UL;
+	ia64_patch(insn_addr + 2,
 		   0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
 				     | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
 				     | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
 				     | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
 				     | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
-	ia64_patch(insn_addr - 1, 0x1ffffffffffUL, val >> 22);
+	ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
 }
 
 void
 ia64_patch_imm60 (u64 insn_addr, u64 val)
 {
-	ia64_patch(insn_addr,
+	/* The assembler may generate offset pointing to either slot 1
+	   or slot 2 for a long (2-slot) instruction, occupying slots 1
+	   and 2.  */
+  	insn_addr &= -16UL;
+	ia64_patch(insn_addr + 2,
 		   0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
 				     | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
-	ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
+	ia64_patch(insn_addr + 1, 0x1fffffffffcUL, val >> 18);
 }
 
 /*
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index d71731e..f7dfc10 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2352,7 +2352,8 @@
 	insert_vm_struct(mm, vma);
 
 	mm->total_vm  += size >> PAGE_SHIFT;
-	vm_stat_account(vma);
+	vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
+							vma_pages(vma));
 	up_write(&task->mm->mmap_sem);
 
 	/*
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index bbb8bc7..4b19d04 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -587,8 +587,9 @@
 static struct task_struct *
 find_thread_for_addr (struct task_struct *child, unsigned long addr)
 {
-	struct task_struct *g, *p;
+	struct task_struct *p;
 	struct mm_struct *mm;
+	struct list_head *this, *next;
 	int mm_users;
 
 	if (!(mm = get_task_mm(child)))
@@ -600,28 +601,21 @@
 		goto out;		/* not multi-threaded */
 
 	/*
-	 * First, traverse the child's thread-list.  Good for scalability with
-	 * NPTL-threads.
+	 * Traverse the current process' children list.  Every task that
+	 * one attaches to becomes a child.  And it is only attached children
+	 * of the debugger that are of interest (ptrace_check_attach checks
+	 * for this).
 	 */
-	p = child;
-	do {
-		if (thread_matches(p, addr)) {
-			child = p;
-			goto out;
-		}
-		if (mm_users-- <= 1)
-			goto out;
-	} while ((p = next_thread(p)) != child);
-
-	do_each_thread(g, p) {
-		if (child->mm != mm)
+ 	list_for_each_safe(this, next, &current->children) {
+		p = list_entry(this, struct task_struct, sibling);
+		if (p->mm != mm)
 			continue;
-
 		if (thread_matches(p, addr)) {
 			child = p;
 			goto out;
 		}
-	} while_each_thread(g, p);
+	}
+
   out:
 	mmput(mm);
 	return child;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 1f5c26d..fc56ca2 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -78,6 +78,19 @@
 unsigned long vga_console_iobase;
 unsigned long vga_console_membase;
 
+static struct resource data_resource = {
+	.name	= "Kernel data",
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+	.name	= "Kernel code",
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+extern void efi_initialize_iomem_resources(struct resource *,
+		struct resource *);
+extern char _text[], _end[], _etext[];
+
 unsigned long ia64_max_cacheline_size;
 unsigned long ia64_iobase;	/* virtual address for I/O accesses */
 EXPORT_SYMBOL(ia64_iobase);
@@ -171,6 +184,22 @@
 	}
 }
 
+/*
+ * Request address space for all standard resources
+ */
+static int __init register_memory(void)
+{
+	code_resource.start = ia64_tpa(_text);
+	code_resource.end   = ia64_tpa(_etext) - 1;
+	data_resource.start = ia64_tpa(_etext);
+	data_resource.end   = ia64_tpa(_end) - 1;
+	efi_initialize_iomem_resources(&code_resource, &data_resource);
+
+	return 0;
+}
+
+__initcall(register_memory);
+
 /**
  * reserve_memory - setup reserved memory areas
  *
@@ -211,6 +240,9 @@
 	}
 #endif
 
+	efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
+	n++;
+
 	/* end of memory marker */
 	rsvd_region[n].start = ~0UL;
 	rsvd_region[n].end   = ~0UL;
@@ -244,28 +276,31 @@
 static void __init
 io_port_init (void)
 {
-	extern unsigned long ia64_iobase;
 	unsigned long phys_iobase;
 
 	/*
-	 *  Set `iobase' to the appropriate address in region 6 (uncached access range).
+	 * Set `iobase' based on the EFI memory map or, failing that, the
+	 * value firmware left in ar.k0.
 	 *
-	 *  The EFI memory map is the "preferred" location to get the I/O port space base,
-	 *  rather the relying on AR.KR0. This should become more clear in future SAL
-	 *  specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is
-	 *  found in the memory map.
+	 * Note that in ia32 mode, IN/OUT instructions use ar.k0 to compute
+	 * the port's virtual address, so ia32_load_state() loads it with a
+	 * user virtual address.  But in ia64 mode, glibc uses the
+	 * *physical* address in ar.k0 to mmap the appropriate area from
+	 * /dev/mem, and the inX()/outX() interfaces use MMIO.  In both
+	 * cases, user-mode can only use the legacy 0-64K I/O port space.
+	 *
+	 * ar.k0 is not involved in kernel I/O port accesses, which can use
+	 * any of the I/O port spaces and are done via MMIO using the
+	 * virtual mmio_base from the appropriate io_space[].
 	 */
 	phys_iobase = efi_get_iobase();
-	if (phys_iobase)
-		/* set AR.KR0 since this is all we use it for anyway */
-		ia64_set_kr(IA64_KR_IO_BASE, phys_iobase);
-	else {
+	if (!phys_iobase) {
 		phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
-		printk(KERN_INFO "No I/O port range found in EFI memory map, falling back "
-		       "to AR.KR0\n");
-		printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase);
+		printk(KERN_INFO "No I/O port range found in EFI memory map, "
+			"falling back to AR.KR0 (0x%lx)\n", phys_iobase);
 	}
 	ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
+	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
 
 	/* setup legacy IO port space */
 	io_space[0].mmio_base = ia64_iobase;
@@ -526,7 +561,7 @@
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
 		   lpj*HZ/500000, (lpj*HZ/5000) % 100);
 #ifdef CONFIG_SMP
-	seq_printf(m, "siblings   : %u\n", c->num_log);
+	seq_printf(m, "siblings   : %u\n", cpus_weight(cpu_core_map[cpunum]));
 	if (c->threads_per_core > 1 || c->cores_per_socket > 1)
 		seq_printf(m,
 		   	   "physical id: %u\n"
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 0166a98..657ac99 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -185,8 +185,8 @@
 {
 	unsigned int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_online(i) && i != smp_processor_id())
+	for_each_online_cpu(i) {
+		if (i != smp_processor_id())
 			send_IPI_single(i, op);
 	}
 }
@@ -199,9 +199,9 @@
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(i))
-			send_IPI_single(i, op);
+	for_each_online_cpu(i) {
+		send_IPI_single(i, op);
+	}
 }
 
 /*
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 7d72c0d..400a489 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -694,9 +694,9 @@
 	 * Allow the user to impress friends.
 	 */
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++)
-		if (cpu_online(cpu))
-			bogosum += cpu_data(cpu)->loops_per_jiffy;
+	for_each_online_cpu(cpu) {
+		bogosum += cpu_data(cpu)->loops_per_jiffy;
+	}
 
 	printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 	       (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 8b8a5a4..5b7e736 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -32,10 +32,6 @@
 
 extern unsigned long wall_jiffies;
 
-u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 #define TIME_KEEPER_ID	0	/* smp_processor_id() of time-keeper */
 
 #ifdef CONFIG_IA64_DEBUG_IRQ
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 4e9d06c..c6d4044 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -205,23 +205,18 @@
 static int __init
 uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
 {
-	long length;
-	unsigned long vstart, vend;
+	long length = end - start;
 	int node;
 
-	length = end - start;
-	vstart = start + __IA64_UNCACHED_OFFSET;
-	vend = end + __IA64_UNCACHED_OFFSET;
-
 	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
 
-	memset((char *)vstart, 0, length);
+	memset((char *)start, 0, length);
 
-	node = paddr_to_nid(start);
+	node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
 
-	for (; vstart < vend ; vstart += PAGE_SIZE) {
-		dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
-		gen_pool_free(uncached_pool[node], vstart, PAGE_SIZE);
+	for (; start < end ; start += PAGE_SIZE) {
+		dprintk(KERN_INFO "sticking %lx into the pool!\n", start);
+		gen_pool_free(uncached_pool[node], start, PAGE_SIZE);
 	}
 
 	return 0;
diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
index a604efc..96edcc0 100644
--- a/arch/ia64/lib/swiotlb.c
+++ b/arch/ia64/lib/swiotlb.c
@@ -49,6 +49,15 @@
  */
 #define IO_TLB_SHIFT 11
 
+#define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
+
+/*
+ * Minimum IO TLB size to bother booting with.  Systems with mainly
+ * 64bit capable cards will only lightly use the swiotlb.  If we can't
+ * allocate a contiguous 1MB, we're probably in trouble anyway.
+ */
+#define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
+
 int swiotlb_force;
 
 /*
@@ -154,6 +163,99 @@
 	swiotlb_init_with_default_size(64 * (1<<20));	/* default to 64MB */
 }
 
+/*
+ * Systems with larger DMA zones (those that don't support ISA) can
+ * initialize the swiotlb later using the slab allocator if needed.
+ * This should be just like above, but with some error catching.
+ */
+int
+swiotlb_late_init_with_default_size (size_t default_size)
+{
+	unsigned long i, req_nslabs = io_tlb_nslabs;
+	unsigned int order;
+
+	if (!io_tlb_nslabs) {
+		io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
+		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+	}
+
+	/*
+	 * Get IO TLB memory from the low pages
+	 */
+	order = get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+	io_tlb_nslabs = SLABS_PER_PAGE << order;
+
+	while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
+		io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
+		                                        order);
+		if (io_tlb_start)
+			break;
+		order--;
+	}
+
+	if (!io_tlb_start)
+		goto cleanup1;
+
+	if (order != get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT))) {
+		printk(KERN_WARNING "Warning: only able to allocate %ld MB "
+		       "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
+		io_tlb_nslabs = SLABS_PER_PAGE << order;
+	}
+	io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
+	memset(io_tlb_start, 0, io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+
+	/*
+	 * Allocate and initialize the free list array.  This array is used
+	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
+	 * between io_tlb_start and io_tlb_end.
+	 */
+	io_tlb_list = (unsigned int *)__get_free_pages(GFP_KERNEL,
+	                              get_order(io_tlb_nslabs * sizeof(int)));
+	if (!io_tlb_list)
+		goto cleanup2;
+
+	for (i = 0; i < io_tlb_nslabs; i++)
+ 		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
+	io_tlb_index = 0;
+
+	io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
+	                           get_order(io_tlb_nslabs * sizeof(char *)));
+	if (!io_tlb_orig_addr)
+		goto cleanup3;
+
+	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
+
+	/*
+	 * Get the overflow emergency buffer
+	 */
+	io_tlb_overflow_buffer = (void *)__get_free_pages(GFP_DMA,
+	                                          get_order(io_tlb_overflow));
+	if (!io_tlb_overflow_buffer)
+		goto cleanup4;
+
+	printk(KERN_INFO "Placing %ldMB software IO TLB between 0x%lx - "
+	       "0x%lx\n", (io_tlb_nslabs * (1 << IO_TLB_SHIFT)) >> 20,
+	       virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
+
+	return 0;
+
+cleanup4:
+	free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs *
+	                                                      sizeof(char *)));
+	io_tlb_orig_addr = NULL;
+cleanup3:
+	free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
+	                                                 sizeof(int)));
+	io_tlb_list = NULL;
+	io_tlb_end = NULL;
+cleanup2:
+	free_pages((unsigned long)io_tlb_start, order);
+	io_tlb_start = NULL;
+cleanup1:
+	io_tlb_nslabs = req_nslabs;
+	return -ENOMEM;
+}
+
 static inline int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
@@ -314,7 +416,7 @@
 
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-		       dma_addr_t *dma_handle, int flags)
+		       dma_addr_t *dma_handle, gfp_t flags)
 {
 	unsigned long dev_addr;
 	void *ret;
diff --git a/arch/ia64/mm/Makefile b/arch/ia64/mm/Makefile
index 7078f67..d78d20f 100644
--- a/arch/ia64/mm/Makefile
+++ b/arch/ia64/mm/Makefile
@@ -7,6 +7,5 @@
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_NUMA)	   += numa.o
 obj-$(CONFIG_DISCONTIGMEM) += discontig.o
-ifndef CONFIG_DISCONTIGMEM
-obj-y += contig.o
-endif
+obj-$(CONFIG_SPARSEMEM)	   += discontig.o
+obj-$(CONFIG_FLATMEM)	   += contig.o
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 91a055f..acaaec4 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -269,7 +269,7 @@
 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
 	if (max_gap < LARGE_GAP) {
 		vmem_map = (struct page *) 0;
-		free_area_init_node(0, &contig_page_data, zones_size, 0,
+		free_area_init_node(0, NODE_DATA(0), zones_size, 0,
 				    zholes_size);
 	} else {
 		unsigned long map_size;
@@ -282,7 +282,7 @@
 		efi_memmap_walk(create_mem_map_page_table, NULL);
 
 		NODE_DATA(0)->node_mem_map = vmem_map;
-		free_area_init_node(0, &contig_page_data, zones_size,
+		free_area_init_node(0, NODE_DATA(0), zones_size,
 				    0, zholes_size);
 
 		printk("Virtual mem_map starts at 0x%p\n", mem_map);
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index b5c90e5..a88cdb7 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -421,6 +421,37 @@
 	return;
 }
 
+#ifdef CONFIG_SPARSEMEM
+/**
+ * register_sparse_mem - notify SPARSEMEM that this memory range exists.
+ * @start: physical start of range
+ * @end: physical end of range
+ * @arg: unused
+ *
+ * Simply calls SPARSEMEM to register memory section(s).
+ */
+static int __init register_sparse_mem(unsigned long start, unsigned long end,
+	void *arg)
+{
+	int nid;
+
+	start = __pa(start) >> PAGE_SHIFT;
+	end = __pa(end) >> PAGE_SHIFT;
+	nid = early_pfn_to_nid(start);
+	memory_present(nid, start, end);
+
+	return 0;
+}
+
+static void __init arch_sparse_init(void)
+{
+	efi_memmap_walk(register_sparse_mem, NULL);
+	sparse_init();
+}
+#else
+#define arch_sparse_init() do {} while (0)
+#endif
+
 /**
  * find_memory - walk the EFI memory map and setup the bootmem allocator
  *
@@ -524,12 +555,18 @@
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
-		unsigned long present = pgdat->node_present_pages;
+		unsigned long present;
+		unsigned long flags;
 		int shared = 0, cached = 0, reserved = 0;
+
 		printk("Node ID: %d\n", pgdat->node_id);
+		pgdat_resize_lock(pgdat, &flags);
+		present = pgdat->node_present_pages;
 		for(i = 0; i < pgdat->node_spanned_pages; i++) {
-			struct page *page = pgdat_page_nr(pgdat, i);
-			if (!ia64_pfn_valid(pgdat->node_start_pfn+i))
+			struct page *page;
+			if (pfn_valid(pgdat->node_start_pfn + i))
+				page = pfn_to_page(pgdat->node_start_pfn + i);
+			else
 				continue;
 			if (PageReserved(page))
 				reserved++;
@@ -538,6 +575,7 @@
 			else if (page_count(page))
 				shared += page_count(page)-1;
 		}
+		pgdat_resize_unlock(pgdat, &flags);
 		total_present += present;
 		total_reserved += reserved;
 		total_cached += cached;
@@ -648,12 +686,16 @@
 
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
+	arch_sparse_init();
+
 	efi_memmap_walk(filter_rsvd_memory, count_node_pages);
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
 	vmalloc_end -= PAGE_ALIGN(max_low_pfn * sizeof(struct page));
 	vmem_map = (struct page *) vmalloc_end;
 	efi_memmap_walk(create_mem_map_page_table, NULL);
 	printk("Virtual mem_map starts at 0x%p\n", vmem_map);
+#endif
 
 	for_each_online_node(node) {
 		memset(zones_size, 0, sizeof(zones_size));
@@ -690,7 +732,9 @@
 
 		pfn_offset = mem_data[node].min_pfn;
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
 		NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
+#endif
 		free_area_init_node(node, NODE_DATA(node), zones_size,
 				    pfn_offset, zholes_size);
 	}
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 3c32af9..af7eb08 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -20,32 +20,6 @@
 extern void die (char *, struct pt_regs *, long);
 
 /*
- * This routine is analogous to expand_stack() but instead grows the
- * register backing store (which grows towards higher addresses).
- * Since the register backing store is access sequentially, we
- * disallow growing the RBS by more than a page at a time.  Note that
- * the VM_GROWSUP flag can be set on any VM area but that's fine
- * because the total process size is still limited by RLIMIT_STACK and
- * RLIMIT_AS.
- */
-static inline long
-expand_backing_store (struct vm_area_struct *vma, unsigned long address)
-{
-	unsigned long grow;
-
-	grow = PAGE_SIZE >> PAGE_SHIFT;
-	if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur
-	    || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->signal->rlim[RLIMIT_AS].rlim_cur))
-		return -ENOMEM;
-	vma->vm_end += PAGE_SIZE;
-	vma->vm_mm->total_vm += grow;
-	if (vma->vm_flags & VM_LOCKED)
-		vma->vm_mm->locked_vm += grow;
-	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
-	return 0;
-}
-
-/*
  * Return TRUE if ADDRESS points at a page in the kernel's mapped segment
  * (inside region 5, on ia64) and that page is present.
  */
@@ -185,7 +159,13 @@
 		if (REGION_NUMBER(address) != REGION_NUMBER(vma->vm_start)
 		    || REGION_OFFSET(address) >= RGN_MAP_LIMIT)
 			goto bad_area;
-		if (expand_backing_store(vma, address))
+		/*
+		 * Since the register backing store is accessed sequentially,
+		 * we disallow growing it by more than a page at a time.
+		 */
+		if (address > vma->vm_end + PAGE_SIZE - sizeof(long))
+			goto bad_area;
+		if (expand_upwards(vma, address))
 			goto bad_area;
 	}
 	goto good_area;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 1281c60..e3215ba 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -158,7 +158,7 @@
 		vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
 		vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
-		vma->vm_flags = VM_DATA_DEFAULT_FLAGS | VM_GROWSUP;
+		vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT;
 		down_write(&current->mm->mmap_sem);
 		if (insert_vm_struct(current->mm, vma)) {
 			up_write(&current->mm->mmap_sem);
@@ -275,26 +275,21 @@
 
 	pgd = pgd_offset_k(address);		/* note: this is NOT pgd_offset()! */
 
-	spin_lock(&init_mm.page_table_lock);
 	{
 		pud = pud_alloc(&init_mm, pgd, address);
 		if (!pud)
 			goto out;
-
 		pmd = pmd_alloc(&init_mm, pud, address);
 		if (!pmd)
 			goto out;
-		pte = pte_alloc_map(&init_mm, pmd, address);
+		pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			goto out;
-		if (!pte_none(*pte)) {
-			pte_unmap(pte);
+		if (!pte_none(*pte))
 			goto out;
-		}
 		set_pte(pte, mk_pte(page, pgprot));
-		pte_unmap(pte);
 	}
-  out:	spin_unlock(&init_mm.page_table_lock);
+  out:
 	/* no need for flush_tlb */
 	return page;
 }
@@ -593,7 +588,7 @@
 	platform_dma_init();
 #endif
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 	if (!mem_map)
 		BUG();
 	max_mapnr = max_low_pfn;
diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
index 77118bb..4e5c8b3 100644
--- a/arch/ia64/mm/numa.c
+++ b/arch/ia64/mm/numa.c
@@ -47,3 +47,27 @@
 
 	return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0);
 }
+
+#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA)
+/*
+ * Because of holes evaluate on section limits.
+ * If the section of memory exists, then return the node where the section
+ * resides.  Otherwise return node 0 as the default.  This is used by
+ * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
+ * the section resides.
+ */
+int early_pfn_to_nid(unsigned long pfn)
+{
+	int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
+
+	for (i = 0; i < num_node_memblks; i++) {
+		ssec = node_memblk[i].start_paddr >> PA_SECTION_SHIFT;
+		esec = (node_memblk[i].start_paddr + node_memblk[i].size +
+			((1L << PA_SECTION_SHIFT) - 1)) >> PA_SECTION_SHIFT;
+		if (section >= ssec && section < esec)
+			return node_memblk[i].nid;
+	}
+
+	return 0;
+}
+#endif
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 464557e..c79a9b9 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -77,19 +77,25 @@
 	/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
 	{
 		int cpu = get_cpu(); /* prevent preemption/migration */
-		for (i = 0; i < NR_CPUS; ++i)
-			if (cpu_online(i) && (i != cpu))
+		for_each_online_cpu(i) {
+			if (i != cpu)
 				per_cpu(ia64_need_tlb_flush, i) = 1;
+		}
 		put_cpu();
 	}
 	local_flush_tlb_all();
 }
 
 void
-ia64_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
+ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits)
 {
 	static DEFINE_SPINLOCK(ptcg_lock);
 
+	if (mm != current->active_mm) {
+		flush_tlb_all();
+		return;
+	}
+
 	/* HW requires global serialization of ptc.ga.  */
 	spin_lock(&ptcg_lock);
 	{
@@ -135,15 +141,12 @@
 	unsigned long size = end - start;
 	unsigned long nbits;
 
+#ifndef CONFIG_SMP
 	if (mm != current->active_mm) {
-		/* this does happen, but perhaps it's not worth optimizing for? */
-#ifdef CONFIG_SMP
-		flush_tlb_all();
-#else
 		mm->context = 0;
-#endif
 		return;
 	}
+#endif
 
 	nbits = ia64_fls(size + 0xfff);
 	while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits))
@@ -153,12 +156,14 @@
 	start &= ~((1UL << nbits) - 1);
 
 # ifdef CONFIG_SMP
-	platform_global_tlb_purge(start, end, nbits);
+	platform_global_tlb_purge(mm, start, end, nbits);
 # else
+	preempt_disable();
 	do {
 		ia64_ptcl(start, (nbits<<2));
 		start += (1UL << nbits);
 	} while (start < end);
+	preempt_enable();
 # endif
 
 	ia64_srlz_i();			/* srlz.i implies srlz.d */
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 9b5de58..017cfc3 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -120,29 +120,6 @@
 	.write = pci_write,
 };
 
-#ifdef CONFIG_NUMA
-extern acpi_status acpi_map_iosapic(acpi_handle, u32, void *, void **);
-static void acpi_map_iosapics(void)
-{
-	acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
-}
-#else
-static void acpi_map_iosapics(void)
-{
-	return;
-}
-#endif /* CONFIG_NUMA */
-
-static int __init
-pci_acpi_init (void)
-{
-	acpi_map_iosapics();
-
-	return 0;
-}
-
-subsys_initcall(pci_acpi_init);
-
 /* Called by ACPI when it finds a new root bus.  */
 
 static struct pci_controller * __devinit
@@ -191,6 +168,29 @@
 	return IO_SPACE_BASE(i);
 }
 
+static acpi_status __devinit resource_to_window(struct acpi_resource *resource,
+	struct acpi_resource_address64 *addr)
+{
+	acpi_status status;
+
+	/*
+	 * We're only interested in _CRS descriptors that are
+	 *	- address space descriptors for memory or I/O space
+	 *	- non-zero size
+	 *	- producers, i.e., the address space is routed downstream,
+	 *	  not consumed by the bridge itself
+	 */
+	status = acpi_resource_to_address64(resource, addr);
+	if (ACPI_SUCCESS(status) &&
+	    (addr->resource_type == ACPI_MEMORY_RANGE ||
+	     addr->resource_type == ACPI_IO_RANGE) &&
+	    addr->address_length &&
+	    addr->producer_consumer == ACPI_PRODUCER)
+		return AE_OK;
+
+	return AE_ERROR;
+}
+
 static acpi_status __devinit
 count_window (struct acpi_resource *resource, void *data)
 {
@@ -198,11 +198,9 @@
 	struct acpi_resource_address64 addr;
 	acpi_status status;
 
-	status = acpi_resource_to_address64(resource, &addr);
+	status = resource_to_window(resource, &addr);
 	if (ACPI_SUCCESS(status))
-		if (addr.resource_type == ACPI_MEMORY_RANGE ||
-		    addr.resource_type == ACPI_IO_RANGE)
-			(*windows)++;
+		(*windows)++;
 
 	return AE_OK;
 }
@@ -221,13 +219,11 @@
 	unsigned long flags, offset = 0;
 	struct resource *root;
 
-	status = acpi_resource_to_address64(res, &addr);
+	/* Return AE_OK for non-window resources to keep scanning for more */
+	status = resource_to_window(res, &addr);
 	if (!ACPI_SUCCESS(status))
 		return AE_OK;
 
-	if (!addr.address_length)
-		return AE_OK;
-
 	if (addr.resource_type == ACPI_MEMORY_RANGE) {
 		flags = IORESOURCE_MEM;
 		root = &iomem_resource;
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 45854c6..d71f4de 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -87,7 +87,7 @@
 	unsigned long irq_flags;
 	unsigned long itc_end = 0;
 	int nasid_to_try[MAX_NODES_TO_TRY];
-	int my_nasid = get_nasid();
+	int my_nasid = cpuid_to_nasid(raw_smp_processor_id());
 	int bte_if_index, nasid_index;
 	int bte_first, btes_per_node = BTES_PER_NODE;
 
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 906622d..b4f5053 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -22,8 +22,6 @@
 #include "xtalk/hubdev.h"
 #include "xtalk/xwidgetdev.h"
 
-nasid_t master_nasid = INVALID_NASID;	/* Partition Master */
-
 static struct list_head sn_sysdata_list;
 
 /* sysdata list struct */
@@ -165,7 +163,7 @@
 	 * Get SGI Specific HUB chipset information.
 	 * Inform Prom that this kernel can support domain bus numbering.
 	 */
-	for (i = 0; i < numionodes; i++) {
+	for (i = 0; i < num_cnodes; i++) {
 		hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
 		nasid = cnodeid_to_nasid(i);
 		hubdev->max_segment_number = 0xffffffff;
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 6f8c588..0fb579e 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -59,8 +59,6 @@
 
 #define MAX_PHYS_MEMORY		(1UL << IA64_MAX_PHYS_BITS)	/* Max physical address supported */
 
-lboard_t *root_lboard[MAX_COMPACT_NODES];
-
 extern void bte_init_node(nodepda_t *, cnodeid_t);
 
 extern void sn_timer_init(void);
@@ -97,15 +95,15 @@
 EXPORT_SYMBOL(sn_region_size);
 int sn_prom_type;	/* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
 
-short physical_node_map[MAX_PHYSNODE_ID];
+short physical_node_map[MAX_NUMALINK_NODES];
 static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
 
 EXPORT_SYMBOL(physical_node_map);
 
-int numionodes;
+int num_cnodes;
 
 static void sn_init_pdas(char **);
-static void scan_for_ionodes(void);
+static void build_cnode_tables(void);
 
 static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
 
@@ -140,19 +138,6 @@
 #endif
 
 /*
- * Get nasid of current cpu early in boot before nodepda is initialized
- */
-static int
-boot_get_nasid(void)
-{
-	int nasid;
-
-	if (ia64_sn_get_sapic_info(get_sapicid(), &nasid, NULL, NULL))
-		BUG();
-	return nasid;
-}
-
-/*
  * This routine can only be used during init, since
  * smp_boot_data is an init data structure.
  * We have to use smp_boot_data.cpu_phys_id to find
@@ -223,7 +208,6 @@
 }
 
 extern int platform_intr_list[];
-extern nasid_t master_nasid;
 static int __initdata shub_1_1_found = 0;
 
 /*
@@ -269,7 +253,6 @@
 void __init sn_setup(char **cmdline_p)
 {
 	long status, ticks_per_sec, drift;
-	int pxm;
 	u32 version = sn_sal_rev();
 	extern void sn_cpu_init(void);
 
@@ -300,11 +283,10 @@
 
 	MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
 
-	memset(physical_node_map, -1, sizeof(physical_node_map));
-	for (pxm = 0; pxm < MAX_PXM_DOMAINS; pxm++)
-		if (pxm_to_nid_map[pxm] != -1)
-			physical_node_map[pxm_to_nasid(pxm)] =
-			    pxm_to_nid_map[pxm];
+	/*
+	 * Build the tables for managing cnodes.
+	 */
+	build_cnode_tables();
 
 	/*
 	 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
@@ -319,8 +301,6 @@
 
 	printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
 
-	master_nasid = boot_get_nasid();
-
 	status =
 	    ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
 			       &drift);
@@ -378,15 +358,6 @@
 {
 	cnodeid_t cnode;
 
-	memset(sn_cnodeid_to_nasid, -1,
-			sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
-	for_each_online_node(cnode)
-		sn_cnodeid_to_nasid[cnode] =
-				pxm_to_nasid(nid_to_pxm_map[cnode]);
-
-	numionodes = num_online_nodes();
-	scan_for_ionodes();
-
 	/*
 	 * Allocate & initalize the nodepda for each node.
 	 */
@@ -402,7 +373,7 @@
 	/*
 	 * Allocate & initialize nodepda for TIOs.  For now, put them on node 0.
 	 */
-	for (cnode = num_online_nodes(); cnode < numionodes; cnode++) {
+	for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) {
 		nodepdaindr[cnode] =
 		    alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
 		memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
@@ -411,7 +382,7 @@
 	/*
 	 * Now copy the array of nodepda pointers to each nodepda.
 	 */
-	for (cnode = 0; cnode < numionodes; cnode++)
+	for (cnode = 0; cnode < num_cnodes; cnode++)
 		memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr,
 		       sizeof(nodepdaindr));
 
@@ -428,7 +399,7 @@
 	 * Initialize the per node hubdev.  This includes IO Nodes and
 	 * headless/memless nodes.
 	 */
-	for (cnode = 0; cnode < numionodes; cnode++) {
+	for (cnode = 0; cnode < num_cnodes; cnode++) {
 		hubdev_init_node(nodepdaindr[cnode], cnode);
 	}
 }
@@ -553,87 +524,58 @@
 }
 
 /*
- * Scan klconfig for ionodes.  Add the nasids to the
- * physical_node_map and the pda and increment numionodes.
+ * Build tables for converting between NASIDs and cnodes.
  */
-
-static void __init scan_for_ionodes(void)
+static inline int __init board_needs_cnode(int type)
 {
-	int nasid = 0;
+	return (type == KLTYPE_SNIA || type == KLTYPE_TIO);
+}
+
+void __init build_cnode_tables(void)
+{
+	int nasid;
+	int node;
 	lboard_t *brd;
 
+	memset(physical_node_map, -1, sizeof(physical_node_map));
+	memset(sn_cnodeid_to_nasid, -1,
+			sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
+
+	/*
+	 * First populate the tables with C/M bricks. This ensures that
+	 * cnode == node for all C & M bricks.
+	 */
+	for_each_online_node(node) {
+		nasid = pxm_to_nasid(nid_to_pxm_map[node]);
+		sn_cnodeid_to_nasid[node] = nasid;
+		physical_node_map[nasid] = node;
+	}
+
+	/*
+	 * num_cnodes is total number of C/M/TIO bricks. Because of the 256 node
+	 * limit on the number of nodes, we can't use the generic node numbers 
+	 * for this. Note that num_cnodes is incremented below as TIOs or
+	 * headless/memoryless nodes are discovered.
+	 */
+	num_cnodes = num_online_nodes();
+
 	/* fakeprom does not support klgraph */
 	if (IS_RUNNING_ON_FAKE_PROM())
 		return;
 
-	/* Setup ionodes with memory */
-	for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-		char *klgraph_header;
-		cnodeid_t cnodeid;
-
-		if (physical_node_map[nasid] == -1)
-			continue;
-
-		cnodeid = -1;
-		klgraph_header = __va(ia64_sn_get_klconfig_addr(nasid));
-		if (!klgraph_header) {
-			BUG();	/* All nodes must have klconfig tables! */
-		}
-		cnodeid = nasid_to_cnodeid(nasid);
-		root_lboard[cnodeid] = (lboard_t *)
-		    NODE_OFFSET_TO_LBOARD((nasid),
-					  ((kl_config_hdr_t
-					    *) (klgraph_header))->
-					  ch_board_info);
-	}
-
-	/* Scan headless/memless IO Nodes. */
-	for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-		/* if there's no nasid, don't try to read the klconfig on the node */
-		if (physical_node_map[nasid] == -1)
-			continue;
-		brd = find_lboard_any((lboard_t *)
-				      root_lboard[nasid_to_cnodeid(nasid)],
-				      KLTYPE_SNIA);
-		if (brd) {
-			brd = KLCF_NEXT_ANY(brd);	/* Skip this node's lboard */
-			if (!brd)
-				continue;
-		}
-
-		brd = find_lboard_any(brd, KLTYPE_SNIA);
-
+	/* Find TIOs & headless/memoryless nodes and add them to the tables */
+	for_each_online_node(node) {
+		kl_config_hdr_t *klgraph_header;
+		nasid = cnodeid_to_nasid(node);
+		if ((klgraph_header = ia64_sn_get_klconfig_addr(nasid)) == NULL)
+			BUG();
+		brd = NODE_OFFSET_TO_LBOARD(nasid, klgraph_header->ch_board_info);
 		while (brd) {
-			sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
-			physical_node_map[brd->brd_nasid] = numionodes;
-			root_lboard[numionodes] = brd;
-			numionodes++;
-			brd = KLCF_NEXT_ANY(brd);
-			if (!brd)
-				break;
-
-			brd = find_lboard_any(brd, KLTYPE_SNIA);
-		}
-	}
-
-	/* Scan for TIO nodes. */
-	for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
-		/* if there's no nasid, don't try to read the klconfig on the node */
-		if (physical_node_map[nasid] == -1)
-			continue;
-		brd = find_lboard_any((lboard_t *)
-				      root_lboard[nasid_to_cnodeid(nasid)],
-				      KLTYPE_TIO);
-		while (brd) {
-			sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
-			physical_node_map[brd->brd_nasid] = numionodes;
-			root_lboard[numionodes] = brd;
-			numionodes++;
-			brd = KLCF_NEXT_ANY(brd);
-			if (!brd)
-				break;
-
-			brd = find_lboard_any(brd, KLTYPE_TIO);
+			if (board_needs_cnode(brd->brd_type) && physical_node_map[brd->brd_nasid] < 0) {
+				sn_cnodeid_to_nasid[num_cnodes] = brd->brd_nasid;
+				physical_node_map[brd->brd_nasid] = num_cnodes++;
+			}
+			brd = find_lboard_next(brd);
 		}
 	}
 }
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 0a4ee50..49b530c 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -177,6 +177,7 @@
 
 /**
  * sn2_global_tlb_purge - globally purge translation cache of virtual address range
+ * @mm: mm_struct containing virtual address range
  * @start: start of virtual address range
  * @end: end of virtual address range
  * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
@@ -188,21 +189,22 @@
  * 	- cpu_vm_mask is a bit mask that indicates which cpus have loaded the context.
  * 	- cpu_vm_mask is converted into a nodemask of the nodes containing the
  * 	  cpus in cpu_vm_mask.
- *	- if only one bit is set in cpu_vm_mask & it is the current cpu,
- *	  then only the local TLB needs to be flushed. This flushing can be done
- *	  using ptc.l. This is the common case & avoids the global spinlock.
+ *	- if only one bit is set in cpu_vm_mask & it is the current cpu & the
+ *	  process is purging its own virtual address range, then only the
+ *	  local TLB needs to be flushed. This flushing can be done using
+ *	  ptc.l. This is the common case & avoids the global spinlock.
  *	- if multiple cpus have loaded the context, then flushing has to be
  *	  done with ptc.g/MMRs under protection of the global ptc_lock.
  */
 
 void
-sn2_global_tlb_purge(unsigned long start, unsigned long end,
-		     unsigned long nbits)
+sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
+		     unsigned long end, unsigned long nbits)
 {
 	int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
+	int mymm = (mm == current->active_mm);
 	volatile unsigned long *ptc0, *ptc1;
-	unsigned long itc, itc2, flags, data0 = 0, data1 = 0;
-	struct mm_struct *mm = current->active_mm;
+	unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value;
 	short nasids[MAX_NUMNODES], nix;
 	nodemask_t nodes_flushed;
 
@@ -216,9 +218,12 @@
 		i++;
 	}
 
+	if (i == 0)
+		return;
+
 	preempt_disable();
 
-	if (likely(i == 1 && lcpu == smp_processor_id())) {
+	if (likely(i == 1 && lcpu == smp_processor_id() && mymm)) {
 		do {
 			ia64_ptcl(start, nbits << 2);
 			start += (1UL << nbits);
@@ -229,7 +234,7 @@
 		return;
 	}
 
-	if (atomic_read(&mm->mm_users) == 1) {
+	if (atomic_read(&mm->mm_users) == 1 && mymm) {
 		flush_tlb_mm(mm);
 		__get_cpu_var(ptcstats).change_rid++;
 		preempt_enable();
@@ -241,11 +246,13 @@
 	for_each_node_mask(cnode, nodes_flushed)
 		nasids[nix++] = cnodeid_to_nasid(cnode);
 
+	rr_value = (mm->context << 3) | REGION_NUMBER(start);
+
 	shub1 = is_shub1();
 	if (shub1) {
 		data0 = (1UL << SH1_PTC_0_A_SHFT) |
 		    	(nbits << SH1_PTC_0_PS_SHFT) |
-		    	((ia64_get_rr(start) >> 8) << SH1_PTC_0_RID_SHFT) |
+			(rr_value << SH1_PTC_0_RID_SHFT) |
 		    	(1UL << SH1_PTC_0_START_SHFT);
 		ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0);
 		ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1);
@@ -254,7 +261,7 @@
 			(nbits << SH2_PTC_PS_SHFT) |
 		    	(1UL << SH2_PTC_START_SHFT);
 		ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC + 
-			((ia64_get_rr(start) >> 8) << SH2_PTC_RID_SHFT) );
+			(rr_value << SH2_PTC_RID_SHFT));
 		ptc1 = NULL;
 	}
 	
@@ -275,7 +282,7 @@
 			data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
 		for (i = 0; i < nix; i++) {
 			nasid = nasids[i];
-			if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid)) {
+			if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid && mymm)) {
 				ia64_ptcga(start, nbits << 2);
 				ia64_srlz_i();
 			} else {
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 0513aac..6c6fbca 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -476,8 +476,8 @@
 				for_each_online_cpu(j) {
 					seq_printf(s, j ? ":%d" : ", dist %d",
 						node_distance(
-						    cpuid_to_cnodeid(i),
-						    cpuid_to_cnodeid(j)));
+						    cpu_to_node(i),
+						    cpu_to_node(j)));
 				}
 				seq_putc(s, '\n');
 			}
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index b45db51..0d8592a 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -183,11 +183,12 @@
  * @part_num: device's part number
  * @mfg_num: device's manufacturer number
  * @hubdev: hub info associated with this device
+ * @bt: board type of the device
  *
  */
 int
 cx_device_register(nasid_t nasid, int part_num, int mfg_num,
-		   struct hubdev_info *hubdev)
+		   struct hubdev_info *hubdev, int bt)
 {
 	struct cx_dev *cx_dev;
 
@@ -200,6 +201,7 @@
 	cx_dev->cx_id.mfg_num = mfg_num;
 	cx_dev->cx_id.nasid = nasid;
 	cx_dev->hubdev = hubdev;
+	cx_dev->bt = bt;
 
 	cx_dev->dev.parent = NULL;
 	cx_dev->dev.bus = &tiocx_bus_type;
@@ -238,7 +240,8 @@
 {
 	cx_device_unregister(cx_dev);
 	return cx_device_register(cx_dev->cx_id.nasid, cx_dev->cx_id.part_num,
-				  cx_dev->cx_id.mfg_num, cx_dev->hubdev);
+				  cx_dev->cx_id.mfg_num, cx_dev->hubdev,
+				  cx_dev->bt);
 }
 
 static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget,
@@ -365,26 +368,20 @@
 	udelay(2000);
 }
 
-static int tiocx_btchar_get(int nasid)
+static int is_fpga_tio(int nasid, int *bt)
 {
-	moduleid_t module_id;
-	geoid_t geoid;
-	int cnodeid;
+	int ioboard_type;
 
-	cnodeid = nasid_to_cnodeid(nasid);
-	geoid = cnodeid_get_geoid(cnodeid);
-	module_id = geo_module(geoid);
-	return MODULE_GET_BTCHAR(module_id);
-}
+	ioboard_type = ia64_sn_sysctl_ioboard_get(nasid);
 
-static int is_fpga_brick(int nasid)
-{
-	switch (tiocx_btchar_get(nasid)) {
+	switch (ioboard_type) {
 	case L1_BRICKTYPE_SA:
 	case L1_BRICKTYPE_ATHENA:
-	case L1_BRICKTYPE_DAYTONA:
+	case L1_BOARDTYPE_DAYTONA:
+		*bt = ioboard_type;
 		return 1;
 	}
+
 	return 0;
 }
 
@@ -407,16 +404,22 @@
 
 	if (bitstream_loaded(nasid)) {
 		uint64_t cx_id;
+		int rv;
 
-		cx_id =
-		    *(volatile uint64_t *)(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
+		rv = ia64_sn_sysctl_tio_clock_reset(nasid);
+		if (rv) {
+			printk(KERN_ALERT "CX port JTAG reset failed.\n");
+		} else {
+			cx_id = *(volatile uint64_t *)
+				(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
 					  WIDGET_ID);
-		part_num = XWIDGET_PART_NUM(cx_id);
-		mfg_num = XWIDGET_MFG_NUM(cx_id);
-		DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
-		/* just ignore it if it's a CE */
-		if (part_num == TIO_CE_ASIC_PARTNUM)
-			return 0;
+			part_num = XWIDGET_PART_NUM(cx_id);
+			mfg_num = XWIDGET_MFG_NUM(cx_id);
+			DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
+			/* just ignore it if it's a CE */
+			if (part_num == TIO_CE_ASIC_PARTNUM)
+				return 0;
+		}
 	}
 
 	cx_dev->cx_id.part_num = part_num;
@@ -436,10 +439,10 @@
 {
 	struct cx_dev *cx_dev = to_cx_dev(dev);
 
-	return sprintf(buf, "0x%x 0x%x 0x%x %d\n",
+	return sprintf(buf, "0x%x 0x%x 0x%x 0x%x\n",
 		       cx_dev->cx_id.nasid,
 		       cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
-		       tiocx_btchar_get(cx_dev->cx_id.nasid));
+		       cx_dev->bt);
 }
 
 static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
@@ -486,13 +489,13 @@
 
 	bus_register(&tiocx_bus_type);
 
-	for (cnodeid = 0; cnodeid < MAX_COMPACT_NODES; cnodeid++) {
+	for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
 		nasid_t nasid;
+		int bt;
 
-		if ((nasid = cnodeid_to_nasid(cnodeid)) < 0)
-			break;	/* No more nasids .. bail out of loop */
+		nasid = cnodeid_to_nasid(cnodeid);
 
-		if ((nasid & 0x1) && is_fpga_brick(nasid)) {
+		if ((nasid & 0x1) && is_fpga_tio(nasid, &bt)) {
 			struct hubdev_info *hubdev;
 			struct xwidget_info *widgetp;
 
@@ -512,7 +515,7 @@
 
 			if (cx_device_register
 			    (nasid, widgetp->xwi_hwid.part_num,
-			     widgetp->xwi_hwid.mfg_num, hubdev) < 0)
+			     widgetp->xwi_hwid.mfg_num, hubdev, bt) < 0)
 				return -ENXIO;
 			else
 				found_tiocx_device++;
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h
index d0ee635..fbcedc7 100644
--- a/arch/ia64/sn/kernel/xpc.h
+++ b/arch/ia64/sn/kernel/xpc.h
@@ -57,7 +57,7 @@
 #define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
 
 #define XPC_HB_DEFAULT_INTERVAL		5	/* incr HB every x secs */
-#define XPC_HB_CHECK_DEFAULT_TIMEOUT	20	/* check HB every x secs */
+#define XPC_HB_CHECK_DEFAULT_INTERVAL	20	/* check HB every x secs */
 
 /* define the process name of HB checker and the CPU it is pinned to */
 #define XPC_HB_CHECK_THREAD_NAME	"xpc_hb"
@@ -67,34 +67,82 @@
 #define XPC_DISCOVERY_THREAD_NAME	"xpc_discovery"
 
 
-#define XPC_HB_ALLOWED(_p, _v)	((_v)->heartbeating_to_mask & (1UL << (_p)))
-#define XPC_ALLOW_HB(_p, _v)	(_v)->heartbeating_to_mask |= (1UL << (_p))
-#define XPC_DISALLOW_HB(_p, _v)	(_v)->heartbeating_to_mask &= (~(1UL << (_p)))
-
-
 /*
- * Reserved Page provided by SAL.
+ * the reserved page
  *
- * SAL provides one page per partition of reserved memory.  When SAL
- * initialization is complete, SAL_signature, SAL_version, partid,
- * part_nasids, and mach_nasids are set.
+ *   SAL reserves one page of memory per partition for XPC. Though a full page
+ *   in length (16384 bytes), its starting address is not page aligned, but it
+ *   is cacheline aligned. The reserved page consists of the following:
+ *
+ *   reserved page header
+ *
+ *     The first cacheline of the reserved page contains the header
+ *     (struct xpc_rsvd_page). Before SAL initialization has completed,
+ *     SAL has set up the following fields of the reserved page header:
+ *     SAL_signature, SAL_version, partid, and nasids_size. The other
+ *     fields are set up by XPC. (xpc_rsvd_page points to the local
+ *     partition's reserved page.)
+ *
+ *   part_nasids mask
+ *   mach_nasids mask
+ *
+ *     SAL also sets up two bitmaps (or masks), one that reflects the actual
+ *     nasids in this partition (part_nasids), and the other that reflects
+ *     the actual nasids in the entire machine (mach_nasids). We're only
+ *     interested in the even numbered nasids (which contain the processors
+ *     and/or memory), so we only need half as many bits to represent the
+ *     nasids. The part_nasids mask is located starting at the first cacheline
+ *     following the reserved page header. The mach_nasids mask follows right
+ *     after the part_nasids mask. The size in bytes of each mask is reflected
+ *     by the reserved page header field 'nasids_size'. (Local partition's
+ *     mask pointers are xpc_part_nasids and xpc_mach_nasids.)
+ *
+ *   vars
+ *   vars part
+ *
+ *     Immediately following the mach_nasids mask are the XPC variables
+ *     required by other partitions. First are those that are generic to all
+ *     partitions (vars), followed on the next available cacheline by those
+ *     which are partition specific (vars part). These are setup by XPC.
+ *     (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
  *
  * Note: Until vars_pa is set, the partition XPC code has not been initialized.
  */
 struct xpc_rsvd_page {
-	u64 SAL_signature;	/* SAL unique signature */
-	u64 SAL_version;	/* SAL specified version */
-	u8 partid;		/* partition ID from SAL */
+	u64 SAL_signature;	/* SAL: unique signature */
+	u64 SAL_version;	/* SAL: version */
+	u8 partid;		/* SAL: partition ID */
 	u8 version;
-	u8 pad[6];		/* pad to u64 align */
+	u8 pad1[6];		/* align to next u64 in cacheline */
 	volatile u64 vars_pa;
-	u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
-	u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
+	struct timespec stamp;	/* time when reserved page was setup by XPC */
+	u64 pad2[9];		/* align to last u64 in cacheline */
+	u64 nasids_size;	/* SAL: size of each nasid mask in bytes */
 };
-#define XPC_RP_VERSION _XPC_VERSION(1,0) /* version 1.0 of the reserved page */
 
-#define XPC_RSVD_PAGE_ALIGNED_SIZE \
-			(L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page)))
+#define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */
+
+#define XPC_SUPPORTS_RP_STAMP(_version) \
+			(_version >= _XPC_VERSION(1,1))
+
+/*
+ * compare stamps - the return value is:
+ *
+ *	< 0,	if stamp1 < stamp2
+ *	= 0,	if stamp1 == stamp2
+ *	> 0,	if stamp1 > stamp2
+ */
+static inline int
+xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
+{
+	int ret;
+
+
+	if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) {
+		ret = stamp1->tv_nsec - stamp2->tv_nsec;
+	}
+	return ret;
+}
 
 
 /*
@@ -121,11 +169,58 @@
 	u64 vars_part_pa;
 	u64 amos_page_pa;	/* paddr of page of AMOs from MSPEC driver */
 	AMO_t *amos_page;	/* vaddr of page of AMOs from MSPEC driver */
-	AMO_t *act_amos;	/* pointer to the first activation AMO */
 };
-#define XPC_V_VERSION _XPC_VERSION(3,0) /* version 3.0 of the cross vars */
 
-#define XPC_VARS_ALIGNED_SIZE  (L1_CACHE_ALIGN(sizeof(struct xpc_vars)))
+#define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */
+
+#define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
+			(_version >= _XPC_VERSION(3,1))
+
+
+static inline int
+xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
+{
+	return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
+}
+
+static inline void
+xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
+{
+	u64 old_mask, new_mask;
+
+	do {
+		old_mask = vars->heartbeating_to_mask;
+		new_mask = (old_mask | (1UL << partid));
+	} while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+							old_mask);
+}
+
+static inline void
+xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
+{
+	u64 old_mask, new_mask;
+
+	do {
+		old_mask = vars->heartbeating_to_mask;
+		new_mask = (old_mask & ~(1UL << partid));
+	} while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+							old_mask);
+}
+
+
+/*
+ * The AMOs page consists of a number of AMO variables which are divided into
+ * four groups, The first two groups are used to identify an IRQ's sender.
+ * These two groups consist of 64 and 128 AMO variables respectively. The last
+ * two groups, consisting of just one AMO variable each, are used to identify
+ * the remote partitions that are currently engaged (from the viewpoint of
+ * the XPC running on the remote partition).
+ */
+#define XPC_NOTIFY_IRQ_AMOS	   0
+#define XPC_ACTIVATE_IRQ_AMOS	   (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
+#define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
+#define XPC_DISENGAGE_REQUEST_AMO  (XPC_ENGAGED_PARTITIONS_AMO + 1)
+
 
 /*
  * The following structure describes the per partition specific variables.
@@ -165,6 +260,16 @@
 #define XPC_VP_MAGIC2	0x0073726176435058L  /* 'XPCvars\0'L (little endian) */
 
 
+/* the reserved page sizes and offsets */
+
+#define XPC_RP_HEADER_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
+#define XPC_RP_VARS_SIZE 	L1_CACHE_ALIGN(sizeof(struct xpc_vars))
+
+#define XPC_RP_PART_NASIDS(_rp) (u64 *) ((u8 *) _rp + XPC_RP_HEADER_SIZE)
+#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
+#define XPC_RP_VARS(_rp)	((struct xpc_vars *) XPC_RP_MACH_NASIDS(_rp) + xp_nasid_mask_words)
+#define XPC_RP_VARS_PART(_rp)	(struct xpc_vars_part *) ((u8 *) XPC_RP_VARS(rp) + XPC_RP_VARS_SIZE)
+
 
 /*
  * Functions registered by add_timer() or called by kernel_thread() only
@@ -349,6 +454,9 @@
 	atomic_t n_on_msg_allocate_wq;   /* #on msg allocation wait queue */
 	wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
 
+	u8 delayed_IPI_flags;		/* IPI flags received, but delayed */
+					/* action until channel disconnected */
+
 	/* queue of msg senders who want to be notified when msg received */
 
 	atomic_t n_to_notify;		/* #of msg senders to notify */
@@ -358,7 +466,7 @@
 	void *key;			/* pointer to user's key */
 
 	struct semaphore msg_to_pull_sema; /* next msg to pull serialization */
-	struct semaphore teardown_sema;    /* wait for teardown completion */
+	struct semaphore wdisconnect_sema; /* wait for channel disconnect */
 
 	struct xpc_openclose_args *local_openclose_args; /* args passed on */
 					/* opening or closing of channel */
@@ -410,6 +518,8 @@
 
 #define	XPC_C_DISCONNECTED	0x00002000 /* channel is disconnected */
 #define	XPC_C_DISCONNECTING	0x00004000 /* channel is being disconnected */
+#define	XPC_C_DISCONNECTCALLOUT	0x00008000 /* chan disconnected callout made */
+#define	XPC_C_WDISCONNECT	0x00010000 /* waiting for channel disconnect */
 
 
 
@@ -422,6 +532,8 @@
 
 	/* XPC HB infrastructure */
 
+	u8 remote_rp_version;		/* version# of partition's rsvd pg */
+	struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */
 	u64 remote_rp_pa;		/* phys addr of partition's rsvd pg */
 	u64 remote_vars_pa;		/* phys addr of partition's vars */
 	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
@@ -432,14 +544,18 @@
 	u32 act_IRQ_rcvd;		/* IRQs since activation */
 	spinlock_t act_lock;		/* protect updating of act_state */
 	u8 act_state;			/* from XPC HB viewpoint */
+	u8 remote_vars_version;		/* version# of partition's vars */
 	enum xpc_retval reason;		/* reason partition is deactivating */
 	int reason_line;		/* line# deactivation initiated from */
 	int reactivate_nasid;		/* nasid in partition to reactivate */
 
+	unsigned long disengage_request_timeout; /* timeout in jiffies */
+	struct timer_list disengage_request_timer;
+
 
 	/* XPC infrastructure referencing and teardown control */
 
-	volatile u8 setup_state;			/* infrastructure setup state */
+	volatile u8 setup_state;	/* infrastructure setup state */
 	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
 	atomic_t references;		/* #of references to infrastructure */
 
@@ -454,6 +570,7 @@
 
 	u8 nchannels;		   /* #of defined channels supported */
 	atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
+	atomic_t nchannels_engaged;/* #of channels engaged with remote part */
 	struct xpc_channel *channels;/* array of channel structures */
 
 	void *local_GPs_base;	  /* base address of kmalloc'd space */
@@ -518,6 +635,7 @@
 #define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
 
 
+
 /*
  * struct xpc_partition IPI_timer #of seconds to wait before checking for
  * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
@@ -526,6 +644,13 @@
 #define XPC_P_DROPPED_IPI_WAIT	(0.25 * HZ)
 
 
+/* number of seconds to wait for other partitions to disengage */
+#define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT	90
+
+/* interval in seconds to print 'waiting disengagement' messages */
+#define XPC_DISENGAGE_PRINTMSG_INTERVAL		10
+
+
 #define XPC_PARTID(_p)	((partid_t) ((_p) - &xpc_partitions[0]))
 
 
@@ -534,24 +659,20 @@
 extern struct xpc_registration xpc_registrations[];
 
 
-/* >>> found in xpc_main.c only */
+/* found in xpc_main.c */
 extern struct device *xpc_part;
 extern struct device *xpc_chan;
+extern int xpc_disengage_request_timelimit;
 extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
 extern void xpc_dropped_IPI_check(struct xpc_partition *);
+extern void xpc_activate_partition(struct xpc_partition *);
 extern void xpc_activate_kthreads(struct xpc_channel *, int);
 extern void xpc_create_kthreads(struct xpc_channel *, int);
 extern void xpc_disconnect_wait(int);
 
 
-/* found in xpc_main.c and efi-xpc.c */
-extern void xpc_activate_partition(struct xpc_partition *);
-
-
 /* found in xpc_partition.c */
 extern int xpc_exiting;
-extern int xpc_hb_interval;
-extern int xpc_hb_check_interval;
 extern struct xpc_vars *xpc_vars;
 extern struct xpc_rsvd_page *xpc_rsvd_page;
 extern struct xpc_vars_part *xpc_vars_part;
@@ -561,6 +682,7 @@
 extern void xpc_allow_IPI_ops(void);
 extern void xpc_restrict_IPI_ops(void);
 extern int xpc_identify_act_IRQ_sender(void);
+extern int xpc_partition_disengaged(struct xpc_partition *);
 extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
 extern void xpc_mark_partition_inactive(struct xpc_partition *);
 extern void xpc_discovery(void);
@@ -585,8 +707,8 @@
 extern void xpc_deliver_msg(struct xpc_channel *);
 extern void xpc_disconnect_channel(const int, struct xpc_channel *,
 					enum xpc_retval, unsigned long *);
-extern void xpc_disconnected_callout(struct xpc_channel *);
-extern void xpc_partition_down(struct xpc_partition *, enum xpc_retval);
+extern void xpc_disconnecting_callout(struct xpc_channel *);
+extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
 extern void xpc_teardown_infrastructure(struct xpc_partition *);
 
 
@@ -674,6 +796,157 @@
 
 
 /*
+ * This next set of inlines are used to keep track of when a partition is
+ * potentially engaged in accessing memory belonging to another partition.
+ */
+
+static inline void
+xpc_mark_partition_engaged(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+				(XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+
+
+	local_irq_save(irq_flags);
+
+	/* set bit corresponding to our partid in remote partition's AMO */
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+						(1UL << sn_partition_id));
+	/*
+	 * We must always use the nofault function regardless of whether we
+	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+	 * didn't, we'd never know that the other partition is down and would
+	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+	 */
+	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+				variable), xp_nofault_PIOR_target));
+
+	local_irq_restore(irq_flags);
+}
+
+static inline void
+xpc_mark_partition_disengaged(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+				(XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+
+
+	local_irq_save(irq_flags);
+
+	/* clear bit corresponding to our partid in remote partition's AMO */
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+						~(1UL << sn_partition_id));
+	/*
+	 * We must always use the nofault function regardless of whether we
+	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+	 * didn't, we'd never know that the other partition is down and would
+	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+	 */
+	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+				variable), xp_nofault_PIOR_target));
+
+	local_irq_restore(irq_flags);
+}
+
+static inline void
+xpc_request_partition_disengage(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+				(XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+
+
+	local_irq_save(irq_flags);
+
+	/* set bit corresponding to our partid in remote partition's AMO */
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+						(1UL << sn_partition_id));
+	/*
+	 * We must always use the nofault function regardless of whether we
+	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+	 * didn't, we'd never know that the other partition is down and would
+	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+	 */
+	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+				variable), xp_nofault_PIOR_target));
+
+	local_irq_restore(irq_flags);
+}
+
+static inline void
+xpc_cancel_partition_disengage_request(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+				(XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+
+
+	local_irq_save(irq_flags);
+
+	/* clear bit corresponding to our partid in remote partition's AMO */
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+						~(1UL << sn_partition_id));
+	/*
+	 * We must always use the nofault function regardless of whether we
+	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+	 * didn't, we'd never know that the other partition is down and would
+	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+	 */
+	(void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+				variable), xp_nofault_PIOR_target));
+
+	local_irq_restore(irq_flags);
+}
+
+static inline u64
+xpc_partition_engaged(u64 partid_mask)
+{
+	AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+
+
+	/* return our partition's AMO variable ANDed with partid_mask */
+	return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+								partid_mask);
+}
+
+static inline u64
+xpc_partition_disengage_requested(u64 partid_mask)
+{
+	AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+
+
+	/* return our partition's AMO variable ANDed with partid_mask */
+	return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+								partid_mask);
+}
+
+static inline void
+xpc_clear_partition_engaged(u64 partid_mask)
+{
+	AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+
+
+	/* clear bit(s) based on partid_mask in our partition's AMO */
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+								~partid_mask);
+}
+
+static inline void
+xpc_clear_partition_disengage_request(u64 partid_mask)
+{
+	AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+
+
+	/* clear bit(s) based on partid_mask in our partition's AMO */
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+								~partid_mask);
+}
+
+
+
+/*
  * The following set of macros and inlines are used for the sending and
  * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
  * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
@@ -722,13 +995,13 @@
  * Flag the appropriate AMO variable and send an IPI to the specified node.
  */
 static inline void
-xpc_activate_IRQ_send(u64 amos_page, int from_nasid, int to_nasid,
+xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
 			int to_phys_cpuid)
 {
 	int w_index = XPC_NASID_W_INDEX(from_nasid);
 	int b_index = XPC_NASID_B_INDEX(from_nasid);
-	AMO_t *amos = (AMO_t *) __va(amos_page +
-					(XP_MAX_PARTITIONS * sizeof(AMO_t)));
+	AMO_t *amos = (AMO_t *) __va(amos_page_pa +
+				(XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
 
 
 	(void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
@@ -756,6 +1029,13 @@
 				xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
 }
 
+static inline void
+xpc_IPI_send_disengage(struct xpc_partition *part)
+{
+	xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+			part->remote_act_nasid, part->remote_act_phys_cpuid);
+}
+
 
 /*
  * IPIs associated with SGI_XPC_NOTIFY IRQ.
@@ -836,6 +1116,7 @@
 
 /* given an AMO variable and a channel#, get its associated IPI flags */
 #define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
+#define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))
 
 #define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f)
 #define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010)
@@ -903,17 +1184,18 @@
  * cacheable mapping for the entire region. This will prevent speculative
  * reading of cached copies of our lines from being issued which will cause
  * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
- * (XP_MAX_PARTITIONS) AMO variables for message notification (xpc_main.c)
- * and an additional 16 AMO variables for partition activation (xpc_hb.c).
+ * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
+ * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
+ * activation and 2 AMO variables for partition deactivation.
  */
 static inline AMO_t *
-xpc_IPI_init(partid_t partid)
+xpc_IPI_init(int index)
 {
-	AMO_t *part_amo = xpc_vars->amos_page + partid;
+	AMO_t *amo = xpc_vars->amos_page + index;
 
 
-	xpc_IPI_receive(part_amo);
-	return part_amo;
+	(void) xpc_IPI_receive(amo);	/* clear AMO variable */
+	return amo;
 }
 
 
@@ -939,7 +1221,7 @@
 
 
 static inline void *
-xpc_kmalloc_cacheline_aligned(size_t size, int flags, void **base)
+xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
 {
 	/* see if kmalloc will give us cachline aligned memory by default */
 	*base = kmalloc(size, flags);
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 94698be..abf4fc2 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -57,6 +57,7 @@
 
 		spin_lock_init(&ch->lock);
 		sema_init(&ch->msg_to_pull_sema, 1);	/* mutex */
+		sema_init(&ch->wdisconnect_sema, 0);	/* event wait */
 
 		atomic_set(&ch->n_on_msg_allocate_wq, 0);
 		init_waitqueue_head(&ch->msg_allocate_wq);
@@ -166,6 +167,7 @@
 	xpc_initialize_channels(part, partid);
 
 	atomic_set(&part->nchannels_active, 0);
+	atomic_set(&part->nchannels_engaged, 0);
 
 
 	/* local_IPI_amo were set to 0 by an earlier memset() */
@@ -555,8 +557,6 @@
 		sema_init(&ch->notify_queue[i].sema, 0);
 	}
 
-	sema_init(&ch->teardown_sema, 0);	/* event wait */
-
 	spin_lock_irqsave(&ch->lock, irq_flags);
 	ch->flags |= XPC_C_SETUP;
 	spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -626,6 +626,55 @@
 
 
 /*
+ * Notify those who wanted to be notified upon delivery of their message.
+ */
+static void
+xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
+{
+	struct xpc_notify *notify;
+	u8 notify_type;
+	s64 get = ch->w_remote_GP.get - 1;
+
+
+	while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
+
+		notify = &ch->notify_queue[get % ch->local_nentries];
+
+		/*
+		 * See if the notify entry indicates it was associated with
+		 * a message who's sender wants to be notified. It is possible
+		 * that it is, but someone else is doing or has done the
+		 * notification.
+		 */
+		notify_type = notify->type;
+		if (notify_type == 0 ||
+				cmpxchg(&notify->type, notify_type, 0) !=
+								notify_type) {
+			continue;
+		}
+
+		DBUG_ON(notify_type != XPC_N_CALL);
+
+		atomic_dec(&ch->n_to_notify);
+
+		if (notify->func != NULL) {
+			dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
+				"msg_number=%ld, partid=%d, channel=%d\n",
+				(void *) notify, get, ch->partid, ch->number);
+
+			notify->func(reason, ch->partid, ch->number,
+								notify->key);
+
+			dev_dbg(xpc_chan, "notify->func() returned, "
+				"notify=0x%p, msg_number=%ld, partid=%d, "
+				"channel=%d\n", (void *) notify, get,
+				ch->partid, ch->number);
+		}
+	}
+}
+
+
+/*
  * Free up message queues and other stuff that were allocated for the specified
  * channel.
  *
@@ -669,9 +718,6 @@
 		ch->remote_msgqueue = NULL;
 		kfree(ch->notify_queue);
 		ch->notify_queue = NULL;
-
-		/* in case someone is waiting for the teardown to complete */
-		up(&ch->teardown_sema);
 	}
 }
 
@@ -683,7 +729,7 @@
 xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
 {
 	struct xpc_partition *part = &xpc_partitions[ch->partid];
-	u32 ch_flags = ch->flags;
+	u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
 
 
 	DBUG_ON(!spin_is_locked(&ch->lock));
@@ -701,12 +747,13 @@
 	}
 	DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
 
-	/* it's now safe to free the channel's message queues */
+	if (part->act_state == XPC_P_DEACTIVATING) {
+		/* can't proceed until the other side disengages from us */
+		if (xpc_partition_engaged(1UL << ch->partid)) {
+			return;
+		}
 
-	xpc_free_msgqueues(ch);
-	DBUG_ON(ch->flags & XPC_C_SETUP);
-
-	if (part->act_state != XPC_P_DEACTIVATING) {
+	} else {
 
 		/* as long as the other side is up do the full protocol */
 
@@ -724,16 +771,42 @@
 		}
 	}
 
+	/* wake those waiting for notify completion */
+	if (atomic_read(&ch->n_to_notify) > 0) {
+		/* >>> we do callout while holding ch->lock */
+		xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put);
+	}
+
 	/* both sides are disconnected now */
 
-	ch->flags = XPC_C_DISCONNECTED;	/* clear all flags, but this one */
+	/* it's now safe to free the channel's message queues */
+	xpc_free_msgqueues(ch);
+
+	/* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */
+	ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
 
 	atomic_dec(&part->nchannels_active);
 
-	if (ch_flags & XPC_C_WASCONNECTED) {
+	if (channel_was_connected) {
 		dev_info(xpc_chan, "channel %d to partition %d disconnected, "
 			"reason=%d\n", ch->number, ch->partid, ch->reason);
 	}
+
+	if (ch->flags & XPC_C_WDISCONNECT) {
+		spin_unlock_irqrestore(&ch->lock, *irq_flags);
+		up(&ch->wdisconnect_sema);
+		spin_lock_irqsave(&ch->lock, *irq_flags);
+
+	} else if (ch->delayed_IPI_flags) {
+		if (part->act_state != XPC_P_DEACTIVATING) {
+			/* time to take action on any delayed IPI flags */
+			spin_lock(&part->IPI_lock);
+			XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
+							ch->delayed_IPI_flags);
+			spin_unlock(&part->IPI_lock);
+		}
+		ch->delayed_IPI_flags = 0;
+	}
 }
 
 
@@ -754,6 +827,19 @@
 
 	spin_lock_irqsave(&ch->lock, irq_flags);
 
+again:
+
+	if ((ch->flags & XPC_C_DISCONNECTED) &&
+					(ch->flags & XPC_C_WDISCONNECT)) {
+		/*
+		 * Delay processing IPI flags until thread waiting disconnect
+		 * has had a chance to see that the channel is disconnected.
+		 */
+		ch->delayed_IPI_flags |= IPI_flags;
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+		return;
+	}
+
 
 	if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
 
@@ -764,7 +850,7 @@
 		/*
 		 * If RCLOSEREQUEST is set, we're probably waiting for
 		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
-		 * with this RCLOSEQREUQEST in the IPI_flags.
+		 * with this RCLOSEREQUEST in the IPI_flags.
 		 */
 
 		if (ch->flags & XPC_C_RCLOSEREQUEST) {
@@ -779,14 +865,22 @@
 
 			/* both sides have finished disconnecting */
 			xpc_process_disconnect(ch, &irq_flags);
+			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+			goto again;
 		}
 
 		if (ch->flags & XPC_C_DISCONNECTED) {
-			// >>> explain this section
-
 			if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
-				DBUG_ON(part->act_state !=
-							XPC_P_DEACTIVATING);
+				if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
+					 ch_number) & XPC_IPI_OPENREQUEST)) {
+
+					DBUG_ON(ch->delayed_IPI_flags != 0);
+					spin_lock(&part->IPI_lock);
+					XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+							ch_number,
+							XPC_IPI_CLOSEREQUEST);
+					spin_unlock(&part->IPI_lock);
+				}
 				spin_unlock_irqrestore(&ch->lock, irq_flags);
 				return;
 			}
@@ -816,9 +910,13 @@
 			}
 
 			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
-		} else {
-			xpc_process_disconnect(ch, &irq_flags);
+
+			DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
 		}
+
+		xpc_process_disconnect(ch, &irq_flags);
 	}
 
 
@@ -834,7 +932,20 @@
 		}
 
 		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
-		DBUG_ON(!(ch->flags & XPC_C_RCLOSEREQUEST));
+
+		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+			if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
+						& XPC_IPI_CLOSEREQUEST)) {
+
+				DBUG_ON(ch->delayed_IPI_flags != 0);
+				spin_lock(&part->IPI_lock);
+				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+						ch_number, XPC_IPI_CLOSEREPLY);
+				spin_unlock(&part->IPI_lock);
+			}
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
 
 		ch->flags |= XPC_C_RCLOSEREPLY;
 
@@ -852,8 +963,14 @@
 			"channel=%d\n", args->msg_size, args->local_nentries,
 			ch->partid, ch->number);
 
-		if ((ch->flags & XPC_C_DISCONNECTING) ||
-					part->act_state == XPC_P_DEACTIVATING) {
+		if (part->act_state == XPC_P_DEACTIVATING ||
+					(ch->flags & XPC_C_ROPENREQUEST)) {
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
+
+		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
+			ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			return;
 		}
@@ -867,8 +984,11 @@
 		 *      msg_size = size of channel's messages in bytes
 		 *      local_nentries = remote partition's local_nentries
 		 */
-		DBUG_ON(args->msg_size == 0);
-		DBUG_ON(args->local_nentries == 0);
+		if (args->msg_size == 0 || args->local_nentries == 0) {
+			/* assume OPENREQUEST was delayed by mistake */
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
 
 		ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
 		ch->remote_nentries = args->local_nentries;
@@ -906,7 +1026,13 @@
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			return;
 		}
-		DBUG_ON(!(ch->flags & XPC_C_OPENREQUEST));
+		if (!(ch->flags & XPC_C_OPENREQUEST)) {
+			XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
+								&irq_flags);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
+
 		DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
 		DBUG_ON(ch->flags & XPC_C_CONNECTED);
 
@@ -960,8 +1086,8 @@
 	struct xpc_registration *registration = &xpc_registrations[ch->number];
 
 
-	if (down_interruptible(&registration->sema) != 0) {
-		return xpcInterrupted;
+	if (down_trylock(&registration->sema) != 0) {
+		return xpcRetry;
 	}
 
 	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
@@ -1040,55 +1166,6 @@
 
 
 /*
- * Notify those who wanted to be notified upon delivery of their message.
- */
-static void
-xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
-{
-	struct xpc_notify *notify;
-	u8 notify_type;
-	s64 get = ch->w_remote_GP.get - 1;
-
-
-	while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
-
-		notify = &ch->notify_queue[get % ch->local_nentries];
-
-		/*
-		 * See if the notify entry indicates it was associated with
-		 * a message who's sender wants to be notified. It is possible
-		 * that it is, but someone else is doing or has done the
-		 * notification.
-		 */
-		notify_type = notify->type;
-		if (notify_type == 0 ||
-				cmpxchg(&notify->type, notify_type, 0) !=
-								notify_type) {
-			continue;
-		}
-
-		DBUG_ON(notify_type != XPC_N_CALL);
-
-		atomic_dec(&ch->n_to_notify);
-
-		if (notify->func != NULL) {
-			dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
-				"msg_number=%ld, partid=%d, channel=%d\n",
-				(void *) notify, get, ch->partid, ch->number);
-
-			notify->func(reason, ch->partid, ch->number,
-								notify->key);
-
-			dev_dbg(xpc_chan, "notify->func() returned, "
-				"notify=0x%p, msg_number=%ld, partid=%d, "
-				"channel=%d\n", (void *) notify, get,
-				ch->partid, ch->number);
-		}
-	}
-}
-
-
-/*
  * Clear some of the msg flags in the local message queue.
  */
 static inline void
@@ -1240,6 +1317,7 @@
 	u64 IPI_amo, IPI_flags;
 	struct xpc_channel *ch;
 	int ch_number;
+	u32 ch_flags;
 
 
 	IPI_amo = xpc_get_IPI_flags(part);
@@ -1266,8 +1344,9 @@
 			xpc_process_openclose_IPI(part, ch_number, IPI_flags);
 		}
 
+		ch_flags = ch->flags;	/* need an atomic snapshot of flags */
 
-		if (ch->flags & XPC_C_DISCONNECTING) {
+		if (ch_flags & XPC_C_DISCONNECTING) {
 			spin_lock_irqsave(&ch->lock, irq_flags);
 			xpc_process_disconnect(ch, &irq_flags);
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
@@ -1278,9 +1357,9 @@
 			continue;
 		}
 
-		if (!(ch->flags & XPC_C_CONNECTED)) {
-			if (!(ch->flags & XPC_C_OPENREQUEST)) {
-				DBUG_ON(ch->flags & XPC_C_SETUP);
+		if (!(ch_flags & XPC_C_CONNECTED)) {
+			if (!(ch_flags & XPC_C_OPENREQUEST)) {
+				DBUG_ON(ch_flags & XPC_C_SETUP);
 				(void) xpc_connect_channel(ch);
 			} else {
 				spin_lock_irqsave(&ch->lock, irq_flags);
@@ -1305,8 +1384,8 @@
 
 
 /*
- * XPC's heartbeat code calls this function to inform XPC that a partition has
- * gone down.  XPC responds by tearing down the XPartition Communication
+ * XPC's heartbeat code calls this function to inform XPC that a partition is
+ * going down.  XPC responds by tearing down the XPartition Communication
  * infrastructure used for the just downed partition.
  *
  * XPC's heartbeat code will never call this function and xpc_partition_up()
@@ -1314,7 +1393,7 @@
  * at the same time.
  */
 void
-xpc_partition_down(struct xpc_partition *part, enum xpc_retval reason)
+xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason)
 {
 	unsigned long irq_flags;
 	int ch_number;
@@ -1330,12 +1409,11 @@
 	}
 
 
-	/* disconnect all channels associated with the downed partition */
+	/* disconnect channels associated with the partition going down */
 
 	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
 		ch = &part->channels[ch_number];
 
-
 		xpc_msgqueue_ref(ch);
 		spin_lock_irqsave(&ch->lock, irq_flags);
 
@@ -1370,6 +1448,7 @@
 	 * this partition.
 	 */
 
+	DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
 	DBUG_ON(atomic_read(&part->nchannels_active) != 0);
 	DBUG_ON(part->setup_state != XPC_P_SETUP);
 	part->setup_state = XPC_P_WTEARDOWN;
@@ -1428,19 +1507,11 @@
 		if (xpc_part_ref(part)) {
 			ch = &part->channels[ch_number];
 
-			if (!(ch->flags & XPC_C_DISCONNECTING)) {
-				DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
-				DBUG_ON(ch->flags & XPC_C_CONNECTED);
-				DBUG_ON(ch->flags & XPC_C_SETUP);
-
-				/*
-				 * Initiate the establishment of a connection
-				 * on the newly registered channel to the
-				 * remote partition.
-				 */
-				xpc_wakeup_channel_mgr(part);
-			}
-
+			/*
+			 * Initiate the establishment of a connection on the
+			 * newly registered channel to the remote partition.
+			 */
+			xpc_wakeup_channel_mgr(part);
 			xpc_part_deref(part);
 		}
 	}
@@ -1450,9 +1521,6 @@
 void
 xpc_connected_callout(struct xpc_channel *ch)
 {
-	unsigned long irq_flags;
-
-
 	/* let the registerer know that a connection has been established */
 
 	if (ch->func != NULL) {
@@ -1465,10 +1533,6 @@
 		dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
 			"partid=%d, channel=%d\n", ch->partid, ch->number);
 	}
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	ch->flags |= XPC_C_CONNECTCALLOUT;
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
 }
 
 
@@ -1506,8 +1570,12 @@
 
 			spin_lock_irqsave(&ch->lock, irq_flags);
 
-			XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
+			if (!(ch->flags & XPC_C_DISCONNECTED)) {
+				ch->flags |= XPC_C_WDISCONNECT;
+
+				XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
 								&irq_flags);
+			}
 
 			spin_unlock_irqrestore(&ch->lock, irq_flags);
 
@@ -1523,8 +1591,9 @@
 /*
  * To disconnect a channel, and reflect it back to all who may be waiting.
  *
- * >>> An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
- * >>> xpc_free_msgqueues().
+ * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+ * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
+ * xpc_disconnect_wait().
  *
  * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
  */
@@ -1532,7 +1601,7 @@
 xpc_disconnect_channel(const int line, struct xpc_channel *ch,
 			enum xpc_retval reason, unsigned long *irq_flags)
 {
-	u32 flags;
+	u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
 
 
 	DBUG_ON(!spin_is_locked(&ch->lock));
@@ -1547,37 +1616,28 @@
 
 	XPC_SET_REASON(ch, reason, line);
 
-	flags = ch->flags;
+	ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
 	/* some of these may not have been set */
 	ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
 			XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
 			XPC_C_CONNECTING | XPC_C_CONNECTED);
 
-	ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
 	xpc_IPI_send_closerequest(ch, irq_flags);
 
-	if (flags & XPC_C_CONNECTED) {
+	if (channel_was_connected) {
 		ch->flags |= XPC_C_WASCONNECTED;
 	}
 
-	if (atomic_read(&ch->kthreads_idle) > 0) {
-		/* wake all idle kthreads so they can exit */
-		wake_up_all(&ch->idle_wq);
-	}
-
 	spin_unlock_irqrestore(&ch->lock, *irq_flags);
 
-
-	/* wake those waiting to allocate an entry from the local msg queue */
-
-	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
-		wake_up(&ch->msg_allocate_wq);
+	/* wake all idle kthreads so they can exit */
+	if (atomic_read(&ch->kthreads_idle) > 0) {
+		wake_up_all(&ch->idle_wq);
 	}
 
-	/* wake those waiting for notify completion */
-
-	if (atomic_read(&ch->n_to_notify) > 0) {
-		xpc_notify_senders(ch, reason, ch->w_local_GP.put);
+	/* wake those waiting to allocate an entry from the local msg queue */
+	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+		wake_up(&ch->msg_allocate_wq);
 	}
 
 	spin_lock_irqsave(&ch->lock, *irq_flags);
@@ -1585,23 +1645,24 @@
 
 
 void
-xpc_disconnected_callout(struct xpc_channel *ch)
+xpc_disconnecting_callout(struct xpc_channel *ch)
 {
 	/*
-	 * Let the channel's registerer know that the channel is now
+	 * Let the channel's registerer know that the channel is being
 	 * disconnected. We don't want to do this if the registerer was never
-	 * informed of a connection being made, unless the disconnect was for
-	 * abnormal reasons.
+	 * informed of a connection being made.
 	 */
 
 	if (ch->func != NULL) {
-		dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
-			"channel=%d\n", ch->reason, ch->partid, ch->number);
+		dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting,"
+			" partid=%d, channel=%d\n", ch->partid, ch->number);
 
-		ch->func(ch->reason, ch->partid, ch->number, NULL, ch->key);
+		ch->func(xpcDisconnecting, ch->partid, ch->number, NULL,
+								ch->key);
 
-		dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
-			"channel=%d\n", ch->reason, ch->partid, ch->number);
+		dev_dbg(xpc_chan, "ch->func() returned, reason="
+			"xpcDisconnecting, partid=%d, channel=%d\n",
+			ch->partid, ch->number);
 	}
 }
 
@@ -1848,7 +1909,7 @@
 			xpc_notify_func func, void *key)
 {
 	enum xpc_retval ret = xpcSuccess;
-	struct xpc_notify *notify = NULL;   // >>> to keep the compiler happy!!
+	struct xpc_notify *notify = notify;
 	s64 put, msg_number = msg->number;
 
 
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index ed7c215..cece3c7 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -54,6 +54,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/uaccess.h>
@@ -82,11 +83,17 @@
 
 /* systune related variables for /proc/sys directories */
 
-static int xpc_hb_min = 1;
-static int xpc_hb_max = 10;
+static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
+static int xpc_hb_min_interval = 1;
+static int xpc_hb_max_interval = 10;
 
-static int xpc_hb_check_min = 10;
-static int xpc_hb_check_max = 120;
+static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
+static int xpc_hb_check_min_interval = 10;
+static int xpc_hb_check_max_interval = 120;
+
+int xpc_disengage_request_timelimit = XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT;
+static int xpc_disengage_request_min_timelimit = 0;
+static int xpc_disengage_request_max_timelimit = 120;
 
 static ctl_table xpc_sys_xpc_hb_dir[] = {
 	{
@@ -99,7 +106,8 @@
 		&proc_dointvec_minmax,
 		&sysctl_intvec,
 		NULL,
-		&xpc_hb_min, &xpc_hb_max
+		&xpc_hb_min_interval,
+		&xpc_hb_max_interval
 	},
 	{
 		2,
@@ -111,7 +119,8 @@
 		&proc_dointvec_minmax,
 		&sysctl_intvec,
 		NULL,
-		&xpc_hb_check_min, &xpc_hb_check_max
+		&xpc_hb_check_min_interval,
+		&xpc_hb_check_max_interval
 	},
 	{0}
 };
@@ -124,6 +133,19 @@
 		0555,
 		xpc_sys_xpc_hb_dir
 	},
+	{
+		2,
+		"disengage_request_timelimit",
+		&xpc_disengage_request_timelimit,
+		sizeof(int),
+		0644,
+		NULL,
+		&proc_dointvec_minmax,
+		&sysctl_intvec,
+		NULL,
+		&xpc_disengage_request_min_timelimit,
+		&xpc_disengage_request_max_timelimit
+	},
 	{0}
 };
 static ctl_table xpc_sys_dir[] = {
@@ -148,10 +170,10 @@
 
 static unsigned long xpc_hb_check_timeout;
 
-/* xpc_hb_checker thread exited notification */
+/* notification that the xpc_hb_checker thread has exited */
 static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
 
-/* xpc_discovery thread exited notification */
+/* notification that the xpc_discovery thread has exited */
 static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
 
 
@@ -161,6 +183,30 @@
 static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
 
 
+static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
+static struct notifier_block xpc_reboot_notifier = {
+	.notifier_call = xpc_system_reboot,
+};
+
+
+/*
+ * Timer function to enforce the timelimit on the partition disengage request.
+ */
+static void
+xpc_timeout_partition_disengage_request(unsigned long data)
+{
+	struct xpc_partition *part = (struct xpc_partition *) data;
+
+
+	DBUG_ON(jiffies < part->disengage_request_timeout);
+
+	(void) xpc_partition_disengaged(part);
+
+	DBUG_ON(part->disengage_request_timeout != 0);
+	DBUG_ON(xpc_partition_engaged(1UL << XPC_PARTID(part)) != 0);
+}
+
+
 /*
  * Notify the heartbeat check thread that an IRQ has been received.
  */
@@ -214,12 +260,6 @@
 
 	while (!(volatile int) xpc_exiting) {
 
-		/* wait for IRQ or timeout */
-		(void) wait_event_interruptible(xpc_act_IRQ_wq,
-			    (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
-					jiffies >= xpc_hb_check_timeout ||
-						(volatile int) xpc_exiting));
-
 		dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
 			"been received\n",
 			(int) (xpc_hb_check_timeout - jiffies),
@@ -240,6 +280,7 @@
 		}
 
 
+		/* check for outstanding IRQs */
 		new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
 		if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
 			force_IRQ = 0;
@@ -257,12 +298,18 @@
 			xpc_hb_check_timeout = jiffies +
 					   (xpc_hb_check_interval * HZ);
 		}
+
+		/* wait for IRQ or timeout */
+		(void) wait_event_interruptible(xpc_act_IRQ_wq,
+			    (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
+					jiffies >= xpc_hb_check_timeout ||
+						(volatile int) xpc_exiting));
 	}
 
 	dev_dbg(xpc_part, "heartbeat checker is exiting\n");
 
 
-	/* mark this thread as inactive */
+	/* mark this thread as having exited */
 	up(&xpc_hb_checker_exited);
 	return 0;
 }
@@ -282,7 +329,7 @@
 
 	dev_dbg(xpc_part, "discovery thread is exiting\n");
 
-	/* mark this thread as inactive */
+	/* mark this thread as having exited */
 	up(&xpc_discovery_exited);
 	return 0;
 }
@@ -309,7 +356,7 @@
 			"partition %d\n", XPC_PARTID(part));
 
 		/* wait a 1/4 of a second or so */
-		msleep_interruptible(250);
+		(void) msleep_interruptible(250);
 
 		if (part->act_state == XPC_P_DEACTIVATING) {
 			return part->reason;
@@ -336,7 +383,8 @@
 xpc_channel_mgr(struct xpc_partition *part)
 {
 	while (part->act_state != XPC_P_DEACTIVATING ||
-				atomic_read(&part->nchannels_active) > 0) {
+			atomic_read(&part->nchannels_active) > 0 ||
+					!xpc_partition_disengaged(part)) {
 
 		xpc_process_channel_activity(part);
 
@@ -360,7 +408,8 @@
 				(volatile u64) part->local_IPI_amo != 0 ||
 				((volatile u8) part->act_state ==
 							XPC_P_DEACTIVATING &&
-				atomic_read(&part->nchannels_active) == 0)));
+				atomic_read(&part->nchannels_active) == 0 &&
+				xpc_partition_disengaged(part))));
 		atomic_set(&part->channel_mgr_requests, 1);
 
 		// >>> Does it need to wakeup periodically as well? In case we
@@ -482,7 +531,7 @@
 		return 0;
 	}
 
-	XPC_ALLOW_HB(partid, xpc_vars);
+	xpc_allow_hb(partid, xpc_vars);
 	xpc_IPI_send_activated(part);
 
 
@@ -492,6 +541,7 @@
 	 */
 	(void) xpc_partition_up(part);
 
+	xpc_disallow_hb(partid, xpc_vars);
 	xpc_mark_partition_inactive(part);
 
 	if (part->reason == xpcReactivating) {
@@ -670,6 +720,7 @@
 	struct xpc_partition *part = &xpc_partitions[partid];
 	struct xpc_channel *ch;
 	int n_needed;
+	unsigned long irq_flags;
 
 
 	daemonize("xpc%02dc%d", partid, ch_number);
@@ -680,11 +731,14 @@
 	ch = &part->channels[ch_number];
 
 	if (!(ch->flags & XPC_C_DISCONNECTING)) {
-		DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
 
 		/* let registerer know that connection has been established */
 
-		if (atomic_read(&ch->kthreads_assigned) == 1) {
+		spin_lock_irqsave(&ch->lock, irq_flags);
+		if (!(ch->flags & XPC_C_CONNECTCALLOUT)) {
+			ch->flags |= XPC_C_CONNECTCALLOUT;
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+
 			xpc_connected_callout(ch);
 
 			/*
@@ -699,16 +753,28 @@
 					!(ch->flags & XPC_C_DISCONNECTING)) {
 				xpc_activate_kthreads(ch, n_needed);
 			}
+		} else {
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
 		}
 
 		xpc_kthread_waitmsgs(part, ch);
 	}
 
-	if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
-			((ch->flags & XPC_C_CONNECTCALLOUT) ||
-				(ch->reason != xpcUnregistering &&
-					ch->reason != xpcOtherUnregistering))) {
-		xpc_disconnected_callout(ch);
+	if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
+		spin_lock_irqsave(&ch->lock, irq_flags);
+		if ((ch->flags & XPC_C_CONNECTCALLOUT) &&
+				!(ch->flags & XPC_C_DISCONNECTCALLOUT)) {
+			ch->flags |= XPC_C_DISCONNECTCALLOUT;
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+			xpc_disconnecting_callout(ch);
+		} else {
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+		}
+		if (atomic_dec_return(&part->nchannels_engaged) == 0) {
+			xpc_mark_partition_disengaged(part);
+			xpc_IPI_send_disengage(part);
+		}
 	}
 
 
@@ -740,12 +806,33 @@
 	unsigned long irq_flags;
 	pid_t pid;
 	u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
+	struct xpc_partition *part = &xpc_partitions[ch->partid];
 
 
 	while (needed-- > 0) {
+
+		/*
+		 * The following is done on behalf of the newly created
+		 * kthread. That kthread is responsible for doing the
+		 * counterpart to the following before it exits.
+		 */
+		(void) xpc_part_ref(part);
+		xpc_msgqueue_ref(ch);
+		if (atomic_inc_return(&ch->kthreads_assigned) == 1 &&
+		    atomic_inc_return(&part->nchannels_engaged) == 1) {
+			xpc_mark_partition_engaged(part);
+		}
+
 		pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
 		if (pid < 0) {
 			/* the fork failed */
+			if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
+			    atomic_dec_return(&part->nchannels_engaged) == 0) {
+				xpc_mark_partition_disengaged(part);
+				xpc_IPI_send_disengage(part);
+			}
+			xpc_msgqueue_deref(ch);
+			xpc_part_deref(part);
 
 			if (atomic_read(&ch->kthreads_assigned) <
 						ch->kthreads_idle_limit) {
@@ -765,14 +852,6 @@
 			break;
 		}
 
-		/*
-		 * The following is done on behalf of the newly created
-		 * kthread. That kthread is responsible for doing the
-		 * counterpart to the following before it exits.
-		 */
-		(void) xpc_part_ref(&xpc_partitions[ch->partid]);
-		xpc_msgqueue_ref(ch);
-		atomic_inc(&ch->kthreads_assigned);
 		ch->kthreads_created++;	// >>> temporary debug only!!!
 	}
 }
@@ -781,87 +860,142 @@
 void
 xpc_disconnect_wait(int ch_number)
 {
+	unsigned long irq_flags;
 	partid_t partid;
 	struct xpc_partition *part;
 	struct xpc_channel *ch;
+	int wakeup_channel_mgr;
 
 
 	/* now wait for all callouts to the caller's function to cease */
 	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
 		part = &xpc_partitions[partid];
 
-		if (xpc_part_ref(part)) {
-			ch = &part->channels[ch_number];
-
-// >>> how do we keep from falling into the window between our check and going
-// >>> down and coming back up where sema is re-inited?
-			if (ch->flags & XPC_C_SETUP) {
-				(void) down(&ch->teardown_sema);
-			}
-
-			xpc_part_deref(part);
+		if (!xpc_part_ref(part)) {
+			continue;
 		}
+
+		ch = &part->channels[ch_number];
+
+		if (!(ch->flags & XPC_C_WDISCONNECT)) {
+			xpc_part_deref(part);
+			continue;
+		}
+
+		(void) down(&ch->wdisconnect_sema);
+
+		spin_lock_irqsave(&ch->lock, irq_flags);
+		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+		wakeup_channel_mgr = 0;
+
+		if (ch->delayed_IPI_flags) {
+			if (part->act_state != XPC_P_DEACTIVATING) {
+				spin_lock(&part->IPI_lock);
+				XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+					ch->number, ch->delayed_IPI_flags);
+				spin_unlock(&part->IPI_lock);
+				wakeup_channel_mgr = 1;
+			}
+			ch->delayed_IPI_flags = 0;
+		}
+
+		ch->flags &= ~XPC_C_WDISCONNECT;
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+		if (wakeup_channel_mgr) {
+			xpc_wakeup_channel_mgr(part);
+		}
+
+		xpc_part_deref(part);
 	}
 }
 
 
 static void
-xpc_do_exit(void)
+xpc_do_exit(enum xpc_retval reason)
 {
 	partid_t partid;
 	int active_part_count;
 	struct xpc_partition *part;
+	unsigned long printmsg_time;
 
 
-	/* now it's time to eliminate our heartbeat */
-	del_timer_sync(&xpc_hb_timer);
-	xpc_vars->heartbeating_to_mask = 0;
-
-	/* indicate to others that our reserved page is uninitialized */
-	xpc_rsvd_page->vars_pa = 0;
+	/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
+	DBUG_ON(xpc_exiting == 1);
 
 	/*
-	 * Ignore all incoming interrupts. Without interupts the heartbeat
-	 * checker won't activate any new partitions that may come up.
-	 */
-	free_irq(SGI_XPC_ACTIVATE, NULL);
-
-	/*
-	 * Cause the heartbeat checker and the discovery threads to exit.
-	 * We don't want them attempting to activate new partitions as we
-	 * try to deactivate the existing ones.
+	 * Let the heartbeat checker thread and the discovery thread
+	 * (if one is running) know that they should exit. Also wake up
+	 * the heartbeat checker thread in case it's sleeping.
 	 */
 	xpc_exiting = 1;
 	wake_up_interruptible(&xpc_act_IRQ_wq);
 
-	/* wait for the heartbeat checker thread to mark itself inactive */
-	down(&xpc_hb_checker_exited);
+	/* ignore all incoming interrupts */
+	free_irq(SGI_XPC_ACTIVATE, NULL);
 
-	/* wait for the discovery thread to mark itself inactive */
+	/* wait for the discovery thread to exit */
 	down(&xpc_discovery_exited);
 
+	/* wait for the heartbeat checker thread to exit */
+	down(&xpc_hb_checker_exited);
 
-	msleep_interruptible(300);
+
+	/* sleep for a 1/3 of a second or so */
+	(void) msleep_interruptible(300);
 
 
 	/* wait for all partitions to become inactive */
 
+	printmsg_time = jiffies;
+
 	do {
 		active_part_count = 0;
 
 		for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
 			part = &xpc_partitions[partid];
-			if (part->act_state != XPC_P_INACTIVE) {
-				active_part_count++;
 
-				XPC_DEACTIVATE_PARTITION(part, xpcUnloading);
+			if (xpc_partition_disengaged(part) &&
+					part->act_state == XPC_P_INACTIVE) {
+				continue;
 			}
+
+			active_part_count++;
+
+			XPC_DEACTIVATE_PARTITION(part, reason);
 		}
 
-		if (active_part_count)
-			msleep_interruptible(300);
-	} while (active_part_count > 0);
+		if (active_part_count == 0) {
+			break;
+		}
 
+		if (jiffies >= printmsg_time) {
+			dev_info(xpc_part, "waiting for partitions to "
+				"deactivate/disengage, active count=%d, remote "
+				"engaged=0x%lx\n", active_part_count,
+				xpc_partition_engaged(1UL << partid));
+
+			printmsg_time = jiffies +
+					(XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+		}
+
+		/* sleep for a 1/3 of a second or so */
+		(void) msleep_interruptible(300);
+
+	} while (1);
+
+	DBUG_ON(xpc_partition_engaged(-1UL));
+
+
+	/* indicate to others that our reserved page is uninitialized */
+	xpc_rsvd_page->vars_pa = 0;
+
+	/* now it's time to eliminate our heartbeat */
+	del_timer_sync(&xpc_hb_timer);
+	DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
+
+	/* take ourselves off of the reboot_notifier_list */
+	(void) unregister_reboot_notifier(&xpc_reboot_notifier);
 
 	/* close down protections for IPI operations */
 	xpc_restrict_IPI_ops();
@@ -876,6 +1010,34 @@
 }
 
 
+/*
+ * This function is called when the system is being rebooted.
+ */
+static int
+xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
+{
+	enum xpc_retval reason;
+
+
+	switch (event) {
+	case SYS_RESTART:
+		reason = xpcSystemReboot;
+		break;
+	case SYS_HALT:
+		reason = xpcSystemHalt;
+		break;
+	case SYS_POWER_OFF:
+		reason = xpcSystemPoweroff;
+		break;
+	default:
+		reason = xpcSystemGoingDown;
+	}
+
+	xpc_do_exit(reason);
+	return NOTIFY_DONE;
+}
+
+
 int __init
 xpc_init(void)
 {
@@ -891,11 +1053,11 @@
 
 	/*
 	 * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
-	 * both a partition's reserved page and its XPC variables. Its size was
-	 * based on the size of a reserved page. So we need to ensure that the
-	 * XPC variables will fit as well.
+	 * various portions of a partition's reserved page. Its size is based
+	 * on the size of the reserved page header and part_nasids mask. So we
+	 * need to ensure that the other items will fit as well.
 	 */
-	if (XPC_VARS_ALIGNED_SIZE > XPC_RSVD_PAGE_ALIGNED_SIZE) {
+	if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) {
 		dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
 		return -EPERM;
 	}
@@ -924,6 +1086,12 @@
 		spin_lock_init(&part->act_lock);
 		part->act_state = XPC_P_INACTIVE;
 		XPC_SET_REASON(part, 0, 0);
+
+		init_timer(&part->disengage_request_timer);
+		part->disengage_request_timer.function =
+				xpc_timeout_partition_disengage_request;
+		part->disengage_request_timer.data = (unsigned long) part;
+
 		part->setup_state = XPC_P_UNSET;
 		init_waitqueue_head(&part->teardown_wq);
 		atomic_set(&part->references, 0);
@@ -980,6 +1148,13 @@
 	}
 
 
+	/* add ourselves to the reboot_notifier_list */
+	ret = register_reboot_notifier(&xpc_reboot_notifier);
+	if (ret != 0) {
+		dev_warn(xpc_part, "can't register reboot notifier\n");
+	}
+
+
 	/*
 	 * Set the beating to other partitions into motion.  This is
 	 * the last requirement for other partitions' discovery to
@@ -1001,6 +1176,9 @@
 		/* indicate to others that our reserved page is uninitialized */
 		xpc_rsvd_page->vars_pa = 0;
 
+		/* take ourselves off of the reboot_notifier_list */
+		(void) unregister_reboot_notifier(&xpc_reboot_notifier);
+
 		del_timer_sync(&xpc_hb_timer);
 		free_irq(SGI_XPC_ACTIVATE, NULL);
 		xpc_restrict_IPI_ops();
@@ -1024,7 +1202,7 @@
 		/* mark this new thread as a non-starter */
 		up(&xpc_discovery_exited);
 
-		xpc_do_exit();
+		xpc_do_exit(xpcUnloading);
 		return -EBUSY;
 	}
 
@@ -1043,7 +1221,7 @@
 void __exit
 xpc_exit(void)
 {
-	xpc_do_exit();
+	xpc_do_exit(xpcUnloading);
 }
 module_exit(xpc_exit);
 
@@ -1060,3 +1238,7 @@
 MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
 		"heartbeat checks.");
 
+module_param(xpc_disengage_request_timelimit, int, 0);
+MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
+		"for disengage request to complete.");
+
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 578265e..581e113 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -44,16 +44,19 @@
 
 
 /* original protection values for each node */
-u64 xpc_prot_vec[MAX_COMPACT_NODES];
+u64 xpc_prot_vec[MAX_NUMNODES];
 
 
-/* this partition's reserved page */
+/* this partition's reserved page pointers */
 struct xpc_rsvd_page *xpc_rsvd_page;
-
-/* this partition's XPC variables (within the reserved page) */
+static u64 *xpc_part_nasids;
+static u64 *xpc_mach_nasids;
 struct xpc_vars *xpc_vars;
 struct xpc_vars_part *xpc_vars_part;
 
+static int xp_nasid_mask_bytes;	/* actual size in bytes of nasid mask */
+static int xp_nasid_mask_words;	/* actual size in words of nasid mask */
+
 
 /*
  * For performance reasons, each entry of xpc_partitions[] is cacheline
@@ -65,20 +68,16 @@
 
 
 /*
- * Generic buffer used to store a local copy of the remote partitions
- * reserved page or XPC variables.
+ * Generic buffer used to store a local copy of portions of a remote
+ * partition's reserved page (either its header and part_nasids mask,
+ * or its vars).
  *
  * xpc_discovery runs only once and is a seperate thread that is
  * very likely going to be processing in parallel with receiving
  * interrupts.
  */
-char ____cacheline_aligned
-		xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE];
-
-
-/* systune related variables */
-int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
-int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_TIMEOUT;
+char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
+							XP_NASID_MASK_BYTES];
 
 
 /*
@@ -86,13 +85,16 @@
  * for that nasid. This function returns 0 on any error.
  */
 static u64
-xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)
+xpc_get_rsvd_page_pa(int nasid)
 {
 	bte_result_t bte_res;
 	s64 status;
 	u64 cookie = 0;
 	u64 rp_pa = nasid;	/* seed with nasid */
 	u64 len = 0;
+	u64 buf = buf;
+	u64 buf_len = 0;
+	void *buf_base = NULL;
 
 
 	while (1) {
@@ -108,13 +110,22 @@
 			break;
 		}
 
-		if (len > buf_size) {
-			dev_err(xpc_part, "len (=0x%016lx) > buf_size\n", len);
-			status = SALRET_ERROR;
-			break;
+		if (L1_CACHE_ALIGN(len) > buf_len) {
+			if (buf_base != NULL) {
+				kfree(buf_base);
+			}
+			buf_len = L1_CACHE_ALIGN(len);
+			buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
+							GFP_KERNEL, &buf_base);
+			if (buf_base == NULL) {
+				dev_err(xpc_part, "unable to kmalloc "
+					"len=0x%016lx\n", buf_len);
+				status = SALRET_ERROR;
+				break;
+			}
 		}
 
-		bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_size,
+		bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len,
 					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 		if (bte_res != BTE_SUCCESS) {
 			dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
@@ -123,6 +134,10 @@
 		}
 	}
 
+	if (buf_base != NULL) {
+		kfree(buf_base);
+	}
+
 	if (status != SALRET_OK) {
 		rp_pa = 0;
 	}
@@ -141,15 +156,15 @@
 {
 	struct xpc_rsvd_page *rp;
 	AMO_t *amos_page;
-	u64 rp_pa, next_cl, nasid_array = 0;
+	u64 rp_pa, nasid_array = 0;
 	int i, ret;
 
 
 	/* get the local reserved page's address */
 
-	rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),
-					(u64) xpc_remote_copy_buffer,
-						XPC_RSVD_PAGE_ALIGNED_SIZE);
+	preempt_disable();
+	rp_pa = xpc_get_rsvd_page_pa(cpuid_to_nasid(smp_processor_id()));
+	preempt_enable();
 	if (rp_pa == 0) {
 		dev_err(xpc_part, "SAL failed to locate the reserved page\n");
 		return NULL;
@@ -164,12 +179,19 @@
 
 	rp->version = XPC_RP_VERSION;
 
-	/*
-	 * Place the XPC variables on the cache line following the
-	 * reserved page structure.
-	 */
-	next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE;
-	xpc_vars = (struct xpc_vars *) next_cl;
+	/* establish the actual sizes of the nasid masks */
+	if (rp->SAL_version == 1) {
+		/* SAL_version 1 didn't set the nasids_size field */
+		rp->nasids_size = 128;
+	}
+	xp_nasid_mask_bytes = rp->nasids_size;
+	xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
+
+	/* setup the pointers to the various items in the reserved page */
+	xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
+	xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
+	xpc_vars = XPC_RP_VARS(rp);
+	xpc_vars_part = XPC_RP_VARS_PART(rp);
 
 	/*
 	 * Before clearing xpc_vars, see if a page of AMOs had been previously
@@ -221,33 +243,32 @@
 		amos_page = (AMO_t *) TO_AMO((u64) amos_page);
 	}
 
+	/* clear xpc_vars */
 	memset(xpc_vars, 0, sizeof(struct xpc_vars));
 
-	/*
-	 * Place the XPC per partition specific variables on the cache line
-	 * following the XPC variables structure.
-	 */
-	next_cl += XPC_VARS_ALIGNED_SIZE;
-	memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *
-							XP_MAX_PARTITIONS);
-	xpc_vars_part = (struct xpc_vars_part *) next_cl;
-	xpc_vars->vars_part_pa = __pa(next_cl);
-
 	xpc_vars->version = XPC_V_VERSION;
 	xpc_vars->act_nasid = cpuid_to_nasid(0);
 	xpc_vars->act_phys_cpuid = cpu_physical_id(0);
+	xpc_vars->vars_part_pa = __pa(xpc_vars_part);
+	xpc_vars->amos_page_pa = ia64_tpa((u64) amos_page);
 	xpc_vars->amos_page = amos_page;  /* save for next load of XPC */
 
 
-	/*
-	 * Initialize the activation related AMO variables.
-	 */
-	xpc_vars->act_amos = xpc_IPI_init(XP_MAX_PARTITIONS);
-	for (i = 1; i < XP_NASID_MASK_WORDS; i++) {
-		xpc_IPI_init(i + XP_MAX_PARTITIONS);
+	/* clear xpc_vars_part */
+	memset((u64 *) xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
+							XP_MAX_PARTITIONS);
+
+	/* initialize the activate IRQ related AMO variables */
+	for (i = 0; i < xp_nasid_mask_words; i++) {
+		(void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
 	}
-	/* export AMO page's physical address to other partitions */
-	xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);
+
+	/* initialize the engaged remote partitions related AMO variables */
+	(void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
+	(void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
+
+	/* timestamp of when reserved page was setup by XPC */
+	rp->stamp = CURRENT_TIME;
 
 	/*
 	 * This signifies to the remote partition that our reserved
@@ -387,6 +408,11 @@
 	remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
 
 	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+
+		if (xpc_exiting) {
+			break;
+		}
+
 		if (partid == sn_partition_id) {
 			continue;
 		}
@@ -401,7 +427,7 @@
 		/* pull the remote_hb cache line */
 		bres = xp_bte_copy(part->remote_vars_pa,
 					ia64_tpa((u64) remote_vars),
-					XPC_VARS_ALIGNED_SIZE,
+					XPC_RP_VARS_SIZE,
 					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 		if (bres != BTE_SUCCESS) {
 			XPC_DEACTIVATE_PARTITION(part,
@@ -417,7 +443,7 @@
 
 		if (((remote_vars->heartbeat == part->last_heartbeat) &&
 			(remote_vars->kdb_status == 0)) ||
-			     !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+			     !xpc_hb_allowed(sn_partition_id, remote_vars)) {
 
 			XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
 			continue;
@@ -429,31 +455,31 @@
 
 
 /*
- * Get a copy of the remote partition's rsvd page.
+ * Get a copy of a portion of the remote partition's rsvd page.
  *
  * remote_rp points to a buffer that is cacheline aligned for BTE copies and
- * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE.
+ * is large enough to contain a copy of their reserved page header and
+ * part_nasids mask.
  */
 static enum xpc_retval
 xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
-		struct xpc_rsvd_page *remote_rp, u64 *remote_rsvd_page_pa)
+		struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa)
 {
 	int bres, i;
 
 
 	/* get the reserved page's physical address */
 
-	*remote_rsvd_page_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,
-						XPC_RSVD_PAGE_ALIGNED_SIZE);
-	if (*remote_rsvd_page_pa == 0) {
+	*remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
+	if (*remote_rp_pa == 0) {
 		return xpcNoRsvdPageAddr;
 	}
 
 
-	/* pull over the reserved page structure */
+	/* pull over the reserved page header and part_nasids mask */
 
-	bres = xp_bte_copy(*remote_rsvd_page_pa, ia64_tpa((u64) remote_rp),
-				XPC_RSVD_PAGE_ALIGNED_SIZE,
+	bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
+				XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
 				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 	if (bres != BTE_SUCCESS) {
 		return xpc_map_bte_errors(bres);
@@ -461,8 +487,11 @@
 
 
 	if (discovered_nasids != NULL) {
-		for (i = 0; i < XP_NASID_MASK_WORDS; i++) {
-			discovered_nasids[i] |= remote_rp->part_nasids[i];
+		u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
+
+
+		for (i = 0; i < xp_nasid_mask_words; i++) {
+			discovered_nasids[i] |= remote_part_nasids[i];
 		}
 	}
 
@@ -489,10 +518,10 @@
 
 
 /*
- * Get a copy of the remote partition's XPC variables.
+ * Get a copy of the remote partition's XPC variables from the reserved page.
  *
  * remote_vars points to a buffer that is cacheline aligned for BTE copies and
- * assumed to be of size XPC_VARS_ALIGNED_SIZE.
+ * assumed to be of size XPC_RP_VARS_SIZE.
  */
 static enum xpc_retval
 xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
@@ -508,7 +537,7 @@
 	/* pull over the cross partition variables */
 
 	bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
-				XPC_VARS_ALIGNED_SIZE,
+				XPC_RP_VARS_SIZE,
 				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 	if (bres != BTE_SUCCESS) {
 		return xpc_map_bte_errors(bres);
@@ -524,7 +553,56 @@
 
 
 /*
- * Prior code has determine the nasid which generated an IPI.  Inspect
+ * Update the remote partition's info.
+ */
+static void
+xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version,
+		struct timespec *remote_rp_stamp, u64 remote_rp_pa,
+		u64 remote_vars_pa, struct xpc_vars *remote_vars)
+{
+	part->remote_rp_version = remote_rp_version;
+	dev_dbg(xpc_part, "  remote_rp_version = 0x%016lx\n",
+		part->remote_rp_version);
+
+	part->remote_rp_stamp = *remote_rp_stamp;
+	dev_dbg(xpc_part, "  remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
+		part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
+
+	part->remote_rp_pa = remote_rp_pa;
+	dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
+
+	part->remote_vars_pa = remote_vars_pa;
+	dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
+		part->remote_vars_pa);
+
+	part->last_heartbeat = remote_vars->heartbeat;
+	dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
+		part->last_heartbeat);
+
+	part->remote_vars_part_pa = remote_vars->vars_part_pa;
+	dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
+		part->remote_vars_part_pa);
+
+	part->remote_act_nasid = remote_vars->act_nasid;
+	dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
+		part->remote_act_nasid);
+
+	part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
+	dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
+		part->remote_act_phys_cpuid);
+
+	part->remote_amos_page_pa = remote_vars->amos_page_pa;
+	dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
+		part->remote_amos_page_pa);
+
+	part->remote_vars_version = remote_vars->version;
+	dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
+		part->remote_vars_version);
+}
+
+
+/*
+ * Prior code has determined the nasid which generated an IPI.  Inspect
  * that nasid to determine if its partition needs to be activated or
  * deactivated.
  *
@@ -542,8 +620,12 @@
 {
 	struct xpc_rsvd_page *remote_rp;
 	struct xpc_vars *remote_vars;
-	u64 remote_rsvd_page_pa;
+	u64 remote_rp_pa;
 	u64 remote_vars_pa;
+	int remote_rp_version;
+	int reactivate = 0;
+	int stamp_diff;
+	struct timespec remote_rp_stamp = { 0, 0 };
 	partid_t partid;
 	struct xpc_partition *part;
 	enum xpc_retval ret;
@@ -553,7 +635,7 @@
 
 	remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;
 
-	ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rsvd_page_pa);
+	ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
 	if (ret != xpcSuccess) {
 		dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
 			"which sent interrupt, reason=%d\n", nasid, ret);
@@ -561,6 +643,10 @@
 	}
 
 	remote_vars_pa = remote_rp->vars_pa;
+	remote_rp_version = remote_rp->version;
+	if (XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+		remote_rp_stamp = remote_rp->stamp;
+	}
 	partid = remote_rp->partid;
 	part = &xpc_partitions[partid];
 
@@ -586,44 +672,117 @@
 		"%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,
 		remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
 
+	if (xpc_partition_disengaged(part) &&
+					part->act_state == XPC_P_INACTIVE) {
 
-	if (part->act_state == XPC_P_INACTIVE) {
+		xpc_update_partition_info(part, remote_rp_version,
+					&remote_rp_stamp, remote_rp_pa,
+					remote_vars_pa, remote_vars);
 
-		part->remote_rp_pa = remote_rsvd_page_pa;
-		dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n",
-			part->remote_rp_pa);
-
-		part->remote_vars_pa = remote_vars_pa;
-		dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
-			part->remote_vars_pa);
-
-		part->last_heartbeat = remote_vars->heartbeat;
-		dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
-			part->last_heartbeat);
-
-		part->remote_vars_part_pa = remote_vars->vars_part_pa;
-		dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
-			part->remote_vars_part_pa);
-
-		part->remote_act_nasid = remote_vars->act_nasid;
-		dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
-			part->remote_act_nasid);
-
-		part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
-		dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
-			part->remote_act_phys_cpuid);
-
-		part->remote_amos_page_pa = remote_vars->amos_page_pa;
-		dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
-			part->remote_amos_page_pa);
+		if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+			if (xpc_partition_disengage_requested(1UL << partid)) {
+				/*
+				 * Other side is waiting on us to disengage,
+				 * even though we already have.
+				 */
+				return;
+			}
+		} else {
+			/* other side doesn't support disengage requests */
+			xpc_clear_partition_disengage_request(1UL << partid);
+		}
 
 		xpc_activate_partition(part);
+		return;
+	}
 
-	} else if (part->remote_amos_page_pa != remote_vars->amos_page_pa ||
-			!XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+	DBUG_ON(part->remote_rp_version == 0);
+	DBUG_ON(part->remote_vars_version == 0);
 
+	if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
+		DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+							remote_vars_version));
+
+		if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+			DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+								version));
+			/* see if the other side rebooted */
+			if (part->remote_amos_page_pa ==
+				remote_vars->amos_page_pa &&
+					xpc_hb_allowed(sn_partition_id,
+								remote_vars)) {
+				/* doesn't look that way, so ignore the IPI */
+				return;
+			}
+		}
+
+		/*
+		 * Other side rebooted and previous XPC didn't support the
+		 * disengage request, so we don't need to do anything special.
+		 */
+
+		xpc_update_partition_info(part, remote_rp_version,
+						&remote_rp_stamp, remote_rp_pa,
+						remote_vars_pa, remote_vars);
 		part->reactivate_nasid = nasid;
 		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+		return;
+	}
+
+	DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
+
+	if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+		DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
+
+		/*
+		 * Other side rebooted and previous XPC did support the
+		 * disengage request, but the new one doesn't.
+		 */
+
+		xpc_clear_partition_engaged(1UL << partid);
+		xpc_clear_partition_disengage_request(1UL << partid);
+
+		xpc_update_partition_info(part, remote_rp_version,
+						&remote_rp_stamp, remote_rp_pa,
+						remote_vars_pa, remote_vars);
+		reactivate = 1;
+
+	} else {
+		DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
+
+		stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
+							&remote_rp_stamp);
+		if (stamp_diff != 0) {
+			DBUG_ON(stamp_diff >= 0);
+
+			/*
+			 * Other side rebooted and the previous XPC did support
+			 * the disengage request, as does the new one.
+			 */
+
+			DBUG_ON(xpc_partition_engaged(1UL << partid));
+			DBUG_ON(xpc_partition_disengage_requested(1UL <<
+								partid));
+
+			xpc_update_partition_info(part, remote_rp_version,
+						&remote_rp_stamp, remote_rp_pa,
+						remote_vars_pa, remote_vars);
+			reactivate = 1;
+		}
+	}
+
+	if (!xpc_partition_disengaged(part)) {
+		/* still waiting on other side to disengage from us */
+		return;
+	}
+
+	if (reactivate) {
+		part->reactivate_nasid = nasid;
+		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+
+	} else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
+			xpc_partition_disengage_requested(1UL << partid)) {
+		XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown);
 	}
 }
 
@@ -643,14 +802,17 @@
 	u64 nasid;			/* remote nasid */
 	int n_IRQs_detected = 0;
 	AMO_t *act_amos;
-	struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
 
 
-	act_amos = xpc_vars->act_amos;
+	act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
 
 
 	/* scan through act AMO variable looking for non-zero entries */
-	for (word = 0; word < XP_NASID_MASK_WORDS; word++) {
+	for (word = 0; word < xp_nasid_mask_words; word++) {
+
+		if (xpc_exiting) {
+			break;
+		}
 
 		nasid_mask = xpc_IPI_receive(&act_amos[word]);
 		if (nasid_mask == 0) {
@@ -668,7 +830,7 @@
 		 * remote nasid in our reserved pages machine mask.
 		 * This is used in the event of module reload.
 		 */
-		rp->mach_nasids[word] |= nasid_mask;
+		xpc_mach_nasids[word] |= nasid_mask;
 
 
 		/* locate the nasid(s) which sent interrupts */
@@ -688,6 +850,55 @@
 
 
 /*
+ * See if the other side has responded to a partition disengage request
+ * from us.
+ */
+int
+xpc_partition_disengaged(struct xpc_partition *part)
+{
+	partid_t partid = XPC_PARTID(part);
+	int disengaged;
+
+
+	disengaged = (xpc_partition_engaged(1UL << partid) == 0);
+	if (part->disengage_request_timeout) {
+		if (!disengaged) {
+			if (jiffies < part->disengage_request_timeout) {
+				/* timelimit hasn't been reached yet */
+				return 0;
+			}
+
+			/*
+			 * Other side hasn't responded to our disengage
+			 * request in a timely fashion, so assume it's dead.
+			 */
+
+			xpc_clear_partition_engaged(1UL << partid);
+			disengaged = 1;
+		}
+		part->disengage_request_timeout = 0;
+
+		/* cancel the timer function, provided it's not us */
+		if (!in_interrupt()) {
+			del_singleshot_timer_sync(&part->
+						      disengage_request_timer);
+		}
+
+		DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
+					part->act_state != XPC_P_INACTIVE);
+		if (part->act_state != XPC_P_INACTIVE) {
+			xpc_wakeup_channel_mgr(part);
+		}
+
+		if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+			xpc_cancel_partition_disengage_request(part);
+		}
+	}
+	return disengaged;
+}
+
+
+/*
  * Mark specified partition as active.
  */
 enum xpc_retval
@@ -721,7 +932,6 @@
 				enum xpc_retval reason)
 {
 	unsigned long irq_flags;
-	partid_t partid = XPC_PARTID(part);
 
 
 	spin_lock_irqsave(&part->act_lock, irq_flags);
@@ -749,17 +959,27 @@
 
 	spin_unlock_irqrestore(&part->act_lock, irq_flags);
 
-	XPC_DISALLOW_HB(partid, xpc_vars);
+	if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+		xpc_request_partition_disengage(part);
+		xpc_IPI_send_disengage(part);
 
-	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n", partid,
-		reason);
+		/* set a timelimit on the disengage request */
+		part->disengage_request_timeout = jiffies +
+					(xpc_disengage_request_timelimit * HZ);
+		part->disengage_request_timer.expires =
+					part->disengage_request_timeout;
+		add_timer(&part->disengage_request_timer);
+	}
 
-	xpc_partition_down(part, reason);
+	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
+		XPC_PARTID(part), reason);
+
+	xpc_partition_going_down(part, reason);
 }
 
 
 /*
- * Mark specified partition as active.
+ * Mark specified partition as inactive.
  */
 void
 xpc_mark_partition_inactive(struct xpc_partition *part)
@@ -792,9 +1012,10 @@
 	void *remote_rp_base;
 	struct xpc_rsvd_page *remote_rp;
 	struct xpc_vars *remote_vars;
-	u64 remote_rsvd_page_pa;
+	u64 remote_rp_pa;
 	u64 remote_vars_pa;
 	int region;
+	int region_size;
 	int max_regions;
 	int nasid;
 	struct xpc_rsvd_page *rp;
@@ -804,7 +1025,8 @@
 	enum xpc_retval ret;
 
 
-	remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE,
+	remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
+						xp_nasid_mask_bytes,
 						GFP_KERNEL, &remote_rp_base);
 	if (remote_rp == NULL) {
 		return;
@@ -812,13 +1034,13 @@
 	remote_vars = (struct xpc_vars *) remote_rp;
 
 
-	discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS,
+	discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words,
 							GFP_KERNEL);
 	if (discovered_nasids == NULL) {
 		kfree(remote_rp_base);
 		return;
 	}
-	memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS);
+	memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
 
 	rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
 
@@ -827,11 +1049,19 @@
 	 * nodes that can comprise an access protection grouping. The access
 	 * protection is in regards to memory, IOI and IPI.
 	 */
-//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or
-//>>> include/asm-ia64/sn/addrs.h
-#define SH1_MAX_REGIONS		64
-#define SH2_MAX_REGIONS		256
-	max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS;
+	max_regions = 64;
+	region_size = sn_region_size;
+
+	switch (region_size) {
+	case 128:
+		max_regions *= 2;
+	case 64:
+		max_regions *= 2;
+	case 32:
+		max_regions *= 2;
+		region_size = 16;
+		DBUG_ON(!is_shub2());
+	}
 
 	for (region = 0; region < max_regions; region++) {
 
@@ -841,8 +1071,8 @@
 
 		dev_dbg(xpc_part, "searching region %d\n", region);
 
-		for (nasid = (region * sn_region_size * 2);
-		     nasid < ((region + 1) * sn_region_size * 2);
+		for (nasid = (region * region_size * 2);
+		     nasid < ((region + 1) * region_size * 2);
 		     nasid += 2) {
 
 			if ((volatile int) xpc_exiting) {
@@ -852,14 +1082,14 @@
 			dev_dbg(xpc_part, "checking nasid %d\n", nasid);
 
 
-			if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) {
+			if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
 				dev_dbg(xpc_part, "PROM indicates Nasid %d is "
 					"part of the local partition; skipping "
 					"region\n", nasid);
 				break;
 			}
 
-			if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) {
+			if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
 				dev_dbg(xpc_part, "PROM indicates Nasid %d was "
 					"not on Numa-Link network at reset\n",
 					nasid);
@@ -877,7 +1107,7 @@
 			/* pull over the reserved page structure */
 
 			ret = xpc_get_remote_rp(nasid, discovered_nasids,
-					      remote_rp, &remote_rsvd_page_pa);
+					      remote_rp, &remote_rp_pa);
 			if (ret != xpcSuccess) {
 				dev_dbg(xpc_part, "unable to get reserved page "
 					"from nasid %d, reason=%d\n", nasid,
@@ -948,6 +1178,13 @@
 				remote_vars->act_nasid,
 				remote_vars->act_phys_cpuid);
 
+			if (XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+								version)) {
+				part->remote_amos_page_pa =
+						remote_vars->amos_page_pa;
+				xpc_mark_partition_disengaged(part);
+				xpc_cancel_partition_disengage_request(part);
+			}
 			xpc_IPI_send_activate(remote_vars);
 		}
 	}
@@ -974,12 +1211,12 @@
 		return xpcPartitionDown;
 	}
 
-	part_nasid_pa = part->remote_rp_pa +
-		(u64) &((struct xpc_rsvd_page *) 0)->part_nasids;
+	memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
+
+	part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
 
 	bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
-				L1_CACHE_ALIGN(XP_NASID_MASK_BYTES),
-				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+			xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
 
 	return xpc_map_bte_errors(bte_res);
 }
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 0e4b9ad..9bf9f23 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -75,7 +75,7 @@
  * more information.
  */
 void *sn_dma_alloc_coherent(struct device *dev, size_t size,
-			    dma_addr_t * dma_handle, int flags)
+			    dma_addr_t * dma_handle, gfp_t flags)
 {
 	void *cpuaddr;
 	unsigned long phys_addr;
@@ -326,6 +326,29 @@
 {
 	unsigned long addr;
 	int ret;
+	struct ia64_sal_retval isrv;
+
+	/*
+	 * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work
+	 * around hw issues at the pci bus level.  SGI proms older than
+	 * 4.10 don't implment this.
+	 */
+
+	SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE,
+		pci_domain_nr(bus), bus->number,
+		0, /* io */
+		0, /* read */
+		port, size, __pa(val));
+
+	if (isrv.status == 0)
+		return size;
+
+	/*
+	 * If the above failed, retry using the SAL_PROBE call which should
+	 * be present in all proms (but which cannot work round PCI chipset
+	 * bugs).  This code is retained for compatability with old
+	 * pre-4.10 proms, and should be removed at some point in the future.
+	 */
 
 	if (!SN_PCIBUS_BUSSOFT(bus))
 		return -ENODEV;
@@ -349,6 +372,29 @@
 	int ret = size;
 	unsigned long paddr;
 	unsigned long *addr;
+	struct ia64_sal_retval isrv;
+
+	/*
+	 * First, try the SN_SAL_IOIF_PCI_SAFE SAL call which can work
+	 * around hw issues at the pci bus level.  SGI proms older than
+	 * 4.10 don't implment this.
+	 */
+
+	SAL_CALL(isrv, SN_SAL_IOIF_PCI_SAFE,
+		pci_domain_nr(bus), bus->number,
+		0, /* io */
+		1, /* write */
+		port, size, __pa(&val));
+
+	if (isrv.status == 0)
+		return size;
+
+	/*
+	 * If the above failed, retry using the SAL_PROBE call which should
+	 * be present in all proms (but which cannot work round PCI chipset
+	 * bugs).  This code is retained for compatability with old
+	 * pre-4.10 proms, and should be removed at some point in the future.
+	 */
 
 	if (!SN_PCIBUS_BUSSOFT(bus)) {
 		ret = -ENODEV;
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
index 21426d0..4f718c3 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
@@ -8,6 +8,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/types.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
@@ -29,10 +30,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_control &= ~bits;
+			__sn_clrq_relaxed(&ptr->tio.cp_control, bits);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_wid_control &= ~bits;
+			__sn_clrq_relaxed(&ptr->pic.p_wid_control, bits);
 			break;
 		default:
 			panic
@@ -49,10 +50,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_control |= bits;
+			__sn_setq_relaxed(&ptr->tio.cp_control, bits);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_wid_control |= bits;
+			__sn_setq_relaxed(&ptr->pic.p_wid_control, bits);
 			break;
 		default:
 			panic
@@ -73,10 +74,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ret = ptr->tio.cp_tflush;
+			ret = __sn_readq_relaxed(&ptr->tio.cp_tflush);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ret = ptr->pic.p_wid_tflush;
+			ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush);
 			break;
 		default:
 			panic
@@ -103,10 +104,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ret = ptr->tio.cp_int_status;
+			ret = __sn_readq_relaxed(&ptr->tio.cp_int_status);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ret = ptr->pic.p_int_status;
+			ret = __sn_readq_relaxed(&ptr->pic.p_int_status);
 			break;
 		default:
 			panic
@@ -127,10 +128,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_int_enable &= ~bits;
+			__sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_int_enable &= ~bits;
+			__sn_clrq_relaxed(&ptr->pic.p_int_enable, ~bits);
 			break;
 		default:
 			panic
@@ -147,10 +148,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_int_enable |= bits;
+			__sn_setq_relaxed(&ptr->tio.cp_int_enable, bits);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_int_enable |= bits;
+			__sn_setq_relaxed(&ptr->pic.p_int_enable, bits);
 			break;
 		default:
 			panic
@@ -171,14 +172,16 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_int_addr[int_n] &= ~TIOCP_HOST_INTR_ADDR;
-			ptr->tio.cp_int_addr[int_n] |=
-			    (addr & TIOCP_HOST_INTR_ADDR);
+			__sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n],
+			    TIOCP_HOST_INTR_ADDR);
+			__sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n],
+			    (addr & TIOCP_HOST_INTR_ADDR));
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_int_addr[int_n] &= ~PIC_HOST_INTR_ADDR;
-			ptr->pic.p_int_addr[int_n] |=
-			    (addr & PIC_HOST_INTR_ADDR);
+			__sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n],
+			    PIC_HOST_INTR_ADDR);
+			__sn_setq_relaxed(&ptr->pic.p_int_addr[int_n],
+			    (addr & PIC_HOST_INTR_ADDR));
 			break;
 		default:
 			panic
@@ -198,10 +201,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_force_pin[int_n] = 1;
+			writeq(1, &ptr->tio.cp_force_pin[int_n]);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_force_pin[int_n] = 1;
+			writeq(1, &ptr->pic.p_force_pin[int_n]);
 			break;
 		default:
 			panic
@@ -222,10 +225,12 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ret = ptr->tio.cp_wr_req_buf[device];
+			ret =
+			    __sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ret = ptr->pic.p_wr_req_buf[device];
+			ret =
+			    __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
 			break;
 		default:
 		      panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", (void *)ptr);
@@ -244,10 +249,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ptr->tio.cp_int_ate_ram[ate_index] = (uint64_t) val;
+			writeq(val, &ptr->tio.cp_int_ate_ram[ate_index]);
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ptr->pic.p_int_ate_ram[ate_index] = (uint64_t) val;
+			writeq(val, &ptr->pic.p_int_ate_ram[ate_index]);
 			break;
 		default:
 			panic
@@ -265,12 +270,10 @@
 	if (pcibus_info) {
 		switch (pcibus_info->pbi_bridge_type) {
 		case PCIBR_BRIDGETYPE_TIOCP:
-			ret =
-			    (uint64_t *) & (ptr->tio.cp_int_ate_ram[ate_index]);
+			ret = &ptr->tio.cp_int_ate_ram[ate_index];
 			break;
 		case PCIBR_BRIDGETYPE_PIC:
-			ret =
-			    (uint64_t *) & (ptr->pic.p_int_ate_ram[ate_index]);
+			ret = &ptr->pic.p_int_ate_ram[ate_index];
 			break;
 		default:
 			panic
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 19bced3..46b646a 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioca_provider.h>
@@ -37,7 +38,7 @@
 	uint64_t offset;
 	struct page *tmp;
 	struct tioca_common *tioca_common;
-	volatile struct tioca *ca_base;
+	struct tioca *ca_base;
 
 	tioca_common = tioca_kern->ca_common;
 	ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
@@ -174,27 +175,29 @@
 	 * 	DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029
 	 */
 
-	ca_base->ca_control1 |= CA_AGPDMA_OP_ENB_COMBDELAY;	/* PV895469 ? */
-	ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
-	ca_base->ca_control2 |= (0x2ull << CA_GART_MEM_PARAM_SHFT);
+	__sn_setq_relaxed(&ca_base->ca_control1,
+			CA_AGPDMA_OP_ENB_COMBDELAY);	/* PV895469 ? */
+	__sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
+	__sn_setq_relaxed(&ca_base->ca_control2,
+			(0x2ull << CA_GART_MEM_PARAM_SHFT));
 	tioca_kern->ca_gart_iscoherent = 1;
-	ca_base->ca_control2 &=
-	    ~(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB);
+	__sn_clrq_relaxed(&ca_base->ca_control2,
+	    		(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB));
 
 	/*
 	 * Unmask GART fetch error interrupts.  Clear residual errors first.
 	 */
 
-	ca_base->ca_int_status_alias = CA_GART_FETCH_ERR;
-	ca_base->ca_mult_error_alias = CA_GART_FETCH_ERR;
-	ca_base->ca_int_mask &= ~CA_GART_FETCH_ERR;
+	writeq(CA_GART_FETCH_ERR, &ca_base->ca_int_status_alias);
+	writeq(CA_GART_FETCH_ERR, &ca_base->ca_mult_error_alias);
+	__sn_clrq_relaxed(&ca_base->ca_int_mask, CA_GART_FETCH_ERR);
 
 	/*
 	 * Program the aperature and gart registers in TIOCA
 	 */
 
-	ca_base->ca_gart_aperature = ap_reg;
-	ca_base->ca_gart_ptr_table = tioca_kern->ca_gart_coretalk_addr | 1;
+	writeq(ap_reg, &ca_base->ca_gart_aperature);
+	writeq(tioca_kern->ca_gart_coretalk_addr|1, &ca_base->ca_gart_ptr_table);
 
 	return 0;
 }
@@ -211,7 +214,6 @@
 tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
 {
 	int cap_ptr;
-	uint64_t ca_control1;
 	uint32_t reg;
 	struct tioca *tioca_base;
 	struct pci_dev *pdev;
@@ -256,9 +258,7 @@
 	 */
 
 	tioca_base = (struct tioca *)common->ca_common.bs_base;
-	ca_control1 = tioca_base->ca_control1;
-	ca_control1 |= CA_AGP_FW_ENABLE;
-	tioca_base->ca_control1 = ca_control1;
+	__sn_setq_relaxed(&tioca_base->ca_control1, CA_AGP_FW_ENABLE);
 }
 
 EXPORT_SYMBOL(tioca_fastwrite_enable);	/* used by agp-sgi */
@@ -345,7 +345,7 @@
 		return 0;
 	}
 
-	agp_dma_extn = ca_base->ca_agp_dma_addr_extn;
+	agp_dma_extn = __sn_readq_relaxed(&ca_base->ca_agp_dma_addr_extn);
 	if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
 		printk(KERN_ERR "%s:  coretalk upper node (%u) "
 		       "mismatch with ca_agp_dma_addr_extn (%lu)\n",
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 8e75db2..9f03d4e 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioce_provider.h>
@@ -227,7 +228,7 @@
 
 		ate = ATE_MAKE(addr, pagesize);
 		ate_shadow[i + j] = ate;
-		ate_reg[i + j] = ate;
+		writeq(ate, &ate_reg[i + j]);
 		addr += pagesize;
 	}
 
@@ -268,10 +269,10 @@
 	pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
 
 	if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
-		volatile uint64_t tmp;
+		uint64_t tmp;
 
 		ce_kern->ce_port[port].dirmap_shadow = ct_upper;
-		ce_mmr->ce_ure_dir_map[port] = ct_upper;
+		writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]);
 		tmp = ce_mmr->ce_ure_dir_map[port];
 		dma_ok = 1;
 	} else
@@ -343,7 +344,7 @@
 	if (TIOCE_D32_ADDR(bus_addr)) {
 		if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
 			ce_kern->ce_port[port].dirmap_shadow = 0;
-			ce_mmr->ce_ure_dir_map[port] = 0;
+			writeq(0, &ce_mmr->ce_ure_dir_map[port]);
 		}
 	} else {
 		struct tioce_dmamap *map;
@@ -582,18 +583,18 @@
 	 */
 
 	tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
-	tioce_mmr->ce_ure_page_map &= ~CE_URE_PAGESIZE_MASK;
-	tioce_mmr->ce_ure_page_map |= CE_URE_256K_PAGESIZE;
+	__sn_clrq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_PAGESIZE_MASK);
+	__sn_setq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_256K_PAGESIZE);
 	tioce_kern->ce_ate3240_pagesize = KB(256);
 
 	for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
 		tioce_kern->ce_ate40_shadow[i] = 0;
-		tioce_mmr->ce_ure_ate40[i] = 0;
+		writeq(0, &tioce_mmr->ce_ure_ate40[i]);
 	}
 
 	for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
 		tioce_kern->ce_ate3240_shadow[i] = 0;
-		tioce_mmr->ce_ure_ate3240[i] = 0;
+		writeq(0, &tioce_mmr->ce_ure_ate3240[i]);
 	}
 
 	return tioce_kern;
@@ -665,7 +666,7 @@
 	default:
 		return;
 	}
-	ce_mmr->ce_adm_force_int = force_int_val;
+	writeq(force_int_val, &ce_mmr->ce_adm_force_int);
 }
 
 /**
@@ -686,6 +687,7 @@
 	struct tioce_common *ce_common;
 	struct tioce *ce_mmr;
 	int bit;
+	uint64_t vector;
 
 	pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
 	if (!pcidev_info)
@@ -696,11 +698,11 @@
 
 	bit = sn_irq_info->irq_int_bit;
 
-	ce_mmr->ce_adm_int_mask |= (1UL << bit);
-	ce_mmr->ce_adm_int_dest[bit] =
-		((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) |
-			   sn_irq_info->irq_xtalkaddr;
-	ce_mmr->ce_adm_int_mask &= ~(1UL << bit);
+	__sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
+	vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
+	vector |= sn_irq_info->irq_xtalkaddr;
+	writeq(vector, &ce_mmr->ce_adm_int_dest[bit]);
+	__sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
 
 	tioce_force_interrupt(sn_irq_info);
 }
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 85920fb..396c942 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -653,8 +653,6 @@
 	SAVE_ALL
 	mvfc	r0, bpc
 	ld	r1, @r0
-	seth	r0, #0xa0f0
-	st	r1, @r0
 	ldi	r1, #0x20			; error_code
 	mv	r0, sp				; pt_regs
 	bl	do_rie_handler
diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
index e545b06..eda9f96 100644
--- a/arch/m32r/kernel/io_m32700ut.c
+++ b/arch/m32r/kernel/io_m32700ut.c
@@ -64,11 +64,11 @@
  * from 0x10000000 to 0x13ffffff on physical address.
  * The base address of LAN controller(LAN91C111) is 0x300.
  */
-#define LAN_IOSTART	0x300
-#define LAN_IOEND	0x320
+#define LAN_IOSTART	0xa0000300
+#define LAN_IOEND	0xa0000320
 static inline void *_port2addr_ne(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+	return (void *)(port + 0x10000000);
 }
 static inline void *_port2addr_usb(unsigned long port)
 {
diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
index 7803316..3c3da04 100644
--- a/arch/m32r/kernel/io_mappi.c
+++ b/arch/m32r/kernel/io_mappi.c
@@ -31,7 +31,7 @@
 
 static inline void *_port2addr(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET);
+	return (void *)(port | (NONCACHE_OFFSET));
 }
 
 static inline void *_port2addr_ne(unsigned long port)
diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
index 5c03504..df3c729 100644
--- a/arch/m32r/kernel/io_mappi2.c
+++ b/arch/m32r/kernel/io_mappi2.c
@@ -33,12 +33,9 @@
 
 static inline void *_port2addr(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET);
+	return (void *)(port | (NONCACHE_OFFSET));
 }
 
-#define LAN_IOSTART	0x300
-#define LAN_IOEND	0x320
-
 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
 static inline void *__port2addr_ata(unsigned long port)
 {
@@ -59,15 +56,17 @@
 }
 #endif
 
+#define LAN_IOSTART	0xa0000300
+#define LAN_IOEND	0xa0000320
 #ifdef CONFIG_CHIP_OPSP
 static inline void *_port2addr_ne(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+	return (void *)(port + 0x10000000);
 }
 #else
 static inline void *_port2addr_ne(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET + 0x04000000);
+	return (void *)(port + 0x04000000);
 }
 #endif
 static inline void *_port2addr_usb(unsigned long port)
diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c
index c80bde6..6716ffe 100644
--- a/arch/m32r/kernel/io_mappi3.c
+++ b/arch/m32r/kernel/io_mappi3.c
@@ -36,9 +36,6 @@
 	return (void *)(port + NONCACHE_OFFSET);
 }
 
-#define LAN_IOSTART	0x300
-#define LAN_IOEND	0x320
-
 #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
 static inline void *__port2addr_ata(unsigned long port)
 {
@@ -59,9 +56,11 @@
 }
 #endif
 
+#define LAN_IOSTART	0xa0000300
+#define LAN_IOEND	0xa0000320
 static inline void *_port2addr_ne(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+	return (void *)(port + 0x10000000);
 }
 
 static inline void *_port2addr_usb(unsigned long port)
diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
index 9997ddd..8be3239 100644
--- a/arch/m32r/kernel/io_oaks32r.c
+++ b/arch/m32r/kernel/io_oaks32r.c
@@ -16,7 +16,7 @@
 
 static inline void *_port2addr(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET);
+	return (void *)(port | (NONCACHE_OFFSET));
 }
 
 static inline  void *_port2addr_ne(unsigned long port)
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
index e34951e..4793bd1 100644
--- a/arch/m32r/kernel/io_opsput.c
+++ b/arch/m32r/kernel/io_opsput.c
@@ -36,7 +36,7 @@
 
 static inline void *_port2addr(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET);
+	return (void *)(port | (NONCACHE_OFFSET));
 }
 
 /*
@@ -44,11 +44,11 @@
  * from 0x10000000 to 0x13ffffff on physical address.
  * The base address of LAN controller(LAN91C111) is 0x300.
  */
-#define LAN_IOSTART	0x300
-#define LAN_IOEND	0x320
+#define LAN_IOSTART	0xa0000300
+#define LAN_IOEND	0xa0000320
 static inline void *_port2addr_ne(unsigned long port)
 {
-	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+	return (void *)(port + 0x10000000);
 }
 static inline void *_port2addr_usb(unsigned long port)
 {
diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c
index 9eb161d..39a379a 100644
--- a/arch/m32r/kernel/io_usrv.c
+++ b/arch/m32r/kernel/io_usrv.c
@@ -47,7 +47,7 @@
 	else if (port >= UART1_IOSTART && port <= UART1_IOEND)
 		port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART;
 #endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
-	return (void *)(port + NONCACHE_OFFSET);
+	return (void *)(port | (NONCACHE_OFFSET));
 }
 
 static inline void delay(void)
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 124f7c1..078d2a0 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -756,7 +756,7 @@
 	return ret;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret;
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index ec56747..f722ec8 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -305,19 +305,19 @@
 
 	seq_printf(m, "processor\t: %ld\n", cpu);
 
-#ifdef CONFIG_CHIP_VDEC2
+#if defined(CONFIG_CHIP_VDEC2)
 	seq_printf(m, "cpu family\t: VDEC2\n"
 		"cache size\t: Unknown\n");
-#elif  CONFIG_CHIP_M32700
+#elif defined(CONFIG_CHIP_M32700)
 	seq_printf(m,"cpu family\t: M32700\n"
 		"cache size\t: I-8KB/D-8KB\n");
-#elif  CONFIG_CHIP_M32102
+#elif defined(CONFIG_CHIP_M32102)
 	seq_printf(m,"cpu family\t: M32102\n"
 		"cache size\t: I-8KB\n");
-#elif  CONFIG_CHIP_OPSP
+#elif defined(CONFIG_CHIP_OPSP)
 	seq_printf(m,"cpu family\t: OPSP\n"
 		"cache size\t: I-8KB/D-8KB\n");
-#elif  CONFIG_CHIP_MP
+#elif defined(CONFIG_CHIP_MP)
 	seq_printf(m, "cpu family\t: M32R-MP\n"
 		"cache size\t: I-xxKB/D-xxKB\n");
 #else
@@ -326,19 +326,19 @@
 	seq_printf(m, "bogomips\t: %lu.%02lu\n",
 		c->loops_per_jiffy/(500000/HZ),
 		(c->loops_per_jiffy/(5000/HZ)) % 100);
-#ifdef CONFIG_PLAT_MAPPI
+#if defined(CONFIG_PLAT_MAPPI)
 	seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
-#elif CONFIG_PLAT_MAPPI2
+#elif defined(CONFIG_PLAT_MAPPI2)
 	seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
-#elif CONFIG_PLAT_MAPPI3
+#elif defined(CONFIG_PLAT_MAPPI3)
 	seq_printf(m, "Machine\t\t: Mappi-III Evaluation board\n");
-#elif  CONFIG_PLAT_M32700UT
+#elif defined(CONFIG_PLAT_M32700UT)
 	seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
-#elif  CONFIG_PLAT_OPSPUT
+#elif defined(CONFIG_PLAT_OPSPUT)
 	seq_printf(m, "Machine\t\t: OPSPUT Evaluation board\n");
-#elif  CONFIG_PLAT_USRV
+#elif defined(CONFIG_PLAT_USRV)
 	seq_printf(m, "Machine\t\t: uServer\n");
-#elif  CONFIG_PLAT_OAKS32R
+#elif defined(CONFIG_PLAT_OAKS32R)
 	seq_printf(m, "Machine\t\t: OAKS32R\n");
 #else
 	seq_printf(m, "Machine\t\t: Unknown\n");
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index 539c562..2ebce20 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -39,10 +39,6 @@
 extern void smp_local_timer_interrupt(struct pt_regs *);
 #endif
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 extern unsigned long wall_jiffies;
 #define TICK_SIZE	(tick_nsec / 1000)
 
diff --git a/arch/m32r/lib/csum_partial_copy.c b/arch/m32r/lib/csum_partial_copy.c
index ddb16a8..3d5f061 100644
--- a/arch/m32r/lib/csum_partial_copy.c
+++ b/arch/m32r/lib/csum_partial_copy.c
@@ -18,10 +18,10 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/string.h>
 
 #include <net/checksum.h>
 #include <asm/byteorder.h>
-#include <asm/string.h>
 #include <asm/uaccess.h>
 
 /*
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index d9a40b1..6facf15 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -48,6 +48,8 @@
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
+		unsigned long flags;
+		pgdat_resize_lock(pgdat, &flags);
 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
 			page = pgdat_page_nr(pgdat, i);
 			total++;
@@ -60,6 +62,7 @@
 			else if (page_count(page))
 				shared += page_count(page) - 1;
 		}
+		pgdat_resize_unlock(pgdat, &flags);
 	}
 	printk("%d pages of RAM\n", total);
 	printk("%d pages of HIGHMEM\n",highmem);
@@ -150,10 +153,14 @@
 	int reservedpages, nid, i;
 
 	reservedpages = 0;
-	for_each_online_node(nid)
+	for_each_online_node(nid) {
+		unsigned long flags;
+		pgdat_resize_lock(NODE_DATA(nid), &flags);
 		for (i = 0 ; i < MAX_LOW_PFN(nid) - START_PFN(nid) ; i++)
 			if (PageReserved(nid_page_nr(nid, i)))
 				reservedpages++;
+		pgdat_resize_unlock(NODE_DATA(nid), &flags);
+	}
 
 	return reservedpages;
 }
diff --git a/arch/m32r/mm/ioremap.c b/arch/m32r/mm/ioremap.c
index 70c5905..a151849 100644
--- a/arch/m32r/mm/ioremap.c
+++ b/arch/m32r/mm/ioremap.c
@@ -67,7 +67,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -90,7 +90,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd;
 		pmd = pmd_alloc(&init_mm, dir, address);
@@ -104,7 +103,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return error;
 }
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index ba960bb..1dd5d18 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -388,33 +388,11 @@
 	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
 	  600. If you intend to use pcmcia cards say Y; otherwise say N.
 
-config STRAM_SWAP
-	bool "Support for ST-RAM as swap space"
-	depends on ATARI && BROKEN
-	---help---
-	  Some Atari 68k machines (including the 520STF and 1020STE) divide
-	  their addressable memory into ST and TT sections.  The TT section
-	  (up to 512MB) is the main memory; the ST section (up to 4MB) is
-	  accessible to the built-in graphics board, runs slower, and is
-	  present mainly for backward compatibility with older machines.
-
-	  This enables support for using (parts of) ST-RAM as swap space,
-	  instead of as normal system memory. This can first enhance system
-	  performance if you have lots of alternate RAM (compared to the size
-	  of ST-RAM), because executable code always will reside in faster
-	  memory. ST-RAM will remain as ultra-fast swap space. On the other
-	  hand, it allows much improved dynamic allocations of ST-RAM buffers
-	  for device driver modules (e.g. floppy, ACSI, SLM printer, DMA
-	  sound). The probability that such allocations at module load time
-	  fail is drastically reduced.
-
 config STRAM_PROC
 	bool "ST-RAM statistics in /proc"
 	depends on ATARI
 	help
-	  Say Y here to report ST-RAM usage statistics in /proc/stram.  See
-	  the help for CONFIG_STRAM_SWAP for discussion of ST-RAM and its
-	  uses.
+	  Say Y here to report ST-RAM usage statistics in /proc/stram.
 
 config HEARTBEAT
 	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 5a3c106..22e0481 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -15,11 +15,9 @@
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/init.h>
-#include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
-#include <linux/shm.h>
 #include <linux/bootmem.h>
 #include <linux/mount.h>
 #include <linux/blkdev.h>
@@ -33,8 +31,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 
-#include <linux/swapops.h>
-
 #undef DEBUG
 
 #ifdef DEBUG
@@ -49,8 +45,7 @@
 #include <linux/proc_fs.h>
 #endif
 
-/* Pre-swapping comments:
- *
+/*
  * ++roman:
  *
  * New version of ST-Ram buffer allocation. Instead of using the
@@ -75,76 +70,6 @@
  *
  */
 
-/*
- * New Nov 1997: Use ST-RAM as swap space!
- *
- * In the past, there were often problems with modules that require ST-RAM
- * buffers. Such drivers have to use __get_dma_pages(), which unfortunately
- * often isn't very successful in allocating more than 1 page :-( [1] The net
- * result was that most of the time you couldn't insmod such modules (ataflop,
- * ACSI, SCSI on Falcon, Atari internal framebuffer, not to speak of acsi_slm,
- * which needs a 1 MB buffer... :-).
- *
- * To overcome this limitation, ST-RAM can now be turned into a very
- * high-speed swap space. If a request for an ST-RAM buffer comes, the kernel
- * now tries to unswap some pages on that swap device to make some free (and
- * contiguous) space. This works much better in comparison to
- * __get_dma_pages(), since used swap pages can be selectively freed by either
- * moving them to somewhere else in swap space, or by reading them back into
- * system memory. Ok, there operation of unswapping isn't really cheap (for
- * each page, one has to go through the page tables of all processes), but it
- * doesn't happen that often (only when allocation ST-RAM, i.e. when loading a
- * module that needs ST-RAM). But it at least makes it possible to load such
- * modules!
- *
- * It could also be that overall system performance increases a bit due to
- * ST-RAM swapping, since slow ST-RAM isn't used anymore for holding data or
- * executing code in. It's then just a (very fast, compared to disk) back
- * storage for not-so-often needed data. (But this effect must be compared
- * with the loss of total memory...) Don't know if the effect is already
- * visible on a TT, where the speed difference between ST- and TT-RAM isn't
- * that dramatic, but it should on machines where TT-RAM is really much faster
- * (e.g. Afterburner).
- *
- *   [1]: __get_free_pages() does a fine job if you only want one page, but if
- * you want more (contiguous) pages, it can give you such a block only if
- * there's already a free one. The algorithm can't try to free buffers or swap
- * out something in order to make more free space, since all that page-freeing
- * mechanisms work "target-less", i.e. they just free something, but not in a
- * specific place. I.e., __get_free_pages() can't do anything to free
- * *adjacent* pages :-( This situation becomes even worse for DMA memory,
- * since the freeing algorithms are also blind to DMA capability of pages.
- */
-
-/* 1998-10-20: ++andreas
-   unswap_by_move disabled because it does not handle swapped shm pages.
-*/
-
-/* 2000-05-01: ++andreas
-   Integrated with bootmem.  Remove all traces of unswap_by_move.
-*/
-
-#ifdef CONFIG_STRAM_SWAP
-#define ALIGN_IF_SWAP(x)	PAGE_ALIGN(x)
-#else
-#define ALIGN_IF_SWAP(x)	(x)
-#endif
-
-/* get index of swap page at address 'addr' */
-#define SWAP_NR(addr)		(((addr) - swap_start) >> PAGE_SHIFT)
-
-/* get address of swap page #'nr' */
-#define SWAP_ADDR(nr)		(swap_start + ((nr) << PAGE_SHIFT))
-
-/* get number of pages for 'n' bytes (already page-aligned) */
-#define N_PAGES(n)			((n) >> PAGE_SHIFT)
-
-/* The following two numbers define the maximum fraction of ST-RAM in total
- * memory, below that the kernel would automatically use ST-RAM as swap
- * space. This decision can be overridden with stram_swap= */
-#define MAX_STRAM_FRACTION_NOM		1
-#define MAX_STRAM_FRACTION_DENOM	3
-
 /* Start and end (virtual) of ST-RAM */
 static void *stram_start, *stram_end;
 
@@ -164,10 +89,9 @@
 } BLOCK;
 
 /* values for flags field */
-#define BLOCK_FREE		0x01	/* free structure in the BLOCKs pool */
+#define BLOCK_FREE	0x01	/* free structure in the BLOCKs pool */
 #define BLOCK_KMALLOCED	0x02	/* structure allocated by kmalloc() */
-#define BLOCK_GFP		0x08	/* block allocated with __get_dma_pages() */
-#define BLOCK_INSWAP	0x10	/* block allocated in swap space */
+#define BLOCK_GFP	0x08	/* block allocated with __get_dma_pages() */
 
 /* list of allocated blocks */
 static BLOCK *alloc_list;
@@ -179,60 +103,8 @@
 #define N_STATIC_BLOCKS	20
 static BLOCK static_blocks[N_STATIC_BLOCKS];
 
-#ifdef CONFIG_STRAM_SWAP
-/* max. number of bytes to use for swapping
- *  0 = no ST-RAM swapping
- * -1 = do swapping (to whole ST-RAM) if it's less than MAX_STRAM_FRACTION of
- *      total memory
- */
-static int max_swap_size = -1;
-
-/* start and end of swapping area */
-static void *swap_start, *swap_end;
-
-/* The ST-RAM's swap info structure */
-static struct swap_info_struct *stram_swap_info;
-
-/* The ST-RAM's swap type */
-static int stram_swap_type;
-
-/* Semaphore for get_stram_region.  */
-static DECLARE_MUTEX(stram_swap_sem);
-
-/* major and minor device number of the ST-RAM device; for the major, we use
- * the same as Amiga z2ram, which is really similar and impossible on Atari,
- * and for the minor a relatively odd number to avoid the user creating and
- * using that device. */
-#define	STRAM_MAJOR		Z2RAM_MAJOR
-#define	STRAM_MINOR		13
-
-/* Some impossible pointer value */
-#define MAGIC_FILE_P	(struct file *)0xffffdead
-
-#ifdef DO_PROC
-static unsigned stat_swap_read;
-static unsigned stat_swap_write;
-static unsigned stat_swap_force;
-#endif /* DO_PROC */
-
-#endif /* CONFIG_STRAM_SWAP */
-
 /***************************** Prototypes *****************************/
 
-#ifdef CONFIG_STRAM_SWAP
-static int swap_init(void *start_mem, void *swap_data);
-static void *get_stram_region( unsigned long n_pages );
-static void free_stram_region( unsigned long offset, unsigned long n_pages
-			       );
-static int in_some_region(void *addr);
-static unsigned long find_free_region( unsigned long n_pages, unsigned long
-				       *total_free, unsigned long
-				       *region_free );
-static void do_stram_request(request_queue_t *);
-static int stram_open( struct inode *inode, struct file *filp );
-static int stram_release( struct inode *inode, struct file *filp );
-static void reserve_region(void *start, void *end);
-#endif
 static BLOCK *add_region( void *addr, unsigned long size );
 static BLOCK *find_region( void *addr );
 static int remove_region( BLOCK *block );
@@ -279,84 +151,11 @@
  */
 void __init atari_stram_reserve_pages(void *start_mem)
 {
-#ifdef CONFIG_STRAM_SWAP
-	/* if max_swap_size is negative (i.e. no stram_swap= option given),
-	 * determine at run time whether to use ST-RAM swapping */
-	if (max_swap_size < 0)
-		/* Use swapping if ST-RAM doesn't make up more than MAX_STRAM_FRACTION
-		 * of total memory. In that case, the max. size is set to 16 MB,
-		 * because ST-RAM can never be bigger than that.
-		 * Also, never use swapping on a Hades, there's no separate ST-RAM in
-		 * that machine. */
-		max_swap_size =
-			(!MACH_IS_HADES &&
-			 (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
-			  ((unsigned long)high_memory>>PAGE_SHIFT)*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
-	DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
-#endif
-
 	/* always reserve first page of ST-RAM, the first 2 kB are
 	 * supervisor-only! */
 	if (!kernel_in_stram)
 		reserve_bootmem (0, PAGE_SIZE);
 
-#ifdef CONFIG_STRAM_SWAP
-	{
-		void *swap_data;
-
-		start_mem = (void *) PAGE_ALIGN ((unsigned long) start_mem);
-		/* determine first page to use as swap: if the kernel is
-		   in TT-RAM, this is the first page of (usable) ST-RAM;
-		   otherwise just use the end of kernel data (= start_mem) */
-		swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem;
-		/* decrement by one page, rest of kernel assumes that first swap page
-		 * is always reserved and maybe doesn't handle swp_entry == 0
-		 * correctly */
-		swap_start -= PAGE_SIZE;
-		swap_end = stram_end;
-		if (swap_end-swap_start > max_swap_size)
-			swap_end =  swap_start + max_swap_size;
-		DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
-				 "swap=%p-%p\n", swap_start, swap_end);
-
-		/* reserve some amount of memory for maintainance of
-		 * swapping itself: one page for each 2048 (PAGE_SIZE/2)
-		 * swap pages. (2 bytes for each page) */
-		swap_data = start_mem;
-		start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
-			      >> (PAGE_SHIFT-1)) << PAGE_SHIFT;
-		/* correct swap_start if necessary */
-		if (swap_start + PAGE_SIZE == swap_data)
-			swap_start = start_mem - PAGE_SIZE;
-
-		if (!swap_init( start_mem, swap_data )) {
-			printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
-			max_swap_size = 0;
-			return;
-		}
-		/* reserve region for swapping meta-data */
-		reserve_region(swap_data, start_mem);
-		/* reserve swapping area itself */
-		reserve_region(swap_start + PAGE_SIZE, swap_end);
-
-		/*
-		 * If the whole ST-RAM is used for swapping, there are no allocatable
-		 * dma pages left. But unfortunately, some shared parts of the kernel
-		 * (particularly the SCSI mid-level) call __get_dma_pages()
-		 * unconditionally :-( These calls then fail, and scsi.c even doesn't
-		 * check for NULL return values and just crashes. The quick fix for
-		 * this (instead of doing much clean up work in the SCSI code) is to
-		 * pretend all pages are DMA-able by setting mach_max_dma_address to
-		 * ULONG_MAX. This doesn't change any functionality so far, since
-		 * get_dma_pages() shouldn't be used on Atari anyway anymore (better
-		 * use atari_stram_alloc()), and the Atari SCSI drivers don't need DMA
-		 * memory. But unfortunately there's now no kind of warning (even not
-		 * a NULL return value) if you use get_dma_pages() nevertheless :-(
-		 * You just will get non-DMA-able memory...
-		 */
-		mach_max_dma_address = 0xffffffff;
-	}
-#endif
 }
 
 void atari_stram_mem_init_hook (void)
@@ -367,7 +166,6 @@
 
 /*
  * This is main public interface: somehow allocate a ST-RAM block
- * There are three strategies:
  *
  *  - If we're before mem_init(), we have to make a static allocation. The
  *    region is taken in the kernel data area (if the kernel is in ST-RAM) or
@@ -375,14 +173,9 @@
  *    rsvd_stram_* region. The ST-RAM is somewhere in the middle of kernel
  *    address space in the latter case.
  *
- *  - If mem_init() already has been called and ST-RAM swapping is enabled,
- *    try to get the memory from the (pseudo) swap-space, either free already
- *    or by moving some other pages out of the swap.
- *
- *  - If mem_init() already has been called, and ST-RAM swapping is not
- *    enabled, the only possibility is to try with __get_dma_pages(). This has
- *    the disadvantage that it's very hard to get more than 1 page, and it is
- *    likely to fail :-(
+ *  - If mem_init() already has been called, try with __get_dma_pages().
+ *    This has the disadvantage that it's very hard to get more than 1 page,
+ *    and it is likely to fail :-(
  *
  */
 void *atari_stram_alloc(long size, const char *owner)
@@ -393,27 +186,13 @@
 
 	DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
 
-	size = ALIGN_IF_SWAP(size);
-	DPRINTK( "atari_stram_alloc: rounded size = %08lx\n", size );
-#ifdef CONFIG_STRAM_SWAP
-	if (max_swap_size) {
-		/* If swapping is active: make some free space in the swap
-		   "device". */
-		DPRINTK( "atari_stram_alloc: after mem_init, swapping ok, "
-				 "calling get_region\n" );
-		addr = get_stram_region( N_PAGES(size) );
-		flags = BLOCK_INSWAP;
-	}
-	else
-#endif
 	if (!mem_init_done)
 		return alloc_bootmem_low(size);
 	else {
-		/* After mem_init() and no swapping: can only resort to
-		 * __get_dma_pages() */
+		/* After mem_init(): can only resort to __get_dma_pages() */
 		addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
 		flags = BLOCK_GFP;
-		DPRINTK( "atari_stram_alloc: after mem_init, swapping off, "
+		DPRINTK( "atari_stram_alloc: after mem_init, "
 				 "get_pages=%p\n", addr );
 	}
 
@@ -422,12 +201,7 @@
 			/* out of memory for BLOCK structure :-( */
 			DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
 					 "freeing again\n" );
-#ifdef CONFIG_STRAM_SWAP
-			if (flags == BLOCK_INSWAP)
-				free_stram_region( SWAP_NR(addr), N_PAGES(size) );
-			else
-#endif
-				free_pages((unsigned long)addr, get_order(size));
+			free_pages((unsigned long)addr, get_order(size));
 			return( NULL );
 		}
 		block->owner = owner;
@@ -451,25 +225,12 @@
 	DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
 			 "flags=%02x\n", block, block->size, block->owner, block->flags );
 
-#ifdef CONFIG_STRAM_SWAP
-	if (!max_swap_size) {
-#endif
-		if (block->flags & BLOCK_GFP) {
-			DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
-				get_order(block->size));
-			free_pages((unsigned long)addr, get_order(block->size));
-		}
-		else
-			goto fail;
-#ifdef CONFIG_STRAM_SWAP
-	}
-	else if (block->flags & BLOCK_INSWAP) {
-		DPRINTK( "atari_stram_free: is swap-alloced\n" );
-		free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) );
-	}
-	else
+	if (!(block->flags & BLOCK_GFP))
 		goto fail;
-#endif
+
+	DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
+		get_order(block->size));
+	free_pages((unsigned long)addr, get_order(block->size));
 	remove_region( block );
 	return;
 
@@ -478,612 +239,6 @@
 			"(called from %p)\n", addr, __builtin_return_address(0) );
 }
 
-
-#ifdef CONFIG_STRAM_SWAP
-
-
-/* ------------------------------------------------------------------------ */
-/*						   Main Swapping Functions							*/
-/* ------------------------------------------------------------------------ */
-
-
-/*
- * Initialize ST-RAM swap device
- * (lots copied and modified from sys_swapon() in mm/swapfile.c)
- */
-static int __init swap_init(void *start_mem, void *swap_data)
-{
-	static struct dentry fake_dentry;
-	static struct vfsmount fake_vfsmnt;
-	struct swap_info_struct *p;
-	struct inode swap_inode;
-	unsigned int type;
-	void *addr;
-	int i, j, k, prev;
-
-	DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n",
-		start_mem, swap_data);
-
-	/* need at least one page for swapping to (and this also isn't very
-	 * much... :-) */
-	if (swap_end - swap_start < 2*PAGE_SIZE) {
-		printk( KERN_WARNING "stram_swap_init: swap space too small\n" );
-		return( 0 );
-	}
-
-	/* find free slot in swap_info */
-	for( p = swap_info, type = 0; type < nr_swapfiles; type++, p++ )
-		if (!(p->flags & SWP_USED))
-			break;
-	if (type >= MAX_SWAPFILES) {
-		printk( KERN_WARNING "stram_swap_init: max. number of "
-				"swap devices exhausted\n" );
-		return( 0 );
-	}
-	if (type >= nr_swapfiles)
-		nr_swapfiles = type+1;
-
-	stram_swap_info = p;
-	stram_swap_type = type;
-
-	/* fake some dir cache entries to give us some name in /dev/swaps */
-	fake_dentry.d_parent = &fake_dentry;
-	fake_dentry.d_name.name = "stram (internal)";
-	fake_dentry.d_name.len = 16;
-	fake_vfsmnt.mnt_parent = &fake_vfsmnt;
-
-	p->flags        = SWP_USED;
-	p->swap_file    = &fake_dentry;
-	p->swap_vfsmnt  = &fake_vfsmnt;
-	p->swap_map	= swap_data;
-	p->cluster_nr   = 0;
-	p->next         = -1;
-	p->prio         = 0x7ff0;	/* a rather high priority, but not the higest
-								 * to give the user a chance to override */
-
-	/* call stram_open() directly, avoids at least the overhead in
-	 * constructing a dummy file structure... */
-	swap_inode.i_rdev = MKDEV( STRAM_MAJOR, STRAM_MINOR );
-	stram_open( &swap_inode, MAGIC_FILE_P );
-	p->max = SWAP_NR(swap_end);
-
-	/* initialize swap_map: set regions that are already allocated or belong
-	 * to kernel data space to SWAP_MAP_BAD, otherwise to free */
-	j = 0; /* # of free pages */
-	k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */
-	p->lowest_bit = 0;
-	p->highest_bit = 0;
-	for( i = 1, addr = SWAP_ADDR(1); i < p->max;
-		 i++, addr += PAGE_SIZE ) {
-		if (in_some_region( addr )) {
-			p->swap_map[i] = SWAP_MAP_BAD;
-			++k;
-		}
-		else if (kernel_in_stram && addr < start_mem ) {
-			p->swap_map[i] = SWAP_MAP_BAD;
-		}
-		else {
-			p->swap_map[i] = 0;
-			++j;
-			if (!p->lowest_bit) p->lowest_bit = i;
-			p->highest_bit = i;
-		}
-	}
-	/* first page always reserved (and doesn't really belong to swap space) */
-	p->swap_map[0] = SWAP_MAP_BAD;
-
-	/* now swapping to this device ok */
-	p->pages = j + k;
-	swap_list_lock();
-	nr_swap_pages += j;
-	p->flags = SWP_WRITEOK;
-
-	/* insert swap space into swap_list */
-	prev = -1;
-	for (i = swap_list.head; i >= 0; i = swap_info[i].next) {
-		if (p->prio >= swap_info[i].prio) {
-			break;
-		}
-		prev = i;
-	}
-	p->next = i;
-	if (prev < 0) {
-		swap_list.head = swap_list.next = p - swap_info;
-	} else {
-		swap_info[prev].next = p - swap_info;
-	}
-	swap_list_unlock();
-
-	printk( KERN_INFO "Using %dk (%d pages) of ST-RAM as swap space.\n",
-			p->pages << 2, p->pages );
-	return( 1 );
-}
-
-
-/*
- * The swap entry has been read in advance, and we return 1 to indicate
- * that the page has been used or is no longer needed.
- *
- * Always set the resulting pte to be nowrite (the same as COW pages
- * after one process has exited).  We don't know just how many PTEs will
- * share this swap entry, so be cautious and let do_wp_page work out
- * what to do if a write is requested later.
- */
-static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
-			      address, pte_t *dir, swp_entry_t entry,
-			      struct page *page)
-{
-	pte_t pte = *dir;
-
-	if (pte_none(pte))
-		return;
-	if (pte_present(pte)) {
-		/* If this entry is swap-cached, then page must already
-                   hold the right address for any copies in physical
-                   memory */
-		if (pte_page(pte) != page)
-			return;
-		/* We will be removing the swap cache in a moment, so... */
-		set_pte(dir, pte_mkdirty(pte));
-		return;
-	}
-	if (pte_val(pte) != entry.val)
-		return;
-
-	DPRINTK("unswap_pte: replacing entry %08lx by new page %p",
-		entry.val, page);
-	set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	swap_free(entry);
-	get_page(page);
-	inc_mm_counter(vma->vm_mm, rss);
-}
-
-static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
-			      unsigned long address, unsigned long size,
-			      unsigned long offset, swp_entry_t entry,
-			      struct page *page)
-{
-	pte_t * pte;
-	unsigned long end;
-
-	if (pmd_none(*dir))
-		return;
-	if (pmd_bad(*dir)) {
-		pmd_ERROR(*dir);
-		pmd_clear(dir);
-		return;
-	}
-	pte = pte_offset_kernel(dir, address);
-	offset += address & PMD_MASK;
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page);
-		address += PAGE_SIZE;
-		pte++;
-	} while (address < end);
-}
-
-static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
-			      unsigned long address, unsigned long size,
-			      swp_entry_t entry, struct page *page)
-{
-	pmd_t * pmd;
-	unsigned long offset, end;
-
-	if (pgd_none(*dir))
-		return;
-	if (pgd_bad(*dir)) {
-		pgd_ERROR(*dir);
-		pgd_clear(dir);
-		return;
-	}
-	pmd = pmd_offset(dir, address);
-	offset = address & PGDIR_MASK;
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	do {
-		unswap_pmd(vma, pmd, address, end - address, offset, entry,
-			   page);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-}
-
-static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,
-		       swp_entry_t entry, struct page *page)
-{
-	unsigned long start = vma->vm_start, end = vma->vm_end;
-
-	do {
-		unswap_pgd(vma, pgdir, start, end - start, entry, page);
-		start = (start + PGDIR_SIZE) & PGDIR_MASK;
-		pgdir++;
-	} while (start < end);
-}
-
-static void unswap_process(struct mm_struct * mm, swp_entry_t entry,
-			   struct page *page)
-{
-	struct vm_area_struct* vma;
-
-	/*
-	 * Go through process' page directory.
-	 */
-	if (!mm)
-		return;
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		pgd_t * pgd = pgd_offset(mm, vma->vm_start);
-		unswap_vma(vma, pgd, entry, page);
-	}
-}
-
-
-static int unswap_by_read(unsigned short *map, unsigned long max,
-			  unsigned long start, unsigned long n_pages)
-{
-	struct task_struct *p;
-	struct page *page;
-	swp_entry_t entry;
-	unsigned long i;
-
-	DPRINTK( "unswapping %lu..%lu by reading in\n",
-			 start, start+n_pages-1 );
-
-	for( i = start; i < start+n_pages; ++i ) {
-		if (map[i] == SWAP_MAP_BAD) {
-			printk( KERN_ERR "get_stram_region: page %lu already "
-					"reserved??\n", i );
-			continue;
-		}
-
-		if (map[i]) {
-			entry = swp_entry(stram_swap_type, i);
-			DPRINTK("unswap: map[i=%lu]=%u nr_swap=%ld\n",
-				i, map[i], nr_swap_pages);
-
-			swap_device_lock(stram_swap_info);
-			map[i]++;
-			swap_device_unlock(stram_swap_info);
-			/* Get a page for the entry, using the existing
-			   swap cache page if there is one.  Otherwise,
-			   get a clean page and read the swap into it. */
-			page = read_swap_cache_async(entry, NULL, 0);
-			if (!page) {
-				swap_free(entry);
-				return -ENOMEM;
-			}
-			read_lock(&tasklist_lock);
-			for_each_process(p)
-				unswap_process(p->mm, entry, page);
-			read_unlock(&tasklist_lock);
-			shmem_unuse(entry, page);
-			/* Now get rid of the extra reference to the
-			   temporary page we've been using. */
-			if (PageSwapCache(page))
-				delete_from_swap_cache(page);
-			__free_page(page);
-	#ifdef DO_PROC
-			stat_swap_force++;
-	#endif
-		}
-
-		DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%ld\n",
-				 i, map[i], nr_swap_pages );
-		swap_list_lock();
-		swap_device_lock(stram_swap_info);
-		map[i] = SWAP_MAP_BAD;
-		if (stram_swap_info->lowest_bit == i)
-			stram_swap_info->lowest_bit++;
-		if (stram_swap_info->highest_bit == i)
-			stram_swap_info->highest_bit--;
-		--nr_swap_pages;
-		swap_device_unlock(stram_swap_info);
-		swap_list_unlock();
-	}
-
-	return 0;
-}
-
-/*
- * reserve a region in ST-RAM swap space for an allocation
- */
-static void *get_stram_region( unsigned long n_pages )
-{
-	unsigned short *map = stram_swap_info->swap_map;
-	unsigned long max = stram_swap_info->max;
-	unsigned long start, total_free, region_free;
-	int err;
-	void *ret = NULL;
-
-	DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages );
-
-	down(&stram_swap_sem);
-
-	/* disallow writing to the swap device now */
-	stram_swap_info->flags = SWP_USED;
-
-	/* find a region of n_pages pages in the swap space including as much free
-	 * pages as possible (and excluding any already-reserved pages). */
-	if (!(start = find_free_region( n_pages, &total_free, &region_free )))
-		goto end;
-	DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",
-			 start, region_free );
-
-	err = unswap_by_read(map, max, start, n_pages);
-	if (err)
-		goto end;
-
-	ret = SWAP_ADDR(start);
-  end:
-	/* allow using swap device again */
-	stram_swap_info->flags = SWP_WRITEOK;
-	up(&stram_swap_sem);
-	DPRINTK( "get_stram_region: returning %p\n", ret );
-	return( ret );
-}
-
-
-/*
- * free a reserved region in ST-RAM swap space
- */
-static void free_stram_region( unsigned long offset, unsigned long n_pages )
-{
-	unsigned short *map = stram_swap_info->swap_map;
-
-	DPRINTK( "free_stram_region(offset=%lu,n_pages=%lu)\n", offset, n_pages );
-
-	if (offset < 1 || offset + n_pages > stram_swap_info->max) {
-		printk( KERN_ERR "free_stram_region: Trying to free non-ST-RAM\n" );
-		return;
-	}
-
-	swap_list_lock();
-	swap_device_lock(stram_swap_info);
-	/* un-reserve the freed pages */
-	for( ; n_pages > 0; ++offset, --n_pages ) {
-		if (map[offset] != SWAP_MAP_BAD)
-			printk( KERN_ERR "free_stram_region: Swap page %lu was not "
-					"reserved\n", offset );
-		map[offset] = 0;
-	}
-
-	/* update swapping meta-data */
-	if (offset < stram_swap_info->lowest_bit)
-		stram_swap_info->lowest_bit = offset;
-	if (offset+n_pages-1 > stram_swap_info->highest_bit)
-		stram_swap_info->highest_bit = offset+n_pages-1;
-	if (stram_swap_info->prio > swap_info[swap_list.next].prio)
-		swap_list.next = swap_list.head;
-	nr_swap_pages += n_pages;
-	swap_device_unlock(stram_swap_info);
-	swap_list_unlock();
-}
-
-
-/* ------------------------------------------------------------------------ */
-/*						Utility Functions for Swapping						*/
-/* ------------------------------------------------------------------------ */
-
-
-/* is addr in some of the allocated regions? */
-static int in_some_region(void *addr)
-{
-	BLOCK *p;
-
-	for( p = alloc_list; p; p = p->next ) {
-		if (p->start <= addr && addr < p->start + p->size)
-			return( 1 );
-	}
-	return( 0 );
-}
-
-
-static unsigned long find_free_region(unsigned long n_pages,
-				      unsigned long *total_free,
-				      unsigned long *region_free)
-{
-	unsigned short *map = stram_swap_info->swap_map;
-	unsigned long max = stram_swap_info->max;
-	unsigned long head, tail, max_start;
-	long nfree, max_free;
-
-	/* first scan the swap space for a suitable place for the allocation */
-	head = 1;
-	max_start = 0;
-	max_free = -1;
-	*total_free = 0;
-
-  start_over:
-	/* increment tail until final window size reached, and count free pages */
-	nfree = 0;
-	for( tail = head; tail-head < n_pages && tail < max; ++tail ) {
-		if (map[tail] == SWAP_MAP_BAD) {
-			head = tail+1;
-			goto start_over;
-		}
-		if (!map[tail]) {
-			++nfree;
-			++*total_free;
-		}
-	}
-	if (tail-head < n_pages)
-		goto out;
-	if (nfree > max_free) {
-		max_start = head;
-		max_free  = nfree;
-		if (max_free >= n_pages)
-			/* don't need more free pages... :-) */
-			goto out;
-	}
-
-	/* now shift the window and look for the area where as much pages as
-	 * possible are free */
-	while( tail < max ) {
-		nfree -= (map[head++] == 0);
-		if (map[tail] == SWAP_MAP_BAD) {
-			head = tail+1;
-			goto start_over;
-		}
-		if (!map[tail]) {
-			++nfree;
-			++*total_free;
-		}
-		++tail;
-		if (nfree > max_free) {
-			max_start = head;
-			max_free  = nfree;
-			if (max_free >= n_pages)
-				/* don't need more free pages... :-) */
-				goto out;
-		}
-	}
-
-  out:
-	if (max_free < 0) {
-		printk( KERN_NOTICE "get_stram_region: ST-RAM too full or fragmented "
-				"-- can't allocate %lu pages\n", n_pages );
-		return( 0 );
-	}
-
-	*region_free = max_free;
-	return( max_start );
-}
-
-
-/* setup parameters from command line */
-void __init stram_swap_setup(char *str, int *ints)
-{
-	if (ints[0] >= 1)
-		max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/*								ST-RAM device								*/
-/* ------------------------------------------------------------------------ */
-
-static int refcnt;
-
-static void do_stram_request(request_queue_t *q)
-{
-	struct request *req;
-
-	while ((req = elv_next_request(q)) != NULL) {
-		void *start = swap_start + (req->sector << 9);
-		unsigned long len = req->current_nr_sectors << 9;
-		if ((start + len) > swap_end) {
-			printk( KERN_ERR "stram: bad access beyond end of device: "
-					"block=%ld, count=%d\n",
-					req->sector,
-					req->current_nr_sectors );
-			end_request(req, 0);
-			continue;
-		}
-
-		if (req->cmd == READ) {
-			memcpy(req->buffer, start, len);
-#ifdef DO_PROC
-			stat_swap_read += N_PAGES(len);
-#endif
-		}
-		else {
-			memcpy(start, req->buffer, len);
-#ifdef DO_PROC
-			stat_swap_write += N_PAGES(len);
-#endif
-		}
-		end_request(req, 1);
-	}
-}
-
-
-static int stram_open( struct inode *inode, struct file *filp )
-{
-	if (filp != MAGIC_FILE_P) {
-		printk( KERN_NOTICE "Only kernel can open ST-RAM device\n" );
-		return( -EPERM );
-	}
-	if (refcnt)
-		return( -EBUSY );
-	++refcnt;
-	return( 0 );
-}
-
-static int stram_release( struct inode *inode, struct file *filp )
-{
-	if (filp != MAGIC_FILE_P) {
-		printk( KERN_NOTICE "Only kernel can close ST-RAM device\n" );
-		return( -EPERM );
-	}
-	if (refcnt > 0)
-		--refcnt;
-	return( 0 );
-}
-
-
-static struct block_device_operations stram_fops = {
-	.open =		stram_open,
-	.release =	stram_release,
-};
-
-static struct gendisk *stram_disk;
-static struct request_queue *stram_queue;
-static DEFINE_SPINLOCK(stram_lock);
-
-int __init stram_device_init(void)
-{
-	if (!MACH_IS_ATARI)
-		/* no point in initializing this, I hope */
-		return -ENXIO;
-
-	if (!max_swap_size)
-		/* swapping not enabled */
-		return -ENXIO;
-	stram_disk = alloc_disk(1);
-	if (!stram_disk)
-		return -ENOMEM;
-
-	if (register_blkdev(STRAM_MAJOR, "stram")) {
-		put_disk(stram_disk);
-		return -ENXIO;
-	}
-
-	stram_queue = blk_init_queue(do_stram_request, &stram_lock);
-	if (!stram_queue) {
-		unregister_blkdev(STRAM_MAJOR, "stram");
-		put_disk(stram_disk);
-		return -ENOMEM;
-	}
-
-	stram_disk->major = STRAM_MAJOR;
-	stram_disk->first_minor = STRAM_MINOR;
-	stram_disk->fops = &stram_fops;
-	stram_disk->queue = stram_queue;
-	sprintf(stram_disk->disk_name, "stram");
-	set_capacity(stram_disk, (swap_end - swap_start)/512);
-	add_disk(stram_disk);
-	return 0;
-}
-
-
-
-/* ------------------------------------------------------------------------ */
-/*							Misc Utility Functions							*/
-/* ------------------------------------------------------------------------ */
-
-/* reserve a range of pages */
-static void reserve_region(void *start, void *end)
-{
-	reserve_bootmem (virt_to_phys(start), end - start);
-}
-
-#endif /* CONFIG_STRAM_SWAP */
-
 
 /* ------------------------------------------------------------------------ */
 /*							  Region Management								*/
@@ -1173,50 +328,9 @@
 {
 	int len = 0;
 	BLOCK *p;
-#ifdef CONFIG_STRAM_SWAP
-	int i;
-	unsigned short *map = stram_swap_info->swap_map;
-	unsigned long max = stram_swap_info->max;
-	unsigned free = 0, used = 0, rsvd = 0;
-#endif
 
-#ifdef CONFIG_STRAM_SWAP
-	if (max_swap_size) {
-		for( i = 1; i < max; ++i ) {
-			if (!map[i])
-				++free;
-			else if (map[i] == SWAP_MAP_BAD)
-				++rsvd;
-			else
-				++used;
-		}
-		PRINT_PROC(
-			"Total ST-RAM:      %8u kB\n"
-			"Total ST-RAM swap: %8lu kB\n"
-			"Free swap:         %8u kB\n"
-			"Used swap:         %8u kB\n"
-			"Allocated swap:    %8u kB\n"
-			"Swap Reads:        %8u\n"
-			"Swap Writes:       %8u\n"
-			"Swap Forced Reads: %8u\n",
-			(stram_end - stram_start) >> 10,
-			(max-1) << (PAGE_SHIFT-10),
-			free << (PAGE_SHIFT-10),
-			used << (PAGE_SHIFT-10),
-			rsvd << (PAGE_SHIFT-10),
-			stat_swap_read,
-			stat_swap_write,
-			stat_swap_force );
-	}
-	else {
-#endif
-		PRINT_PROC( "ST-RAM swapping disabled\n" );
-		PRINT_PROC("Total ST-RAM:      %8u kB\n",
+	PRINT_PROC("Total ST-RAM:      %8u kB\n",
 			   (stram_end - stram_start) >> 10);
-#ifdef CONFIG_STRAM_SWAP
-	}
-#endif
-
 	PRINT_PROC( "Allocated regions:\n" );
 	for( p = alloc_list; p; p = p->next ) {
 		if (len + 50 >= PAGE_SIZE)
@@ -1227,8 +341,6 @@
 			   p->owner);
 		if (p->flags & BLOCK_GFP)
 			PRINT_PROC( "page-alloced)\n" );
-		else if (p->flags & BLOCK_INSWAP)
-			PRINT_PROC( "in swap)\n" );
 		else
 			PRINT_PROC( "??)\n" );
 	}
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 8ed1b01..f7f1d2e 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -121,7 +121,7 @@
 	child->thread.work.syscall_trace = 0;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	unsigned long tmp;
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 4ec95e3..98e4b1a 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -27,10 +27,6 @@
 #include <linux/timex.h>
 #include <linux/profile.h>
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 static inline int set_rtc_mmss(unsigned long nowtime)
 {
   if (mach_set_clock_mmss)
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index 5dcb3fa..fe2383e 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -201,7 +201,7 @@
 			virtaddr += PTRTREESIZE;
 			size -= PTRTREESIZE;
 		} else {
-			pte_dir = pte_alloc_kernel(&init_mm, pmd_dir, virtaddr);
+			pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
 			if (!pte_dir) {
 				printk("ioremap: no mem for pte_dir\n");
 				return NULL;
diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c
index 32e55ad..117481e 100644
--- a/arch/m68k/sun3x/dvma.c
+++ b/arch/m68k/sun3x/dvma.c
@@ -116,7 +116,7 @@
 			pte_t *pte;
 			unsigned long end3;
 
-			if((pte = pte_alloc_kernel(&init_mm, pmd, vaddr)) == NULL) {
+			if((pte = pte_alloc_kernel(pmd, vaddr)) == NULL) {
 				ret = -ENOMEM;
 				goto out;
 			}
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 9724e1c..621d7b9 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -101,7 +101,7 @@
 	put_reg(child, PT_SR, tmp);
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret;
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index b17c1ec..b9d8abb 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -27,10 +27,6 @@
 
 #define	TICK_SIZE (tick_nsec / 1000)
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 extern unsigned long wall_jiffies;
 
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4cd724c..0097a0d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -4,15 +4,1318 @@
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 
-# shouldn't it be per-subarchitecture?
-config ARCH_MAY_HAVE_PC_FDC
-	bool
-	default y
-
 mainmenu "Linux/MIPS Kernel Configuration"
 
 source "init/Kconfig"
 
+menu "Machine selection"
+
+choice
+	prompt "System type"
+	default SGI_IP22
+
+config MIPS_MTX1
+	bool "Support for 4G Systems MTX-1 board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SOC_AU1500
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_BOSPORUS
+	bool "AMD Alchemy Bosporus board"
+	select SOC_AU1500
+	select DMA_NONCOHERENT
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1000
+	bool "AMD Alchemy PB1000 board"
+	select SOC_AU1000
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1100
+	bool "AMD Alchemy PB1100 board"
+	select SOC_AU1100
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1500
+	bool "AMD Alchemy PB1500 board"
+	select SOC_AU1500
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1550
+	bool "AMD Alchemy PB1550 board"
+	select SOC_AU1550
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1200
+	bool "AMD Alchemy PB1200 board"
+	select SOC_AU1200
+	select DMA_NONCOHERENT
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1000
+	bool "AMD Alchemy DB1000 board"
+	select SOC_AU1000
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1100
+	bool "AMD Alchemy DB1100 board"
+	select SOC_AU1100
+	select DMA_NONCOHERENT
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1500
+	bool "AMD Alchemy DB1500 board"
+	select SOC_AU1500
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1550
+	bool "AMD Alchemy DB1550 board"
+	select SOC_AU1550
+	select HW_HAS_PCI
+	select DMA_NONCOHERENT
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1200
+	bool "AMD Alchemy DB1200 board"
+	select SOC_AU1200
+	select DMA_COHERENT
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_MIRAGE
+	bool "AMD Alchemy Mirage board"
+	select DMA_NONCOHERENT
+	select SOC_AU1500
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_COBALT
+	bool "Support for Cobalt Server"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select I8259
+	select IRQ_CPU
+	select MIPS_GT64111
+	select SYS_HAS_CPU_NEVADA
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MACH_DECSTATION
+	bool "Support for DECstations"
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select EARLY_PRINTK
+	select IRQ_CPU
+	select SYS_HAS_CPU_R3000
+	select SYS_HAS_CPU_R4X00
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for DEC's MIPS based workstations.  For details
+	  see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
+	  DECstation porting pages on <http://decstation.unix-ag.org/>.
+
+	  If you have one of the following DECstation Models you definitely
+	  want to choose R4xx0 for the CPU Type:
+
+	  	DECstation 5000/50
+	  	DECstation 5000/150
+	  	DECstation 5000/260
+	  	DECsystem 5900/260
+
+	  otherwise choose R3000.
+
+config MIPS_EV64120
+	bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_GT64120
+	select SYS_HAS_CPU_R5000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  This is an evaluation board based on the Galileo GT-64120
+	  single-chip system controller that contains a MIPS R5000 compatible
+	  core running at 75/100MHz.  Their website is located at
+	  <http://www.marvell.com/>.  Say Y here if you wish to build a
+	  kernel for this platform.
+
+config MIPS_EV96100
+	bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select MIPS_GT96100
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_R5000
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  This is an evaluation board based on the Galileo GT-96100 LAN/WAN
+	  communications controllers containing a MIPS R5000 compatible core
+	  running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
+	  here if you wish to build a kernel for this platform.
+
+config MIPS_IVR
+	bool "Support for Globespan IVR board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select ITE_BOARD_GEN
+	select SYS_HAS_CPU_NEVADA
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This is an evaluation board built by Globespan to showcase thir
+	  iVR (Internet Video Recorder) design. It utilizes a QED RM5231
+	  R5000 MIPS core. More information can be found out their website
+	  located at <http://www.globespan.net/>. Say Y here if you wish to
+	  build a kernel for this platform.
+
+config MIPS_ITE8172
+	bool "Support for ITE 8172G board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select ITE_BOARD_GEN
+	select SYS_HAS_CPU_R5432
+	select SYS_HAS_CPU_NEVADA
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  Ths is an evaluation board made by ITE <http://www.ite.com.tw/>
+	  with ATX form factor that utilizes a MIPS R5000 to work with its
+	  ITE8172G companion internet appliance chip. The MIPS core can be
+	  either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
+	  a kernel for this platform.
+
+config MACH_JAZZ
+	bool "Support for the Jazz family of machines"
+	select ARC
+	select ARC32
+	select ARCH_MAY_HAVE_PC_FDC
+	select GENERIC_ISA_DMA
+	select I8259
+	select ISA
+	select SYS_HAS_CPU_R4X00
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	help
+	 This a family of machines based on the MIPS R4030 chipset which was
+	 used by several vendors to build RISC/os and Windows NT workstations.
+	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
+	 Olivetti M700-10 workstations.
+
+config LASAT
+	bool "Support for LASAT Networks platforms"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_GT64120
+	select MIPS_NILE4
+	select R5000_CPU_SCACHE
+	select SYS_HAS_CPU_R5000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_ATLAS
+	bool "Support for MIPS Atlas board"
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select HW_HAS_PCI
+	select MIPS_BOARDS_GEN
+	select MIPS_BONITO64
+	select MIPS_GT64120
+	select MIPS_MSC
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS64_R1
+	select SYS_HAS_CPU_NEVADA
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the MIPS Technologies Atlas evaluation
+	  board.
+
+config MIPS_MALTA
+	bool "Support for MIPS Malta board"
+	select ARCH_MAY_HAVE_PC_FDC
+	select BOOT_ELF32
+	select HAVE_STD_PC_SERIAL_PORT
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select GENERIC_ISA_DMA
+	select HW_HAS_PCI
+	select I8259
+	select MIPS_BOARDS_GEN
+	select MIPS_BONITO64
+	select MIPS_GT64120
+	select MIPS_MSC
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS64_R1
+	select SYS_HAS_CPU_NEVADA
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the MIPS Technologies Malta evaluation
+	  board.
+
+config MIPS_SEAD
+	bool "Support for MIPS SEAD board (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select IRQ_CPU
+	select DMA_NONCOHERENT
+	select MIPS_BOARDS_GEN
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS64_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the MIPS Technologies SEAD evaluation
+	  board.
+
+config MIPS_SIM
+	bool 'Support for MIPS simulator (MIPSsim)'
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This option enables support for MIPS Technologies MIPSsim software
+	  emulator.
+
+config MOMENCO_JAGUAR_ATX
+	bool "Support for Momentum Jaguar board"
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_CPU_RM7K
+	select IRQ_MV64340
+	select LIMITED_DMA
+	select PCI_MARVELL
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_RM9000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
+	  Momentum Computer <http://www.momenco.com/>.
+
+config MOMENCO_OCELOT
+	bool "Support for Momentum Ocelot board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_CPU_RM7K
+	select MIPS_GT64120
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+	  Momentum Computer <http://www.momenco.com/>.
+
+config MOMENCO_OCELOT_3
+	bool "Support for Momentum Ocelot-3 board"
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_CPU_RM7K
+	select IRQ_MV64340
+	select PCI_MARVELL
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_RM9000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  The Ocelot-3 is based off Discovery III System Controller and
+	  PMC-Sierra Rm79000 core.
+
+config MOMENCO_OCELOT_C
+	bool "Support for Momentum Ocelot-C board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_MV64340
+	select PCI_MARVELL
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+	  Momentum Computer <http://www.momenco.com/>.
+
+config MOMENCO_OCELOT_G
+	bool "Support for Momentum Ocelot-G board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_CPU_RM7K
+	select PCI_MARVELL
+	select RM7000_CPU_SCACHE
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+	  Momentum Computer <http://www.momenco.com/>.
+
+config MIPS_XXS1500
+	bool "Support for MyCable XXS1500 board"
+	select DMA_NONCOHERENT
+	select SOC_AU1500
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config PNX8550_V2PCI
+	bool "Support for Philips PNX8550 based Viper2-PCI board"
+	select PNX8550
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config PNX8550_JBS
+	bool "Support for Philips PNX8550 based JBS board"
+	select PNX8550
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config DDB5074
+	bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select DDB5XXX_COMMON
+	select DMA_NONCOHERENT
+	select HAVE_STD_PC_SERIAL_PORT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select I8259
+	select ISA
+	select SYS_HAS_CPU_R5000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the VR5000-based NEC DDB Vrc-5074
+	  evaluation board.
+
+config DDB5476
+	bool "Support for NEC DDB Vrc-5476"
+	select DDB5XXX_COMMON
+	select DMA_NONCOHERENT
+	select HAVE_STD_PC_SERIAL_PORT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select I8259
+	select ISA
+	select SYS_HAS_CPU_R5432
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the R5432-based NEC DDB Vrc-5476
+	  evaluation board.
+
+	  Features : kernel debugging, serial terminal, NFS root fs, on-board
+	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
+	  IDE controller, PS2 keyboard, PS2 mouse, etc.
+
+config DDB5477
+	bool "Support for NEC DDB Vrc-5477"
+	select DDB5XXX_COMMON
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select I8259
+	select IRQ_CPU
+	select SYS_HAS_CPU_R5432
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the R5432-based NEC DDB Vrc-5477,
+	  or Rockhopper/SolutionGear boards with R5432/R5500 CPUs.
+
+	  Features : kernel debugging, serial terminal, NFS root fs, on-board
+	  ether port USB, AC97, PCI, etc.
+
+config MACH_VR41XX
+	bool "Support for NEC VR4100 series based machines"
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+
+config PMC_YOSEMITE
+	bool "Support for PMC-Sierra Yosemite eval board"
+	select DMA_COHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_CPU_RM7K
+	select IRQ_CPU_RM9K
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_RM9000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	help
+	  Yosemite is an evaluation board for the RM9000x2 processor
+	  manufactured by PMC-Sierra.
+
+config QEMU
+	bool "Support for Qemu"
+	select DMA_COHERENT
+	select GENERIC_ISA_DMA
+	select HAVE_STD_PC_SERIAL_PORT
+	select I8259
+	select ISA
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  Qemu is a software emulator which among other architectures also
+	  can simulate a MIPS32 4Kc system.  This patch adds support for the
+	  system architecture that currently is being simulated by Qemu.  It
+	  will eventually be removed again when Qemu has the capability to
+	  simulate actual MIPS hardware platforms.  More information on Qemu
+	  can be found at http://www.linux-mips.org/wiki/Qemu.
+
+config SGI_IP22
+	bool "Support for SGI IP22 (Indy/Indigo2)"
+	select ARC
+	select ARC32
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select HW_HAS_EISA
+	select IP22_CPU_SCACHE
+	select IRQ_CPU
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_R4X00
+	select SYS_HAS_CPU_R5000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  This are the SGI Indy, Challenge S and Indigo2, as well as certain
+	  OEM variants like the Tandem CMN B006S. To compile a Linux kernel
+	  that runs on these, say Y here.
+
+config SGI_IP27
+	bool "Support for SGI IP27 (Origin200/2000)"
+	select ARC
+	select ARC64
+	select BOOT_ELF64
+	select DMA_IP27
+	select HW_HAS_PCI
+	select PCI_DOMAINS
+	select SYS_HAS_CPU_R10000
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
+	  workstations.  To compile a Linux kernel that runs on these, say Y
+	  here.
+
+config SGI_IP32
+	bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	select ARC
+	select ARC32
+	select BOOT_ELF32
+	select OWN_DMA
+	select DMA_IP32
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select R5000_CPU_SCACHE
+	select RM7000_CPU_SCACHE
+	select SYS_HAS_CPU_R5000
+	select SYS_HAS_CPU_R10000 if BROKEN
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  If you want this kernel to run on SGI O2 workstation, say Y here.
+
+config SIBYTE_BIGSUR
+	bool "Support for Sibyte BigSur"
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select PCI_DOMAINS
+	select SIBYTE_BCM1x80
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_SWARM
+	bool "Support for Sibyte BCM91250A-SWARM"
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_SB1250
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_SENTOSA
+	bool "Support for Sibyte BCM91250E-Sentosa"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_SB1250
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_RHONE
+	bool "Support for Sibyte BCM91125E-Rhone"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_BCM1125H
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_CARMEL
+	bool "Support for Sibyte BCM91120x-Carmel"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_BCM1120
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_PTSWARM
+	bool "Support for Sibyte BCM91250PT-PTSWARM"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_SB1250
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_LITTLESUR
+	bool "Support for Sibyte BCM91250C2-LittleSur"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_SB1250
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_CRHINE
+	bool "Support for Sibyte BCM91120C-CRhine"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_BCM1120
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SIBYTE_CRHONE
+	bool "Support for Sibyte BCM91125C-CRhone"
+	depends on EXPERIMENTAL
+	select BOOT_ELF32
+	select DMA_COHERENT
+	select SIBYTE_BCM1125
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_SB1
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config SNI_RM200_PCI
+	bool "Support for SNI RM200 PCI"
+	select ARC
+	select ARC32
+	select ARCH_MAY_HAVE_PC_FDC
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select GENERIC_ISA_DMA
+	select HAVE_STD_PC_SERIAL_PORT
+	select HW_HAS_EISA
+	select HW_HAS_PCI
+	select I8259
+	select ISA
+	select SYS_HAS_CPU_R4X00
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_BIG_ENDIAN if EXPERIMENTAL
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
+	  Nixdorf Informationssysteme (SNI), parent company of Pyramid
+	  Technology and now in turn merged with Fujitsu.  Say Y here to
+	  support this machine type.
+
+config TOSHIBA_JMR3927
+	bool "Support for Toshiba JMR-TX3927 board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_TX3927
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_TX39XX
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select TOSHIBA_BOARDS
+
+config TOSHIBA_RBTX4927
+	bool "Support for Toshiba TBTX49[23]7 board"
+	select DMA_NONCOHERENT
+	select HAS_TXX9_SERIAL
+	select HW_HAS_PCI
+	select I8259
+	select ISA
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_TX49XX
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select TOSHIBA_BOARDS
+	help
+	  This Toshiba board is based on the TX4927 processor. Say Y here to
+	  support this machine type
+
+config TOSHIBA_RBTX4938
+	bool "Support for Toshiba RBTX4938 board"
+	select HAVE_STD_PC_SERIAL_PORT
+	select DMA_NONCOHERENT
+	select GENERIC_ISA_DMA
+	select HAS_TXX9_SERIAL
+	select HW_HAS_PCI
+	select I8259
+	select ISA
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_TX49XX
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select TOSHIBA_BOARDS
+	help
+	  This Toshiba board is based on the TX4938 processor. Say Y here to
+	  support this machine type
+
+endchoice
+
+source "arch/mips/ddb5xxx/Kconfig"
+source "arch/mips/gt64120/ev64120/Kconfig"
+source "arch/mips/jazz/Kconfig"
+source "arch/mips/ite-boards/Kconfig"
+source "arch/mips/lasat/Kconfig"
+source "arch/mips/momentum/Kconfig"
+source "arch/mips/pmc-sierra/Kconfig"
+source "arch/mips/sgi-ip27/Kconfig"
+source "arch/mips/sibyte/Kconfig"
+source "arch/mips/tx4927/Kconfig"
+source "arch/mips/tx4938/Kconfig"
+source "arch/mips/vr41xx/Kconfig"
+source "arch/mips/philips/pnx8550/common/Kconfig"
+
+endmenu
+
+config RWSEM_GENERIC_SPINLOCK
+	bool
+	default y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
+#
+# Select some configuration options automatically based on user selections.
+#
+config ARC
+	bool
+
+config ARCH_MAY_HAVE_PC_FDC
+	bool
+
+config DMA_COHERENT
+	bool
+
+config DMA_IP27
+	bool
+
+config DMA_IP32
+	bool
+	select DMA_NEED_PCI_MAP_STATE
+
+config DMA_NONCOHERENT
+	bool
+	select DMA_NEED_PCI_MAP_STATE
+
+config DMA_NEED_PCI_MAP_STATE
+	bool
+
+config OWN_DMA
+	bool
+
+config EARLY_PRINTK
+	bool
+
+config GENERIC_ISA_DMA
+	bool
+
+config I8259
+	bool
+
+config LIMITED_DMA
+	bool
+	select HIGHMEM
+	select SYS_SUPPORTS_HIGHMEM
+
+config MIPS_BONITO64
+	bool
+
+config MIPS_MSC
+	bool
+
+config MIPS_NILE4
+	bool
+
+config MIPS_DISABLE_OBSOLETE_IDE
+	bool
+
+#
+# Endianess selection.  Suffiently obscure so many users don't know what to
+# answer,so we try hard to limit the available choices.  Also the use of a
+# choice statement should be more obvious to the user.
+#
+choice
+	prompt "Endianess selection"
+	help
+	  Some MIPS machines can be configured for either little or big endian
+	  byte order. These modes require different kernels and a different
+	  Linux distribution.  In general there is one prefered byteorder for a
+	  particular system but some systems are just as commonly used in the
+	  one or the other endianess.
+
+config CPU_BIG_ENDIAN
+	bool "Big endian"
+	depends on SYS_SUPPORTS_BIG_ENDIAN
+
+config CPU_LITTLE_ENDIAN
+	bool "Little endian"
+	depends on SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+
+endchoice
+
+config SYS_SUPPORTS_BIG_ENDIAN
+	bool
+
+config SYS_SUPPORTS_LITTLE_ENDIAN
+	bool
+
+config IRQ_CPU
+	bool
+
+config IRQ_CPU_RM7K
+	bool
+
+config IRQ_CPU_RM9K
+	bool
+
+config IRQ_MV64340
+	bool
+
+config DDB5XXX_COMMON
+	bool
+
+config MIPS_BOARDS_GEN
+	bool
+
+config MIPS_GT64111
+	bool
+
+config MIPS_GT64120
+	bool
+
+config MIPS_TX3927
+	bool
+	select HAS_TXX9_SERIAL
+
+config PCI_MARVELL
+	bool
+
+config ITE_BOARD_GEN
+	bool
+
+config SOC_AU1000
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1100
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1500
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1550
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1200
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1X00
+	bool
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+
+config PNX8550
+	bool
+	select SOC_PNX8550
+
+config SOC_PNX8550
+	bool
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SYS_HAS_CPU_R4X00
+	select SYS_SUPPORTS_32BIT_KERNEL
+
+config SWAP_IO_SPACE
+	bool
+
+#
+# Unfortunately not all GT64120 systems run the chip at the same clock.
+# As the user for the clock rate and try to minimize the available options.
+#
+choice
+	prompt "Galileo Chip Clock"
+	#default SYSCLK_83 if MIPS_EV64120
+	depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+	default SYSCLK_83 if MIPS_EV64120
+	default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G
+
+config SYSCLK_75
+	bool "75" if MIPS_EV64120
+
+config SYSCLK_83
+	bool "83.3" if MIPS_EV64120
+
+config SYSCLK_100
+	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+
+endchoice
+
+config ARC32
+	bool
+
+config AU1X00_USB_DEVICE
+	bool
+	depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
+	default n
+
+config MIPS_GT96100
+	bool
+	select MIPS_GT64120
+
+config IT8172_CIR
+	bool
+	depends on MIPS_ITE8172 || MIPS_IVR
+	default y
+
+config IT8712
+	bool
+	depends on MIPS_ITE8172
+	default y
+
+config BOOT_ELF32
+	bool
+
+config MIPS_L1_CACHE_SHIFT
+	int
+	default "4" if MACH_DECSTATION
+	default "7" if SGI_IP27
+	default "5"
+
+config HAVE_STD_PC_SERIAL_PORT
+	bool
+
+config ARC_CONSOLE
+	bool "ARC console support"
+	depends on SGI_IP22 || SNI_RM200_PCI
+
+config ARC_MEMORY
+	bool
+	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32
+	default y
+
+config ARC_PROMLIB
+	bool
+	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
+	default y
+
+config ARC64
+	bool
+
+config BOOT_ELF64
+	bool
+
+config TOSHIBA_BOARDS
+	bool
+
+menu "CPU selection"
+
+choice
+	prompt "CPU type"
+	default CPU_R4X00
+
+config CPU_MIPS32_R1
+	bool "MIPS32 Release 1"
+	depends on SYS_HAS_CPU_MIPS32_R1
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	help
+	  Choose this option to build a kernel for release 1 or later of the
+	  MIPS32 architecture.  Most modern embedded systems with a 32-bit
+	  MIPS processor are based on a MIPS32 processor.  If you know the
+	  specific type of processor in your system, choose those that one
+	  otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
+	  Release 2 of the MIPS32 architecture is available since several
+	  years so chances are you even have a MIPS32 Release 2 processor
+	  in which case you should choose CPU_MIPS32_R2 instead for better
+	  performance.
+
+config CPU_MIPS32_R2
+	bool "MIPS32 Release 2"
+	depends on SYS_HAS_CPU_MIPS32_R2
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	help
+	  Choose this option to build a kernel for release 2 or later of the
+	  MIPS32 architecture.  Most modern embedded systems with a 32-bit
+	  MIPS processor are based on a MIPS32 processor.  If you know the
+	  specific type of processor in your system, choose those that one
+	  otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
+
+config CPU_MIPS64_R1
+	bool "MIPS64 Release 1"
+	depends on SYS_HAS_CPU_MIPS64_R1
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  Choose this option to build a kernel for release 1 or later of the
+	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
+	  MIPS processor are based on a MIPS64 processor.  If you know the
+	  specific type of processor in your system, choose those that one
+	  otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
+	  Release 2 of the MIPS64 architecture is available since several
+	  years so chances are you even have a MIPS64 Release 2 processor
+	  in which case you should choose CPU_MIPS64_R2 instead for better
+	  performance.
+
+config CPU_MIPS64_R2
+	bool "MIPS64 Release 2"
+	depends on SYS_HAS_CPU_MIPS64_R2
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  Choose this option to build a kernel for release 2 or later of the
+	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
+	  MIPS processor are based on a MIPS64 processor.  If you know the
+	  specific type of processor in your system, choose those that one
+	  otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
+
+config CPU_R3000
+	bool "R3000"
+	depends on SYS_HAS_CPU_R3000
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	help
+	  Please make sure to pick the right CPU type. Linux/MIPS is not
+	  designed to be generic, i.e. Kernels compiled for R3000 CPUs will
+	  *not* work on R4000 machines and vice versa.  However, since most
+	  of the supported machines have an R4000 (or similar) CPU, R4x00
+	  might be a safe bet.  If the resulting kernel does not work,
+	  try to recompile with R3000.
+
+config CPU_TX39XX
+	bool "R39XX"
+	depends on SYS_HAS_CPU_TX39XX
+	select CPU_SUPPORTS_32BIT_KERNEL
+
+config CPU_VR41XX
+	bool "R41xx"
+	depends on SYS_HAS_CPU_VR41XX
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  The options selects support for the NEC VR4100 series of processors.
+	  Only choose this option if you have one of these processors as a
+	  kernel built with this option will not run on any other type of
+	  processor or vice versa.
+
+config CPU_R4300
+	bool "R4300"
+	depends on SYS_HAS_CPU_R4300
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  MIPS Technologies R4300-series processors.
+
+config CPU_R4X00
+	bool "R4x00"
+	depends on SYS_HAS_CPU_R4X00
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  MIPS Technologies R4000-series processors other than 4300, including
+	  the R4000, R4400, R4600, and 4700.
+
+config CPU_TX49XX
+	bool "R49XX"
+	depends on SYS_HAS_CPU_TX49XX
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+
+config CPU_R5000
+	bool "R5000"
+	depends on SYS_HAS_CPU_R5000
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  MIPS Technologies R5000-series processors other than the Nevada.
+
+config CPU_R5432
+	bool "R5432"
+	depends on SYS_HAS_CPU_R5432
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+
+config CPU_R6000
+	bool "R6000"
+	depends on EXPERIMENTAL
+	depends on SYS_HAS_CPU_R6000
+	select CPU_SUPPORTS_32BIT_KERNEL
+	help
+	  MIPS Technologies R6000 and R6000A series processors.  Note these
+	  processors are extremly rare and the support for them is incomplete.
+
+config CPU_NEVADA
+	bool "RM52xx"
+	depends on SYS_HAS_CPU_NEVADA
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  QED / PMC-Sierra RM52xx-series ("Nevada") processors.
+
+config CPU_R8000
+	bool "R8000"
+	depends on EXPERIMENTAL
+	depends on SYS_HAS_CPU_R8000
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_64BIT_KERNEL
+	help
+	  MIPS Technologies R8000 processors.  Note these processors are
+	  uncommon and the support for them is incomplete.
+
+config CPU_R10000
+	bool "R10000"
+	depends on SYS_HAS_CPU_R10000
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	help
+	  MIPS Technologies R10000-series processors.
+
+config CPU_RM7000
+	bool "RM7000"
+	depends on SYS_HAS_CPU_RM7000
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+
+config CPU_RM9000
+	bool "RM9000"
+	depends on SYS_HAS_CPU_RM9000
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+
+config CPU_SB1
+	bool "SB1"
+	depends on SYS_HAS_CPU_SB1
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+
+endchoice
+
+config SYS_HAS_CPU_MIPS32_R1
+	bool
+
+config SYS_HAS_CPU_MIPS32_R2
+	bool
+
+config SYS_HAS_CPU_MIPS64_R1
+	bool
+
+config SYS_HAS_CPU_MIPS64_R2
+	bool
+
+config SYS_HAS_CPU_R3000
+	bool
+
+config SYS_HAS_CPU_TX39XX
+	bool
+
+config SYS_HAS_CPU_VR41XX
+	bool
+
+config SYS_HAS_CPU_R4300
+	bool
+
+config SYS_HAS_CPU_R4X00
+	bool
+
+config SYS_HAS_CPU_TX49XX
+	bool
+
+config SYS_HAS_CPU_R5000
+	bool
+
+config SYS_HAS_CPU_R5432
+	bool
+
+config SYS_HAS_CPU_R6000
+	bool
+
+config SYS_HAS_CPU_NEVADA
+	bool
+
+config SYS_HAS_CPU_R8000
+	bool
+
+config SYS_HAS_CPU_R10000
+	bool
+
+config SYS_HAS_CPU_RM7000
+	bool
+
+config SYS_HAS_CPU_RM9000
+	bool
+
+config SYS_HAS_CPU_SB1
+	bool
+
+endmenu
+
+#
+# These two indicate any levelof the MIPS32 and MIPS64 architecture
+#
+config CPU_MIPS32
+	bool
+	default y if CPU_MIPS32_R1 || CPU_MIPS32_R2
+
+config CPU_MIPS64
+	bool
+	default y if CPU_MIPS64_R1 || CPU_MIPS64_R2
+
+#
+# These two indicate the revision of the architecture, either 32 bot 64 bit.
+#
+config CPU_MIPSR1
+	bool
+	default y if CPU_MIPS32_R1 || CPU_MIPS64_R1
+
+config CPU_MIPSR2
+	bool
+	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2
+
 config SYS_SUPPORTS_32BIT_KERNEL
 	bool
 config SYS_SUPPORTS_64BIT_KERNEL
@@ -39,7 +1342,6 @@
 	select TRAD_SIGNALS
 	help
 	  Select this option if you want to build a 32-bit kernel.
-
 config 64BIT
 	bool "64-bit kernel"
 	depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
@@ -48,1306 +1350,6 @@
 
 endchoice
 
-endmenu
-
-menu "Machine selection"
-
-config MACH_JAZZ
-	bool "Support for the Jazz family of machines"
-	select ARC
-	select ARC32
-	select GENERIC_ISA_DMA
-	select I8259
-	select ISA
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	help
-	 This a family of machines based on the MIPS R4030 chipset which was
-	 used by several vendors to build RISC/os and Windows NT workstations.
-	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
-	 Olivetti M700-10 workstations.
-
-config ACER_PICA_61
-	bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)"
-	depends on MACH_JAZZ && EXPERIMENTAL
-	select DMA_NONCOHERENT
-	help
-	  This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
-	  kernel that runs on these, say Y here. For details about Linux on
-	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-	  <http://www.linux-mips.org/>.
-
-config MIPS_MAGNUM_4000
-	bool "Support for MIPS Magnum 4000"
-	depends on MACH_JAZZ
-	select DMA_NONCOHERENT
-	help
-	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
-	  kernel that runs on these, say Y here. For details about Linux on
-	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-	  <http://www.linux-mips.org/>.
-
-config OLIVETTI_M700
-	bool "Support for Olivetti M700-10"
-	depends on MACH_JAZZ
-	select DMA_NONCOHERENT
-	help
-	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
-	  kernel that runs on these, say Y here. For details about Linux on
-	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-	  <http://www.linux-mips.org/>.
-
-config MACH_VR41XX
-	bool "Support for NEC VR4100 series based machines"
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-
-config NEC_CMBVR4133
-	bool "Support for NEC CMB-VR4133"
-	depends on MACH_VR41XX
-	select CPU_VR41XX
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select HW_HAS_PCI
-
-config ROCKHOPPER
-	bool "Support for Rockhopper baseboard"
-	depends on NEC_CMBVR4133
-	select I8259
-	select HAVE_STD_PC_SERIAL_PORT
-
-config CASIO_E55
-	bool "Support for CASIO CASSIOPEIA E-10/15/55/65"
-	depends on MACH_VR41XX
-	select CPU_LITTLE_ENDIAN
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select ISA
-
-config IBM_WORKPAD
-	bool "Support for IBM WorkPad z50"
-	depends on MACH_VR41XX
-	select CPU_LITTLE_ENDIAN
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select ISA
-
-config TANBAC_TB022X
-	bool "Support for TANBAC VR4131 multichip module and TANBAC VR4131DIMM"
-	depends on MACH_VR41XX
-	select CPU_LITTLE_ENDIAN
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select HW_HAS_PCI
-	help
-	  The TANBAC VR4131 multichip module(TB0225) and
-	  the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms
-	  manufactured by TANBAC.
-	  Please refer to <http://www.tanbac.co.jp/>
-	  about VR4131 multichip module and VR4131DIMM.
-
-config TANBAC_TB0226
-	bool "Support for TANBAC Mbase(TB0226)"
-	depends on TANBAC_TB022X
-	select GPIO_VR41XX
-	help
-	  The TANBAC Mbase(TB0226) is a MIPS-based platform manufactured by TANBAC.
-	  Please refer to <http://www.tanbac.co.jp/> about Mbase.
-
-config TANBAC_TB0287
-	bool "Support for TANBAC Mini-ITX DIMM base(TB0287)"
-	depends on TANBAC_TB022X
-	help
-	  The TANBAC Mini-ITX DIMM base(TB0287) is a MIPS-based platform manufactured by TANBAC.
-	  Please refer to <http://www.tanbac.co.jp/> about Mini-ITX DIMM base.
-
-config VICTOR_MPC30X
-	bool "Support for Victor MP-C303/304"
-	depends on MACH_VR41XX
-	select CPU_LITTLE_ENDIAN
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select HW_HAS_PCI
-
-config ZAO_CAPCELLA
-	bool "Support for ZAO Networks Capcella"
-	depends on MACH_VR41XX
-	select CPU_LITTLE_ENDIAN
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select HW_HAS_PCI
-
-config PCI_VR41XX
-	bool "Add PCI control unit support of NEC VR4100 series"
-	depends on MACH_VR41XX && HW_HAS_PCI
-	default y
-	select PCI
-
-config VRC4173
-	tristate "Add NEC VRC4173 companion chip support"
-	depends on MACH_VR41XX && PCI_VR41XX
-	---help---
-	  The NEC VRC4173 is a companion chip for NEC VR4122/VR4131.
-
-config TOSHIBA_JMR3927
-	bool "Support for Toshiba JMR-TX3927 board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-
-config MIPS_COBALT
-	bool "Support for Cobalt Server"
-	depends on EXPERIMENTAL
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select I8259
-	select IRQ_CPU
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-
-config MACH_DECSTATION
-	bool "Support for DECstations"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select IRQ_CPU
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	---help---
-	  This enables support for DEC's MIPS based workstations.  For details
-	  see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
-	  DECstation porting pages on <http://decstation.unix-ag.org/>.
-
-	  If you have one of the following DECstation Models you definitely
-	  want to choose R4xx0 for the CPU Type:
-
-	  	DECstation 5000/50
-	  	DECstation 5000/150
-	  	DECstation 5000/260
-	  	DECsystem 5900/260
-
-	  otherwise choose R3000.
-
-config MIPS_EV64120
-	bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select MIPS_GT64120
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This is an evaluation board based on the Galileo GT-64120
-	  single-chip system controller that contains a MIPS R5000 compatible
-	  core running at 75/100MHz.  Their website is located at
-	  <http://www.marvell.com/>.  Say Y here if you wish to build a
-	  kernel for this platform.
-
-config EVB_PCI1
-	bool "Enable Second PCI (PCI1)"
-	depends on MIPS_EV64120
-
-config MIPS_EV96100
-	bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select MIPS_GT96100
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This is an evaluation board based on the Galileo GT-96100 LAN/WAN
-	  communications controllers containing a MIPS R5000 compatible core
-	  running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
-	  here if you wish to build a kernel for this platform.
-
-config MIPS_IVR
-	bool "Support for Globespan IVR board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	help
-	  This is an evaluation board built by Globespan to showcase thir
-	  iVR (Internet Video Recorder) design. It utilizes a QED RM5231
-	  R5000 MIPS core. More information can be found out their website
-	  located at <http://www.globespan.net/>. Say Y here if you wish to
-	  build a kernel for this platform.
-
-config LASAT
-	bool "Support for LASAT Networks platforms"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select MIPS_GT64120
-	select R5000_CPU_SCACHE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-
-config PICVUE
-	tristate "PICVUE LCD display driver"
-	depends on LASAT
-
-config PICVUE_PROC
-	tristate "PICVUE LCD display driver /proc interface"
-	depends on PICVUE
-
-config DS1603
-	bool "DS1603 RTC driver"
-	depends on LASAT
-
-config LASAT_SYSCTL
-	bool "LASAT sysctl interface"
-	depends on LASAT
-
-config MIPS_ITE8172
-	bool "Support for ITE 8172G board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	help
-	  Ths is an evaluation board made by ITE <http://www.ite.com.tw/>
-	  with ATX form factor that utilizes a MIPS R5000 to work with its
-	  ITE8172G companion internet appliance chip. The MIPS core can be
-	  either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
-	  a kernel for this platform.
-
-config IT8172_REVC
-	bool "Support for older IT8172 (Rev C)"
-	depends on MIPS_ITE8172
-	help
-	  Say Y here to support the older, Revision C version of the Integrated
-	  Technology Express, Inc. ITE8172 SBC.  Vendor page at
-	  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
-	  board at <http://www.mvista.com/partners/semiconductor/ite.html>.
-
-config MIPS_ATLAS
-	bool "Support for MIPS Atlas board"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select MIPS_GT64120
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This enables support for the QED R5231-based MIPS Atlas evaluation
-	  board.
-
-config MIPS_MALTA
-	bool "Support for MIPS Malta board"
-	select BOOT_ELF32
-	select HAVE_STD_PC_SERIAL_PORT
-	select DMA_NONCOHERENT
-	select GENERIC_ISA_DMA
-	select HW_HAS_PCI
-	select I8259
-	select MIPS_GT64120
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This enables support for the VR5000-based MIPS Malta evaluation
-	  board.
-
-config MIPS_SEAD
-	bool "Support for MIPS SEAD board (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select IRQ_CPU
-	select DMA_NONCOHERENT
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-
-config MOMENCO_OCELOT
-	bool "Support for Momentum Ocelot board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select MIPS_GT64120
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
-config MOMENCO_OCELOT_G
-	bool "Support for Momentum Ocelot-G board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
-config MOMENCO_OCELOT_C
-	bool "Support for Momentum Ocelot-C board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_MV64340
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
-config MOMENCO_OCELOT_3
-	bool "Support for Momentum Ocelot-3 board"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_MV64340
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  The Ocelot-3 is based off Discovery III System Controller and
-	  PMC-Sierra Rm79000 core.
-
-config MOMENCO_JAGUAR_ATX
-	bool "Support for Momentum Jaguar board"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_MV64340
-	select LIMITED_DMA
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
-config JAGUAR_DMALOW
-	bool "Low DMA Mode"
-	depends on MOMENCO_JAGUAR_ATX
-	help
-	  Select to Y if jump JP5 is set on your board, N otherwise.  Normally
-	  the jumper is set, so if you feel unsafe, just say Y.
-
-config PMC_YOSEMITE
-	bool "Support for PMC-Sierra Yosemite eval board"
-	select DMA_COHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_CPU_RM9K
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  Yosemite is an evaluation board for the RM9000x2 processor
-	  manufactured by PMC-Sierra
-
-config HYPERTRANSPORT
-	bool "Hypertransport Support for PMC-Sierra Yosemite"
-	depends on PMC_YOSEMITE
-
-config DDB5074
-	bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select DMA_NONCOHERENT
-	select HAVE_STD_PC_SERIAL_PORT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select I8259
-	select ISA
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This enables support for the VR5000-based NEC DDB Vrc-5074
-	  evaluation board.
-
-config DDB5476
-	bool "Support for NEC DDB Vrc-5476"
-	select DMA_NONCOHERENT
-	select HAVE_STD_PC_SERIAL_PORT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select I8259
-	select ISA
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	help
-	  This enables support for the R5432-based NEC DDB Vrc-5476
-	  evaluation board.
-
-	  Features : kernel debugging, serial terminal, NFS root fs, on-board
-	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
-	  IDE controller, PS2 keyboard, PS2 mouse, etc.
-
-config DDB5477
-	bool "Support for NEC DDB Vrc-5477"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select I8259
-	select IRQ_CPU
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	help
-	  This enables support for the R5432-based NEC DDB Vrc-5477,
-	  or Rockhopper/SolutionGear boards with R5432/R5500 CPUs.
-
-	  Features : kernel debugging, serial terminal, NFS root fs, on-board
-	  ether port USB, AC97, PCI, etc.
-
-config DDB5477_BUS_FREQUENCY
-	int "bus frequency (in kHZ, 0 for auto-detect)"
-	depends on DDB5477
-	default 0
-
-config QEMU
-	bool "Support for Qemu"
-	select DMA_COHERENT
-	select GENERIC_ISA_DMA
-	select HAVE_STD_PC_SERIAL_PORT
-	select I8259
-	select ISA
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	help
-	 Qemu is a software emulator which among other architectures also
-	 can simulate a MIPS32 4Kc system.  This patch adds support for the
-	 system architecture that currently is being simulated by Qemu.  It
-	 will eventually be removed again when Qemu has the capability to
-	 simulate actual MIPS hardware platforms.  More information on Qemu
-	 can be found at http://www.linux-mips.org/wiki/Qemu.
-
-config SGI_IP22
-	bool "Support for SGI IP22 (Indy/Indigo2)"
-	select ARC
-	select ARC32
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select IP22_CPU_SCACHE
-	select IRQ_CPU
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This are the SGI Indy, Challenge S and Indigo2, as well as certain
-	  OEM variants like the Tandem CMN B006S. To compile a Linux kernel
-	  that runs on these, say Y here.
-
-config SGI_IP27
-	bool "Support for SGI IP27 (Origin200/2000)"
-	select ARC
-	select ARC64
-	select DMA_IP27
-	select HW_HAS_PCI
-	select PCI_DOMAINS
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
-	  workstations.  To compile a Linux kernel that runs on these, say Y
-	  here.
-
-#config SGI_SN0_XXL
-#	bool "IP27 XXL"
-#	depends on SGI_IP27
-#	  This options adds support for userspace processes upto 16TB size.
-#	  Normally the limit is just .5TB.
-
-config SGI_SN0_N_MODE
-	bool "IP27 N-Mode"
-	depends on SGI_IP27
-	help
-	  The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
-	  configured in either N-Modes which allows for more nodes or M-Mode
-	  which allows for more memory.  Your system is most probably
-	  running in M-Mode, so you should say N here.
-
-config ARCH_DISCONTIGMEM_ENABLE
-	bool
-	default y if SGI_IP27
-	help
-	  Say Y to upport efficient handling of discontiguous physical memory,
-	  for architectures which are either NUMA (Non-Uniform Memory Access)
-	  or have huge holes in the physical address space for other reasons.
-	  See <file:Documentation/vm/numa> for more.
-
-config NUMA
-	bool "NUMA Support"
-	depends on SGI_IP27
-	help
-	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
-	  Access).  This option is for configuring high-end multiprocessor
-	  server machines.  If in doubt, say N.
-
-config MAPPED_KERNEL
-	bool "Mapped kernel support"
-	depends on SGI_IP27
-	help
-	  Change the way a Linux kernel is loaded into memory on a MIPS64
-	  machine.  This is required in order to support text replication and
-	  NUMA.  If you need to understand it, read the source code.
-
-config REPLICATE_KTEXT
-	bool "Kernel text replication support"
-	depends on SGI_IP27
-	help
-	  Say Y here to enable replicating the kernel text across multiple
-	  nodes in a NUMA cluster.  This trades memory for speed.
-
-config REPLICATE_EXHANDLERS
-	bool "Exception handler replication support"
-	depends on SGI_IP27
-	help
-	  Say Y here to enable replicating the kernel exception handlers
-	  across multiple nodes in a NUMA cluster. This trades memory for
-	  speed.
-
-config SGI_IP32
-	bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select ARC
-	select ARC32
-	select BOOT_ELF32
-	select OWN_DMA
-	select DMA_IP32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select R5000_CPU_SCACHE
-	select RM7000_CPU_SCACHE
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  If you want this kernel to run on SGI O2 workstation, say Y here.
-
-config SOC_AU1X00
-	bool "Support for AMD/Alchemy Au1X00 SOCs"
-	select SYS_SUPPORTS_32BIT_KERNEL
-
-choice
-	prompt "Au1X00 SOC Type"
-	depends on SOC_AU1X00
-	help
-	  Say Y here to enable support for one of three AMD/Alchemy
-	  SOCs. For additional documentation see www.amd.com.
-
-config SOC_AU1000
-	bool "SOC_AU1000"
-config SOC_AU1100
-	bool "SOC_AU1100"
-config SOC_AU1500
-	bool "SOC_AU1500"
-config SOC_AU1550
-	bool "SOC_AU1550"
-
-endchoice
-
-choice
-	prompt "AMD/Alchemy Au1x00 board support"
-	depends on SOC_AU1X00
-	help
-	  These are evaluation boards built by AMD/Alchemy to
-	  showcase their Au1X00 Internet Edge Processors. The SOC design
-	  is based on the MIPS32 architecture running at 266/400/500MHz
-	  with many integrated peripherals. Further information can be
-	  found at their website, <http://www.amd.com/>. Say Y here if you
-	  wish to build a kernel for this platform.
-
-config MIPS_PB1000
-	bool "PB1000 board"
-	depends on SOC_AU1000
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SWAP_IO_SPACE
-
-config MIPS_PB1100
-	bool "PB1100 board"
-	depends on SOC_AU1100
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SWAP_IO_SPACE
-
-config MIPS_PB1500
-	bool "PB1500 board"
-	depends on SOC_AU1500
-	select DMA_COHERENT
-	select HW_HAS_PCI
-
-config MIPS_PB1550
-	bool "PB1550 board"
-	depends on SOC_AU1550
-	select DMA_COHERENT
-	select HW_HAS_PCI
-	select MIPS_DISABLE_OBSOLETE_IDE
-
-config MIPS_DB1000
-	bool "DB1000 board"
-	depends on SOC_AU1000
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-
-config MIPS_DB1100
-	bool "DB1100 board"
-	depends on SOC_AU1100
-	select DMA_NONCOHERENT
-
-config MIPS_DB1500
-	bool "DB1500 board"
-	depends on SOC_AU1500
-	select DMA_COHERENT
-	select HW_HAS_PCI
-	select MIPS_DISABLE_OBSOLETE_IDE
-
-config MIPS_DB1550
-	bool "DB1550 board"
-	depends on SOC_AU1550
-	select HW_HAS_PCI
-	select DMA_COHERENT
-	select MIPS_DISABLE_OBSOLETE_IDE
-
-config MIPS_BOSPORUS
-	bool "Bosporus board"
-	depends on SOC_AU1500
-	select DMA_NONCOHERENT
-
-config MIPS_MIRAGE
-	bool "Mirage board"
-	depends on SOC_AU1500
-	select DMA_NONCOHERENT
-
-config MIPS_XXS1500
-	bool "MyCable XXS1500 board"
-	depends on SOC_AU1500
-	select DMA_NONCOHERENT
-
-config MIPS_MTX1
-	bool "4G Systems MTX-1 board"
-	depends on SOC_AU1500
-	select HW_HAS_PCI
-	select DMA_NONCOHERENT
-
-endchoice
-
-config SIBYTE_SB1xxx_SOC
-	bool "Support for Broadcom BCM1xxx SOCs (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select BOOT_ELF32
-	select DMA_COHERENT
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-
-choice
-	prompt "BCM1xxx SOC-based board"
-	depends on SIBYTE_SB1xxx_SOC
-	default SIBYTE_SWARM
-	help
-	  Enable support for boards based on the SiByte line of SOCs
-	  from Broadcom.  There are configurations for the known
-	  evaluation boards, or you can choose "Other" and add your
-	  own board support code.
-
-config SIBYTE_SWARM
-	bool "BCM91250A-SWARM"
-	select SIBYTE_SB1250
-
-config SIBYTE_SENTOSA
-	bool "BCM91250E-Sentosa"
-	select SIBYTE_SB1250
-
-config SIBYTE_RHONE
-	bool "BCM91125E-Rhone"
-	select SIBYTE_BCM1125H
-
-config SIBYTE_CARMEL
-	bool "BCM91120x-Carmel"
-	select SIBYTE_BCM1120
-
-config SIBYTE_PTSWARM
-	bool "BCM91250PT-PTSWARM"
-	select SIBYTE_SB1250
-
-config SIBYTE_LITTLESUR
-	bool "BCM91250C2-LittleSur"
-	select SIBYTE_SB1250
-
-config SIBYTE_CRHINE
-	bool "BCM91120C-CRhine"
-	select SIBYTE_BCM1120
-
-config SIBYTE_CRHONE
-	bool "BCM91125C-CRhone"
-	select SIBYTE_BCM1125
-
-config SIBYTE_UNKNOWN
-	bool "Other"
-
-endchoice
-
-config SIBYTE_BOARD
-	bool
-	depends on SIBYTE_SB1xxx_SOC && !SIBYTE_UNKNOWN
-	default y
-
-choice
-	prompt "BCM1xxx SOC Type"
-	depends on SIBYTE_UNKNOWN
-	default SIBYTE_UNK_BCM1250
-	help
-	  Since you haven't chosen a known evaluation board from
-	  Broadcom, you must explicitly pick the SOC this kernel is
-	  targetted for.
-
-config SIBYTE_UNK_BCM1250
-	bool "BCM1250"
-	select SIBYTE_SB1250
-
-config SIBYTE_UNK_BCM1120
-	bool "BCM1120"
-	select SIBYTE_BCM1120
-
-config SIBYTE_UNK_BCM1125
-	bool "BCM1125"
-	select SIBYTE_BCM1125
-
-config SIBYTE_UNK_BCM1125H
-	bool "BCM1125H"
-	select SIBYTE_BCM1125H
-
-endchoice
-
-config SIBYTE_SB1250
-	bool
-	select HW_HAS_PCI
-
-config SIBYTE_BCM1120
-	bool
-	select SIBYTE_BCM112X
-
-config SIBYTE_BCM1125
-	bool
-	select HW_HAS_PCI
-	select SIBYTE_BCM112X
-
-config SIBYTE_BCM1125H
-	bool
-	select HW_HAS_PCI
-	select SIBYTE_BCM112X
-
-config SIBYTE_BCM112X
-	bool
-
-choice
-	prompt "SiByte SOC Stepping"
-	depends on SIBYTE_SB1xxx_SOC
-
-config CPU_SB1_PASS_1
-	bool "1250 Pass1"
-	depends on SIBYTE_SB1250
-	select CPU_HAS_PREFETCH
-
-config CPU_SB1_PASS_2_1250
-	bool "1250 An"
-	depends on SIBYTE_SB1250
-	select CPU_SB1_PASS_2
-	help
-	  Also called BCM1250 Pass 2
-
-config CPU_SB1_PASS_2_2
-	bool "1250 Bn"
-	depends on SIBYTE_SB1250
-	select CPU_HAS_PREFETCH
-	help
-	  Also called BCM1250 Pass 2.2
-
-config CPU_SB1_PASS_4
-	bool "1250 Cn"
-	depends on SIBYTE_SB1250
-	select CPU_HAS_PREFETCH
-	help
-	  Also called BCM1250 Pass 3
-
-config CPU_SB1_PASS_2_112x
-	bool "112x Hybrid"
-	depends on SIBYTE_BCM112X
-	select CPU_SB1_PASS_2
-
-config CPU_SB1_PASS_3
-	bool "112x An"
-	depends on SIBYTE_BCM112X
-	select CPU_HAS_PREFETCH
-
-endchoice
-
-config CPU_SB1_PASS_2
-	bool
-
-config SIBYTE_HAS_LDT
-	bool
-	depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H)
-	default y
-
-config SIMULATION
-	bool "Running under simulation"
-	depends on SIBYTE_SB1xxx_SOC
-	help
-	  Build a kernel suitable for running under the GDB simulator.
-	  Primarily adjusts the kernel's notion of time.
-
-config SIBYTE_CFE
-	bool "Booting from CFE"
-	depends on SIBYTE_SB1xxx_SOC
-	help
-	  Make use of the CFE API for enumerating available memory,
-	  controlling secondary CPUs, and possibly console output.
-
-config SIBYTE_CFE_CONSOLE
-	bool "Use firmware console"
-	depends on SIBYTE_CFE
-	help
-	  Use the CFE API's console write routines during boot.  Other console
-	  options (VT console, sb1250 duart console, etc.) should not be
-	  configured.
-
-config SIBYTE_STANDALONE
-	bool
-	depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
-	default y
-
-config SIBYTE_STANDALONE_RAM_SIZE
-	int "Memory size (in megabytes)"
-	depends on SIBYTE_STANDALONE
-	default "32"
-
-config SIBYTE_BUS_WATCHER
-	bool "Support for Bus Watcher statistics"
-	depends on SIBYTE_SB1xxx_SOC
-	help
-	  Handle and keep statistics on the bus error interrupts (COR_ECC,
-	  BAD_ECC, IO_BUS).
-
-config SIBYTE_BW_TRACE
-	bool "Capture bus trace before bus error"
-	depends on SIBYTE_BUS_WATCHER
-	help
-	  Run a continuous bus trace, dumping the raw data as soon as
-	  a ZBbus error is detected.  Cannot work if ZBbus profiling
-	  is turned on, and also will interfere with JTAG-based trace
-	  buffer activity.  Raw buffer data is dumped to console, and
-	  must be processed off-line.
-
-config SIBYTE_SB1250_PROF
-	bool "Support for SB1/SOC profiling - SB1/SCD perf counters"
-	depends on SIBYTE_SB1xxx_SOC
-
-config SIBYTE_TBPROF
-	bool "Support for ZBbus profiling"
-	depends on SIBYTE_SB1xxx_SOC
-
-config SNI_RM200_PCI
-	bool "Support for SNI RM200 PCI"
-	select ARC
-	select ARC32
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select GENERIC_ISA_DMA
-	select HAVE_STD_PC_SERIAL_PORT
-	select HW_HAS_PCI
-	select I8259
-	select ISA
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	help
-	  The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
-	  Nixdorf Informationssysteme (SNI), parent company of Pyramid
-	  Technology and now in turn merged with Fujitsu.  Say Y here to
-	  support this machine type.
-
-config TOSHIBA_RBTX4927
-	bool "Support for Toshiba TBTX49[23]7 board"
-	select DMA_NONCOHERENT
-	select HAS_TXX9_SERIAL
-	select HW_HAS_PCI
-	select I8259
-	select ISA
-	select SWAP_IO_SPACE
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	help
-	  This Toshiba board is based on the TX4927 processor. Say Y here to
-	  support this machine type
-
-config TOSHIBA_FPCIB0
-	bool "FPCIB0 Backplane Support"
-	depends on TOSHIBA_RBTX4927
-
-config RWSEM_GENERIC_SPINLOCK
-	bool
-	default y
-
-config RWSEM_XCHGADD_ALGORITHM
-	bool
-
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
-#
-# Select some configuration options automatically based on user selections.
-#
-config ARC
-	bool
-	depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP27 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61
-	default y
-
-config DMA_COHERENT
-	bool
-
-config DMA_IP27
-	bool
-
-config DMA_IP32
-	bool
-	select DMA_NEED_PCI_MAP_STATE
-
-config DMA_NONCOHERENT
-	bool
-	select DMA_NEED_PCI_MAP_STATE
-
-config DMA_NEED_PCI_MAP_STATE
-	bool
-
-config EARLY_PRINTK
-	bool
-	depends on MACH_DECSTATION
-	default y
-
-config GENERIC_ISA_DMA
-	bool
-	depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 || MIPS_MALTA
-	default y
-
-config I8259
-	bool
-	depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MACH_JAZZ || MIPS_MALTA || MIPS_COBALT
-	default y
-
-config LIMITED_DMA
-	bool
-	select HIGHMEM
-
-config MIPS_BONITO64
-	bool
-	depends on MIPS_ATLAS || MIPS_MALTA
-	default y
-
-config MIPS_MSC
-	bool
-	depends on MIPS_ATLAS || MIPS_MALTA
-	default y
-
-config MIPS_NILE4
-	bool
-	depends on LASAT
-	default y
-
-config MIPS_DISABLE_OBSOLETE_IDE
-	bool
-
-config CPU_LITTLE_ENDIAN
-	bool "Generate little endian code"
-	default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
-	default n if MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927
-	help
-	  Some MIPS machines can be configured for either little or big endian
-	  byte order. These modes require different kernels. Say Y if your
-	  machine is little endian, N if it's a big endian machine.
-
-config IRQ_CPU
-	bool
-
-config IRQ_CPU_RM7K
-	bool
-
-config IRQ_MV64340
-	bool
-
-config DDB5XXX_COMMON
-	bool
-	depends on DDB5074 || DDB5476 || DDB5477
-	default y
-
-config MIPS_BOARDS_GEN
-	bool
-	depends on MIPS_ATLAS || MIPS_MALTA || MIPS_SEAD
-	default y
-
-config MIPS_GT64111
-	bool
-	depends on MIPS_COBALT
-	default y
-
-config MIPS_GT64120
-	bool
-	depends on MIPS_EV64120 || MIPS_EV96100 || LASAT || MIPS_ATLAS || MIPS_MALTA || MOMENCO_OCELOT
-	default y
-
-config MIPS_TX3927
-	bool
-	depends on TOSHIBA_JMR3927
-	select HAS_TXX9_SERIAL
-	default y
-
-config PCI_MARVELL
-	bool
-
-config ITE_BOARD_GEN
-	bool
-	depends on MIPS_IVR || MIPS_ITE8172
-	default y
-
-config SWAP_IO_SPACE
-	bool
-
-#
-# Unfortunately not all GT64120 systems run the chip at the same clock.
-# As the user for the clock rate and try to minimize the available options.
-#
-choice
-	prompt "Galileo Chip Clock"
-	#default SYSCLK_83 if MIPS_EV64120
-	depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
-	default SYSCLK_83 if MIPS_EV64120
-	default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G
-
-config SYSCLK_75
-	bool "75" if MIPS_EV64120
-
-config SYSCLK_83
-	bool "83.3" if MIPS_EV64120
-
-config SYSCLK_100
-	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
-
-endchoice
-
-config AU1X00_USB_DEVICE
-	bool
-	depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
-	default n
-
-config MIPS_GT96100
-	bool
-	depends on MIPS_EV96100
-	default y
-	help
-	  Say Y here to support the Galileo Technology GT96100 communications
-	  controller card.  There is a web page at <http://www.galileot.com/>.
-
-config IT8172_CIR
-	bool
-	depends on MIPS_ITE8172 || MIPS_IVR
-	default y
-
-config IT8712
-	bool
-	depends on MIPS_ITE8172
-	default y
-
-config BOOT_ELF32
-	bool
-	depends on MACH_DECSTATION || MIPS_ATLAS || MIPS_MALTA || MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT_3 || SIBYTE_SB1xxx_SOC || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI
-	default y
-
-config MIPS_L1_CACHE_SHIFT
-	int
-	default "4" if MACH_DECSTATION
-	default "7" if SGI_IP27
-	default "5"
-
-config ARC32
-	bool
-	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
-	default y
-
-config HAVE_STD_PC_SERIAL_PORT
-	bool
-
-config ARC_CONSOLE
-	bool "ARC console support"
-	depends on SGI_IP22 || SNI_RM200_PCI
-
-config ARC_MEMORY
-	bool
-	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32
-	default y
-
-config ARC_PROMLIB
-	bool
-	depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
-	default y
-
-config ARC64
-	bool
-	depends on SGI_IP27
-	default y
-
-config BOOT_ELF64
-	bool
-	depends on SGI_IP27
-	default y
-
-#config MAPPED_PCI_IO y
-#	bool
-#	depends on SGI_IP27
-#	default y
-
-config QL_ISP_A64
-	bool
-	depends on SGI_IP27
-	default y
-
-config TOSHIBA_BOARDS
-	bool
-	depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927
-	default y
-
-endmenu
-
-menu "CPU selection"
-
-choice
-	prompt "CPU type"
-	default CPU_R4X00
-
-config CPU_MIPS32
-	bool "MIPS32"
-	select CPU_SUPPORTS_32BIT_KERNEL
-
-config CPU_MIPS64
-	bool "MIPS64"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-
-config CPU_R3000
-	bool "R3000"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	help
-	  Please make sure to pick the right CPU type. Linux/MIPS is not
-	  designed to be generic, i.e. Kernels compiled for R3000 CPUs will
-	  *not* work on R4000 machines and vice versa.  However, since most
-	  of the supported machines have an R4000 (or similar) CPU, R4x00
-	  might be a safe bet.  If the resulting kernel does not work,
-	  try to recompile with R3000.
-
-config CPU_TX39XX
-	bool "R39XX"
-	select CPU_SUPPORTS_32BIT_KERNEL
-
-config CPU_VR41XX
-	bool "R41xx"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  The options selects support for the NEC VR41xx series of processors.
-	  Only choose this option if you have one of these processors as a
-	  kernel built with this option will not run on any other type of
-	  processor or vice versa.
-
-config CPU_R4300
-	bool "R4300"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  MIPS Technologies R4300-series processors.
-
-config CPU_R4X00
-	bool "R4x00"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  MIPS Technologies R4000-series processors other than 4300, including
-	  the R4000, R4400, R4600, and 4700.
-
-config CPU_TX49XX
-	bool "R49XX"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-
-config CPU_R5000
-	bool "R5000"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  MIPS Technologies R5000-series processors other than the Nevada.
-
-config CPU_R5432
-	bool "R5432"
-
-config CPU_R6000
-	bool "R6000"
-	depends on EXPERIMENTAL
-	select CPU_SUPPORTS_32BIT_KERNEL
-	help
-	  MIPS Technologies R6000 and R6000A series processors.  Note these
-	  processors are extremly rare and the support for them is incomplete.
-
-config CPU_NEVADA
-	bool "RM52xx"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  QED / PMC-Sierra RM52xx-series ("Nevada") processors.
-
-config CPU_R8000
-	bool "R8000"
-	depends on EXPERIMENTAL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  MIPS Technologies R8000 processors.  Note these processors are
-	  uncommon and the support for them is incomplete.
-
-config CPU_R10000
-	bool "R10000"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-	help
-	  MIPS Technologies R10000-series processors.
-
-config CPU_RM7000
-	bool "RM7000"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-
-config CPU_RM9000
-	bool "RM9000"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-
-config CPU_SB1
-	bool "SB1"
-	select CPU_SUPPORTS_32BIT_KERNEL
-	select CPU_SUPPORTS_64BIT_KERNEL
-
-endchoice
-
 choice
 	prompt "Kernel page size"
 	default PAGE_SIZE_4KB
@@ -1416,12 +1418,43 @@
 	  SiByte Linux port.  Seems to give a small performance benefit.
 
 config CPU_HAS_PREFETCH
-	bool "Enable prefetches" if CPU_SB1 && !CPU_SB1_PASS_2
-	default y if CPU_MIPS32 || CPU_MIPS64 || CPU_RM7000 || CPU_RM9000 || CPU_R10000
+	bool
 
-config VTAG_ICACHE
-	bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32
-	default y if CPU_SB1
+config MIPS_MT
+	bool "Enable MIPS MT"
+
+choice
+	prompt "MIPS MT options"
+	depends on MIPS_MT
+
+config MIPS_MT_SMP
+	bool "Use 1 TC on each available VPE for SMP"
+	select SMP
+
+config MIPS_VPE_LOADER
+	bool "VPE loader support."
+	depends on MIPS_MT
+	help
+	  Includes a loader for loading an elf relocatable object
+	  onto another VPE and running it.
+
+endchoice
+
+config MIPS_VPE_LOADER_TOM
+	bool "Load VPE program into memory hidden from linux"
+	depends on MIPS_VPE_LOADER
+	default y
+	help
+	  The loader can use memory that is present but has been hidden from
+	  Linux using the kernel command line option "mem=xxMB". It's up to
+	  you to ensure the amount you put in the option and the space your
+	  program requires is less or equal to the amount physically present.
+
+# this should possibly be in drivers/char, but it is rather cpu related. Hmmm
+config MIPS_VPE_APSP_API
+	bool "Enable support for AP/SP API (RTLX)"
+	depends on MIPS_VPE_LOADER
+	help
 
 config SB1_PASS_1_WORKAROUNDS
 	bool
@@ -1440,7 +1473,7 @@
 
 config 64BIT_PHYS_ADDR
 	bool "Support for 64-bit physical address space"
-	depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && 32BIT
+	depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32_R1 || CPU_MIPS64_R1) && 32BIT
 
 config CPU_ADVANCED
 	bool "Override CPU Options"
@@ -1463,7 +1496,7 @@
 
 config CPU_HAS_LLDSCD
 	bool "lld/scd Instructions available" if CPU_ADVANCED
-	default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX && !CPU_MIPS32
+	default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX && !CPU_MIPS32_R1
 	help
 	  Say Y here if your CPU has the lld and scd instructions, the 64-bit
 	  equivalents of ll and sc.  Say Y here for better performance, N if
@@ -1477,12 +1510,52 @@
 	  machines which require flushing of write buffers in software.  Saying
 	  Y is the safe option; N may result in kernel malfunction and crashes.
 
+menu "MIPSR2 Interrupt handling"
+	depends on CPU_MIPSR2 && CPU_ADVANCED
+
+config CPU_MIPSR2_IRQ_VI
+	bool "Vectored interrupt mode"
+	help
+	   Vectored interrupt mode allowing faster dispatching of interrupts.
+	   The board support code needs to be written to take advantage of this
+	   mode.  Compatibility code is included to allow the kernel to run on
+	   a CPU that does not support vectored interrupts.  It's safe to
+	   say Y here.
+
+config CPU_MIPSR2_IRQ_EI
+	bool "External interrupt controller mode"
+	help
+	   Extended interrupt mode takes advantage of an external interrupt
+	   controller to allow fast dispatching from many possible interrupt
+	   sources. Say N unless you know that external interrupt support is
+	   required.
+
+config CPU_MIPSR2_SRS
+	bool "Make shadow set registers available for interrupt handlers"
+	depends on CPU_MIPSR2_IRQ_VI || CPU_MIPSR2_IRQ_EI
+	help
+	   Allow the kernel to use shadow register sets for fast interrupts.
+	   Interrupt handlers must be specially written to use shadow sets.
+	   Say N unless you know that shadow register set upport is needed.
+endmenu
+
 config CPU_HAS_SYNC
 	bool
 	depends on !CPU_R3000
 	default y
 
 #
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_HARDIRQS
+	bool
+	default y
+
+config GENERIC_IRQ_PROBE
+	bool
+	default y
+
+#
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
 #   caches such as R3000, SB1, R7000 or those that look like they're virtually
@@ -1491,14 +1564,19 @@
 #   where it's known to be safe.  This will not offer highmem on a few systems
 #   such as MIPS32 and MIPS64 CPUs which may have virtual and physically
 #   indexed CPUs but we're playing safe.
-# - We should not offer highmem for system of which we already know that they
-#   don't have memory configurations that could gain from highmem support in
-#   the kernel because they don't support configurations with RAM at physical
-#   addresses > 0x20000000.
+# - We use SYS_SUPPORTS_HIGHMEM to offer highmem only for systems where we
+#   know they might have memory configurations that could make use of highmem
+#   support.
 #
 config HIGHMEM
 	bool "High Memory Support"
-	depends on 32BIT && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX)
+	depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM
+
+config CPU_SUPPORTS_HIGHMEM
+	bool
+
+config SYS_SUPPORTS_HIGHMEM
+	bool
 
 config ARCH_FLATMEM_ENABLE
 	def_bool y
@@ -1508,7 +1586,7 @@
 
 config SMP
 	bool "Multi-Processing support"
-	depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27
+	depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP
 	---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
@@ -1543,14 +1621,7 @@
 	  This is purely to save memory - each supported CPU adds
 	  approximately eight kilobytes to the kernel image.
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	help
-	  This option reduces the latency of the kernel when reacting to
-	  real-time or interactive events by allowing a low priority process to
-	  be preempted even if it is in kernel mode executing a system call.
-	  This allows applications to run more reliably even when the system is
-	  under load.
+source "kernel/Kconfig.preempt"
 
 config RTC_DS1742
 	bool "DS1742 BRAM/RTC support"
@@ -1566,14 +1637,16 @@
 	  This will result in additional memory usage, so it is not
 	  recommended for normal users.
 
+endmenu
+
 config RWSEM_GENERIC_SPINLOCK
 	bool
 	default y
 
-endmenu
-
 menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
 
+config HW_HAS_EISA
+	bool
 config HW_HAS_PCI
 	bool
 
@@ -1607,7 +1680,7 @@
 
 config EISA
 	bool "EISA support"
-	depends on SGI_IP22 || SNI_RM200_PCI
+	depends on HW_HAS_EISA
 	select ISA
 	---help---
 	  The Extended Industry Standard Architecture (EISA) bus was
@@ -1641,12 +1714,6 @@
 	bool
 	default y
 
-config MCA
-	bool
-
-config SBUS
-	bool
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
@@ -1659,7 +1726,6 @@
 
 config TRAD_SIGNALS
 	bool
-	default y if 32BIT
 
 config BUILD_ELF64
 	bool "Use 64-bit ELF format for building"
@@ -1678,7 +1744,7 @@
 
 config BINFMT_IRIX
 	bool "Include IRIX binary compatibility"
-	depends on !CPU_LITTLE_ENDIAN && 32BIT && BROKEN
+	depends on CPU_BIG_ENDIAN && 32BIT && BROKEN
 
 config MIPS32_COMPAT
 	bool "Kernel support for Linux/MIPS 32-bit binary compatibility"
@@ -1718,9 +1784,26 @@
 	bool
 	default y if MIPS32_O32 || MIPS32_N32
 
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS && BROKEN
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 config PM
 	bool "Power Management support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && MACH_AU1X00
+	depends on EXPERIMENTAL && SOC_AU1X00
 
 endmenu
 
@@ -1730,6 +1813,8 @@
 
 source "fs/Kconfig"
 
+source "arch/mips/oprofile/Kconfig"
+
 source "arch/mips/Kconfig.debug"
 
 source "security/Kconfig"
@@ -1737,18 +1822,3 @@
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
-	bool
-	default y
-
-config GENERIC_IRQ_PROBE
-	bool
-	default y
-
-config ISA_DMA_API
-	bool
-	default y
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 346e803..0269202 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -52,6 +52,21 @@
 CROSS_COMPILE		:= $(tool-prefix)
 endif
 
+CHECKFLAGS-y				+= -D__linux__ -D__mips__ \
+					   -D_ABIO32=1 \
+					   -D_ABIN32=2 \
+					   -D_ABI64=3
+CHECKFLAGS-$(CONFIG_32BIT)		+= -D_MIPS_SIM=_ABIO32 \
+					   -D_MIPS_SZLONG=32 \
+					   -D__PTRDIFF_TYPE__=int
+CHECKFLAGS-$(CONFIG_64BIT)		+= -m64 -D_MIPS_SIM=_ABI64 \
+					   -D_MIPS_SZLONG=64 \
+					   -D__PTRDIFF_TYPE__="long int"
+CHECKFLAGS-$(CONFIG_CPU_BIG_ENDIAN)	+= -D__MIPSEB__
+CHECKFLAGS-$(CONFIG_CPU_LITTLE_ENDIAN)	+= -D__MIPSEL__
+
+CHECKFLAGS				= $(CHECKFLAGS-y)
+
 ifdef CONFIG_BUILD_ELF64
 gas-abi			= 64
 ld-emul			= $(64bit-emul)
@@ -79,9 +94,18 @@
 cflags-y			+= -I $(TOPDIR)/include/asm/gcc
 cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
 cflags-y			+= $(call cc-option, -finline-limit=100000)
-LDFLAGS_vmlinux			+= -G 0 -static -n
+LDFLAGS_vmlinux			+= -G 0 -static -n -nostdlib
 MODFLAGS			+= -mlong-calls
 
+#
+# We explicitly add the endianness specifier if needed, this allows
+# to compile kernels with a toolchain for the other endianness. We
+# carefully avoid to add it redundantly because gcc 3.3/3.4 complains
+# when fed the toolchain default!
+#
+cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB)
+cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL)
+
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= -mno-sched-prolog -fno-omit-frame-pointer
 
 #
@@ -167,14 +191,22 @@
 			$(call set_gccflags,r4600,mips3,r4600,mips3,mips2)  \
 			-Wa,--trap
 
-cflags-$(CONFIG_CPU_MIPS32)	+= \
+cflags-$(CONFIG_CPU_MIPS32_R1)	+= \
 			$(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \
 			-Wa,--trap
 
-cflags-$(CONFIG_CPU_MIPS64)	+= \
+cflags-$(CONFIG_CPU_MIPS32_R2)	+= \
+			$(call set_gccflags,mips32r2,mips32r2,r4600,mips3,mips2) \
+			-Wa,--trap
+
+cflags-$(CONFIG_CPU_MIPS64_R1)	+= \
 			$(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \
 			-Wa,--trap
 
+cflags-$(CONFIG_CPU_MIPS64_R2)	+= \
+			$(call set_gccflags,mips64r2,mips64r2,r4600,mips3,mips2) \
+			-Wa,--trap
+
 cflags-$(CONFIG_CPU_R5000)	+= \
 			$(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
@@ -196,6 +228,7 @@
 			$(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
 
+
 cflags-$(CONFIG_CPU_SB1)	+= \
 			$(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
 			-Wa,--trap
@@ -266,6 +299,13 @@
 load-$(CONFIG_MIPS_PB1550)	+= 0xffffffff80100000
 
 #
+# AMD Alchemy Pb1200 eval board
+#
+libs-$(CONFIG_MIPS_PB1200)	+= arch/mips/au1000/pb1200/
+cflags-$(CONFIG_MIPS_PB1200)	+= -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1200)	+= 0xffffffff80100000
+
+#
 # AMD Alchemy Db1000 eval board
 #
 libs-$(CONFIG_MIPS_DB1000)	+= arch/mips/au1000/db1x00/
@@ -294,6 +334,13 @@
 load-$(CONFIG_MIPS_DB1550)	+= 0xffffffff80100000
 
 #
+# AMD Alchemy Db1200 eval board
+#
+libs-$(CONFIG_MIPS_DB1200)	+= arch/mips/au1000/pb1200/
+cflags-$(CONFIG_MIPS_DB1200)	+= -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1200)	+= 0xffffffff80100000
+
+#
 # AMD Alchemy Bosporus eval board
 #
 libs-$(CONFIG_MIPS_BOSPORUS)	+= arch/mips/au1000/db1x00/
@@ -323,6 +370,7 @@
 # Cobalt Server
 #
 core-$(CONFIG_MIPS_COBALT)	+= arch/mips/cobalt/
+cflags-$(CONFIG_MIPS_COBALT)	+= -Iinclude/asm-mips/cobalt
 load-$(CONFIG_MIPS_COBALT)	+= 0xffffffff80080000
 
 #
@@ -389,6 +437,13 @@
 load-$(CONFIG_MIPS_SEAD)	+= 0xffffffff80100000
 
 #
+# MIPS SIM
+#
+core-$(CONFIG_MIPS_SIM)		+= arch/mips/mips-boards/sim/
+cflags-$(CONFIG_MIPS_SIM)	+= -Iinclude/asm-mips/mach-sim
+load-$(CONFIG_MIPS_SIM)		+= 0x80100000
+
+#
 # Momentum Ocelot board
 #
 # The Ocelot setup.o must be linked early - it does the ioremap() for the
@@ -514,6 +569,19 @@
 load-$(CONFIG_TANBAC_TB022X)	+= 0xffffffff80000000
 
 #
+# Common Philips PNX8550
+#
+core-$(CONFIG_SOC_PNX8550)	+= arch/mips/philips/pnx8550/common/
+cflags-$(CONFIG_SOC_PNX8550)	+= -Iinclude/asm-mips/mach-pnx8550
+
+#
+# Philips PNX8550 JBS board
+#
+libs-$(CONFIG_PNX8550_JBS)	+= arch/mips/philips/pnx8550/jbs/
+#cflags-$(CONFIG_PNX8550_JBS)	+= -Iinclude/asm-mips/mach-pnx8550
+load-$(CONFIG_PNX8550_JBS)	+= 0xffffffff80060000
+
+#
 # SGI IP22 (Indy/Indigo2)
 #
 # Set the load address to >= 0xffffffff88069000 if you want to leave space for
@@ -582,10 +650,20 @@
 # removed (as happens, even if they have __initcall/module_init)
 #
 core-$(CONFIG_SIBYTE_BCM112X)	+= arch/mips/sibyte/sb1250/
-cflags-$(CONFIG_SIBYTE_BCM112X)	+= -Iinclude/asm-mips/mach-sibyte
+cflags-$(CONFIG_SIBYTE_BCM112X)	+= -Iinclude/asm-mips/mach-sibyte \
+			-DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL
 
 core-$(CONFIG_SIBYTE_SB1250)	+= arch/mips/sibyte/sb1250/
-cflags-$(CONFIG_SIBYTE_SB1250)	+= -Iinclude/asm-mips/mach-sibyte
+cflags-$(CONFIG_SIBYTE_SB1250)	+= -Iinclude/asm-mips/mach-sibyte \
+			-DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL
+
+core-$(CONFIG_SIBYTE_BCM1x55)	+= arch/mips/sibyte/bcm1480/
+cflags-$(CONFIG_SIBYTE_BCM1x55)	+= -Iinclude/asm-mips/mach-sibyte \
+			-DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL
+
+core-$(CONFIG_SIBYTE_BCM1x80)	+= arch/mips/sibyte/bcm1480/
+cflags-$(CONFIG_SIBYTE_BCM1x80)	+= -Iinclude/asm-mips/mach-sibyte \
+			-DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL
 
 #
 # Sibyte BCM91120x (Carmel) board
@@ -593,6 +671,7 @@
 # Sibyte BCM91125C (CRhone) board
 # Sibyte BCM91125E (Rhone) board
 # Sibyte SWARM board
+# Sibyte BCM91x80 (BigSur) board
 #
 libs-$(CONFIG_SIBYTE_CARMEL)	+= arch/mips/sibyte/swarm/
 load-$(CONFIG_SIBYTE_CARMEL)	:= 0xffffffff80100000
@@ -606,6 +685,8 @@
 load-$(CONFIG_SIBYTE_SENTOSA)	:= 0xffffffff80100000
 libs-$(CONFIG_SIBYTE_SWARM)	+= arch/mips/sibyte/swarm/
 load-$(CONFIG_SIBYTE_SWARM)	:= 0xffffffff80100000
+libs-$(CONFIG_SIBYTE_BIGSUR)	+= arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_BIGSUR)	:= 0xffffffff80100000
 
 #
 # SNI RM200 PCI
@@ -629,6 +710,13 @@
 core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/tx4927/common/
 load-$(CONFIG_TOSHIBA_RBTX4927)	+= 0xffffffff80020000
 
+#
+# Toshiba RBTX4938 board
+#
+core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/toshiba_rbtx4938/
+core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
+load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
+
 cflags-y			+= -Iinclude/asm-mips/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/
 
@@ -701,10 +789,29 @@
 all:	$(vmlinux-64)
 endif
 
+ifdef CONFIG_MIPS_ATLAS
+all:	vmlinux.srec
+endif
+
+ifdef CONFIG_MIPS_MALTA
+all:	vmlinux.srec
+endif
+
+ifdef CONFIG_MIPS_SEAD
+all:	vmlinux.srec
+endif
+
+ifdef CONFIG_QEMU
+all:	vmlinux.bin
+endif
+
 ifdef CONFIG_SNI_RM200_PCI
 all:	vmlinux.ecoff
 endif
 
+vmlinux.bin: $(vmlinux-32)
+	+@$(call makeboot,$@)
+
 vmlinux.ecoff vmlinux.rm200: $(vmlinux-32)
 	+@$(call makeboot,$@)
 
@@ -720,7 +827,6 @@
 	@$(MAKE) $(clean)=arch/mips/boot
 	@$(MAKE) $(clean)=arch/mips/lasat
 
-
 CLEAN_FILES += vmlinux.32 \
 	       vmlinux.64 \
 	       vmlinux.ecoff
diff --git a/arch/mips/arc/Makefile b/arch/mips/arc/Makefile
index e842493..4f349ec 100644
--- a/arch/mips/arc/Makefile
+++ b/arch/mips/arc/Makefile
@@ -3,7 +3,7 @@
 #
 
 lib-y				+= cmdline.o env.o file.o identify.o init.o \
-				   misc.o time.o tree.o
+				   misc.o salone.o time.o tree.o
 
 lib-$(CONFIG_ARC_MEMORY)	+= memory.o
 lib-$(CONFIG_ARC_CONSOLE)	+= arc_con.o
diff --git a/arch/mips/arc/identify.c b/arch/mips/arc/identify.c
index 0dd7a34..1bd6199 100644
--- a/arch/mips/arc/identify.c
+++ b/arch/mips/arc/identify.c
@@ -44,6 +44,11 @@
 		MACH_GROUP_SGI,
 		MACH_SGI_IP28,
 		PROM_FLAG_ARCS
+	}, {	"SGI-IP30",
+		"SGI Octane",
+		MACH_GROUP_SGI,
+		MACH_SGI_IP30,
+		PROM_FLAG_ARCS
 	}, {	"SGI-IP32",
 		"SGI O2",
 		MACH_GROUP_SGI,
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
index 594b75e..a1edfd1 100644
--- a/arch/mips/au1000/common/Makefile
+++ b/arch/mips/au1000/common/Makefile
@@ -8,7 +8,7 @@
 
 obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
 	au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
-	sleeper.o cputable.o dma.o dbdma.o
+	sleeper.o cputable.o dma.o dbdma.o gpio.o
 
 obj-$(CONFIG_AU1X00_USB_DEVICE)	+= usbdev.o
 obj-$(CONFIG_KGDB)		+= dbg_io.o
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c
index 8a0f39f..0b2c03c 100644
--- a/arch/mips/au1000/common/au1xxx_irqmap.c
+++ b/arch/mips/au1000/common/au1xxx_irqmap.c
@@ -173,14 +173,14 @@
 	{ AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0},
-	{ AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-	{ AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
 	{ AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0},
 	{ AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
 	{ AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
@@ -201,14 +201,14 @@
 	{ AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0},
-	{ AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-	{ AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-	{ AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+	{ AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+	{ AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
 	{ AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0},
 	{ AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
 	{ AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c
index f5521df..4dbde82 100644
--- a/arch/mips/au1000/common/cputable.c
+++ b/arch/mips/au1000/common/cputable.c
@@ -37,7 +37,8 @@
     { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 },
     { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 },
     { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 },
-    { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 },
+    { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 },
+    { 0xffffffff, 0x04030201, "Au1200 AC", 0, 1 },
     { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 },
 };
 
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
index adfc317..d00e824 100644
--- a/arch/mips/au1000/common/dbdma.c
+++ b/arch/mips/au1000/common/dbdma.c
@@ -29,6 +29,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -38,10 +39,12 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/system.h>
 
+
 #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
 
 /*
@@ -61,37 +64,10 @@
 */
 #define ALIGN_ADDR(x, a)	((((u32)(x)) + (a-1)) & ~(a-1))
 
-static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
-static int dbdma_initialized;
+static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
+static int dbdma_initialized=0;
 static void au1xxx_dbdma_init(void);
 
-typedef struct dbdma_device_table {
-	u32		dev_id;
-	u32		dev_flags;
-	u32		dev_tsize;
-	u32		dev_devwidth;
-	u32		dev_physaddr;		/* If FIFO */
-	u32		dev_intlevel;
-	u32		dev_intpolarity;
-} dbdev_tab_t;
-
-typedef struct dbdma_chan_config {
-	u32			chan_flags;
-	u32			chan_index;
-	dbdev_tab_t		*chan_src;
-	dbdev_tab_t		*chan_dest;
-	au1x_dma_chan_t		*chan_ptr;
-	au1x_ddma_desc_t	*chan_desc_base;
-	au1x_ddma_desc_t	*get_ptr, *put_ptr, *cur_ptr;
-	void			*chan_callparam;
-	void (*chan_callback)(int, void *, struct pt_regs *);
-} chan_tab_t;
-
-#define	DEV_FLAGS_INUSE		(1 << 0)
-#define	DEV_FLAGS_ANYUSE	(1 << 1)
-#define DEV_FLAGS_OUT		(1 << 2)
-#define DEV_FLAGS_IN		(1 << 3)
-
 static dbdev_tab_t dbdev_tab[] = {
 #ifdef CONFIG_SOC_AU1550
 	/* UARTS */
@@ -157,25 +133,25 @@
 	{ DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 	{ DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
+	{ DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 },
+	{ DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
+	{ DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 },
 
-	{ DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
+	{ DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
 
-	{ DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
-	{ DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
+	{ DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 },
+	{ DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x11a0001c, 0, 0 },
 	{ DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
-	{ DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
+	{ DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 },
+	{ DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x11b0001c, 0, 0 },
 	{ DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
-	{ DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
-	{ DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+	{ DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
+	{ DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
+	{ DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
 	{ DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 
 	{ DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
@@ -184,6 +160,24 @@
 
 	{ DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
 	{ DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+	/* Provide 16 user definable device types */
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0 },
 };
 
 #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t))
@@ -203,6 +197,36 @@
 	return NULL;
 }
 
+void * au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp)
+{
+        return phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+}
+EXPORT_SYMBOL(au1xxx_ddma_get_nextptr_virt);
+
+u32
+au1xxx_ddma_add_device(dbdev_tab_t *dev)
+{
+	u32 ret = 0;
+	dbdev_tab_t *p=NULL;
+	static u16 new_id=0x1000;
+
+	p = find_dbdev_id(0);
+	if ( NULL != p )
+	{
+		memcpy(p, dev, sizeof(dbdev_tab_t));
+ 		p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id);
+		ret = p->dev_id;
+		new_id++;
+#if 0
+		printk("add_device: id:%x flags:%x padd:%x\n",
+				p->dev_id, p->dev_flags, p->dev_physaddr );
+#endif
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(au1xxx_ddma_add_device);
+
 /* Allocate a channel and return a non-zero descriptor if successful.
 */
 u32
@@ -215,7 +239,7 @@
 	int		i;
 	dbdev_tab_t	*stp, *dtp;
 	chan_tab_t	*ctp;
-	volatile au1x_dma_chan_t *cp;
+	au1x_dma_chan_t *cp;
 
 	/* We do the intialization on the first channel allocation.
 	 * We have to wait because of the interrupt handler initialization
@@ -225,9 +249,6 @@
 		au1xxx_dbdma_init();
 	dbdma_initialized = 1;
 
-	if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
-		return 0;
-
 	if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
 	if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
 
@@ -271,7 +292,6 @@
 				 */
 				ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
 				chan_tab_ptr[i] = ctp;
-				ctp->chan_index = chan = i;
 				break;
 			}
 		}
@@ -279,10 +299,11 @@
 
 		if (ctp != NULL) {
 			memset(ctp, 0, sizeof(chan_tab_t));
+			ctp->chan_index = chan = i;
 			dcp = DDMA_CHANNEL_BASE;
 			dcp += (0x0100 * chan);
 			ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
-			cp = (volatile au1x_dma_chan_t *)dcp;
+			cp = (au1x_dma_chan_t *)dcp;
 			ctp->chan_src = stp;
 			ctp->chan_dest = dtp;
 			ctp->chan_callback = callback;
@@ -299,6 +320,9 @@
 				i |= DDMA_CFG_DED;
 			if (dtp->dev_intpolarity)
 				i |= DDMA_CFG_DP;
+			if ((stp->dev_flags & DEV_FLAGS_SYNC) ||
+				(dtp->dev_flags & DEV_FLAGS_SYNC))
+					i |= DDMA_CFG_SYNC;
 			cp->ddma_cfg = i;
 			au_sync();
 
@@ -309,14 +333,14 @@
 			rv = (u32)(&chan_tab_ptr[chan]);
 		}
 		else {
-			/* Release devices.
-			*/
+			/* Release devices */
 			stp->dev_flags &= ~DEV_FLAGS_INUSE;
 			dtp->dev_flags &= ~DEV_FLAGS_INUSE;
 		}
 	}
 	return rv;
 }
+EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc);
 
 /* Set the device width if source or destination is a FIFO.
  * Should be 8, 16, or 32 bits.
@@ -344,6 +368,7 @@
 
 	return rv;
 }
+EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth);
 
 /* Allocate a descriptor ring, initializing as much as possible.
 */
@@ -370,7 +395,8 @@
 	 * and if we try that first we are likely to not waste larger
 	 * slabs of memory.
 	 */
-	desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL);
+	desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t),
+			GFP_KERNEL|GFP_DMA);
 	if (desc_base == 0)
 		return 0;
 
@@ -381,7 +407,7 @@
 		kfree((const void *)desc_base);
 		i = entries * sizeof(au1x_ddma_desc_t);
 		i += (sizeof(au1x_ddma_desc_t) - 1);
-		if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0)
+		if ((desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA)) == 0)
 			return 0;
 
 		desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
@@ -403,7 +429,13 @@
 	cmd0 |= DSCR_CMD0_SID(srcid);
 	cmd0 |= DSCR_CMD0_DID(destid);
 	cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV;
-	cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_CURRENT);
+	cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_NOCHANGE);
+
+        /* is it mem to mem transfer? */
+        if(((DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_THROTTLE) || (DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_ALWAYS)) &&
+           ((DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_THROTTLE) || (DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_ALWAYS))) {
+               cmd0 |= DSCR_CMD0_MEM;
+        }
 
 	switch (stp->dev_devwidth) {
 	case 8:
@@ -461,9 +493,14 @@
 	/* If source input is fifo, set static address.
 	*/
 	if (stp->dev_flags & DEV_FLAGS_IN) {
-		src0 = stp->dev_physaddr;
+		if ( stp->dev_flags & DEV_FLAGS_BURSTABLE )
+			src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST);
+		else
 		src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
+
 	}
+	if (stp->dev_physaddr)
+		src0 = stp->dev_physaddr;
 
 	/* Set up dest1.  For now, assume no stride and increment.
 	 * A channel attribute update can change this later.
@@ -487,10 +524,18 @@
 	/* If destination output is fifo, set static address.
 	*/
 	if (dtp->dev_flags & DEV_FLAGS_OUT) {
-		dest0 = dtp->dev_physaddr;
+		if ( dtp->dev_flags & DEV_FLAGS_BURSTABLE )
+	                dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST);
+				else
 		dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC);
 	}
+	if (dtp->dev_physaddr)
+		dest0 = dtp->dev_physaddr;
 
+#if 0
+		printk("did:%x sid:%x cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
+			dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, src1, dest0, dest1 );
+#endif
 	for (i=0; i<entries; i++) {
 		dp->dscr_cmd0 = cmd0;
 		dp->dscr_cmd1 = cmd1;
@@ -499,6 +544,8 @@
 		dp->dscr_dest0 = dest0;
 		dp->dscr_dest1 = dest1;
 		dp->dscr_stat = 0;
+		dp->sw_context = 0;
+		dp->sw_status = 0;
 		dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1));
 		dp++;
 	}
@@ -511,13 +558,14 @@
 
 	return (u32)(ctp->chan_desc_base);
 }
+EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc);
 
 /* Put a source buffer into the DMA ring.
  * This updates the source pointer and byte count.  Normally used
  * for memory to fifo transfers.
  */
 u32
-au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes)
+_au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags)
 {
 	chan_tab_t		*ctp;
 	au1x_ddma_desc_t	*dp;
@@ -544,8 +592,24 @@
 	*/
 	dp->dscr_source0 = virt_to_phys(buf);
 	dp->dscr_cmd1 = nbytes;
-	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
-	ctp->chan_ptr->ddma_dbell = 0xffffffff;	/* Make it go */
+	/* Check flags  */
+	if (flags & DDMA_FLAGS_IE)
+		dp->dscr_cmd0 |= DSCR_CMD0_IE;
+	if (flags & DDMA_FLAGS_NOIE)
+		dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
+
+	/*
+	 * There is an errata on the Au1200/Au1550 parts that could result
+	 * in "stale" data being DMA'd. It has to do with the snoop logic on
+	 * the dache eviction buffer.  NONCOHERENT_IO is on by default for
+	 * these parts. If it is fixedin the future, these dma_cache_inv will
+	 * just be nothing more than empty macros. See io.h.
+	 * */
+	dma_cache_wback_inv((unsigned long)buf, nbytes);
+        dp->dscr_cmd0 |= DSCR_CMD0_V;        /* Let it rip */
+	au_sync();
+	dma_cache_wback_inv((unsigned long)dp, sizeof(dp));
+        ctp->chan_ptr->ddma_dbell = 0;
 
 	/* Get next descriptor pointer.
 	*/
@@ -555,13 +619,14 @@
 	*/
 	return nbytes;
 }
+EXPORT_SYMBOL(_au1xxx_dbdma_put_source);
 
 /* Put a destination buffer into the DMA ring.
  * This updates the destination pointer and byte count.  Normally used
  * to place an empty buffer into the ring for fifo to memory transfers.
  */
 u32
-au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes)
+_au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags)
 {
 	chan_tab_t		*ctp;
 	au1x_ddma_desc_t	*dp;
@@ -583,11 +648,33 @@
 	if (dp->dscr_cmd0 & DSCR_CMD0_V)
 		return 0;
 
-	/* Load up buffer address and byte count.
-	*/
+	/* Load up buffer address and byte count */
+
+	/* Check flags  */
+	if (flags & DDMA_FLAGS_IE)
+		dp->dscr_cmd0 |= DSCR_CMD0_IE;
+	if (flags & DDMA_FLAGS_NOIE)
+		dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
+
 	dp->dscr_dest0 = virt_to_phys(buf);
 	dp->dscr_cmd1 = nbytes;
+#if 0
+	printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
+			dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0,
+			dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 );
+#endif
+	/*
+	 * There is an errata on the Au1200/Au1550 parts that could result in
+	 * "stale" data being DMA'd. It has to do with the snoop logic on the
+	 * dache eviction buffer. NONCOHERENT_IO is on by default for these
+	 * parts. If it is fixedin the future, these dma_cache_inv will just
+	 * be nothing more than empty macros. See io.h.
+	 * */
+	dma_cache_inv((unsigned long)buf,nbytes);
 	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
+	au_sync();
+	dma_cache_wback_inv((unsigned long)dp, sizeof(dp));
+        ctp->chan_ptr->ddma_dbell = 0;
 
 	/* Get next descriptor pointer.
 	*/
@@ -597,6 +684,7 @@
 	*/
 	return nbytes;
 }
+EXPORT_SYMBOL(_au1xxx_dbdma_put_dest);
 
 /* Get a destination buffer into the DMA ring.
  * Normally used to get a full buffer from the ring during fifo
@@ -646,7 +734,7 @@
 au1xxx_dbdma_stop(u32 chanid)
 {
 	chan_tab_t	*ctp;
-	volatile au1x_dma_chan_t *cp;
+	au1x_dma_chan_t *cp;
 	int halt_timeout = 0;
 
 	ctp = *((chan_tab_t **)chanid);
@@ -666,6 +754,7 @@
 	cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
 	au_sync();
 }
+EXPORT_SYMBOL(au1xxx_dbdma_stop);
 
 /* Start using the current descriptor pointer.  If the dbdma encounters
  * a not valid descriptor, it will stop.  In this case, we can just
@@ -675,17 +764,17 @@
 au1xxx_dbdma_start(u32 chanid)
 {
 	chan_tab_t	*ctp;
-	volatile au1x_dma_chan_t *cp;
+	au1x_dma_chan_t *cp;
 
 	ctp = *((chan_tab_t **)chanid);
-
 	cp = ctp->chan_ptr;
 	cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
 	cp->ddma_cfg |= DDMA_CFG_EN;	/* Enable channel */
 	au_sync();
-	cp->ddma_dbell = 0xffffffff;	/* Make it go */
+	cp->ddma_dbell = 0;
 	au_sync();
 }
+EXPORT_SYMBOL(au1xxx_dbdma_start);
 
 void
 au1xxx_dbdma_reset(u32 chanid)
@@ -704,15 +793,21 @@
 
 	do {
 		dp->dscr_cmd0 &= ~DSCR_CMD0_V;
+		/* reset our SW status -- this is used to determine
+		 * if a descriptor is in use by upper level SW. Since
+		 * posting can reset 'V' bit.
+		 */
+		dp->sw_status = 0;
 		dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
 	} while (dp != ctp->chan_desc_base);
 }
+EXPORT_SYMBOL(au1xxx_dbdma_reset);
 
 u32
 au1xxx_get_dma_residue(u32 chanid)
 {
 	chan_tab_t	*ctp;
-	volatile au1x_dma_chan_t *cp;
+	au1x_dma_chan_t *cp;
 	u32		rv;
 
 	ctp = *((chan_tab_t **)chanid);
@@ -738,8 +833,7 @@
 
 	au1xxx_dbdma_stop(chanid);
 
-	if (ctp->chan_desc_base != NULL)
-		kfree(ctp->chan_desc_base);
+	kfree((void *)ctp->chan_desc_base);
 
 	stp->dev_flags &= ~DEV_FLAGS_INUSE;
 	dtp->dev_flags &= ~DEV_FLAGS_INUSE;
@@ -747,15 +841,16 @@
 
 	kfree(ctp);
 }
+EXPORT_SYMBOL(au1xxx_dbdma_chan_free);
 
 static irqreturn_t
 dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	u32	intstat;
-	u32	chan_index;
+	u32 intstat;
+	u32 chan_index;
 	chan_tab_t		*ctp;
 	au1x_ddma_desc_t	*dp;
-	volatile au1x_dma_chan_t *cp;
+	au1x_dma_chan_t *cp;
 
 	intstat = dbdma_gptr->ddma_intstat;
 	au_sync();
@@ -774,19 +869,27 @@
 		(ctp->chan_callback)(irq, ctp->chan_callparam, regs);
 
 	ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
-
-	return IRQ_HANDLED;
+	return IRQ_RETVAL(1);
 }
 
-static void
-au1xxx_dbdma_init(void)
+static void au1xxx_dbdma_init(void)
 {
+	int irq_nr;
+
 	dbdma_gptr->ddma_config = 0;
 	dbdma_gptr->ddma_throttle = 0;
 	dbdma_gptr->ddma_inten = 0xffff;
 	au_sync();
 
-	if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT,
+#if defined(CONFIG_SOC_AU1550)
+	irq_nr = AU1550_DDMA_INT;
+#elif defined(CONFIG_SOC_AU1200)
+	irq_nr = AU1200_DDMA_INT;
+#else
+	#error Unknown Au1x00 SOC
+#endif
+
+	if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT,
 			"Au1xxx dbdma", (void *)dbdma_gptr))
 		printk("Can't get 1550 dbdma irq");
 }
@@ -797,7 +900,8 @@
 	chan_tab_t		*ctp;
 	au1x_ddma_desc_t	*dp;
 	dbdev_tab_t		*stp, *dtp;
-	volatile au1x_dma_chan_t *cp;
+	au1x_dma_chan_t *cp;
+		u32			i = 0;
 
 	ctp = *((chan_tab_t **)chanid);
 	stp = ctp->chan_src;
@@ -822,15 +926,64 @@
 	dp = ctp->chan_desc_base;
 
 	do {
-		printk("dp %08x, cmd0 %08x, cmd1 %08x\n",
-			(u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
-		printk("src0 %08x, src1 %08x, dest0 %08x\n",
-			dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0);
-		printk("dest1 %08x, stat %08x, nxtptr %08x\n",
-			dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr);
+                printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n",
+                        i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
+                printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n",
+                        dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
+                printk("stat %08x, nxtptr %08x\n",
+                        dp->dscr_stat, dp->dscr_nxtptr);
 		dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
 	} while (dp != ctp->chan_desc_base);
 }
 
+/* Put a descriptor into the DMA ring.
+ * This updates the source/destination pointers and byte count.
+ */
+u32
+au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr )
+{
+	chan_tab_t *ctp;
+	au1x_ddma_desc_t *dp;
+	u32 nbytes=0;
+
+	/* I guess we could check this to be within the
+	* range of the table......
+	*/
+	ctp = *((chan_tab_t **)chanid);
+
+	/* We should have multiple callers for a particular channel,
+	* an interrupt doesn't affect this pointer nor the descriptor,
+	* so no locking should be needed.
+	*/
+	dp = ctp->put_ptr;
+
+	/* If the descriptor is valid, we are way ahead of the DMA
+	* engine, so just return an error condition.
+	*/
+	if (dp->dscr_cmd0 & DSCR_CMD0_V)
+		return 0;
+
+	/* Load up buffer addresses and byte count.
+	*/
+	dp->dscr_dest0 = dscr->dscr_dest0;
+	dp->dscr_source0 = dscr->dscr_source0;
+	dp->dscr_dest1 = dscr->dscr_dest1;
+	dp->dscr_source1 = dscr->dscr_source1;
+	dp->dscr_cmd1 = dscr->dscr_cmd1;
+	nbytes = dscr->dscr_cmd1;
+	/* Allow the caller to specifiy if an interrupt is generated */
+	dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
+	dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V;
+	ctp->chan_ptr->ddma_dbell = 0;
+
+	/* Get next descriptor pointer.
+	*/
+	ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+
+	/* return something not zero.
+	*/
+	return nbytes;
+}
+
 #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
 
diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c
index 372c33f..1905c6b 100644
--- a/arch/mips/au1000/common/dma.c
+++ b/arch/mips/au1000/common/dma.c
@@ -39,7 +39,6 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1000_dma.h>
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
new file mode 100644
index 0000000..5f5915b
--- /dev/null
+++ b/arch/mips/au1000/common/gpio.c
@@ -0,0 +1,119 @@
+/*
+ *  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  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <au1000.h>
+#include <au1xxx_gpio.h>
+
+#define gpio1 sys
+#if !defined(CONFIG_SOC_AU1000)
+static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
+
+#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
+
+int au1xxx_gpio2_read(int signal)
+{
+	signal -= 200;
+/*	gpio2->dir &= ~(0x01 << signal);						//Set GPIO to input */
+	return ((gpio2->pinstate >> signal) & 0x01);
+}
+
+void au1xxx_gpio2_write(int signal, int value)
+{
+	signal -= 200;
+
+	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
+		(value << signal);
+}
+
+void au1xxx_gpio2_tristate(int signal)
+{
+	signal -= 200;
+	gpio2->dir &= ~(0x01 << signal); 	/* Set GPIO to input */
+}
+#endif
+
+int au1xxx_gpio1_read(int signal)
+{
+/*	gpio1->trioutclr |= (0x01 << signal); */
+	return ((gpio1->pinstaterd >> signal) & 0x01);
+}
+
+void au1xxx_gpio1_write(int signal, int value)
+{
+	if(value)
+		gpio1->outputset = (0x01 << signal);
+	else
+		gpio1->outputclr = (0x01 << signal);	/* Output a Zero */
+}
+
+void au1xxx_gpio1_tristate(int signal)
+{
+	gpio1->trioutclr = (0x01 << signal);		/* Tristate signal */
+}
+
+
+int au1xxx_gpio_read(int signal)
+{
+	if(signal >= 200)
+#if defined(CONFIG_SOC_AU1000)
+		return 0;
+#else
+		return au1xxx_gpio2_read(signal);
+#endif
+	else
+		return au1xxx_gpio1_read(signal);
+}
+
+void au1xxx_gpio_write(int signal, int value)
+{
+	if(signal >= 200)
+#if defined(CONFIG_SOC_AU1000)
+		;
+#else
+		au1xxx_gpio2_write(signal, value);
+#endif
+	else
+		au1xxx_gpio1_write(signal, value);
+}
+
+void au1xxx_gpio_tristate(int signal)
+{
+	if(signal >= 200)
+#if defined(CONFIG_SOC_AU1000)
+		;
+#else
+		au1xxx_gpio2_tristate(signal);
+#endif
+	else
+		au1xxx_gpio1_tristate(signal);
+}
+
+void au1xxx_gpio1_set_inputs(void)
+{
+	gpio1->pininputen = 0;
+}
+
+EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
+EXPORT_SYMBOL(au1xxx_gpio_tristate);
+EXPORT_SYMBOL(au1xxx_gpio_write);
+EXPORT_SYMBOL(au1xxx_gpio_read);
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index d1eb5a4..1339a09 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -83,7 +83,7 @@
 void	(*board_init_irq)(void);
 
 #ifdef CONFIG_PM
-extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 
 static DEFINE_SPINLOCK(irq_lock);
@@ -253,52 +253,72 @@
 
 
 static struct hw_interrupt_type rise_edge_irq_type = {
-	"Au1000 Rise Edge",
-	startup_irq,
-	shutdown_irq,
-	local_enable_irq,
-	local_disable_irq,
-	mask_and_ack_rise_edge_irq,
-	end_irq,
-	NULL
+	.typename = "Au1000 Rise Edge",
+	.startup = startup_irq,
+	.shutdown = shutdown_irq,
+	.enable = local_enable_irq,
+	.disable = local_disable_irq,
+	.ack = mask_and_ack_rise_edge_irq,
+	.end = end_irq,
 };
 
 static struct hw_interrupt_type fall_edge_irq_type = {
-	"Au1000 Fall Edge",
-	startup_irq,
-	shutdown_irq,
-	local_enable_irq,
-	local_disable_irq,
-	mask_and_ack_fall_edge_irq,
-	end_irq,
-	NULL
+	.typename = "Au1000 Fall Edge",
+	.startup = startup_irq,
+	.shutdown = shutdown_irq,
+	.enable = local_enable_irq,
+	.disable = local_disable_irq,
+	.ack = mask_and_ack_fall_edge_irq,
+	.end = end_irq,
 };
 
 static struct hw_interrupt_type either_edge_irq_type = {
-	"Au1000 Rise or Fall Edge",
-	startup_irq,
-	shutdown_irq,
-	local_enable_irq,
-	local_disable_irq,
-	mask_and_ack_either_edge_irq,
-	end_irq,
-	NULL
+	.typename = "Au1000 Rise or Fall Edge",
+	.startup = startup_irq,
+	.shutdown = shutdown_irq,
+	.enable = local_enable_irq,
+	.disable = local_disable_irq,
+	.ack = mask_and_ack_either_edge_irq,
+	.end = end_irq,
 };
 
 static struct hw_interrupt_type level_irq_type = {
-	"Au1000 Level",
-	startup_irq,
-	shutdown_irq,
-	local_enable_irq,
-	local_disable_irq,
-	mask_and_ack_level_irq,
-	end_irq,
-	NULL
+	.typename = "Au1000 Level",
+	.startup = startup_irq,
+	.shutdown = shutdown_irq,
+	.enable = local_enable_irq,
+	.disable = local_disable_irq,
+	.ack = mask_and_ack_level_irq,
+	.end = end_irq,
 };
 
 #ifdef CONFIG_PM
-void startup_match20_interrupt(void)
+void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 {
+	struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT];
+
+	static struct irqaction action;
+	memset(&action, 0, sizeof(struct irqaction));
+
+	/* This is a big problem.... since we didn't use request_irq
+	 * when kernel/irq.c calls probe_irq_xxx this interrupt will
+	 * be probed for usage. This will end up disabling the device :(
+	 * Give it a bogus "action" pointer -- this will keep it from
+	 * getting auto-probed!
+	 *
+	 * By setting the status to match that of request_irq() we
+	 * can avoid it.  --cgray
+	*/
+	action.dev_id = handler;
+	action.flags = SA_INTERRUPT;
+	cpus_clear(action.mask);
+	action.name = "Au1xxx TOY";
+	action.handler = handler;
+	action.next = NULL;
+
+	desc->action = &action;
+	desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+
 	local_enable_irq(AU1000_TOY_MATCH2_INT);
 }
 #endif
@@ -426,7 +446,6 @@
 	extern int au1xxx_ic0_nr_irqs;
 
 	cp0_status = read_c0_status();
-	memset(irq_desc, 0, sizeof(irq_desc));
 	set_except_vector(0, au1000_IRQ);
 
 	/* Initialize interrupt controllers to a safe state.
@@ -492,7 +511,7 @@
 	intc0_req0 |= au_readl(IC0_REQ0INT);
 
 	if (!intc0_req0) return;
-
+#ifdef AU1000_USB_DEV_REQ_INT
 	/*
 	 * Because of the tight timing of SETUP token to reply
 	 * transactions, the USB devices-side packet complete
@@ -503,7 +522,7 @@
 		do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
 		return;
 	}
-
+#endif
 	irq = au_ffs(intc0_req0) - 1;
 	intc0_req0 &= ~(1<<irq);
 	do_IRQ(irq, regs);
@@ -521,17 +540,7 @@
 
 	irq = au_ffs(intc0_req1) - 1;
 	intc0_req1 &= ~(1<<irq);
-#ifdef CONFIG_PM
-	if (irq == AU1000_TOY_MATCH2_INT) {
-		mask_and_ack_rise_edge_irq(irq);
-		counter0_irq(irq, NULL, regs);
-		local_enable_irq(irq);
-	}
-	else
-#endif
-	{
-		do_IRQ(irq, regs);
-	}
+	do_IRQ(irq, regs);
 }
 
 
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 0776b2d..1f7b465 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -7,13 +7,15 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
+#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/resource.h>
 
-#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx.h>
 
+/* OHCI (USB full speed host controller) */
 static struct resource au1xxx_usb_ohci_resources[] = {
 	[0] = {
 		.start		= USB_OHCI_BASE,
@@ -41,8 +43,252 @@
 	.resource	= au1xxx_usb_ohci_resources,
 };
 
+/*** AU1100 LCD controller ***/
+
+#ifdef CONFIG_FB_AU1100
+static struct resource au1100_lcd_resources[] = {
+	[0] = {
+		.start          = LCD_PHYS_ADDR,
+		.end            = LCD_PHYS_ADDR + 0x800 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start          = AU1100_LCD_INT,
+		.end            = AU1100_LCD_INT,
+		.flags          = IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1100_lcd_dmamask = ~(u32)0;
+
+static struct platform_device au1100_lcd_device = {
+	.name           = "au1100-lcd",
+	.id             = 0,
+	.dev = {
+		.dma_mask               = &au1100_lcd_dmamask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(au1100_lcd_resources),
+	.resource       = au1100_lcd_resources,
+};
+#endif
+
+#ifdef CONFIG_SOC_AU1200
+/* EHCI (USB high speed host controller) */
+static struct resource au1xxx_usb_ehci_resources[] = {
+	[0] = {
+		.start		= USB_EHCI_BASE,
+		.end		= USB_EHCI_BASE + USB_EHCI_LEN - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= AU1000_USB_HOST_INT,
+		.end		= AU1000_USB_HOST_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static u64 ehci_dmamask = ~(u32)0;
+
+static struct platform_device au1xxx_usb_ehci_device = {
+	.name		= "au1xxx-ehci",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &ehci_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(au1xxx_usb_ehci_resources),
+	.resource	= au1xxx_usb_ehci_resources,
+};
+
+/* Au1200 UDC (USB gadget controller) */
+static struct resource au1xxx_usb_gdt_resources[] = {
+	[0] = {
+		.start		= USB_UDC_BASE,
+		.end		= USB_UDC_BASE + USB_UDC_LEN - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= AU1200_USB_INT,
+		.end		= AU1200_USB_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource au1xxx_mmc_resources[] = {
+	[0] = {
+		.start          = SD0_PHYS_ADDR,
+		.end            = SD0_PHYS_ADDR + 0x40,
+		.flags          = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= SD1_PHYS_ADDR,
+		.end 		= SD1_PHYS_ADDR + 0x40,
+		.flags		= IORESOURCE_MEM,
+	},
+	[2] = {
+		.start          = AU1200_SD_INT,
+		.end            = AU1200_SD_INT,
+		.flags          = IORESOURCE_IRQ,
+	}
+};
+
+static u64 udc_dmamask = ~(u32)0;
+
+static struct platform_device au1xxx_usb_gdt_device = {
+	.name		= "au1xxx-udc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &udc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(au1xxx_usb_gdt_resources),
+	.resource	= au1xxx_usb_gdt_resources,
+};
+
+/* Au1200 UOC (USB OTG controller) */
+static struct resource au1xxx_usb_otg_resources[] = {
+	[0] = {
+		.start		= USB_UOC_BASE,
+		.end		= USB_UOC_BASE + USB_UOC_LEN - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= AU1200_USB_INT,
+		.end		= AU1200_USB_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static u64 uoc_dmamask = ~(u32)0;
+
+static struct platform_device au1xxx_usb_otg_device = {
+	.name		= "au1xxx-uoc",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &uoc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(au1xxx_usb_otg_resources),
+	.resource	= au1xxx_usb_otg_resources,
+};
+
+static struct resource au1200_lcd_resources[] = {
+	[0] = {
+		.start          = LCD_PHYS_ADDR,
+		.end            = LCD_PHYS_ADDR + 0x800 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start          = AU1200_LCD_INT,
+		.end            = AU1200_LCD_INT,
+		.flags          = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource au1200_ide0_resources[] = {
+	[0] = {
+		.start		= AU1XXX_ATA_PHYS_ADDR,
+		.end 		= AU1XXX_ATA_PHYS_ADDR + AU1XXX_ATA_PHYS_LEN,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= AU1XXX_ATA_INT,
+		.end		= AU1XXX_ATA_INT,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static u64 au1200_lcd_dmamask = ~(u32)0;
+
+static struct platform_device au1200_lcd_device = {
+	.name           = "au1200-lcd",
+	.id             = 0,
+	.dev = {
+		.dma_mask               = &au1200_lcd_dmamask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(au1200_lcd_resources),
+	.resource       = au1200_lcd_resources,
+};
+
+
+static u64 ide0_dmamask = ~(u32)0;
+
+static struct platform_device au1200_ide0_device = {
+	.name		= "au1200-ide",
+	.id		= 0,
+	.dev = {
+		.dma_mask 		= &ide0_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources = ARRAY_SIZE(au1200_ide0_resources),
+	.resource	= au1200_ide0_resources,
+};
+
+static u64 au1xxx_mmc_dmamask =  ~(u32)0;
+
+static struct platform_device au1xxx_mmc_device = {
+	.name = "au1xxx-mmc",
+	.id = 0,
+	.dev = {
+		.dma_mask               = &au1xxx_mmc_dmamask,
+		.coherent_dma_mask      = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(au1xxx_mmc_resources),
+	.resource       = au1xxx_mmc_resources,
+};
+#endif /* #ifdef CONFIG_SOC_AU1200 */
+
+static struct platform_device au1x00_pcmcia_device = {
+	.name 		= "au1x00-pcmcia",
+	.id 		= 0,
+};
+
+#ifdef CONFIG_MIPS_DB1200
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.name	= "smc91x-regs",
+		.start	= AU1XXX_SMC91111_PHYS_ADDR,
+		.end	= AU1XXX_SMC91111_PHYS_ADDR + 0xfffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AU1XXX_SMC91111_IRQ,
+		.end	= AU1XXX_SMC91111_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+ 	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+#endif
+
 static struct platform_device *au1xxx_platform_devices[] __initdata = {
 	&au1xxx_usb_ohci_device,
+	&au1x00_pcmcia_device,
+#ifdef CONFIG_FB_AU1100
+	&au1100_lcd_device,
+#endif
+#ifdef CONFIG_SOC_AU1200
+#if 0	/* fixme */
+	&au1xxx_usb_ehci_device,
+#endif
+	&au1xxx_usb_gdt_device,
+	&au1xxx_usb_otg_device,
+	&au1200_lcd_device,
+	&au1200_ide0_device,
+	&au1xxx_mmc_device,
+#endif
+#ifdef CONFIG_MIPS_DB1200
+ 	&smc91x_device,
+#endif
 };
 
 int au1xxx_platform_init(void)
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
index c40dacc..f85093b 100644
--- a/arch/mips/au1000/common/power.c
+++ b/arch/mips/au1000/common/power.c
@@ -34,11 +34,13 @@
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/jiffies.h>
 
 #include <asm/string.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/cacheflush.h>
 #include <asm/mach-au1x00/au1000.h>
 
 #ifdef CONFIG_PM
@@ -50,7 +52,7 @@
 #  define DPRINTK(fmt, args...)
 #endif
 
-static void calibrate_delay(void);
+static void au1000_calibrate_delay(void);
 
 extern void set_au1x00_speed(unsigned int new_freq);
 extern unsigned int get_au1x00_speed(void);
@@ -260,7 +262,7 @@
 }
 
 static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
-		       void *buffer, size_t * len)
+		       void __user *buffer, size_t * len, loff_t *ppos)
 {
 	int retval = 0;
 #ifdef SLEEP_TEST_TIMEOUT
@@ -294,10 +296,9 @@
 }
 
 static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
-			 void *buffer, size_t * len)
+			 void __user *buffer, size_t * len, loff_t *ppos)
 {
 	int retval = 0;
-	void	au1k_wait(void);
 
 	if (!write) {
 		*len = 0;
@@ -306,7 +307,7 @@
 		if (retval)
 			return retval;
 		suspend_mode = 1;
-		au1k_wait();
+
 		retval = pm_send_all(PM_RESUME, (void *) 0);
 	}
 	return retval;
@@ -314,7 +315,7 @@
 
 
 static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
-		      void *buffer, size_t * len)
+		      void __user *buffer, size_t * len, loff_t *ppos)
 {
 	int retval = 0, i;
 	unsigned long val, pll;
@@ -409,14 +410,14 @@
 
 
 	/* We don't want _any_ interrupts other than
-	 * match20. Otherwise our calibrate_delay()
+	 * match20. Otherwise our au1000_calibrate_delay()
 	 * calculation will be off, potentially a lot.
 	 */
 	intc0_mask = save_local_and_disable(0);
 	intc1_mask = save_local_and_disable(1);
 	local_enable_irq(AU1000_TOY_MATCH2_INT);
 	spin_unlock_irqrestore(&pm_lock, flags);
-	calibrate_delay();
+	au1000_calibrate_delay();
 	restore_local_and_enable(0, intc0_mask);
 	restore_local_and_enable(1, intc1_mask);
 	return retval;
@@ -456,7 +457,7 @@
    better than 1% */
 #define LPS_PREC 8
 
-static void calibrate_delay(void)
+static void au1000_calibrate_delay(void)
 {
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
index 22e5a85..9c171af 100644
--- a/arch/mips/au1000/common/prom.c
+++ b/arch/mips/au1000/common/prom.c
@@ -75,7 +75,8 @@
 	}
 	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
 		--cp;
-	*cp = '\0';
+	if (prom_argc > 1)
+		*cp = '\0';
 
 }
 
diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c
index c2ae462..2705829 100644
--- a/arch/mips/au1000/common/puts.c
+++ b/arch/mips/au1000/common/puts.c
@@ -39,7 +39,6 @@
 #define TIMEOUT       0xffffff
 #define SLOW_DOWN
 
-static const char digits[16] = "0123456789abcdef";
 static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE;
 
 
@@ -54,7 +53,7 @@
 #endif
 
 void
-putch(const unsigned char c)
+prom_putchar(const unsigned char c)
 {
     unsigned char ch;
     int i = 0;
@@ -69,77 +68,3 @@
     } while (0 == (ch & TX_BUSY));
     com1[SER_DATA] = c;
 }
-
-void
-puts(unsigned char *cp)
-{
-    unsigned char ch;
-    int i = 0;
-
-    while (*cp) {
-        do {
-             ch = com1[SER_CMD];
-            slow_down();
-            i++;
-            if (i>TIMEOUT) {
-                break;
-            }
-        } while (0 == (ch & TX_BUSY));
-        com1[SER_DATA] = *cp++;
-    }
-    putch('\r');
-    putch('\n');
-}
-
-void
-fputs(const char *cp)
-{
-    unsigned char ch;
-    int i = 0;
-
-    while (*cp) {
-
-        do {
-             ch = com1[SER_CMD];
-             slow_down();
-            i++;
-            if (i>TIMEOUT) {
-                break;
-            }
-        } while (0 == (ch & TX_BUSY));
-        com1[SER_DATA] = *cp++;
-    }
-}
-
-
-void
-put64(uint64_t ul)
-{
-    int cnt;
-    unsigned ch;
-
-    cnt = 16;            /* 16 nibbles in a 64 bit long */
-    putch('0');
-    putch('x');
-    do {
-        cnt--;
-        ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
-                putch(digits[ch]);
-    } while (cnt > 0);
-}
-
-void
-put32(unsigned u)
-{
-    int cnt;
-    unsigned ch;
-
-    cnt = 8;            /* 8 nibbles in a 32 bit long */
-    putch('0');
-    putch('x');
-    do {
-        cnt--;
-        ch = (unsigned char)(u >> cnt * 4) & 0x0F;
-                putch(digits[ch]);
-    } while (cnt > 0);
-}
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index eff89e1..1ef15d5 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -32,6 +32,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -57,7 +58,7 @@
 extern void au1xxx_timer_setup(struct irqaction *irq);
 extern void set_cpuspec(void);
 
-static int __init au1x00_setup(void)
+void __init plat_setup(void)
 {
 	struct	cpu_spec *sp;
 	char *argptr;
@@ -106,8 +107,6 @@
         /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
 #ifdef CONFIG_MIPS_HYDROGEN3
          strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
-#else
-        strcat(argptr, " video=au1100fb:panel:s10,nohwcursor");
 #endif
     }
 #endif
@@ -153,15 +152,11 @@
 	au_sync();
 	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
 	au_writel(0, SYS_TOYTRIM);
-
-	return 0;
 }
 
-early_initcall(au1x00_setup);
-
 #if defined(CONFIG_64BIT_PHYS_ADDR)
 /* This routine should be valid for all Au1x based boards */
-phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
 {
 	u32 start, end;
 
@@ -192,4 +187,5 @@
 	/* default nop */
 	return phys_addr;
 }
+EXPORT_SYMBOL(__fixup_bigphys_addr);
 #endif
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index 57675b4..883d3f3 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -50,7 +50,6 @@
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 
-extern void startup_match20_interrupt(void);
 extern void do_softirq(void);
 extern volatile unsigned long wall_jiffies;
 unsigned long missed_heart_beats = 0;
@@ -58,14 +57,17 @@
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
 int	no_au1xxx_32khz;
-void	(*au1k_wait_ptr)(void);
+extern int allow_au1k_wait; /* default off for CP0 Counter */
 
 /* Cycle counter value at the previous timer interrupt.. */
 static unsigned int timerhi = 0, timerlo = 0;
 
 #ifdef CONFIG_PM
-#define MATCH20_INC 328
-extern void startup_match20_interrupt(void);
+#if HZ < 100 || HZ > 1000
+#error "unsupported HZ value! Must be in [100,1000]"
+#endif
+#define MATCH20_INC (328*100/HZ) /* magic number 328 is for HZ=100... */
+extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 static unsigned long last_pc0, last_match20;
 #endif
 
@@ -117,17 +119,16 @@
 }
 
 #ifdef CONFIG_PM
-void counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long pc0;
 	int time_elapsed;
 	static int jiffie_drift = 0;
 
-	kstat.irqs[0][irq]++;
 	if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
 		/* should never happen! */
-		printk(KERN_WARNING "counter 0 w status eror\n");
-		return;
+		printk(KERN_WARNING "counter 0 w status error\n");
+		return IRQ_NONE;
 	}
 
 	pc0 = au_readl(SYS_TOYREAD);
@@ -164,6 +165,8 @@
 		update_process_times(user_mode(regs));
 #endif
 	}
+
+	return IRQ_HANDLED;
 }
 
 /* When we wakeup from sleep, we have to "catch up" on all of the
@@ -388,7 +391,6 @@
 {
         unsigned int est_freq;
 	extern unsigned long (*do_gettimeoffset)(void);
-	extern void au1k_wait(void);
 
 	printk("calculating r4koff... ");
 	r4k_offset = cal_r4koff();
@@ -441,18 +443,18 @@
 		au_sync();
 		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
 
-		/* setup match20 to interrupt once every 10ms */
+		/* setup match20 to interrupt once every HZ */
 		last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
 		au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
 		au_sync();
 		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
-		startup_match20_interrupt();
+		startup_match20_interrupt(counter0_irq);
 
 		do_gettimeoffset = do_fast_pm_gettimeoffset;
 
 		/* We can use the real 'wait' instruction.
 		*/
-		au1k_wait_ptr = au1k_wait;
+		allow_au1k_wait = 1;
 	}
 
 #else
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c
index 447a9a4..0b21bed 100644
--- a/arch/mips/au1000/common/usbdev.c
+++ b/arch/mips/au1000/common/usbdev.c
@@ -1005,11 +1005,11 @@
 #endif
 		dev->ep0_stage = SETUP_STAGE;
 		break;
-		}
+	}
 
 	spin_unlock(&ep0->lock);
-		// we're done processing the packet, free it
-		kfree(pkt);
+	// we're done processing the packet, free it
+	kfree(pkt);
 }
 
 
@@ -1072,8 +1072,7 @@
 			clear_dma_done1(ep0->indma);
 
 		pkt = send_packet_complete(ep0);
-		if (pkt)
-			kfree(pkt);
+		kfree(pkt);
 	}
 
 	/*
@@ -1302,8 +1301,7 @@
 		endpoint_flush(ep);
 	}
 
-	if (usbdev.full_conf_desc)
-		kfree(usbdev.full_conf_desc);
+	kfree(usbdev.full_conf_desc);
 }
 
 int
diff --git a/arch/mips/au1000/csb250/init.c b/arch/mips/au1000/csb250/init.c
index bd99733..a4898b1 100644
--- a/arch/mips/au1000/csb250/init.c
+++ b/arch/mips/au1000/csb250/init.c
@@ -35,7 +35,6 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
index 8f6ef0d..f63024a 100644
--- a/arch/mips/au1000/db1x00/irqmap.c
+++ b/arch/mips/au1000/db1x00/irqmap.c
@@ -48,6 +48,38 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
+#ifdef CONFIG_MIPS_DB1500
+char irq_tab_alchemy[][5] __initdata = {
+ [12] =	{ -1, INTA, INTX, INTX, INTX},   /* IDSEL 12 - HPT371   */
+ [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
+};
+#endif
+
+#ifdef CONFIG_MIPS_BOSPORUS
+char irq_tab_alchemy[][5] __initdata = {
+ [11] =	{ -1, INTA, INTB, INTX, INTX},   /* IDSEL 11 - miniPCI  */
+ [12] =	{ -1, INTA, INTX, INTX, INTX},   /* IDSEL 12 - SN1741   */
+ [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
+};
+#endif
+
+#ifdef CONFIG_MIPS_MIRAGE
+char irq_tab_alchemy[][5] __initdata = {
+ [11] =	{ -1, INTD, INTX, INTX, INTX},   /* IDSEL 11 - SMI VGX */
+ [12] =	{ -1, INTX, INTX, INTC, INTX},   /* IDSEL 12 - PNX1300 */
+ [13] =	{ -1, INTA, INTB, INTX, INTX},   /* IDSEL 13 - miniPCI */
+};
+#endif
+
+#ifdef CONFIG_MIPS_DB1550
+char irq_tab_alchemy[][5] __initdata = {
+ [11] =	{ -1, INTC, INTX, INTX, INTX},   /* IDSEL 11 - on-board HPT371    */
+ [12] =	{ -1, INTB, INTC, INTD, INTA},   /* IDSEL 12 - PCI slot 2 (left)  */
+ [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot 1 (right) */
+};
+#endif
+
+
 au1xxx_irq_map_t au1xxx_irq_map[] = {
 
 #ifndef CONFIG_MIPS_MIRAGE
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
index ade35e4..c29852c 100644
--- a/arch/mips/au1000/db1x00/mirage_ts.c
+++ b/arch/mips/au1000/db1x00/mirage_ts.c
@@ -102,15 +102,15 @@
 } mirage_ts_cal =
 {
 #if 0
-	xscale:   84,
-	xtrans: -157,
-	yscale:   66,
-	ytrans: -150,
+	.xscale   = 84,
+	.xtrans = -157,
+	.yscale   = 66,
+	.ytrans = -150,
 #else
-	xscale:   84,
-	xtrans: -150,
-	yscale:   66,
-	ytrans: -146,
+	.xscale   = 84,
+	.xtrans = -150,
+	.yscale   = 66,
+	.ytrans = -146,
 #endif
 };
 
diff --git a/arch/mips/au1000/hydrogen3/init.c b/arch/mips/au1000/hydrogen3/init.c
index 8cc9879..01ab284 100644
--- a/arch/mips/au1000/hydrogen3/init.c
+++ b/arch/mips/au1000/hydrogen3/init.c
@@ -37,7 +37,6 @@
 #include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c
index 02e7dbc..88f2b6d 100644
--- a/arch/mips/au1000/mtx-1/init.c
+++ b/arch/mips/au1000/mtx-1/init.c
@@ -33,7 +33,6 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/sched.h>
 #include <linux/bootmem.h>
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c
index ddcb9d0..f9a0a8b 100644
--- a/arch/mips/au1000/mtx-1/irqmap.c
+++ b/arch/mips/au1000/mtx-1/irqmap.c
@@ -47,6 +47,17 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
+char irq_tab_alchemy[][5] __initdata = {
+ [0] = { -1, INTA, INTB, INTX, INTX},   /* IDSEL 00 - AdapterA-Slot0 (top)    */
+ [1] = { -1, INTB, INTA, INTX, INTX},   /* IDSEL 01 - AdapterA-Slot1 (bottom) */
+ [2] = { -1, INTC, INTD, INTX, INTX},   /* IDSEL 02 - AdapterB-Slot0 (top)    */
+ [3] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 03 - AdapterB-Slot1 (bottom) */
+ [4] = { -1, INTA, INTB, INTX, INTX},   /* IDSEL 04 - AdapterC-Slot0 (top)    */
+ [5] = { -1, INTB, INTA, INTX, INTX},   /* IDSEL 05 - AdapterC-Slot1 (bottom) */
+ [6] = { -1, INTC, INTD, INTX, INTX},   /* IDSEL 06 - AdapterD-Slot0 (top)    */
+ [7] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 07 - AdapterD-Slot1 (bottom) */
+};
+
 au1xxx_irq_map_t au1xxx_irq_map[] = {
        { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
        { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c
index 34713c5..e9fa1ba 100644
--- a/arch/mips/au1000/pb1000/init.c
+++ b/arch/mips/au1000/pb1000/init.c
@@ -65,5 +65,4 @@
 		memsize = simple_strtol(memsize_str, NULL, 0);
 	}
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
-	return 0;
 }
diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/au1000/pb1200/Makefile
new file mode 100644
index 0000000..22b673c
--- /dev/null
+++ b/arch/mips/au1000/pb1200/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Alchemy Semiconductor PB1200 board.
+#
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
new file mode 100644
index 0000000..a45b175
--- /dev/null
+++ b/arch/mips/au1000/pb1200/board_setup.c
@@ -0,0 +1,193 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Alchemy Pb1200/Db1200 board setup.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
+#include <linux/ide.h>
+#endif
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#ifdef CONFIG_MIPS_PB1200
+#include <asm/mach-pb1x00/pb1200.h>
+#endif
+
+#ifdef CONFIG_MIPS_DB1200
+#include <asm/mach-db1x00/db1200.h>
+#define PB1200_ETH_INT DB1200_ETH_INT
+#define PB1200_IDE_INT DB1200_IDE_INT
+#endif
+
+extern void _board_init_irq(void);
+extern void	(*board_init_irq)(void);
+
+void board_reset (void)
+{
+	bcsr->resets = 0;
+	bcsr->system = 0;
+}
+
+void __init board_setup(void)
+{
+	char *argptr = NULL;
+	u32 pin_func;
+
+#if 0
+	/* Enable PSC1 SYNC for AC97.  Normaly done in audio driver,
+	 * but it is board specific code, so put it here.
+	 */
+	pin_func = au_readl(SYS_PINFUNC);
+	au_sync();
+	pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
+	au_writel(pin_func, SYS_PINFUNC);
+
+	au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
+	au_sync();
+#endif
+
+#if defined(CONFIG_I2C_AU1550)
+	{
+	u32 freq0, clksrc;
+
+	/* Select SMBUS in CPLD */
+	bcsr->resets &= ~(BCSR_RESETS_PCS0MUX);
+
+	pin_func = au_readl(SYS_PINFUNC);
+	au_sync();
+	pin_func &= ~(3<<17 | 1<<4);
+	/* Set GPIOs correctly */
+	pin_func |= 2<<17;
+	au_writel(pin_func, SYS_PINFUNC);
+	au_sync();
+
+	/* The i2c driver depends on 50Mhz clock */
+	freq0 = au_readl(SYS_FREQCTRL0);
+	au_sync();
+	freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1);
+	freq0 |= (3<<SYS_FC_FRDIV1_BIT);
+	/* 396Mhz / (3+1)*2 == 49.5Mhz */
+	au_writel(freq0, SYS_FREQCTRL0);
+	au_sync();
+	freq0 |= SYS_FC_FE1;
+	au_writel(freq0, SYS_FREQCTRL0);
+	au_sync();
+
+	clksrc = au_readl(SYS_CLKSRC);
+	au_sync();
+	clksrc &= ~0x01f00000;
+	/* bit 22 is EXTCLK0 for PSC0 */
+	clksrc |= (0x3 << 22);
+	au_writel(clksrc, SYS_CLKSRC);
+	au_sync();
+	}
+#endif
+
+#ifdef CONFIG_FB_AU1200
+	argptr = prom_getcmdline();
+#ifdef CONFIG_MIPS_PB1200
+	strcat(argptr, " video=au1200fb:panel:bs");
+#endif
+#ifdef CONFIG_MIPS_DB1200
+	strcat(argptr, " video=au1200fb:panel:bs");
+#endif
+#endif
+
+	/* The Pb1200 development board uses external MUX for PSC0 to
+	support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
+	*/
+#if defined(CONFIG_AU1XXX_PSC_SPI) && defined(CONFIG_I2C_AU1550)
+	#error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
+			Refer to Pb1200/Db1200 documentation.
+#elif defined( CONFIG_AU1XXX_PSC_SPI )
+	bcsr->resets |= BCSR_RESETS_PCS0MUX;
+	/*Hard Coding Value to enable Temp Sensors [bit 14] Value for SOC Au1200. Pls refer documentation*/
+	  bcsr->resets =0x900f;
+#elif defined( CONFIG_I2C_AU1550 )
+	bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
+#endif
+	au_sync();
+
+#ifdef CONFIG_MIPS_PB1200
+	printk("AMD Alchemy Pb1200 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1200
+	printk("AMD Alchemy Db1200 Board\n");
+#endif
+
+	/* Setup Pb1200 External Interrupt Controller */
+	{
+		extern void (*board_init_irq)(void);
+		extern void _board_init_irq(void);
+		board_init_irq = _board_init_irq;
+	}
+}
+
+int
+board_au1200fb_panel (void)
+{
+	BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+	int p;
+
+	p = bcsr->switches;
+	p >>= 8;
+	p &= 0x0F;
+	return p;
+}
+
+int
+board_au1200fb_panel_init (void)
+{
+	/* Apply power */
+    BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+	bcsr->board |= (BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL);
+	/*printk("board_au1200fb_panel_init()\n"); */
+	return 0;
+}
+
+int
+board_au1200fb_panel_shutdown (void)
+{
+	/* Remove power */
+    BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+	bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL);
+	/*printk("board_au1200fb_panel_shutdown()\n"); */
+	return 0;
+}
+
diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/au1000/pb1200/init.c
new file mode 100644
index 0000000..27f09e3
--- /dev/null
+++ b/arch/mips/au1000/pb1200/init.c
@@ -0,0 +1,69 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	PB1200 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+	return "Alchemy Pb1200";
+}
+
+void __init prom_init(void)
+{
+	unsigned char *memsize_str;
+	unsigned long memsize;
+
+	prom_argc = (int) fw_arg0;
+	prom_argv = (char **) fw_arg1;
+	prom_envp = (char **) fw_arg2;
+
+	mips_machgroup = MACH_GROUP_ALCHEMY;
+	mips_machtype = MACH_PB1200;
+
+	prom_init_cmdline();
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		memsize = 0x08000000;
+	} else {
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
new file mode 100644
index 0000000..59e70e5
--- /dev/null
+++ b/arch/mips/au1000/pb1200/irqmap.c
@@ -0,0 +1,182 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *	Au1xxx irq map table
+ *
+ *  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  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#ifdef CONFIG_MIPS_PB1200
+#include <asm/mach-pb1x00/pb1200.h>
+#endif
+
+#ifdef CONFIG_MIPS_DB1200
+#include <asm/mach-db1x00/db1200.h>
+#define PB1200_INT_BEGIN DB1200_INT_BEGIN
+#define PB1200_INT_END DB1200_INT_END
+#endif
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+	{ AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+
+/*
+ *	Support for External interrupts on the PbAu1200 Development platform.
+ */
+static volatile int pb1200_cascade_en=0;
+
+irqreturn_t pb1200_cascade_handler( int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned short bisr = bcsr->int_status;
+	int extirq_nr = 0;
+
+	/* Clear all the edge interrupts. This has no effect on level */
+	bcsr->int_status = bisr;
+	for( ; bisr; bisr &= (bisr-1) )
+	{
+		extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr);
+		/* Ack and dispatch IRQ */
+		do_IRQ(extirq_nr,regs);
+	}
+	return IRQ_RETVAL(1);
+}
+
+inline void pb1200_enable_irq(unsigned int irq_nr)
+{
+	bcsr->intset_mask = 1<<(irq_nr - PB1200_INT_BEGIN);
+	bcsr->intset = 1<<(irq_nr - PB1200_INT_BEGIN);
+}
+
+inline void pb1200_disable_irq(unsigned int irq_nr)
+{
+	bcsr->intclr_mask = 1<<(irq_nr - PB1200_INT_BEGIN);
+	bcsr->intclr = 1<<(irq_nr - PB1200_INT_BEGIN);
+}
+
+static unsigned int pb1200_startup_irq( unsigned int irq_nr )
+{
+	if (++pb1200_cascade_en == 1)
+	{
+		request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
+			0, "Pb1200 Cascade", (void *)&pb1200_cascade_handler );
+#ifdef CONFIG_MIPS_PB1200
+    /* We have a problem with CPLD rev3. Enable a workaround */
+	if( ((bcsr->whoami & BCSR_WHOAMI_CPLD)>>4) <= 3)
+	{
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
+		printk("updated to latest revision. This software will not\n");
+		printk("work on anything less than CPLD rev4\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		printk("\nWARNING!!!\n");
+		while(1);
+	}
+#endif
+	}
+	pb1200_enable_irq(irq_nr);
+	return 0;
+}
+
+static void pb1200_shutdown_irq( unsigned int irq_nr )
+{
+	pb1200_disable_irq(irq_nr);
+	if (--pb1200_cascade_en == 0)
+	{
+		free_irq(AU1000_GPIO_7,&pb1200_cascade_handler );
+	}
+	return;
+}
+
+static inline void pb1200_mask_and_ack_irq(unsigned int irq_nr)
+{
+	pb1200_disable_irq( irq_nr );
+}
+
+static void pb1200_end_irq(unsigned int irq_nr)
+{
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+		pb1200_enable_irq(irq_nr);
+	}
+}
+
+static struct hw_interrupt_type external_irq_type =
+{
+#ifdef CONFIG_MIPS_PB1200
+	"Pb1200 Ext",
+#endif
+#ifdef CONFIG_MIPS_DB1200
+	"Db1200 Ext",
+#endif
+	pb1200_startup_irq,
+	pb1200_shutdown_irq,
+	pb1200_enable_irq,
+	pb1200_disable_irq,
+	pb1200_mask_and_ack_irq,
+	pb1200_end_irq,
+	NULL
+};
+
+void _board_init_irq(void)
+{
+	int irq_nr;
+
+	for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
+	{
+		irq_desc[irq_nr].handler = &external_irq_type;
+		pb1200_disable_irq(irq_nr);
+	}
+
+	/* GPIO_7 can not be hooked here, so it is hooked upon first
+	request of any source attached to the cascade */
+}
+
diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c
index 476e250..8cb76c2 100644
--- a/arch/mips/au1000/pb1500/irqmap.c
+++ b/arch/mips/au1000/pb1500/irqmap.c
@@ -47,6 +47,11 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
+char irq_tab_alchemy[][5] __initdata = {
+ [12] = { -1, INTA, INTX, INTX, INTX},   /* IDSEL 12 - HPT370   */
+ [13] = { -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
+};
+
 au1xxx_irq_map_t au1xxx_irq_map[] = {
 	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c
index 889d494..47c7a1c 100644
--- a/arch/mips/au1000/pb1550/irqmap.c
+++ b/arch/mips/au1000/pb1550/irqmap.c
@@ -47,6 +47,11 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
+char irq_tab_alchemy[][5] __initdata = {
+ [12] =	{ -1, INTB, INTC, INTD, INTA},   /* IDSEL 12 - PCI slot 2 (left)  */
+ [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot 1 (right) */
+};
+
 au1xxx_irq_map_t au1xxx_irq_map[] = {
 	{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
 	{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
index efbeac3..0dc8441 100644
--- a/arch/mips/boot/Makefile
+++ b/arch/mips/boot/Makefile
@@ -33,6 +33,9 @@
 $(obj)/elf2ecoff: $(obj)/elf2ecoff.c
 	$(HOSTCC) -o $@ $^
 
+vmlinux.bin: $(VMLINUX)
+	$(OBJCOPY) -O binary $(strip-flags) $(VMLINUX) $(obj)/vmlinux.bin
+
 vmlinux.srec: $(VMLINUX)
 	$(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec
 
@@ -45,5 +48,6 @@
 
 clean-files += addinitrd \
 	       elf2ecoff \
+	       vmlinux.bin \
 	       vmlinux.ecoff \
 	       vmlinux.srec
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index a5e6554..3b6b757 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o int-handler.o reset.o setup.o promcon.o
+obj-y	 := irq.o int-handler.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
index 1a21dec..f92608e 100644
--- a/arch/mips/cobalt/int-handler.S
+++ b/arch/mips/cobalt/int-handler.S
@@ -18,8 +18,8 @@
 		SAVE_ALL
 		CLI
 
-		la	ra, ret_from_irq
-		move	a1, sp
+		PTR_LA	ra, ret_from_irq
+		move	a0, sp
 		j	cobalt_irq
 
 		END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index 6d2a815..0d90851 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -10,6 +10,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
 
 #include <asm/i8259.h>
 #include <asm/irq_cpu.h>
@@ -25,8 +27,8 @@
  * the CPU interrupt lines, and ones that come in on the via chip. The CPU
  * mappings are:
  *
- *    16,  - Software interrupt 0 (unused)	IE_SW0
- *    17   - Software interrupt 1 (unused)	IE_SW0
+ *    16   - Software interrupt 0 (unused)	IE_SW0
+ *    17   - Software interrupt 1 (unused)	IE_SW1
  *    18   - Galileo chip (timer)		IE_IRQ0
  *    19   - Tulip 0 + NCR SCSI			IE_IRQ1
  *    20   - Tulip 1				IE_IRQ2
@@ -42,61 +44,94 @@
  *    15  - IDE1
  */
 
-asmlinkage void cobalt_irq(struct pt_regs *regs)
+static inline void galileo_irq(struct pt_regs *regs)
 {
-	unsigned int pending = read_c0_status() & read_c0_cause();
+	unsigned int mask, pending, devfn;
 
-	if (pending & CAUSEF_IP2) {			/* int 18 */
-		unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
+	mask = GALILEO_INL(GT_INTRMASK_OFS);
+	pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask;
 
-		/* Check for timer irq ... */
-		if (irq_src & GALILEO_T0EXP) {
-			/* Clear the int line */
-			GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
-			do_IRQ(COBALT_TIMER_IRQ, regs);
-		}
-		return;
-	}
+	if (pending & GALILEO_INTR_T0EXP) {
 
-	if (pending & CAUSEF_IP6) {			/* int 22 */
-		int irq = i8259_irq();
+		GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS);
+		do_IRQ(COBALT_GALILEO_IRQ, regs);
 
-		if (irq >= 0)
-			do_IRQ(irq, regs);
-		return;
-	}
+	} else if (pending & GALILEO_INTR_RETRY_CTR) {
 
-	if (pending & CAUSEF_IP3) {			/* int 19 */
-		do_IRQ(COBALT_ETH0_IRQ, regs);
-		return;
-	}
+		devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8;
+		GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS);
+		printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n",
+			PCI_SLOT(devfn), PCI_FUNC(devfn));
 
-	if (pending & CAUSEF_IP4) {			/* int 20 */
-		do_IRQ(COBALT_ETH1_IRQ, regs);
-		return;
-	}
+	} else {
 
-	if (pending & CAUSEF_IP5) {			/* int 21 */
-		do_IRQ(COBALT_SERIAL_IRQ, regs);
-		return;
-	}
-
-	if (pending & CAUSEF_IP7) {			/* int 23 */
-		do_IRQ(COBALT_QUBE_SLOT_IRQ, regs);
-		return;
+		GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS);
+		printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending);
 	}
 }
 
+static inline void via_pic_irq(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = i8259_irq();
+	if (irq >= 0)
+		do_IRQ(irq, regs);
+}
+
+asmlinkage void cobalt_irq(struct pt_regs *regs)
+{
+	unsigned pending;
+
+	pending = read_c0_status() & read_c0_cause();
+
+	if (pending & CAUSEF_IP2)			/* COBALT_GALILEO_IRQ (18) */
+
+		galileo_irq(regs);
+
+	else if (pending & CAUSEF_IP6)			/* COBALT_VIA_IRQ (22) */
+
+		via_pic_irq(regs);
+
+	else if (pending & CAUSEF_IP3)			/* COBALT_ETH0_IRQ (19) */
+
+		do_IRQ(COBALT_CPU_IRQ + 3, regs);
+
+	else if (pending & CAUSEF_IP4)			/* COBALT_ETH1_IRQ (20) */
+
+		do_IRQ(COBALT_CPU_IRQ + 4, regs);
+
+	else if (pending & CAUSEF_IP5)			/* COBALT_SERIAL_IRQ (21) */
+
+		do_IRQ(COBALT_CPU_IRQ + 5, regs);
+
+	else if (pending & CAUSEF_IP7)			/* IRQ 23 */
+
+		do_IRQ(COBALT_CPU_IRQ + 7, regs);
+}
+
+static struct irqaction irq_via = {
+	no_action, 0, { { 0, } }, "cascade", NULL, NULL
+};
+
 void __init arch_init_irq(void)
 {
+	/*
+	 * Mask all Galileo interrupts. The Galileo
+	 * handler is set in cobalt_timer_setup()
+	 */
+	GALILEO_OUTL(0, GT_INTRMASK_OFS);
+
 	set_except_vector(0, cobalt_handle_int);
 
 	init_i8259_irqs();				/*  0 ... 15 */
-	mips_cpu_irq_init(16);				/* 16 ... 23 */
+	mips_cpu_irq_init(COBALT_CPU_IRQ);		/* 16 ... 23 */
 
 	/*
 	 * Mask all cpu interrupts
 	 *  (except IE4, we already masked those at VIA level)
 	 */
 	change_c0_status(ST0_IM, IE_IRQ4);
+
+	setup_irq(COBALT_VIA_IRQ, &irq_via);
 }
diff --git a/arch/mips/cobalt/promcon.c b/arch/mips/cobalt/promcon.c
deleted file mode 100644
index f03df76..0000000
--- a/arch/mips/cobalt/promcon.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * PROM console for Cobalt Raq2
- *
- * 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) 1995, 1996, 1997 by Ralf Baechle
- * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
- *
- */
-
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kdev_t.h>
-#include <linux/serial_reg.h>
-
-#include <asm/delay.h>
-#include <asm/serial.h>
-#include <asm/io.h>
-
-static unsigned long port = 0xc800000;
-
-static __inline__ void ns16550_cons_put_char(char ch, unsigned long ioaddr)
-{
-	char lsr;
-
-	do {
-		lsr = inb(ioaddr + UART_LSR);
-	} while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
-	outb(ch, ioaddr + UART_TX);
-}
-
-static __inline__ char ns16550_cons_get_char(unsigned long ioaddr)
-{
-	while ((inb(ioaddr + UART_LSR) & UART_LSR_DR) == 0)
-		udelay(1);
-	return inb(ioaddr + UART_RX);
-}
-
-void ns16550_console_write(struct console *co, const char *s, unsigned count)
-{
-	char lsr, ier;
-	unsigned i;
-
-	ier = inb(port + UART_IER);
-	outb(0x00, port + UART_IER);
-	for (i=0; i < count; i++, s++) {
-
-		if(*s == '\n')
-			ns16550_cons_put_char('\r', port);
-		ns16550_cons_put_char(*s, port);
-	}
-
-	do {
-		lsr = inb(port + UART_LSR);
-   	} while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
-
-	outb(ier, port + UART_IER);
-}
-
-char getDebugChar(void)
-{
-	return ns16550_cons_get_char(port);
-}
-
-void putDebugChar(char kgdb_char)
-{
-	ns16550_cons_put_char(kgdb_char, port);
-}
-
-static struct console ns16550_console = {
-    .name	= "prom",
-    .setup	= NULL,
-    .write	= ns16550_console_write,
-    .flags	= CON_PRINTBUFFER,
-    .index	= -1,
-};
-
-static int __init ns16550_setup_console(void)
-{
-	register_console(&ns16550_console);
-
-	return 0;
-}
-
-console_initcall(ns16550_setup_console);
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c
index 084c8e5..805a0e8 100644
--- a/arch/mips/cobalt/reset.c
+++ b/arch/mips/cobalt/reset.c
@@ -16,48 +16,45 @@
 #include <asm/reboot.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
-
-void cobalt_machine_restart(char *command)
-{
-	*(volatile char *)0xbc000000 = 0x0f;
-
-	/*
-	 * Ouch, we're still alive ... This time we take the silver bullet ...
-	 * ... and find that we leave the hardware in a state in which the
-	 * kernel in the flush locks up somewhen during of after the PCI
-	 * detection stuff.
-	 */
-	set_c0_status(ST0_BEV | ST0_ERL);
-	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
-	write_c0_wired(0);
-	__asm__ __volatile__(
-		"jr\t%0"
-		:
-		: "r" (0xbfc00000));
-}
-
-extern int led_state;
-#define kLED            0xBC000000
-#define LEDSet(x)       (*(volatile unsigned char *) kLED) = (( unsigned char)x)
+#include <asm/cobalt/cobalt.h>
 
 void cobalt_machine_halt(void)
 {
-	int mark;
+	int state, last, diff;
+	unsigned long mark;
 
-	/* Blink our cute? little LED (number 3)... */
-	while (1) {
-		led_state = led_state | ( 1 << 3 );
-		LEDSet(led_state);
-		mark = jiffies;
-		while (jiffies<(mark+HZ));
-		led_state = led_state & ~( 1 << 3 );
-		LEDSet(led_state);
-		mark = jiffies;
-		while (jiffies<(mark+HZ));
+	/*
+	 * turn off bar on Qube, flash power off LED on RaQ (0.5Hz)
+	 *
+	 * restart if ENTER and SELECT are pressed
+	 */
+
+	last = COBALT_KEY_PORT;
+
+	for (state = 0;;) {
+
+		state ^= COBALT_LED_POWER_OFF;
+		COBALT_LED_PORT = state;
+
+		diff = COBALT_KEY_PORT ^ last;
+		last ^= diff;
+
+		if((diff & (COBALT_KEY_ENTER | COBALT_KEY_SELECT)) && !(~last & (COBALT_KEY_ENTER | COBALT_KEY_SELECT)))
+			COBALT_LED_PORT = COBALT_LED_RESET;
+
+		for (mark = jiffies; jiffies - mark < HZ;)
+			;
 	}
 }
 
+void cobalt_machine_restart(char *command)
+{
+	COBALT_LED_PORT = COBALT_LED_RESET;
+
+	/* we should never get here */
+	cobalt_machine_halt();
+}
+
 /*
  * This triggers the luser mode device driver for the power switch ;-)
  */
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index 6b4737e..d358a11 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -13,6 +13,8 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
 
 #include <asm/bootinfo.h>
 #include <asm/time.h>
@@ -21,6 +23,7 @@
 #include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/gt64120.h>
+#include <asm/serial.h>
 
 #include <asm/cobalt/cobalt.h>
 
@@ -30,45 +33,44 @@
 
 int cobalt_board_id;
 
-static char my_cmdline[CL_SIZE] = {
- "console=ttyS0,115200 "
-#ifdef CONFIG_IP_PNP
- "ip=on "
-#endif
-#ifdef CONFIG_ROOT_NFS
- "root=/dev/nfs "
-#else
- "root=/dev/hda1 "
-#endif
- };
-
 const char *get_system_type(void)
 {
+	switch (cobalt_board_id) {
+		case COBALT_BRD_ID_QUBE1:
+			return "Cobalt Qube";
+		case COBALT_BRD_ID_RAQ1:
+			return "Cobalt RaQ";
+		case COBALT_BRD_ID_QUBE2:
+			return "Cobalt Qube2";
+		case COBALT_BRD_ID_RAQ2:
+			return "Cobalt RaQ2";
+	}
 	return "MIPS Cobalt";
 }
 
 static void __init cobalt_timer_setup(struct irqaction *irq)
 {
-	/* Load timer value for 150 Hz */
-	GALILEO_OUTL(500000, GT_TC0_OFS);
+	/* Load timer value for 1KHz (TCLK is 50MHz) */
+	GALILEO_OUTL(50*1000*1000 / 1000, GT_TC0_OFS);
 
-	/* Register our timer interrupt */
-	setup_irq(COBALT_TIMER_IRQ, irq);
+	/* Enable timer */
+	GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS);
 
-	/* Enable timer ints */
-	GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS);
-	/* Unmask timer int */
-	GALILEO_OUTL(0x100, GT_INTRMASK_OFS);
+	/* Register interrupt */
+	setup_irq(COBALT_GALILEO_IRQ, irq);
+
+	/* Enable interrupt */
+	GALILEO_OUTL(GALILEO_INTR_T0EXP | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS);
 }
 
 extern struct pci_ops gt64111_pci_ops;
 
 static struct resource cobalt_mem_resource = {
-	"GT64111 PCI MEM", GT64111_IO_BASE, 0xffffffffUL, IORESOURCE_MEM
+	"PCI memory", GT64111_MEM_BASE, GT64111_MEM_END, IORESOURCE_MEM
 };
 
 static struct resource cobalt_io_resource = {
-	"GT64111 IO MEM", 0x00001000UL, 0x0fffffffUL, IORESOURCE_IO
+	"PCI I/O", 0x1000, 0xffff, IORESOURCE_IO
 };
 
 static struct resource cobalt_io_resources[] = {
@@ -86,11 +88,12 @@
 	.mem_resource	= &cobalt_mem_resource,
 	.mem_offset	= 0,
 	.io_resource	= &cobalt_io_resource,
-	.io_offset	= 0x00001000UL - GT64111_IO_BASE
+	.io_offset	= 0 - GT64111_IO_BASE
 };
 
-static void __init cobalt_setup(void)
+void __init plat_setup(void)
 {
+	static struct uart_port uart;
 	unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
 	int i;
 
@@ -100,7 +103,10 @@
 
 	board_timer_setup = cobalt_timer_setup;
 
-        set_io_port_base(KSEG1ADDR(GT64111_IO_BASE));
+        set_io_port_base(CKSEG1ADDR(GT64111_IO_BASE));
+
+	/* I/O port resource must include UART and LCD/buttons */
+	ioport_resource.end = 0x0fffffff;
 
 	/*
 	 * This is a prom style console. We just poke at the
@@ -120,27 +126,61 @@
         cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
         cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
 
+	printk("Cobalt board ID: %d\n", cobalt_board_id);
+
 #ifdef CONFIG_PCI
 	register_pci_controller(&cobalt_pci_controller);
 #endif
-}
 
-early_initcall(cobalt_setup);
+#ifdef CONFIG_SERIAL_8250
+	if (cobalt_board_id > COBALT_BRD_ID_RAQ1) {
+
+		uart.line	= 0;
+		uart.type	= PORT_UNKNOWN;
+		uart.uartclk	= 18432000;
+		uart.irq	= COBALT_SERIAL_IRQ;
+		uart.flags	= STD_COM_FLAGS;
+		uart.iobase	= 0xc800000;
+		uart.iotype	= UPIO_PORT;
+
+		early_serial_setup(&uart);
+	}
+#endif
+}
 
 /*
  * Prom init. We read our one and only communication with the firmware.
- * Grab the amount of installed memory
+ * Grab the amount of installed memory.
+ * Better boot loaders (CoLo) pass a command line too :-)
  */
 
 void __init prom_init(void)
 {
-	int argc = fw_arg0;
-
-	strcpy(arcs_cmdline, my_cmdline);
+	int narg, indx, posn, nchr;
+	unsigned long memsz;
+	char **argv;
 
 	mips_machgroup = MACH_GROUP_COBALT;
 
-	add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM);
+	memsz = fw_arg0 & 0x7fff0000;
+	narg = fw_arg0 & 0x0000ffff;
+
+	if (narg) {
+		arcs_cmdline[0] = '\0';
+		argv = (char **) fw_arg1;
+		posn = 0;
+		for (indx = 1; indx < narg; ++indx) {
+			nchr = strlen(argv[indx]);
+			if (posn + 1 + nchr + 1 > sizeof(arcs_cmdline))
+				break;
+			if (posn)
+				arcs_cmdline[posn++] = ' ';
+			strcpy(arcs_cmdline + posn, argv[indx]);
+			posn += nchr;
+		}
+	}
+
+	add_memory_region(0x0, memsz, BOOT_MEM_RAM);
 }
 
 unsigned long __init prom_free_prom_memory(void)
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 3120a02..132ec3d 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:00 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:13 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,42 +59,72 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 CONFIG_MIPS_ATLAS=y
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_BONITO64=y
 CONFIG_MIPS_MSC=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
 CONFIG_MIPS_BOARDS_GEN=y
 CONFIG_MIPS_GT64120=y
 CONFIG_SWAP_IO_SPACE=y
@@ -101,8 +134,10 @@
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -118,15 +153,46 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -135,7 +201,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -144,10 +209,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -160,6 +221,305 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+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
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+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_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_DCCP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+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_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=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+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
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+CONFIG_NET_CLS_IND=y
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -171,6 +531,11 @@
 CONFIG_FW_LOADER=y
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -187,7 +552,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -201,7 +565,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -247,6 +610,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -259,6 +623,7 @@
 CONFIG_BLK_DEV_SR=m
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -273,6 +638,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -288,12 +654,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
@@ -303,7 +665,6 @@
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -312,6 +673,8 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -335,11 +698,15 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -352,284 +719,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-CONFIG_IP_TCPDIAG_IPV6=y
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_PHYSDEV=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-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_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=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_PHYSDEV=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-CONFIG_IP6_NF_RAW=m
-
-#
-# Bridge: Netfilter Configuration
-#
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_ULOG=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-# CONFIG_ATM is not set
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-# CONFIG_DECNET is not set
-CONFIG_LLC=m
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# 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
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-CONFIG_NET_CLS_IND=y
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_ACT is not set
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -637,6 +733,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -681,13 +792,17 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -700,6 +815,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -712,6 +829,8 @@
 # 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
@@ -741,19 +860,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -766,6 +872,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -786,6 +903,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -812,6 +930,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -822,10 +945,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -845,7 +978,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -855,13 +987,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -879,10 +1007,15 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -903,12 +1036,14 @@
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=m
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 CONFIG_MINIX_FS=m
 CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 CONFIG_QFMT_V2=y
@@ -916,6 +1051,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -943,12 +1079,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -974,16 +1108,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -992,6 +1129,7 @@
 # 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
@@ -1051,7 +1189,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -1073,6 +1213,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1097,9 +1238,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
new file mode 100644
index 0000000..25e8a08
--- /dev/null
+++ b/arch/mips/configs/bigsur_defconfig
@@ -0,0 +1,881 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:17 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+CONFIG_SIBYTE_BIGSUR=y
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_SIBYTE_BCM1x80=y
+CONFIG_SIBYTE_SB1xxx_SOC=y
+# CONFIG_CPU_SB1_PASS_1 is not set
+# CONFIG_CPU_SB1_PASS_2_1250 is not set
+# CONFIG_CPU_SB1_PASS_2_2 is not set
+# CONFIG_CPU_SB1_PASS_4 is not set
+# CONFIG_CPU_SB1_PASS_2_112x is not set
+# CONFIG_CPU_SB1_PASS_3 is not set
+# CONFIG_SIMULATION is not set
+# CONFIG_CONFIG_SB1_CEX_ALWAYS_FATAL is not set
+# CONFIG_CONFIG_SB1_CERR_STALL is not set
+CONFIG_SIBYTE_CFE=y
+# CONFIG_SIBYTE_CFE_CONSOLE is not set
+# CONFIG_SIBYTE_BUS_WATCHER is not set
+# CONFIG_SIBYTE_SB1250_PROF is not set
+# CONFIG_SIBYTE_TBPROF is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_COHERENT=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+CONFIG_CPU_SB1=y
+CONFIG_SYS_HAS_CPU_SB1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_SIBYTE_DMA_PAGEOPS is not set
+# CONFIG_MIPS_MT is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_PREEMPT_BKL is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_DEBUG=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_BUILD_ELF64=y
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDETAPE=y
+CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_IDE_SWARM is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# 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_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# 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_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+CONFIG_NET_SB1250_MAC=y
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_STALDRV is not set
+CONFIG_SIBYTE_SB1250_DUART=y
+CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X 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
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+CONFIG_I2C_ALGO_SIBYTE=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+CONFIG_I2C_SIBYTE=y
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB 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=y
+CONFIG_SENSORS_DS1374=y
+CONFIG_SENSORS_EEPROM=y
+CONFIG_SENSORS_PCF8574=y
+CONFIG_SENSORS_PCA9539=y
+CONFIG_SENSORS_PCF8591=y
+CONFIG_SENSORS_RTC8564=y
+CONFIG_SENSORS_MAX6875=y
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_SB1XXX_CORELIS is not set
+# CONFIG_RUNTIME_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 158e716..bfbaa08 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:00 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:20 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,57 +59,86 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_VICTOR_MPC30X is not set
-CONFIG_ZAO_CAPCELLA=y
-CONFIG_PCI_VR41XX=y
-CONFIG_VRC4173=y
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB022X is not set
+# CONFIG_VICTOR_MPC30X is not set
+CONFIG_ZAO_CAPCELLA=y
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -122,12 +154,36 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -136,7 +192,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -145,10 +200,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -161,6 +212,81 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -169,7 +295,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -188,7 +319,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -199,11 +329,8 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -244,6 +371,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -254,6 +382,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -266,79 +395,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -346,10 +409,25 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -359,7 +437,30 @@
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
-# CONFIG_NET_PCI 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 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -371,12 +472,17 @@
 # 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -389,6 +495,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -400,6 +508,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -419,29 +529,13 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=m
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -451,6 +545,12 @@
 # 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
@@ -461,16 +561,16 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -483,19 +583,7 @@
 #
 # Watchdog Cards
 #
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
+# CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -506,9 +594,15 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -519,10 +613,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -542,7 +646,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -552,13 +655,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -576,21 +675,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -611,12 +718,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -648,6 +753,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -656,6 +762,7 @@
 # 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
@@ -676,9 +783,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+CONFIG_CMDLINE="mem=32M console=ttyVR0,38400"
 
 #
 # Security options
@@ -690,7 +799,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -700,7 +833,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 4302c6f..4b4d1dd 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:00 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:23 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -50,41 +53,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_I8259=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_GT64111=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -92,8 +123,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -109,14 +142,38 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -125,7 +182,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -134,10 +190,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -150,6 +202,77 @@
 CONFIG_TRAD_SIGNALS=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=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -161,6 +284,11 @@
 CONFIG_FW_LOADER=y
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -177,7 +305,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -189,7 +316,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -234,6 +360,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -244,6 +371,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -256,75 +384,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -332,6 +398,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -357,12 +438,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -375,6 +460,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -386,6 +473,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -415,19 +504,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -437,6 +513,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -457,6 +544,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -483,6 +571,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -493,10 +586,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -516,7 +619,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -526,13 +628,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -550,12 +648,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 CONFIG_FS_MBCACHE=y
@@ -565,10 +668,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -589,12 +694,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -622,7 +725,7 @@
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -631,6 +734,7 @@
 # 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
@@ -651,7 +755,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -665,7 +771,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -675,7 +805,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 962fc14..6501144 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:01 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:26 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,63 +59,79 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+CONFIG_MIPS_DB1000=y
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-CONFIG_SOC_AU1000=y
-# CONFIG_SOC_AU1100 is not set
-# CONFIG_SOC_AU1500 is not set
-# CONFIG_SOC_AU1550 is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-CONFIG_MIPS_DB1000=y
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1000=y
+CONFIG_SOC_AU1X00=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -128,15 +147,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -152,6 +195,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
@@ -169,6 +214,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -179,12 +318,86 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
 
 #
 # Parallel port support
@@ -198,14 +411,12 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -228,6 +439,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -238,6 +450,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -248,94 +461,28 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -389,6 +536,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -418,18 +567,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -439,6 +576,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -473,14 +620,14 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 
 #
 # PCMCIA character devices
@@ -489,6 +636,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -499,10 +650,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -522,7 +683,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -532,12 +692,9 @@
 #
 # USB support
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI 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_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -552,7 +709,10 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
@@ -561,6 +721,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -579,10 +740,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -603,13 +766,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -621,6 +781,8 @@
 # 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 is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -641,6 +803,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -650,6 +813,7 @@
 # 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
@@ -709,7 +873,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -725,26 +891,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -756,9 +923,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 6a528d4..b8cd2cd 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:01 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:29 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,63 +59,79 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+CONFIG_MIPS_DB1100=y
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-CONFIG_SOC_AU1100=y
-# CONFIG_SOC_AU1500 is not set
-# CONFIG_SOC_AU1550 is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_DB1000 is not set
-CONFIG_MIPS_DB1100=y
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1100=y
+CONFIG_SOC_AU1X00=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -128,15 +147,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_MIPS_MT is not set
+CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -147,15 +190,7 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-CONFIG_PCCARD=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=m
-
-#
-# PC-card bridges
-#
-# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_AU1X00 is not set
+# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -167,6 +202,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -180,9 +309,83 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
 
 #
 # Parallel port support
@@ -196,14 +399,12 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -226,6 +427,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -236,6 +438,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -246,101 +449,35 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
-# CONFIG_MIPS_AU1X00_ENET is not set
+CONFIG_MIPS_AU1X00_ENET=y
 
 #
 # Ethernet (1000 Mbit)
@@ -360,19 +497,6 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-CONFIG_PCMCIA_AXNET=m
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -387,6 +511,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -416,18 +542,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_LIBPS2=m
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -437,6 +551,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=m
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -454,7 +578,10 @@
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_AU1X00 is not set
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -468,20 +595,19 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
-# PCMCIA character devices
+# TPM devices
 #
-CONFIG_SYNCLINK_CS=m
-# CONFIG_RAW_DRIVER is not set
 
 #
 # I2C support
@@ -494,10 +620,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -510,13 +646,43 @@
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_AU1100=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -527,12 +693,9 @@
 #
 # USB support
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI 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_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -547,7 +710,10 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
@@ -556,6 +722,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -574,10 +741,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -598,13 +767,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -616,6 +782,8 @@
 # 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 is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -636,6 +804,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -645,6 +814,7 @@
 # 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
@@ -704,7 +874,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -720,26 +892,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -751,9 +924,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
new file mode 100644
index 0000000..530b6c2
--- /dev/null
+++ b/arch/mips/configs/db1200_defconfig
@@ -0,0 +1,987 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:32 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+CONFIG_MIPS_DB1200=y
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_COHERENT=y
+CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1200=y
+CONFIG_SOC_AU1X00=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_AU1X00=m
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_AU1550 is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+# 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
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDE_AU1XXX=y
+CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA=y
+# CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA is not set
+# CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON is not set
+CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ=128
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_MIPS_AU1X00_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+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=y
+# 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+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 is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_AU1200=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AU1X=y
+
+#
+# InfiniBand support
+#
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=y
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# 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_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=48M"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index fed6f2f..1c2784d 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:01 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:36 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,63 +59,81 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+CONFIG_MIPS_DB1500=y
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-# CONFIG_SOC_AU1100 is not set
-CONFIG_SOC_AU1500=y
-# CONFIG_SOC_AU1550 is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-CONFIG_MIPS_DB1500=y
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_DMA_COHERENT=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1500=y
+CONFIG_SOC_AU1X00=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -128,15 +149,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -145,7 +190,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -154,6 +198,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 CONFIG_CARDBUS=y
 
 #
@@ -176,6 +222,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -186,15 +326,20 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 
@@ -232,16 +377,14 @@
 # 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
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_DB1X00=y
-CONFIG_MTD_DB1X00_BOOT=y
-CONFIG_MTD_DB1X00_USER=y
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -277,7 +420,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -290,7 +432,6 @@
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -336,6 +477,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -346,6 +488,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -358,94 +501,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -453,6 +515,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -479,12 +556,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -497,6 +578,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # PCMCIA network device support
@@ -520,6 +603,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -549,19 +634,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -571,6 +643,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -590,6 +673,7 @@
 CONFIG_SERIAL_AU1X00_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -603,7 +687,8 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -620,6 +705,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -630,10 +720,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -647,7 +747,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -680,7 +779,6 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_ALI5455 is not set
 # CONFIG_SOUND_FORTE is not set
 # CONFIG_SOUND_RME96XX is not set
@@ -689,6 +787,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -699,23 +799,23 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -733,12 +833,17 @@
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+CONFIG_USB_YEALINK=m
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -762,6 +867,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -786,9 +892,10 @@
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_LD=m
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -807,12 +914,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -831,10 +943,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -855,13 +969,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -895,6 +1006,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -904,6 +1016,7 @@
 # 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
@@ -963,7 +1076,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -979,26 +1094,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -1010,9 +1126,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 178c0ad..64248e2 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:02 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:39 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,63 +59,80 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+CONFIG_MIPS_DB1550=y
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-# CONFIG_SOC_AU1100 is not set
-# CONFIG_SOC_AU1500 is not set
-CONFIG_SOC_AU1550=y
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-CONFIG_MIPS_DB1550=y
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_DMA_COHERENT=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1550=y
+CONFIG_SOC_AU1X00=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -128,15 +148,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -145,7 +189,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -154,6 +197,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 CONFIG_CARDBUS=y
 
 #
@@ -176,6 +221,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -186,15 +325,20 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 
@@ -238,9 +382,8 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_DB1550=y
-CONFIG_MTD_DB1550_BOOT=y
-CONFIG_MTD_DB1550_USER=y
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -281,7 +424,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -293,7 +435,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -350,6 +491,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX 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 is not set
@@ -367,6 +509,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -377,6 +520,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -389,94 +533,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -484,6 +547,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -510,12 +588,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -528,6 +610,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # PCMCIA network device support
@@ -559,6 +643,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -588,19 +674,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -610,6 +683,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -629,6 +713,7 @@
 CONFIG_SERIAL_AU1X00_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -660,6 +745,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -670,10 +760,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -687,7 +787,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -697,13 +796,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -721,12 +816,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -745,10 +845,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -769,13 +871,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -809,6 +908,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -818,6 +918,7 @@
 # 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
@@ -877,7 +978,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -893,26 +996,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -924,9 +1028,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
index 70addc7..b260e51 100644
--- a/arch/mips/configs/ddb5476_defconfig
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:02 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:42 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -50,41 +53,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 CONFIG_DDB5476=y
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_I8259=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_DDB5XXX_COMMON=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -93,8 +124,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -110,14 +143,38 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5432=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -126,7 +183,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_ISA=y
 CONFIG_MMU=y
 
@@ -136,11 +192,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-CONFIG_PCMCIA_PROBE=y
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -153,6 +204,80 @@
 CONFIG_TRAD_SIGNALS=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=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -161,7 +286,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
 
 #
 # Memory Technology Devices (MTD)
@@ -181,8 +311,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -193,7 +321,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -239,6 +366,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -254,6 +382,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -266,78 +395,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -345,6 +409,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -352,7 +431,6 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 
@@ -377,12 +455,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -395,6 +477,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -406,6 +490,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -435,19 +521,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -457,6 +530,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -477,6 +561,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -503,6 +588,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -513,10 +603,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -530,6 +630,11 @@
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -537,6 +642,7 @@
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
@@ -549,8 +655,11 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_E1356 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -575,13 +684,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -599,21 +704,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -634,12 +747,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -668,7 +779,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -677,6 +788,7 @@
 # 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
@@ -697,7 +809,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any"
 
@@ -711,7 +825,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -721,7 +859,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 6029280..c2a01df 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:02 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:45 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -50,42 +53,70 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 CONFIG_DDB5477=y
-CONFIG_DDB5477_BUS_FREQUENCY=0
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_DDB5477_BUS_FREQUENCY=0
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_I8259=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_DDB5XXX_COMMON=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -93,8 +124,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -110,14 +143,38 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5432=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -126,7 +183,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -135,10 +191,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -151,6 +203,80 @@
 CONFIG_TRAD_SIGNALS=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=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -159,7 +285,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
 
 #
 # Memory Technology Devices (MTD)
@@ -178,7 +309,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -189,7 +319,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -212,6 +341,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -222,6 +352,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -234,78 +365,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -313,6 +379,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -357,13 +438,17 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -376,6 +461,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -387,6 +474,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -416,19 +505,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -438,6 +514,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -458,6 +545,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -484,6 +572,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -494,10 +587,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -517,7 +620,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -527,13 +629,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -551,21 +649,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -586,12 +692,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -623,6 +727,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -631,6 +736,7 @@
 # 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
@@ -651,7 +757,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any"
 
@@ -665,7 +773,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -675,7 +807,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 66ec1f4..5bc885b 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:03 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:48 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,30 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -49,48 +53,76 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
+# CONFIG_MODVERSIONS is not set
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
 
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_EARLY_PRINTK=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_BOOT_ELF32=y
 CONFIG_MIPS_L1_CACHE_SHIFT=4
@@ -98,8 +130,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 CONFIG_CPU_R3000=y
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -115,12 +149,37 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R3000=y
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_WB=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -135,10 +194,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -150,6 +205,80 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# 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=y
+# 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -159,6 +288,12 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -177,17 +312,14 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -196,7 +328,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -206,6 +338,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -213,10 +346,12 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
+CONFIG_CHR_DEV_ST=m
 # CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -228,9 +363,10 @@
 #
 # SCSI Transport Attributes
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -248,6 +384,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -258,78 +395,28 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -363,6 +450,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -377,48 +466,22 @@
 #
 # Input device support
 #
-CONFIG_INPUT=y
+# CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-CONFIG_INPUT_MOUSEDEV=y
-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
-
-#
-# Input I/O drivers
-#
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_DEC=y
+CONFIG_SERIAL_DEC_CONSOLE=y
+CONFIG_ZS=y
 
 #
 # Serial drivers
@@ -445,18 +508,20 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
+CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -467,10 +532,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -483,13 +558,29 @@
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_PMAG_AA is not set
+CONFIG_FB_PMAG_BA=y
+CONFIG_FB_PMAGB_B=y
+# CONFIG_FB_MAXINE is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
-# Console display driver support
+# Logo configuration
 #
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_DEC_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -504,10 +595,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -520,7 +607,10 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
@@ -529,6 +619,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 CONFIG_FS_MBCACHE=y
@@ -538,10 +629,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -562,12 +655,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -584,19 +675,31 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
+CONFIG_UFS_FS=y
+CONFIG_UFS_FS_WRITE=y
 
 #
 # Network File Systems
 #
-# CONFIG_NFS_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # 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
@@ -631,9 +734,24 @@
 #
 # Kernel hacking
 #
-# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
 
 #
 # Security options
@@ -645,7 +763,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -655,7 +797,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index ba2ec01..c0d06ea 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:03 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:51 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,56 +59,84 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
-CONFIG_CASIO_E55=y
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-# CONFIG_VRC4171 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_NEC_CMBVR4133 is not set
+CONFIG_CASIO_E55=y
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB022X is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -121,12 +152,36 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -141,11 +196,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-CONFIG_PCMCIA_PROBE=y
-
-#
 # PCI Hotplug Support
 #
 
@@ -157,6 +207,78 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -168,6 +290,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -185,18 +312,13 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -205,7 +327,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -237,6 +359,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -252,6 +375,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -262,76 +386,13 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -339,12 +400,26 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
@@ -380,6 +455,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -401,26 +478,14 @@
 #
 CONFIG_INPUT_MOUSEDEV=y
 CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -430,6 +495,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -440,16 +515,15 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -484,10 +558,14 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -498,10 +576,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -522,7 +610,6 @@
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -536,10 +623,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -552,24 +635,31 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -590,12 +680,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -617,16 +705,17 @@
 #
 # Network File Systems
 #
-CONFIG_NFS_FS=y
+CONFIG_NFS_FS=m
 # CONFIG_NFS_V3 is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 # CONFIG_NFSD_V3 is not set
 # CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
+CONFIG_LOCKD=m
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -634,6 +723,7 @@
 # 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
@@ -654,9 +744,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
 
 #
 # Security options
@@ -668,7 +760,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -678,7 +794,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index 17e87f7..f1309d8 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:03 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:54 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,41 +59,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 CONFIG_MIPS_EV64120=y
-# CONFIG_EVB_PCI1 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_EVB_PCI1 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_MIPS_GT64120=y
 # CONFIG_SYSCLK_75 is not set
 # CONFIG_SYSCLK_83 is not set
@@ -100,8 +131,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -117,15 +150,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -134,7 +191,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -143,10 +199,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -159,6 +211,79 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -167,7 +292,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -186,7 +316,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -197,7 +326,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -220,6 +348,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -230,6 +359,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -242,77 +372,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -320,6 +386,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -345,12 +426,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -363,6 +448,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -381,6 +468,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -410,19 +499,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -432,6 +508,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -452,6 +539,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -478,6 +566,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -488,10 +581,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -511,7 +614,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -521,13 +623,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -545,21 +643,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -580,12 +686,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -614,7 +718,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -623,6 +727,7 @@
 # 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
@@ -643,7 +748,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
 
@@ -657,7 +764,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -667,7 +798,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=y
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index 9da4140..8ac55b7 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:03 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:57 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,40 +59,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 CONFIG_MIPS_EV96100=y
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_GT64120=y
 CONFIG_SWAP_IO_SPACE=y
@@ -99,8 +130,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -116,6 +149,18 @@
 CONFIG_CPU_RM7000=y
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -123,11 +168,25 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -143,10 +202,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -158,6 +213,79 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -169,6 +297,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -185,13 +318,11 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -214,6 +345,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -224,6 +356,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -234,77 +367,28 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -338,6 +422,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -367,18 +453,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -388,6 +462,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -429,10 +513,13 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -443,10 +530,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -466,7 +563,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -480,10 +576,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -496,24 +588,31 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -534,12 +633,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -568,7 +665,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -577,6 +674,7 @@
 # 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
@@ -597,7 +695,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -611,7 +711,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -621,7 +745,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 17fa5c4..3ae3838 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:04 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:01 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,25 +11,30 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -42,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,41 +60,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 CONFIG_SGI_IP22=y
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_ARC32=y
@@ -103,8 +134,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -120,22 +153,48 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_BOARD_SCACHE=y
 CONFIG_IP22_CPU_SCACHE=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
 #
+CONFIG_HW_HAS_EISA=y
 # CONFIG_EISA is not set
 CONFIG_MMU=y
 
@@ -145,10 +204,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -160,115 +215,7 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=m
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-CONFIG_SGIWD93_SCSI=y
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
+# Networking
 #
 CONFIG_NET=y
 
@@ -277,12 +224,14 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # 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=y
@@ -296,8 +245,10 @@
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-CONFIG_IP_TCPDIAG_IPV6=y
+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
@@ -341,6 +292,9 @@
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
 
 #
 # IP: Netfilter Configuration
@@ -348,11 +302,15 @@
 CONFIG_IP_NF_CONNTRACK=m
 CONFIG_IP_NF_CT_ACCT=y
 CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
 # 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=m
 CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_LIMIT=m
@@ -376,9 +334,12 @@
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_REALM=m
 CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_DCCP=m
 CONFIG_IP_NF_MATCH_COMMENT=m
 CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -395,12 +356,14 @@
 CONFIG_IP_NF_NAT_FTP=m
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_TARGET_CONNMARK=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -410,7 +373,7 @@
 CONFIG_IP_NF_ARP_MANGLE=m
 
 #
-# IPv6: Netfilter Configuration
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -429,11 +392,16 @@
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -456,10 +424,6 @@
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 CONFIG_NET_SCHED=y
 # CONFIG_NET_SCH_CLK_JIFFIES is not set
 CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
@@ -479,6 +443,7 @@
 CONFIG_NET_QOS=y
 CONFIG_NET_ESTIMATOR=y
 CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
 CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_ROUTE=y
@@ -489,6 +454,7 @@
 # CONFIG_CLS_U32_MARK is not set
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
 # CONFIG_NET_CLS_ACT is not set
 CONFIG_NET_CLS_POLICE=y
 
@@ -496,17 +462,153 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SGIWD93_SCSI=y
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-CONFIG_ETHERTAP=m
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -540,6 +642,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -569,18 +673,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -598,6 +690,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -644,11 +746,14 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_MAX_RAW_DEVS=256
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -659,10 +764,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -693,7 +808,6 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_SGI_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -707,10 +821,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -723,13 +833,17 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=m
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -741,12 +855,14 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=m
 CONFIG_XFS_SECURITY=y
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 CONFIG_MINIX_FS=m
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 CONFIG_QFMT_V2=m
@@ -754,6 +870,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -781,12 +898,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -811,15 +926,20 @@
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -835,6 +955,7 @@
 CONFIG_CODA_FS=m
 # CONFIG_CODA_FS_OLD_API is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -908,7 +1029,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -931,6 +1054,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -942,10 +1066,10 @@
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -955,9 +1079,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index b2a67da..d962f61 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -1,11 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:04 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:04 2005
 #
 CONFIG_MIPS=y
-CONFIG_64BIT=y
-CONFIG_64BIT=y
 
 #
 # Code maturity level options
@@ -13,25 +11,31 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_CPUSETS=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +45,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,55 +62,85 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
 CONFIG_SGI_IP27=y
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_SGI_SN0_N_MODE is not set
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_NUMA=y
 # CONFIG_MAPPED_KERNEL is not set
 # CONFIG_REPLICATE_KTEXT is not set
 # CONFIG_REPLICATE_EXHANDLERS is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
 CONFIG_DMA_IP27=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_MIPS_L1_CACHE_SHIFT=7
 CONFIG_ARC64=y
 CONFIG_BOOT_ELF64=y
-CONFIG_QL_ISP_A64=y
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -121,17 +156,42 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R10000=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=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_SMP=y
 CONFIG_NR_CPUS=64
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
 # CONFIG_MIPS_INSANE_LARGE is not set
 
 #
@@ -141,7 +201,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -150,10 +209,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -163,7 +218,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
-# CONFIG_BUILD_ELF64 is not set
+CONFIG_BUILD_ELF64=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -171,6 +226,111 @@
 CONFIG_BINFMT_ELF32=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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_IP_MROUTE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -179,7 +339,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -198,7 +363,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -210,7 +374,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -232,6 +395,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -241,8 +405,10 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 # CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -256,7 +422,8 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -271,26 +438,24 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-CONFIG_SCSI_QLOGIC_ISP=y
 # CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLOGIC_1280=y
+CONFIG_SCSI_QLOGIC_1280_1040=y
 CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA21XX is not set
 # CONFIG_SCSI_QLA22XX is not set
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -313,11 +478,15 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -330,107 +499,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-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_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-CONFIG_NET_SCHED=y
-# CONFIG_NET_SCH_CLK_JIFFIES is not set
-CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
-# CONFIG_NET_SCH_CLK_CPU is not set
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-# CONFIG_NET_CLS_IND is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_ACT is not set
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -438,13 +513,25 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_SGI_IOC3_ETH=y
-CONFIG_SGI_IOC3_ETH_HW_RX_CSUM=y
-CONFIG_SGI_IOC3_ETH_HW_TX_CSUM=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -466,12 +553,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -484,6 +575,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -496,6 +589,8 @@
 # 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
@@ -513,25 +608,15 @@
 # CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 CONFIG_SERIO=y
 # CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_LIBPS2=m
 CONFIG_SERIO_RAW=m
-
-#
-# Input Device Drivers
-#
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -549,7 +634,6 @@
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -557,6 +641,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -584,6 +669,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -594,10 +684,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -611,7 +711,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -621,13 +720,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -645,12 +740,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -662,17 +762,19 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
+CONFIG_XFS_QUOTA=m
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -693,12 +795,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -722,13 +822,14 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
@@ -738,6 +839,7 @@
 # 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
@@ -772,7 +874,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -788,28 +892,29 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -819,9 +924,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index b26e117..bf8fb95 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -1,11 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:04 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:07 2005
 #
 CONFIG_MIPS=y
-CONFIG_64BIT=y
-CONFIG_64BIT=y
 
 #
 # Code maturity level options
@@ -13,11 +11,13 @@
 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_POSIX_MQUEUE is not set
@@ -25,13 +25,16 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -50,42 +54,71 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 CONFIG_SGI_IP32=y
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
 CONFIG_DMA_IP32=y
-CONFIG_OWN_DMA=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_OWN_DMA=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_ARC32=y
 CONFIG_BOOT_ELF32=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -95,8 +128,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -112,6 +147,17 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -119,9 +165,22 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_R5000_CPU_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
+# CONFIG_MIPS_MT is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
 
 #
@@ -130,7 +189,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -139,10 +197,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -160,6 +214,80 @@
 CONFIG_BINFMT_ELF32=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -168,7 +296,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
 
 #
 # Memory Technology Devices (MTD)
@@ -187,7 +320,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -199,7 +331,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -221,6 +352,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -233,6 +365,7 @@
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -244,9 +377,10 @@
 #
 # SCSI Transport Attributes
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
 
 #
 # SCSI low-level drivers
@@ -266,18 +400,13 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -286,6 +415,8 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -299,6 +430,8 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -311,78 +444,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -390,6 +458,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -416,12 +499,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -434,6 +521,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -446,6 +535,8 @@
 # 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
@@ -475,20 +566,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_MACEPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -498,6 +575,18 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_MACEPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -518,6 +607,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -544,6 +634,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -554,10 +649,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -577,7 +682,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -587,13 +691,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -611,21 +711,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -646,13 +754,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -676,13 +781,14 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -691,6 +797,7 @@
 # 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
@@ -721,7 +828,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -735,7 +844,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -745,7 +878,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index 08bd3ad..0940771 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:05 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:09 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,11 +11,13 @@
 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_POSIX_MQUEUE is not set
@@ -26,13 +25,16 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -42,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,41 +60,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 CONFIG_MIPS_ITE8172=y
-# CONFIG_IT8172_REVC is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_IT8172_REVC is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_ITE_BOARD_GEN=y
 CONFIG_IT8172_CIR=y
 CONFIG_IT8712=y
@@ -100,8 +131,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -117,14 +150,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5432=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -140,10 +198,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -155,6 +209,80 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -166,12 +294,17 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
 # CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
 
 #
 # User Modules And Translation Layers
@@ -207,7 +340,6 @@
 # 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
@@ -217,6 +349,7 @@
 CONFIG_MTD_PHYSMAP_START=0x8000000
 CONFIG_MTD_PHYSMAP_LEN=0x2000000
 CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -251,14 +384,12 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -302,6 +433,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -312,6 +444,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -322,78 +455,28 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -426,6 +509,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -455,18 +540,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -476,6 +549,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -521,10 +604,13 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -535,10 +621,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -558,7 +654,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -574,15 +669,9 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_SONICVIBES is not set
 CONFIG_SOUND_IT8172=y
-# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_AD1980 is not set
 
 #
@@ -592,10 +681,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -608,24 +693,31 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -646,12 +738,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -682,7 +772,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -691,6 +781,7 @@
 # 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
@@ -711,7 +802,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -725,7 +818,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -735,7 +852,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index 583ef5c..9ba61dfc 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:05 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:12 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,11 +11,13 @@
 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_POSIX_MQUEUE is not set
@@ -26,13 +25,16 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -42,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,40 +60,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 CONFIG_MIPS_IVR=y
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_ITE_BOARD_GEN=y
 CONFIG_IT8172_CIR=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -98,8 +129,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -115,14 +148,38 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -131,7 +188,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -140,10 +196,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -156,6 +208,80 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -164,7 +290,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -183,7 +314,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -194,7 +324,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -239,6 +368,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -249,6 +379,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -261,78 +392,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -340,6 +406,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -365,12 +446,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -383,6 +468,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -394,6 +481,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -423,19 +512,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -445,6 +521,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -467,6 +554,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -492,6 +580,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -502,10 +595,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -525,7 +628,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -535,13 +637,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -559,21 +657,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -594,12 +700,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -628,7 +732,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -637,6 +741,7 @@
 # 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
@@ -657,7 +762,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -671,7 +778,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -681,7 +812,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 8abb5a0..21b2b80 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:05 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:14 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 # CONFIG_EXPERIMENTAL is not set
 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_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -54,36 +57,70 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
 CONFIG_MOMENCO_JAGUAR_ATX=y
-CONFIG_JAGUAR_DMALOW=y
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_JAGUAR_DMALOW=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_LIMITED_DMA=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_CPU_RM7K=y
 CONFIG_IRQ_MV64340=y
@@ -95,8 +132,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -112,6 +151,17 @@
 # CONFIG_CPU_RM7000 is not set
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -119,13 +169,24 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_HIGHMEM=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 # CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -134,7 +195,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -143,10 +203,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -158,6 +214,68 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_NETFILTER 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_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -166,7 +284,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -185,7 +308,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -195,7 +317,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -218,6 +339,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -228,6 +350,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -240,58 +363,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# 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
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -304,6 +377,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -343,9 +431,11 @@
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 CONFIG_MV643XX_ETH=y
 CONFIG_MV643XX_ETH_0=y
 CONFIG_MV643XX_ETH_1=y
@@ -354,6 +444,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -366,6 +457,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -374,6 +467,8 @@
 # CONFIG_FDDI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -391,20 +486,10 @@
 # CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -425,6 +510,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -451,6 +537,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -461,10 +551,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -478,7 +578,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -488,13 +587,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -512,6 +607,10 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
@@ -519,13 +618,16 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -546,10 +648,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -570,7 +672,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
@@ -591,7 +693,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -605,7 +709,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -615,7 +743,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=m
+CONFIG_CRC32=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index da5d9ee..9a728c2 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:06 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:17 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -50,40 +53,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-CONFIG_TOSHIBA_JMR3927=y
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+CONFIG_TOSHIBA_JMR3927=y
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_MIPS_TX3927=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -92,8 +123,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 CONFIG_CPU_TX39XX=y
 # CONFIG_CPU_VR41XX is not set
@@ -109,12 +142,34 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_TX39XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_RTC_DS1742=y
 
@@ -124,7 +179,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -133,10 +187,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -149,6 +199,80 @@
 CONFIG_TRAD_SIGNALS=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=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -157,7 +281,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
 
 #
 # Memory Technology Devices (MTD)
@@ -176,7 +305,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -187,7 +315,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -210,6 +337,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -220,6 +348,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -232,78 +361,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -311,6 +375,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -336,12 +415,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -354,6 +437,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -365,6 +450,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -394,19 +481,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -416,6 +490,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -426,11 +511,9 @@
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
 # CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
@@ -438,10 +521,6 @@
 # CONFIG_SX is not set
 # CONFIG_RIO is not set
 # CONFIG_STALDRV is not set
-# CONFIG_SERIAL_TX3912 is not set
-CONFIG_TXX927_SERIAL=y
-CONFIG_TXX927_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_TXX9 is not set
 
 #
 # Serial drivers
@@ -451,6 +530,8 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_JSM is not set
 # CONFIG_UNIX98_PTYS is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -477,6 +558,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -487,10 +573,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -504,6 +600,11 @@
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -511,6 +612,7 @@
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
@@ -523,8 +625,11 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_E1356 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -548,13 +653,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -572,6 +673,10 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
@@ -579,13 +684,16 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -606,10 +714,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -638,7 +746,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -647,6 +755,7 @@
 # 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
@@ -667,7 +776,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -681,7 +792,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -691,7 +826,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index 8d600ae..03cd0ca 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:06 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:19 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,53 +59,83 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
 CONFIG_LASAT=y
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_PICVUE=y
 CONFIG_PICVUE_PROC=y
 CONFIG_DS1603=y
 CONFIG_LASAT_SYSCTL=y
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_NILE4=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_MIPS_GT64120=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -118,17 +151,41 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_BOARD_SCACHE=y
 CONFIG_R5000_CPU_SCACHE=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -137,7 +194,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
 CONFIG_MMU=y
 
 #
@@ -146,10 +202,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -162,6 +214,76 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -170,15 +292,20 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 
@@ -223,6 +350,7 @@
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_PHYSMAP is not set
 CONFIG_MTD_LASAT=y
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -258,7 +386,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -269,7 +396,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -326,6 +452,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX 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 is not set
@@ -343,6 +470,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -353,6 +481,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -365,68 +494,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -439,6 +508,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -464,12 +548,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -482,6 +570,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -493,6 +583,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -522,19 +614,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -544,6 +623,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -564,6 +654,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -590,6 +681,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -600,10 +696,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -623,7 +729,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -633,13 +738,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -657,10 +758,15 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -670,13 +776,16 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -697,12 +806,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -728,12 +835,13 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -742,6 +850,7 @@
 # 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
@@ -762,7 +871,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -776,7 +887,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -786,7 +921,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 79519ac..2acdec9 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:53:14 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:22 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,44 +59,75 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 CONFIG_MIPS_MALTA=y
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_I8259=y
 CONFIG_MIPS_BONITO64=y
 CONFIG_MIPS_MSC=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
 CONFIG_MIPS_BOARDS_GEN=y
 CONFIG_MIPS_GT64120=y
 CONFIG_SWAP_IO_SPACE=y
@@ -104,8 +138,10 @@
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -121,14 +157,48 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMP is not set
+CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_VPE_LOADER_TOM=y
+CONFIG_MIPS_VPE_APSP_API=y
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -137,7 +207,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -146,10 +215,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -162,6 +227,305 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+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
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+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_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_DCCP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+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_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=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+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
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+CONFIG_NET_CLS_IND=y
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -173,6 +537,11 @@
 CONFIG_FW_LOADER=y
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -203,7 +572,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -261,6 +629,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 CONFIG_BLK_DEV_PIIX=y
+# 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 is not set
@@ -278,6 +647,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
 CONFIG_SCSI_PROC_FS=y
 
@@ -290,6 +660,7 @@
 CONFIG_BLK_DEV_SR=m
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -304,6 +675,7 @@
 CONFIG_SCSI_SPI_ATTRS=m
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -324,18 +696,13 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=m
@@ -344,6 +711,8 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -367,11 +736,15 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -384,284 +757,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-CONFIG_IP_TCPDIAG_IPV6=y
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_PHYSDEV=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-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_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=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_PHYSDEV=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-CONFIG_IP6_NF_RAW=m
-
-#
-# Bridge: Netfilter Configuration
-#
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_ULOG=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-# CONFIG_ATM is not set
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-# CONFIG_DECNET is not set
-CONFIG_LLC=m
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-CONFIG_NET_DIVERT=y
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# 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
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-CONFIG_NET_CLS_IND=y
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_ACT is not set
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -669,6 +771,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -713,13 +830,17 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -732,6 +853,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -744,6 +867,8 @@
 # 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
@@ -773,19 +898,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -795,6 +907,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -815,6 +938,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -840,6 +964,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -850,10 +979,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -873,7 +1012,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -883,13 +1021,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -907,10 +1041,15 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -931,12 +1070,14 @@
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=m
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 CONFIG_MINIX_FS=m
 CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 CONFIG_QFMT_V2=y
@@ -944,6 +1085,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -971,12 +1113,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1002,16 +1142,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -1020,6 +1163,7 @@
 # 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
@@ -1079,7 +1223,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -1101,6 +1247,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1125,9 +1272,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
new file mode 100644
index 0000000..fb9bdd9
--- /dev/null
+++ b/arch/mips/configs/mipssim_defconfig
@@ -0,0 +1,775 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:25 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+CONFIG_MIPS_SIM=y
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMP is not set
+CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_VPE_LOADER_TOM=y
+CONFIG_MIPS_VPE_APSP_API=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+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_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+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 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# 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_NET_DIVERT=y
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+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
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+# CONFIG_NET_CLS_POLICE 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_MIPS_SIM_NET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+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 is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 0fea57e..e2c0821 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:07 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:28 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,57 +59,86 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-CONFIG_VICTOR_MPC30X=y
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_PCI_VR41XX=y
-CONFIG_VRC4173=y
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB022X is not set
+CONFIG_VICTOR_MPC30X=y
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+CONFIG_VRC4173=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -122,12 +154,36 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -136,17 +192,26 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+# CONFIG_CARDBUS is not set
 
 #
 # PC-card bridges
 #
+# CONFIG_YENTA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_VRC4173=y
 
 #
 # PCI Hotplug Support
@@ -161,6 +226,78 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -169,7 +306,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -188,7 +330,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -197,13 +338,11 @@
 # CONFIG_BLK_DEV_LOOP 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 is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -217,11 +356,35 @@
 #
 # ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -232,6 +395,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -244,79 +408,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -324,20 +422,14 @@
 # CONFIG_ARCNET is not set
 
 #
-# Ethernet (10 or 100Mbit)
+# PHY device support
 #
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
 
 #
-# Tulip family network device support
+# Ethernet (10 or 100Mbit)
 #
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=m
 
 #
 # Ethernet (1000 Mbit)
@@ -349,12 +441,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -366,7 +462,59 @@
 #
 # Wireless LAN (non-hamradio)
 #
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
 
 #
 # Wan interfaces
@@ -378,6 +526,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -407,19 +557,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -429,6 +566,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -439,16 +587,16 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -472,9 +620,20 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -485,10 +644,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -508,7 +677,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -518,13 +686,120 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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 is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=m
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
 
 #
 # USB Gadget Support
@@ -542,21 +817,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -577,12 +860,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -609,9 +890,8 @@
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -620,6 +900,7 @@
 # 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
@@ -640,9 +921,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
 
 #
 # Security options
@@ -656,26 +939,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -687,9 +971,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC16=m
+CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index b4cf97a..ffb23fc 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:07 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:30 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,25 +11,30 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -42,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,40 +60,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-CONFIG_MOMENCO_OCELOT_3=y
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+CONFIG_MOMENCO_OCELOT_3=y
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_CPU_RM7K=y
 CONFIG_IRQ_MV64340=y
@@ -102,8 +133,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -119,6 +152,17 @@
 # CONFIG_CPU_RM7000 is not set
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -126,13 +170,26 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
-# CONFIG_HIGHMEM is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -141,7 +198,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -150,10 +206,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -166,6 +218,110 @@
 CONFIG_TRAD_SIGNALS=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_NET_KEY=y
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_TUNNEL 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_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -174,7 +330,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -193,7 +354,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -205,7 +365,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -226,6 +385,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=m
 CONFIG_SCSI_PROC_FS=y
 
@@ -237,6 +397,7 @@
 # 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
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -251,6 +412,7 @@
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -266,18 +428,13 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=m
@@ -286,6 +443,8 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -300,6 +459,8 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -312,105 +473,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL is not set
-CONFIG_IP_TCPDIAG=m
-CONFIG_IP_TCPDIAG_IPV6=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration
-#
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -418,6 +487,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -440,7 +524,6 @@
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -463,9 +546,12 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 CONFIG_MV643XX_ETH=y
 CONFIG_MV643XX_ETH_0=y
 CONFIG_MV643XX_ETH_1=y
@@ -474,6 +560,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -486,6 +573,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -505,6 +594,8 @@
 # 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
@@ -531,19 +622,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -553,6 +631,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -573,6 +662,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -598,6 +688,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -608,10 +703,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -625,6 +730,11 @@
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -632,6 +742,7 @@
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
@@ -644,8 +755,11 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_E1356 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -675,13 +789,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -699,10 +809,15 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=m
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -715,17 +830,21 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -746,15 +865,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -778,16 +892,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -797,6 +914,7 @@
 # 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
@@ -856,7 +974,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any root=nfs"
 
@@ -869,7 +989,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -879,9 +1023,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index a38903d..d3a5fee 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -1,11 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:07 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:33 2005
 #
 CONFIG_MIPS=y
-CONFIG_64BIT=y
-CONFIG_64BIT=y
 
 #
 # Code maturity level options
@@ -13,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -40,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -49,39 +53,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-CONFIG_MOMENCO_OCELOT_C=y
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+CONFIG_MOMENCO_OCELOT_C=y
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 # CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_MV64340=y
 CONFIG_PCI_MARVELL=y
@@ -91,8 +124,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -108,6 +143,17 @@
 CONFIG_CPU_RM7000=y
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -115,9 +161,23 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -126,7 +186,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -135,10 +194,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -156,6 +211,79 @@
 CONFIG_BINFMT_ELF32=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -164,7 +292,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
 
 #
 # Memory Technology Devices (MTD)
@@ -183,7 +316,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -194,7 +326,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -216,6 +347,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -226,6 +358,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -238,77 +371,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -316,6 +385,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -341,13 +425,17 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 # CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -360,6 +448,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -371,6 +461,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -400,19 +492,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -422,6 +501,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -442,6 +532,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -468,6 +559,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -478,10 +574,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -501,7 +607,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -511,13 +616,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -535,21 +636,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -570,12 +679,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -607,6 +714,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -615,6 +723,7 @@
 # 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
@@ -635,7 +744,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -649,7 +760,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -659,7 +794,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 920d59b..1edde12 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:08 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:35 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -50,40 +53,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-CONFIG_MOMENCO_OCELOT=y
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+CONFIG_MOMENCO_OCELOT=y
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_CPU_RM7K=y
 CONFIG_MIPS_GT64120=y
@@ -96,8 +127,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -113,6 +146,17 @@
 CONFIG_CPU_RM7000=y
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -120,11 +164,25 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -140,10 +198,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -155,6 +209,79 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -166,6 +293,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -182,13 +314,11 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -211,6 +341,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -221,6 +352,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -231,77 +363,28 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
 
 #
 # Ethernet (10 or 100Mbit)
@@ -334,6 +417,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -363,18 +448,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -384,6 +457,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -425,10 +508,13 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -439,10 +525,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -462,7 +558,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -476,10 +571,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -492,24 +583,31 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -530,12 +628,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -567,6 +663,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -575,6 +672,7 @@
 # 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
@@ -595,7 +693,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -609,7 +709,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -619,7 +743,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index ef5ea50..e2d5188 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -1,11 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:08 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:38 2005
 #
 CONFIG_MIPS=y
-CONFIG_64BIT=y
-CONFIG_64BIT=y
 
 #
 # Code maturity level options
@@ -13,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -40,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -49,39 +53,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-CONFIG_MOMENCO_OCELOT_G=y
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+CONFIG_MOMENCO_OCELOT_G=y
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 # CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_CPU_RM7K=y
 CONFIG_PCI_MARVELL=y
@@ -94,8 +127,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -111,6 +146,17 @@
 CONFIG_CPU_RM7000=y
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
@@ -118,9 +164,23 @@
 CONFIG_BOARD_SCACHE=y
 CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -129,7 +189,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -138,10 +197,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -159,6 +214,79 @@
 CONFIG_BINFMT_ELF32=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+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=y
+# 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_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
 # Device Drivers
 #
 
@@ -167,7 +295,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
 
 #
 # Memory Technology Devices (MTD)
@@ -186,7 +319,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -197,7 +329,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -219,6 +350,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -229,6 +361,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -241,77 +374,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# 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_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -319,6 +388,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -345,12 +429,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -363,6 +451,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=y
 
 #
 # Wan interfaces
@@ -374,6 +464,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -403,19 +495,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -425,6 +504,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -445,6 +535,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -471,6 +562,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -481,10 +577,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -504,7 +610,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -514,13 +619,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -538,21 +639,29 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -573,12 +682,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -610,6 +717,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -618,6 +726,7 @@
 # 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
@@ -638,7 +747,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -652,7 +763,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -662,7 +797,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 813e3a8..47247ad 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:08 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:41 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,56 +59,70 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+CONFIG_MIPS_PB1100=y
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-CONFIG_SOC_AU1100=y
-# CONFIG_SOC_AU1500 is not set
-# CONFIG_SOC_AU1550 is not set
-# CONFIG_MIPS_PB1000 is not set
-CONFIG_MIPS_PB1100=y
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1100=y
+CONFIG_SOC_AU1X00=y
 CONFIG_SWAP_IO_SPACE=y
 # CONFIG_AU1X00_USB_DEVICE is not set
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -113,8 +130,10 @@
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -130,15 +149,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
-# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_MIPS_MT is not set
+CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -154,6 +197,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
@@ -171,6 +216,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -181,15 +320,20 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 
@@ -233,9 +377,8 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_PB1100=y
-CONFIG_MTD_PB1500_BOOT=y
-CONFIG_MTD_PB1500_USER=y
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -270,14 +413,12 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -300,6 +441,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -310,6 +452,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -320,94 +463,28 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -453,6 +530,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -482,18 +561,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -503,6 +570,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -534,14 +611,14 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 
 #
 # PCMCIA character devices
@@ -550,6 +627,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -560,10 +641,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -583,7 +674,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -593,12 +683,9 @@
 #
 # USB support
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI 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_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -613,7 +700,10 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
@@ -622,6 +712,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -640,10 +731,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -664,13 +757,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -704,6 +794,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -713,6 +804,7 @@
 # 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
@@ -772,7 +864,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -788,26 +882,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -819,9 +914,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 49e52834..f91a4ea 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:09 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:44 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,63 +59,80 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+CONFIG_MIPS_PB1500=y
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-# CONFIG_SOC_AU1100 is not set
-CONFIG_SOC_AU1500=y
-# CONFIG_SOC_AU1550 is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-CONFIG_MIPS_PB1500=y
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_DMA_COHERENT=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1500=y
+CONFIG_SOC_AU1X00=y
 # CONFIG_AU1X00_USB_DEVICE is not set
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -128,15 +148,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -145,7 +189,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -154,6 +197,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 CONFIG_CARDBUS=y
 
 #
@@ -177,6 +222,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -187,12 +326,87 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
 
 #
 # Parallel port support
@@ -206,7 +420,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -218,7 +431,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -275,6 +487,7 @@
 CONFIG_BLK_DEV_HPT366=y
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX 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 is not set
@@ -292,6 +505,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -302,6 +516,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -314,94 +529,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -409,6 +543,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -435,12 +584,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -453,6 +606,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # PCMCIA network device support
@@ -484,6 +639,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -513,19 +670,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -535,6 +679,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -554,6 +709,7 @@
 CONFIG_SERIAL_AU1X00_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -585,6 +741,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -595,10 +756,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -612,7 +783,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -622,13 +792,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -646,12 +812,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -670,10 +841,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -694,13 +867,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -712,6 +882,8 @@
 # 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 is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -732,6 +904,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -741,6 +914,7 @@
 # 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
@@ -800,7 +974,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -816,27 +992,28 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -847,9 +1024,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 8e42677..bbad27c 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:09 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:47 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,63 +59,80 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+CONFIG_MIPS_PB1550=y
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SOC_AU1X00=y
-# CONFIG_SOC_AU1000 is not set
-# CONFIG_SOC_AU1100 is not set
-# CONFIG_SOC_AU1500 is not set
-CONFIG_SOC_AU1550=y
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-CONFIG_MIPS_PB1550=y
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_DMA_COHERENT=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SOC_AU1550=y
+CONFIG_SOC_AU1X00=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -128,15 +148,39 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -145,7 +189,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -154,6 +197,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 CONFIG_CARDBUS=y
 
 #
@@ -177,6 +222,100 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_TRAD_SIGNALS=y
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+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_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -187,12 +326,87 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_ALCHEMY=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
 
 #
 # Parallel port support
@@ -206,7 +420,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -218,7 +431,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -275,6 +487,7 @@
 CONFIG_BLK_DEV_HPT366=y
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX 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 is not set
@@ -292,6 +505,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -302,6 +516,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -314,94 +529,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -409,6 +543,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -435,12 +584,16 @@
 # 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_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -453,6 +606,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # PCMCIA network device support
@@ -476,6 +631,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -505,19 +662,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -527,6 +671,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -546,6 +701,7 @@
 CONFIG_SERIAL_AU1X00_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -577,6 +733,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -587,10 +748,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -604,7 +775,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -614,13 +784,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -638,12 +804,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -662,10 +833,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -686,13 +859,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -704,6 +874,8 @@
 # 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 is not set
 CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -724,6 +896,7 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -733,6 +906,7 @@
 # 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
@@ -792,7 +966,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -808,26 +984,27 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-CONFIG_CRYPTO_TWOFISH=y
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
@@ -839,9 +1016,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
new file mode 100644
index 0000000..95f84d7
--- /dev/null
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -0,0 +1,1069 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:50 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+CONFIG_PNX8550_JBS=y
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_PNX8550=y
+CONFIG_SOC_PNX8550=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+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_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 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 is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+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
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# 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_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 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 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_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
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_MON=y
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
new file mode 100644
index 0000000..deb24c2
--- /dev/null
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -0,0 +1,1251 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:53 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+CONFIG_PNX8550_V2PCI=y
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_PNX8550=y
+CONFIG_SOC_PNX8550=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_ADVANCED=y
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_LLDSCD is not set
+# CONFIG_CPU_HAS_WB is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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_TUNNEL 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_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+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_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=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
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=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_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK 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
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+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
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# 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_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 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 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+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=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_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
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB 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_SENSORS_EEPROM is not set
+# 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_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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 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_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D 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
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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_ONETOUCH is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_MON=y
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY 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 is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index b6568e42..741a9a9 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6
-# Mon Aug  8 11:49:54 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:56 2005
 #
 CONFIG_MIPS=y
 
@@ -17,6 +17,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
 # CONFIG_SYSVIPC is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
@@ -25,6 +26,7 @@
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -74,6 +76,7 @@
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
 # CONFIG_MOMENCO_OCELOT_3 is not set
@@ -91,6 +94,7 @@
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
 # CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
 # CONFIG_SIBYTE_SWARM is not set
 # CONFIG_SIBYTE_SENTOSA is not set
 # CONFIG_SIBYTE_RHONE is not set
@@ -105,7 +109,6 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_COHERENT=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_I8259=y
@@ -119,7 +122,7 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R1=y
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
 # CONFIG_CPU_MIPS64_R2 is not set
@@ -127,7 +130,7 @@
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
 # CONFIG_CPU_R4300 is not set
-CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
@@ -138,9 +141,11 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
@@ -151,15 +156,18 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -214,8 +222,8 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
@@ -232,9 +240,15 @@
 #
 # Network testing
 #
+# CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
 
 #
 # Device Drivers
@@ -248,6 +262,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -265,13 +284,12 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -291,6 +309,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -331,6 +350,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=y
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -470,7 +504,6 @@
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -481,12 +514,17 @@
 # Hardware Monitoring support
 #
 # CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
 
 #
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -532,7 +570,6 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
 
 #
 # SN Devices
@@ -547,10 +584,6 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -559,6 +592,7 @@
 # CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -576,11 +610,13 @@
 #
 # Pseudo filesystems
 #
-# CONFIG_PROC_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
 # CONFIG_SYSFS is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -634,12 +670,35 @@
 # Security options
 #
 # CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -649,7 +708,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
new file mode 100644
index 0000000..2bc61ca
--- /dev/null
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -0,0 +1,1259 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:26:59 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+# CONFIG_KOBJECT_UEVENT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_TOSHIBA_RBTX4938=y
+
+#
+# Multiplex Pin Select
+#
+CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61=y
+# CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND is not set
+# CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+CONFIG_TOSHIBA_BOARDS=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+CONFIG_CPU_TX49XX=y
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_TX49XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
+CONFIG_CPU_ADVANCED=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL 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_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# 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
+
+#
+# Disk-On-Chip Device Drivers
+#
+# 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 is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# 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_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=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_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 is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=y
+# CONFIG_SEEQ8005 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_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# 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
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
+# CONFIG_AIRO is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+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=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_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
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+# CONFIG_FB_ATY_GENERIC_LCD is not set
+# CONFIG_FB_ATY_XL_INIT is not set
+# CONFIG_FB_ATY_GX is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_CYBLA is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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 is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+CONFIG_USB_YEALINK=m
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# 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_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 17d4fce..988a058 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:09 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:03 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,11 +11,13 @@
 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_POSIX_MQUEUE=y
@@ -26,14 +25,17 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +45,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -58,43 +61,73 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 CONFIG_SNI_RM200_PCI=y
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_I8259=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_ARC32=y
 CONFIG_BOOT_ELF32=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -106,8 +139,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -123,24 +158,49 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
 #
+CONFIG_HW_HAS_EISA=y
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
 CONFIG_ISA=y
 # CONFIG_EISA is not set
 CONFIG_MMU=y
@@ -151,11 +211,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-CONFIG_PCMCIA_PROBE=y
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -168,6 +223,281 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# 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_TUNNEL=m
+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_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_DCCP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+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_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=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+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
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_NET_CLS_IND is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_BAYCOM_PAR is not set
+# CONFIG_BAYCOM_EPP is not set
+# CONFIG_YAM is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -176,7 +506,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -188,11 +523,11 @@
 #
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
 CONFIG_PARPORT_SERIAL=m
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
 CONFIG_PARPORT_1284=y
 
 #
@@ -204,7 +539,6 @@
 # Block devices
 #
 CONFIG_BLK_DEV_FD=m
-# CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE=m
 CONFIG_PARIDE_PARPORT=m
 
@@ -249,7 +583,6 @@
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -272,6 +605,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -284,6 +618,7 @@
 CONFIG_BLK_DEV_SR=m
 CONFIG_BLK_DEV_SR_VENDOR=y
 # CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -297,17 +632,16 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
@@ -318,13 +652,9 @@
 CONFIG_MEGARAID_MM=m
 CONFIG_MEGARAID_MAILBOX=m
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
 # CONFIG_SCSI_IPS is not set
@@ -344,7 +674,6 @@
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -353,11 +682,12 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -384,11 +714,15 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -401,266 +735,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=m
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=m
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-CONFIG_IP_TCPDIAG_IPV6=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_PHYSDEV=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-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_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=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_PHYSDEV=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-CONFIG_IP6_NF_RAW=m
-
-#
-# DECnet: Netfilter Configuration
-#
-CONFIG_DECNET_NF_GRABULATOR=m
-
-#
-# Bridge: Netfilter Configuration
-#
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-# CONFIG_BRIDGE_EBT_ULOG is not set
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-CONFIG_BRIDGE=m
-# CONFIG_VLAN_8021Q is not set
-CONFIG_DECNET=m
-# CONFIG_DECNET_ROUTER 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# 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
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-# CONFIG_NET_CLS_IND is not set
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_ACT is not set
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-CONFIG_HAMRADIO=y
-
-#
-# Packet Radio protocols
-#
-CONFIG_AX25=m
-CONFIG_AX25_DAMA_SLAVE=y
-CONFIG_NETROM=m
-CONFIG_ROSE=m
-
-#
-# AX.25 network device drivers
-#
-CONFIG_MKISS=m
-CONFIG_6PACK=m
-CONFIG_BPQETHER=m
-# CONFIG_DMASCC is not set
-# CONFIG_SCC is not set
-# CONFIG_BAYCOM_SER_FDX is not set
-# CONFIG_BAYCOM_SER_HDX is not set
-# CONFIG_BAYCOM_PAR is not set
-# CONFIG_BAYCOM_EPP is not set
-# CONFIG_YAM is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-CONFIG_ETHERTAP=m
 
 #
 # ARCnet devices
@@ -668,6 +749,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -675,7 +771,6 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 
@@ -696,7 +791,6 @@
 # CONFIG_LP486E is not set
 # CONFIG_ETH16I is not set
 CONFIG_NE2000=m
-# CONFIG_ZNET is not set
 # CONFIG_SEEQ8005 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
@@ -733,13 +827,17 @@
 # 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_SK98LIN is not set
 CONFIG_VIA_VELOCITY=m
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -752,6 +850,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -765,6 +865,8 @@
 # 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
@@ -794,20 +896,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_PARKBD=m
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -828,6 +916,18 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_PARKBD=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -844,13 +944,13 @@
 # CONFIG_SERIAL_8250_MANY_PORTS is not set
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_MULTIPORT=y
 CONFIG_SERIAL_8250_RSA=y
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=m
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -881,6 +981,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -891,15 +996,26 @@
 CONFIG_W1=m
 CONFIG_W1_MATROX=m
 CONFIG_W1_DS9490=m
-CONFIG_W1_DS9490_BRIDGE=m
+# CONFIG_W1_DS9490_BRIDGE is not set
 CONFIG_W1_THERM=m
 CONFIG_W1_SMEM=m
+# CONFIG_W1_DS2433 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
 
 #
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -920,7 +1036,6 @@
 CONFIG_VGA_CONSOLE=y
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -930,6 +1045,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -940,8 +1057,6 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -949,7 +1064,10 @@
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
 
@@ -965,11 +1083,10 @@
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
+# CONFIG_USB_STORAGE_USBAT is not set
 CONFIG_USB_STORAGE_SDDR09=y
 CONFIG_USB_STORAGE_SDDR55=y
 CONFIG_USB_STORAGE_JUMPSHOT=y
@@ -992,12 +1109,17 @@
 CONFIG_USB_MOUSE=m
 CONFIG_USB_AIPTEK=m
 CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
 CONFIG_USB_KBTAB=m
 CONFIG_USB_POWERMATE=m
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 CONFIG_USB_EGALAX=m
+CONFIG_USB_YEALINK=m
 CONFIG_USB_XPAD=m
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -1022,30 +1144,15 @@
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_USBNET=m
-
-#
-# USB Host-to-Host Cables
-#
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_GENESYS=y
-CONFIG_USB_NET1080=y
-CONFIG_USB_PL2301=y
-CONFIG_USB_KC2190=y
-
-#
-# Intelligent USB Devices/Gadgets
-#
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_ZAURUS=y
-CONFIG_USB_CDCETHER=y
-
-#
-# USB Network Adapters
-#
-CONFIG_USB_AX8817X=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -1057,9 +1164,11 @@
 #
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
 CONFIG_USB_SERIAL_BELKIN=m
 CONFIG_USB_SERIAL_WHITEHEAT=m
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
 CONFIG_USB_SERIAL_CYPRESS_M8=m
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
@@ -1088,6 +1197,7 @@
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
 # CONFIG_USB_SERIAL_TI is not set
@@ -1110,10 +1220,13 @@
 CONFIG_USB_PHIDGETKIT=m
 CONFIG_USB_PHIDGETSERVO=m
 # CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_SISUSBVGA=m
+# CONFIG_USB_SISUSBVGA_CON is not set
+CONFIG_USB_LD=m
 CONFIG_USB_TEST=m
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -1132,10 +1245,15 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -1152,17 +1270,20 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=m
 CONFIG_XFS_SECURITY=y
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 CONFIG_MINIX_FS=m
 CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -1192,12 +1313,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1224,15 +1343,18 @@
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1256,6 +1378,7 @@
 CONFIG_CODA_FS_OLD_API=y
 CONFIG_AFS_FS=m
 CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1329,7 +1452,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -1352,6 +1477,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1360,13 +1486,13 @@
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
-CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -1376,9 +1502,12 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 1dc935f3..4365d9c 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:10 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:05 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,30 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,32 +61,49 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-CONFIG_SIBYTE_SB1xxx_SOC=y
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
 CONFIG_SIBYTE_SWARM=y
 # CONFIG_SIBYTE_SENTOSA is not set
 # CONFIG_SIBYTE_RHONE is not set
@@ -91,9 +112,12 @@
 # CONFIG_SIBYTE_LITTLESUR is not set
 # CONFIG_SIBYTE_CRHINE is not set
 # CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SIBYTE_UNKNOWN is not set
-CONFIG_SIBYTE_BOARD=y
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_SIBYTE_SB1250=y
+CONFIG_SIBYTE_SB1xxx_SOC=y
 CONFIG_CPU_SB1_PASS_1=y
 # CONFIG_CPU_SB1_PASS_2_1250 is not set
 # CONFIG_CPU_SB1_PASS_2_2 is not set
@@ -102,18 +126,20 @@
 # CONFIG_CPU_SB1_PASS_3 is not set
 CONFIG_SIBYTE_HAS_LDT=y
 # CONFIG_SIMULATION is not set
+# CONFIG_CONFIG_SB1_CEX_ALWAYS_FATAL is not set
+# CONFIG_CONFIG_SB1_CERR_STALL is not set
 CONFIG_SIBYTE_CFE=y
 # CONFIG_SIBYTE_CFE_CONSOLE is not set
 # CONFIG_SIBYTE_BUS_WATCHER is not set
 # CONFIG_SIBYTE_SB1250_PROF is not set
 # CONFIG_SIBYTE_TBPROF is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_COHERENT=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_BOOT_ELF32=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -121,8 +147,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -138,22 +166,46 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 CONFIG_CPU_SB1=y
+CONFIG_SYS_HAS_CPU_SB1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_SIBYTE_DMA_PAGEOPS is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 CONFIG_SB1_PASS_1_WORKAROUNDS=y
-# CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
-# CONFIG_HIGHMEM is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_SMP=y
 CONFIG_NR_CPUS=2
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -161,7 +213,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
@@ -170,10 +221,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -183,7 +230,86 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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=y
+CONFIG_IP_PNP_BOOTP=y
+# 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
 
 #
 # Device Drivers
@@ -194,7 +320,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -213,7 +344,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -226,8 +356,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=9220
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -263,7 +391,7 @@
 #
 CONFIG_IDE_GENERIC=y
 # CONFIG_BLK_DEV_IDEPCI is not set
-CONFIG_BLK_DEV_IDE_SWARM=y
+# CONFIG_BLK_DEV_IDE_SWARM is not set
 # CONFIG_IDE_ARM is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
@@ -272,6 +400,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -282,6 +411,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -294,78 +424,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -373,6 +438,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -399,12 +479,16 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 CONFIG_NET_SB1250_MAC=y
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -417,6 +501,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -428,6 +514,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -445,25 +533,15 @@
 # CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 CONFIG_SERIO=y
 # CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
 # CONFIG_SERIO_LIBPS2 is not set
 CONFIG_SERIO_RAW=m
-
-#
-# Input Device Drivers
-#
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -472,11 +550,13 @@
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
 # CONFIG_STALDRV is not set
 CONFIG_SIBYTE_SB1250_DUART=y
 CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
@@ -489,6 +569,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -515,6 +596,11 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -525,10 +611,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -542,7 +638,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -552,13 +647,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -576,12 +667,17 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 CONFIG_FS_MBCACHE=y
@@ -591,10 +687,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -615,11 +713,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -643,13 +740,14 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -658,6 +756,7 @@
 # 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
@@ -678,7 +777,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 # CONFIG_SB1XXX_CORELIS is not set
@@ -695,27 +796,28 @@
 #
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
@@ -726,9 +828,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index dd07e86..d835f6d 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:10 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:07 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,22 +11,26 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -39,6 +40,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -48,40 +50,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 CONFIG_MIPS_SEAD=y
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_BOARDS_GEN=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
@@ -89,8 +120,10 @@
 #
 # CPU selection
 #
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -106,15 +139,42 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -128,10 +188,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -143,6 +199,11 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+# CONFIG_NET is not set
+
+#
 # Device Drivers
 #
 
@@ -154,6 +215,10 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -170,7 +235,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -178,11 +242,8 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=18432
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -200,6 +261,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=y
 # CONFIG_SCSI is not set
 
 #
@@ -210,6 +272,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -220,9 +283,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-# CONFIG_NET is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 
@@ -238,47 +300,18 @@
 #
 # Input device support
 #
-CONFIG_INPUT=y
+# CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-CONFIG_INPUT_MOUSEDEV=y
-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
-
-#
-# Input I/O drivers
-#
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -294,7 +327,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 
@@ -315,10 +348,13 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -329,10 +365,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -347,13 +393,6 @@
 # CONFIG_FB is not set
 
 #
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
 # Sound
 #
 # CONFIG_SOUND is not set
@@ -365,10 +404,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -381,28 +416,31 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD 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_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
 
 #
 # CD-ROM/DVD Filesystems
@@ -423,10 +461,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -448,8 +486,18 @@
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
 
 #
 # Native Language Support
@@ -464,15 +512,16 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -488,7 +537,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index c9d3f83..bf60a17 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:12 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:10 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,55 +59,87 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_IBM_WORKPAD is not set
-CONFIG_TANBAC_TB0226=y
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+CONFIG_TANBAC_TB022X=y
+CONFIG_TANBAC_TB0226=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -120,19 +155,44 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
 #
 CONFIG_HW_HAS_PCI=y
-# CONFIG_PCI is not set
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_MMU=y
 
 #
@@ -141,12 +201,9 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -156,6 +213,87 @@
 CONFIG_TRAD_SIGNALS=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=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+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_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -167,6 +305,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -183,19 +326,21 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -209,33 +354,12 @@
 #
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=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=y
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -245,15 +369,15 @@
 CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_ST is not set
 # CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
 #
@@ -262,11 +386,42 @@
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -277,131 +432,132 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=m
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-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_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 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
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
 
 #
 # Ethernet (1000 Mbit)
 #
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
+# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW2200 is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
+# CONFIG_FDDI is not set
+# 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
@@ -421,28 +577,13 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -452,6 +593,12 @@
 # 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
@@ -462,16 +609,16 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -489,14 +636,22 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_TANBAC_TB0219 is not set
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -507,10 +662,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -523,48 +688,147 @@
 #
 # Graphics support
 #
-CONFIG_FB=y
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND is not set
 
 #
 # USB support
 #
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH 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_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM 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
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_MON=y
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
 
 #
 # USB Gadget Support
@@ -582,39 +846,41 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
+# CONFIG_ISO9660_FS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -623,13 +889,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -653,16 +916,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -673,6 +939,7 @@
 # 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
@@ -732,9 +999,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+CONFIG_CMDLINE="mem=32M console=ttyVR0,115200"
 
 #
 # Security options
@@ -746,7 +1015,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -756,9 +1049,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
+CONFIG_CRC16=m
+CONFIG_CRC32=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index 2cb6691..ac8b64e 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:12 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:13 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,58 +59,87 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
-# CONFIG_CASIO_E55 is not set
-# CONFIG_IBM_WORKPAD is not set
-# CONFIG_TANBAC_TB0226 is not set
-CONFIG_TANBAC_TB0229=y
-CONFIG_TANBAC_TB0219=y
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_PCI_VR41XX=y
-# CONFIG_VRC4173 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+CONFIG_TANBAC_TB022X=y
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -123,12 +155,36 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -136,8 +192,7 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_MMU=y
 
 #
@@ -146,10 +201,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -162,6 +213,88 @@
 CONFIG_TRAD_SIGNALS=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=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+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_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -170,7 +303,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -189,7 +327,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -199,11 +336,11 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
 # 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=4096
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -226,6 +363,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -236,6 +374,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -248,83 +387,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=m
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-# CONFIG_NET_IPGRE_BROADCAST is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-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_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -332,6 +401,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -346,7 +430,7 @@
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
+# CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
@@ -358,7 +442,11 @@
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -375,14 +463,19 @@
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE 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_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -395,6 +488,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -416,6 +511,8 @@
 CONFIG_SLIP_MODE_SLIP6=y
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -435,29 +532,13 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -467,6 +548,12 @@
 # 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
@@ -477,16 +564,16 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -505,14 +592,21 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
+CONFIG_TANBAC_TB0219=y
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -523,10 +617,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -546,7 +650,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -556,13 +659,122 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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 is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_USB_MON=y
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
 
 #
 # USB Gadget Support
@@ -580,10 +792,15 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=m
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -597,18 +814,22 @@
 # CONFIG_JFS_SECURITY is not set
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
+# CONFIG_FS_POSIX_ACL is not set
 CONFIG_XFS_FS=y
-# CONFIG_XFS_RT is not set
+CONFIG_XFS_EXPORT=y
 CONFIG_XFS_QUOTA=y
 # CONFIG_XFS_SECURITY is not set
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -635,13 +856,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -665,16 +883,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -685,6 +906,7 @@
 # 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
@@ -744,9 +966,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="mem=64M console=ttyS0,38400 ip=bootp root=/dev/nfs"
+CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
 
 #
 # Security options
@@ -758,7 +982,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -768,9 +1016,8 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 17b9f2f..9534483 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-mm1
-# Thu Sep  1 22:58:34 2005
+# Linux kernel version: 2.6.14-rc5-mm1
+# Tue Oct 25 00:20:22 2005
 #
 CONFIG_MIPS=y
 
@@ -19,6 +19,7 @@
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
+CONFIG_SWAP_PREFETCH=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
@@ -55,25 +56,67 @@
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
 
 #
 # Machine selection
 #
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_CASIO_E55 is not set
 # CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_CMBVR4133 is not set
 CONFIG_TANBAC_TB022X=y
 # CONFIG_TANBAC_TB0226 is not set
 CONFIG_TANBAC_TB0287=y
@@ -81,48 +124,23 @@
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
 # CONFIG_VRC4173 is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_QEMU is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -138,12 +156,25 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -152,6 +183,9 @@
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -262,7 +296,6 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NETFILTER_NETLINK is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -280,6 +313,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -296,7 +334,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -312,6 +349,7 @@
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -321,6 +359,11 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -410,13 +453,20 @@
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI Transport Layers
+#
+# CONFIG_SAS_CLASS is not set
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
@@ -425,12 +475,10 @@
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
@@ -462,6 +510,7 @@
 # CONFIG_FUSION is not set
 # CONFIG_FUSION_SPI is not set
 # CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -529,6 +578,7 @@
 CONFIG_MII=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
 
 #
@@ -572,6 +622,7 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_HOSTAP is not set
 
 #
 # Wan interfaces
@@ -682,6 +733,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -770,12 +822,15 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_BLUETOOTH_TTY is not set
 # 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
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -891,6 +946,11 @@
 #
 
 #
+# EDAC - error detection and reporting (RAS)
+#
+# CONFIG_EDAC is not set
+
+#
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
@@ -901,20 +961,22 @@
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
 # CONFIG_REISER4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 CONFIG_XFS_FS=y
-# CONFIG_XFS_RT is not set
 CONFIG_XFS_QUOTA=y
 # CONFIG_XFS_SECURITY is not set
 CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=m
@@ -948,8 +1010,8 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
 # CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1004,6 +1066,11 @@
 # CONFIG_NLS is not set
 
 #
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
@@ -1036,6 +1103,3 @@
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ISA_DMA_API=y
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 16e07fc..ab13621 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:12 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:16 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,24 +11,29 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,56 +59,84 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-CONFIG_MACH_VR41XX=y
-# CONFIG_NEC_CMBVR4133 is not set
-# CONFIG_CASIO_E55 is not set
-CONFIG_IBM_WORKPAD=y
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0229 is not set
-# CONFIG_VICTOR_MPC30X is not set
-# CONFIG_ZAO_CAPCELLA is not set
-CONFIG_VRC4171=y
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+CONFIG_IBM_WORKPAD=y
+# CONFIG_TANBAC_TB022X is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 CONFIG_CPU_VR41XX=y
@@ -121,12 +152,36 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 
 #
@@ -138,11 +193,17 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
 
 #
 # PC-card bridges
 #
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
 CONFIG_PCMCIA_PROBE=y
 
 #
@@ -157,6 +218,78 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -165,7 +298,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -185,18 +323,13 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # IO Schedulers
@@ -219,6 +352,7 @@
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -237,6 +371,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -252,6 +387,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -262,76 +398,13 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -339,12 +412,26 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
@@ -373,6 +460,19 @@
 # CONFIG_NET_RADIO is not set
 
 #
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -380,6 +480,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -409,18 +511,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -430,6 +520,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -440,16 +540,15 @@
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -484,10 +583,19 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_GPIO_VR41XX is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -498,10 +606,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -522,7 +640,6 @@
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -536,10 +653,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -552,7 +665,10 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
@@ -561,6 +677,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
 CONFIG_FS_MBCACHE=y
@@ -570,10 +687,12 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -594,12 +713,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -630,6 +747,7 @@
 # CONFIG_NFSD_TCP is not set
 CONFIG_LOCKD=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -638,6 +756,7 @@
 # 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
@@ -658,9 +777,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
 
 #
 # Security options
@@ -672,7 +793,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -682,7 +827,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 6d22907..5b0b7f3 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:49:13 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:27:18 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,25 +11,31 @@
 # CONFIG_EXPERIMENTAL is not set
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -42,6 +45,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -56,34 +60,68 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-CONFIG_PMC_YOSEMITE=y
-# CONFIG_HYPERTRANSPORT is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+CONFIG_PMC_YOSEMITE=y
+# CONFIG_QEMU is not set
 # CONFIG_SGI_IP22 is not set
-# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_HYPERTRANSPORT is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_DMA_COHERENT=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_IRQ_CPU_RM7K=y
 CONFIG_IRQ_CPU_RM9K=y
@@ -93,8 +131,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -110,20 +150,43 @@
 # CONFIG_CPU_RM7000 is not set
 CONFIG_CPU_RM9000=y
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_HIGHMEM=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -131,7 +194,7 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_MMU=y
 
 #
@@ -140,10 +203,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -155,6 +214,69 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE 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_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_NETFILTER 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_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
 # Device Drivers
 #
 
@@ -163,10 +285,15 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -183,7 +310,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -193,7 +319,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -216,6 +341,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 # CONFIG_SCSI is not set
 
 #
@@ -226,6 +352,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -238,59 +365,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=m
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=m
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE 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_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# 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
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -303,6 +379,21 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -327,13 +418,16 @@
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 CONFIG_TITAN_GE=y
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -346,6 +440,8 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
+# CONFIG_IPW_DEBUG is not set
+CONFIG_IPW2200=m
 
 #
 # Wan interfaces
@@ -354,6 +450,8 @@
 # CONFIG_FDDI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -371,20 +469,10 @@
 # CONFIG_INPUT is not set
 
 #
-# Userland interfaces
+# Hardware I/O ports
 #
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -405,6 +493,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -432,6 +521,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -442,10 +535,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -459,7 +562,6 @@
 # Graphics support
 #
 # CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -469,13 +571,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -493,6 +591,10 @@
 # CONFIG_INFINIBAND is not set
 
 #
+# SN Devices
+#
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
@@ -500,13 +602,16 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -527,11 +632,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -552,7 +656,7 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
@@ -573,8 +677,11 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -599,7 +706,31 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -609,7 +740,8 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CRC16=m
+CONFIG_CRC32=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/ddb5xxx/Kconfig b/arch/mips/ddb5xxx/Kconfig
new file mode 100644
index 0000000..e9b5de4
--- /dev/null
+++ b/arch/mips/ddb5xxx/Kconfig
@@ -0,0 +1,4 @@
+config DDB5477_BUS_FREQUENCY
+	int "bus frequency (in kHZ, 0 for auto-detect)"
+	depends on DDB5477
+	default 0
diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
index 68c127c..8743ffc 100644
--- a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
+++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
@@ -209,14 +209,13 @@
 #define nile4_irq_shutdown nile4_disable_irq
 
 static hw_irq_controller nile4_irq_controller = {
-    "nile4",
-    nile4_irq_startup,
-    nile4_irq_shutdown,
-    nile4_enable_irq,
-    nile4_disable_irq,
-    nile4_ack_irq,
-    nile4_irq_end,
-    NULL
+	.typename = "nile4",
+	.startup = nile4_irq_startup,
+	.shutdown = nile4_irq_shutdown,
+	.enable = nile4_enable_irq,
+	.disable = nile4_disable_irq,
+	.ack = nile4_ack_irq,
+	.end = nile4_irq_end,
 };
 
 void nile4_irq_setup(u32 base) {
diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c
index a73a597..11535be 100644
--- a/arch/mips/ddb5xxx/ddb5074/setup.c
+++ b/arch/mips/ddb5xxx/ddb5074/setup.c
@@ -85,7 +85,7 @@
 
 
 
-static void __init ddb5074_setup(void)
+void __init plat_setup(void)
 {
 	set_io_port_base(NILE4_PCI_IO_BASE);
 	isa_slot_offset = NILE4_PCI_MEM_BASE;
@@ -106,8 +106,6 @@
 	panic_timeout = 180;
 }
 
-early_initcall(ddb5074_setup);
-
 #define USE_NILE4_SERIAL	0
 
 #if USE_NILE4_SERIAL
diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c
index 71531f8..f4e480a 100644
--- a/arch/mips/ddb5xxx/ddb5476/setup.c
+++ b/arch/mips/ddb5xxx/ddb5476/setup.c
@@ -124,7 +124,7 @@
 
 static void ddb5476_board_init(void);
 
-static void __init ddb5476_setup(void)
+void __init plat_setup(void)
 {
 	set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
 
@@ -158,8 +158,6 @@
 	ddb5476_board_init();
 }
 
-early_initcall(ddb5476_setup);
-
 /*
  * We don't trust bios.  We essentially does hardware re-initialization
  * as complete as possible, as far as we know we can safely do.
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
index a77682b..f66fe5b 100644
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -53,14 +53,13 @@
 }
 
 static hw_irq_controller vrc5476_irq_controller = {
-	"vrc5476",
-	vrc5476_irq_startup,
-	vrc5476_irq_shutdown,
-	vrc5476_irq_enable,
-	vrc5476_irq_disable,
-	vrc5476_irq_ack,
-	vrc5476_irq_end,
-	NULL				/* no affinity stuff for UP */
+	.typename = "vrc5476",
+	.startup = vrc5476_irq_startup,
+	.shutdown = vrc5476_irq_shutdown,
+	.enable = vrc5476_irq_enable,
+	.disable = vrc5476_irq_disable,
+	.ack = vrc5476_irq_ack,
+	.end = vrc5476_irq_end
 };
 
 void __init
diff --git a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
index 0d5e706..5fcd5f0 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq_5477.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
@@ -90,14 +90,13 @@
 }
 
 hw_irq_controller vrc5477_irq_controller = {
-	"vrc5477_irq",
-	vrc5477_irq_startup,
-	vrc5477_irq_shutdown,
-	vrc5477_irq_enable,
-	vrc5477_irq_disable,
-	vrc5477_irq_ack,
-	vrc5477_irq_end,
-	NULL			/* no affinity stuff for UP */
+	.typename = "vrc5477_irq",
+	.startup = vrc5477_irq_startup,
+	.shutdown = vrc5477_irq_shutdown,
+	.enable = vrc5477_irq_enable,
+	.disable = vrc5477_irq_disable,
+	.ack = vrc5477_irq_ack,
+	.end = vrc5477_irq_end
 };
 
 void __init vrc5477_irq_init(u32 irq_base)
diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c
index d62f5a7..8116335 100644
--- a/arch/mips/ddb5xxx/ddb5477/setup.c
+++ b/arch/mips/ddb5xxx/ddb5477/setup.c
@@ -170,7 +170,7 @@
 extern struct pci_controller ddb5477_ext_controller;
 extern struct pci_controller ddb5477_io_controller;
 
-static int  ddb5477_setup(void)
+void __init plat_setup(void)
 {
 	/* initialize board - we don't trust the loader */
         ddb5477_board_init();
@@ -193,12 +193,8 @@
 
 	register_pci_controller (&ddb5477_ext_controller);
 	register_pci_controller (&ddb5477_io_controller);
-
-	return 0;
 }
 
-early_initcall(ddb5477_setup);
-
 static void __init ddb5477_board_init(void)
 {
 	/* ----------- setup PDARs ------------ */
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
index 688757a..ed181fd 100644
--- a/arch/mips/dec/Makefile
+++ b/arch/mips/dec/Makefile
@@ -2,8 +2,8 @@
 # Makefile for the DECstation family specific parts of the kernel
 #
 
-obj-y		:= ecc-berr.o int-handler.o ioasic-irq.o kn02-irq.o reset.o \
-		   setup.o time.o
+obj-y		:= ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
+		   kn02-irq.o kn02xa-berr.o reset.o setup.o time.o
 
 obj-$(CONFIG_PROM_CONSOLE)	+= promcon.o
 obj-$(CONFIG_CPU_HAS_WB)	+= wbflush.o
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
index 6dbce92..cc24c5e 100644
--- a/arch/mips/dec/ecc-berr.c
+++ b/arch/mips/dec/ecc-berr.c
@@ -6,7 +6,7 @@
  *	5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
  *	5900/260 (KN05) systems.
  *
- *	Copyright (c) 2003  Maciej W. Rozycki
+ *	Copyright (c) 2003, 2005  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -15,6 +15,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
@@ -57,7 +58,7 @@
 
 	const char *kind, *agent, *cycle, *event;
 	const char *status = "", *xbit = "", *fmt = "";
-	dma_addr_t address;
+	unsigned long address;
 	u16 syn = 0, sngl;
 
 	int i = 0;
@@ -66,7 +67,7 @@
 	u32 chksyn = *kn0x_chksyn;
 	int action = MIPS_BE_FATAL;
 
-	/* For non-ECC ack ASAP, so any subsequent errors get caught. */
+	/* For non-ECC ack ASAP, so that any subsequent errors get caught. */
 	if ((erraddr & (KN0X_EAR_VALID | KN0X_EAR_ECCERR)) == KN0X_EAR_VALID)
 		dec_ecc_be_ack();
 
@@ -74,7 +75,7 @@
 
 	if (!(erraddr & KN0X_EAR_VALID)) {
 		/* No idea what happened. */
-		printk(KERN_ALERT "Unidentified bus error %s.\n", kind);
+		printk(KERN_ALERT "Unidentified bus error %s\n", kind);
 		return action;
 	}
 
@@ -126,7 +127,7 @@
 			/* Ack now, no rewrite will happen. */
 			dec_ecc_be_ack();
 
-			fmt = KERN_ALERT "%s" "invalid.\n";
+			fmt = KERN_ALERT "%s" "invalid\n";
 		} else {
 			sngl = syn & KN0X_ESR_SNGLO;
 			syn &= KN0X_ESR_SYNLO;
@@ -144,7 +145,8 @@
 			} else if (!sngl) {
 				status = dbestr;
 			} else {
-				volatile u32 *ptr = (void *)KSEG1ADDR(address);
+				volatile u32 *ptr =
+					(void *)CKSEG1ADDR(address);
 
 				*ptr = *ptr;		/* Rewrite. */
 				iob();
@@ -160,12 +162,12 @@
 				if (syn == 0x01) {
 					fmt = KERN_ALERT "%s"
 					      "%#04x -- %s bit error "
-					      "at check bit C%s.\n";
+					      "at check bit C%s\n";
 					xbit = "X";
 				} else {
 					fmt = KERN_ALERT "%s"
 					      "%#04x -- %s bit error "
-					      "at check bit C%s%u.\n";
+					      "at check bit C%s%u\n";
 				}
 				i = syn >> 2;
 			} else {
@@ -175,16 +177,16 @@
 				if (i < 32)
 					fmt = KERN_ALERT "%s"
 					      "%#04x -- %s bit error "
-					      "at data bit D%s%u.\n";
+					      "at data bit D%s%u\n";
 				else
 					fmt = KERN_ALERT "%s"
-					      "%#04x -- %s bit error.\n";
+					      "%#04x -- %s bit error\n";
 			}
 		}
 	}
 
 	if (action != MIPS_BE_FIXUP)
-		printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx.\n",
+		printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
 			kind, agent, cycle, event, address);
 
 	if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR)
@@ -203,11 +205,11 @@
 	int action = dec_ecc_be_backend(regs, 0, 1);
 
 	if (action == MIPS_BE_DISCARD)
-		return IRQ_NONE;
+		return IRQ_HANDLED;
 
 	/*
-	 * FIXME: Find affected processes and kill them, otherwise we
-	 * must die.
+	 * FIXME: Find the affected processes and kill them, otherwise
+	 * we must die.
 	 *
 	 * The interrupt is asynchronously delivered thus EPC and RA
 	 * may be irrelevant, but are printed for a reference.
@@ -225,16 +227,16 @@
  */
 static inline void dec_kn02_be_init(void)
 {
-	volatile u32 *csr = (void *)KN02_CSR_BASE;
+	volatile u32 *csr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR);
 	unsigned long flags;
 
-	kn0x_erraddr = (void *)(KN02_SLOT_BASE + KN02_ERRADDR);
-	kn0x_chksyn = (void *)(KN02_SLOT_BASE + KN02_CHKSYN);
+	kn0x_erraddr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_ERRADDR);
+	kn0x_chksyn = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CHKSYN);
 
 	spin_lock_irqsave(&kn02_lock, flags);
 
 	/* Preset write-only bits of the Control Register cache. */
-	cached_kn02_csr = *csr | KN03_CSR_LEDS;
+	cached_kn02_csr = *csr | KN02_CSR_LEDS;
 
 	/* Set normal ECC detection and generation. */
 	cached_kn02_csr &= ~(KN02_CSR_DIAGCHK | KN02_CSR_DIAGGEN);
@@ -248,11 +250,11 @@
 
 static inline void dec_kn03_be_init(void)
 {
-	volatile u32 *mcr = (void *)(KN03_SLOT_BASE + IOASIC_MCR);
-	volatile u32 *mbcs = (void *)(KN03_SLOT_BASE + KN05_MB_CSR);
+	volatile u32 *mcr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_MCR);
+	volatile u32 *mbcs = (void *)CKSEG1ADDR(KN4K_SLOT_BASE + KN4K_MB_CSR);
 
-	kn0x_erraddr = (void *)(KN03_SLOT_BASE + IOASIC_ERRADDR);
-	kn0x_chksyn = (void *)(KN03_SLOT_BASE + IOASIC_CHKSYN);
+	kn0x_erraddr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_ERRADDR);
+	kn0x_chksyn = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_CHKSYN);
 
 	/*
 	 * Set normal ECC detection and generation, enable ECC correction.
@@ -264,7 +266,7 @@
 	*mcr = (*mcr & ~(KN03_MCR_DIAGCHK | KN03_MCR_DIAGGEN)) |
 	       KN03_MCR_CORRECT;
 	if (current_cpu_data.cputype == CPU_R4400SC)
-		*mbcs |= KN05_MB_CSR_EE;
+		*mbcs |= KN4K_MB_CSR_EE;
 	fast_iob();
 }
 
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index c89768d..41fa372 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -2,9 +2,9 @@
  * arch/mips/dec/int-handler.S
  *
  * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
- * Copyright (C) 2000, 2001, 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
  *
- * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * Written by Ralf Baechle and Andreas Busse, modified for DECstation
  * support by Paul Antoine and Harald Koerfgen.
  *
  * completly rewritten:
@@ -14,11 +14,12 @@
  * by Maciej W. Rozycki.
  */
 #include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
+
 #include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic_addrs.h>
@@ -28,11 +29,14 @@
 #include <asm/dec/kn02xa.h>
 #include <asm/dec/kn03.h>
 
+#define KN02_CSR_BASE		CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR)
+#define KN02XA_IOASIC_BASE	CKSEG1ADDR(KN02XA_SLOT_BASE + IOASIC_IOCTL)
+#define KN03_IOASIC_BASE	CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_IOCTL)
 
 		.text
 		.set	noreorder
 /*
- * decstation_handle_int: Interrupt handler for DECStations
+ * decstation_handle_int: Interrupt handler for DECstations
  *
  * We follow the model in the Indy interrupt code by David Miller, where he
  * says: a lot of complication here is taken away because:
@@ -48,7 +52,7 @@
  * 3) Linux only thinks in terms of all IRQs on or all IRQs
  *    off, nothing in between like BSD spl() brain-damage.
  *
- * Furthermore, the IRQs on the DECStations look basically (barring
+ * Furthermore, the IRQs on the DECstations look basically (barring
  * software IRQs which we don't use at all) like...
  *
  * DS2100/3100's, aka kn01, aka Pmax:
@@ -61,7 +65,7 @@
  *             3        Lance Ethernet
  *             4        DZ11 serial
  *             5        RTC
- *             6        Memory Controller
+ *             6        Memory Controller & Video
  *             7        FPU
  *
  * DS5000/200, aka kn02, aka 3max:
diff --git a/arch/mips/dec/kn01-berr.c b/arch/mips/dec/kn01-berr.c
new file mode 100644
index 0000000..b9271db
--- /dev/null
+++ b/arch/mips/dec/kn01-berr.c
@@ -0,0 +1,201 @@
+/*
+ *	linux/arch/mips/dec/kn01-berr.c
+ *
+ *	Bus error event handling code for DECstation/DECsystem 3100
+ *	and 2100 (KN01) systems equipped with parity error detection
+ *	logic.
+ *
+ *	Copyright (c) 2005  Maciej W. Rozycki
+ *
+ *	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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/inst.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+#include <asm/dec/kn01.h>
+
+
+/* CP0 hazard avoidance. */
+#define BARRIER				\
+	__asm__ __volatile__(		\
+		".set	push\n\t"	\
+		".set	noreorder\n\t"	\
+		"nop\n\t"		\
+		".set	pop\n\t")
+
+/*
+ * Bits 7:0 of the Control Register are write-only -- the
+ * corresponding bits of the Status Register have a different
+ * meaning.  Hence we use a cache.  It speeds up things a bit
+ * as well.
+ *
+ * There is no default value -- it has to be initialized.
+ */
+u16 cached_kn01_csr;
+DEFINE_SPINLOCK(kn01_lock);
+
+
+static inline void dec_kn01_be_ack(void)
+{
+	volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
+	unsigned long flags;
+
+	spin_lock_irqsave(&kn01_lock, flags);
+
+	*csr = cached_kn01_csr | KN01_CSR_MEMERR;	/* Clear bus IRQ. */
+	iob();
+
+	spin_unlock_irqrestore(&kn01_lock, flags);
+}
+
+static int dec_kn01_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
+{
+	volatile u32 *kn01_erraddr = (void *)CKSEG1ADDR(KN01_SLOT_BASE +
+							KN01_ERRADDR);
+
+	static const char excstr[] = "exception";
+	static const char intstr[] = "interrupt";
+	static const char cpustr[] = "CPU";
+	static const char mreadstr[] = "memory read";
+	static const char readstr[] = "read";
+	static const char writestr[] = "write";
+	static const char timestr[] = "timeout";
+	static const char paritystr[] = "parity error";
+
+	int data = regs->cp0_cause & 4;
+	unsigned int __user *pc = (unsigned int __user *)regs->cp0_epc +
+				  ((regs->cp0_cause & CAUSEF_BD) != 0);
+	union mips_instruction insn;
+	unsigned long entrylo, offset;
+	long asid, entryhi, vaddr;
+
+	const char *kind, *agent, *cycle, *event;
+	unsigned long address;
+
+	u32 erraddr = *kn01_erraddr;
+	int action = MIPS_BE_FATAL;
+
+	/* Ack ASAP, so that any subsequent errors get caught. */
+	dec_kn01_be_ack();
+
+	kind = invoker ? intstr : excstr;
+
+	agent = cpustr;
+
+	if (invoker)
+		address = erraddr;
+	else {
+		/* Bloody hardware doesn't record the address for reads... */
+		if (data) {
+			/* This never faults. */
+			__get_user(insn.word, pc);
+			vaddr = regs->regs[insn.i_format.rs] +
+				insn.i_format.simmediate;
+		} else
+			vaddr = (long)pc;
+		if (KSEGX(vaddr) == CKSEG0 || KSEGX(vaddr) == CKSEG1)
+			address = CPHYSADDR(vaddr);
+		else {
+			/* Peek at what physical address the CPU used. */
+			asid = read_c0_entryhi();
+			entryhi = asid & (PAGE_SIZE - 1);
+			entryhi |= vaddr & ~(PAGE_SIZE - 1);
+			write_c0_entryhi(entryhi);
+			BARRIER;
+			tlb_probe();
+			/* No need to check for presence. */
+			tlb_read();
+			entrylo = read_c0_entrylo0();
+			write_c0_entryhi(asid);
+			offset = vaddr & (PAGE_SIZE - 1);
+			address = (entrylo & ~(PAGE_SIZE - 1)) | offset;
+		}
+	}
+
+	/* Treat low 256MB as memory, high -- as I/O. */
+	if (address < 0x10000000) {
+		cycle = mreadstr;
+		event = paritystr;
+	} else {
+		cycle = invoker ? writestr : readstr;
+		event = timestr;
+	}
+
+	if (is_fixup)
+		action = MIPS_BE_FIXUP;
+
+	if (action != MIPS_BE_FIXUP)
+		printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
+			kind, agent, cycle, event, address);
+
+	return action;
+}
+
+int dec_kn01_be_handler(struct pt_regs *regs, int is_fixup)
+{
+	return dec_kn01_be_backend(regs, is_fixup, 0);
+}
+
+irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id,
+				    struct pt_regs *regs)
+{
+	volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
+	int action;
+
+	if (!(*csr & KN01_CSR_MEMERR))
+		return IRQ_NONE;		/* Must have been video. */
+
+	action = dec_kn01_be_backend(regs, 0, 1);
+
+	if (action == MIPS_BE_DISCARD)
+		return IRQ_HANDLED;
+
+	/*
+	 * FIXME: Find the affected processes and kill them, otherwise
+	 * we must die.
+	 *
+	 * The interrupt is asynchronously delivered thus EPC and RA
+	 * may be irrelevant, but are printed for a reference.
+	 */
+	printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
+	       regs->cp0_epc, regs->regs[31]);
+	die("Unrecoverable bus error", regs);
+}
+
+
+void __init dec_kn01_be_init(void)
+{
+	volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
+	unsigned long flags;
+
+	spin_lock_irqsave(&kn01_lock, flags);
+
+	/* Preset write-only bits of the Control Register cache. */
+	cached_kn01_csr = *csr;
+	cached_kn01_csr &= KN01_CSR_STATUS | KN01_CSR_PARDIS | KN01_CSR_TXDIS;
+	cached_kn01_csr |= KN01_CSR_LEDS;
+
+	/* Enable parity error detection. */
+	cached_kn01_csr &= ~KN01_CSR_PARDIS;
+	*csr = cached_kn01_csr;
+	iob();
+
+	spin_unlock_irqrestore(&kn01_lock, flags);
+
+	/* Clear any leftover errors from the firmware. */
+	dec_kn01_be_ack();
+}
diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c
index e0bfcd1..898bed5 100644
--- a/arch/mips/dec/kn02-irq.c
+++ b/arch/mips/dec/kn02-irq.c
@@ -4,7 +4,7 @@
  *	DECstation 5000/200 (KN02) Control and Status Register
  *	interrupts.
  *
- *	Copyright (c) 2002, 2003  Maciej W. Rozycki
+ *	Copyright (c) 2002, 2003, 2005  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -37,7 +37,8 @@
 
 static inline void unmask_kn02_irq(unsigned int irq)
 {
-	volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE;
+	volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
+						       KN02_CSR);
 
 	cached_kn02_csr |= (1 << (irq - kn02_irq_base + 16));
 	*csr = cached_kn02_csr;
@@ -45,7 +46,8 @@
 
 static inline void mask_kn02_irq(unsigned int irq)
 {
-	volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE;
+	volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
+						       KN02_CSR);
 
 	cached_kn02_csr &= ~(1 << (irq - kn02_irq_base + 16));
 	*csr = cached_kn02_csr;
@@ -105,13 +107,14 @@
 
 void __init init_kn02_irqs(int base)
 {
-	volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE;
+	volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
+						       KN02_CSR);
 	unsigned long flags;
 	int i;
 
 	/* Mask interrupts. */
 	spin_lock_irqsave(&kn02_lock, flags);
-	cached_kn02_csr &= ~KN03_CSR_IOINTEN;
+	cached_kn02_csr &= ~KN02_CSR_IOINTEN;
 	*csr = cached_kn02_csr;
 	iob();
 	spin_unlock_irqrestore(&kn02_lock, flags);
diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c
new file mode 100644
index 0000000..6cd3f94
--- /dev/null
+++ b/arch/mips/dec/kn02xa-berr.c
@@ -0,0 +1,139 @@
+/*
+ *	linux/arch/mips/dec/kn02xa-berr.c
+ *
+ *	Bus error event handling code for 5000-series systems equipped
+ *	with parity error detection logic, i.e. DECstation/DECsystem
+ *	5000/120, /125, /133 (KN02-BA), 5000/150 (KN04-BA) and Personal
+ *	DECstation/DECsystem 5000/20, /25, /33 (KN02-CA), 5000/50
+ *	(KN04-CA) systems.
+ *
+ *	Copyright (c) 2005  Maciej W. Rozycki
+ *
+ *	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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+#include <asm/dec/kn02ca.h>
+#include <asm/dec/kn02xa.h>
+#include <asm/dec/kn05.h>
+
+static inline void dec_kn02xa_be_ack(void)
+{
+	volatile u32 *mer = (void *)CKSEG1ADDR(KN02XA_MER);
+	volatile u32 *mem_intr = (void *)CKSEG1ADDR(KN02XA_MEM_INTR);
+
+	*mer = KN02CA_MER_INTR;		/* Clear errors; keep the ARC IRQ. */
+	*mem_intr = 0;			/* Any write clears the bus IRQ. */
+	iob();
+}
+
+static int dec_kn02xa_be_backend(struct pt_regs *regs, int is_fixup,
+				 int invoker)
+{
+	volatile u32 *kn02xa_mer = (void *)CKSEG1ADDR(KN02XA_MER);
+	volatile u32 *kn02xa_ear = (void *)CKSEG1ADDR(KN02XA_EAR);
+
+	static const char excstr[] = "exception";
+	static const char intstr[] = "interrupt";
+	static const char cpustr[] = "CPU";
+	static const char mreadstr[] = "memory read";
+	static const char readstr[] = "read";
+	static const char writestr[] = "write";
+	static const char timestr[] = "timeout";
+	static const char paritystr[] = "parity error";
+	static const char lanestat[][4] = { " OK", "BAD" };
+
+	const char *kind, *agent, *cycle, *event;
+	unsigned long address;
+
+	u32 mer = *kn02xa_mer;
+	u32 ear = *kn02xa_ear;
+	int action = MIPS_BE_FATAL;
+
+	/* Ack ASAP, so that any subsequent errors get caught. */
+	dec_kn02xa_be_ack();
+
+	kind = invoker ? intstr : excstr;
+
+	/* No DMA errors? */
+	agent = cpustr;
+
+	address = ear & KN02XA_EAR_ADDRESS;
+
+	/* Low 256MB is decoded as memory, high -- as TC. */
+	if (address < 0x10000000) {
+		cycle = mreadstr;
+		event = paritystr;
+	} else {
+		cycle = invoker ? writestr : readstr;
+		event = timestr;
+	}
+
+	if (is_fixup)
+		action = MIPS_BE_FIXUP;
+
+	if (action != MIPS_BE_FIXUP)
+		printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
+			kind, agent, cycle, event, address);
+
+	if (action != MIPS_BE_FIXUP && address < 0x10000000)
+		printk(KERN_ALERT "  Byte lane status %#3x -- "
+		       "#3: %s, #2: %s, #1: %s, #0: %s\n",
+		       (mer & KN02XA_MER_BYTERR) >> 8,
+		       lanestat[(mer & KN02XA_MER_BYTERR_3) != 0],
+		       lanestat[(mer & KN02XA_MER_BYTERR_2) != 0],
+		       lanestat[(mer & KN02XA_MER_BYTERR_1) != 0],
+		       lanestat[(mer & KN02XA_MER_BYTERR_0) != 0]);
+
+	return action;
+}
+
+int dec_kn02xa_be_handler(struct pt_regs *regs, int is_fixup)
+{
+	return dec_kn02xa_be_backend(regs, is_fixup, 0);
+}
+
+irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id,
+				    struct pt_regs *regs)
+{
+	int action = dec_kn02xa_be_backend(regs, 0, 1);
+
+	if (action == MIPS_BE_DISCARD)
+		return IRQ_HANDLED;
+
+	/*
+	 * FIXME: Find the affected processes and kill them, otherwise
+	 * we must die.
+	 *
+	 * The interrupt is asynchronously delivered thus EPC and RA
+	 * may be irrelevant, but are printed for a reference.
+	 */
+	printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
+	       regs->cp0_epc, regs->regs[31]);
+	die("Unrecoverable bus error", regs);
+}
+
+
+void __init dec_kn02xa_be_init(void)
+{
+	volatile u32 *mbcs = (void *)CKSEG1ADDR(KN4K_SLOT_BASE + KN4K_MB_CSR);
+
+        /* For KN04 we need to make sure EE (?) is enabled in the MB.  */
+        if (current_cpu_data.cputype == CPU_R4000SC)
+		*mbcs |= KN4K_MB_CSR_EE;
+	fast_iob();
+
+	/* Clear any leftover errors from the firmware. */
+	dec_kn02xa_be_ack();
+}
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
index 9380588..81d5e87 100644
--- a/arch/mips/dec/prom/identify.c
+++ b/arch/mips/dec/prom/identify.c
@@ -2,7 +2,7 @@
  * identify.c: machine identification code.
  *
  * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
- * Copyright (C) 2002, 2003, 2004  Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2004, 2005  Maciej W. Rozycki
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 
 #include <asm/bootinfo.h>
+
 #include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
 #include <asm/dec/kn01.h>
@@ -21,6 +22,7 @@
 #include <asm/dec/kn03.h>
 #include <asm/dec/kn230.h>
 #include <asm/dec/prom.h>
+#include <asm/dec/system.h>
 
 #include "dectypes.h"
 
@@ -68,34 +70,44 @@
 
 static inline void prom_init_kn01(void)
 {
-	dec_rtc_base = (void *)KN01_RTC_BASE;
+	dec_kn_slot_base = KN01_SLOT_BASE;
 	dec_kn_slot_size = KN01_SLOT_SIZE;
+
+	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
 }
 
 static inline void prom_init_kn230(void)
 {
-	dec_rtc_base = (void *)KN01_RTC_BASE;
+	dec_kn_slot_base = KN01_SLOT_BASE;
 	dec_kn_slot_size = KN01_SLOT_SIZE;
+
+	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
 }
 
 static inline void prom_init_kn02(void)
 {
-	dec_rtc_base = (void *)KN02_RTC_BASE;
+	dec_kn_slot_base = KN02_SLOT_BASE;
 	dec_kn_slot_size = KN02_SLOT_SIZE;
+
+	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC);
 }
 
 static inline void prom_init_kn02xa(void)
 {
-	ioasic_base = (void *)KN02XA_IOASIC_BASE;
-	dec_rtc_base = (void *)KN02XA_RTC_BASE;
+	dec_kn_slot_base = KN02XA_SLOT_BASE;
 	dec_kn_slot_size = IOASIC_SLOT_SIZE;
+
+	ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
+	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
 }
 
 static inline void prom_init_kn03(void)
 {
-	ioasic_base = (void *)KN03_IOASIC_BASE;
-	dec_rtc_base = (void *)KN03_RTC_BASE;
+	dec_kn_slot_base = KN03_SLOT_BASE;
 	dec_kn_slot_size = IOASIC_SLOT_SIZE;
+
+	ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
+	dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
 }
 
 
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index 60f7425..32a7cc7 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -6,6 +6,8 @@
  */
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
 #include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -85,17 +87,13 @@
 
 void __init prom_init(void)
 {
-	extern void dec_machine_halt(void);
+	extern void ATTRIB_NORET dec_machine_halt(void);
 	static char cpu_msg[] __initdata =
 		"Sorry, this kernel is compiled for a wrong CPU type!\n";
-	static char r3k_msg[] __initdata =
-		"Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
-	static char r4k_msg[] __initdata =
-		"Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
 	s32 argc = fw_arg0;
-	s32 argv = fw_arg1;
+	s32 *argv = (void *)fw_arg1;
 	u32 magic = fw_arg2;
-	s32 prom_vec = fw_arg3;
+	s32 *prom_vec = (void *)fw_arg3;
 
 	/*
 	 * Determine which PROM we have
@@ -113,6 +111,8 @@
 #if defined(CONFIG_CPU_R3000)
 	if ((current_cpu_data.cputype == CPU_R4000SC) ||
 	    (current_cpu_data.cputype == CPU_R4400SC)) {
+		static char r4k_msg[] __initdata =
+			"Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
 		printk(cpu_msg);
 		printk(r4k_msg);
 		dec_machine_halt();
@@ -122,6 +122,8 @@
 #if defined(CONFIG_CPU_R4X00)
 	if ((current_cpu_data.cputype == CPU_R3000) ||
 	    (current_cpu_data.cputype == CPU_R3000A)) {
+		static char r3k_msg[] __initdata =
+			"Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
 		printk(cpu_msg);
 		printk(r3k_msg);
 		dec_machine_halt();
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
index e4f6f26..83d4556 100644
--- a/arch/mips/dec/prom/memory.c
+++ b/arch/mips/dec/prom/memory.c
@@ -35,22 +35,22 @@
 	extern char genexcept_early;
 
 	/* Install exception handler */
-	memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80);
-	memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80);
+	memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80);
+	memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80);
 
 	/* read unmapped and uncached (KSEG1)
 	 * DECstations have at least 4MB RAM
 	 * Assume less than 480MB of RAM, as this is max for 5000/2xx
 	 * FIXME this should be replaced by the first free page!
 	 */
-	for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE;
-	     (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000));
+	for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE;
+	     mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000;
   	     memory_page += CHUNK_SIZE) {
 		dummy = *memory_page;
 	}
-	memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80);
+	memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80);
 
-	add_memory_region(0, (unsigned long)memory_page - KSEG1 - CHUNK_SIZE,
+	add_memory_region(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE,
 			  BOOT_MEM_RAM);
 }
 
@@ -65,7 +65,7 @@
 	memmap *bm;
 
 	/* some free 64k */
-	bm = (memmap *)KSEG0ADDR(0x28000);
+	bm = (memmap *)CKSEG0ADDR(0x28000);
 
 	bitmap_size = rex_getbitmap(bm);
 
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
index 7e4d34d..f78c6da 100644
--- a/arch/mips/dec/reset.c
+++ b/arch/mips/dec/reset.c
@@ -14,7 +14,7 @@
 
 static inline void ATTRIB_NORET back_to_prom(void)
 {
-	noret_func_t func = (void *) KSEG1ADDR(0x1fc00000);
+	noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000);
 
 	func();
 }
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 6a69309..9ef54fe 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -1,19 +1,20 @@
 /*
- * Setup the interrupt stuff.
+ * System-specific setup, especially interrupts.
  *
  * 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) 1998 Harald Koerfgen
- * Copyright (C) 2000, 2001, 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
  */
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
 #include <linux/console.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/param.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
@@ -38,6 +39,7 @@
 #include <asm/dec/kn02ca.h>
 #include <asm/dec/kn03.h>
 #include <asm/dec/kn230.h>
+#include <asm/dec/system.h>
 
 
 extern void dec_machine_restart(char *command);
@@ -47,10 +49,16 @@
 
 extern asmlinkage void decstation_handle_int(void);
 
+unsigned long dec_kn_slot_base, dec_kn_slot_size;
+
+EXPORT_SYMBOL(dec_kn_slot_base);
+EXPORT_SYMBOL(dec_kn_slot_size);
+
 spinlock_t ioasic_ssr_lock;
 
 volatile u32 *ioasic_base;
-unsigned long dec_kn_slot_size;
+
+EXPORT_SYMBOL(ioasic_base);
 
 /*
  * IRQ routing and priority tables.  Priorites are set as follows:
@@ -77,6 +85,9 @@
 int dec_interrupt[DEC_NR_INTS] = {
 	[0 ... DEC_NR_INTS - 1] = -1
 };
+
+EXPORT_SYMBOL(dec_interrupt);
+
 int_ptr cpu_mask_nr_tbl[DEC_MAX_CPU_INTS][2] = {
 	{ { .i = ~0 }, { .p = dec_intr_unimplemented } },
 };
@@ -108,11 +119,20 @@
 /*
  * Bus error (DBE/IBE exceptions and bus interrupts) handling setup.
  */
-void __init dec_be_init(void)
+static void __init dec_be_init(void)
 {
 	switch (mips_machtype) {
 	case MACH_DS23100:	/* DS2100/DS3100 Pmin/Pmax */
+		board_be_handler = dec_kn01_be_handler;
+		busirq.handler = dec_kn01_be_interrupt;
 		busirq.flags |= SA_SHIRQ;
+		dec_kn01_be_init();
+		break;
+	case MACH_DS5000_1XX:	/* DS5000/1xx 3min */
+	case MACH_DS5000_XX:	/* DS5000/xx Maxine */
+		board_be_handler = dec_kn02xa_be_handler;
+		busirq.handler = dec_kn02xa_be_interrupt;
+		dec_kn02xa_be_init();
 		break;
 	case MACH_DS5000_200:	/* DS5000/200 3max */
 	case MACH_DS5000_2X0:	/* DS5000/240 3max+ */
@@ -128,7 +148,7 @@
 extern void dec_time_init(void);
 extern void dec_timer_setup(struct irqaction *);
 
-static void __init decstation_setup(void)
+void __init plat_setup(void)
 {
 	board_be_init = dec_be_init;
 	board_time_init = dec_time_init;
@@ -139,9 +159,10 @@
 	_machine_restart = dec_machine_restart;
 	_machine_halt = dec_machine_halt;
 	_machine_power_off = dec_machine_power_off;
-}
 
-early_initcall(decstation_setup);
+	ioport_resource.start = ~0UL;
+	ioport_resource.end = 0UL;
+}
 
 /*
  * Machine-specific initialisation for KN01, aka DS2100 (aka Pmin)
@@ -206,7 +227,7 @@
 		{ .p = cpu_all_int } },
 };
 
-void __init dec_init_kn01(void)
+static void __init dec_init_kn01(void)
 {
 	/* IRQ routing. */
 	memcpy(&dec_interrupt, &kn01_interrupt,
@@ -281,7 +302,7 @@
 		{ .p = cpu_all_int } },
 };
 
-void __init dec_init_kn230(void)
+static void __init dec_init_kn230(void)
 {
 	/* IRQ routing. */
 	memcpy(&dec_interrupt, &kn230_interrupt,
@@ -371,7 +392,7 @@
 		{ .p = kn02_all_int } },
 };
 
-void __init dec_init_kn02(void)
+static void __init dec_init_kn02(void)
 {
 	/* IRQ routing. */
 	memcpy(&dec_interrupt, &kn02_interrupt,
@@ -472,7 +493,7 @@
 		{ .p = asic_all_int } },
 };
 
-void __init dec_init_kn02ba(void)
+static void __init dec_init_kn02ba(void)
 {
 	/* IRQ routing. */
 	memcpy(&dec_interrupt, &kn02ba_interrupt,
@@ -569,7 +590,7 @@
 		{ .p = asic_all_int } },
 };
 
-void __init dec_init_kn02ca(void)
+static void __init dec_init_kn02ca(void)
 {
 	/* IRQ routing. */
 	memcpy(&dec_interrupt, &kn02ca_interrupt,
@@ -670,7 +691,7 @@
 		{ .p = asic_all_int } },
 };
 
-void __init dec_init_kn03(void)
+static void __init dec_init_kn03(void)
 {
 	/* IRQ routing. */
 	memcpy(&dec_interrupt, &kn03_interrupt,
@@ -744,7 +765,3 @@
 	if (dec_interrupt[DEC_IRQ_HALT] >= 0)
 		setup_irq(dec_interrupt[DEC_IRQ_HALT], &haltirq);
 }
-
-EXPORT_SYMBOL(ioasic_base);
-EXPORT_SYMBOL(dec_kn_slot_size);
-EXPORT_SYMBOL(dec_interrupt);
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 20f84b1..4b585e6 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -1,12 +1,9 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 02:48:59 2005
+# Linux kernel version: 2.6.14-rc2
+# Thu Oct 20 22:25:09 2005
 #
 CONFIG_MIPS=y
-# CONFIG_64BIT is not set
-# CONFIG_64BIT is not set
-CONFIG_32BIT=y
 
 #
 # Code maturity level options
@@ -14,25 +11,30 @@
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -42,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -57,41 +60,69 @@
 #
 # Machine selection
 #
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
 # CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
-# CONFIG_NEC_OSPREY is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
 CONFIG_SGI_IP22=y
-# CONFIG_SOC_AU1X00 is not set
-# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_IRQ_CPU=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_ARC32=y
@@ -103,8 +134,10 @@
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32 is not set
-# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
 # CONFIG_CPU_VR41XX is not set
@@ -120,22 +153,48 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R4X00=y
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_BOARD_SCACHE=y
 CONFIG_IP22_CPU_SCACHE=y
+# CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
 # CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_LLDSCD=y
 CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+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_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
 #
+CONFIG_HW_HAS_EISA=y
 # CONFIG_EISA is not set
 CONFIG_MMU=y
 
@@ -145,10 +204,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -160,115 +215,7 @@
 CONFIG_TRAD_SIGNALS=y
 
 #
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=m
-# CONFIG_SCSI_FC_ATTRS is not set
-CONFIG_SCSI_ISCSI_ATTRS=m
-
-#
-# SCSI low-level drivers
-#
-CONFIG_SGIWD93_SCSI=y
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
+# Networking
 #
 CONFIG_NET=y
 
@@ -277,12 +224,14 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # 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=y
@@ -296,8 +245,10 @@
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_TUNNEL=m
-CONFIG_IP_TCPDIAG=m
-CONFIG_IP_TCPDIAG_IPV6=y
+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
@@ -341,6 +292,9 @@
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
 
 #
 # IP: Netfilter Configuration
@@ -348,11 +302,15 @@
 CONFIG_IP_NF_CONNTRACK=m
 CONFIG_IP_NF_CT_ACCT=y
 CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
 # 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=m
 CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_LIMIT=m
@@ -376,9 +334,12 @@
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_REALM=m
 CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_DCCP=m
 CONFIG_IP_NF_MATCH_COMMENT=m
 CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -395,12 +356,14 @@
 CONFIG_IP_NF_NAT_FTP=m
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_TARGET_CONNMARK=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -410,7 +373,7 @@
 CONFIG_IP_NF_ARP_MANGLE=m
 
 #
-# IPv6: Netfilter Configuration
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
 CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -429,11 +392,16 @@
 CONFIG_IP6_NF_MATCH_EUI64=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -456,10 +424,6 @@
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 CONFIG_NET_SCHED=y
 # CONFIG_NET_SCH_CLK_JIFFIES is not set
 CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
@@ -479,6 +443,7 @@
 CONFIG_NET_QOS=y
 CONFIG_NET_ESTIMATOR=y
 CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
 CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_ROUTE=y
@@ -489,6 +454,7 @@
 # CONFIG_CLS_U32_MARK is not set
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
 # CONFIG_NET_CLS_ACT is not set
 CONFIG_NET_CLS_POLICE=y
 
@@ -496,17 +462,153 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SGIWD93_SCSI=y
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-CONFIG_ETHERTAP=m
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -540,6 +642,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -569,18 +673,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -598,6 +690,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -644,11 +746,14 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=m
 CONFIG_MAX_RAW_DEVS=256
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -659,10 +764,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -693,7 +808,6 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_SGI_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -707,10 +821,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -723,13 +833,17 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=m
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -741,12 +855,14 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=m
 CONFIG_XFS_SECURITY=y
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 CONFIG_MINIX_FS=m
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 CONFIG_QFMT_V2=m
@@ -754,6 +870,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -781,12 +898,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -811,15 +926,20 @@
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
 CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -835,6 +955,7 @@
 CONFIG_CODA_FS=m
 # CONFIG_CODA_FS_OLD_API is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -908,7 +1029,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
@@ -931,6 +1054,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -942,10 +1066,10 @@
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Hardware crypto devices
@@ -955,9 +1079,12 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=m
 CONFIG_CRC32=m
 CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c
index 28bd908..78dbb18 100644
--- a/arch/mips/galileo-boards/ev96100/setup.c
+++ b/arch/mips/galileo-boards/ev96100/setup.c
@@ -55,7 +55,7 @@
 
 unsigned char mac_0_1[12];
 
-static void __init ev96100_setup(void)
+void __init plat_setup(void)
 {
 	unsigned int config = read_c0_config();
 	unsigned int status = read_c0_status();
@@ -142,8 +142,6 @@
 	tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
 }
 
-early_initcall(ev96100_setup);
-
 unsigned short get_gt_devid(void)
 {
 	u32 gt_devid;
diff --git a/arch/mips/gt64120/ev64120/Kconfig b/arch/mips/gt64120/ev64120/Kconfig
new file mode 100644
index 0000000..d691762
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/Kconfig
@@ -0,0 +1,3 @@
+config EVB_PCI1
+	bool "Enable Second PCI (PCI1)"
+	depends on MIPS_EV64120
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
index dba0961..98b5a96 100644
--- a/arch/mips/gt64120/ev64120/setup.c
+++ b/arch/mips/gt64120/ev64120/setup.c
@@ -69,7 +69,7 @@
  */
 extern void gt64120_time_init(void);
 
-static void __init ev64120_setup(void)
+void __init plat_setup(void)
 {
 	_machine_restart = galileo_machine_restart;
 	_machine_halt = galileo_machine_halt;
@@ -79,8 +79,6 @@
 	set_io_port_base(KSEG1);
 }
 
-early_initcall(ev64120_setup);
-
 const char *get_system_type(void)
 {
 	return "Galileo EV64120A";
diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c
index d610f8c..0d07c33 100644
--- a/arch/mips/gt64120/momenco_ocelot/setup.c
+++ b/arch/mips/gt64120/momenco_ocelot/setup.c
@@ -150,7 +150,7 @@
 	gt64120_base = 0xe0000000;
 }
 
-static void __init momenco_ocelot_setup(void)
+void __init plat_setup(void)
 {
 	void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
 	unsigned int tmpword;
@@ -307,8 +307,6 @@
 	GT_WRITE(GT_DEV_B3_OFS, 0xfef73);
 }
 
-early_initcall(momenco_ocelot_setup);
-
 extern int rm7k_tcache_enabled;
 /*
  * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
diff --git a/arch/mips/ite-boards/Kconfig b/arch/mips/ite-boards/Kconfig
new file mode 100644
index 0000000..a6d59ad
--- /dev/null
+++ b/arch/mips/ite-boards/Kconfig
@@ -0,0 +1,8 @@
+config IT8172_REVC
+	bool "Support for older IT8172 (Rev C)"
+	depends on MIPS_ITE8172
+	help
+	  Say Y here to support the older, Revision C version of the Integrated
+	  Technology Express, Inc. ITE8172 SBC.  Vendor page at
+	  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+	  board at <http://www.mvista.com/partners/semiconductor/ite.html>.
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
index cb71b90..e67f961 100644
--- a/arch/mips/ite-boards/generic/irq.c
+++ b/arch/mips/ite-boards/generic/irq.c
@@ -138,14 +138,13 @@
 }
 
 static struct hw_interrupt_type it8172_irq_type = {
-	"ITE8172",
-	startup_ite_irq,
-	shutdown_ite_irq,
-	enable_it8172_irq,
-	disable_it8172_irq,
-	mask_and_ack_ite_irq,
-	end_ite_irq,
-	NULL
+	.typename = "ITE8172",
+	.startup = startup_ite_irq,
+	.shutdown = shutdown_ite_irq,
+	.enable = enable_it8172_irq,
+	.disable = disable_it8172_irq,
+	.ack = mask_and_ack_ite_irq,
+	.end = end_ite_irq,
 };
 
 
@@ -159,13 +158,13 @@
 #define end_none	enable_none
 
 static struct hw_interrupt_type cp0_irq_type = {
-	"CP0 Count",
-	startup_none,
-	shutdown_none,
-	enable_none,
-	disable_none,
-	ack_none,
-	end_none
+	.typename = "CP0 Count",
+	.startup = startup_none,
+	.shutdown = shutdown_none,
+	.enable = enable_none,
+	.disable = disable_none,
+	.ack = ack_none,
+	.end = end_none
 };
 
 void enable_cpu_timer(void)
@@ -182,7 +181,6 @@
 	int i;
         unsigned long flags;
 
-        memset(irq_desc, 0, sizeof(irq_desc));
         set_except_vector(0, it8172_IRQ);
 
 	/* mask all interrupts */
diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c
index a5f6d84..062429d 100644
--- a/arch/mips/ite-boards/generic/it8172_setup.c
+++ b/arch/mips/ite-boards/generic/it8172_setup.c
@@ -105,7 +105,7 @@
 	it8172_resources.ram.end = memsize;
 }
 
-static void __init it8172_setup(void)
+void __init plat_setup(void)
 {
 	unsigned short dsr;
 	char *argptr;
@@ -251,8 +251,6 @@
 #endif /* CONFIG_IT8172_SCR1 */
 }
 
-early_initcall(it8172_setup);
-
 #ifdef CONFIG_SERIO_I8042
 /*
  * According to the ITE Special BIOS Note for waking up the
diff --git a/arch/mips/jazz/Kconfig b/arch/mips/jazz/Kconfig
new file mode 100644
index 0000000..1f372b0
--- /dev/null
+++ b/arch/mips/jazz/Kconfig
@@ -0,0 +1,33 @@
+config ACER_PICA_61
+	bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)"
+	depends on MACH_JAZZ && EXPERIMENTAL
+	select DMA_NONCOHERENT
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
+	  kernel that runs on these, say Y here. For details about Linux on
+	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+	  <http://www.linux-mips.org/>.
+
+config MIPS_MAGNUM_4000
+	bool "Support for MIPS Magnum 4000"
+	depends on MACH_JAZZ
+	select DMA_NONCOHERENT
+	select SYS_SUPPORTS_BIG_ENDIAN if EXPERIMENTAL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
+	  kernel that runs on these, say Y here. For details about Linux on
+	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+	  <http://www.linux-mips.org/>.
+
+config OLIVETTI_M700
+	bool "Support for Olivetti M700-10"
+	depends on MACH_JAZZ
+	select DMA_NONCOHERENT
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This is a machine with a R4000 100 MHz CPU. To compile a Linux
+	  kernel that runs on these, say Y here. For details about Linux on
+	  the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+	  <http://www.linux-mips.org/>.
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index 0b608fa..b309b1b 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -58,14 +58,13 @@
 }
 
 static struct hw_interrupt_type r4030_irq_type = {
-	"R4030",
-	startup_r4030_irq,
-	shutdown_r4030_irq,
-	enable_r4030_irq,
-	disable_r4030_irq,
-	mask_and_ack_r4030_irq,
-	end_r4030_irq,
-	NULL
+	.typename = "R4030",
+	.startup = startup_r4030_irq,
+	.shutdown = shutdown_r4030_irq,
+	.enable = enable_r4030_irq,
+	.disable = disable_r4030_irq,
+	.ack = mask_and_ack_r4030_irq,
+	.end = end_r4030_irq,
 };
 
 void __init init_r4030_ints(void)
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index fccb06f..044df9d 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -50,7 +50,7 @@
 	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 };
 
-static void __init jazz_setup(void)
+void __init plat_setup(void)
 {
 	int i;
 
@@ -97,5 +97,3 @@
 
 	vdma_init();
 }
-
-early_initcall(jazz_setup);
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index b9799b8..7cbe144 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -412,13 +412,13 @@
 }
 
 static hw_irq_controller jmr3927_irq_controller = {
-	"jmr3927_irq",
-	jmr3927_irq_startup,
-	jmr3927_irq_shutdown,
-	jmr3927_irq_enable,
-	jmr3927_irq_disable,
-	jmr3927_irq_ack,
-	jmr3927_irq_end,
+	.typename = "jmr3927_irq",
+	.startup = jmr3927_irq_startup,
+	.shutdown = jmr3927_irq_shutdown,
+	.enable = jmr3927_irq_enable,
+	.disable = jmr3927_irq_disable,
+	.ack = jmr3927_irq_ack,
+	.end = jmr3927_irq_end,
 };
 
 void jmr3927_irq_init(u32 irq_base)
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 32039bb..3e2fbdc 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -44,6 +44,11 @@
 #include <linux/ioport.h>
 #include <linux/param.h>	/* for HZ */
 #include <linux/delay.h>
+#ifdef CONFIG_SERIAL_TXX9
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#endif
 
 #include <asm/addrspace.h>
 #include <asm/time.h>
@@ -193,7 +198,7 @@
 extern struct resource pci_io_resource;
 extern struct resource pci_mem_resource;
 
-static void __init jmr3927_setup(void)
+void __init plat_setup(void)
 {
 	char *argptr;
 
@@ -211,8 +216,8 @@
 	 */
 	ioport_resource.start = pci_io_resource.start;
 	ioport_resource.end = pci_io_resource.end;
-	iomem_resource.start = pci_mem_resource.start;
-	iomem_resource.end = pci_mem_resource.end;
+	iomem_resource.start = 0;
+	iomem_resource.end = 0xffffffff;
 
 	/* Reboot on panic */
 	panic_timeout = 180;
@@ -265,18 +270,35 @@
 		strcat(argptr, " ip=bootp");
 	}
 
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_TXX9
+	{
+		extern int early_serial_txx9_setup(struct uart_port *port);
+		int i;
+		struct uart_port req;
+		for(i = 0; i < 2; i++) {
+			memset(&req, 0, sizeof(req));
+			req.line = i;
+			req.iotype = UPIO_MEM;
+			req.membase = (char *)TX3927_SIO_REG(i);
+			req.mapbase = TX3927_SIO_REG(i);
+			req.irq = i == 0 ?
+				JMR3927_IRQ_IRC_SIO0 : JMR3927_IRQ_IRC_SIO1;
+			if (i == 0)
+				req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+			req.uartclk = JMR3927_IMCLK;
+			early_serial_txx9_setup(&req);
+		}
+	}
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
 	argptr = prom_getcmdline();
 	if ((argptr = strstr(argptr, "console=")) == NULL) {
 		argptr = prom_getcmdline();
 		strcat(argptr, " console=ttyS1,115200");
 	}
 #endif
+#endif
 }
 
-early_initcall(jmr3927_setup);
-
-
 static void tx3927_setup(void);
 
 #ifdef CONFIG_PCI
@@ -335,7 +357,7 @@
 		       jmr3927_io_dipsw());
 }
 
-static void __init tx3927_setup(void)
+void __init plat_setup(void)
 {
 	int i;
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index d330358..72f2126 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -11,11 +11,7 @@
 binfmt_irix-objs	:= irixelf.o irixinv.o irixioctl.o irixsig.o	\
 			   irix5sys.o sysirix.o
 
-ifdef CONFIG_MODULES
-obj-y				+= mips_ksyms.o module.o
-obj-$(CONFIG_32BIT)		+= module-elf32.o
-obj-$(CONFIG_64BIT)		+= module-elf64.o
-endif
+obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
 obj-$(CONFIG_CPU_R3000)		+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
@@ -38,12 +34,18 @@
 
 obj-$(CONFIG_SMP)		+= smp.o
 
+obj-$(CONFIG_MIPS_MT_SMP)	+= smp_mt.o
+
+obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
+obj-$(CONFIG_MIPS_VPE_APSP_API)	+= rtlx.o
+
 obj-$(CONFIG_NO_ISA)		+= dma-no-isa.o
 obj-$(CONFIG_I8259)		+= i8259.o
 obj-$(CONFIG_IRQ_CPU)		+= irq_cpu.o
 obj-$(CONFIG_IRQ_CPU_RM7K)	+= irq-rm7000.o
 obj-$(CONFIG_IRQ_CPU_RM9K)	+= irq-rm9000.o
 obj-$(CONFIG_IRQ_MV64340)	+= irq-mv6434x.o
+obj-$(CONFIG_MIPS_BOARDS_GEN)	+= irq-msc01.o
 
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
 obj-$(CONFIG_64BIT)		+= scall64-64.o
@@ -57,8 +59,6 @@
 
 obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
 
-obj-$(CONFIG_GEN_RTC)		+= genrtc.o
-
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 CFLAGS_ioctl32.o	+= -Ifs/
 
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 2c11abb..ca6b03c 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -95,6 +95,7 @@
 	offset("#define TI_PRE_COUNT       ", struct thread_info, preempt_count);
 	offset("#define TI_ADDR_LIMIT      ", struct thread_info, addr_limit);
 	offset("#define TI_RESTART_BLOCK   ", struct thread_info, restart_block);
+	offset("#define TI_TP_VALUE	   ", struct thread_info, tp_value);
 	constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
 	constant("#define _THREAD_SIZE       ", THREAD_SIZE);
 	constant("#define _THREAD_MASK       ", THREAD_MASK);
@@ -240,6 +241,7 @@
 	linefeed;
 }
 
+#ifdef CONFIG_32BIT
 void output_sc_defines(void)
 {
 	text("/* Linux sigcontext offsets. */");
@@ -251,10 +253,29 @@
 	offset("#define SC_STATUS     ", struct sigcontext, sc_status);
 	offset("#define SC_FPC_CSR    ", struct sigcontext, sc_fpc_csr);
 	offset("#define SC_FPC_EIR    ", struct sigcontext, sc_fpc_eir);
-	offset("#define SC_CAUSE      ", struct sigcontext, sc_cause);
-	offset("#define SC_BADVADDR   ", struct sigcontext, sc_badvaddr);
+	offset("#define SC_HI1        ", struct sigcontext, sc_hi1);
+	offset("#define SC_LO1        ", struct sigcontext, sc_lo1);
+	offset("#define SC_HI2        ", struct sigcontext, sc_hi2);
+	offset("#define SC_LO2        ", struct sigcontext, sc_lo2);
+	offset("#define SC_HI3        ", struct sigcontext, sc_hi3);
+	offset("#define SC_LO3        ", struct sigcontext, sc_lo3);
 	linefeed;
 }
+#endif
+
+#ifdef CONFIG_64BIT
+void output_sc_defines(void)
+{
+	text("/* Linux sigcontext offsets. */");
+	offset("#define SC_REGS       ", struct sigcontext, sc_regs);
+	offset("#define SC_FPREGS     ", struct sigcontext, sc_fpregs);
+	offset("#define SC_MDHI       ", struct sigcontext, sc_hi);
+	offset("#define SC_MDLO       ", struct sigcontext, sc_lo);
+	offset("#define SC_PC         ", struct sigcontext, sc_pc);
+	offset("#define SC_FPC_CSR    ", struct sigcontext, sc_fpc_csr);
+	linefeed;
+}
+#endif
 
 #ifdef CONFIG_MIPS32_COMPAT
 void output_sc32_defines(void)
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
index 6b645fb..d8e2674a1 100644
--- a/arch/mips/kernel/binfmt_elfn32.c
+++ b/arch/mips/kernel/binfmt_elfn32.c
@@ -52,7 +52,6 @@
 
 #include <asm/processor.h>
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
 
@@ -116,4 +115,7 @@
 #undef MODULE_DESCRIPTION
 #undef MODULE_AUTHOR
 
+#undef TASK_SIZE
+#define TASK_SIZE TASK_SIZE32
+
 #include "../../../fs/binfmt_elf.c"
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index b4075e9..cec5f32 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -54,7 +54,6 @@
 
 #include <asm/processor.h>
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
 
@@ -98,7 +97,7 @@
 #define init_elf_binfmt init_elf32_binfmt
 
 #define jiffies_to_timeval jiffies_to_compat_timeval
-static __inline__ void
+static inline void
 jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
 {
 	/*
@@ -113,21 +112,26 @@
 #undef ELF_CORE_COPY_REGS
 #define ELF_CORE_COPY_REGS(_dest,_regs) elf32_core_copy_regs(_dest,_regs);
 
-void elf32_core_copy_regs(elf_gregset_t _dest, struct pt_regs *_regs)
+void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
 {
 	int i;
 
-	memset(_dest, 0, sizeof(elf_gregset_t));
-
-	/* XXXKW the 6 is from EF_REG0 in gdb/gdb/mips-linux-tdep.c, include/asm-mips/reg.h */
-	for (i=6; i<38; i++)
-		_dest[i] = (elf_greg_t) _regs->regs[i-6];
-	_dest[i++] = (elf_greg_t) _regs->lo;
-	_dest[i++] = (elf_greg_t) _regs->hi;
-	_dest[i++] = (elf_greg_t) _regs->cp0_epc;
-	_dest[i++] = (elf_greg_t) _regs->cp0_badvaddr;
-	_dest[i++] = (elf_greg_t) _regs->cp0_status;
-	_dest[i++] = (elf_greg_t) _regs->cp0_cause;
+	for (i = 0; i < EF_R0; i++)
+		grp[i] = 0;
+	grp[EF_R0] = 0;
+	for (i = 1; i <= 31; i++)
+		grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
+	grp[EF_R26] = 0;
+	grp[EF_R27] = 0;
+	grp[EF_LO] = (elf_greg_t) regs->lo;
+	grp[EF_HI] = (elf_greg_t) regs->hi;
+	grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
+	grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
+	grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
+	grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
+#ifdef EF_UNUSED0
+	grp[EF_UNUSED0] = 0;
+#endif
 }
 
 MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
@@ -136,4 +140,7 @@
 #undef MODULE_DESCRIPTION
 #undef MODULE_AUTHOR
 
+#undef TASK_SIZE
+#define TASK_SIZE TASK_SIZE32
+
 #include "../../../fs/binfmt_elf.c"
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 01117e9..374de83 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -12,6 +12,7 @@
 #include <asm/branch.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm/fpu.h>
 #include <asm/inst.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
@@ -21,7 +22,7 @@
  */
 int __compute_return_epc(struct pt_regs *regs)
 {
-	unsigned int *addr, bit, fcr31;
+	unsigned int *addr, bit, fcr31, dspcontrol;
 	long epc;
 	union mips_instruction insn;
 
@@ -98,6 +99,18 @@
 				epc += 8;
 			regs->cp0_epc = epc;
 			break;
+		case bposge32_op:
+			if (!cpu_has_dsp)
+				goto sigill;
+
+			dspcontrol = rddsp(0x01);
+
+			if (dspcontrol >= 32) {
+				epc = epc + 4 + (insn.i_format.simmediate << 2);
+			} else
+				epc += 8;
+			regs->cp0_epc = epc;
+			break;
 		}
 		break;
 
@@ -161,10 +174,13 @@
 	 * And now the FPA/cp1 branch instructions.
 	 */
 	case cop1_op:
-		if (!cpu_has_fpu)
-			fcr31 = current->thread.fpu.soft.fcr31;
-		else
+		preempt_disable();
+		if (is_fpu_owner())
 			asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+		else
+			fcr31 = current->thread.fpu.hard.fcr31;
+		preempt_enable();
+
 		bit = (insn.i_format.rt >> 2);
 		bit += (bit != 0);
 		bit += 23;
@@ -196,4 +212,9 @@
 	printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
 	force_sig(SIGBUS, current);
 	return -EFAULT;
+
+sigill:
+	printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
+	force_sig(SIGBUS, current);
+	return -EFAULT;
 }
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 7685f8b..a263fb7 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -2,9 +2,9 @@
  * Processor capabilities determination functions.
  *
  * Copyright (C) xxxx  the Anonymous
- * Copyright (C) 2003  Maciej W. Rozycki
+ * Copyright (C) 2003, 2004  Maciej W. Rozycki
  * Copyright (C) 1994 - 2003 Ralf Baechle
- * Copyright (C) 2001 MIPS Inc.
+ * Copyright (C) 2001, 2004  MIPS Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,7 +17,6 @@
 #include <linux/ptrace.h>
 #include <linux/stddef.h>
 
-#include <asm/bugs.h>
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
@@ -51,36 +50,48 @@
 		".set\tmips0");
 }
 
-/*
- * The Au1xxx wait is available only if we run CONFIG_PM and
- * the timer setup found we had a 32KHz counter available.
- * There are still problems with functions that may call au1k_wait
- * directly, but that will be discovered pretty quickly.
- */
-extern void (*au1k_wait_ptr)(void);
+/* The Au1xxx wait is available only if using 32khz counter or
+ * external timer source, but specifically not CP0 Counter. */
+int allow_au1k_wait;
 
-void au1k_wait(void)
+static void au1k_wait(void)
 {
-#ifdef CONFIG_PM
 	/* using the wait instruction makes CP0 counter unusable */
-	__asm__(".set\tmips3\n\t"
+	__asm__(".set mips3\n\t"
+		"cache 0x14, 0(%0)\n\t"
+		"cache 0x14, 32(%0)\n\t"
+		"sync\n\t"
+		"nop\n\t"
 		"wait\n\t"
 		"nop\n\t"
 		"nop\n\t"
 		"nop\n\t"
 		"nop\n\t"
-		".set\tmips0");
-#else
-	__asm__("nop\n\t"
-		"nop");
-#endif
+		".set mips0\n\t"
+		: : "r" (au1k_wait));
 }
 
+static int __initdata nowait = 0;
+
+int __init wait_disable(char *s)
+{
+	nowait = 1;
+
+	return 1;
+}
+
+__setup("nowait", wait_disable);
+
 static inline void check_wait(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 
 	printk("Checking for 'wait' instruction... ");
+	if (nowait) {
+		printk (" disabled.\n");
+		return;
+	}
+
 	switch (c->cputype) {
 	case CPU_R3081:
 	case CPU_R3081E:
@@ -109,22 +120,22 @@
 /*	case CPU_20KC:*/
 	case CPU_24K:
 	case CPU_25KF:
+	case CPU_34K:
+ 	case CPU_PR4450:
 		cpu_wait = r4k_wait;
 		printk(" available.\n");
 		break;
-#ifdef CONFIG_PM
 	case CPU_AU1000:
 	case CPU_AU1100:
 	case CPU_AU1500:
-		if (au1k_wait_ptr != NULL) {
-			cpu_wait = au1k_wait_ptr;
+	case CPU_AU1550:
+	case CPU_AU1200:
+		if (allow_au1k_wait) {
+			cpu_wait = au1k_wait;
 			printk(" available.\n");
-		}
-		else {
+		} else
 			printk(" unavailable.\n");
-		}
 		break;
-#endif
 	default:
 		printk(" unavailable.\n");
 		break;
@@ -180,7 +191,7 @@
 	return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
 }
 
-#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
+#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
 		| MIPS_CPU_COUNTER)
 
 static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
@@ -189,7 +200,8 @@
 	case PRID_IMP_R2000:
 		c->cputype = CPU_R2000;
 		c->isa_level = MIPS_CPU_ISA_I;
-		c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
+		             MIPS_CPU_NOFPUEX;
 		if (__cpu_has_fpu())
 			c->options |= MIPS_CPU_FPU;
 		c->tlbsize = 64;
@@ -203,7 +215,8 @@
 		else
 			c->cputype = CPU_R3000;
 		c->isa_level = MIPS_CPU_ISA_I;
-		c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
+		             MIPS_CPU_NOFPUEX;
 		if (__cpu_has_fpu())
 			c->options |= MIPS_CPU_FPU;
 		c->tlbsize = 64;
@@ -266,7 +279,8 @@
 	case PRID_IMP_R4600:
 		c->cputype = CPU_R4600;
 		c->isa_level = MIPS_CPU_ISA_III;
-		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
+		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+			     MIPS_CPU_LLSC;
 		c->tlbsize = 48;
 		break;
 	#if 0
@@ -285,7 +299,7 @@
 	#endif
 	case PRID_IMP_TX39:
 		c->isa_level = MIPS_CPU_ISA_I;
-		c->options = MIPS_CPU_TLB;
+		c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
 
 		if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
 			c->cputype = CPU_TX3927;
@@ -421,74 +435,147 @@
 	}
 }
 
-static inline void decode_config1(struct cpuinfo_mips *c)
+static inline unsigned int decode_config0(struct cpuinfo_mips *c)
 {
-	unsigned long config0 = read_c0_config();
-	unsigned long config1;
+	unsigned int config0;
+	int isa;
 
-	if ((config0 & (1 << 31)) == 0)
-		return;			/* actually wort a panic() */
+	config0 = read_c0_config();
 
-	/* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */
-	c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-		MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
-		MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
+	if (((config0 & MIPS_CONF_MT) >> 7) == 1)
+		c->options |= MIPS_CPU_TLB;
+	isa = (config0 & MIPS_CONF_AT) >> 13;
+	switch (isa) {
+	case 0:
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	case 2:
+		c->isa_level = MIPS_CPU_ISA_M64;
+		break;
+	default:
+		panic("Unsupported ISA type, cp0.config0.at: %d.", isa);
+	}
+
+	return config0 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_config1(struct cpuinfo_mips *c)
+{
+	unsigned int config1;
+
 	config1 = read_c0_config1();
-	if (config1 & (1 << 3))
+
+	if (config1 & MIPS_CONF1_MD)
+		c->ases |= MIPS_ASE_MDMX;
+	if (config1 & MIPS_CONF1_WR)
 		c->options |= MIPS_CPU_WATCH;
-	if (config1 & (1 << 2))
-		c->options |= MIPS_CPU_MIPS16;
-	if (config1 & (1 << 1))
+	if (config1 & MIPS_CONF1_CA)
+		c->ases |= MIPS_ASE_MIPS16;
+	if (config1 & MIPS_CONF1_EP)
 		c->options |= MIPS_CPU_EJTAG;
-	if (config1 & 1) {
+	if (config1 & MIPS_CONF1_FP) {
 		c->options |= MIPS_CPU_FPU;
 		c->options |= MIPS_CPU_32FPR;
 	}
+	if (cpu_has_tlb)
+		c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
+
+	return config1 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_config2(struct cpuinfo_mips *c)
+{
+	unsigned int config2;
+
+	config2 = read_c0_config2();
+
+	if (config2 & MIPS_CONF2_SL)
+		c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+	return config2 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_config3(struct cpuinfo_mips *c)
+{
+	unsigned int config3;
+
+	config3 = read_c0_config3();
+
+	if (config3 & MIPS_CONF3_SM)
+		c->ases |= MIPS_ASE_SMARTMIPS;
+	if (config3 & MIPS_CONF3_DSP)
+		c->ases |= MIPS_ASE_DSP;
+	if (config3 & MIPS_CONF3_VINT)
+		c->options |= MIPS_CPU_VINT;
+	if (config3 & MIPS_CONF3_VEIC)
+		c->options |= MIPS_CPU_VEIC;
+	if (config3 & MIPS_CONF3_MT)
+                c->ases |= MIPS_ASE_MIPSMT;
+
+	return config3 & MIPS_CONF_M;
+}
+
+static inline void decode_configs(struct cpuinfo_mips *c)
+{
+	/* MIPS32 or MIPS64 compliant CPU.  */
+	c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
+	             MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
+
 	c->scache.flags = MIPS_CACHE_NOT_PRESENT;
 
-	c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
+	/* Read Config registers.  */
+	if (!decode_config0(c))
+		return;			/* actually worth a panic() */
+	if (!decode_config1(c))
+		return;
+	if (!decode_config2(c))
+		return;
+	if (!decode_config3(c))
+		return;
 }
 
 static inline void cpu_probe_mips(struct cpuinfo_mips *c)
 {
-	decode_config1(c);
+	decode_configs(c);
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_4KC:
 		c->cputype = CPU_4KC;
-		c->isa_level = MIPS_CPU_ISA_M32;
 		break;
 	case PRID_IMP_4KEC:
 		c->cputype = CPU_4KEC;
-		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	case PRID_IMP_4KECR2:
+		c->cputype = CPU_4KEC;
 		break;
 	case PRID_IMP_4KSC:
+	case PRID_IMP_4KSD:
 		c->cputype = CPU_4KSC;
-		c->isa_level = MIPS_CPU_ISA_M32;
 		break;
 	case PRID_IMP_5KC:
 		c->cputype = CPU_5KC;
-		c->isa_level = MIPS_CPU_ISA_M64;
 		break;
 	case PRID_IMP_20KC:
 		c->cputype = CPU_20KC;
-		c->isa_level = MIPS_CPU_ISA_M64;
 		break;
 	case PRID_IMP_24K:
+	case PRID_IMP_24KE:
 		c->cputype = CPU_24K;
-		c->isa_level = MIPS_CPU_ISA_M32;
 		break;
 	case PRID_IMP_25KF:
 		c->cputype = CPU_25KF;
-		c->isa_level = MIPS_CPU_ISA_M64;
 		/* Probe for L2 cache */
 		c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
 		break;
+	case PRID_IMP_34K:
+		c->cputype = CPU_34K;
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
 	}
 }
 
 static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
 {
-	decode_config1(c);
+	decode_configs(c);
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_AU1_REV1:
 	case PRID_IMP_AU1_REV2:
@@ -505,50 +592,70 @@
 		case 3:
 			c->cputype = CPU_AU1550;
 			break;
+		case 4:
+			c->cputype = CPU_AU1200;
+			break;
 		default:
 			panic("Unknown Au Core!");
 			break;
 		}
-		c->isa_level = MIPS_CPU_ISA_M32;
 		break;
 	}
 }
 
 static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
 {
-	decode_config1(c);
+	decode_configs(c);
+
+	/*
+	 * For historical reasons the SB1 comes with it's own variant of
+	 * cache code which eventually will be folded into c-r4k.c.  Until
+	 * then we pretend it's got it's own cache architecture.
+	 */
+	c->options &= ~MIPS_CPU_4K_CACHE;
+	c->options |= MIPS_CPU_SB1_CACHE;
+
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_SB1:
 		c->cputype = CPU_SB1;
-		c->isa_level = MIPS_CPU_ISA_M64;
-		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-		             MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
-		             MIPS_CPU_MCHECK | MIPS_CPU_EJTAG |
-		             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
-#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
+#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 		/* FPU in pass1 is known to have issues. */
-		c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
+		c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
 #endif
 		break;
+	case PRID_IMP_SB1A:
+		c->cputype = CPU_SB1A;
+		break;
 	}
 }
 
 static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
 {
-	decode_config1(c);
+	decode_configs(c);
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_SR71000:
 		c->cputype = CPU_SR71000;
-		c->isa_level = MIPS_CPU_ISA_M64;
-		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-		             MIPS_CPU_4KTLB | MIPS_CPU_FPU |
-		             MIPS_CPU_COUNTER | MIPS_CPU_MCHECK;
 		c->scache.ways = 8;
 		c->tlbsize = 64;
 		break;
 	}
 }
 
+static inline void cpu_probe_philips(struct cpuinfo_mips *c)
+{
+	decode_configs(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_PR4450:
+		c->cputype = CPU_PR4450;
+		c->isa_level = MIPS_CPU_ISA_M32;
+		break;
+	default:
+		panic("Unknown Philips Core!"); /* REVISIT: die? */
+		break;
+	}
+}
+
+
 __init void cpu_probe(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -571,15 +678,24 @@
 	case PRID_COMP_SIBYTE:
 		cpu_probe_sibyte(c);
 		break;
-
 	case PRID_COMP_SANDCRAFT:
 		cpu_probe_sandcraft(c);
 		break;
+ 	case PRID_COMP_PHILIPS:
+		cpu_probe_philips(c);
+ 		break;
 	default:
 		c->cputype = CPU_UNKNOWN;
 	}
-	if (c->options & MIPS_CPU_FPU)
+	if (c->options & MIPS_CPU_FPU) {
 		c->fpu_id = cpu_get_fpu_id();
+
+		if (c->isa_level == MIPS_CPU_ISA_M32 ||
+		    c->isa_level == MIPS_CPU_ISA_M64) {
+			if (c->fpu_id & MIPS_FPIR_3D)
+				c->ases |= MIPS_ASE_MIPS3D;
+		}
+	}
 }
 
 __init void cpu_report(void)
diff --git a/arch/mips/kernel/dma-no-isa.c b/arch/mips/kernel/dma-no-isa.c
new file mode 100644
index 0000000..6df8b07
--- /dev/null
+++ b/arch/mips/kernel/dma-no-isa.c
@@ -0,0 +1,28 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 by Ralf Baechle
+ *
+ * Dummy ISA DMA functions for systems that don't have ISA but share drivers
+ * with ISA such as legacy free PCI.
+ */
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+DEFINE_SPINLOCK(dma_spin_lock);
+
+int request_dma(unsigned int dmanr, const char * device_id)
+{
+	return -EINVAL;
+}
+
+void free_dma(unsigned int dmanr)
+{
+}
+
+EXPORT_SYMBOL(dma_spin_lock);
+EXPORT_SYMBOL(request_dma);
+EXPORT_SYMBOL(free_dma);
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 5eb4291..83c87fe 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -19,11 +19,11 @@
 #include <asm/war.h>
 
 #ifdef CONFIG_PREEMPT
-	.macro	preempt_stop reg=t0
+	.macro	preempt_stop
 	.endm
 #else
-	.macro	preempt_stop reg=t0
-	local_irq_disable \reg
+	.macro	preempt_stop
+	local_irq_disable
 	.endm
 #define resume_kernel	restore_all
 #endif
@@ -37,17 +37,18 @@
 	andi	t0, t0, KU_USER
 	beqz	t0, resume_kernel
 
-FEXPORT(resume_userspace)
-	local_irq_disable	t0	# make sure we dont miss an
+resume_userspace:
+	local_irq_disable		# make sure we dont miss an
 					# interrupt setting need_resched
 					# between sampling and return
 	LONG_L	a2, TI_FLAGS($28)	# current->work
-	andi	a2, _TIF_WORK_MASK	# (ignoring syscall_trace)
-	bnez	a2, work_pending
+	andi	t0, a2, _TIF_WORK_MASK	# (ignoring syscall_trace)
+	bnez	t0, work_pending
 	j	restore_all
 
 #ifdef CONFIG_PREEMPT
-ENTRY(resume_kernel)
+resume_kernel:
+	local_irq_disable
 	lw	t0, TI_PRE_COUNT($28)
 	bnez	t0, restore_all
 need_resched:
@@ -57,12 +58,7 @@
 	LONG_L	t0, PT_STATUS(sp)		# Interrupts off?
 	andi	t0, 1
 	beqz	t0, restore_all
-	li	t0, PREEMPT_ACTIVE
-	sw	t0, TI_PRE_COUNT($28)
-	local_irq_enable t0
-	jal	schedule
-	sw	zero, TI_PRE_COUNT($28)
-	local_irq_disable t0
+	jal	preempt_schedule_irq
 	b	need_resched
 #endif
 
@@ -88,13 +84,13 @@
 	RESTORE_SP_AND_RET
 	.set	at
 
-FEXPORT(work_pending)
-	andi	t0, a2, _TIF_NEED_RESCHED
+work_pending:
+	andi	t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 	beqz	t0, work_notifysig
 work_resched:
 	jal	schedule
 
-	local_irq_disable t0		# make sure need_resched and
+	local_irq_disable		# make sure need_resched and
 					# signals dont change between
 					# sampling and return
 	LONG_L	a2, TI_FLAGS($28)
@@ -109,15 +105,14 @@
 	move	a0, sp
 	li	a1, 0
 	jal	do_notify_resume	# a2 already loaded
-	j	restore_all
+	j	resume_userspace
 
 FEXPORT(syscall_exit_work_partial)
 	SAVE_STATIC
-FEXPORT(syscall_exit_work)
-	LONG_L	t0, TI_FLAGS($28)
-	li	t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
-	and	t0, t1
-	beqz	t0, work_pending	# trace bit is set
+syscall_exit_work:
+	li	t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+	and	t0, a2			# a2 is preloaded with TI_FLAGS
+	beqz	t0, work_pending	# trace bit set?
 	local_irq_enable		# could let do_syscall_trace()
 					# call schedule() instead
 	move	a0, sp
@@ -128,28 +123,25 @@
 /*
  * Common spurious interrupt handler.
  */
-	.text
-	.align  5
 LEAF(spurious_interrupt)
 	/*
 	 * Someone tried to fool us by sending an interrupt but we
 	 * couldn't find a cause for it.
 	 */
+	PTR_LA	t1, irq_err_count
 #ifdef CONFIG_SMP
-	lui     t1, %hi(irq_err_count)
-1:	ll      t0, %lo(irq_err_count)(t1)
+1:	ll      t0, (t1)
 	addiu   t0, 1
-	sc      t0, %lo(irq_err_count)(t1)
+	sc      t0, (t1)
 #if R10000_LLSC_WAR
 	beqzl	t0, 1b
 #else
 	beqz	t0, 1b
 #endif
 #else
-	lui     t1, %hi(irq_err_count)
-	lw      t0, %lo(irq_err_count)(t1)
+	lw      t0, (t1)
 	addiu   t0, 1
-	sw      t0, %lo(irq_err_count)(t1)
+	sw      t0, (t1)
 #endif
 	j	ret_from_irq
 	END(spurious_interrupt)
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 512bedb..83b8986 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -52,16 +52,15 @@
 		/*
 		 * Called from user mode, go somewhere else.
 		 */
-		lui	k1, %hi(saved_vectors)
 		mfc0	k0, CP0_CAUSE
 		andi	k0, k0, 0x7c
 		add	k1, k1, k0
-		lw	k0, %lo(saved_vectors)(k1)
+		PTR_L	k0, saved_vectors(k1)
 		jr	k0
 		nop
 1:
 		move	k0, sp
-		subu	sp, k1, GDB_FR_SIZE*2	# see comment above
+		PTR_SUBU sp, k1, GDB_FR_SIZE*2	# see comment above
 		LONG_S	k0, GDB_FR_REG29(sp)
 		LONG_S	$2, GDB_FR_REG2(sp)
 
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index d3fd1ab..96d18c4 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -176,8 +176,10 @@
 /*
  * spin locks for smp case
  */
-static spinlock_t kgdb_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t kgdb_cpulock[NR_CPUS] = { [0 ... NR_CPUS-1] = SPIN_LOCK_UNLOCKED};
+static DEFINE_SPINLOCK(kgdb_lock);
+static raw_spinlock_t kgdb_cpulock[NR_CPUS] = {
+	[0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED;
+};
 
 /*
  * BUFMAX defines the maximum number of characters in inbound/outbound buffers
@@ -637,29 +639,32 @@
  * and only one can be active at a time.
  */
 extern spinlock_t smp_call_lock;
+
 void set_async_breakpoint(unsigned long *epc)
 {
 	/* skip breaking into userland */
 	if ((*epc & 0x80000000) == 0)
 		return;
 
+#ifdef CONFIG_SMP
 	/* avoid deadlock if someone is make IPC */
 	if (spin_is_locked(&smp_call_lock))
 		return;
+#endif
 
 	async_bp.addr = *epc;
 	*epc = (unsigned long)async_breakpoint;
 }
 
-void kgdb_wait(void *arg)
+static void kgdb_wait(void *arg)
 {
 	unsigned flags;
 	int cpu = smp_processor_id();
 
 	local_irq_save(flags);
 
-	spin_lock(&kgdb_cpulock[cpu]);
-	spin_unlock(&kgdb_cpulock[cpu]);
+	__raw_spin_lock(&kgdb_cpulock[cpu]);
+	__raw_spin_unlock(&kgdb_cpulock[cpu]);
 
 	local_irq_restore(flags);
 }
@@ -707,7 +712,7 @@
 	 * acquire the CPU spinlocks
 	 */
 	for (i = num_online_cpus()-1; i >= 0; i--)
-		if (spin_trylock(&kgdb_cpulock[i]) == 0)
+		if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0)
 			panic("kgdb: couldn't get cpulock %d\n", i);
 
 	/*
@@ -982,7 +987,7 @@
 exit_kgdb_exception:
 	/* release locks so other CPUs can go */
 	for (i = num_online_cpus()-1; i >= 0; i--)
-		spin_unlock(&kgdb_cpulock[i]);
+		__raw_spin_unlock(&kgdb_cpulock[i]);
 	spin_unlock(&kgdb_lock);
 
 	__flush_cache_all();
@@ -1036,12 +1041,12 @@
  * malloc is needed by gdb client in "call func()", even a private one
  * will make gdb happy
  */
-static void *malloc(size_t size)
+static void * __attribute_used__ malloc(size_t size)
 {
 	return kmalloc(size, GFP_ATOMIC);
 }
 
-static void free(void *where)
+static void __attribute_used__ free (void *where)
 {
 	kfree(where);
 }
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index e7f6c1b..aa18a8b 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -82,7 +82,7 @@
 	 li	k0, 14<<2
 	beq	k1, k0, handle_vcei
 #ifdef CONFIG_64BIT
-	dsll	k1, k1, 1
+	 dsll	k1, k1, 1
 #endif
 	.set	pop
 	PTR_L	k0, exception_handlers(k1)
@@ -90,17 +90,17 @@
 
 	/*
 	 * Big shit, we now may have two dirty primary cache lines for the same
-	 * physical address.  We can savely invalidate the line pointed to by
+	 * physical address.  We can safely invalidate the line pointed to by
 	 * c0_badvaddr because after return from this exception handler the
 	 * load / store will be re-executed.
 	 */
 handle_vced:
-	DMFC0	k0, CP0_BADVADDR
+	MFC0	k0, CP0_BADVADDR
 	li	k1, -4					# Is this ...
 	and	k0, k1					# ... really needed?
 	mtc0	zero, CP0_TAGLO
-	cache	Index_Store_Tag_D,(k0)
-	cache	Hit_Writeback_Inv_SD,(k0)
+	cache	Index_Store_Tag_D, (k0)
+	cache	Hit_Writeback_Inv_SD, (k0)
 #ifdef CONFIG_PROC_FS
 	PTR_LA	k0, vced_count
 	lw	k1, (k0)
@@ -148,6 +148,38 @@
 	__FINIT
 
 /*
+ * Vectored interrupt handler.
+ * This prototype is copied to ebase + n*IntCtl.VS and patched
+ * to invoke the handler
+ */
+NESTED(except_vec_vi, 0, sp)
+	SAVE_SOME
+	SAVE_AT
+	.set	push
+	.set	noreorder
+EXPORT(except_vec_vi_lui)
+	lui	v0, 0		/* Patched */
+	j	except_vec_vi_handler
+EXPORT(except_vec_vi_ori)
+	 ori	v0, 0		/* Patched */
+	.set	pop
+	END(except_vec_vi)
+EXPORT(except_vec_vi_end)
+
+/*
+ * Common Vectored Interrupt code
+ * Complete the register saves and invoke the handler which is passed in $v0
+ */
+NESTED(except_vec_vi_handler, 0, sp)
+	SAVE_TEMP
+	SAVE_STATIC
+	CLI
+	move	a0, sp
+	jalr	v0
+	j	ret_from_irq
+	END(except_vec_vi_handler)
+
+/*
  * EJTAG debug exception handler.
  */
 NESTED(ejtag_debug_handler, PT_SIZE, sp)
@@ -291,6 +323,8 @@
 	BUILD_HANDLER mdmx mdmx sti silent		/* #22 */
 	BUILD_HANDLER watch watch sti verbose		/* #23 */
 	BUILD_HANDLER mcheck mcheck cli verbose		/* #24 */
+	BUILD_HANDLER mt mt sti verbose			/* #25 */
+	BUILD_HANDLER dsp dsp sti silent		/* #26 */
 	BUILD_HANDLER reserved reserved sti verbose	/* others */
 
 #ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/genrtc.c b/arch/mips/kernel/genrtc.c
deleted file mode 100644
index 71416e7..0000000
--- a/arch/mips/kernel/genrtc.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * A glue layer that provides RTC read/write to drivers/char/genrtc.c driver
- * based on MIPS internal RTC routines.  It does take care locking
- * issues so that we are SMP/Preemption safe.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Please read the COPYING file for all license details.
- */
-
-#include <linux/spinlock.h>
-
-#include <asm/rtc.h>
-#include <asm/time.h>
-
-static DEFINE_SPINLOCK(mips_rtc_lock);
-
-unsigned int get_rtc_time(struct rtc_time *time)
-{
-	unsigned long nowtime;
-
-	spin_lock(&mips_rtc_lock);
-	nowtime = rtc_get_time();
-	to_tm(nowtime, time);
-	time->tm_year -= 1900;
-	spin_unlock(&mips_rtc_lock);
-
-	return RTC_24H;
-}
-
-int set_rtc_time(struct rtc_time *time)
-{
-	unsigned long nowtime;
-	int ret;
-
-	spin_lock(&mips_rtc_lock);
-	nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
-			time->tm_mday, time->tm_hour, time->tm_min,
-			time->tm_sec);
-	ret = rtc_set_time(nowtime);
-	spin_unlock(&mips_rtc_lock);
-
-	return ret;
-}
-
-unsigned int get_rtc_ss(void)
-{
-	struct rtc_time h;
-
-	get_rtc_time(&h);
-	return h.tm_sec;
-}
-
-int get_rtc_pll(struct rtc_pll_info *pll)
-{
-	return -EINVAL;
-}
-
-int set_rtc_pll(struct rtc_pll_info *pll)
-{
-	return -EINVAL;
-}
-
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 2a1b45d..2e9122a 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -22,11 +22,8 @@
 #include <asm/page.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
-#ifdef CONFIG_SGI_IP27
-#include <asm/sn/addrs.h>
-#include <asm/sn/sn0/hubni.h>
-#include <asm/sn/klkernvars.h>
-#endif
+
+#include <kernel-entry-init.h>
 
 	.macro	ARC64_TWIDDLE_PC
 #if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL)
@@ -38,18 +35,6 @@
 #endif
 	.endm
 
-#ifdef CONFIG_SGI_IP27
-	/*
-	 * outputs the local nasid into res.  IP27 stuff.
-	 */
-	.macro GET_NASID_ASM res
-	dli	\res, LOCAL_HUB_ADDR(NI_STATUS_REV_ID)
-	ld	\res, (\res)
-	and	\res, NSRI_NODEID_MASK
-	dsrl	\res, NSRI_NODEID_SHFT
-	.endm
-#endif /* CONFIG_SGI_IP27 */
-
 	/*
 	 * inputs are the text nasid in t1, data nasid in t2.
 	 */
@@ -131,16 +116,21 @@
 EXPORT(stext)					# used for profiling
 EXPORT(_stext)
 
+#if defined(CONFIG_QEMU) || defined(CONFIG_MIPS_SIM)
+	/*
+	 * Give us a fighting chance of running if execution beings at the
+	 * kernel load address.  This is needed because this platform does
+	 * not have a ELF loader yet.
+	 */
+	j	kernel_entry
+#endif
 	__INIT
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
-	setup_c0_status_pri
 
-#ifdef CONFIG_SGI_IP27
-	GET_NASID_ASM	t1
-	move	t2, t1				# text and data are here
-	MAPPED_KERNEL_SETUP_TLB
-#endif /* IP27 */
+	kernel_entry_setup			# cpu specific setup
+
+	setup_c0_status_pri
 
 	ARC64_TWIDDLE_PC
 
@@ -157,6 +147,7 @@
 	LONG_S		a2, fw_arg2
 	LONG_S		a3, fw_arg3
 
+	MTC0		zero, CP0_CONTEXT	# clear context register
 	PTR_LA		$28, init_thread_union
 	PTR_ADDIU	sp, $28, _THREAD_SIZE - 32
 	set_saved_sp	sp, t0, t1
@@ -165,6 +156,10 @@
 	j		start_kernel
 	END(kernel_entry)
 
+#ifdef CONFIG_QEMU
+	__INIT
+#endif
+
 #ifdef CONFIG_SMP
 /*
  * SMP slave cpus entry point.  Board specific code for bootstrap calls this
@@ -172,20 +167,7 @@
  */
 NESTED(smp_bootstrap, 16, sp)
 	setup_c0_status_sec
-
-#ifdef CONFIG_SGI_IP27
-	GET_NASID_ASM	t1
-	dli	t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \
-		    KLDIR_OFF_POINTER + CAC_BASE
-	dsll	t1, NASID_SHFT
-	or	t0, t0, t1
-	ld	t0, 0(t0)			# t0 points to kern_vars struct
-	lh	t1, KV_RO_NASID_OFFSET(t0)
-	lh	t2, KV_RW_NASID_OFFSET(t0)
-	MAPPED_KERNEL_SETUP_TLB
-	ARC64_TWIDDLE_PC
-#endif /* CONFIG_SGI_IP27 */
-
+	smp_slave_setup
 	j	start_secondary
 	END(smp_bootstrap)
 #endif /* CONFIG_SMP */
@@ -200,19 +182,13 @@
 	.comm	fw_arg2, SZREG, SZREG
 	.comm	fw_arg3, SZREG, SZREG
 
-	.macro	page name, order=0
-	.globl	\name
-\name:	.size	\name, (_PAGE_SIZE << \order)
-	.org	. + (_PAGE_SIZE << \order)
-	.type	\name, @object
+	.macro page name, order
+	.comm	\name, (_PAGE_SIZE << \order), (_PAGE_SIZE << \order)
 	.endm
 
-	.data
-	.align	PAGE_SHIFT
-
 	/*
-	 * ... but on 64-bit we've got three-level pagetables with a
-	 * slightly different layout ...
+	 * On 64-bit we've got three-level pagetables with a slightly
+	 * different layout ...
 	 */
 	page	swapper_pg_dir, _PGD_ORDER
 #ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 4477592..b974ac9 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -31,7 +31,7 @@
  * moves to arch independent land
  */
 
-spinlock_t DEFINE_SPINLOCK(i8259A_lock);
+DEFINE_SPINLOCK(i8259A_lock);
 
 static void end_8259A_irq (unsigned int irq)
 {
@@ -52,14 +52,13 @@
 }
 
 static struct hw_interrupt_type i8259A_irq_type = {
-	"XT-PIC",
-	startup_8259A_irq,
-	shutdown_8259A_irq,
-	enable_8259A_irq,
-	disable_8259A_irq,
-	mask_and_ack_8259A,
-	end_8259A_irq,
-	NULL
+	.typename = "XT-PIC",
+	.startup = startup_8259A_irq,
+	.shutdown = shutdown_8259A_irq,
+	.enable = enable_8259A_irq,
+	.disable = disable_8259A_irq,
+	.ack = mask_and_ack_8259A,
+	.end = end_8259A_irq,
 };
 
 /*
@@ -308,7 +307,7 @@
 
 /*
  * On systems with i8259-style interrupt controllers we assume for
- * driver compatibility reasons interrupts 0 - 15 to be the i8295
+ * driver compatibility reasons interrupts 0 - 15 to be the i8259
  * interrupts even if the hardware uses a different interrupt numbering.
  */
 void __init init_i8259_irqs (void)
@@ -322,7 +321,7 @@
 
 	for (i = 0; i < 16; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = 0;
+		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;
 		irq_desc[i].handler = &i8259A_irq_type;
 	}
diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c
index c069719..ed9b2da 100644
--- a/arch/mips/kernel/ioctl32.c
+++ b/arch/mips/kernel/ioctl32.c
@@ -41,12 +41,6 @@
 #define DECLARES
 #include "compat_ioctl.c"
 
-#ifdef CONFIG_SIBYTE_TBPROF
-COMPATIBLE_IOCTL(SBPROF_ZBSTART)
-COMPATIBLE_IOCTL(SBPROF_ZBSTOP)
-COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL)
-#endif /* CONFIG_SIBYTE_TBPROF */
-
 /*HANDLE_IOCTL(RTC_IRQP_READ, w_long)
 COMPATIBLE_IOCTL(RTC_IRQP_SET)
 HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 4af20cd..10d3644 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -8,7 +8,7 @@
  *
  * Copyright (C) 1993 - 1994 Eric Youngdale <ericy@cais.com>
  * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com>
- * Copyright (C) 2004 Steven J. Hill <sjhill@realitydiluted.com>
+ * Copyright (C) 2004 - 2005 Steven J. Hill <sjhill@realitydiluted.com>
  */
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -31,15 +31,16 @@
 #include <linux/elfcore.h>
 #include <linux/smp_lock.h>
 
-#include <asm/uaccess.h>
 #include <asm/mipsregs.h>
+#include <asm/namei.h>
 #include <asm/prctl.h>
+#include <asm/uaccess.h>
 
 #define DLINFO_ITEMS 12
 
 #include <linux/elf.h>
 
-#undef DEBUG_ELF
+#undef DEBUG
 
 static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_irix_library(struct file *);
@@ -55,7 +56,7 @@
 #define elf_addr_t unsigned long
 #endif
 
-#ifdef DEBUG_ELF
+#ifdef DEBUG
 /* Debugging routines. */
 static char *get_elf_p_type(Elf32_Word p_type)
 {
@@ -120,7 +121,7 @@
 			print_phdr(i, ep);
 	}
 }
-#endif /* (DEBUG_ELF) */
+#endif /* DEBUG */
 
 static void set_brk(unsigned long start, unsigned long end)
 {
@@ -146,20 +147,20 @@
 	nbyte = elf_bss & (PAGE_SIZE-1);
 	if (nbyte) {
 		nbyte = PAGE_SIZE - nbyte;
-		clear_user((void *) elf_bss, nbyte);
+		clear_user((void __user *) elf_bss, nbyte);
 	}
 }
 
-unsigned long * create_irix_tables(char * p, int argc, int envc,
-				   struct elfhdr * exec, unsigned int load_addr,
-				   unsigned int interp_load_addr,
-				   struct pt_regs *regs, struct elf_phdr *ephdr)
+static unsigned long * create_irix_tables(char * p, int argc, int envc,
+	struct elfhdr * exec, unsigned int load_addr,
+	unsigned int interp_load_addr, struct pt_regs *regs,
+	struct elf_phdr *ephdr)
 {
 	elf_addr_t *argv;
 	elf_addr_t *envp;
 	elf_addr_t *sp, *csp;
 
-#ifdef DEBUG_ELF
+#ifdef DEBUG
 	printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
 	       "load_addr[%08x] interp_load_addr[%08x]\n",
 	       p, argc, envc, load_addr, interp_load_addr);
@@ -248,14 +249,13 @@
 	last_bss = 0;
 	error = load_addr = 0;
 
-#ifdef DEBUG_ELF
+#ifdef DEBUG
 	print_elfhdr(interp_elf_ex);
 #endif
 
 	/* First of all, some simple consistency checks */
 	if ((interp_elf_ex->e_type != ET_EXEC &&
 	     interp_elf_ex->e_type != ET_DYN) ||
-	     !irix_elf_check_arch(interp_elf_ex) ||
 	     !interpreter->f_op->mmap) {
 		printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);
 		return 0xffffffff;
@@ -290,7 +290,7 @@
 			   (char *) elf_phdata,
 			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
-#ifdef DEBUG_ELF
+#ifdef DEBUG
 	dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);
 #endif
 
@@ -306,13 +306,11 @@
 	    elf_type |= MAP_FIXED;
 	    vaddr = eppnt->p_vaddr;
 
-#ifdef DEBUG_ELF
-	    printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
+	    pr_debug("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
 		   interpreter, vaddr,
 		   (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
 		   (unsigned long) elf_prot, (unsigned long) elf_type,
 		   (unsigned long) (eppnt->p_offset & 0xfffff000));
-#endif
 	    down_write(&current->mm->mmap_sem);
 	    error = do_mmap(interpreter, vaddr,
 			    eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
@@ -324,14 +322,10 @@
 		    printk("Aieee IRIX interp mmap error=%d\n", error);
 		    break;  /* Real error */
 	    }
-#ifdef DEBUG_ELF
-	    printk("error=%08lx ", (unsigned long) error);
-#endif
+	    pr_debug("error=%08lx ", (unsigned long) error);
 	    if(!load_addr && interp_elf_ex->e_type == ET_DYN) {
 	      load_addr = error;
-#ifdef DEBUG_ELF
-              printk("load_addr = error ");
-#endif
+              pr_debug("load_addr = error ");
 	    }
 
 	    /* Find the end of the file  mapping for this phdr, and keep
@@ -345,17 +339,13 @@
 	     */
 	    k = eppnt->p_memsz + eppnt->p_vaddr;
 	    if(k > last_bss) last_bss = k;
-#ifdef DEBUG_ELF
-	    printk("\n");
-#endif
+	    pr_debug("\n");
 	  }
 	}
 
 	/* Now use mmap to map the library into memory. */
 	if(error < 0 && error > -1024) {
-#ifdef DEBUG_ELF
-		printk("got error %d\n", error);
-#endif
+		pr_debug("got error %d\n", error);
 		kfree(elf_phdata);
 		return 0xffffffff;
 	}
@@ -365,16 +355,12 @@
 	 * that there are zero-mapped pages up to and including the
 	 * last bss page.
 	 */
-#ifdef DEBUG_ELF
-	printk("padzero(%08lx) ", (unsigned long) (elf_bss));
-#endif
+	pr_debug("padzero(%08lx) ", (unsigned long) (elf_bss));
 	padzero(elf_bss);
 	len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
 
-#ifdef DEBUG_ELF
-	printk("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss,
-	       (unsigned long) len);
-#endif
+	pr_debug("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss,
+	         (unsigned long) len);
 
 	/* Map the last of the bss segment */
 	if (last_bss > len) {
@@ -396,12 +382,7 @@
 
 	/* First of all, some simple consistency checks */
 	if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
-	    !irix_elf_check_arch(ehp) || !bprm->file->f_op->mmap) {
-		return -ENOEXEC;
-	}
-
-	/* Only support MIPS ARCH2 or greater IRIX binaries for now. */
-	if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) {
+	    !bprm->file->f_op->mmap) {
 		return -ENOEXEC;
 	}
 
@@ -411,16 +392,17 @@
 	 * XXX all registers as 64bits on cpu's capable of this at
 	 * XXX exception time plus frob the XTLB exception vector.
 	 */
-	if((ehp->e_flags & 0x20)) {
+	if((ehp->e_flags & EF_MIPS_ABI2))
 		return -ENOEXEC;
-	}
 
-	return 0; /* It's ok. */
+	return 0;
 }
 
-#define IRIX_INTERP_PREFIX "/usr/gnemul/irix"
-
-/* Look for an IRIX ELF interpreter. */
+/*
+ * This is where the detailed check is performed. Irix binaries
+ * use interpreters with 'libc.so' in the name, so this function
+ * can differentiate between Linux and Irix binaries.
+ */
 static inline int look_for_irix_interpreter(char **name,
 					    struct file **interpreter,
 					    struct elfhdr *interp_elf_ex,
@@ -440,12 +422,11 @@
 		if (*name != NULL)
 			goto out;
 
-		*name = kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)),
-				GFP_KERNEL);
+		*name = kmalloc(epp->p_filesz + strlen(IRIX_EMUL), GFP_KERNEL);
 		if (!*name)
 			return -ENOMEM;
 
-		strcpy(*name, IRIX_INTERP_PREFIX);
+		strcpy(*name, IRIX_EMUL);
 		retval = kernel_read(bprm->file, epp->p_offset, (*name + 16),
 		                     epp->p_filesz);
 		if (retval < 0)
@@ -562,7 +543,7 @@
  * process and the system, here we map the page and fill the
  * structure
  */
-void irix_map_prda_page (void)
+static void irix_map_prda_page(void)
 {
 	unsigned long v;
 	struct prda *pp;
@@ -601,14 +582,33 @@
 
 	load_addr = 0;
 	has_interp = has_ephdr = 0;
-	elf_ihdr = elf_ephdr = 0;
+	elf_ihdr = elf_ephdr = NULL;
 	elf_ex = *((struct elfhdr *) bprm->buf);
 	retval = -ENOEXEC;
 
 	if (verify_binary(&elf_ex, bprm))
 		goto out;
 
-#ifdef DEBUG_ELF
+	/*
+	 * Telling -o32 static binaries from Linux and Irix apart from each
+	 * other is difficult. There are 2 differences to be noted for static
+	 * binaries from the 2 operating systems:
+	 *
+	 *    1) Irix binaries have their .text section before their .init
+	 *       section. Linux binaries are just the opposite.
+	 *
+	 *    2) Irix binaries usually have <= 12 sections and Linux
+	 *       binaries have > 20.
+	 *
+	 * We will use Method #2 since Method #1 would require us to read in
+	 * the section headers which is way too much overhead. This appears
+	 * to work for everything we have ran into so far. If anyone has a
+	 * better method to tell the binaries apart, I'm listening.
+	 */
+	if (elf_ex.e_shnum > 20)
+		goto out;
+
+#ifdef DEBUG
 	print_elfhdr(&elf_ex);
 #endif
 
@@ -623,11 +623,10 @@
 	}
 
 	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size);
-
 	if (retval < 0)
 		goto out_free_ph;
 
-#ifdef DEBUG_ELF
+#ifdef DEBUG
 	dump_phdrs(elf_phdata, elf_ex.e_phnum);
 #endif
 
@@ -644,9 +643,8 @@
 			break;
 		};
 	}
-#ifdef DEBUG_ELF
-	printk("\n");
-#endif
+
+	pr_debug("\n");
 
 	elf_bss = 0;
 	elf_brk = 0;
@@ -657,12 +655,19 @@
 	end_code = 0;
 	end_data = 0;
 
-	retval = look_for_irix_interpreter(&elf_interpreter,
-	                                   &interpreter,
+	/*
+	 * If we get a return value, we change the value to be ENOEXEC
+	 * so that we can exit gracefully and the main binary format
+	 * search loop in 'fs/exec.c' will move onto the next handler
+	 * which should be the normal ELF binary handler.
+	 */
+	retval = look_for_irix_interpreter(&elf_interpreter, &interpreter,
 					   &interp_elf_ex, elf_phdata, bprm,
 					   elf_ex.e_phnum);
-	if (retval)
+	if (retval) {
+		retval = -ENOEXEC;
 		goto out_free_file;
+	}
 
 	if (elf_interpreter) {
 		retval = verify_irix_interpreter(&interp_elf_ex);
@@ -692,7 +697,6 @@
 	/* Do this so that we can load the interpreter, if need be.  We will
 	 * change some of these later.
 	 */
-	set_mm_counter(current->mm, rss, 0);
 	setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
 	current->mm->start_stack = bprm->p;
 
@@ -746,18 +750,16 @@
 	 * IRIX maps a page at 0x200000 which holds some system
 	 * information.  Programs depend on this.
 	 */
-	irix_map_prda_page ();
+	irix_map_prda_page();
 
 	padzero(elf_bss);
 
-#ifdef DEBUG_ELF
-	printk("(start_brk) %lx\n" , (long) current->mm->start_brk);
-	printk("(end_code) %lx\n" , (long) current->mm->end_code);
-	printk("(start_code) %lx\n" , (long) current->mm->start_code);
-	printk("(end_data) %lx\n" , (long) current->mm->end_data);
-	printk("(start_stack) %lx\n" , (long) current->mm->start_stack);
-	printk("(brk) %lx\n" , (long) current->mm->brk);
-#endif
+	pr_debug("(start_brk) %lx\n" , (long) current->mm->start_brk);
+	pr_debug("(end_code) %lx\n" , (long) current->mm->end_code);
+	pr_debug("(start_code) %lx\n" , (long) current->mm->start_code);
+	pr_debug("(end_data) %lx\n" , (long) current->mm->end_data);
+	pr_debug("(start_stack) %lx\n" , (long) current->mm->start_stack);
+	pr_debug("(brk) %lx\n" , (long) current->mm->brk);
 
 #if 0 /* XXX No fucking way dude... */
 	/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
@@ -782,8 +784,7 @@
 	allow_write_access(interpreter);
 	fput(interpreter);
 out_free_interp:
-	if (elf_interpreter)
-		kfree(elf_interpreter);
+	kfree(elf_interpreter);
 out_free_file:
 out_free_ph:
 	kfree (elf_phdata);
@@ -813,7 +814,7 @@
 
 	/* First of all, some simple consistency checks. */
 	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-	   !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap)
+	   !file->f_op->mmap)
 		return -ENOEXEC;
 
 	/* Now read in all of the header information. */
@@ -874,35 +875,36 @@
  * phdrs there are in the USER_PHDRP array.  We return the vaddr the
  * first phdr was successfully mapped to.
  */
-unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt)
+unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt)
 {
-	struct elf_phdr *hp;
+	unsigned long type, vaddr, filesz, offset, flags;
+	struct elf_phdr __user *hp;
 	struct file *filp;
 	int i, retval;
 
-#ifdef DEBUG_ELF
-	printk("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n",
-	       fd, user_phdrp, cnt);
-#endif
+	pr_debug("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n",
+	         fd, user_phdrp, cnt);
 
 	/* First get the verification out of the way. */
 	hp = user_phdrp;
 	if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) {
-#ifdef DEBUG_ELF
-		printk("irix_mapelf: access_ok fails!\n");
-#endif
+		pr_debug("irix_mapelf: bad pointer to ELF PHDR!\n");
+
 		return -EFAULT;
 	}
 
-#ifdef DEBUG_ELF
+#ifdef DEBUG
 	dump_phdrs(user_phdrp, cnt);
 #endif
 
-	for(i = 0; i < cnt; i++, hp++)
-		if(hp->p_type != PT_LOAD) {
+	for (i = 0; i < cnt; i++, hp++) {
+		if (__get_user(type, &hp->p_type))
+			return -EFAULT;
+		if (type != PT_LOAD) {
 			printk("irix_mapelf: One section is not PT_LOAD!\n");
 			return -ENOEXEC;
 		}
+	}
 
 	filp = fget(fd);
 	if (!filp)
@@ -917,29 +919,40 @@
 	for(i = 0; i < cnt; i++, hp++) {
 		int prot;
 
-		prot  = (hp->p_flags & PF_R) ? PROT_READ : 0;
-		prot |= (hp->p_flags & PF_W) ? PROT_WRITE : 0;
-		prot |= (hp->p_flags & PF_X) ? PROT_EXEC : 0;
+		retval = __get_user(vaddr, &hp->p_vaddr);
+		retval |= __get_user(filesz, &hp->p_filesz);
+		retval |= __get_user(offset, &hp->p_offset);
+		retval |= __get_user(flags, &hp->p_flags);
+		if (retval)
+			return retval;
+
+		prot  = (flags & PF_R) ? PROT_READ : 0;
+		prot |= (flags & PF_W) ? PROT_WRITE : 0;
+		prot |= (flags & PF_X) ? PROT_EXEC : 0;
+
 		down_write(&current->mm->mmap_sem);
-		retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000),
-				 (hp->p_filesz + (hp->p_vaddr & 0xfff)),
+		retval = do_mmap(filp, (vaddr & 0xfffff000),
+				 (filesz + (vaddr & 0xfff)),
 				 prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
-				 (hp->p_offset & 0xfffff000));
+				 (offset & 0xfffff000));
 		up_write(&current->mm->mmap_sem);
 
-		if(retval != (hp->p_vaddr & 0xfffff000)) {
+		if (retval != (vaddr & 0xfffff000)) {
 			printk("irix_mapelf: do_mmap fails with %d!\n", retval);
 			fput(filp);
 			return retval;
 		}
 	}
 
-#ifdef DEBUG_ELF
-	printk("irix_mapelf: Success, returning %08lx\n",
-		(unsigned long) user_phdrp->p_vaddr);
-#endif
+	pr_debug("irix_mapelf: Success, returning %08lx\n",
+		 (unsigned long) user_phdrp->p_vaddr);
+
 	fput(filp);
-	return user_phdrp->p_vaddr;
+
+	if (__get_user(vaddr, &user_phdrp->p_vaddr))
+		return -EFAULT;
+
+	return vaddr;
 }
 
 /*
@@ -952,9 +965,9 @@
 /* These are the only things you should do on a core-file: use only these
  * functions to write out all the necessary info.
  */
-static int dump_write(struct file *file, const void *addr, int nr)
+static int dump_write(struct file *file, const void __user *addr, int nr)
 {
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+	return file->f_op->write(file, (const char __user *) addr, nr, &file->f_pos) == nr;
 }
 
 static int dump_seek(struct file *file, off_t off)
@@ -1064,8 +1077,8 @@
 	struct elfhdr elf;
 	off_t offset = 0, dataoff;
 	int limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
-	int numnote = 4;
-	struct memelfnote notes[4];
+	int numnote = 3;
+	struct memelfnote notes[3];
 	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
 	elf_fpregset_t fpu;		/* NT_PRFPREG */
 	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
@@ -1073,7 +1086,7 @@
 	/* Count what's needed to dump, up to the limit of coredump size. */
 	segs = 0;
 	size = 0;
-	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		if (maydump(vma))
 		{
 			int sz = vma->vm_end-vma->vm_start;
@@ -1187,9 +1200,9 @@
 
 		len = current->mm->arg_end - current->mm->arg_start;
 		len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len;
-		copy_from_user(&psinfo.pr_psargs,
-			       (const char *)current->mm->arg_start, len);
-		for(i = 0; i < len; i++)
+		(void *) copy_from_user(&psinfo.pr_psargs,
+			       (const char __user *)current->mm->arg_start, len);
+		for (i = 0; i < len; i++)
 			if (psinfo.pr_psargs[i] == 0)
 				psinfo.pr_psargs[i] = ' ';
 		psinfo.pr_psargs[len] = 0;
@@ -1198,20 +1211,15 @@
 	}
 	strlcpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
 
-	notes[2].name = "CORE";
-	notes[2].type = NT_TASKSTRUCT;
-	notes[2].datasz = sizeof(*current);
-	notes[2].data = current;
-
 	/* Try to dump the FPU. */
 	prstatus.pr_fpvalid = dump_fpu (regs, &fpu);
 	if (!prstatus.pr_fpvalid) {
 		numnote--;
 	} else {
-		notes[3].name = "CORE";
-		notes[3].type = NT_PRFPREG;
-		notes[3].datasz = sizeof(fpu);
-		notes[3].data = &fpu;
+		notes[2].name = "CORE";
+		notes[2].type = NT_PRFPREG;
+		notes[2].datasz = sizeof(fpu);
+		notes[2].data = &fpu;
 	}
 
 	/* Write notes phdr entry. */
@@ -1256,8 +1264,10 @@
 		phdr.p_memsz = sz;
 		offset += phdr.p_filesz;
 		phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
-		if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
-		if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
+		if (vma->vm_flags & VM_WRITE)
+			phdr.p_flags |= PF_W;
+		if (vma->vm_flags & VM_EXEC)
+			phdr.p_flags |= PF_X;
 		phdr.p_align = PAGE_SIZE;
 
 		DUMP_WRITE(&phdr, sizeof(phdr));
@@ -1283,7 +1293,7 @@
 #ifdef DEBUG
 		printk("elf_core_dump: writing %08lx %lx\n", addr, len);
 #endif
-		DUMP_WRITE((void *)addr, len);
+		DUMP_WRITE((void __user *)addr, len);
 	}
 
 	if ((off_t) file->f_pos != offset) {
@@ -1299,7 +1309,7 @@
 
 static int __init init_irix_binfmt(void)
 {
-	int init_inventory(void);
+	extern int init_inventory(void);
 	extern asmlinkage unsigned long sys_call_table;
 	extern asmlinkage unsigned long sys_call_table_irix5;
 
@@ -1318,7 +1328,9 @@
 
 static void __exit exit_irix_binfmt(void)
 {
-	/* Remove the IRIX ELF loaders. */
+	/*
+	 * Remove the Irix ELF loader.
+	 */
 	unregister_binfmt(&irix_format);
 }
 
diff --git a/arch/mips/kernel/irixinv.c b/arch/mips/kernel/irixinv.c
index 60aa98c..de8584f6 100644
--- a/arch/mips/kernel/irixinv.c
+++ b/arch/mips/kernel/irixinv.c
@@ -30,10 +30,10 @@
 	inventory_items++;
 }
 
-int dump_inventory_to_user (void *userbuf, int size)
+int dump_inventory_to_user (void __user *userbuf, int size)
 {
 	inventory_t *inv  = &inventory [0];
-	inventory_t *user = userbuf;
+	inventory_t __user *user = userbuf;
 	int v;
 
 	if (!access_ok(VERIFY_WRITE, userbuf, size))
@@ -41,7 +41,8 @@
 
 	for (v = 0; v < inventory_items; v++){
 		inv = &inventory [v];
-		copy_to_user (user, inv, sizeof (inventory_t));
+		if (copy_to_user (user, inv, sizeof (inventory_t)))
+			return -EFAULT;
 		user++;
 	}
 	return inventory_items * sizeof (inventory_t);
diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c
index 3cdc223..e286382 100644
--- a/arch/mips/kernel/irixioctl.c
+++ b/arch/mips/kernel/irixioctl.c
@@ -59,7 +59,7 @@
 {
 	struct tty_struct *tp, *rtp;
 	mm_segment_t old_fs;
-	int error = 0;
+	int i, error = 0;
 
 #ifdef DEBUG_IOCTLS
 	printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
@@ -74,12 +74,13 @@
 
 	case 0x0000540d: {
 		struct termios kt;
-		struct irix_termios *it = (struct irix_termios *) arg;
+		struct irix_termios __user *it =
+			(struct irix_termios __user *) arg;
 
 #ifdef DEBUG_IOCTLS
 		printk("TCGETS, %08lx) ", arg);
 #endif
-		if(!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
+		if (!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
 			error = -EFAULT;
 			break;
 		}
@@ -88,13 +89,14 @@
 		set_fs(old_fs);
 		if (error)
 			break;
-		__put_user(kt.c_iflag, &it->c_iflag);
-		__put_user(kt.c_oflag, &it->c_oflag);
-		__put_user(kt.c_cflag, &it->c_cflag);
-		__put_user(kt.c_lflag, &it->c_lflag);
-		for(error = 0; error < NCCS; error++)
-			__put_user(kt.c_cc[error], &it->c_cc[error]);
-		error = 0;
+
+		error = __put_user(kt.c_iflag, &it->c_iflag);
+		error |= __put_user(kt.c_oflag, &it->c_oflag);
+		error |= __put_user(kt.c_cflag, &it->c_cflag);
+		error |= __put_user(kt.c_lflag, &it->c_lflag);
+
+		for (i = 0; i < NCCS; i++)
+			error |= __put_user(kt.c_cc[i], &it->c_cc[i]);
 		break;
 	}
 
@@ -112,14 +114,19 @@
 		old_fs = get_fs(); set_fs(get_ds());
 		error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
 		set_fs(old_fs);
-		if(error)
+		if (error)
 			break;
-		__get_user(kt.c_iflag, &it->c_iflag);
-		__get_user(kt.c_oflag, &it->c_oflag);
-		__get_user(kt.c_cflag, &it->c_cflag);
-		__get_user(kt.c_lflag, &it->c_lflag);
-		for(error = 0; error < NCCS; error++)
-			__get_user(kt.c_cc[error], &it->c_cc[error]);
+
+		error = __get_user(kt.c_iflag, &it->c_iflag);
+		error |= __get_user(kt.c_oflag, &it->c_oflag);
+		error |= __get_user(kt.c_cflag, &it->c_cflag);
+		error |= __get_user(kt.c_lflag, &it->c_lflag);
+
+		for (i = 0; i < NCCS; i++)
+			error |= __get_user(kt.c_cc[i], &it->c_cc[i]);
+
+		if (error)
+			break;
 		old_fs = get_fs(); set_fs(get_ds());
 		error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
 		set_fs(old_fs);
@@ -153,7 +160,7 @@
 #ifdef DEBUG_IOCTLS
 		printk("rtp->session=%d ", rtp->session);
 #endif
-		error = put_user(rtp->session, (unsigned long *) arg);
+		error = put_user(rtp->session, (unsigned long __user *) arg);
 		break;
 
 	case 0x746e:
@@ -195,50 +202,32 @@
 		break;
 
 	case 0x8004667e:
-#ifdef DEBUG_IOCTLS
-		printk("FIONBIO, %08lx) arg=%d ", arg, *(int *)arg);
-#endif
 		error = sys_ioctl(fd, FIONBIO, arg);
 		break;
 
 	case 0x80047476:
-#ifdef DEBUG_IOCTLS
-		printk("TIOCSPGRP, %08lx) arg=%d ", arg, *(int *)arg);
-#endif
 		error = sys_ioctl(fd, TIOCSPGRP, arg);
 		break;
 
 	case 0x8020690c:
-#ifdef DEBUG_IOCTLS
-		printk("SIOCSIFADDR, %08lx) arg=%d ", arg, *(int *)arg);
-#endif
 		error = sys_ioctl(fd, SIOCSIFADDR, arg);
 		break;
 
 	case 0x80206910:
-#ifdef DEBUG_IOCTLS
-		printk("SIOCSIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg);
-#endif
 		error = sys_ioctl(fd, SIOCSIFFLAGS, arg);
 		break;
 
 	case 0xc0206911:
-#ifdef DEBUG_IOCTLS
-		printk("SIOCGIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg);
-#endif
 		error = sys_ioctl(fd, SIOCGIFFLAGS, arg);
 		break;
 
 	case 0xc020691b:
-#ifdef DEBUG_IOCTLS
-		printk("SIOCGIFMETRIC, %08lx) arg=%d ", arg, *(int *)arg);
-#endif
 		error = sys_ioctl(fd, SIOCGIFMETRIC, arg);
 		break;
 
 	default: {
 #ifdef DEBUG_MISSING_IOCTL
-		char *msg = "Unimplemented IOCTL cmd tell linux@engr.sgi.com\n";
+		char *msg = "Unimplemented IOCTL cmd tell linux-mips@linux-mips.org\n";
 
 #ifdef DEBUG_IOCTLS
 		printk("UNIMP_IOCTL, %08lx)\n", arg);
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index eff8932..908e636 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -76,36 +76,39 @@
 }
 #endif
 
-static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
-			     int signr, sigset_t *oldmask)
+static int setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
+			    int signr, sigset_t *oldmask)
 {
+	struct sigctx_irix5 __user *ctx;
 	unsigned long sp;
-	struct sigctx_irix5 *ctx;
-	int i;
+	int error, i;
 
 	sp = regs->regs[29];
 	sp -= sizeof(struct sigctx_irix5);
 	sp &= ~(0xf);
-	ctx = (struct sigctx_irix5 *) sp;
+	ctx = (struct sigctx_irix5 __user *) sp;
 	if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
 		goto segv_and_exit;
 
-	__put_user(0, &ctx->weird_fpu_thing);
-	__put_user(~(0x00000001), &ctx->rmask);
-	__put_user(0, &ctx->regs[0]);
+	error = __put_user(0, &ctx->weird_fpu_thing);
+	error |= __put_user(~(0x00000001), &ctx->rmask);
+	error |= __put_user(0, &ctx->regs[0]);
 	for(i = 1; i < 32; i++)
-		__put_user((u64) regs->regs[i], &ctx->regs[i]);
+		error |= __put_user((u64) regs->regs[i], &ctx->regs[i]);
 
-	__put_user((u64) regs->hi, &ctx->hi);
-	__put_user((u64) regs->lo, &ctx->lo);
-	__put_user((u64) regs->cp0_epc, &ctx->pc);
-	__put_user(!!used_math(), &ctx->usedfp);
-	__put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
-	__put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
+	error |= __put_user((u64) regs->hi, &ctx->hi);
+	error |= __put_user((u64) regs->lo, &ctx->lo);
+	error |= __put_user((u64) regs->cp0_epc, &ctx->pc);
+	error |= __put_user(!!used_math(), &ctx->usedfp);
+	error |= __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
+	error |= __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
 
-	__put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
+	error |= __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
 
-	__copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t));
+	error |= __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t)) ? -EFAULT : 0;
+
+	if (error)
+		goto segv_and_exit;
 
 #ifdef DEBUG_SIG
 	dump_irix5_sigctx(ctx);
@@ -117,13 +120,14 @@
 	regs->regs[7] = (unsigned long) ka->sa.sa_handler;
 	regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa_restorer;
 
-	return;
+	return 1;
 
 segv_and_exit:
 	force_sigsegv(signr, current);
+	return 0;
 }
 
-static void inline
+static int inline
 setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
                int signr, sigset_t *oldmask, siginfo_t *info)
 {
@@ -131,9 +135,11 @@
 	do_exit(SIGSEGV);
 }
 
-static inline void handle_signal(unsigned long sig, siginfo_t *info,
+static inline int handle_signal(unsigned long sig, siginfo_t *info,
 	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
 {
+	int ret;
+
 	switch(regs->regs[0]) {
 	case ERESTARTNOHAND:
 		regs->regs[2] = EINTR;
@@ -151,9 +157,9 @@
 	regs->regs[0] = 0;		/* Don't deal with this again.  */
 
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_irix_rt_frame(ka, regs, sig, oldset, info);
+		ret = setup_irix_rt_frame(ka, regs, sig, oldset, info);
 	else
-		setup_irix_frame(ka, regs, sig, oldset);
+		ret = setup_irix_frame(ka, regs, sig, oldset);
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -161,6 +167,8 @@
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	return ret;
 }
 
 asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
@@ -184,10 +192,8 @@
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		handle_signal(signr, &info, &ka, oldset, regs);
-		return 1;
-	}
+	if (signr > 0)
+		return handle_signal(signr, &info, &ka, oldset, regs);
 
 no_signal:
 	/*
@@ -208,10 +214,11 @@
 asmlinkage void
 irix_sigreturn(struct pt_regs *regs)
 {
-	struct sigctx_irix5 *context, *magic;
+	struct sigctx_irix5 __user *context, *magic;
 	unsigned long umask, mask;
 	u64 *fregs;
-	int sig, i, base = 0;
+	u32 usedfp;
+	int error, sig, i, base = 0;
 	sigset_t blocked;
 
 	/* Always make any pending restarted system calls return -EINTR */
@@ -220,8 +227,8 @@
 	if (regs->regs[2] == 1000)
 		base = 1;
 
-	context = (struct sigctx_irix5 *) regs->regs[base + 4];
-	magic = (struct sigctx_irix5 *) regs->regs[base + 5];
+	context = (struct sigctx_irix5 __user *) regs->regs[base + 4];
+	magic = (struct sigctx_irix5 __user *) regs->regs[base + 5];
 	sig = (int) regs->regs[base + 6];
 #ifdef DEBUG_SIG
 	printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
@@ -236,25 +243,31 @@
 	dump_irix5_sigctx(context);
 #endif
 
-	__get_user(regs->cp0_epc, &context->pc);
-	umask = context->rmask; mask = 2;
-	for (i = 1; i < 32; i++, mask <<= 1) {
-		if(umask & mask)
-			__get_user(regs->regs[i], &context->regs[i]);
-	}
-	__get_user(regs->hi, &context->hi);
-	__get_user(regs->lo, &context->lo);
+	error = __get_user(regs->cp0_epc, &context->pc);
+	error |= __get_user(umask, &context->rmask);
 
-	if ((umask & 1) && context->usedfp) {
+	mask = 2;
+	for (i = 1; i < 32; i++, mask <<= 1) {
+		if (umask & mask)
+			error |= __get_user(regs->regs[i], &context->regs[i]);
+	}
+	error |= __get_user(regs->hi, &context->hi);
+	error |= __get_user(regs->lo, &context->lo);
+
+	error |= __get_user(usedfp, &context->usedfp);
+	if ((umask & 1) && usedfp) {
 		fregs = (u64 *) &current->thread.fpu;
+
 		for(i = 0; i < 32; i++)
-			fregs[i] = (u64) context->fpregs[i];
-		__get_user(current->thread.fpu.hard.fcr31, &context->fpcsr);
+			error |= __get_user(fregs[i], &context->fpregs[i]);
+		error |= __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr);
 	}
 
 	/* XXX do sigstack crapola here... XXX */
 
-	if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))
+	error |= __copy_from_user(&blocked, &context->sigset, sizeof(blocked)) ? -EFAULT : 0;
+
+	if (error)
 		goto badframe;
 
 	sigdelsetmask(&blocked, ~_BLOCKABLE);
@@ -296,8 +309,8 @@
 #endif
 
 asmlinkage int
-irix_sigaction(int sig, const struct sigaction *act,
-	      struct sigaction *oact, void *trampoline)
+irix_sigaction(int sig, const struct sigaction __user *act,
+	      struct sigaction __user *oact, void __user *trampoline)
 {
 	struct k_sigaction new_ka, old_ka;
 	int ret;
@@ -311,12 +324,16 @@
 #endif
 	if (act) {
 		sigset_t mask;
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))
-			return -EFAULT;
+		int err;
 
-		__copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+			return -EFAULT;
+		err = __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+		err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+
+		err |= __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)) ? -EFAULT : 0;
+		if (err)
+			return err;
 
 		/*
 		 * Hmmm... methinks IRIX libc always passes a valid trampoline
@@ -330,30 +347,37 @@
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+		int err;
+
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
 			return -EFAULT;
-		__copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
-		               sizeof(sigset_t));
+
+		err = __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+		err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		err |= __copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask,
+		               sizeof(sigset_t)) ? -EFAULT : 0;
+		if (err)
+			return -EFAULT;
 	}
 
 	return ret;
 }
 
-asmlinkage int irix_sigpending(irix_sigset_t *set)
+asmlinkage int irix_sigpending(irix_sigset_t __user *set)
 {
 	return do_sigpending(set, sizeof(*set));
 }
 
-asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
+asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
+	irix_sigset_t __user *old)
 {
 	sigset_t oldbits, newbits;
 
 	if (new) {
 		if (!access_ok(VERIFY_READ, new, sizeof(*new)))
 			return -EFAULT;
-		__copy_from_user(&newbits, new, sizeof(unsigned long)*4);
+		if (__copy_from_user(&newbits, new, sizeof(unsigned long)*4))
+			return -EFAULT;
 		sigdelsetmask(&newbits, ~_BLOCKABLE);
 
 		spin_lock_irq(&current->sighand->siglock);
@@ -381,20 +405,19 @@
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
 	}
-	if(old) {
-		if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
-			return -EFAULT;
-		__copy_to_user(old, &current->blocked, sizeof(unsigned long)*4);
-	}
+	if (old)
+		return copy_to_user(old, &current->blocked,
+		                  sizeof(unsigned long)*4) ? -EFAULT : 0;
 
 	return 0;
 }
 
 asmlinkage int irix_sigsuspend(struct pt_regs *regs)
 {
-	sigset_t *uset, saveset, newset;
+	sigset_t saveset, newset;
+	sigset_t __user *uset;
 
-	uset = (sigset_t *) regs->regs[4];
+	uset = (sigset_t __user *) regs->regs[4];
 	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -440,12 +463,13 @@
 	} stuff;
 };
 
-asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
-				struct timespec *tp)
+asmlinkage int irix_sigpoll_sys(unsigned long __user *set,
+	struct irix5_siginfo __user *info, struct timespec __user *tp)
 {
 	long expire = MAX_SCHEDULE_TIMEOUT;
 	sigset_t kset;
 	int i, sig, error, timeo = 0;
+	struct timespec ktp;
 
 #ifdef DEBUG_SIG
 	printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
@@ -456,14 +480,8 @@
 	if (!set)
 		return -EINVAL;
 
-	if (!access_ok(VERIFY_READ, set, sizeof(kset))) {
-		error = -EFAULT;
-		goto out;
-	}
-
-	__copy_from_user(&kset, set, sizeof(set));
-	if (error)
-		goto out;
+	if (copy_from_user(&kset, set, sizeof(set)))
+		return -EFAULT;
 
 	if (info && clear_user(info, sizeof(*info))) {
 		error = -EFAULT;
@@ -471,19 +489,21 @@
 	}
 
 	if (tp) {
-		if (!access_ok(VERIFY_READ, tp, sizeof(*tp)))
+		if (copy_from_user(&ktp, tp, sizeof(*tp)))
 			return -EFAULT;
-		if (!tp->tv_sec && !tp->tv_nsec) {
-			error = -EINVAL;
-			goto out;
-		}
-		expire = timespec_to_jiffies(tp) + (tp->tv_sec||tp->tv_nsec);
+
+		if (!ktp.tv_sec && !ktp.tv_nsec)
+			return -EINVAL;
+
+		expire = timespec_to_jiffies(&ktp) +
+		         (ktp.tv_sec || ktp.tv_nsec);
 	}
 
 	while(1) {
 		long tmp = 0;
 
-		expire = schedule_timeout_interruptible(expire);
+		current->state = TASK_INTERRUPTIBLE;
+		expire = schedule_timeout(expire);
 
 		for (i=0; i<=4; i++)
 			tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
@@ -500,15 +520,14 @@
 	if (timeo)
 		return -EAGAIN;
 
-	for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
+	for (sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
 		if (sigismember (&kset, sig))
 			continue;
 		if (sigismember (&current->pending.signal, sig)) {
 			/* XXX need more than this... */
 			if (info)
-				info->sig = sig;
-			error = 0;
-			goto out;
+				return copy_to_user(&info->sig, &sig, sizeof(sig));
+			return 0;
 		}
 	}
 
@@ -534,8 +553,9 @@
 
 #define W_MASK      (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
 
-asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
-			    int options, struct rusage *ru)
+asmlinkage int irix_waitsys(int type, int pid,
+	struct irix5_siginfo __user *info, int options,
+	struct rusage __user *ru)
 {
 	int flag, retval;
 	DECLARE_WAITQUEUE(wait, current);
@@ -543,28 +563,22 @@
 	struct task_struct *p;
 	struct list_head *_p;
 
-	if (!info) {
-		retval = -EINVAL;
-		goto out;
-	}
-	if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) {
-		retval = -EFAULT;
-		goto out;
-	}
-	if (ru) {
-		if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru))) {
-			retval = -EFAULT;
-			goto out;
-		}
-	}
-	if (options & ~(W_MASK)) {
-		retval = -EINVAL;
-		goto out;
-	}
-	if (type != IRIX_P_PID && type != IRIX_P_PGID && type != IRIX_P_ALL) {
-		retval = -EINVAL;
-		goto out;
-	}
+	if (!info)
+		return -EINVAL;
+
+	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+		return -EFAULT;
+
+	if (ru)
+		if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)))
+			return -EFAULT;
+
+	if (options & ~W_MASK)
+		return -EINVAL;
+
+	if (type != IRIX_P_PID && type != IRIX_P_PGID && type != IRIX_P_ALL)
+		return -EINVAL;
+
 	add_wait_queue(&current->signal->wait_chldexit, &wait);
 repeat:
 	flag = 0;
@@ -595,18 +609,20 @@
 			add_parent(p, p->parent);
 			write_unlock_irq(&tasklist_lock);
 			retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
-			if (!retval && ru) {
-				retval |= __put_user(SIGCHLD, &info->sig);
-				retval |= __put_user(0, &info->code);
-				retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
-				retval |= __put_user((p->exit_code >> 8) & 0xff,
-				           &info->stuff.procinfo.procdata.child.status);
-				retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
-				retval |= __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime);
-			}
-			if (!retval) {
-				p->exit_code = 0;
-			}
+			if (retval)
+				goto end_waitsys;
+
+			retval = __put_user(SIGCHLD, &info->sig);
+			retval |= __put_user(0, &info->code);
+			retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
+			retval |= __put_user((p->exit_code >> 8) & 0xff,
+			           &info->stuff.procinfo.procdata.child.status);
+			retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
+			retval |= __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime);
+			if (retval)
+				goto end_waitsys;
+
+			p->exit_code = 0;
 			goto end_waitsys;
 
 		case EXIT_ZOMBIE:
@@ -614,16 +630,18 @@
 			current->signal->cstime += p->stime + p->signal->cstime;
 			if (ru != NULL)
 				getrusage(p, RUSAGE_BOTH, ru);
-			__put_user(SIGCHLD, &info->sig);
-			__put_user(1, &info->code);      /* CLD_EXITED */
-			__put_user(p->pid, &info->stuff.procinfo.pid);
-			__put_user((p->exit_code >> 8) & 0xff,
+			retval = __put_user(SIGCHLD, &info->sig);
+			retval |= __put_user(1, &info->code);      /* CLD_EXITED */
+			retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
+			retval |= __put_user((p->exit_code >> 8) & 0xff,
 			           &info->stuff.procinfo.procdata.child.status);
-			__put_user(p->utime,
+			retval |= __put_user(p->utime,
 			           &info->stuff.procinfo.procdata.child.utime);
-			__put_user(p->stime,
+			retval |= __put_user(p->stime,
 			           &info->stuff.procinfo.procdata.child.stime);
-			retval = 0;
+			if (retval)
+				return retval;
+
 			if (p->real_parent != p->parent) {
 				write_lock_irq(&tasklist_lock);
 				remove_parent(p);
@@ -656,7 +674,6 @@
 	current->state = TASK_RUNNING;
 	remove_wait_queue(&current->signal->wait_chldexit, &wait);
 
-out:
 	return retval;
 }
 
@@ -675,39 +692,39 @@
 
 asmlinkage int irix_getcontext(struct pt_regs *regs)
 {
-	int i, base = 0;
-	struct irix5_context *ctx;
+	int error, i, base = 0;
+	struct irix5_context __user *ctx;
 	unsigned long flags;
 
 	if (regs->regs[2] == 1000)
 		base = 1;
-	ctx = (struct irix5_context *) regs->regs[base + 4];
+	ctx = (struct irix5_context __user *) regs->regs[base + 4];
 
 #ifdef DEBUG_SIG
 	printk("[%s:%d] irix_getcontext(%p)\n",
 	       current->comm, current->pid, ctx);
 #endif
 
-	if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
+	if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)));
 		return -EFAULT;
 
-	__put_user(current->thread.irix_oldctx, &ctx->link);
+	error = __put_user(current->thread.irix_oldctx, &ctx->link);
 
-	__copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t));
+	error |= __copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t)) ? -EFAULT : 0;
 
 	/* XXX Do sigstack stuff someday... */
-	__put_user(0, &ctx->stack.sp);
-	__put_user(0, &ctx->stack.size);
-	__put_user(0, &ctx->stack.flags);
+	error |= __put_user(0, &ctx->stack.sp);
+	error |= __put_user(0, &ctx->stack.size);
+	error |= __put_user(0, &ctx->stack.flags);
 
-	__put_user(0, &ctx->weird_graphics_thing);
-	__put_user(0, &ctx->regs[0]);
+	error |= __put_user(0, &ctx->weird_graphics_thing);
+	error |= __put_user(0, &ctx->regs[0]);
 	for (i = 1; i < 32; i++)
-		__put_user(regs->regs[i], &ctx->regs[i]);
-	__put_user(regs->lo, &ctx->regs[32]);
-	__put_user(regs->hi, &ctx->regs[33]);
-	__put_user(regs->cp0_cause, &ctx->regs[34]);
-	__put_user(regs->cp0_epc, &ctx->regs[35]);
+		error |= __put_user(regs->regs[i], &ctx->regs[i]);
+	error |= __put_user(regs->lo, &ctx->regs[32]);
+	error |= __put_user(regs->hi, &ctx->regs[33]);
+	error |= __put_user(regs->cp0_cause, &ctx->regs[34]);
+	error |= __put_user(regs->cp0_epc, &ctx->regs[35]);
 
 	flags = 0x0f;
 	if (!used_math()) {
@@ -716,119 +733,124 @@
 		/* XXX wheee... */
 		printk("Wheee, no code for saving IRIX FPU context yet.\n");
 	}
-	__put_user(flags, &ctx->flags);
+	error |= __put_user(flags, &ctx->flags);
 
-	return 0;
+	return error;
 }
 
-asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
+asmlinkage void irix_setcontext(struct pt_regs *regs)
 {
-	int error, base = 0;
-	struct irix5_context *ctx;
+	struct irix5_context __user *ctx;
+	int err, base = 0;
+	u32 flags;
 
-	if(regs->regs[2] == 1000)
+	if (regs->regs[2] == 1000)
 		base = 1;
-	ctx = (struct irix5_context *) regs->regs[base + 4];
+	ctx = (struct irix5_context __user *) regs->regs[base + 4];
 
 #ifdef DEBUG_SIG
 	printk("[%s:%d] irix_setcontext(%p)\n",
 	       current->comm, current->pid, ctx);
 #endif
 
-	if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))) {
-		error = -EFAULT;
-		goto out;
-	}
+	if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)))
+		goto segv_and_exit;
 
-	if (ctx->flags & 0x02) {
+	err = __get_user(flags, &ctx->flags);
+	if (flags & 0x02) {
 		/* XXX sigstack garbage, todo... */
 		printk("Wheee, cannot do sigstack stuff in setcontext\n");
 	}
 
-	if (ctx->flags & 0x04) {
+	if (flags & 0x04) {
 		int i;
 
 		/* XXX extra control block stuff... todo... */
-		for(i = 1; i < 32; i++)
-			regs->regs[i] = ctx->regs[i];
-		regs->lo = ctx->regs[32];
-		regs->hi = ctx->regs[33];
-		regs->cp0_epc = ctx->regs[35];
+		for (i = 1; i < 32; i++)
+			err |= __get_user(regs->regs[i], &ctx->regs[i]);
+		err |= __get_user(regs->lo, &ctx->regs[32]);
+		err |= __get_user(regs->hi, &ctx->regs[33]);
+		err |= __get_user(regs->cp0_epc, &ctx->regs[35]);
 	}
 
-	if (ctx->flags & 0x08) {
+	if (flags & 0x08)
 		/* XXX fpu context, blah... */
-		printk("Wheee, cannot restore FPU context yet...\n");
-	}
-	current->thread.irix_oldctx = ctx->link;
-	error = regs->regs[2];
+		printk(KERN_ERR "Wheee, cannot restore FPU context yet...\n");
 
-out:
-	return error;
+	err |= __get_user(current->thread.irix_oldctx, &ctx->link);
+	if (err)
+		goto segv_and_exit;
+
+	/*
+	 * Don't let your children do this ...
+	 */
+	if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
+		do_syscall_trace(regs, 1);
+	__asm__ __volatile__(
+		"move\t$29,%0\n\t"
+		"j\tsyscall_exit"
+		:/* no outputs */
+		:"r" (&regs));
+		/* Unreached */
+
+segv_and_exit:
+	force_sigsegv(SIGSEGV, current);
 }
 
-struct irix_sigstack { unsigned long sp; int status; };
+struct irix_sigstack {
+	unsigned long sp;
+	int status;
+};
 
-asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
+asmlinkage int irix_sigstack(struct irix_sigstack __user *new,
+	struct irix_sigstack __user *old)
 {
-	int error = -EFAULT;
-
 #ifdef DEBUG_SIG
 	printk("[%s:%d] irix_sigstack(%p,%p)\n",
 	       current->comm, current->pid, new, old);
 #endif
-	if(new) {
-		if (!access_ok(VERIFY_READ, new, sizeof(*new)))
-			goto out;
-	}
-
-	if(old) {
-		if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
-			goto out;
-	}
-	error = 0;
-
-out:
-	return error;
-}
-
-struct irix_sigaltstack { unsigned long sp; int size; int status; };
-
-asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
-				struct irix_sigaltstack *old)
-{
-	int error = -EFAULT;
-
-#ifdef DEBUG_SIG
-	printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
-	       current->comm, current->pid, new, old);
-#endif
 	if (new) {
 		if (!access_ok(VERIFY_READ, new, sizeof(*new)))
-			goto out;
+			return -EFAULT;
 	}
 
 	if (old) {
 		if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
-			goto out;
+			return -EFAULT;
 	}
-	error = 0;
 
-out:
-	error = 0;
+	return 0;
+}
 
-	return error;
+struct irix_sigaltstack { unsigned long sp; int size; int status; };
+
+asmlinkage int irix_sigaltstack(struct irix_sigaltstack __user *new,
+				struct irix_sigaltstack __user *old)
+{
+#ifdef DEBUG_SIG
+	printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
+	       current->comm, current->pid, new, old);
+#endif
+	if (new)
+		if (!access_ok(VERIFY_READ, new, sizeof(*new)))
+			return -EFAULT;
+
+	if (old) {
+		if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+			return -EFAULT;
+	}
+
+	return 0;
 }
 
 struct irix_procset {
 	int cmd, ltype, lid, rtype, rid;
 };
 
-asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
+asmlinkage int irix_sigsendset(struct irix_procset __user *pset, int sig)
 {
 	if (!access_ok(VERIFY_READ, pset, sizeof(*pset)))
 		return -EFAULT;
-
 #ifdef DEBUG_SIG
 	printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
 	       current->comm, current->pid,
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 43c00ac..3f653c7 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -74,7 +74,7 @@
 static void level_mask_and_ack_msc_irq(unsigned int irq)
 {
 	mask_msc_irq(irq);
-	if (!cpu_has_ei)
+	if (!cpu_has_veic)
 		MSCIC_WRITE(MSC01_IC_EOI, 0);
 }
 
@@ -84,7 +84,7 @@
 static void edge_mask_and_ack_msc_irq(unsigned int irq)
 {
 	mask_msc_irq(irq);
-	if (!cpu_has_ei)
+	if (!cpu_has_veic)
 		MSCIC_WRITE(MSC01_IC_EOI, 0);
 	else {
 		u32 r;
@@ -129,25 +129,23 @@
 #define shutdown_msc_irq	disable_msc_irq
 
 struct hw_interrupt_type msc_levelirq_type = {
-	"SOC-it-Level",
-	startup_msc_irq,
-	shutdown_msc_irq,
-	enable_msc_irq,
-	disable_msc_irq,
-	level_mask_and_ack_msc_irq,
-	end_msc_irq,
-	NULL
+	.typename = "SOC-it-Level",
+	.startup = startup_msc_irq,
+	.shutdown = shutdown_msc_irq,
+	.enable = enable_msc_irq,
+	.disable = disable_msc_irq,
+	.ack = level_mask_and_ack_msc_irq,
+	.end = end_msc_irq,
 };
 
 struct hw_interrupt_type msc_edgeirq_type = {
-	"SOC-it-Edge",
-	startup_msc_irq,
-	shutdown_msc_irq,
-	enable_msc_irq,
-	disable_msc_irq,
-	edge_mask_and_ack_msc_irq,
-	end_msc_irq,
-	NULL
+	.typename = "SOC-it-Edge",
+	.startup =startup_msc_irq,
+	.shutdown = shutdown_msc_irq,
+	.enable = enable_msc_irq,
+	.disable = disable_msc_irq,
+	.ack = edge_mask_and_ack_msc_irq,
+	.end = end_msc_irq,
 };
 
 
@@ -168,14 +166,14 @@
 		switch (imp->im_type) {
 		case MSC01_IRQ_EDGE:
 			irq_desc[base+n].handler = &msc_edgeirq_type;
-			if (cpu_has_ei)
+			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
 			else
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
 			break;
 		case MSC01_IRQ_LEVEL:
 			irq_desc[base+n].handler = &msc_levelirq_type;
-			if (cpu_has_ei)
+			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
 			else
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
index 088bbbc..0ac067f 100644
--- a/arch/mips/kernel/irq-mv6434x.c
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -135,14 +135,13 @@
 #define shutdown_mv64340_irq	disable_mv64340_irq
 
 struct hw_interrupt_type mv64340_irq_type = {
-	"MV-64340",
-	startup_mv64340_irq,
-	shutdown_mv64340_irq,
-	enable_mv64340_irq,
-	disable_mv64340_irq,
-	mask_and_ack_mv64340_irq,
-	end_mv64340_irq,
-	NULL
+	.typename = "MV-64340",
+	.startup = startup_mv64340_irq,
+	.shutdown = shutdown_mv64340_irq,
+	.enable = enable_mv64340_irq,
+	.disable = disable_mv64340_irq,
+	.ack = mask_and_ack_mv64340_irq,
+	.end = end_mv64340_irq,
 };
 
 void __init mv64340_irq_init(unsigned int base)
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index f5d779f..0b130c5 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -72,13 +72,13 @@
 }
 
 static hw_irq_controller rm7k_irq_controller = {
-	"RM7000",
-	rm7k_cpu_irq_startup,
-	rm7k_cpu_irq_shutdown,
-	rm7k_cpu_irq_enable,
-	rm7k_cpu_irq_disable,
-	rm7k_cpu_irq_ack,
-	rm7k_cpu_irq_end,
+	.typename = "RM7000",
+	.startup = rm7k_cpu_irq_startup,
+	.shutdown = rm7k_cpu_irq_shutdown,
+	.enable = rm7k_cpu_irq_enable,
+	.disable = rm7k_cpu_irq_disable,
+	.ack = rm7k_cpu_irq_ack,
+	.end = rm7k_cpu_irq_end,
 };
 
 void __init rm7k_cpu_irq_init(int base)
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index bdd1302..9b5f20c 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -106,23 +106,23 @@
 }
 
 static hw_irq_controller rm9k_irq_controller = {
-	"RM9000",
-	rm9k_cpu_irq_startup,
-	rm9k_cpu_irq_shutdown,
-	rm9k_cpu_irq_enable,
-	rm9k_cpu_irq_disable,
-	rm9k_cpu_irq_ack,
-	rm9k_cpu_irq_end,
+	.typename = "RM9000",
+	.startup = rm9k_cpu_irq_startup,
+	.shutdown = rm9k_cpu_irq_shutdown,
+	.enable = rm9k_cpu_irq_enable,
+	.disable = rm9k_cpu_irq_disable,
+	.ack = rm9k_cpu_irq_ack,
+	.end = rm9k_cpu_irq_end,
 };
 
 static hw_irq_controller rm9k_perfcounter_irq = {
-	"RM9000",
-	rm9k_perfcounter_irq_startup,
-	rm9k_perfcounter_irq_shutdown,
-	rm9k_cpu_irq_enable,
-	rm9k_cpu_irq_disable,
-	rm9k_cpu_irq_ack,
-	rm9k_cpu_irq_end,
+	.typename = "RM9000",
+	.startup = rm9k_perfcounter_irq_startup,
+	.shutdown = rm9k_perfcounter_irq_shutdown,
+	.enable = rm9k_cpu_irq_enable,
+	.disable = rm9k_cpu_irq_disable,
+	.ack = rm9k_cpu_irq_ack,
+	.end = rm9k_cpu_irq_end,
 };
 
 unsigned int rm9000_perfcount_irq;
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 2b936cf..5db67e3 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -3,6 +3,8 @@
  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  *
  * Copyright (C) 2001 Ralf Baechle
+ * Copyright (C) 2005  MIPS Technologies, Inc.  All rights reserved.
+ *      Author: Maciej W. Rozycki <macro@mips.com>
  *
  * This file define the irq handler for MIPS CPU interrupts.
  *
@@ -31,19 +33,21 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/system.h>
 
 static int mips_cpu_irq_base;
 
 static inline void unmask_mips_irq(unsigned int irq)
 {
-	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
 	set_c0_status(0x100 << (irq - mips_cpu_irq_base));
+	irq_enable_hazard();
 }
 
 static inline void mask_mips_irq(unsigned int irq)
 {
 	clear_c0_status(0x100 << (irq - mips_cpu_irq_base));
+	irq_disable_hazard();
 }
 
 static inline void mips_cpu_irq_enable(unsigned int irq)
@@ -52,6 +56,7 @@
 
 	local_irq_save(flags);
 	unmask_mips_irq(irq);
+	back_to_back_c0_hazard();
 	local_irq_restore(flags);
 }
 
@@ -61,6 +66,7 @@
 
 	local_irq_save(flags);
 	mask_mips_irq(irq);
+	back_to_back_c0_hazard();
 	local_irq_restore(flags);
 }
 
@@ -71,7 +77,7 @@
 	return 0;
 }
 
-#define	mips_cpu_irq_shutdown	mips_cpu_irq_disable
+#define	mips_cpu_irq_shutdown		mips_cpu_irq_disable
 
 /*
  * While we ack the interrupt interrupts are disabled and thus we don't need
@@ -79,9 +85,6 @@
  */
 static void mips_cpu_irq_ack(unsigned int irq)
 {
-	/* Only necessary for soft interrupts */
-	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
-
 	mask_mips_irq(irq);
 }
 
@@ -92,22 +95,82 @@
 }
 
 static hw_irq_controller mips_cpu_irq_controller = {
-	"MIPS",
-	mips_cpu_irq_startup,
-	mips_cpu_irq_shutdown,
-	mips_cpu_irq_enable,
-	mips_cpu_irq_disable,
-	mips_cpu_irq_ack,
-	mips_cpu_irq_end,
-	NULL			/* no affinity stuff for UP */
+	.typename	= "MIPS",
+	.startup	= mips_cpu_irq_startup,
+	.shutdown	= mips_cpu_irq_shutdown,
+	.enable		= mips_cpu_irq_enable,
+	.disable	= mips_cpu_irq_disable,
+	.ack		= mips_cpu_irq_ack,
+	.end		= mips_cpu_irq_end,
 };
 
+/*
+ * Basically the same as above but taking care of all the MT stuff
+ */
+
+#define unmask_mips_mt_irq	unmask_mips_irq
+#define mask_mips_mt_irq	mask_mips_irq
+#define mips_mt_cpu_irq_enable	mips_cpu_irq_enable
+#define mips_mt_cpu_irq_disable	mips_cpu_irq_disable
+
+static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
+{
+	unsigned int vpflags = dvpe();
+
+	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+	evpe(vpflags);
+	mips_mt_cpu_irq_enable(irq);
+
+	return 0;
+}
+
+#define	mips_mt_cpu_irq_shutdown	mips_mt_cpu_irq_disable
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for mips_cpu_irq_end.
+ */
+static void mips_mt_cpu_irq_ack(unsigned int irq)
+{
+	unsigned int vpflags = dvpe();
+	clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+	evpe(vpflags);
+	mask_mips_mt_irq(irq);
+}
+
+#define mips_mt_cpu_irq_end mips_cpu_irq_end
+
+static hw_irq_controller mips_mt_cpu_irq_controller = {
+	.typename	= "MIPS",
+	.startup	= mips_mt_cpu_irq_startup,
+	.shutdown	= mips_mt_cpu_irq_shutdown,
+	.enable		= mips_mt_cpu_irq_enable,
+	.disable	= mips_mt_cpu_irq_disable,
+	.ack		= mips_mt_cpu_irq_ack,
+	.end		= mips_mt_cpu_irq_end,
+};
 
 void __init mips_cpu_irq_init(int irq_base)
 {
 	int i;
 
-	for (i = irq_base; i < irq_base + 8; i++) {
+	/* Mask interrupts. */
+	clear_c0_status(ST0_IM);
+	clear_c0_cause(CAUSEF_IP);
+
+	/*
+	 * Only MT is using the software interrupts currently, so we just
+	 * leave them uninitialized for other processors.
+	 */
+	if (cpu_has_mipsmt)
+		for (i = irq_base; i < irq_base + 2; i++) {
+			irq_desc[i].status = IRQ_DISABLED;
+			irq_desc[i].action = NULL;
+			irq_desc[i].depth = 1;
+			irq_desc[i].handler = &mips_mt_cpu_irq_controller;
+		}
+
+	for (i = irq_base + 2; i < irq_base + 8; i++) {
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index ece4564..330cf84 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -215,81 +215,32 @@
 	return(n);
 }
 
-struct rusage32 {
-        struct compat_timeval ru_utime;
-        struct compat_timeval ru_stime;
-        int    ru_maxrss;
-        int    ru_ixrss;
-        int    ru_idrss;
-        int    ru_isrss;
-        int    ru_minflt;
-        int    ru_majflt;
-        int    ru_nswap;
-        int    ru_inblock;
-        int    ru_oublock;
-        int    ru_msgsnd;
-        int    ru_msgrcv;
-        int    ru_nsignals;
-        int    ru_nvcsw;
-        int    ru_nivcsw;
-};
-
-static int
-put_rusage (struct rusage32 *ru, struct rusage *r)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, ru, sizeof *ru))
-		return -EFAULT;
-
-	err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
-	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
-	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
-	err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
-	err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
-	err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
-	err |= __put_user (r->ru_idrss, &ru->ru_idrss);
-	err |= __put_user (r->ru_isrss, &ru->ru_isrss);
-	err |= __put_user (r->ru_minflt, &ru->ru_minflt);
-	err |= __put_user (r->ru_majflt, &ru->ru_majflt);
-	err |= __put_user (r->ru_nswap, &ru->ru_nswap);
-	err |= __put_user (r->ru_inblock, &ru->ru_inblock);
-	err |= __put_user (r->ru_oublock, &ru->ru_oublock);
-	err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
-	err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
-	err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
-	err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
-	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
-
-	return err;
-}
-
-asmlinkage int
-sys32_wait4(compat_pid_t pid, unsigned int * stat_addr, int options,
-	    struct rusage32 * ru)
-{
-	if (!ru)
-		return sys_wait4(pid, stat_addr, options, NULL);
-	else {
-		struct rusage r;
-		int ret;
-		unsigned int status;
-		mm_segment_t old_fs = get_fs();
-
-		set_fs(KERNEL_DS);
-		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
-		set_fs(old_fs);
-		if (put_rusage (ru, &r)) return -EFAULT;
-		if (stat_addr && put_user (status, stat_addr))
-			return -EFAULT;
-		return ret;
-	}
-}
-
 asmlinkage int
 sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options)
 {
-	return sys32_wait4(pid, stat_addr, options, NULL);
+	return compat_sys_wait4(pid, stat_addr, options, NULL);
+}
+
+asmlinkage long
+sysn32_waitid(int which, compat_pid_t pid,
+	      siginfo_t __user *uinfo, int options,
+	      struct compat_rusage __user *uru)
+{
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, uinfo, options,
+			 uru ? (struct rusage __user *) &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || uinfo->si_signo == 0)
+		return ret;
+
+	if (uru)
+		ret = put_compat_rusage(&ru, uru);
+	return ret;
 }
 
 struct sysinfo32 {
@@ -1467,3 +1418,80 @@
 	}
 	return err;
 }
+
+struct sigevent32 {
+	u32 sigev_value;
+	u32 sigev_signo;
+	u32 sigev_notify;
+	u32 payload[(64 / 4) - 3];
+};
+
+extern asmlinkage long
+sys_timer_create(clockid_t which_clock,
+		 struct sigevent __user *timer_event_spec,
+		 timer_t __user * created_timer_id);
+
+long
+sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
+{
+	struct sigevent __user *p = NULL;
+	if (se32) {
+		struct sigevent se;
+		p = compat_alloc_user_space(sizeof(struct sigevent));
+		memset(&se, 0, sizeof(struct sigevent));
+		if (get_user(se.sigev_value.sival_int,  &se32->sigev_value) ||
+		    __get_user(se.sigev_signo, &se32->sigev_signo) ||
+		    __get_user(se.sigev_notify, &se32->sigev_notify) ||
+		    __copy_from_user(&se._sigev_un._pad, &se32->payload,
+				     sizeof(se32->payload)) ||
+		    copy_to_user(p, &se, sizeof(se)))
+			return -EFAULT;
+	}
+	return sys_timer_create(clock, p, timer_id);
+}
+
+asmlinkage long
+sysn32_rt_sigtimedwait(const sigset_t __user *uthese,
+		       siginfo_t __user *uinfo,
+		       const struct compat_timespec __user *uts32,
+		       size_t sigsetsize)
+{
+	struct timespec __user *uts = NULL;
+
+	if (uts32) {
+		struct timespec ts;
+		uts = compat_alloc_user_space(sizeof(struct timespec));
+		if (get_user(ts.tv_sec, &uts32->tv_sec) ||
+		    get_user(ts.tv_nsec, &uts32->tv_nsec) ||
+		    copy_to_user (uts, &ts, sizeof (ts)))
+			return -EFAULT;
+	}
+	return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
+}
+
+save_static_function(sys32_clone);
+__attribute_used__ noinline static int
+_sys32_clone(nabi_no_regargs struct pt_regs regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+	int __user *parent_tidptr, *child_tidptr;
+
+	clone_flags = regs.regs[4];
+	newsp = regs.regs[5];
+	if (!newsp)
+		newsp = regs.regs[29];
+	parent_tidptr = (int *) regs.regs[6];
+
+	/* Use __dummy4 instead of getting it off the stack, so that
+	   syscall() works.  */
+	child_tidptr = (int __user *) __dummy4;
+	return do_fork(clone_flags, newsp, &regs, 0,
+	               parent_tidptr, child_tidptr);
+}
+
+extern asmlinkage void sys_set_thread_area(u32 addr);
+asmlinkage void sys32_set_thread_area(u32 addr)
+{
+	sys_set_thread_area(AA(addr));
+}
diff --git a/arch/mips/kernel/module-elf32.c b/arch/mips/kernel/module-elf32.c
deleted file mode 100644
index ffd216d..0000000
--- a/arch/mips/kernel/module-elf32.c
+++ /dev/null
@@ -1,250 +0,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, 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
- *
- *  Copyright (C) 2001 Rusty Russell.
- *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-
-#undef DEBUG
-
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-struct mips_hi16 {
-	struct mips_hi16 *next;
-	Elf32_Addr *addr;
-	Elf32_Addr value;
-};
-
-static struct mips_hi16 *mips_hi16_list;
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-static int apply_r_mips_none(struct module *me, uint32_t *location,
-	Elf32_Addr v)
-{
-	return 0;
-}
-
-static int apply_r_mips_32(struct module *me, uint32_t *location,
-	Elf32_Addr v)
-{
-	*location += v;
-
-	return 0;
-}
-
-static int apply_r_mips_26(struct module *me, uint32_t *location,
-	Elf32_Addr v)
-{
-	if (v % 4) {
-		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
-		return -ENOEXEC;
-	}
-
-	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
-		       "module %s: relocation overflow\n",
-		       me->name);
-		return -ENOEXEC;
-	}
-
-	*location = (*location & ~0x03ffffff) |
-	            ((*location + (v >> 2)) & 0x03ffffff);
-
-	return 0;
-}
-
-static int apply_r_mips_hi16(struct module *me, uint32_t *location,
-	Elf32_Addr v)
-{
-	struct mips_hi16 *n;
-
-	/*
-	 * We cannot relocate this one now because we don't know the value of
-	 * the carry we need to add.  Save the information, and let LO16 do the
-	 * actual relocation.
-	 */
-	n = kmalloc(sizeof *n, GFP_KERNEL);
-	if (!n)
-		return -ENOMEM;
-
-	n->addr = location;
-	n->value = v;
-	n->next = mips_hi16_list;
-	mips_hi16_list = n;
-
-	return 0;
-}
-
-static int apply_r_mips_lo16(struct module *me, uint32_t *location,
-	Elf32_Addr v)
-{
-	unsigned long insnlo = *location;
-	Elf32_Addr val, vallo;
-
-	/* Sign extend the addend we extract from the lo insn.  */
-	vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
-
-	if (mips_hi16_list != NULL) {
-		struct mips_hi16 *l;
-
-		l = mips_hi16_list;
-		while (l != NULL) {
-			struct mips_hi16 *next;
-			unsigned long insn;
-
-			/*
-			 * The value for the HI16 had best be the same.
-			 */
-			if (v != l->value)
-				goto out_danger;
-
-			/*
-			 * Do the HI16 relocation.  Note that we actually don't
-			 * need to know anything about the LO16 itself, except
-			 * where to find the low 16 bits of the addend needed
-			 * by the LO16.
-			 */
-			insn = *l->addr;
-			val = ((insn & 0xffff) << 16) + vallo;
-			val += v;
-
-			/*
-			 * Account for the sign extension that will happen in
-			 * the low bits.
-			 */
-			val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
-
-			insn = (insn & ~0xffff) | val;
-			*l->addr = insn;
-
-			next = l->next;
-			kfree(l);
-			l = next;
-		}
-
-		mips_hi16_list = NULL;
-	}
-
-	/*
-	 * Ok, we're done with the HI16 relocs.  Now deal with the LO16.
-	 */
-	val = v + vallo;
-	insnlo = (insnlo & ~0xffff) | (val & 0xffff);
-	*location = insnlo;
-
-	return 0;
-
-out_danger:
-	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
-
-	return -ENOEXEC;
-}
-
-static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
-	Elf32_Addr v) = {
-	[R_MIPS_NONE]	= apply_r_mips_none,
-	[R_MIPS_32]	= apply_r_mips_32,
-	[R_MIPS_26]	= apply_r_mips_26,
-	[R_MIPS_HI16]	= apply_r_mips_hi16,
-	[R_MIPS_LO16]	= apply_r_mips_lo16
-};
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-	unsigned int i;
-	Elf32_Addr v;
-	int res;
-
-	pr_debug("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		Elf32_Word r_info = rel[i].r_info;
-
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(r_info);
-		if (!sym->st_value) {
-			printk(KERN_WARNING "%s: Unknown symbol %s\n",
-			       me->name, strtab + sym->st_name);
-			return -ENOENT;
-		}
-
-		v = sym->st_value;
-
-		res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
-		if (res)
-			return res;
-	}
-
-	return 0;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	/*
-	 * Current binutils always generate .rela relocations.  Keep smiling
-	 * if it's empty, abort otherwise.
-	 */
-	if (!sechdrs[relsec].sh_size)
-		return 0;
-
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
diff --git a/arch/mips/kernel/module-elf64.c b/arch/mips/kernel/module-elf64.c
deleted file mode 100644
index e804792..0000000
--- a/arch/mips/kernel/module-elf64.c
+++ /dev/null
@@ -1,274 +0,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, 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
- *
- *  Copyright (C) 2001 Rusty Russell.
- *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-
-#undef DEBUG
-
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-struct mips_hi16 {
-	struct mips_hi16 *next;
-	Elf32_Addr *addr;
-	Elf64_Addr value;
-};
-
-static struct mips_hi16 *mips_hi16_list;
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
-}
-
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf64_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	/*
-	 * We don't want to deal with REL relocations - RELA is so much saner.
-	 */
-	if (!sechdrs[relsec].sh_size)
-		return 0;
-
-	printk(KERN_ERR "module %s: REL relocation unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
-static int apply_r_mips_none(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	return 0;
-}
-
-static int apply_r_mips_32(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	*location = v;
-
-	return 0;
-}
-
-static int apply_r_mips_26(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	if (v % 4) {
-		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
-		return -ENOEXEC;
-	}
-
-	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
-		       "module %s: relocation overflow\n",
-		       me->name);
-		return -ENOEXEC;
-	}
-
-	*location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
-
-	return 0;
-}
-
-static int apply_r_mips_hi16(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	struct mips_hi16 *n;
-
-	/*
-	 * We cannot relocate this one now because we don't know the value of
-	 * the carry we need to add.  Save the information, and let LO16 do the
-	 * actual relocation.
-	 */
-	n = kmalloc(sizeof *n, GFP_KERNEL);
-	if (!n)
-		return -ENOMEM;
-
-	n->addr = location;
-	n->value = v;
-	n->next = mips_hi16_list;
-	mips_hi16_list = n;
-
-	return 0;
-}
-
-static int apply_r_mips_lo16(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	unsigned long insnlo = *location;
-	Elf32_Addr val, vallo;
-
-	/* Sign extend the addend we extract from the lo insn.  */
-	vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
-
-	if (mips_hi16_list != NULL) {
-		struct mips_hi16 *l;
-
-		l = mips_hi16_list;
-		while (l != NULL) {
-			struct mips_hi16 *next;
-			unsigned long insn;
-
-			/*
-			 * The value for the HI16 had best be the same.
-			 */
-			if (v != l->value)
-				goto out_danger;
-
-			/*
-			 * Do the HI16 relocation.  Note that we actually don't
-			 * need to know anything about the LO16 itself, except
-			 * where to find the low 16 bits of the addend needed
-			 * by the LO16.
-			 */
-			insn = *l->addr;
-			val = ((insn & 0xffff) << 16) + vallo;
-			val += v;
-
-			/*
-			 * Account for the sign extension that will happen in
-			 * the low bits.
-			 */
-			val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
-
-			insn = (insn & ~0xffff) | val;
-			*l->addr = insn;
-
-			next = l->next;
-			kfree(l);
-			l = next;
-		}
-
-		mips_hi16_list = NULL;
-	}
-
-	/*
-	 * Ok, we're done with the HI16 relocs.  Now deal with the LO16.
-	 */
-	insnlo = (insnlo & ~0xffff) | (v & 0xffff);
-	*location = insnlo;
-
-	return 0;
-
-out_danger:
-	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
-
-	return -ENOEXEC;
-}
-
-static int apply_r_mips_64(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	*(uint64_t *) location = v;
-
-	return 0;
-}
-
-
-static int apply_r_mips_higher(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	*location = (*location & 0xffff0000) |
-	            ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
-
-	return 0;
-}
-
-static int apply_r_mips_highest(struct module *me, uint32_t *location,
-	Elf64_Addr v)
-{
-	*location = (*location & 0xffff0000) |
-	            ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
-
-	return 0;
-}
-
-static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
-	Elf64_Addr v) = {
-	[R_MIPS_NONE]		= apply_r_mips_none,
-	[R_MIPS_32]		= apply_r_mips_32,
-	[R_MIPS_26]		= apply_r_mips_26,
-	[R_MIPS_HI16]		= apply_r_mips_hi16,
-	[R_MIPS_LO16]		= apply_r_mips_lo16,
-	[R_MIPS_64]		= apply_r_mips_64,
-	[R_MIPS_HIGHER]		= apply_r_mips_higher,
-	[R_MIPS_HIGHEST]	= apply_r_mips_highest
-};
-
-int apply_relocate_add(Elf64_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	Elf64_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
-	Elf64_Sym *sym;
-	uint32_t *location;
-	unsigned int i;
-	Elf64_Addr v;
-	int res;
-
-	pr_debug("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to */
-		sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + rel[i].r_sym;
-		if (!sym->st_value) {
-			printk(KERN_WARNING "%s: Unknown symbol %s\n",
-			       me->name, strtab + sym->st_name);
-			return -ENOENT;
-		}
-
-		v = sym->st_value;
-
-		res = reloc_handlers[rel[i].r_type](me, location, v);
-		if (res)
-			return res;
-	}
-
-	return 0;
-}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 458af3c..e54a7f4 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -1,9 +1,345 @@
+/*
+ *  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
+ *
+ *  Copyright (C) 2001 Rusty Russell.
+ *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ *  Copyright (C) 2005 Thiemo Seufer
+ */
+
+#undef DEBUG
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
+struct mips_hi16 {
+	struct mips_hi16 *next;
+	Elf_Addr *addr;
+	Elf_Addr value;
+};
+
+static struct mips_hi16 *mips_hi16_list;
+
 static LIST_HEAD(dbe_list);
 static DEFINE_SPINLOCK(dbe_lock);
 
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc(size);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+			      char *secstrings, struct module *mod)
+{
+	return 0;
+}
+
+static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
+{
+	return 0;
+}
+
+static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location += v;
+
+	return 0;
+}
+
+static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location = v;
+
+	return 0;
+}
+
+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	if (v % 4) {
+		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+		return -ENOEXEC;
+	}
+
+	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+		printk(KERN_ERR
+		       "module %s: relocation overflow\n",
+		       me->name);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & ~0x03ffffff) |
+	            ((*location + (v >> 2)) & 0x03ffffff);
+
+	return 0;
+}
+
+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	if (v % 4) {
+		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+		return -ENOEXEC;
+	}
+
+	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+		printk(KERN_ERR
+		       "module %s: relocation overflow\n",
+		       me->name);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
+
+	return 0;
+}
+
+static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	struct mips_hi16 *n;
+
+	/*
+	 * We cannot relocate this one now because we don't know the value of
+	 * the carry we need to add.  Save the information, and let LO16 do the
+	 * actual relocation.
+	 */
+	n = kmalloc(sizeof *n, GFP_KERNEL);
+	if (!n)
+		return -ENOMEM;
+
+	n->addr = (Elf_Addr *)location;
+	n->value = v;
+	n->next = mips_hi16_list;
+	mips_hi16_list = n;
+
+	return 0;
+}
+
+static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) |
+	            ((((long long) v + 0x8000LL) >> 16) & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	unsigned long insnlo = *location;
+	Elf_Addr val, vallo;
+
+	/* Sign extend the addend we extract from the lo insn.  */
+	vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+	if (mips_hi16_list != NULL) {
+		struct mips_hi16 *l;
+
+		l = mips_hi16_list;
+		while (l != NULL) {
+			struct mips_hi16 *next;
+			unsigned long insn;
+
+			/*
+			 * The value for the HI16 had best be the same.
+			 */
+			if (v != l->value)
+				goto out_danger;
+
+			/*
+			 * Do the HI16 relocation.  Note that we actually don't
+			 * need to know anything about the LO16 itself, except
+			 * where to find the low 16 bits of the addend needed
+			 * by the LO16.
+			 */
+			insn = *l->addr;
+			val = ((insn & 0xffff) << 16) + vallo;
+			val += v;
+
+			/*
+			 * Account for the sign extension that will happen in
+			 * the low bits.
+			 */
+			val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
+
+			insn = (insn & ~0xffff) | val;
+			*l->addr = insn;
+
+			next = l->next;
+			kfree(l);
+			l = next;
+		}
+
+		mips_hi16_list = NULL;
+	}
+
+	/*
+	 * Ok, we're done with the HI16 relocs.  Now deal with the LO16.
+	 */
+	val = v + vallo;
+	insnlo = (insnlo & ~0xffff) | (val & 0xffff);
+	*location = insnlo;
+
+	return 0;
+
+out_danger:
+	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+
+	return -ENOEXEC;
+}
+
+static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) | (v & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*(Elf_Addr *)location = v;
+
+	return 0;
+}
+
+static int apply_r_mips_higher_rela(struct module *me, u32 *location,
+				    Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) |
+	            ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_highest_rela(struct module *me, u32 *location,
+				     Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) |
+	            ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
+
+	return 0;
+}
+
+static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
+				Elf_Addr v) = {
+	[R_MIPS_NONE]		= apply_r_mips_none,
+	[R_MIPS_32]		= apply_r_mips_32_rel,
+	[R_MIPS_26]		= apply_r_mips_26_rel,
+	[R_MIPS_HI16]		= apply_r_mips_hi16_rel,
+	[R_MIPS_LO16]		= apply_r_mips_lo16_rel
+};
+
+static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
+				Elf_Addr v) = {
+	[R_MIPS_NONE]		= apply_r_mips_none,
+	[R_MIPS_32]		= apply_r_mips_32_rela,
+	[R_MIPS_26]		= apply_r_mips_26_rela,
+	[R_MIPS_HI16]		= apply_r_mips_hi16_rela,
+	[R_MIPS_LO16]		= apply_r_mips_lo16_rela,
+	[R_MIPS_64]		= apply_r_mips_64_rela,
+	[R_MIPS_HIGHER]		= apply_r_mips_higher_rela,
+	[R_MIPS_HIGHEST]	= apply_r_mips_highest_rela
+};
+
+int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
+		   unsigned int symindex, unsigned int relsec,
+		   struct module *me)
+{
+	Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr;
+	Elf_Sym *sym;
+	u32 *location;
+	unsigned int i;
+	Elf_Addr v;
+	int res;
+
+	pr_debug("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to */
+		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+			+ ELF_MIPS_R_SYM(rel[i]);
+		if (!sym->st_value) {
+			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+
+		v = sym->st_value;
+
+		res = reloc_handlers_rel[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
+		if (res)
+			return res;
+	}
+
+	return 0;
+}
+
+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
+		       unsigned int symindex, unsigned int relsec,
+		       struct module *me)
+{
+	Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
+	Elf_Sym *sym;
+	u32 *location;
+	unsigned int i;
+	Elf_Addr v;
+	int res;
+
+	pr_debug("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to */
+		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+			+ ELF_MIPS_R_SYM(rel[i]);
+		if (!sym->st_value) {
+			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+
+		v = sym->st_value + rel[i].r_addend;
+
+		res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
+		if (res)
+			return res;
+	}
+
+	return 0;
+}
+
 /* Given an address, look for it in the module exception tables. */
 const struct exception_table_entry *search_module_dbetables(unsigned long addr)
 {
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 0f159f3..86fe15b 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -2,7 +2,8 @@
  *  linux/arch/mips/kernel/proc.c
  *
  *  Copyright (C) 1995, 1996, 2001  Ralf Baechle
- *  Copyright (C) 2001  MIPS Technologies, Inc.
+ *  Copyright (C) 2001, 2004  MIPS Technologies, Inc.
+ *  Copyright (C) 2004  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/delay.h>
@@ -19,63 +20,69 @@
 unsigned int vced_count, vcei_count;
 
 static const char *cpu_name[] = {
-	[CPU_UNKNOWN]	"unknown",
-	[CPU_R2000]	"R2000",
-	[CPU_R3000]	"R3000",
-	[CPU_R3000A]	"R3000A",
-	[CPU_R3041]	"R3041",
-	[CPU_R3051]	"R3051",
-	[CPU_R3052]	"R3052",
-	[CPU_R3081]	"R3081",
-	[CPU_R3081E]	"R3081E",
-	[CPU_R4000PC]	"R4000PC",
-	[CPU_R4000SC]	"R4000SC",
-	[CPU_R4000MC]	"R4000MC",
-        [CPU_R4200]	"R4200",
-	[CPU_R4400PC]	"R4400PC",
-	[CPU_R4400SC]	"R4400SC",
-	[CPU_R4400MC]	"R4400MC",
-	[CPU_R4600]	"R4600",
-	[CPU_R6000]	"R6000",
-        [CPU_R6000A]	"R6000A",
-	[CPU_R8000]	"R8000",
-	[CPU_R10000]	"R10000",
-	[CPU_R12000]	"R12000",
-	[CPU_R4300]	"R4300",
-	[CPU_R4650]	"R4650",
-	[CPU_R4700]	"R4700",
-	[CPU_R5000]	"R5000",
-        [CPU_R5000A]	"R5000A",
-	[CPU_R4640]	"R4640",
-	[CPU_NEVADA]	"Nevada",
-	[CPU_RM7000]	"RM7000",
-	[CPU_RM9000]	"RM9000",
-	[CPU_R5432]	"R5432",
-	[CPU_4KC]	"MIPS 4Kc",
-        [CPU_5KC]	"MIPS 5Kc",
-	[CPU_R4310]	"R4310",
-	[CPU_SB1]	"SiByte SB1",
-	[CPU_TX3912]	"TX3912",
-	[CPU_TX3922]	"TX3922",
-	[CPU_TX3927]	"TX3927",
-	[CPU_AU1000]	"Au1000",
-	[CPU_AU1500]	"Au1500",
-	[CPU_4KEC]	"MIPS 4KEc",
-	[CPU_4KSC]	"MIPS 4KSc",
-	[CPU_VR41XX]	"NEC Vr41xx",
-	[CPU_R5500]	"R5500",
-	[CPU_TX49XX]	"TX49xx",
-	[CPU_20KC]	"MIPS 20Kc",
-	[CPU_24K]	"MIPS 24K",
-	[CPU_25KF]	"MIPS 25Kf",
-	[CPU_VR4111]	"NEC VR4111",
-	[CPU_VR4121]	"NEC VR4121",
-	[CPU_VR4122]	"NEC VR4122",
-	[CPU_VR4131]	"NEC VR4131",
-	[CPU_VR4133]	"NEC VR4133",
-	[CPU_VR4181]	"NEC VR4181",
-	[CPU_VR4181A]	"NEC VR4181A",
-	[CPU_SR71000]	"Sandcraft SR71000"
+	[CPU_UNKNOWN]	= "unknown",
+	[CPU_R2000]	= "R2000",
+	[CPU_R3000]	= "R3000",
+	[CPU_R3000A]	= "R3000A",
+	[CPU_R3041]	= "R3041",
+	[CPU_R3051]	= "R3051",
+	[CPU_R3052]	= "R3052",
+	[CPU_R3081]	= "R3081",
+	[CPU_R3081E]	= "R3081E",
+	[CPU_R4000PC]	= "R4000PC",
+	[CPU_R4000SC]	= "R4000SC",
+	[CPU_R4000MC]	= "R4000MC",
+        [CPU_R4200]	= "R4200",
+	[CPU_R4400PC]	= "R4400PC",
+	[CPU_R4400SC]	= "R4400SC",
+	[CPU_R4400MC]	= "R4400MC",
+	[CPU_R4600]	= "R4600",
+	[CPU_R6000]	= "R6000",
+        [CPU_R6000A]	= "R6000A",
+	[CPU_R8000]	= "R8000",
+	[CPU_R10000]	= "R10000",
+	[CPU_R12000]	= "R12000",
+	[CPU_R4300]	= "R4300",
+	[CPU_R4650]	= "R4650",
+	[CPU_R4700]	= "R4700",
+	[CPU_R5000]	= "R5000",
+        [CPU_R5000A]	= "R5000A",
+	[CPU_R4640]	= "R4640",
+	[CPU_NEVADA]	= "Nevada",
+	[CPU_RM7000]	= "RM7000",
+	[CPU_RM9000]	= "RM9000",
+	[CPU_R5432]	= "R5432",
+	[CPU_4KC]	= "MIPS 4Kc",
+        [CPU_5KC]	= "MIPS 5Kc",
+	[CPU_R4310]	= "R4310",
+	[CPU_SB1]	= "SiByte SB1",
+	[CPU_SB1A]	= "SiByte SB1A",
+	[CPU_TX3912]	= "TX3912",
+	[CPU_TX3922]	= "TX3922",
+	[CPU_TX3927]	= "TX3927",
+	[CPU_AU1000]	= "Au1000",
+	[CPU_AU1500]	= "Au1500",
+	[CPU_AU1100]	= "Au1100",
+	[CPU_AU1550]	= "Au1550",
+	[CPU_AU1200]	= "Au1200",
+	[CPU_4KEC]	= "MIPS 4KEc",
+	[CPU_4KSC]	= "MIPS 4KSc",
+	[CPU_VR41XX]	= "NEC Vr41xx",
+	[CPU_R5500]	= "R5500",
+	[CPU_TX49XX]	= "TX49xx",
+	[CPU_20KC]	= "MIPS 20Kc",
+	[CPU_24K]	= "MIPS 24K",
+	[CPU_25KF]	= "MIPS 25Kf",
+	[CPU_34K]	= "MIPS 34K",
+	[CPU_VR4111]	= "NEC VR4111",
+	[CPU_VR4121]	= "NEC VR4121",
+	[CPU_VR4122]	= "NEC VR4122",
+	[CPU_VR4131]	= "NEC VR4131",
+	[CPU_VR4133]	= "NEC VR4133",
+	[CPU_VR4181]	= "NEC VR4181",
+	[CPU_VR4181A]	= "NEC VR4181A",
+	[CPU_SR71000]	= "Sandcraft SR71000",
+	[CPU_PR4450]	= "Philips PR4450",
 };
 
 
@@ -105,8 +112,8 @@
 	                           (version >> 4) & 0x0f, version & 0x0f,
 	                           (fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
 	seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n",
-	              loops_per_jiffy / (500000/HZ),
-	              (loops_per_jiffy / (5000/HZ)) % 100);
+	              cpu_data[n].udelay_val / (500000/HZ),
+	              (cpu_data[n].udelay_val / (5000/HZ)) % 100);
 	seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no");
 	seq_printf(m, "microsecond timers\t: %s\n",
 	              cpu_has_counter ? "yes" : "no");
@@ -115,6 +122,14 @@
 	              cpu_has_divec ? "yes" : "no");
 	seq_printf(m, "hardware watchpoint\t: %s\n",
 	              cpu_has_watch ? "yes" : "no");
+	seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n",
+		      cpu_has_mips16 ? " mips16" : "",
+		      cpu_has_mdmx ? " mdmx" : "",
+		      cpu_has_mips3d ? " mips3d" : "",
+		      cpu_has_smartmips ? " smartmips" : "",
+		      cpu_has_dsp ? " dsp" : "",
+		      cpu_has_mipsmt ? " mt" : ""
+		);
 
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
 	        cpu_has_vce ? "%u" : "not available");
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index e4f2f80..4fe3d57 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -25,8 +25,10 @@
 #include <linux/init.h>
 #include <linux/completion.h>
 
+#include <asm/abi.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -39,14 +41,6 @@
 #include <asm/inst.h>
 
 /*
- * We use this if we don't have any better idle routine..
- * (This to kill: kernel/platform.c.
- */
-void default_idle (void)
-{
-}
-
-/*
  * The idle thread. There's no useful work to be done, so just try to conserve
  * power and have a low exit latency (ie sit in a loop waiting for somebody to
  * say that they'd like to reschedule)
@@ -62,6 +56,54 @@
 	}
 }
 
+extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
+extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+
+/*
+ * Native o32 and N64 ABI without DSP ASE
+ */
+extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+        int signr, sigset_t *set);
+extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+        int signr, sigset_t *set, siginfo_t *info);
+
+struct mips_abi mips_abi = {
+	.do_signal	= do_signal,
+#ifdef CONFIG_TRAD_SIGNALS
+	.setup_frame	= setup_frame,
+#endif
+	.setup_rt_frame	= setup_rt_frame
+};
+
+#ifdef CONFIG_MIPS32_O32
+/*
+ * o32 compatibility on 64-bit kernels, without DSP ASE
+ */
+extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
+        int signr, sigset_t *set);
+extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
+        int signr, sigset_t *set, siginfo_t *info);
+
+struct mips_abi mips_abi_32 = {
+	.do_signal	= do_signal32,
+	.setup_frame	= setup_frame_32,
+	.setup_rt_frame	= setup_rt_frame_32
+};
+#endif /* CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_MIPS32_N32
+/*
+ * N32 on 64-bit kernels, without DSP ASE
+ */
+extern int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
+        int signr, sigset_t *set, siginfo_t *info);
+
+struct mips_abi mips_abi_n32 = {
+	.do_signal	= do_signal,
+	.setup_rt_frame	= setup_rt_frame_n32
+};
+#endif /* CONFIG_MIPS32_N32 */
+
 asmlinkage void ret_from_fork(void);
 
 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
@@ -78,6 +120,8 @@
 	regs->cp0_status = status;
 	clear_used_math();
 	lose_fpu();
+	if (cpu_has_dsp)
+		__init_dsp();
 	regs->cp0_epc = pc;
 	regs->regs[29] = sp;
 	current_thread_info()->addr_limit = USER_DS;
@@ -97,14 +141,17 @@
 	struct thread_info *ti = p->thread_info;
 	struct pt_regs *childregs;
 	long childksp;
+	p->set_child_tid = p->clear_child_tid = NULL;
 
 	childksp = (unsigned long)ti + THREAD_SIZE - 32;
 
 	preempt_disable();
 
-	if (is_fpu_owner()) {
+	if (is_fpu_owner())
 		save_fp(p);
-	}
+
+	if (cpu_has_dsp)
+		save_dsp(p);
 
 	preempt_enable();
 
@@ -142,6 +189,9 @@
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
 
+	if (clone_flags & CLONE_SETTLS)
+		ti->tp_value = regs->regs[7];
+
 	return 0;
 }
 
@@ -175,6 +225,14 @@
 #endif
 }
 
+int dump_task_regs (struct task_struct *tsk, elf_gregset_t *regs)
+{
+	struct thread_info *ti = tsk->thread_info;
+	long ksp = (unsigned long)ti + THREAD_SIZE - 32;
+	dump_regs(&(*regs)[0], (struct pt_regs *) ksp - 1);
+	return 1;
+}
+
 int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr)
 {
 	memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu));
@@ -211,22 +269,48 @@
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 
-struct mips_frame_info {
+static struct mips_frame_info {
+	void *func;
+	int omit_fp;	/* compiled without fno-omit-frame-pointer */
 	int frame_offset;
 	int pc_offset;
+} schedule_frame, mfinfo[] = {
+	{ schedule, 0 },	/* must be first */
+	/* arch/mips/kernel/semaphore.c */
+	{ __down, 1 },
+	{ __down_interruptible, 1 },
+	/* kernel/sched.c */
+#ifdef CONFIG_PREEMPT
+	{ preempt_schedule, 0 },
+#endif
+	{ wait_for_completion, 0 },
+	{ interruptible_sleep_on, 0 },
+	{ interruptible_sleep_on_timeout, 0 },
+	{ sleep_on, 0 },
+	{ sleep_on_timeout, 0 },
+	{ yield, 0 },
+	{ io_schedule, 0 },
+	{ io_schedule_timeout, 0 },
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
+	{ __preempt_spin_lock, 0 },
+	{ __preempt_write_lock, 0 },
+#endif
+	/* kernel/timer.c */
+	{ schedule_timeout, 1 },
+/*	{ nanosleep_restart, 1 }, */
+	/* lib/rwsem-spinlock.c */
+	{ __down_read, 1 },
+	{ __down_write, 1 },
 };
-static struct mips_frame_info schedule_frame;
-static struct mips_frame_info schedule_timeout_frame;
-static struct mips_frame_info sleep_on_frame;
-static struct mips_frame_info sleep_on_timeout_frame;
-static struct mips_frame_info wait_for_completion_frame;
+
 static int mips_frame_info_initialized;
-static int __init get_frame_info(struct mips_frame_info *info, void *func)
+static int __init get_frame_info(struct mips_frame_info *info)
 {
 	int i;
+	void *func = info->func;
 	union mips_instruction *ip = (union mips_instruction *)func;
 	info->pc_offset = -1;
-	info->frame_offset = -1;
+	info->frame_offset = info->omit_fp ? 0 : -1;
 	for (i = 0; i < 128; i++, ip++) {
 		/* if jal, jalr, jr, stop. */
 		if (ip->j_format.opcode == jal_op ||
@@ -247,14 +331,16 @@
 			/* sw / sd $ra, offset($sp) */
 			if (ip->i_format.rt == 31) {
 				if (info->pc_offset != -1)
-					break;
+					continue;
 				info->pc_offset =
 					ip->i_format.simmediate / sizeof(long);
 			}
 			/* sw / sd $s8, offset($sp) */
 			if (ip->i_format.rt == 30) {
+//#if 0	/* gcc 3.4 does aggressive optimization... */
 				if (info->frame_offset != -1)
-					break;
+					continue;
+//#endif
 				info->frame_offset =
 					ip->i_format.simmediate / sizeof(long);
 			}
@@ -272,13 +358,25 @@
 
 static int __init frame_info_init(void)
 {
-	mips_frame_info_initialized =
-		!get_frame_info(&schedule_frame, schedule) &&
-		!get_frame_info(&schedule_timeout_frame, schedule_timeout) &&
-		!get_frame_info(&sleep_on_frame, sleep_on) &&
-		!get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) &&
-		!get_frame_info(&wait_for_completion_frame, wait_for_completion);
-
+	int i, found;
+	for (i = 0; i < ARRAY_SIZE(mfinfo); i++)
+		if (get_frame_info(&mfinfo[i]))
+			return -1;
+	schedule_frame = mfinfo[0];
+	/* bubble sort */
+	do {
+		struct mips_frame_info tmp;
+		found = 0;
+		for (i = 1; i < ARRAY_SIZE(mfinfo); i++) {
+			if (mfinfo[i-1].func > mfinfo[i].func) {
+				tmp = mfinfo[i];
+				mfinfo[i] = mfinfo[i-1];
+				mfinfo[i-1] = tmp;
+				found = 1;
+			}
+		}
+	} while (found);
+	mips_frame_info_initialized = 1;
 	return 0;
 }
 
@@ -303,60 +401,39 @@
 /* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
+	unsigned long stack_page;
 	unsigned long frame, pc;
 
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
-	if (!mips_frame_info_initialized)
+	stack_page = (unsigned long)p->thread_info;
+	if (!stack_page || !mips_frame_info_initialized)
 		return 0;
+
 	pc = thread_saved_pc(p);
 	if (!in_sched_functions(pc))
-		goto out;
+		return pc;
 
-	if (pc >= (unsigned long) sleep_on_timeout)
-		goto schedule_timeout_caller;
-	if (pc >= (unsigned long) sleep_on)
-		goto schedule_caller;
-	if (pc >= (unsigned long) interruptible_sleep_on_timeout)
-		goto schedule_timeout_caller;
-	if (pc >= (unsigned long)interruptible_sleep_on)
-		goto schedule_caller;
-	if (pc >= (unsigned long)wait_for_completion)
-		goto schedule_caller;
-	goto schedule_timeout_caller;
-
-schedule_caller:
 	frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
-	if (pc >= (unsigned long) sleep_on)
-		pc = ((unsigned long *)frame)[sleep_on_frame.pc_offset];
-	else
-		pc = ((unsigned long *)frame)[wait_for_completion_frame.pc_offset];
-	goto out;
+	do {
+		int i;
 
-schedule_timeout_caller:
-	/*
-	 * The schedule_timeout frame
-	 */
-	frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
+		if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
+			return 0;
 
-	/*
-	 * frame now points to sleep_on_timeout's frame
-	 */
-	pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
+		for (i = ARRAY_SIZE(mfinfo) - 1; i >= 0; i--) {
+			if (pc >= (unsigned long) mfinfo[i].func)
+				break;
+		}
+		if (i < 0)
+			break;
 
-	if (in_sched_functions(pc)) {
-		/* schedule_timeout called by [interruptible_]sleep_on_timeout */
-		frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
-		pc    = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
-	}
-
-out:
-
-#ifdef CONFIG_64BIT
-	if (current->thread.mflags & MF_32BIT_REGS) /* Kludge for 32-bit ps  */
-		pc &= 0xffffffffUL;
-#endif
+		if (mfinfo[i].omit_fp)
+			break;
+		pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
+		frame = ((unsigned long *)frame)[mfinfo[i].frame_offset];
+	} while (in_sched_functions(pc));
 
 	return pc;
 }
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 0b571a5..f1b0f3e 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -28,14 +28,18 @@
 #include <linux/security.h>
 #include <linux/signal.h>
 
+#include <asm/byteorder.h>
 #include <asm/cpu.h>
+#include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
+#include <asm/reg.h>
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -47,7 +51,130 @@
 	/* Nothing to do.. */
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+/*
+ * Read a general register set.  We always use the 64-bit format, even
+ * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
+ * Registers are sign extended to fill the available space.
+ */
+int ptrace_getregs (struct task_struct *child, __s64 __user *data)
+{
+	struct pt_regs *regs;
+	int i;
+
+	if (!access_ok(VERIFY_WRITE, data, 38 * 8))
+		return -EIO;
+
+	regs = (struct pt_regs *) ((unsigned long) child->thread_info +
+	       THREAD_SIZE - 32 - sizeof(struct pt_regs));
+
+	for (i = 0; i < 32; i++)
+		__put_user (regs->regs[i], data + i);
+	__put_user (regs->lo, data + EF_LO - EF_R0);
+	__put_user (regs->hi, data + EF_HI - EF_R0);
+	__put_user (regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+	__put_user (regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
+	__put_user (regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
+	__put_user (regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+
+	return 0;
+}
+
+/*
+ * Write a general register set.  As for PTRACE_GETREGS, we always use
+ * the 64-bit format.  On a 32-bit kernel only the lower order half
+ * (according to endianness) will be used.
+ */
+int ptrace_setregs (struct task_struct *child, __s64 __user *data)
+{
+	struct pt_regs *regs;
+	int i;
+
+	if (!access_ok(VERIFY_READ, data, 38 * 8))
+		return -EIO;
+
+	regs = (struct pt_regs *) ((unsigned long) child->thread_info +
+	       THREAD_SIZE - 32 - sizeof(struct pt_regs));
+
+	for (i = 0; i < 32; i++)
+		__get_user (regs->regs[i], data + i);
+	__get_user (regs->lo, data + EF_LO - EF_R0);
+	__get_user (regs->hi, data + EF_HI - EF_R0);
+	__get_user (regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+
+	/* badvaddr, status, and cause may not be written.  */
+
+	return 0;
+}
+
+int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
+{
+	int i;
+
+	if (!access_ok(VERIFY_WRITE, data, 33 * 8))
+		return -EIO;
+
+	if (tsk_used_math(child)) {
+		fpureg_t *fregs = get_fpu_regs(child);
+		for (i = 0; i < 32; i++)
+			__put_user (fregs[i], i + (__u64 __user *) data);
+	} else {
+		for (i = 0; i < 32; i++)
+			__put_user ((__u64) -1, i + (__u64 __user *) data);
+	}
+
+	if (cpu_has_fpu) {
+		unsigned int flags, tmp;
+
+		__put_user (child->thread.fpu.hard.fcr31, data + 64);
+
+		preempt_disable();
+		if (cpu_has_mipsmt) {
+			unsigned int vpflags = dvpe();
+			flags = read_c0_status();
+			__enable_fpu();
+			__asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
+			write_c0_status(flags);
+			evpe(vpflags);
+		} else {
+			flags = read_c0_status();
+			__enable_fpu();
+			__asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
+			write_c0_status(flags);
+		}
+		preempt_enable();
+		__put_user (tmp, data + 65);
+	} else {
+		__put_user (child->thread.fpu.soft.fcr31, data + 64);
+		__put_user ((__u32) 0, data + 65);
+	}
+
+	return 0;
+}
+
+int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
+{
+	fpureg_t *fregs;
+	int i;
+
+	if (!access_ok(VERIFY_READ, data, 33 * 8))
+		return -EIO;
+
+	fregs = get_fpu_regs(child);
+
+	for (i = 0; i < 32; i++)
+		__get_user (fregs[i], i + (__u64 __user *) data);
+
+	if (cpu_has_fpu)
+		__get_user (child->thread.fpu.hard.fcr31, data + 64);
+	else
+		__get_user (child->thread.fpu.soft.fcr31, data + 64);
+
+	/* FIR may not be written.  */
+
+	return 0;
+}
+
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret;
@@ -103,7 +230,7 @@
 		ret = -EIO;
 		if (copied != sizeof(tmp))
 			break;
-		ret = put_user(tmp,(unsigned long *) data);
+		ret = put_user(tmp,(unsigned long __user *) data);
 		break;
 	}
 
@@ -169,18 +296,53 @@
 			if (!cpu_has_fpu)
 				break;
 
-			flags = read_c0_status();
-			__enable_fpu();
-			__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
-			write_c0_status(flags);
+			preempt_disable();
+			if (cpu_has_mipsmt) {
+				unsigned int vpflags = dvpe();
+				flags = read_c0_status();
+				__enable_fpu();
+				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+				write_c0_status(flags);
+				evpe(vpflags);
+			} else {
+				flags = read_c0_status();
+				__enable_fpu();
+				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+				write_c0_status(flags);
+			}
+			preempt_enable();
 			break;
 		}
+		case DSP_BASE ... DSP_BASE + 5: {
+			dspreg_t *dregs;
+
+			if (!cpu_has_dsp) {
+				tmp = 0;
+				ret = -EIO;
+				goto out_tsk;
+			}
+			if (child->thread.dsp.used_dsp) {
+				dregs = __get_dsp_regs(child);
+				tmp = (unsigned long) (dregs[addr - DSP_BASE]);
+			} else {
+				tmp = -1;	/* DSP registers yet used  */
+			}
+			break;
+		}
+		case DSP_CONTROL:
+			if (!cpu_has_dsp) {
+				tmp = 0;
+				ret = -EIO;
+				goto out_tsk;
+			}
+			tmp = child->thread.dsp.dspcontrol;
+			break;
 		default:
 			tmp = 0;
 			ret = -EIO;
 			goto out_tsk;
 		}
-		ret = put_user(tmp, (unsigned long *) data);
+		ret = put_user(tmp, (unsigned long __user *) data);
 		break;
 	}
 
@@ -247,6 +409,25 @@
 			else
 				child->thread.fpu.soft.fcr31 = data;
 			break;
+		case DSP_BASE ... DSP_BASE + 5: {
+			dspreg_t *dregs;
+
+			if (!cpu_has_dsp) {
+				ret = -EIO;
+				break;
+			}
+
+			dregs = __get_dsp_regs(child);
+			dregs[addr - DSP_BASE] = data;
+			break;
+		}
+		case DSP_CONTROL:
+			if (!cpu_has_dsp) {
+				ret = -EIO;
+				break;
+			}
+			child->thread.dsp.dspcontrol = data;
+			break;
 		default:
 			/* The rest are not allowed. */
 			ret = -EIO;
@@ -255,6 +436,22 @@
 		break;
 		}
 
+	case PTRACE_GETREGS:
+		ret = ptrace_getregs (child, (__u64 __user *) data);
+		break;
+
+	case PTRACE_SETREGS:
+		ret = ptrace_setregs (child, (__u64 __user *) data);
+		break;
+
+	case PTRACE_GETFPREGS:
+		ret = ptrace_getfpregs (child, (__u32 __user *) data);
+		break;
+
+	case PTRACE_SETFPREGS:
+		ret = ptrace_setfpregs (child, (__u32 __user *) data);
+		break;
+
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
@@ -289,6 +486,11 @@
 		ret = ptrace_detach(child, data);
 		break;
 
+	case PTRACE_GET_THREAD_AREA:
+		ret = put_user(child->thread_info->tp_value,
+				(unsigned long __user *) data);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
@@ -303,21 +505,14 @@
 
 static inline int audit_arch(void)
 {
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
+	int arch = EM_MIPS;
 #ifdef CONFIG_64BIT
-	if (!(current->thread.mflags & MF_32BIT_REGS))
-		return AUDIT_ARCH_MIPSEL64;
-#endif /* MIPS64 */
-	return AUDIT_ARCH_MIPSEL;
-
-#else /* big endian... */
-#ifdef CONFIG_64BIT
-	if (!(current->thread.mflags & MF_32BIT_REGS))
-		return AUDIT_ARCH_MIPS64;
-#endif /* MIPS64 */
-	return AUDIT_ARCH_MIPS;
-
-#endif /* endian */
+	arch |=  __AUDIT_ARCH_64BIT;
+#endif
+#if defined(__LITTLE_ENDIAN)
+	arch |=  __AUDIT_ARCH_LE;
+#endif
+	return arch;
 }
 
 /*
@@ -327,12 +522,13 @@
 asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
 	if (unlikely(current->audit_context) && entryexit)
-		audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), regs->regs[2]);
+		audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
+		                   regs->regs[2]);
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		goto out;
 	if (!(current->ptrace & PT_PTRACED))
 		goto out;
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		goto out;
 
 	/* The 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index eee2079..9a9b049 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -24,17 +24,24 @@
 #include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
-#include <linux/signal.h>
 
 #include <asm/cpu.h>
+#include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
+int ptrace_getregs (struct task_struct *child, __s64 __user *data);
+int ptrace_setregs (struct task_struct *child, __s64 __user *data);
+
+int ptrace_getfpregs (struct task_struct *child, __u32 __user *data);
+int ptrace_setfpregs (struct task_struct *child, __u32 __user *data);
+
 /*
  * Tracing a 32-bit process with a 64-bit strace and vice versa will not
  * work.  I don't know how to fix this.
@@ -99,6 +106,35 @@
 		break;
 	}
 
+	/*
+	 * Read 4 bytes of the other process' storage
+	 *  data is a pointer specifying where the user wants the
+	 *	4 bytes copied into
+	 *  addr is a pointer in the user's storage that contains an 8 byte
+	 *	address in the other process of the 4 bytes that is to be read
+	 * (this is run in a 32-bit process looking at a 64-bit process)
+	 * when I and D space are separate, these will need to be fixed.
+	 */
+	case PTRACE_PEEKTEXT_3264:
+	case PTRACE_PEEKDATA_3264: {
+		u32 tmp;
+		int copied;
+		u32 __user * addrOthers;
+
+		ret = -EIO;
+
+		/* Get the addr in the other process that we want to read */
+		if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
+			break;
+
+		copied = access_process_vm(child, (u64)addrOthers, &tmp,
+				sizeof(tmp), 0);
+		if (copied != sizeof(tmp))
+			break;
+		ret = put_user(tmp, (u32 __user *) (unsigned long) data);
+		break;
+	}
+
 	/* Read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
 		struct pt_regs *regs;
@@ -156,12 +192,44 @@
 			if (!cpu_has_fpu)
 				break;
 
-			flags = read_c0_status();
-			__enable_fpu();
-			__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
-			write_c0_status(flags);
+			preempt_disable();
+			if (cpu_has_mipsmt) {
+				unsigned int vpflags = dvpe();
+				flags = read_c0_status();
+				__enable_fpu();
+				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+				write_c0_status(flags);
+				evpe(vpflags);
+			} else {
+				flags = read_c0_status();
+				__enable_fpu();
+				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+				write_c0_status(flags);
+			}
+			preempt_enable();
 			break;
 		}
+		case DSP_BASE ... DSP_BASE + 5:
+			if (!cpu_has_dsp) {
+				tmp = 0;
+				ret = -EIO;
+				goto out_tsk;
+			}
+			if (child->thread.dsp.used_dsp) {
+				dspreg_t *dregs = __get_dsp_regs(child);
+				tmp = (unsigned long) (dregs[addr - DSP_BASE]);
+			} else {
+				tmp = -1;	/* DSP registers yet used  */
+			}
+			break;
+		case DSP_CONTROL:
+			if (!cpu_has_dsp) {
+				tmp = 0;
+				ret = -EIO;
+				goto out_tsk;
+			}
+			tmp = child->thread.dsp.dspcontrol;
+			break;
 		default:
 			tmp = 0;
 			ret = -EIO;
@@ -181,6 +249,31 @@
 		ret = -EIO;
 		break;
 
+	/*
+	 * Write 4 bytes into the other process' storage
+	 *  data is the 4 bytes that the user wants written
+	 *  addr is a pointer in the user's storage that contains an
+	 *	8 byte address in the other process where the 4 bytes
+	 *	that is to be written
+	 * (this is run in a 32-bit process looking at a 64-bit process)
+	 * when I and D space are separate, these will need to be fixed.
+	 */
+	case PTRACE_POKETEXT_3264:
+	case PTRACE_POKEDATA_3264: {
+		u32 __user * addrOthers;
+
+		/* Get the addr in the other process that we want to write into */
+		ret = -EIO;
+		if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
+			break;
+		ret = 0;
+		if (access_process_vm(child, (u64)addrOthers, &data,
+					sizeof(data), 1) == sizeof(data))
+			break;
+		ret = -EIO;
+		break;
+	}
+
 	case PTRACE_POKEUSR: {
 		struct pt_regs *regs;
 		ret = 0;
@@ -231,6 +324,22 @@
 			else
 				child->thread.fpu.soft.fcr31 = data;
 			break;
+		case DSP_BASE ... DSP_BASE + 5:
+			if (!cpu_has_dsp) {
+				ret = -EIO;
+				break;
+			}
+
+			dspreg_t *dregs = __get_dsp_regs(child);
+			dregs[addr - DSP_BASE] = data;
+			break;
+		case DSP_CONTROL:
+			if (!cpu_has_dsp) {
+				ret = -EIO;
+				break;
+			}
+			child->thread.dsp.dspcontrol = data;
+			break;
 		default:
 			/* The rest are not allowed. */
 			ret = -EIO;
@@ -239,6 +348,22 @@
 		break;
 		}
 
+	case PTRACE_GETREGS:
+		ret = ptrace_getregs (child, (__u64 __user *) (__u64) data);
+		break;
+
+	case PTRACE_SETREGS:
+		ret = ptrace_setregs (child, (__u64 __user *) (__u64) data);
+		break;
+
+	case PTRACE_GETFPREGS:
+		ret = ptrace_getfpregs (child, (__u32 __user *) (__u64) data);
+		break;
+
+	case PTRACE_SETFPREGS:
+		ret = ptrace_setfpregs (child, (__u32 __user *) (__u64) data);
+		break;
+
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
@@ -269,10 +394,25 @@
 		wake_up_process(child);
 		break;
 
+	case PTRACE_GET_THREAD_AREA:
+		ret = put_user(child->thread_info->tp_value,
+				(unsigned int __user *) (unsigned long) data);
+		break;
+
 	case PTRACE_DETACH: /* detach a process that was attached. */
 		ret = ptrace_detach(child, data);
 		break;
 
+	case PTRACE_GETEVENTMSG:
+		ret = put_user(child->ptrace_message,
+			       (unsigned int __user *) (unsigned long) data);
+		break;
+
+	case PTRACE_GET_THREAD_AREA_3264:
+		ret = put_user(child->thread_info->tp_value,
+				(unsigned long __user *) (unsigned long) data);
+		break;
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 1a14c6b..283a985 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -32,7 +32,7 @@
 
 	.set	noreorder
 	.set	mips3
-	/* Save floating point context */
+
 LEAF(_save_fp_context)
 	cfc1	t1, fcr31
 
@@ -74,9 +74,6 @@
 	EX	sdc1 $f28, SC_FPREGS+224(a0)
 	EX	sdc1 $f30, SC_FPREGS+240(a0)
 	EX	sw t1, SC_FPC_CSR(a0)
-	cfc1	t0, $0				# implementation/version
-	EX	sw t0, SC_FPC_EIR(a0)
-
 	jr	ra
 	 li	v0, 0					# success
 	END(_save_fp_context)
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
new file mode 100644
index 0000000..8c81f3c
--- /dev/null
+++ b/arch/mips/kernel/rtlx.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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/fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/seq_file.h>
+#include <linux/syscalls.h>
+#include <linux/moduleloader.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <asm/mipsmtregs.h>
+#include <asm/cacheflush.h>
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/rtlx.h>
+
+#define RTLX_MAJOR 64
+#define RTLX_TARG_VPE 1
+
+struct rtlx_info *rtlx;
+static int major;
+static char module_name[] = "rtlx";
+static inline int spacefree(int read, int write, int size);
+
+static struct chan_waitqueues {
+	wait_queue_head_t rt_queue;
+	wait_queue_head_t lx_queue;
+} channel_wqs[RTLX_CHANNELS];
+
+static struct irqaction irq;
+static int irq_num;
+
+extern void *vpe_get_shared(int index);
+
+static void rtlx_dispatch(struct pt_regs *regs)
+{
+	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
+}
+
+irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	irqreturn_t r = IRQ_HANDLED;
+	int i;
+
+	for (i = 0; i < RTLX_CHANNELS; i++) {
+		struct rtlx_channel *chan = &rtlx->channel[i];
+
+		if (chan->lx_read != chan->lx_write)
+			wake_up_interruptible(&channel_wqs[i].lx_queue);
+	}
+
+	return r;
+}
+
+void dump_rtlx(void)
+{
+	int i;
+
+	printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
+
+	for (i = 0; i < RTLX_CHANNELS; i++) {
+		struct rtlx_channel *chan = &rtlx->channel[i];
+
+		printk(" rt_state %d lx_state %d buffer_size %d\n",
+		       chan->rt_state, chan->lx_state, chan->buffer_size);
+
+		printk(" rt_read %d rt_write %d\n",
+		       chan->rt_read, chan->rt_write);
+
+		printk(" lx_read %d lx_write %d\n",
+		       chan->lx_read, chan->lx_write);
+
+		printk(" rt_buffer <%s>\n", chan->rt_buffer);
+		printk(" lx_buffer <%s>\n", chan->lx_buffer);
+	}
+}
+
+/* call when we have the address of the shared structure from the SP side. */
+static int rtlx_init(struct rtlx_info *rtlxi)
+{
+	int i;
+
+	if (rtlxi->id != RTLX_ID) {
+		printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi);
+		return (-ENOEXEC);
+	}
+
+	/* initialise the wait queues */
+	for (i = 0; i < RTLX_CHANNELS; i++) {
+		init_waitqueue_head(&channel_wqs[i].rt_queue);
+		init_waitqueue_head(&channel_wqs[i].lx_queue);
+	}
+
+	/* set up for interrupt handling */
+	memset(&irq, 0, sizeof(struct irqaction));
+
+	if (cpu_has_vint) {
+		set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+	}
+
+	irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+	irq.handler = rtlx_interrupt;
+	irq.flags = SA_INTERRUPT;
+	irq.name = "RTLX";
+	irq.dev_id = rtlx;
+	setup_irq(irq_num, &irq);
+
+	rtlx = rtlxi;
+	return (0);
+}
+
+/* only allow one open process at a time to open each channel */
+static int rtlx_open(struct inode *inode, struct file *filp)
+{
+	int minor, ret;
+	struct rtlx_channel *chan;
+
+	/* assume only 1 device at the mo. */
+	minor = MINOR(inode->i_rdev);
+
+	if (rtlx == NULL) {
+		struct rtlx_info **p;
+		if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
+			printk(" vpe_get_shared is NULL. Has an SP program been loaded?\n");
+			return (-EFAULT);
+		}
+
+		if (*p == NULL) {
+			printk(" vpe_shared %p %p\n", p, *p);
+			return (-EFAULT);
+		}
+
+		if ((ret = rtlx_init(*p)) < 0)
+			return (ret);
+	}
+
+	chan = &rtlx->channel[minor];
+
+	/* already open? */
+	if (chan->lx_state == RTLX_STATE_OPENED)
+		return (-EBUSY);
+
+	chan->lx_state = RTLX_STATE_OPENED;
+	return (0);
+}
+
+static int rtlx_release(struct inode *inode, struct file *filp)
+{
+	int minor;
+
+	minor = MINOR(inode->i_rdev);
+	rtlx->channel[minor].lx_state = RTLX_STATE_UNUSED;
+	return (0);
+}
+
+static unsigned int rtlx_poll(struct file *file, poll_table * wait)
+{
+	int minor;
+	unsigned int mask = 0;
+	struct rtlx_channel *chan;
+
+	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	chan = &rtlx->channel[minor];
+
+	poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+	poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+
+	/* data available to read? */
+	if (chan->lx_read != chan->lx_write)
+		mask |= POLLIN | POLLRDNORM;
+
+	/* space to write */
+	if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size))
+		mask |= POLLOUT | POLLWRNORM;
+
+	return (mask);
+}
+
+static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
+			 loff_t * ppos)
+{
+	size_t fl = 0L;
+	int minor;
+	struct rtlx_channel *lx;
+	DECLARE_WAITQUEUE(wait, current);
+
+	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	lx = &rtlx->channel[minor];
+
+	/* data available? */
+	if (lx->lx_write == lx->lx_read) {
+		if (file->f_flags & O_NONBLOCK)
+			return (0);	// -EAGAIN makes cat whinge
+
+		/* go to sleep */
+		add_wait_queue(&channel_wqs[minor].lx_queue, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		while (lx->lx_write == lx->lx_read)
+			schedule();
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&channel_wqs[minor].lx_queue, &wait);
+
+		/* back running */
+	}
+
+	/* find out how much in total */
+	count = min( count,
+		     (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
+
+	/* then how much from the read pointer onwards */
+	fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
+
+	copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
+
+	/* and if there is anything left at the beginning of the buffer */
+	if ( count - fl )
+		copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
+
+	/* update the index */
+	lx->lx_read += count;
+	lx->lx_read %= lx->buffer_size;
+
+	return (count);
+}
+
+static inline int spacefree(int read, int write, int size)
+{
+	if (read == write) {
+		/* never fill the buffer completely, so indexes are always equal if empty
+		   and only empty, or !equal if data available */
+		return (size - 1);
+	}
+
+	return ((read + size - write) % size) - 1;
+}
+
+static ssize_t rtlx_write(struct file *file, const char __user * buffer,
+			  size_t count, loff_t * ppos)
+{
+	int minor;
+	struct rtlx_channel *rt;
+	size_t fl;
+	DECLARE_WAITQUEUE(wait, current);
+
+	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	rt = &rtlx->channel[minor];
+
+	/* any space left... */
+	if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) {
+
+		if (file->f_flags & O_NONBLOCK)
+			return (-EAGAIN);
+
+		add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		while (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size))
+			schedule();
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
+	}
+
+	/* total number of bytes to copy */
+	count = min( count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
+
+	/* first bit from write pointer to the end of the buffer, or count */
+	fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
+
+	copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
+
+	/* if there's any left copy to the beginning of the buffer */
+	if( count - fl )
+		copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
+
+	rt->rt_write += count;
+	rt->rt_write %= rt->buffer_size;
+
+	return(count);
+}
+
+static struct file_operations rtlx_fops = {
+	.owner = THIS_MODULE,
+	.open = rtlx_open,
+	.release = rtlx_release,
+	.write = rtlx_write,
+	.read = rtlx_read,
+	.poll = rtlx_poll
+};
+
+static int rtlx_module_init(void)
+{
+	if ((major = register_chrdev(RTLX_MAJOR, module_name, &rtlx_fops)) < 0) {
+		printk("rtlx_module_init: unable to register device\n");
+		return (-EBUSY);
+	}
+
+	if (major == 0)
+		major = RTLX_MAJOR;
+
+	return (0);
+}
+
+static void rtlx_module_exit(void)
+{
+	unregister_chrdev(major, module_name);
+}
+
+module_init(rtlx_module_init);
+module_exit(rtlx_module_exit);
+MODULE_DESCRIPTION("MIPS RTLX");
+MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 17b5030..4dd8e8b 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -578,7 +578,7 @@
 	sys	sys_fremovexattr	2	/* 4235 */
 	sys	sys_tkill		2
 	sys	sys_sendfile64		5
-	sys	sys_futex		2
+	sys	sys_futex		6
 	sys	sys_sched_setaffinity	3
 	sys	sys_sched_getaffinity	3	/* 4240 */
 	sys	sys_io_setup		2
@@ -587,7 +587,7 @@
 	sys	sys_io_submit		3
 	sys	sys_io_cancel		3	/* 4245 */
 	sys	sys_exit_group		1
-	sys	sys_lookup_dcookie	3
+	sys	sys_lookup_dcookie	4
 	sys	sys_epoll_create	1
 	sys	sys_epoll_ctl		4
 	sys	sys_epoll_wait		3	/* 4250 */
@@ -618,12 +618,15 @@
 	sys	sys_mq_notify		2	/* 4275 */
 	sys	sys_mq_getsetattr	3
 	sys	sys_ni_syscall		0	/* sys_vserver */
-	sys	sys_waitid		4
+	sys	sys_waitid		5
 	sys	sys_ni_syscall		0	/* available, was setaltroot */
-	sys	sys_add_key		5
+	sys	sys_add_key		5	/* 4280 */
 	sys	sys_request_key		4
 	sys	sys_keyctl		5
-
+	sys	sys_set_thread_area	1
+	sys	sys_inotify_init	0
+	sys	sys_inotify_add_watch	3	/* 4285 */
+	sys	sys_inotify_rm_watch	2
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index ffb22a2..9085838 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -449,3 +449,7 @@
 	PTR	sys_add_key
 	PTR	sys_request_key			/* 5240 */
 	PTR	sys_keyctl
+	PTR	sys_set_thread_area
+	PTR	sys_inotify_init
+	PTR	sys_inotify_add_watch
+	PTR	sys_inotify_rm_watch		/* 5245 */
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index e52049c..7e66eb8 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -176,7 +176,7 @@
 	PTR	sys_fork
 	PTR	sys32_execve
 	PTR	sys_exit
-	PTR	sys32_wait4
+	PTR	compat_sys_wait4
 	PTR	sys_kill			/* 6060 */
 	PTR	sys32_newuname
 	PTR	sys_semget
@@ -216,7 +216,7 @@
 	PTR	compat_sys_getrusage
 	PTR	sys32_sysinfo
 	PTR	compat_sys_times
-	PTR	sys_ptrace
+	PTR	sys32_ptrace
 	PTR	sys_getuid			/* 6100 */
 	PTR	sys_syslog
 	PTR	sys_getgid
@@ -243,14 +243,14 @@
 	PTR	sys_capget
 	PTR	sys_capset
 	PTR	sys32_rt_sigpending		/* 6125 */
-	PTR	compat_sys_rt_sigtimedwait
-	PTR	sys32_rt_sigqueueinfo
+	PTR	sysn32_rt_sigtimedwait
+	PTR	sys_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
 	PTR	sys32_sigaltstack
 	PTR	compat_sys_utime		/* 6130 */
 	PTR	sys_mknod
 	PTR	sys32_personality
-	PTR	sys_ustat
+	PTR	sys32_ustat
 	PTR	compat_sys_statfs
 	PTR	compat_sys_fstatfs		/* 6135 */
 	PTR	sys_sysfs
@@ -329,7 +329,7 @@
 	PTR	sys_epoll_wait
 	PTR	sys_remap_file_pages		/* 6210 */
 	PTR	sysn32_rt_sigreturn
-	PTR	sys_fcntl
+	PTR	compat_sys_fcntl64
 	PTR	sys_set_tid_address
 	PTR	sys_restart_syscall
 	PTR	sys_semtimedop			/* 6215 */
@@ -337,15 +337,15 @@
 	PTR	compat_sys_statfs64
 	PTR	compat_sys_fstatfs64
 	PTR	sys_sendfile64
-	PTR	sys_timer_create		/* 6220 */
-	PTR	sys_timer_settime
-	PTR	sys_timer_gettime
+	PTR	sys32_timer_create		/* 6220 */
+	PTR	compat_sys_timer_settime
+	PTR	compat_sys_timer_gettime
 	PTR	sys_timer_getoverrun
 	PTR	sys_timer_delete
-	PTR	sys_clock_settime		/* 6225 */
-	PTR	sys_clock_gettime
-	PTR	sys_clock_getres
-	PTR	sys_clock_nanosleep
+	PTR	compat_sys_clock_settime		/* 6225 */
+	PTR	compat_sys_clock_gettime
+	PTR	compat_sys_clock_getres
+	PTR	compat_sys_clock_nanosleep
 	PTR	sys_tgkill
 	PTR	compat_sys_utimes		/* 6230 */
 	PTR	sys_ni_syscall			/* sys_mbind */
@@ -358,8 +358,12 @@
 	PTR	compat_sys_mq_notify
 	PTR	compat_sys_mq_getsetattr
 	PTR	sys_ni_syscall			/* 6240, sys_vserver */
-	PTR	sys_waitid
+	PTR	sysn32_waitid
 	PTR	sys_ni_syscall			/* available, was setaltroot */
 	PTR	sys_add_key
 	PTR	sys_request_key
 	PTR	sys_keyctl			/* 6245 */
+	PTR	sys_set_thread_area
+	PTR	sys_inotify_init
+	PTR	sys_inotify_add_watch
+	PTR	sys_inotify_rm_watch
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 739f399..5a16401 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -316,13 +316,13 @@
 	PTR	sys_vhangup
 	PTR	sys_ni_syscall			/* was sys_idle	 */
 	PTR	sys_ni_syscall			/* sys_vm86 */
-	PTR	sys32_wait4
+	PTR	compat_sys_wait4
 	PTR	sys_swapoff			/* 4115 */
 	PTR	sys32_sysinfo
 	PTR	sys32_ipc
 	PTR	sys_fsync
 	PTR	sys32_sigreturn
-	PTR	sys_clone			/* 4120 */
+	PTR	sys32_clone			/* 4120 */
 	PTR	sys_setdomainname
 	PTR	sys32_newuname
 	PTR	sys_ni_syscall			/* sys_modify_ldt */
@@ -391,7 +391,7 @@
 	PTR	sys_getresuid
 	PTR	sys_ni_syscall			/* was query_module */
 	PTR	sys_poll
-	PTR	sys_nfsservctl
+	PTR	compat_sys_nfsservctl
 	PTR	sys_setresgid			/* 4190 */
 	PTR	sys_getresgid
 	PTR	sys_prctl
@@ -459,7 +459,7 @@
 	PTR	sys_fadvise64_64
 	PTR	compat_sys_statfs64		/* 4255 */
 	PTR	compat_sys_fstatfs64
-	PTR	sys_timer_create
+	PTR	sys32_timer_create
 	PTR	compat_sys_timer_settime
 	PTR	compat_sys_timer_gettime
 	PTR	sys_timer_getoverrun		/* 4260 */
@@ -480,9 +480,13 @@
 	PTR	compat_sys_mq_notify		/* 4275 */
 	PTR	compat_sys_mq_getsetattr
 	PTR	sys_ni_syscall			/* sys_vserver */
-	PTR	sys_waitid
+	PTR	sys32_waitid
 	PTR	sys_ni_syscall			/* available, was setaltroot */
 	PTR	sys_add_key			/* 4280 */
 	PTR	sys_request_key
 	PTR	sys_keyctl
+	PTR	sys_set_thread_area
+	PTR	sys_inotify_init
+	PTR	sys_inotify_add_watch		/* 4285 */
+	PTR	sys_inotify_rm_watch
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c
index 9c40fe5..1265358 100644
--- a/arch/mips/kernel/semaphore.c
+++ b/arch/mips/kernel/semaphore.c
@@ -42,24 +42,28 @@
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		__asm__ __volatile__(
-		"1:	ll	%0, %2					\n"
+		"	.set	mips3					\n"
+		"1:	ll	%0, %2		# __sem_update_count	\n"
 		"	sra	%1, %0, 31				\n"
 		"	not	%1					\n"
 		"	and	%1, %0, %1				\n"
-		"	add	%1, %1, %3				\n"
+		"	addu	%1, %1, %3				\n"
 		"	sc	%1, %2					\n"
 		"	beqzl	%1, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
 		: "r" (incr), "m" (sem->count));
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
-		"1:	ll	%0, %2					\n"
+		"	.set	mips3					\n"
+		"1:	ll	%0, %2		# __sem_update_count	\n"
 		"	sra	%1, %0, 31				\n"
 		"	not	%1					\n"
 		"	and	%1, %0, %1				\n"
-		"	add	%1, %1, %3				\n"
+		"	addu	%1, %1, %3				\n"
 		"	sc	%1, %2					\n"
 		"	beqz	%1, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
 		: "r" (incr), "m" (sem->count));
 	} else {
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 12b531c..d86affa 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -37,12 +37,13 @@
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
+#include <asm/cache.h>
 #include <asm/cpu.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/system.h>
 
-struct cpuinfo_mips cpu_data[NR_CPUS];
+struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
 EXPORT_SYMBOL(cpu_data);
 
@@ -62,8 +63,8 @@
  *
  * These are initialized so they are in the .data section
  */
-unsigned long mips_machtype = MACH_UNKNOWN;
-unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
+unsigned long mips_machtype __read_mostly = MACH_UNKNOWN;
+unsigned long mips_machgroup __read_mostly = MACH_GROUP_UNKNOWN;
 
 EXPORT_SYMBOL(mips_machtype);
 EXPORT_SYMBOL(mips_machgroup);
@@ -77,7 +78,7 @@
  * mips_io_port_base is the begin of the address space to which x86 style
  * I/O ports are mapped.
  */
-const unsigned long mips_io_port_base = -1;
+const unsigned long mips_io_port_base __read_mostly = -1;
 EXPORT_SYMBOL(mips_io_port_base);
 
 /*
@@ -510,31 +511,7 @@
 #undef MAXMEM
 #undef MAXMEM_PFN
 
-static int __initdata earlyinit_debug;
-
-static int __init earlyinit_debug_setup(char *str)
-{
-	earlyinit_debug = 1;
-	return 1;
-}
-__setup("earlyinit_debug", earlyinit_debug_setup);
-
-extern initcall_t __earlyinitcall_start, __earlyinitcall_end;
-
-static void __init do_earlyinitcalls(void)
-{
-	initcall_t *call, *start, *end;
-
-	start = &__earlyinitcall_start;
-	end = &__earlyinitcall_end;
-
-	for (call = start; call < end; call++) {
-		if (earlyinit_debug)
-			printk("calling earlyinitcall 0x%p\n", *call);
-
-		(*call)();
-	}
-}
+extern void plat_setup(void);
 
 void __init setup_arch(char **cmdline_p)
 {
@@ -551,7 +528,7 @@
 #endif
 
 	/* call board setup routine */
-	do_earlyinitcalls();
+	plat_setup();
 
 	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
 	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
@@ -573,3 +550,12 @@
 }
 
 __setup("nofpu", fpu_disable);
+
+int __init dsp_disable(char *s)
+{
+	cpu_data[0].ases &= ~MIPS_ASE_DSP;
+
+	return 1;
+}
+
+__setup("nodsp", dsp_disable);
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index f9234df..0f66ae58 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -8,13 +8,14 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 
+#include <linux/config.h>
+
 static inline int
 setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
 	int err = 0;
 
 	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
-	err |= __put_user(regs->cp0_status, &sc->sc_status);
 
 #define save_gp_reg(i) do {						\
 	err |= __put_user(regs->regs[i], &sc->sc_regs[i]);		\
@@ -30,10 +31,32 @@
 	save_gp_reg(31);
 #undef save_gp_reg
 
+#ifdef CONFIG_32BIT
 	err |= __put_user(regs->hi, &sc->sc_mdhi);
 	err |= __put_user(regs->lo, &sc->sc_mdlo);
-	err |= __put_user(regs->cp0_cause, &sc->sc_cause);
-	err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
+	if (cpu_has_dsp) {
+		err |= __put_user(mfhi1(), &sc->sc_hi1);
+		err |= __put_user(mflo1(), &sc->sc_lo1);
+		err |= __put_user(mfhi2(), &sc->sc_hi2);
+		err |= __put_user(mflo2(), &sc->sc_lo2);
+		err |= __put_user(mfhi3(), &sc->sc_hi3);
+		err |= __put_user(mflo3(), &sc->sc_lo3);
+		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+	}
+#endif
+#ifdef CONFIG_64BIT
+	err |= __put_user(regs->hi, &sc->sc_hi[0]);
+	err |= __put_user(regs->lo, &sc->sc_lo[0]);
+	if (cpu_has_dsp) {
+		err |= __put_user(mfhi1(), &sc->sc_hi[1]);
+		err |= __put_user(mflo1(), &sc->sc_lo[1]);
+		err |= __put_user(mfhi2(), &sc->sc_hi[2]);
+		err |= __put_user(mflo2(), &sc->sc_lo[2]);
+		err |= __put_user(mfhi3(), &sc->sc_hi[3]);
+		err |= __put_user(mflo3(), &sc->sc_lo[3]);
+		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+	}
+#endif
 
 	err |= __put_user(!!used_math(), &sc->sc_used_math);
 
@@ -61,15 +84,40 @@
 static inline int
 restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
-	int err = 0;
 	unsigned int used_math;
+	unsigned long treg;
+	int err = 0;
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
 	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+#ifdef CONFIG_32BIT
 	err |= __get_user(regs->hi, &sc->sc_mdhi);
 	err |= __get_user(regs->lo, &sc->sc_mdlo);
+	if (cpu_has_dsp) {
+		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+	}
+#endif
+#ifdef CONFIG_64BIT
+	err |= __get_user(regs->hi, &sc->sc_hi[0]);
+	err |= __get_user(regs->lo, &sc->sc_lo[0]);
+	if (cpu_has_dsp) {
+		err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
+		err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
+		err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
+		err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
+		err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
+		err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
+		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+	}
+#endif
 
 #define restore_gp_reg(i) do {						\
 	err |= __get_user(regs->regs[i], &sc->sc_regs[i]);		\
@@ -112,7 +160,7 @@
 static inline void *
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 {
-	unsigned long sp, almask;
+	unsigned long sp;
 
 	/* Default to using normal stack */
 	sp = regs->regs[29];
@@ -128,10 +176,32 @@
 	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
-	if (PLAT_TRAMPOLINE_STUFF_LINE)
-		almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1);
-	else
-		almask = ALMASK;
+	return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
+}
 
-	return (void *)((sp - frame_size) & almask);
+static inline int install_sigtramp(unsigned int __user *tramp,
+	unsigned int syscall)
+{
+	int err;
+
+	/*
+	 * Set up the return code ...
+	 *
+	 *         li      v0, __NR__foo_sigreturn
+	 *         syscall
+	 */
+
+	err = __put_user(0x24020000 + syscall, tramp + 0);
+	err |= __put_user(0x0000000c          , tramp + 1);
+	if (ICACHE_REFILLS_WORKAROUND_WAR) {
+		err |= __put_user(0, tramp + 2);
+		err |= __put_user(0, tramp + 3);
+		err |= __put_user(0, tramp + 4);
+		err |= __put_user(0, tramp + 5);
+		err |= __put_user(0, tramp + 6);
+		err |= __put_user(0, tramp + 7);
+	}
+	flush_cache_sigtramp((unsigned long) tramp);
+
+	return err;
 }
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 0209c1d..9202a17 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -8,6 +8,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
+#include <linux/cache.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/personality.h>
@@ -21,6 +22,7 @@
 #include <linux/unistd.h>
 #include <linux/compiler.h>
 
+#include <asm/abi.h>
 #include <asm/asm.h>
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
@@ -29,6 +31,7 @@
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
 #include <asm/cpu-features.h>
+#include <asm/war.h>
 
 #include "signal-common.h"
 
@@ -36,7 +39,7 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-static int do_signal(sigset_t *oldset, struct pt_regs *regs);
+int do_signal(sigset_t *oldset, struct pt_regs *regs);
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
@@ -47,9 +50,10 @@
 __attribute_used__ noinline static int
 _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
-	sigset_t *uset, saveset, newset;
+	sigset_t saveset, newset;
+	sigset_t __user *uset;
 
-	uset = (sigset_t *) regs.regs[4];
+	uset = (sigset_t __user *) regs.regs[4];
 	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -75,7 +79,8 @@
 __attribute_used__ noinline static int
 _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
-	sigset_t *unewset, saveset, newset;
+	sigset_t saveset, newset;
+	sigset_t __user *unewset;
 	size_t sigsetsize;
 
 	/* XXX Don't preclude handling different sized sigset_t's.  */
@@ -83,7 +88,7 @@
 	if (sigsetsize != sizeof(sigset_t))
 		return -EINVAL;
 
-	unewset = (sigset_t *) regs.regs[4];
+	unewset = (sigset_t __user *) regs.regs[4];
 	if (copy_from_user(&newset, unewset, sizeof(newset)))
 		return -EFAULT;
 	sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -147,33 +152,46 @@
 
 asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
 {
-	const stack_t *uss = (const stack_t *) regs.regs[4];
-	stack_t *uoss = (stack_t *) regs.regs[5];
+	const stack_t __user *uss = (const stack_t __user *) regs.regs[4];
+	stack_t __user *uoss = (stack_t __user *) regs.regs[5];
 	unsigned long usp = regs.regs[29];
 
 	return do_sigaltstack(uss, uoss, usp);
 }
 
-#if PLAT_TRAMPOLINE_STUFF_LINE
-#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
-#else
-#define __tramp
-#endif
-
+/*
+ * Horribly complicated - with the bloody RM9000 workarounds enabled
+ * the signal trampolines is moving to the end of the structure so we can
+ * increase the alignment without breaking software compatibility.
+ */
 #ifdef CONFIG_TRAD_SIGNALS
 struct sigframe {
 	u32 sf_ass[4];			/* argument save space for o32 */
-	u32 sf_code[2] __tramp;		/* signal trampoline */
-	struct sigcontext sf_sc __tramp;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 sf_pad[2];
+#else
+	u32 sf_code[2];			/* signal trampoline */
+#endif
+	struct sigcontext sf_sc;
 	sigset_t sf_mask;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
+#endif
 };
 #endif
 
 struct rt_sigframe {
 	u32 rs_ass[4];			/* argument save space for o32 */
-	u32 rs_code[2] __tramp;		/* signal trampoline */
-	struct siginfo rs_info __tramp;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 rs_pad[2];
+#else
+	u32 rs_code[2];			/* signal trampoline */
+#endif
+	struct siginfo rs_info;
 	struct ucontext rs_uc;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 rs_code[8] ____cacheline_aligned;	/* signal trampoline */
+#endif
 };
 
 #ifdef CONFIG_TRAD_SIGNALS
@@ -214,7 +232,7 @@
 badframe:
 	force_sig(SIGSEGV, current);
 }
-#endif
+#endif /* CONFIG_TRAD_SIGNALS */
 
 save_static_function(sys_rt_sigreturn);
 __attribute_used__ noinline static void
@@ -260,7 +278,7 @@
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
-static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set)
 {
 	struct sigframe *frame;
@@ -270,17 +288,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	/*
-	 * Set up the return code ...
-	 *
-	 *         li      v0, __NR_sigreturn
-	 *         syscall
-	 */
-	if (PLAT_TRAMPOLINE_STUFF_LINE)
-		__clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE);
-	err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0);
-	err |= __put_user(0x0000000c                 , frame->sf_code + 1);
-	flush_cache_sigtramp((unsigned long) frame->sf_code);
+	install_sigtramp(frame->sf_code, __NR_sigreturn);
 
 	err |= setup_sigcontext(regs, &frame->sf_sc);
 	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
@@ -309,14 +317,15 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, frame->regs[31]);
 #endif
-        return;
+        return 1;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
+	return 0;
 }
 #endif
 
-static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	int signr, sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe *frame;
@@ -326,17 +335,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	/*
-	 * Set up the return code ...
-	 *
-	 *         li      v0, __NR_rt_sigreturn
-	 *         syscall
-	 */
-	if (PLAT_TRAMPOLINE_STUFF_LINE)
-		__clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
-	err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0);
-	err |= __put_user(0x0000000c                    , frame->rs_code + 1);
-	flush_cache_sigtramp((unsigned long) frame->rs_code);
+	install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
 
 	/* Create siginfo.  */
 	err |= copy_siginfo_to_user(&frame->rs_info, info);
@@ -378,18 +377,21 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 #endif
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
+	return 0;
 }
 
 extern void setup_rt_frame_n32(struct k_sigaction * ka,
 	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info);
 
-static inline void handle_signal(unsigned long sig, siginfo_t *info,
+static inline int handle_signal(unsigned long sig, siginfo_t *info,
 	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
 {
+	int ret;
+
 	switch(regs->regs[0]) {
 	case ERESTART_RESTARTBLOCK:
 	case ERESTARTNOHAND:
@@ -408,22 +410,10 @@
 
 	regs->regs[0] = 0;		/* Don't deal with this again.  */
 
-#ifdef CONFIG_TRAD_SIGNALS
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-#else
-	if (1) {
-#endif
-#ifdef CONFIG_MIPS32_N32
-		if ((current->thread.mflags & MF_ABI_MASK) == MF_N32)
-			setup_rt_frame_n32 (ka, regs, sig, oldset, info);
-		else
-#endif
-			setup_rt_frame(ka, regs, sig, oldset, info);
-	}
-#ifdef CONFIG_TRAD_SIGNALS
+	if (sig_uses_siginfo(ka))
+		ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
 	else
-		setup_frame(ka, regs, sig, oldset);
-#endif
+		ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -431,23 +421,16 @@
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	return ret;
 }
 
-extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
-extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
-
-static int do_signal(sigset_t *oldset, struct pt_regs *regs)
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
 {
 	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
-#ifdef CONFIG_BINFMT_ELF32
-	if ((current->thread.mflags & MF_ABI_MASK) == MF_O32) {
-		return do_signal32(oldset, regs);
-	}
-#endif
-
 	/*
 	 * We want the common case to go fast, which is why we may in certain
 	 * cases get here from kernel mode. Just return without doing anything
@@ -463,10 +446,8 @@
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		handle_signal(signr, &info, &ka, oldset, regs);
-		return 1;
-	}
+	if (signr > 0)
+		return handle_signal(signr, &info, &ka, oldset, regs);
 
 no_signal:
 	/*
@@ -499,18 +480,6 @@
 {
 	/* deal with pending signal delivery */
 	if (thread_info_flags & _TIF_SIGPENDING) {
-#ifdef CONFIG_BINFMT_ELF32
-		if (likely((current->thread.mflags & MF_ABI_MASK) == MF_O32)) {
-			do_signal32(oldset, regs);
-			return;
-		}
-#endif
-#ifdef CONFIG_BINFMT_IRIX
-		if (unlikely(current->personality != PER_LINUX)) {
-			do_irix_signal(oldset, regs);
-			return;
-		}
-#endif
-		do_signal(oldset, regs);
+		current->thread.abi->do_signal(oldset, regs);
 	}
 }
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 8ddfbd8..dbe8213 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -7,6 +7,7 @@
  * Copyright (C) 1994 - 2000  Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
+#include <linux/cache.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -21,6 +22,7 @@
 #include <linux/suspend.h>
 #include <linux/compiler.h>
 
+#include <asm/abi.h>
 #include <asm/asm.h>
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
@@ -29,6 +31,7 @@
 #include <asm/ucontext.h>
 #include <asm/system.h>
 #include <asm/fpu.h>
+#include <asm/war.h>
 
 #define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
 
@@ -76,8 +79,10 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			compat_sigval_t _sigval;/* same as below */
+			int _sys_private;       /* not to be passed to user */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -259,11 +264,12 @@
 
 	if (act) {
 		old_sigset_t mask;
+		s32 handler;
 
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 			return -EFAULT;
-		err |= __get_user((u32)(u64)new_ka.sa.sa_handler,
-		                  &act->sa_handler);
+		err |= __get_user(handler, &act->sa_handler);
+		new_ka.sa.sa_handler = (void*)(s64)handler;
 		err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		err |= __get_user(mask, &act->sa_mask.sig[0]);
 		if (err)
@@ -331,8 +337,9 @@
 
 static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
 {
+	u32 used_math;
 	int err = 0;
-	__u32 used_math;
+	s32 treg;
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -340,6 +347,15 @@
 	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
 	err |= __get_user(regs->hi, &sc->sc_mdhi);
 	err |= __get_user(regs->lo, &sc->sc_mdlo);
+	if (cpu_has_dsp) {
+		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+	}
 
 #define restore_gp_reg(i) do {						\
 	err |= __get_user(regs->regs[i], &sc->sc_regs[i]);		\
@@ -378,16 +394,30 @@
 
 struct sigframe {
 	u32 sf_ass[4];			/* argument save space for o32 */
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 sf_pad[2];
+#else
 	u32 sf_code[2];			/* signal trampoline */
+#endif
 	struct sigcontext32 sf_sc;
 	sigset_t sf_mask;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
+#endif
 };
 
 struct rt_sigframe32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 rs_pad[2];
+#else
 	u32 rs_code[2];			/* signal trampoline */
+#endif
 	compat_siginfo_t rs_info;
 	struct ucontext32 rs_uc;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 rs_code[8] __attribute__((aligned(32)));	/* signal trampoline */
+#endif
 };
 
 int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
@@ -411,6 +441,11 @@
 		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 	else {
 		switch (from->si_code >> 16) {
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_tid, &to->si_tid);
+			err |= __put_user(from->si_overrun, &to->si_overrun);
+			err |= __put_user(from->si_int, &to->si_int);
+			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
 			err |= __put_user(from->si_stime, &to->si_stime);
@@ -480,6 +515,7 @@
 _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
 	struct rt_sigframe32 *frame;
+	mm_segment_t old_fs;
 	sigset_t set;
 	stack_t st;
 	s32 sp;
@@ -510,7 +546,10 @@
 
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
 	do_sigaltstack(&st, NULL, regs.regs[29]);
+	set_fs (old_fs);
 
 	/*
 	 * Don't let your children do this ...
@@ -550,8 +589,15 @@
 
 	err |= __put_user(regs->hi, &sc->sc_mdhi);
 	err |= __put_user(regs->lo, &sc->sc_mdlo);
-	err |= __put_user(regs->cp0_cause, &sc->sc_cause);
-	err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
+	if (cpu_has_dsp) {
+		err |= __put_user(rddsp(DSP_MASK), &sc->sc_hi1);
+		err |= __put_user(mfhi1(), &sc->sc_hi1);
+		err |= __put_user(mflo1(), &sc->sc_lo1);
+		err |= __put_user(mfhi2(), &sc->sc_hi2);
+		err |= __put_user(mflo2(), &sc->sc_lo2);
+		err |= __put_user(mfhi3(), &sc->sc_hi3);
+		err |= __put_user(mflo3(), &sc->sc_lo3);
+	}
 
 	err |= __put_user(!!used_math(), &sc->sc_used_math);
 
@@ -601,7 +647,7 @@
 	return (void *)((sp - frame_size) & ALMASK);
 }
 
-static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
 			       int signr, sigset_t *set)
 {
 	struct sigframe *frame;
@@ -654,9 +700,7 @@
 	force_sigsegv(signr, current);
 }
 
-static inline void setup_rt_frame(struct k_sigaction * ka,
-				  struct pt_regs *regs, int signr,
-				  sigset_t *set, siginfo_t *info)
+void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr,	sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe32 *frame;
 	int err = 0;
@@ -725,9 +769,11 @@
 	force_sigsegv(signr, current);
 }
 
-static inline void handle_signal(unsigned long sig, siginfo_t *info,
+static inline int handle_signal(unsigned long sig, siginfo_t *info,
 	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
 {
+	int ret;
+
 	switch (regs->regs[0]) {
 	case ERESTART_RESTARTBLOCK:
 	case ERESTARTNOHAND:
@@ -747,9 +793,9 @@
 	regs->regs[0] = 0;		/* Don't deal with this again.  */
 
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(ka, regs, sig, oldset, info);
+		ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
 	else
-		setup_frame(ka, regs, sig, oldset);
+		ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -757,6 +803,8 @@
 		sigaddset(&current->blocked,sig);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	return ret;
 }
 
 int do_signal32(sigset_t *oldset, struct pt_regs *regs)
@@ -780,10 +828,8 @@
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		handle_signal(signr, &info, &ka, oldset, regs);
-		return 1;
-	}
+	if (signr > 0)
+		return handle_signal(signr, &info, &ka, oldset, regs);
 
 no_signal:
 	/*
@@ -819,12 +865,13 @@
 		goto out;
 
 	if (act) {
+		s32 handler;
 		int err = 0;
 
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 			return -EFAULT;
-		err |= __get_user((u32)(u64)new_sa.sa.sa_handler,
-		                  &act->sa_handler);
+		err |= __get_user(handler, &act->sa_handler);
+		new_sa.sa.sa_handler = (void*)(s64)handler;
 		err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
 		err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
 		if (err)
@@ -902,3 +949,30 @@
 	set_fs (old_fs);
 	return ret;
 }
+
+asmlinkage long
+sys32_waitid(int which, compat_pid_t pid,
+	     compat_siginfo_t __user *uinfo, int options,
+	     struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	info.si_signo = 0;
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
+			 uru ? (struct rusage __user *) &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru && (ret = put_compat_rusage(&ru, uru)))
+		return ret;
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 3544208..ec61b26 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -15,6 +15,8 @@
  * 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/cache.h>
+#include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -36,6 +38,7 @@
 #include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/cpu-features.h>
+#include <asm/war.h>
 
 #include "signal-common.h"
 
@@ -62,17 +65,18 @@
 	sigset_t            uc_sigmask;   /* mask last for extensibility */
 };
 
-#if PLAT_TRAMPOLINE_STUFF_LINE
-#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
-#else
-#define __tramp
-#endif
-
 struct rt_sigframe_n32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
-	u32 rs_code[2] __tramp;		/* signal trampoline */
-	struct siginfo rs_info __tramp;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 rs_pad[2];
+#else
+	u32 rs_code[2];			/* signal trampoline */
+#endif
+	struct siginfo rs_info;
 	struct ucontextn32 rs_uc;
+#if ICACHE_REFILLS_WORKAROUND_WAR
+	u32 rs_code[8] ____cacheline_aligned;		/* signal trampoline */
+#endif
 };
 
 save_static_function(sysn32_rt_sigreturn);
@@ -126,7 +130,7 @@
 	force_sig(SIGSEGV, current);
 }
 
-void setup_rt_frame_n32(struct k_sigaction * ka,
+int setup_rt_frame_n32(struct k_sigaction * ka,
 	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
 {
 	struct rt_sigframe_n32 *frame;
@@ -137,17 +141,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto give_sigsegv;
 
-	/*
-	 * Set up the return code ...
-	 *
-	 *         li      v0, __NR_rt_sigreturn
-	 *         syscall
-	 */
-	if (PLAT_TRAMPOLINE_STUFF_LINE)
-		__clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
-	err |= __put_user(0x24020000 + __NR_N32_rt_sigreturn, frame->rs_code + 0);
-	err |= __put_user(0x0000000c                        , frame->rs_code + 1);
-	flush_cache_sigtramp((unsigned long) frame->rs_code);
+	install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
 
 	/* Create siginfo.  */
 	err |= copy_siginfo_to_user(&frame->rs_info, info);
@@ -190,8 +184,9 @@
 	       current->comm, current->pid,
 	       frame, regs->cp0_epc, regs->regs[31]);
 #endif
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(signr, current);
+	return 0;
 }
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index af5cd3b..fcacf1a 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -50,7 +50,6 @@
 {
 	struct cache_desc *cd = &current_cpu_data.scache;
 	unsigned long cachesize;       /* kB   */
-	unsigned long bandwidth = 350; /* MB/s */
 	unsigned long cpu_khz;
 
 	/*
@@ -121,7 +120,19 @@
  * or are or have executed.
  *
  * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
+ * hardware interrupt handler or from a bottom half handler:
+ *
+ * CPU A                               CPU B
+ * Disable interrupts
+ *                                     smp_call_function()
+ *                                     Take call_lock
+ *                                     Send IPIs
+ *                                     Wait for all cpus to acknowledge IPI
+ *                                     CPU A has not responded, spin waiting
+ *                                     for cpu A to respond, holding call_lock
+ * smp_call_function()
+ * Spin waiting for call_lock
+ * Deadlock                            Deadlock
  */
 int smp_call_function (void (*func) (void *info), void *info, int retry,
 								int wait)
@@ -130,6 +141,11 @@
 	int i, cpus = num_online_cpus() - 1;
 	int cpu = smp_processor_id();
 
+	/*
+	 * Can die spectacularly if this CPU isn't yet marked online
+	 */
+	BUG_ON(!cpu_online(cpu));
+
 	if (!cpus)
 		return 0;
 
@@ -214,7 +230,6 @@
 /* called from main before smp_init() */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	cpu_data[0].udelay_val = loops_per_jiffy;
 	init_new_context(current, &init_mm);
 	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
@@ -236,44 +251,32 @@
 }
 
 /*
- * Startup the CPU with this logical number
- */
-static int __init do_boot_cpu(int cpu)
-{
-	struct task_struct *idle;
-
-	/*
-	 * The following code is purely to make sure
-	 * Linux can schedule processes on this slave.
-	 */
-	idle = fork_idle(cpu);
-	if (IS_ERR(idle))
-		panic("failed fork for CPU %d\n", cpu);
-
-	prom_boot_secondary(cpu, idle);
-
-	/* XXXKW timeout */
-	while (!cpu_isset(cpu, cpu_callin_map))
-		udelay(100);
-
-	cpu_set(cpu, cpu_online_map);
-
-	return 0;
-}
-
-/*
  * Called once for each "cpu_possible(cpu)".  Needs to spin up the cpu
  * and keep control until "cpu_online(cpu)" is set.  Note: cpu is
  * physical, not logical.
  */
 int __devinit __cpu_up(unsigned int cpu)
 {
-	int ret;
+	struct task_struct *idle;
 
-	/* Processor goes to start_secondary(), sets online flag */
-	ret = do_boot_cpu(cpu);
-	if (ret < 0)
-		return ret;
+	/*
+	 * Processor goes to start_secondary(), sets online flag
+	 * The following code is purely to make sure
+	 * Linux can schedule processes on this slave.
+	 */
+	idle = fork_idle(cpu);
+	if (IS_ERR(idle))
+		panic(KERN_ERR "Fork failed for CPU %d", cpu);
+
+	prom_boot_secondary(cpu, idle);
+
+	/*
+	 * Trust is futile.  We should really have timeouts ...
+	 */
+	while (!cpu_isset(cpu, cpu_callin_map))
+		udelay(100);
+
+	cpu_set(cpu, cpu_online_map);
 
 	return 0;
 }
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c
new file mode 100644
index 0000000..d429544
--- /dev/null
+++ b/arch/mips/kernel/smp_mt.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  Elizabeth Clarke (beth@mips.com)
+ *
+ *  This program is free software; you can distribute 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 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/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/time.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/cacheflush.h>
+#include <asm/mips-boards/maltaint.h>
+
+#define MIPS_CPU_IPI_RESCHED_IRQ 0
+#define MIPS_CPU_IPI_CALL_IRQ 1
+
+static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
+
+#if 0
+static void dump_mtregisters(int vpe, int tc)
+{
+	printk("vpe %d tc %d\n", vpe, tc);
+
+	settc(tc);
+
+	printk("  c0 status  0x%lx\n", read_vpe_c0_status());
+	printk("  vpecontrol 0x%lx\n", read_vpe_c0_vpecontrol());
+	printk("  vpeconf0    0x%lx\n", read_vpe_c0_vpeconf0());
+	printk("  tcstatus 0x%lx\n", read_tc_c0_tcstatus());
+	printk("  tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+	printk("  tcbind 0x%lx\n", read_tc_c0_tcbind());
+	printk("  tchalt 0x%lx\n", read_tc_c0_tchalt());
+}
+#endif
+
+void __init sanitize_tlb_entries(void)
+{
+	int i, tlbsiz;
+	unsigned long mvpconf0, ncpu;
+
+	if (!cpu_has_mipsmt)
+		return;
+
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	/* Disable TLB sharing */
+	clear_c0_mvpcontrol(MVPCONTROL_STLB);
+
+	mvpconf0 = read_c0_mvpconf0();
+
+	printk(KERN_INFO "MVPConf0 0x%lx TLBS %lx PTLBE %ld\n", mvpconf0,
+		   (mvpconf0 & MVPCONF0_TLBS) >> MVPCONF0_TLBS_SHIFT,
+			   (mvpconf0 & MVPCONF0_PTLBE) >> MVPCONF0_PTLBE_SHIFT);
+
+	tlbsiz = (mvpconf0 & MVPCONF0_PTLBE) >> MVPCONF0_PTLBE_SHIFT;
+	ncpu = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+
+	printk(" tlbsiz %d ncpu %ld\n", tlbsiz, ncpu);
+
+	if (tlbsiz > 0) {
+		/* share them out across the vpe's */
+		tlbsiz /= ncpu;
+
+		printk(KERN_INFO "setting Config1.MMU_size to %d\n", tlbsiz);
+
+		for (i = 0; i < ncpu; i++) {
+			settc(i);
+
+			if (i == 0)
+				write_c0_config1((read_c0_config1() & ~(0x3f << 25)) | (tlbsiz << 25));
+			else
+				write_vpe_c0_config1((read_vpe_c0_config1() & ~(0x3f << 25)) |
+						   (tlbsiz << 25));
+		}
+	}
+
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+}
+
+#if 0
+/*
+ * Use c0_MVPConf0 to find out how many CPUs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ */
+void __init prom_build_cpu_map(void)
+{
+	int i, num, ncpus;
+
+	cpus_clear(phys_cpu_present_map);
+
+	/* assume we boot on cpu 0.... */
+	cpu_set(0, phys_cpu_present_map);
+	__cpu_number_map[0] = 0;
+	__cpu_logical_map[0] = 0;
+
+	if (cpu_has_mipsmt) {
+		ncpus = ((read_c0_mvpconf0() & (MVPCONF0_PVPE)) >> MVPCONF0_PVPE_SHIFT) + 1;
+		for (i=1, num=0; i< NR_CPUS && i<ncpus; i++) {
+			cpu_set(i, phys_cpu_present_map);
+			__cpu_number_map[i] = ++num;
+			__cpu_logical_map[num] = i;
+		}
+
+		printk(KERN_INFO "%i available secondary CPU(s)\n", num);
+	}
+}
+#endif
+
+static void ipi_resched_dispatch (struct pt_regs *regs)
+{
+	do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs);
+}
+
+static void ipi_call_dispatch (struct pt_regs *regs)
+{
+	do_IRQ(MIPS_CPU_IPI_CALL_IRQ, regs);
+}
+
+irqreturn_t ipi_resched_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	return IRQ_HANDLED;
+}
+
+irqreturn_t ipi_call_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	smp_call_function_interrupt();
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+	.handler	= ipi_resched_interrupt,
+	.flags		= SA_INTERRUPT,
+	.name		= "IPI_resched"
+};
+
+static struct irqaction irq_call = {
+	.handler	= ipi_call_interrupt,
+	.flags		= SA_INTERRUPT,
+	.name		= "IPI_call"
+};
+
+/*
+ * Common setup before any secondaries are started
+ * Make sure all CPU's are in a sensible state before we boot any of the
+ * secondarys
+ */
+void prom_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned long val;
+	int i, num;
+
+	if (!cpu_has_mipsmt)
+		return;
+
+	/* disable MT so we can configure */
+	dvpe();
+	dmt();
+
+	/* Put MVPE's into 'configuration state' */
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	val = read_c0_mvpconf0();
+
+	/* we'll always have more TC's than VPE's, so loop setting everything
+	   to a sensible state */
+	for (i = 0, num = 0; i <= ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT); i++) {
+		settc(i);
+
+		/* VPE's */
+		if (i <= ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) {
+
+			/* deactivate all but vpe0 */
+			if (i != 0) {
+				unsigned long tmp = read_vpe_c0_vpeconf0();
+
+				tmp &= ~VPECONF0_VPA;
+
+				/* master VPE */
+				tmp |= VPECONF0_MVP;
+				write_vpe_c0_vpeconf0(tmp);
+
+				/* Record this as available CPU */
+				if (i < max_cpus) {
+					cpu_set(i, phys_cpu_present_map);
+					__cpu_number_map[i]	= ++num;
+					__cpu_logical_map[num]	= i;
+				}
+			}
+
+			/* disable multi-threading with TC's */
+			write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
+
+			if (i != 0) {
+				write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
+				write_vpe_c0_cause(read_vpe_c0_cause() & ~CAUSEF_IP);
+
+				/* set config to be the same as vpe0, particularly kseg0 coherency alg */
+				write_vpe_c0_config( read_c0_config());
+			}
+
+		}
+
+		/* TC's */
+
+		if (i != 0) {
+			unsigned long tmp;
+
+			/* bind a TC to each VPE, May as well put all excess TC's
+			   on the last VPE */
+			if ( i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1) )
+				write_tc_c0_tcbind(read_tc_c0_tcbind() | ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) );
+			else {
+				write_tc_c0_tcbind( read_tc_c0_tcbind() | i);
+
+				/* and set XTC */
+				write_vpe_c0_vpeconf0( read_vpe_c0_vpeconf0() | (i << VPECONF0_XTC_SHIFT));
+			}
+
+			tmp = read_tc_c0_tcstatus();
+
+			/* mark not allocated and not dynamically allocatable */
+			tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+			tmp |= TCSTATUS_IXMT;		/* interrupt exempt */
+			write_tc_c0_tcstatus(tmp);
+
+			write_tc_c0_tchalt(TCHALT_H);
+		}
+	}
+
+	/* Release config state */
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	/* We'll wait until starting the secondaries before starting MVPE */
+
+	printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+
+	/* set up ipi interrupts */
+	if (cpu_has_vint) {
+		set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
+		set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
+	}
+
+	cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
+	cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
+
+	setup_irq(cpu_ipi_resched_irq, &irq_resched);
+	setup_irq(cpu_ipi_call_irq, &irq_call);
+
+	/* need to mark IPI's as IRQ_PER_CPU */
+	irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU;
+	irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU;
+}
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ * smp_bootstrap is the place to resume from
+ * __KSTK_TOS(idle) is apparently the stack pointer
+ * (unsigned long)idle->thread_info the gp
+ * assumes a 1:1 mapping of TC => VPE
+ */
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+	dvpe();
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	settc(cpu);
+
+	/* restart */
+	write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
+
+	/* enable the tc this vpe/cpu will be running */
+	write_tc_c0_tcstatus((read_tc_c0_tcstatus() & ~TCSTATUS_IXMT) | TCSTATUS_A);
+
+	write_tc_c0_tchalt(0);
+
+	/* enable the VPE */
+	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+
+	/* stack pointer */
+	write_tc_gpr_sp( __KSTK_TOS(idle));
+
+	/* global pointer */
+	write_tc_gpr_gp((unsigned long)idle->thread_info);
+
+	flush_icache_range((unsigned long)idle->thread_info,
+					   (unsigned long)idle->thread_info +
+					   sizeof(struct thread_info));
+
+	/* finally out of configuration and into chaos */
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	evpe(EVPE_ENABLE);
+}
+
+void prom_init_secondary(void)
+{
+	write_c0_status((read_c0_status() & ~ST0_IM ) |
+	                (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7));
+}
+
+void prom_smp_finish(void)
+{
+	write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
+
+	local_irq_enable();
+}
+
+void prom_cpus_done(void)
+{
+}
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+	int i;
+	unsigned long flags;
+	int vpflags;
+
+	local_irq_save (flags);
+
+	vpflags = dvpe();	/* cant access the other CPU's registers whilst MVPE enabled */
+
+	switch (action) {
+	case SMP_CALL_FUNCTION:
+		i = C_SW1;
+		break;
+
+	case SMP_RESCHEDULE_YOURSELF:
+	default:
+		i = C_SW0;
+		break;
+	}
+
+	/* 1:1 mapping of vpe and tc... */
+	settc(cpu);
+	write_vpe_c0_cause(read_vpe_c0_cause() | i);
+	evpe(vpflags);
+
+	local_irq_restore(flags);
+}
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 21e3e13..ee98eeb 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -7,6 +7,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
+#include <linux/config.h>
 #include <linux/a.out.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
@@ -26,6 +27,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/compiler.h>
+#include <linux/module.h>
 
 #include <asm/branch.h>
 #include <asm/cachectl.h>
@@ -56,6 +58,8 @@
 
 unsigned long shm_align_mask = PAGE_SIZE - 1;	/* Sane caches */
 
+EXPORT_SYMBOL(shm_align_mask);
+
 #define COLOUR_ALIGN(addr,pgoff)				\
 	((((addr) + shm_align_mask) & ~shm_align_mask) +	\
 	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
@@ -173,14 +177,28 @@
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
-	int *parent_tidptr, *child_tidptr;
+	int __user *parent_tidptr, *child_tidptr;
 
 	clone_flags = regs.regs[4];
 	newsp = regs.regs[5];
 	if (!newsp)
 		newsp = regs.regs[29];
-	parent_tidptr = (int *) regs.regs[6];
-	child_tidptr = (int *) regs.regs[7];
+	parent_tidptr = (int __user *) regs.regs[6];
+#ifdef CONFIG_32BIT
+	/* We need to fetch the fifth argument off the stack.  */
+	child_tidptr = NULL;
+	if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
+		int __user *__user *usp = (int __user *__user *) regs.regs[29];
+		if (regs.regs[2] == __NR_syscall) {
+			if (get_user (child_tidptr, &usp[5]))
+				return -EFAULT;
+		}
+		else if (get_user (child_tidptr, &usp[4]))
+			return -EFAULT;
+	}
+#else
+	child_tidptr = (int __user *) regs.regs[8];
+#endif
 	return do_fork(clone_flags, newsp, &regs, 0,
 	               parent_tidptr, child_tidptr);
 }
@@ -242,6 +260,16 @@
 	return error;
 }
 
+void sys_set_thread_area(unsigned long addr)
+{
+	struct thread_info *ti = current->thread_info;
+
+	ti->tp_value = addr;
+
+	/* If some future MIPS implementation has this register in hardware,
+	 * we will need to update it here (and in context switches).  */
+}
+
 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
 {
 	int	tmp, len;
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 7ae4af4..52924f8 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -73,32 +73,30 @@
 }
 
 /* The prctl commands. */
-#define PR_MAXPROCS          1 /* Tasks/user. */
-#define PR_ISBLOCKED         2 /* If blocked, return 1. */
-#define PR_SETSTACKSIZE      3 /* Set largest task stack size. */
-#define PR_GETSTACKSIZE      4 /* Get largest task stack size. */
-#define PR_MAXPPROCS         5 /* Num parallel tasks. */
-#define PR_UNBLKONEXEC       6 /* When task exec/exit's, unblock. */
-#define PR_SETEXITSIG        8 /* When task exit's, set signal. */
-#define PR_RESIDENT          9 /* Make task unswappable. */
-#define PR_ATTACHADDR       10 /* (Re-)Connect a vma to a task. */
-#define PR_DETACHADDR       11 /* Disconnect a vma from a task. */
-#define PR_TERMCHILD        12 /* When parent sleeps with fishes, kill child. */
-#define PR_GETSHMASK        13 /* Get the sproc() share mask. */
-#define PR_GETNSHARE        14 /* Number of share group members. */
-#define PR_COREPID          15 /* Add task pid to name when it core. */
-#define	PR_ATTACHADDRPERM   16 /* (Re-)Connect vma, with specified prot. */
-#define PR_PTHREADEXIT      17 /* Kill a pthread without prejudice. */
+#define PR_MAXPROCS		 1 /* Tasks/user. */
+#define PR_ISBLOCKED		 2 /* If blocked, return 1. */
+#define PR_SETSTACKSIZE		 3 /* Set largest task stack size. */
+#define PR_GETSTACKSIZE		 4 /* Get largest task stack size. */
+#define PR_MAXPPROCS		 5 /* Num parallel tasks. */
+#define PR_UNBLKONEXEC		 6 /* When task exec/exit's, unblock. */
+#define PR_SETEXITSIG		 8 /* When task exit's, set signal. */
+#define PR_RESIDENT		 9 /* Make task unswappable. */
+#define PR_ATTACHADDR		10 /* (Re-)Connect a vma to a task. */
+#define PR_DETACHADDR		11 /* Disconnect a vma from a task. */
+#define PR_TERMCHILD		12 /* Kill child if the parent dies. */
+#define PR_GETSHMASK		13 /* Get the sproc() share mask. */
+#define PR_GETNSHARE		14 /* Number of share group members. */
+#define PR_COREPID		15 /* Add task pid to name when it core. */
+#define PR_ATTACHADDRPERM	16 /* (Re-)Connect vma, with specified prot. */
+#define PR_PTHREADEXIT		17 /* Kill a pthread, only for IRIX 6.[234] */
 
-asmlinkage int irix_prctl(struct pt_regs *regs)
+asmlinkage int irix_prctl(unsigned option, ...)
 {
-	unsigned long cmd;
-	int error = 0, base = 0;
+	va_list args;
+	int error = 0;
 
-	if (regs->regs[2] == 1000)
-		base = 1;
-	cmd = regs->regs[base + 4];
-	switch (cmd) {
+	va_start(args, option);
+	switch (option) {
 	case PR_MAXPROCS:
 		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
 		       current->comm, current->pid);
@@ -111,7 +109,7 @@
 		printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
 		       current->comm, current->pid);
 		read_lock(&tasklist_lock);
-		task = find_task_by_pid(regs->regs[base + 5]);
+		task = find_task_by_pid(va_arg(args, pid_t));
 		error = -ESRCH;
 		if (error)
 			error = (task->run_list.next != NULL);
@@ -121,7 +119,7 @@
 	}
 
 	case PR_SETSTACKSIZE: {
-		long value = regs->regs[base + 5];
+		long value = va_arg(args, long);
 
 		printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",
 		       current->comm, current->pid, (unsigned long) value);
@@ -222,24 +220,20 @@
 		error = -EINVAL;
 		break;
 
-	case PR_PTHREADEXIT:
-		printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
-		       current->comm, current->pid);
-		do_exit(regs->regs[base + 5]);
-
 	default:
 		printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",
-		       current->comm, current->pid, (int)cmd);
+		       current->comm, current->pid, option);
 		error = -EINVAL;
 		break;
 	}
+	va_end(args);
 
 	return error;
 }
 
 #undef DEBUG_PROCGRPS
 
-extern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt);
+extern unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt);
 extern int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
 extern char *prom_getenv(char *name);
 extern long prom_setenv(char *name, char *value);
@@ -276,23 +270,19 @@
 	cmd = regs->regs[base + 4];
 	switch(cmd) {
 	case SGI_SYSID: {
-		char *buf = (char *) regs->regs[base + 5];
+		char __user *buf = (char __user *) regs->regs[base + 5];
 
 		/* XXX Use ethernet addr.... */
-		retval = clear_user(buf, 64);
+		retval = clear_user(buf, 64) ? -EFAULT : 0;
 		break;
 	}
 #if 0
 	case SGI_RDNAME: {
 		int pid = (int) regs->regs[base + 5];
-		char *buf = (char *) regs->regs[base + 6];
+		char __user *buf = (char __user *) regs->regs[base + 6];
 		struct task_struct *p;
 		char tcomm[sizeof(current->comm)];
 
-		if (!access_ok(VERIFY_WRITE, buf, sizeof(tcomm))) {
-			retval = -EFAULT;
-			break;
-		}
 		read_lock(&tasklist_lock);
 		p = find_task_by_pid(pid);
 		if (!p) {
@@ -304,34 +294,28 @@
 		read_unlock(&tasklist_lock);
 
 		/* XXX Need to check sizes. */
-		copy_to_user(buf, tcomm, sizeof(tcomm));
-		retval = 0;
+		retval = copy_to_user(buf, tcomm, sizeof(tcomm)) ? -EFAULT : 0;
 		break;
 	}
 
 	case SGI_GETNVRAM: {
-		char *name = (char *) regs->regs[base+5];
-		char *buf = (char *) regs->regs[base+6];
+		char __user *name = (char __user *) regs->regs[base+5];
+		char __user *buf = (char __user *) regs->regs[base+6];
 		char *value;
 		return -EINVAL;	/* til I fix it */
-		if (!access_ok(VERIFY_WRITE, buf, 128)) {
-			retval = -EFAULT;
-			break;
-		}
 		value = prom_getenv(name);	/* PROM lock?  */
 		if (!value) {
 			retval = -EINVAL;
 			break;
 		}
 		/* Do I strlen() for the length? */
-		copy_to_user(buf, value, 128);
-		retval = 0;
+		retval = copy_to_user(buf, value, 128) ? -EFAULT : 0;
 		break;
 	}
 
 	case SGI_SETNVRAM: {
-		char *name = (char *) regs->regs[base+5];
-		char *value = (char *) regs->regs[base+6];
+		char __user *name = (char __user *) regs->regs[base+5];
+		char __user *value = (char __user *) regs->regs[base+6];
 		return -EINVAL;	/* til I fix it */
 		retval = prom_setenv(name, value);
 		/* XXX make sure retval conforms to syssgi(2) */
@@ -407,16 +391,16 @@
 
 	case SGI_SETGROUPS:
 		retval = sys_setgroups((int) regs->regs[base + 5],
-		                       (gid_t *) regs->regs[base + 6]);
+		                       (gid_t __user *) regs->regs[base + 6]);
 		break;
 
 	case SGI_GETGROUPS:
 		retval = sys_getgroups((int) regs->regs[base + 5],
-		                       (gid_t *) regs->regs[base + 6]);
+		                       (gid_t __user *) regs->regs[base + 6]);
 		break;
 
 	case SGI_RUSAGE: {
-		struct rusage *ru = (struct rusage *) regs->regs[base + 6];
+		struct rusage __user *ru = (struct rusage __user *) regs->regs[base + 6];
 
 		switch((int) regs->regs[base + 5]) {
 		case 0:
@@ -453,7 +437,7 @@
 
 	case SGI_ELFMAP:
 		retval = irix_mapelf((int) regs->regs[base + 5],
-				     (struct elf_phdr *) regs->regs[base + 6],
+				     (struct elf_phdr __user *) regs->regs[base + 6],
 				     (int) regs->regs[base + 7]);
 		break;
 
@@ -468,24 +452,24 @@
 
 	case SGI_PHYSP: {
 		unsigned long addr = regs->regs[base + 5];
-		int *pageno = (int *) (regs->regs[base + 6]);
+		int __user *pageno = (int __user *) (regs->regs[base + 6]);
 		struct mm_struct *mm = current->mm;
 		pgd_t *pgdp;
+		pud_t *pudp;
 		pmd_t *pmdp;
 		pte_t *ptep;
 
-		if (!access_ok(VERIFY_WRITE, pageno, sizeof(int)))
-			return -EFAULT;
-
 		down_read(&mm->mmap_sem);
 		pgdp = pgd_offset(mm, addr);
-		pmdp = pmd_offset(pgdp, addr);
+		pudp = pud_offset(pgdp, addr);
+		pmdp = pmd_offset(pudp, addr);
 		ptep = pte_offset(pmdp, addr);
 		retval = -EINVAL;
 		if (ptep) {
 			pte_t pte = *ptep;
 
 			if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) {
+				/* b0rked on 64-bit */
 				retval =  put_user((pte_val(pte) & PAGE_MASK) >>
 				                   PAGE_SHIFT, pageno);
 			}
@@ -496,7 +480,7 @@
 
 	case SGI_INVENT: {
 		int  arg1    = (int)    regs->regs [base + 5];
-		void *buffer = (void *) regs->regs [base + 6];
+		void __user *buffer = (void __user *) regs->regs [base + 6];
 		int  count   = (int)    regs->regs [base + 7];
 
 		switch (arg1) {
@@ -692,8 +676,8 @@
 }
 
 /* XXX need more than this... */
-asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
-			  char *type, void *data, int datalen)
+asmlinkage int irix_mount(char __user *dev_name, char __user *dir_name,
+	unsigned long flags, char __user *type, void __user *data, int datalen)
 {
 	printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
 	       current->comm, current->pid,
@@ -708,8 +692,8 @@
 	char  f_fname[6], f_fpack[6];
 };
 
-asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
-			   int len, int fs_type)
+asmlinkage int irix_statfs(const char __user *path,
+	struct irix_statfs __user *buf, int len, int fs_type)
 {
 	struct nameidata nd;
 	struct kstatfs kbuf;
@@ -724,6 +708,7 @@
 		error = -EFAULT;
 		goto out;
 	}
+
 	error = user_path_walk(path, &nd);
 	if (error)
 		goto out;
@@ -732,18 +717,17 @@
 	if (error)
 		goto dput_and_out;
 
-	__put_user(kbuf.f_type, &buf->f_type);
-	__put_user(kbuf.f_bsize, &buf->f_bsize);
-	__put_user(kbuf.f_frsize, &buf->f_frsize);
-	__put_user(kbuf.f_blocks, &buf->f_blocks);
-	__put_user(kbuf.f_bfree, &buf->f_bfree);
-	__put_user(kbuf.f_files, &buf->f_files);
-	__put_user(kbuf.f_ffree, &buf->f_ffree);
+	error = __put_user(kbuf.f_type, &buf->f_type);
+	error |= __put_user(kbuf.f_bsize, &buf->f_bsize);
+	error |= __put_user(kbuf.f_frsize, &buf->f_frsize);
+	error |= __put_user(kbuf.f_blocks, &buf->f_blocks);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bfree);
+	error |= __put_user(kbuf.f_files, &buf->f_files);
+	error |= __put_user(kbuf.f_ffree, &buf->f_ffree);
 	for (i = 0; i < 6; i++) {
-		__put_user(0, &buf->f_fname[i]);
-		__put_user(0, &buf->f_fpack[i]);
+		error |= __put_user(0, &buf->f_fname[i]);
+		error |= __put_user(0, &buf->f_fpack[i]);
 	}
-	error = 0;
 
 dput_and_out:
 	path_release(&nd);
@@ -751,7 +735,7 @@
 	return error;
 }
 
-asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
+asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf)
 {
 	struct kstatfs kbuf;
 	struct file *file;
@@ -761,6 +745,7 @@
 		error = -EFAULT;
 		goto out;
 	}
+
 	if (!(file = fget(fd))) {
 		error = -EBADF;
 		goto out;
@@ -770,16 +755,17 @@
 	if (error)
 		goto out_f;
 
-	__put_user(kbuf.f_type, &buf->f_type);
-	__put_user(kbuf.f_bsize, &buf->f_bsize);
-	__put_user(kbuf.f_frsize, &buf->f_frsize);
-	__put_user(kbuf.f_blocks, &buf->f_blocks);
-	__put_user(kbuf.f_bfree, &buf->f_bfree);
-	__put_user(kbuf.f_files, &buf->f_files);
-	__put_user(kbuf.f_ffree, &buf->f_ffree);
-	for(i = 0; i < 6; i++) {
-		__put_user(0, &buf->f_fname[i]);
-		__put_user(0, &buf->f_fpack[i]);
+	error = __put_user(kbuf.f_type, &buf->f_type);
+	error |= __put_user(kbuf.f_bsize, &buf->f_bsize);
+	error |= __put_user(kbuf.f_frsize, &buf->f_frsize);
+	error |= __put_user(kbuf.f_blocks, &buf->f_blocks);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bfree);
+	error |= __put_user(kbuf.f_files, &buf->f_files);
+	error |= __put_user(kbuf.f_ffree, &buf->f_ffree);
+
+	for (i = 0; i < 6; i++) {
+		error |= __put_user(0, &buf->f_fname[i]);
+		error |= __put_user(0, &buf->f_fpack[i]);
 	}
 
 out_f:
@@ -806,14 +792,15 @@
 	return error;
 }
 
-asmlinkage int irix_times(struct tms * tbuf)
+asmlinkage int irix_times(struct tms __user *tbuf)
 {
 	int err = 0;
 
 	if (tbuf) {
 		if (!access_ok(VERIFY_WRITE,tbuf,sizeof *tbuf))
 			return -EFAULT;
-		err |= __put_user(current->utime, &tbuf->tms_utime);
+
+		err = __put_user(current->utime, &tbuf->tms_utime);
 		err |= __put_user(current->stime, &tbuf->tms_stime);
 		err |= __put_user(current->signal->cutime, &tbuf->tms_cutime);
 		err |= __put_user(current->signal->cstime, &tbuf->tms_cstime);
@@ -829,13 +816,13 @@
 
 	if(regs->regs[2] == 1000)
 		base = 1;
-	filename = getname((char *) (long)regs->regs[base + 4]);
+	filename = getname((char __user *) (long)regs->regs[base + 4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		return error;
 
-	error = do_execve(filename, (char **) (long)regs->regs[base + 5],
-	                  (char **) 0, regs);
+	error = do_execve(filename, (char __user * __user *) (long)regs->regs[base + 5],
+	                  NULL, regs);
 	putname(filename);
 
 	return error;
@@ -848,12 +835,12 @@
 
 	if (regs->regs[2] == 1000)
 		base = 1;
-	filename = getname((char *) (long)regs->regs[base + 4]);
+	filename = getname((char __user *) (long)regs->regs[base + 4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		return error;
-	error = do_execve(filename, (char **) (long)regs->regs[base + 5],
-	                  (char **) (long)regs->regs[base + 6], regs);
+	error = do_execve(filename, (char __user * __user *) (long)regs->regs[base + 5],
+	                  (char __user * __user *) (long)regs->regs[base + 6], regs);
 	putname(filename);
 
 	return error;
@@ -909,22 +896,17 @@
 	return sys_socket(family, type, protocol);
 }
 
-asmlinkage int irix_getdomainname(char *name, int len)
+asmlinkage int irix_getdomainname(char __user *name, int len)
 {
-	int error;
-
-	if (!access_ok(VERIFY_WRITE, name, len))
-		return -EFAULT;
+	int err;
 
 	down_read(&uts_sem);
 	if (len > __NEW_UTS_LEN)
 		len = __NEW_UTS_LEN;
-	error = 0;
-	if (copy_to_user(name, system_utsname.domainname, len))
-		error = -EFAULT;
+	err = copy_to_user(name, system_utsname.domainname, len) ? -EFAULT : 0;
 	up_read(&uts_sem);
 
-	return error;
+	return err;
 }
 
 asmlinkage unsigned long irix_getpagesize(void)
@@ -940,12 +922,13 @@
 	case 0:
 		return sys_msgget((key_t) arg0, (int) arg1);
 	case 1:
-		return sys_msgctl((int) arg0, (int) arg1, (struct msqid_ds *)arg2);
+		return sys_msgctl((int) arg0, (int) arg1,
+		                  (struct msqid_ds __user *)arg2);
 	case 2:
-		return sys_msgrcv((int) arg0, (struct msgbuf *) arg1,
+		return sys_msgrcv((int) arg0, (struct msgbuf __user *) arg1,
 				  (size_t) arg2, (long) arg3, (int) arg4);
 	case 3:
-		return sys_msgsnd((int) arg0, (struct msgbuf *) arg1,
+		return sys_msgsnd((int) arg0, (struct msgbuf __user *) arg1,
 				  (size_t) arg2, (int) arg3);
 	default:
 		return -EINVAL;
@@ -957,12 +940,13 @@
 {
 	switch (opcode) {
 	case 0:
-		return do_shmat((int) arg0, (char *)arg1, (int) arg2,
+		return do_shmat((int) arg0, (char __user *) arg1, (int) arg2,
 				 (unsigned long *) arg3);
 	case 1:
-		return sys_shmctl((int)arg0, (int)arg1, (struct shmid_ds *)arg2);
+		return sys_shmctl((int)arg0, (int)arg1,
+		                  (struct shmid_ds __user *)arg2);
 	case 2:
-		return sys_shmdt((char *)arg0);
+		return sys_shmdt((char __user *)arg0);
 	case 3:
 		return sys_shmget((key_t) arg0, (int) arg1, (int) arg2);
 	default:
@@ -980,7 +964,7 @@
 	case 1:
 		return sys_semget((key_t) arg0, (int) arg1, (int) arg2);
 	case 2:
-		return sys_semop((int) arg0, (struct sembuf *)arg1,
+		return sys_semop((int) arg0, (struct sembuf __user *)arg1,
 				 (unsigned int) arg2);
 	default:
 		return -EINVAL;
@@ -998,15 +982,16 @@
 	lock_kernel();
 	retval = fn(file, offset, origin);
 	unlock_kernel();
+
 	return retval;
 }
 
 asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow,
                             int origin)
 {
-	int retval;
 	struct file * file;
 	loff_t offset;
+	int retval;
 
 	retval = -EBADF;
 	file = fget(fd);
@@ -1031,12 +1016,12 @@
 	return 0;
 }
 
-asmlinkage int irix_sgikopt(char *istring, char *ostring, int len)
+asmlinkage int irix_sgikopt(char __user *istring, char __user *ostring, int len)
 {
 	return -EINVAL;
 }
 
-asmlinkage int irix_gettimeofday(struct timeval *tv)
+asmlinkage int irix_gettimeofday(struct timeval __user *tv)
 {
 	time_t sec;
 	long nsec, seq;
@@ -1077,7 +1062,7 @@
 
 			if (max_size > file->f_dentry->d_inode->i_size) {
 				old_pos = sys_lseek (fd, max_size - 1, 0);
-				sys_write (fd, "", 1);
+				sys_write (fd, (void __user *) "", 1);
 				sys_lseek (fd, old_pos, 0);
 			}
 		}
@@ -1102,7 +1087,7 @@
 	return -EINVAL;
 }
 
-asmlinkage int irix_pagelock(char *addr, int len, int op)
+asmlinkage int irix_pagelock(char __user *addr, int len, int op)
 {
 	printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
 	       current->comm, current->pid, addr, len, op);
@@ -1142,7 +1127,7 @@
 	return error;
 }
 
-asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
+asmlinkage int irix_systeminfo(int cmd, char __user *buf, int cnt)
 {
 	printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
 	       current->comm, current->pid, cmd, buf, cnt);
@@ -1158,14 +1143,14 @@
 	char _unused3[257], _unused4[257], _unused5[257];
 };
 
-asmlinkage int irix_uname(struct iuname *buf)
+asmlinkage int irix_uname(struct iuname __user *buf)
 {
 	down_read(&uts_sem);
-	if (copy_to_user(system_utsname.sysname, buf->sysname, 65)
-	    || copy_to_user(system_utsname.nodename, buf->nodename, 65)
-	    || copy_to_user(system_utsname.release, buf->release, 65)
-	    || copy_to_user(system_utsname.version, buf->version, 65)
-	    || copy_to_user(system_utsname.machine, buf->machine, 65)) {
+	if (copy_from_user(system_utsname.sysname, buf->sysname, 65)
+	    || copy_from_user(system_utsname.nodename, buf->nodename, 65)
+	    || copy_from_user(system_utsname.release, buf->release, 65)
+	    || copy_from_user(system_utsname.version, buf->version, 65)
+	    || copy_from_user(system_utsname.machine, buf->machine, 65)) {
 		return -EFAULT;
 	}
 	up_read(&uts_sem);
@@ -1175,7 +1160,7 @@
 
 #undef DEBUG_XSTAT
 
-static int irix_xstat32_xlate(struct kstat *stat, void *ubuf)
+static int irix_xstat32_xlate(struct kstat *stat, void __user *ubuf)
 {
 	struct xstat32 {
 		u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid;
@@ -1215,7 +1200,7 @@
 	return copy_to_user(ubuf, &ub, sizeof(ub)) ? -EFAULT : 0;
 }
 
-static int irix_xstat64_xlate(struct kstat *stat, void *ubuf)
+static int irix_xstat64_xlate(struct kstat *stat, void __user *ubuf)
 {
 	struct xstat64 {
 		u32 st_dev; s32 st_pad1[3];
@@ -1265,7 +1250,7 @@
 	return copy_to_user(ubuf, &ks, sizeof(ks)) ? -EFAULT : 0;
 }
 
-asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
+asmlinkage int irix_xstat(int version, char __user *filename, struct stat __user *statbuf)
 {
 	int retval;
 	struct kstat stat;
@@ -1291,7 +1276,7 @@
 	return retval;
 }
 
-asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
+asmlinkage int irix_lxstat(int version, char __user *filename, struct stat __user *statbuf)
 {
 	int error;
 	struct kstat stat;
@@ -1318,7 +1303,7 @@
 	return error;
 }
 
-asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
+asmlinkage int irix_fxstat(int version, int fd, struct stat __user *statbuf)
 {
 	int error;
 	struct kstat stat;
@@ -1344,7 +1329,7 @@
 	return error;
 }
 
-asmlinkage int irix_xmknod(int ver, char *filename, int mode, unsigned dev)
+asmlinkage int irix_xmknod(int ver, char __user *filename, int mode, unsigned dev)
 {
 	int retval;
 	printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
@@ -1364,7 +1349,7 @@
 	return retval;
 }
 
-asmlinkage int irix_swapctl(int cmd, char *arg)
+asmlinkage int irix_swapctl(int cmd, char __user *arg)
 {
 	printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
 	       current->comm, current->pid, cmd, arg);
@@ -1380,7 +1365,7 @@
 	char	f_fstr[32]; u32 f_filler[16];
 };
 
-asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
+asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf)
 {
 	struct nameidata nd;
 	struct kstatfs kbuf;
@@ -1388,10 +1373,9 @@
 
 	printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
 	       current->comm, current->pid, fname, buf);
-	if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
-		error = -EFAULT;
-		goto out;
-	}
+	if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)))
+		return -EFAULT;
+
 	error = user_path_walk(fname, &nd);
 	if (error)
 		goto out;
@@ -1399,27 +1383,25 @@
 	if (error)
 		goto dput_and_out;
 
-	__put_user(kbuf.f_bsize, &buf->f_bsize);
-	__put_user(kbuf.f_frsize, &buf->f_frsize);
-	__put_user(kbuf.f_blocks, &buf->f_blocks);
-	__put_user(kbuf.f_bfree, &buf->f_bfree);
-	__put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
-	__put_user(kbuf.f_files, &buf->f_files);
-	__put_user(kbuf.f_ffree, &buf->f_ffree);
-	__put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
+	error |= __put_user(kbuf.f_bsize, &buf->f_bsize);
+	error |= __put_user(kbuf.f_frsize, &buf->f_frsize);
+	error |= __put_user(kbuf.f_blocks, &buf->f_blocks);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bfree);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
+	error |= __put_user(kbuf.f_files, &buf->f_files);
+	error |= __put_user(kbuf.f_ffree, &buf->f_ffree);
+	error |= __put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
 #ifdef __MIPSEB__
-	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
 #else
-	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
 #endif
 	for (i = 0; i < 16; i++)
-		__put_user(0, &buf->f_basetype[i]);
-	__put_user(0, &buf->f_flag);
-	__put_user(kbuf.f_namelen, &buf->f_namemax);
+		error |= __put_user(0, &buf->f_basetype[i]);
+	error |= __put_user(0, &buf->f_flag);
+	error |= __put_user(kbuf.f_namelen, &buf->f_namemax);
 	for (i = 0; i < 32; i++)
-		__put_user(0, &buf->f_fstr[i]);
-
-	error = 0;
+		error |= __put_user(0, &buf->f_fstr[i]);
 
 dput_and_out:
 	path_release(&nd);
@@ -1427,7 +1409,7 @@
 	return error;
 }
 
-asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
+asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf)
 {
 	struct kstatfs kbuf;
 	struct file *file;
@@ -1436,10 +1418,9 @@
 	printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
 	       current->comm, current->pid, fd, buf);
 
-	if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
-		error = -EFAULT;
-		goto out;
-	}
+	if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)))
+		return -EFAULT;
+
 	if (!(file = fget(fd))) {
 		error = -EBADF;
 		goto out;
@@ -1448,24 +1429,24 @@
 	if (error)
 		goto out_f;
 
-	__put_user(kbuf.f_bsize, &buf->f_bsize);
-	__put_user(kbuf.f_frsize, &buf->f_frsize);
-	__put_user(kbuf.f_blocks, &buf->f_blocks);
-	__put_user(kbuf.f_bfree, &buf->f_bfree);
-	__put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
-	__put_user(kbuf.f_files, &buf->f_files);
-	__put_user(kbuf.f_ffree, &buf->f_ffree);
-	__put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
+	error = __put_user(kbuf.f_bsize, &buf->f_bsize);
+	error |= __put_user(kbuf.f_frsize, &buf->f_frsize);
+	error |= __put_user(kbuf.f_blocks, &buf->f_blocks);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bfree);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
+	error |= __put_user(kbuf.f_files, &buf->f_files);
+	error |= __put_user(kbuf.f_ffree, &buf->f_ffree);
+	error |= __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
 #ifdef __MIPSEB__
-	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
 #else
-	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
 #endif
 	for(i = 0; i < 16; i++)
-		__put_user(0, &buf->f_basetype[i]);
-	__put_user(0, &buf->f_flag);
-	__put_user(kbuf.f_namelen, &buf->f_namemax);
-	__clear_user(&buf->f_fstr, sizeof(buf->f_fstr));
+		error |= __put_user(0, &buf->f_basetype[i]);
+	error |= __put_user(0, &buf->f_flag);
+	error |= __put_user(kbuf.f_namelen, &buf->f_namemax);
+	error |= __clear_user(&buf->f_fstr, sizeof(buf->f_fstr)) ? -EFAULT : 0;
 
 out_f:
 	fput(file);
@@ -1489,7 +1470,7 @@
 	return -EINVAL;
 }
 
-asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2)
+asmlinkage int irix_truncate64(char __user *name, int pad, int size1, int size2)
 {
 	int retval;
 
@@ -1522,6 +1503,7 @@
 	int len, prot, flags, fd, off1, off2, error, base = 0;
 	unsigned long addr, pgoff, *sp;
 	struct file *file = NULL;
+	int err;
 
 	if (regs->regs[2] == 1000)
 		base = 1;
@@ -1531,36 +1513,31 @@
 	prot = regs->regs[base + 6];
 	if (!base) {
 		flags = regs->regs[base + 7];
-		if (!access_ok(VERIFY_READ, sp, (4 * sizeof(unsigned long)))) {
-			error = -EFAULT;
-			goto out;
-		}
+		if (!access_ok(VERIFY_READ, sp, (4 * sizeof(unsigned long))))
+			return -EFAULT;
 		fd = sp[0];
-		__get_user(off1, &sp[1]);
-		__get_user(off2, &sp[2]);
+		err = __get_user(off1, &sp[1]);
+		err |= __get_user(off2, &sp[2]);
 	} else {
-		if (!access_ok(VERIFY_READ, sp, (5 * sizeof(unsigned long)))) {
-			error = -EFAULT;
-			goto out;
-		}
-		__get_user(flags, &sp[0]);
-		__get_user(fd, &sp[1]);
-		__get_user(off1, &sp[2]);
-		__get_user(off2, &sp[3]);
+		if (!access_ok(VERIFY_READ, sp, (5 * sizeof(unsigned long))))
+			return -EFAULT;
+		err = __get_user(flags, &sp[0]);
+		err |= __get_user(fd, &sp[1]);
+		err |= __get_user(off1, &sp[2]);
+		err |= __get_user(off2, &sp[3]);
 	}
 
-	if (off1 & PAGE_MASK) {
-		error = -EOVERFLOW;
-		goto out;
-	}
+	if (err)
+		return err;
+
+	if (off1 & PAGE_MASK)
+		return -EOVERFLOW;
 
 	pgoff = (off1 << (32 - PAGE_SHIFT)) | (off2 >> PAGE_SHIFT);
 
 	if (!(flags & MAP_ANONYMOUS)) {
-		if (!(file = fget(fd))) {
-			error = -EBADF;
-			goto out;
-		}
+		if (!(file = fget(fd)))
+			return -EBADF;
 
 		/* Ok, bad taste hack follows, try to think in something else
 		   when reading this */
@@ -1570,7 +1547,7 @@
 
 			if (max_size > file->f_dentry->d_inode->i_size) {
 				old_pos = sys_lseek (fd, max_size - 1, 0);
-				sys_write (fd, "", 1);
+				sys_write (fd, (void __user *) "", 1);
 				sys_lseek (fd, old_pos, 0);
 			}
 		}
@@ -1585,7 +1562,6 @@
 	if (file)
 		fput(file);
 
-out:
 	return error;
 }
 
@@ -1597,7 +1573,7 @@
 	return -EINVAL;
 }
 
-asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
+asmlinkage int irix_pread(int fd, char __user *buf, int cnt, int off64,
 			  int off1, int off2)
 {
 	printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
@@ -1606,7 +1582,7 @@
 	return -EINVAL;
 }
 
-asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
+asmlinkage int irix_pwrite(int fd, char __user *buf, int cnt, int off64,
 			   int off1, int off2)
 {
 	printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
@@ -1638,7 +1614,7 @@
 	u32  f_filler[16];
 };
 
-asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
+asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user *buf)
 {
 	struct nameidata nd;
 	struct kstatfs kbuf;
@@ -1650,6 +1626,7 @@
 		error = -EFAULT;
 		goto out;
 	}
+
 	error = user_path_walk(fname, &nd);
 	if (error)
 		goto out;
@@ -1657,27 +1634,25 @@
 	if (error)
 		goto dput_and_out;
 
-	__put_user(kbuf.f_bsize, &buf->f_bsize);
-	__put_user(kbuf.f_frsize, &buf->f_frsize);
-	__put_user(kbuf.f_blocks, &buf->f_blocks);
-	__put_user(kbuf.f_bfree, &buf->f_bfree);
-	__put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
-	__put_user(kbuf.f_files, &buf->f_files);
-	__put_user(kbuf.f_ffree, &buf->f_ffree);
-	__put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
+	error = __put_user(kbuf.f_bsize, &buf->f_bsize);
+	error |= __put_user(kbuf.f_frsize, &buf->f_frsize);
+	error |= __put_user(kbuf.f_blocks, &buf->f_blocks);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bfree);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
+	error |= __put_user(kbuf.f_files, &buf->f_files);
+	error |= __put_user(kbuf.f_ffree, &buf->f_ffree);
+	error |= __put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
 #ifdef __MIPSEB__
-	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
 #else
-	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
 #endif
 	for(i = 0; i < 16; i++)
-		__put_user(0, &buf->f_basetype[i]);
-	__put_user(0, &buf->f_flag);
-	__put_user(kbuf.f_namelen, &buf->f_namemax);
+		error |= __put_user(0, &buf->f_basetype[i]);
+	error |= __put_user(0, &buf->f_flag);
+	error |= __put_user(kbuf.f_namelen, &buf->f_namemax);
 	for(i = 0; i < 32; i++)
-		__put_user(0, &buf->f_fstr[i]);
-
-	error = 0;
+		error |= __put_user(0, &buf->f_fstr[i]);
 
 dput_and_out:
 	path_release(&nd);
@@ -1685,7 +1660,7 @@
 	return error;
 }
 
-asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
+asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf)
 {
 	struct kstatfs kbuf;
 	struct file *file;
@@ -1706,24 +1681,24 @@
 	if (error)
 		goto out_f;
 
-	__put_user(kbuf.f_bsize, &buf->f_bsize);
-	__put_user(kbuf.f_frsize, &buf->f_frsize);
-	__put_user(kbuf.f_blocks, &buf->f_blocks);
-	__put_user(kbuf.f_bfree, &buf->f_bfree);
-	__put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
-	__put_user(kbuf.f_files, &buf->f_files);
-	__put_user(kbuf.f_ffree, &buf->f_ffree);
-	__put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
+	error = __put_user(kbuf.f_bsize, &buf->f_bsize);
+	error |= __put_user(kbuf.f_frsize, &buf->f_frsize);
+	error |= __put_user(kbuf.f_blocks, &buf->f_blocks);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bfree);
+	error |= __put_user(kbuf.f_bfree, &buf->f_bavail);  /* XXX hackety hack... */
+	error |= __put_user(kbuf.f_files, &buf->f_files);
+	error |= __put_user(kbuf.f_ffree, &buf->f_ffree);
+	error |= __put_user(kbuf.f_ffree, &buf->f_favail);  /* XXX hackety hack... */
 #ifdef __MIPSEB__
-	__put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
 #else
-	__put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+	error |= __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
 #endif
 	for(i = 0; i < 16; i++)
-		__put_user(0, &buf->f_basetype[i]);
-	__put_user(0, &buf->f_flag);
-	__put_user(kbuf.f_namelen, &buf->f_namemax);
-	__clear_user(buf->f_fstr, sizeof(buf->f_fstr[i]));
+		error |= __put_user(0, &buf->f_basetype[i]);
+	error |= __put_user(0, &buf->f_flag);
+	error |= __put_user(kbuf.f_namelen, &buf->f_namemax);
+	error |= __clear_user(buf->f_fstr, sizeof(buf->f_fstr[i])) ? -EFAULT : 0;
 
 out_f:
 	fput(file);
@@ -1731,9 +1706,9 @@
 	return error;
 }
 
-asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
+asmlinkage int irix_getmountid(char __user *fname, unsigned long __user *midbuf)
 {
-	int err = 0;
+	int err;
 
 	printk("[%s:%d] irix_getmountid(%s, %p)\n",
 	       current->comm, current->pid, fname, midbuf);
@@ -1746,7 +1721,7 @@
 	 * fsid of the filesystem to try and make the right decision, but
 	 * we don't have this so for now. XXX
 	 */
-	err |= __put_user(0, &midbuf[0]);
+	err = __put_user(0, &midbuf[0]);
 	err |= __put_user(0, &midbuf[1]);
 	err |= __put_user(0, &midbuf[2]);
 	err |= __put_user(0, &midbuf[3]);
@@ -1773,8 +1748,8 @@
 };
 
 struct irix_dirent32_callback {
-	struct irix_dirent32 *current_dir;
-	struct irix_dirent32 *previous;
+	struct irix_dirent32 __user *current_dir;
+	struct irix_dirent32 __user *previous;
 	int count;
 	int error;
 };
@@ -1782,13 +1757,13 @@
 #define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de)))
 #define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
 
-static int irix_filldir32(void *__buf, const char *name, int namlen,
-                          loff_t offset, ino_t ino, unsigned int d_type)
+static int irix_filldir32(void *__buf, const char *name,
+	int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
-	struct irix_dirent32 *dirent;
-	struct irix_dirent32_callback *buf =
-		 (struct irix_dirent32_callback *)__buf;
+	struct irix_dirent32 __user *dirent;
+	struct irix_dirent32_callback *buf = __buf;
 	unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
+	int err = 0;
 
 #ifdef DEBUG_GETDENTS
 	printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
@@ -1799,25 +1774,26 @@
 		return -EINVAL;
 	dirent = buf->previous;
 	if (dirent)
-		__put_user(offset, &dirent->d_off);
+		err = __put_user(offset, &dirent->d_off);
 	dirent = buf->current_dir;
-	buf->previous = dirent;
-	__put_user(ino, &dirent->d_ino);
-	__put_user(reclen, &dirent->d_reclen);
-	copy_to_user(dirent->d_name, name, namlen);
-	__put_user(0, &dirent->d_name[namlen]);
-	((char *) dirent) += reclen;
+	err |= __put_user(dirent, &buf->previous);
+	err |= __put_user(ino, &dirent->d_ino);
+	err |= __put_user(reclen, &dirent->d_reclen);
+	err |= copy_to_user((char __user *)dirent->d_name, name, namlen) ? -EFAULT : 0;
+	err |= __put_user(0, &dirent->d_name[namlen]);
+	dirent = (struct irix_dirent32 __user *) ((char __user *) dirent + reclen);
+
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 
-	return 0;
+	return err;
 }
 
-asmlinkage int irix_ngetdents(unsigned int fd, void * dirent,
-	unsigned int count, int *eob)
+asmlinkage int irix_ngetdents(unsigned int fd, void __user * dirent,
+	unsigned int count, int __user *eob)
 {
 	struct file *file;
-	struct irix_dirent32 *lastdirent;
+	struct irix_dirent32 __user *lastdirent;
 	struct irix_dirent32_callback buf;
 	int error;
 
@@ -1830,7 +1806,7 @@
 	if (!file)
 		goto out;
 
-	buf.current_dir = (struct irix_dirent32 *) dirent;
+	buf.current_dir = (struct irix_dirent32 __user *) dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
@@ -1870,8 +1846,8 @@
 };
 
 struct irix_dirent64_callback {
-	struct irix_dirent64 *curr;
-	struct irix_dirent64 *previous;
+	struct irix_dirent64 __user *curr;
+	struct irix_dirent64 __user *previous;
 	int count;
 	int error;
 };
@@ -1879,37 +1855,44 @@
 #define NAME_OFFSET64(de) ((int) ((de)->d_name - (char *) (de)))
 #define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
 
-static int irix_filldir64(void * __buf, const char * name, int namlen,
-			  loff_t offset, ino_t ino, unsigned int d_type)
+static int irix_filldir64(void *__buf, const char *name,
+	int namlen, loff_t offset, ino_t ino, unsigned int d_type)
 {
-	struct irix_dirent64 *dirent;
-	struct irix_dirent64_callback * buf =
-		(struct irix_dirent64_callback *) __buf;
+	struct irix_dirent64 __user *dirent;
+	struct irix_dirent64_callback * buf = __buf;
 	unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
+	int err = 0;
 
-	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
+		return -EFAULT;
+
+	if (__put_user(-EINVAL, &buf->error))	/* only used if we fail.. */
+		return -EFAULT;
 	if (reclen > buf->count)
 		return -EINVAL;
 	dirent = buf->previous;
 	if (dirent)
-		__put_user(offset, &dirent->d_off);
+		err = __put_user(offset, &dirent->d_off);
 	dirent = buf->curr;
 	buf->previous = dirent;
-	__put_user(ino, &dirent->d_ino);
-	__put_user(reclen, &dirent->d_reclen);
-	__copy_to_user(dirent->d_name, name, namlen);
-	__put_user(0, &dirent->d_name[namlen]);
-	((char *) dirent) += reclen;
+	err |= __put_user(ino, &dirent->d_ino);
+	err |= __put_user(reclen, &dirent->d_reclen);
+	err |= __copy_to_user((char __user *)dirent->d_name, name, namlen)
+	       ? -EFAULT : 0;
+	err |= __put_user(0, &dirent->d_name[namlen]);
+
+	dirent = (struct irix_dirent64 __user *) ((char __user *) dirent + reclen);
+
 	buf->curr = dirent;
 	buf->count -= reclen;
 
-	return 0;
+	return err;
 }
 
-asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
+asmlinkage int irix_getdents64(int fd, void __user *dirent, int cnt)
 {
 	struct file *file;
-	struct irix_dirent64 *lastdirent;
+	struct irix_dirent64 __user *lastdirent;
 	struct irix_dirent64_callback buf;
 	int error;
 
@@ -1929,7 +1912,7 @@
 	if (cnt < (sizeof(struct irix_dirent64) + 255))
 		goto out_f;
 
-	buf.curr = (struct irix_dirent64 *) dirent;
+	buf.curr = (struct irix_dirent64 __user *) dirent;
 	buf.previous = NULL;
 	buf.count = cnt;
 	buf.error = 0;
@@ -1941,7 +1924,8 @@
 		error = buf.error;
 		goto out_f;
 	}
-	lastdirent->d_off = (u64) file->f_pos;
+	if (put_user(file->f_pos, &lastdirent->d_off))
+		return -EFAULT;
 #ifdef DEBUG_GETDENTS
 	printk("returning %d\n", cnt - buf.count);
 #endif
@@ -1953,10 +1937,10 @@
 	return error;
 }
 
-asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
+asmlinkage int irix_ngetdents64(int fd, void __user *dirent, int cnt, int *eob)
 {
 	struct file *file;
-	struct irix_dirent64 *lastdirent;
+	struct irix_dirent64 __user *lastdirent;
 	struct irix_dirent64_callback buf;
 	int error;
 
@@ -1978,7 +1962,7 @@
 		goto out_f;
 
 	*eob = 0;
-	buf.curr = (struct irix_dirent64 *) dirent;
+	buf.curr = (struct irix_dirent64 __user *) dirent;
 	buf.previous = NULL;
 	buf.count = cnt;
 	buf.error = 0;
@@ -1990,7 +1974,8 @@
 		error = buf.error;
 		goto out_f;
 	}
-	lastdirent->d_off = (u64) file->f_pos;
+	if (put_user(file->f_pos, &lastdirent->d_off))
+		return -EFAULT;
 #ifdef DEBUG_GETDENTS
 	printk("eob=%d returning %d\n", *eob, cnt - buf.count);
 #endif
@@ -2053,14 +2038,14 @@
 	return retval;
 }
 
-asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
+asmlinkage int irix_utssys(char __user *inbuf, int arg, int type, char __user *outbuf)
 {
 	int retval;
 
 	switch(type) {
 	case 0:
 		/* uname() */
-		retval = irix_uname((struct iuname *)inbuf);
+		retval = irix_uname((struct iuname __user *)inbuf);
 		goto out;
 
 	case 2:
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 0dd0df7a..787ed54 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,6 +11,7 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -25,6 +26,7 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
+#include <asm/cache.h>
 #include <asm/compiler.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -43,10 +45,6 @@
 
 #define TICK_SIZE	(tick_nsec / 1000)
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 /*
  * forward reference
  */
@@ -76,7 +74,7 @@
 static unsigned int sll32_usecs_per_cycle;
 
 /* how many counter cycles in a jiffy */
-static unsigned long cycles_per_jiffy;
+static unsigned long cycles_per_jiffy __read_mostly;
 
 /* Cycle counter value at the previous timer interrupt.. */
 static unsigned int timerhi, timerlo;
@@ -98,7 +96,10 @@
 	return 0;
 }
 
-static void null_hpt_init(unsigned int count) { /* nothing */ }
+static void null_hpt_init(unsigned int count)
+{
+	/* nothing */
+}
 
 
 /*
@@ -108,8 +109,10 @@
 {
 	unsigned int count;
 
+#ifndef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
 	/* Ack this timer interrupt and set the next one.  */
 	expirelo += cycles_per_jiffy;
+#endif
 	write_c0_compare(expirelo);
 
 	/* Check to see if we have missed any timer interrupts.  */
@@ -224,7 +227,6 @@
 	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
 	ntp_clear();
-
 	write_sequnlock_irq(&xtime_lock);
 	clock_was_set();
 	return 0;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a53b1ed..6f3ff96 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -9,7 +9,7 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000, 01 MIPS Technologies, Inc.
- * Copyright (C) 2002, 2003, 2004  Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2004, 2005  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -20,12 +20,16 @@
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
+#include <linux/bootmem.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
 #include <asm/break.h>
 #include <asm/cpu.h>
+#include <asm/dsp.h>
 #include <asm/fpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/module.h>
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
@@ -54,14 +58,19 @@
 extern asmlinkage void handle_fpe(void);
 extern asmlinkage void handle_mdmx(void);
 extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_mt(void);
+extern asmlinkage void handle_dsp(void);
 extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
-extern int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
+extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 	struct mips_fpu_soft_struct *ctx);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
+void (*board_nmi_handler_setup)(void);
+void (*board_ejtag_handler_setup)(void);
+void (*board_bind_eic_interrupt)(int irq, int regset);
 
 /*
  * These constant is for searching for possible module text segments.
@@ -201,32 +210,47 @@
 
 	printk("Status: %08x    ", (uint32_t) regs->cp0_status);
 
-	if (regs->cp0_status & ST0_KX)
-		printk("KX ");
-	if (regs->cp0_status & ST0_SX)
-		printk("SX ");
-	if (regs->cp0_status & ST0_UX)
-		printk("UX ");
-	switch (regs->cp0_status & ST0_KSU) {
-	case KSU_USER:
-		printk("USER ");
-		break;
-	case KSU_SUPERVISOR:
-		printk("SUPERVISOR ");
-		break;
-	case KSU_KERNEL:
-		printk("KERNEL ");
-		break;
-	default:
-		printk("BAD_MODE ");
-		break;
+	if (current_cpu_data.isa_level == MIPS_CPU_ISA_I) {
+		if (regs->cp0_status & ST0_KUO)
+			printk("KUo ");
+		if (regs->cp0_status & ST0_IEO)
+			printk("IEo ");
+		if (regs->cp0_status & ST0_KUP)
+			printk("KUp ");
+		if (regs->cp0_status & ST0_IEP)
+			printk("IEp ");
+		if (regs->cp0_status & ST0_KUC)
+			printk("KUc ");
+		if (regs->cp0_status & ST0_IEC)
+			printk("IEc ");
+	} else {
+		if (regs->cp0_status & ST0_KX)
+			printk("KX ");
+		if (regs->cp0_status & ST0_SX)
+			printk("SX ");
+		if (regs->cp0_status & ST0_UX)
+			printk("UX ");
+		switch (regs->cp0_status & ST0_KSU) {
+		case KSU_USER:
+			printk("USER ");
+			break;
+		case KSU_SUPERVISOR:
+			printk("SUPERVISOR ");
+			break;
+		case KSU_KERNEL:
+			printk("KERNEL ");
+			break;
+		default:
+			printk("BAD_MODE ");
+			break;
+		}
+		if (regs->cp0_status & ST0_ERL)
+			printk("ERL ");
+		if (regs->cp0_status & ST0_EXL)
+			printk("EXL ");
+		if (regs->cp0_status & ST0_IE)
+			printk("IE ");
 	}
-	if (regs->cp0_status & ST0_ERL)
-		printk("ERL ");
-	if (regs->cp0_status & ST0_EXL)
-		printk("EXL ");
-	if (regs->cp0_status & ST0_IE)
-		printk("IE ");
 	printk("\n");
 
 	printk("Cause : %08x\n", cause);
@@ -252,29 +276,18 @@
 
 static DEFINE_SPINLOCK(die_lock);
 
-NORET_TYPE void __die(const char * str, struct pt_regs * regs,
-	const char * file, const char * func, unsigned long line)
+NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
 {
 	static int die_counter;
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
-	printk("%s", str);
-	if (file && func)
-		printk(" in %s:%s, line %ld", file, func, line);
-	printk("[#%d]:\n", ++die_counter);
+	printk("%s[#%d]:\n", str, ++die_counter);
 	show_registers(regs);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
 }
 
-void __die_if_kernel(const char * str, struct pt_regs * regs,
-		     const char * file, const char * func, unsigned long line)
-{
-	if (!user_mode(regs))
-		__die(str, regs, file, func, line);
-}
-
 extern const struct exception_table_entry __start___dbe_table[];
 extern const struct exception_table_entry __stop___dbe_table[];
 
@@ -339,9 +352,9 @@
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
 {
-	unsigned int *epc;
+	unsigned int __user *epc;
 
-	epc = (unsigned int *) regs->cp0_epc +
+	epc = (unsigned int __user *) regs->cp0_epc +
 	      ((regs->cp0_cause & CAUSEF_BD) != 0);
 	if (!get_user(*opcode, epc))
 		return 0;
@@ -360,6 +373,10 @@
 #define OFFSET 0x0000ffff
 #define LL     0xc0000000
 #define SC     0xe0000000
+#define SPEC3  0x7c000000
+#define RD     0x0000f800
+#define FUNC   0x0000003f
+#define RDHWR  0x0000003b
 
 /*
  * The ll_bit is cleared by r*_switch.S
@@ -371,7 +388,7 @@
 
 static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
 {
-	unsigned long value, *vaddr;
+	unsigned long value, __user *vaddr;
 	long offset;
 	int signal = 0;
 
@@ -385,7 +402,8 @@
 	offset <<= 16;
 	offset >>= 16;
 
-	vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
+	vaddr = (unsigned long __user *)
+	        ((unsigned long)(regs->regs[(opcode & BASE) >> 21]) + offset);
 
 	if ((unsigned long)vaddr & 3) {
 		signal = SIGBUS;
@@ -407,9 +425,10 @@
 
 	preempt_enable();
 
+	compute_return_epc(regs);
+
 	regs->regs[(opcode & RT) >> 16] = value;
 
-	compute_return_epc(regs);
 	return;
 
 sig:
@@ -418,7 +437,8 @@
 
 static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
 {
-	unsigned long *vaddr, reg;
+	unsigned long __user *vaddr;
+	unsigned long reg;
 	long offset;
 	int signal = 0;
 
@@ -432,7 +452,8 @@
 	offset <<= 16;
 	offset >>= 16;
 
-	vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
+	vaddr = (unsigned long __user *)
+	        ((unsigned long)(regs->regs[(opcode & BASE) >> 21]) + offset);
 	reg = (opcode & RT) >> 16;
 
 	if ((unsigned long)vaddr & 3) {
@@ -443,9 +464,9 @@
 	preempt_disable();
 
 	if (ll_bit == 0 || ll_task != current) {
+		compute_return_epc(regs);
 		regs->regs[reg] = 0;
 		preempt_enable();
-		compute_return_epc(regs);
 		return;
 	}
 
@@ -456,9 +477,9 @@
 		goto sig;
 	}
 
+	compute_return_epc(regs);
 	regs->regs[reg] = 1;
 
-	compute_return_epc(regs);
 	return;
 
 sig:
@@ -491,6 +512,37 @@
 	return -EFAULT;			/* Strange things going on ... */
 }
 
+/*
+ * Simulate trapping 'rdhwr' instructions to provide user accessible
+ * registers not implemented in hardware.  The only current use of this
+ * is the thread area pointer.
+ */
+static inline int simulate_rdhwr(struct pt_regs *regs)
+{
+	struct thread_info *ti = current->thread_info;
+	unsigned int opcode;
+
+	if (unlikely(get_insn_opcode(regs, &opcode)))
+		return -EFAULT;
+
+	if (unlikely(compute_return_epc(regs)))
+		return -EFAULT;
+
+	if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) {
+		int rd = (opcode & RD) >> 11;
+		int rt = (opcode & RT) >> 16;
+		switch (rd) {
+			case 29:
+				regs->regs[rt] = ti->tp_value;
+				break;
+			default:
+				return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	siginfo_t info;
@@ -498,7 +550,7 @@
 	info.si_code = FPE_INTOVF;
 	info.si_signo = SIGFPE;
 	info.si_errno = 0;
-	info.si_addr = (void *)regs->cp0_epc;
+	info.si_addr = (void __user *) regs->cp0_epc;
 	force_sig_info(SIGFPE, &info, current);
 }
 
@@ -512,6 +564,14 @@
 
 		preempt_disable();
 
+#ifdef CONFIG_PREEMPT
+		if (!is_fpu_owner()) {
+			/* We might lose fpu before disabling preempt... */
+			own_fpu();
+			BUG_ON(!used_math());
+			restore_fp(current);
+		}
+#endif
 		/*
 	 	 * Unimplemented operation exception.  If we've got the full
 		 * software emulator on-board, let's use it...
@@ -523,11 +583,18 @@
 		 * a bit extreme for what should be an infrequent event.
 		 */
 		save_fp(current);
+		/* Ensure 'resume' not overwrite saved fp context again. */
+		lose_fpu();
+
+		preempt_enable();
 
 		/* Run the emulator */
-		sig = fpu_emulator_cop1Handler (0, regs,
+		sig = fpu_emulator_cop1Handler (regs,
 			&current->thread.fpu.soft);
 
+		preempt_disable();
+
+		own_fpu();	/* Using the FPU again.  */
 		/*
 		 * We can't allow the emulated instruction to leave any of
 		 * the cause bit set in $fcr31.
@@ -584,7 +651,7 @@
 			info.si_code = FPE_INTOVF;
 		info.si_signo = SIGFPE;
 		info.si_errno = 0;
-		info.si_addr = (void *)regs->cp0_epc;
+		info.si_addr = (void __user *) regs->cp0_epc;
 		force_sig_info(SIGFPE, &info, current);
 		break;
 	default:
@@ -621,7 +688,7 @@
 			info.si_code = FPE_INTOVF;
 		info.si_signo = SIGFPE;
 		info.si_errno = 0;
-		info.si_addr = (void *)regs->cp0_epc;
+		info.si_addr = (void __user *) regs->cp0_epc;
 		force_sig_info(SIGFPE, &info, current);
 		break;
 	default:
@@ -637,6 +704,9 @@
 		if (!simulate_llsc(regs))
 			return;
 
+	if (!simulate_rdhwr(regs))
+		return;
+
 	force_sig(SIGILL, current);
 }
 
@@ -650,11 +720,13 @@
 
 	switch (cpid) {
 	case 0:
-		if (cpu_has_llsc)
-			break;
+		if (!cpu_has_llsc)
+			if (!simulate_llsc(regs))
+				return;
 
-		if (!simulate_llsc(regs))
+		if (!simulate_rdhwr(regs))
 			return;
+
 		break;
 
 	case 1:
@@ -668,15 +740,15 @@
 			set_used_math();
 		}
 
+		preempt_enable();
+
 		if (!cpu_has_fpu) {
-			int sig = fpu_emulator_cop1Handler(0, regs,
+			int sig = fpu_emulator_cop1Handler(regs,
 						&current->thread.fpu.soft);
 			if (sig)
 				force_sig(sig, current);
 		}
 
-		preempt_enable();
-
 		return;
 
 	case 2:
@@ -716,6 +788,22 @@
 	      (regs->cp0_status & ST0_TS) ? "" : "not ");
 }
 
+asmlinkage void do_mt(struct pt_regs *regs)
+{
+	die_if_kernel("MIPS MT Thread exception in kernel", regs);
+
+	force_sig(SIGILL, current);
+}
+
+
+asmlinkage void do_dsp(struct pt_regs *regs)
+{
+	if (cpu_has_dsp)
+		panic("Unexpected DSP exception\n");
+
+	force_sig(SIGILL, current);
+}
+
 asmlinkage void do_reserved(struct pt_regs *regs)
 {
 	/*
@@ -728,6 +816,12 @@
 	      (regs->cp0_cause & 0x7f) >> 2);
 }
 
+asmlinkage void do_default_vi(struct pt_regs *regs)
+{
+	show_regs(regs);
+	panic("Caught unexpected vectored interrupt.");
+}
+
 /*
  * Some MIPS CPUs can enable/disable for cache parity detection, but do
  * it different ways.
@@ -736,16 +830,12 @@
 {
 	switch (current_cpu_data.cputype) {
 	case CPU_24K:
-		/* 24K cache parity not currently implemented in FPGA */
-		printk(KERN_INFO "Disable cache parity protection for "
-		       "MIPS 24K CPU.\n");
-		write_c0_ecc(read_c0_ecc() & ~0x80000000);
-		break;
 	case CPU_5KC:
-		/* Set the PE bit (bit 31) in the c0_ecc register. */
-		printk(KERN_INFO "Enable cache parity protection for "
-		       "MIPS 5KC/24K CPUs.\n");
-		write_c0_ecc(read_c0_ecc() | 0x80000000);
+		write_c0_ecc(0x80000000);
+		back_to_back_c0_hazard();
+		/* Set the PE bit (bit 31) in the c0_errctl register. */
+		printk(KERN_INFO "Cache parity protection %sabled\n",
+		       (read_c0_ecc() & 0x80000000) ? "en" : "dis");
 		break;
 	case CPU_20KC:
 	case CPU_25KF:
@@ -783,7 +873,7 @@
 	       reg_val & (1<<22) ? "E0 " : "");
 	printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1));
 
-#if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64)
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
 	if (reg_val & (1<<22))
 		printk("DErrAddr0: 0x%0*lx\n", field, read_c0_derraddr0());
 
@@ -840,7 +930,11 @@
 	while(1) ;
 }
 
+#define VECTORSPACING 0x100	/* for EI/VI mode */
+
+unsigned long ebase;
 unsigned long exception_handlers[32];
+unsigned long vi_handlers[64];
 
 /*
  * As a side effect of the way this is implemented we're limited
@@ -854,13 +948,156 @@
 
 	exception_handlers[n] = handler;
 	if (n == 0 && cpu_has_divec) {
-		*(volatile u32 *)(CAC_BASE + 0x200) = 0x08000000 |
+		*(volatile u32 *)(ebase + 0x200) = 0x08000000 |
 		                                 (0x03ffffff & (handler >> 2));
-		flush_icache_range(CAC_BASE + 0x200, CAC_BASE + 0x204);
+		flush_icache_range(ebase + 0x200, ebase + 0x204);
 	}
 	return (void *)old_handler;
 }
 
+#ifdef CONFIG_CPU_MIPSR2
+/*
+ * Shadow register allocation
+ * FIXME: SMP...
+ */
+
+/* MIPSR2 shadow register sets */
+struct shadow_registers {
+	spinlock_t sr_lock;	/*  */
+	int sr_supported;	/* Number of shadow register sets supported */
+	int sr_allocated;	/* Bitmap of allocated shadow registers */
+} shadow_registers;
+
+void mips_srs_init(void)
+{
+#ifdef CONFIG_CPU_MIPSR2_SRS
+	shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
+	printk ("%d MIPSR2 register sets available\n", shadow_registers.sr_supported);
+#else
+	shadow_registers.sr_supported = 1;
+#endif
+	shadow_registers.sr_allocated = 1;	/* Set 0 used by kernel */
+	spin_lock_init(&shadow_registers.sr_lock);
+}
+
+int mips_srs_max(void)
+{
+	return shadow_registers.sr_supported;
+}
+
+int mips_srs_alloc (void)
+{
+	struct shadow_registers *sr = &shadow_registers;
+	unsigned long flags;
+	int set;
+
+	spin_lock_irqsave(&sr->sr_lock, flags);
+
+	for (set = 0; set < sr->sr_supported; set++) {
+		if ((sr->sr_allocated & (1 << set)) == 0) {
+			sr->sr_allocated |= 1 << set;
+			spin_unlock_irqrestore(&sr->sr_lock, flags);
+			return set;
+		}
+	}
+
+	/* None available */
+	spin_unlock_irqrestore(&sr->sr_lock, flags);
+	return -1;
+}
+
+void mips_srs_free (int set)
+{
+	struct shadow_registers *sr = &shadow_registers;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sr->sr_lock, flags);
+	sr->sr_allocated &= ~(1 << set);
+	spin_unlock_irqrestore(&sr->sr_lock, flags);
+}
+
+void *set_vi_srs_handler (int n, void *addr, int srs)
+{
+	unsigned long handler;
+	unsigned long old_handler = vi_handlers[n];
+	u32 *w;
+	unsigned char *b;
+
+	if (!cpu_has_veic && !cpu_has_vint)
+		BUG();
+
+	if (addr == NULL) {
+		handler = (unsigned long) do_default_vi;
+		srs = 0;
+	}
+	else
+		handler = (unsigned long) addr;
+	vi_handlers[n] = (unsigned long) addr;
+
+	b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING);
+
+	if (srs >= mips_srs_max())
+		panic("Shadow register set %d not supported", srs);
+
+	if (cpu_has_veic) {
+		if (board_bind_eic_interrupt)
+			board_bind_eic_interrupt (n, srs);
+	}
+	else if (cpu_has_vint) {
+		/* SRSMap is only defined if shadow sets are implemented */
+		if (mips_srs_max() > 1)
+			change_c0_srsmap (0xf << n*4, srs << n*4);
+	}
+
+	if (srs == 0) {
+		/*
+		 * If no shadow set is selected then use the default handler
+		 * that does normal register saving and a standard interrupt exit
+		 */
+
+		extern char except_vec_vi, except_vec_vi_lui;
+		extern char except_vec_vi_ori, except_vec_vi_end;
+		const int handler_len = &except_vec_vi_end - &except_vec_vi;
+		const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
+		const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
+
+		if (handler_len > VECTORSPACING) {
+			/*
+			 * Sigh... panicing won't help as the console
+			 * is probably not configured :(
+			 */
+			panic ("VECTORSPACING too small");
+		}
+
+		memcpy (b, &except_vec_vi, handler_len);
+		w = (u32 *)(b + lui_offset);
+		*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
+		w = (u32 *)(b + ori_offset);
+		*w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
+		flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len));
+	}
+	else {
+		/*
+		 * In other cases jump directly to the interrupt handler
+		 *
+		 * It is the handlers responsibility to save registers if required
+		 * (eg hi/lo) and return from the exception using "eret"
+		 */
+		w = (u32 *)b;
+		*w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */
+		*w = 0;
+		flush_icache_range((unsigned long)b, (unsigned long)(b+8));
+	}
+
+	return (void *)old_handler;
+}
+
+void *set_vi_handler (int n, void *addr)
+{
+	return set_vi_srs_handler (n, addr, 0);
+}
+#endif
+
 /*
  * This is used by native signal handling
  */
@@ -912,6 +1149,7 @@
 
 extern void cpu_cache_init(void);
 extern void tlb_init(void);
+extern void flush_tlb_handlers(void);
 
 void __init per_cpu_trap_init(void)
 {
@@ -929,15 +1167,32 @@
 #endif
 	if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
 		status_set |= ST0_XX;
-	change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
+	change_c0_status(ST0_CU|ST0_MX|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
 			 status_set);
 
+	if (cpu_has_dsp)
+		set_c0_status(ST0_MX);
+
+#ifdef CONFIG_CPU_MIPSR2
+	write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
+#endif
+
 	/*
-	 * Some MIPS CPUs have a dedicated interrupt vector which reduces the
-	 * interrupt processing overhead.  Use it where available.
+	 * Interrupt handling.
 	 */
-	if (cpu_has_divec)
-		set_c0_cause(CAUSEF_IV);
+	if (cpu_has_veic || cpu_has_vint) {
+		write_c0_ebase (ebase);
+		/* Setting vector spacing enables EI/VI mode  */
+		change_c0_intctl (0x3e0, VECTORSPACING);
+	}
+	if (cpu_has_divec) {
+		if (cpu_has_mipsmt) {
+			unsigned int vpflags = dvpe();
+			set_c0_cause(CAUSEF_IV);
+			evpe(vpflags);
+		} else
+			set_c0_cause(CAUSEF_IV);
+	}
 
 	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 	TLBMISS_HANDLER_SETUP();
@@ -951,13 +1206,41 @@
 	tlb_init();
 }
 
+/* Install CPU exception handler */
+void __init set_handler (unsigned long offset, void *addr, unsigned long size)
+{
+	memcpy((void *)(ebase + offset), addr, size);
+	flush_icache_range(ebase + offset, ebase + offset + size);
+}
+
+/* Install uncached CPU exception handler */
+void __init set_uncached_handler (unsigned long offset, void *addr, unsigned long size)
+{
+#ifdef CONFIG_32BIT
+	unsigned long uncached_ebase = KSEG1ADDR(ebase);
+#endif
+#ifdef CONFIG_64BIT
+	unsigned long uncached_ebase = TO_UNCAC(ebase);
+#endif
+
+	memcpy((void *)(uncached_ebase + offset), addr, size);
+}
+
 void __init trap_init(void)
 {
 	extern char except_vec3_generic, except_vec3_r4000;
-	extern char except_vec_ejtag_debug;
 	extern char except_vec4;
 	unsigned long i;
 
+	if (cpu_has_veic || cpu_has_vint)
+		ebase = (unsigned long) alloc_bootmem_low_pages (0x200 + VECTORSPACING*64);
+	else
+		ebase = CAC_BASE;
+
+#ifdef CONFIG_CPU_MIPSR2
+	mips_srs_init();
+#endif
+
 	per_cpu_trap_init();
 
 	/*
@@ -965,7 +1248,7 @@
 	 * This will be overriden later as suitable for a particular
 	 * configuration.
 	 */
-	memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
+	set_handler(0x180, &except_vec3_generic, 0x80);
 
 	/*
 	 * Setup default vectors
@@ -977,8 +1260,8 @@
 	 * Copy the EJTAG debug exception vector handler code to it's final
 	 * destination.
 	 */
-	if (cpu_has_ejtag)
-		memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, 0x80);
+	if (cpu_has_ejtag && board_ejtag_handler_setup)
+		board_ejtag_handler_setup ();
 
 	/*
 	 * Only some CPUs have the watch exceptions.
@@ -987,11 +1270,15 @@
 		set_except_vector(23, handle_watch);
 
 	/*
-	 * Some MIPS CPUs have a dedicated interrupt vector which reduces the
-	 * interrupt processing overhead.  Use it where available.
+	 * Initialise interrupt handlers
 	 */
-	if (cpu_has_divec)
-		memcpy((void *)(CAC_BASE + 0x200), &except_vec4, 0x8);
+	if (cpu_has_veic || cpu_has_vint) {
+		int nvec = cpu_has_veic ? 64 : 8;
+		for (i = 0; i < nvec; i++)
+			set_vi_handler (i, NULL);
+	}
+	else if (cpu_has_divec)
+		set_handler(0x200, &except_vec4, 0x8);
 
 	/*
 	 * Some CPUs can enable/disable for cache parity detection, but does
@@ -1023,21 +1310,6 @@
 	set_except_vector(11, handle_cpu);
 	set_except_vector(12, handle_ov);
 	set_except_vector(13, handle_tr);
-	set_except_vector(22, handle_mdmx);
-
-	if (cpu_has_fpu && !cpu_has_nofpuex)
-		set_except_vector(15, handle_fpe);
-
-	if (cpu_has_mcheck)
-		set_except_vector(24, handle_mcheck);
-
-	if (cpu_has_vce)
-		/* Special exception: R4[04]00 uses also the divec space. */
-		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
-	else if (cpu_has_4kex)
-		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
-	else
-		memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
 
 	if (current_cpu_data.cputype == CPU_R6000 ||
 	    current_cpu_data.cputype == CPU_R6000A) {
@@ -1053,10 +1325,37 @@
 		//set_except_vector(15, handle_ndc);
 	}
 
+
+	if (board_nmi_handler_setup)
+		board_nmi_handler_setup();
+
+	if (cpu_has_fpu && !cpu_has_nofpuex)
+		set_except_vector(15, handle_fpe);
+
+	set_except_vector(22, handle_mdmx);
+
+	if (cpu_has_mcheck)
+		set_except_vector(24, handle_mcheck);
+
+	if (cpu_has_mipsmt)
+		set_except_vector(25, handle_mt);
+
+	if (cpu_has_dsp)
+		set_except_vector(26, handle_dsp);
+
+	if (cpu_has_vce)
+		/* Special exception: R4[04]00 uses also the divec space. */
+		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
+	else if (cpu_has_4kex)
+		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
+	else
+		memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
+
 	signal_init();
 #ifdef CONFIG_MIPS32_COMPAT
 	signal32_init();
 #endif
 
-	flush_icache_range(CAC_BASE, CAC_BASE + 0x400);
+	flush_icache_range(ebase, ebase + 0x400);
+	flush_tlb_handlers();
 }
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 36c5212..5b5a373 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -94,7 +94,7 @@
 #endif
 
 static inline int emulate_load_store_insn(struct pt_regs *regs,
-	void *addr, unsigned long pc,
+	void __user *addr, unsigned int __user *pc,
 	unsigned long **regptr, unsigned long *newvalue)
 {
 	union mips_instruction insn;
@@ -107,7 +107,7 @@
 	/*
 	 * This load never faults.
 	 */
-	__get_user(insn.word, (unsigned int *)pc);
+	__get_user(insn.word, pc);
 
 	switch (insn.i_format.opcode) {
 	/*
@@ -494,8 +494,8 @@
 {
 	unsigned long *regptr, newval;
 	extern int do_dsemulret(struct pt_regs *);
+	unsigned int __user *pc;
 	mm_segment_t seg;
-	unsigned long pc;
 
 	/*
 	 * Address errors may be deliberately induced by the FPU emulator to
@@ -515,7 +515,7 @@
 	if ((regs->cp0_badvaddr == regs->cp0_epc) || (regs->cp0_epc & 0x1))
 		goto sigbus;
 
-	pc = exception_epc(regs);
+	pc = (unsigned int __user *) exception_epc(regs);
 	if ((current->thread.mflags & MF_FIXADE) == 0)
 		goto sigbus;
 
@@ -526,7 +526,7 @@
 	seg = get_fs();
 	if (!user_mode(regs))
 		set_fs(KERNEL_DS);
-	if (!emulate_load_store_insn(regs, (void *)regs->cp0_badvaddr, pc,
+	if (!emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc,
 	                             &regptr, &newval)) {
 		compute_return_epc(regs);
 		/*
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 482ac31..25cc856 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -54,13 +54,6 @@
 
     *(.data)
 
-   /* Align the initial ramdisk image (INITRD) on page boundaries. */
-   . = ALIGN(4096);
-   __rd_start = .;
-   *(.initrd)
-   . = ALIGN(4096);
-   __rd_end = .;
-
     CONSTRUCTORS
   }
   _gp = . + 0x8000;
@@ -96,12 +89,6 @@
   .init.setup : { *(.init.setup) }
   __setup_end = .;
 
-  .early_initcall.init : {
-  __earlyinitcall_start = .;
-	*(.initcall.early1.init)
-  }
-  __earlyinitcall_end = .;
-
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init)
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
new file mode 100644
index 0000000..97fefcc
--- /dev/null
+++ b/arch/mips/kernel/vpe.c
@@ -0,0 +1,1296 @@
+/*
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ */
+
+/*
+ * VPE support module
+ *
+ * Provides support for loading a MIPS SP program on VPE1.
+ * The SP enviroment is rather simple, no tlb's.  It needs to be relocatable
+ * (or partially linked). You should initialise your stack in the startup
+ * code. This loader looks for the symbol __start and sets up
+ * execution to resume from there. The MIPS SDE kit contains suitable examples.
+ *
+ * To load and run, simply cat a SP 'program file' to /dev/vpe1.
+ * i.e cat spapp >/dev/vpe1.
+ *
+ * You'll need to have the following device files.
+ * mknod /dev/vpe0 c 63 0
+ * mknod /dev/vpe1 c 63 1
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/seq_file.h>
+#include <linux/syscalls.h>
+#include <linux/moduleloader.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/bootmem.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#include <asm/cacheflush.h>
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+
+typedef void *vpe_handle;
+
+// defined here because the kernel module loader doesn't have
+// anything to do with it.
+#define SHN_MIPS_SCOMMON 0xff03
+
+#ifndef ARCH_SHF_SMALL
+#define ARCH_SHF_SMALL 0
+#endif
+
+/* If this is set, the section belongs in the init part of the module */
+#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
+
+// temp number,
+#define VPE_MAJOR 63
+
+static char module_name[] = "vpe";
+static int major = 0;
+
+/* grab the likely amount of memory we will need. */
+#ifdef CONFIG_MIPS_VPE_LOADER_TOM
+#define P_SIZE (2 * 1024 * 1024)
+#else
+/* add an overhead to the max kmalloc size for non-striped symbols/etc */
+#define P_SIZE (256 * 1024)
+#endif
+
+#define MAX_VPES 16
+
+enum vpe_state {
+	VPE_STATE_UNUSED = 0,
+	VPE_STATE_INUSE,
+	VPE_STATE_RUNNING
+};
+
+enum tc_state {
+	TC_STATE_UNUSED = 0,
+	TC_STATE_INUSE,
+	TC_STATE_RUNNING,
+	TC_STATE_DYNAMIC
+};
+
+struct vpe;
+typedef struct tc {
+	enum tc_state state;
+	int index;
+
+	/* parent VPE */
+	struct vpe *pvpe;
+
+	/* The list of TC's with this VPE */
+	struct list_head tc;
+
+	/* The global list of tc's */
+	struct list_head list;
+} tc_t;
+
+typedef struct vpe {
+	enum vpe_state state;
+
+	/* (device) minor associated with this vpe */
+	int minor;
+
+	/* elfloader stuff */
+	void *load_addr;
+	u32 len;
+	char *pbuffer;
+	u32 plen;
+
+	unsigned long __start;
+
+	/* tc's associated with this vpe */
+	struct list_head tc;
+
+	/* The list of vpe's */
+	struct list_head list;
+
+	/* shared symbol address */
+	void *shared_ptr;
+} vpe_t;
+
+struct vpecontrol_ {
+	/* Virtual processing elements */
+	struct list_head vpe_list;
+
+	/* Thread contexts */
+	struct list_head tc_list;
+} vpecontrol;
+
+static void release_progmem(void *ptr);
+static void dump_vpe(vpe_t * v);
+extern void save_gp_address(unsigned int secbase, unsigned int rel);
+
+/* get the vpe associated with this minor */
+struct vpe *get_vpe(int minor)
+{
+	struct vpe *v;
+
+	list_for_each_entry(v, &vpecontrol.vpe_list, list) {
+		if (v->minor == minor)
+			return v;
+	}
+
+	printk(KERN_DEBUG "VPE: get_vpe minor %d not found\n", minor);
+	return NULL;
+}
+
+/* get the vpe associated with this minor */
+struct tc *get_tc(int index)
+{
+	struct tc *t;
+
+	list_for_each_entry(t, &vpecontrol.tc_list, list) {
+		if (t->index == index)
+			return t;
+	}
+
+	printk(KERN_DEBUG "VPE: get_tc index %d not found\n", index);
+
+	return NULL;
+}
+
+struct tc *get_tc_unused(void)
+{
+	struct tc *t;
+
+	list_for_each_entry(t, &vpecontrol.tc_list, list) {
+		if (t->state == TC_STATE_UNUSED)
+			return t;
+	}
+
+	printk(KERN_DEBUG "VPE: All TC's are in use\n");
+
+	return NULL;
+}
+
+/* allocate a vpe and associate it with this minor (or index) */
+struct vpe *alloc_vpe(int minor)
+{
+	struct vpe *v;
+
+	if ((v = kmalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
+		printk(KERN_WARNING "VPE: alloc_vpe no mem\n");
+		return NULL;
+	}
+
+	memset(v, 0, sizeof(struct vpe));
+
+	INIT_LIST_HEAD(&v->tc);
+	list_add_tail(&v->list, &vpecontrol.vpe_list);
+
+	v->minor = minor;
+	return v;
+}
+
+/* allocate a tc. At startup only tc0 is running, all other can be halted. */
+struct tc *alloc_tc(int index)
+{
+	struct tc *t;
+
+	if ((t = kmalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
+		printk(KERN_WARNING "VPE: alloc_tc no mem\n");
+		return NULL;
+	}
+
+	memset(t, 0, sizeof(struct tc));
+
+	INIT_LIST_HEAD(&t->tc);
+	list_add_tail(&t->list, &vpecontrol.tc_list);
+
+	t->index = index;
+
+	return t;
+}
+
+/* clean up and free everything */
+void release_vpe(struct vpe *v)
+{
+	list_del(&v->list);
+	if (v->load_addr)
+		release_progmem(v);
+	kfree(v);
+}
+
+void dump_mtregs(void)
+{
+	unsigned long val;
+
+	val = read_c0_config3();
+	printk("config3 0x%lx MT %ld\n", val,
+	       (val & CONFIG3_MT) >> CONFIG3_MT_SHIFT);
+
+	val = read_c0_mvpconf0();
+	printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
+	       (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
+	       val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
+
+	val = read_c0_mvpcontrol();
+	printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val,
+	       (val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT,
+	       (val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT,
+	       (val & MVPCONTROL_EVP));
+
+	val = read_c0_vpeconf0();
+	printk("VPEConf0 0x%lx MVP %ld\n", val,
+	       (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+}
+
+/* Find some VPE program space  */
+static void *alloc_progmem(u32 len)
+{
+#ifdef CONFIG_MIPS_VPE_LOADER_TOM
+	/* this means you must tell linux to use less memory than you physically have */
+	return (void *)((max_pfn * PAGE_SIZE) + KSEG0);
+#else
+	// simple grab some mem for now
+	return kmalloc(len, GFP_KERNEL);
+#endif
+}
+
+static void release_progmem(void *ptr)
+{
+#ifndef CONFIG_MIPS_VPE_LOADER_TOM
+	kfree(ptr);
+#endif
+}
+
+/* Update size with this section: return offset. */
+static long get_offset(unsigned long *size, Elf_Shdr * sechdr)
+{
+	long ret;
+
+	ret = ALIGN(*size, sechdr->sh_addralign ? : 1);
+	*size = ret + sechdr->sh_size;
+	return ret;
+}
+
+/* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld
+   might -- code, read-only data, read-write data, small data.  Tally
+   sizes, and place the offsets into sh_entsize fields: high bit means it
+   belongs in init. */
+static void layout_sections(struct module *mod, const Elf_Ehdr * hdr,
+			    Elf_Shdr * sechdrs, const char *secstrings)
+{
+	static unsigned long const masks[][2] = {
+		/* NOTE: all executable code must be the first section
+		 * in this array; otherwise modify the text_size
+		 * finder in the two loops below */
+		{SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL},
+		{SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL},
+		{SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL},
+		{ARCH_SHF_SMALL | SHF_ALLOC, 0}
+	};
+	unsigned int m, i;
+
+	for (i = 0; i < hdr->e_shnum; i++)
+		sechdrs[i].sh_entsize = ~0UL;
+
+	for (m = 0; m < ARRAY_SIZE(masks); ++m) {
+		for (i = 0; i < hdr->e_shnum; ++i) {
+			Elf_Shdr *s = &sechdrs[i];
+
+			//  || strncmp(secstrings + s->sh_name, ".init", 5) == 0)
+			if ((s->sh_flags & masks[m][0]) != masks[m][0]
+			    || (s->sh_flags & masks[m][1])
+			    || s->sh_entsize != ~0UL)
+				continue;
+			s->sh_entsize = get_offset(&mod->core_size, s);
+		}
+
+		if (m == 0)
+			mod->core_text_size = mod->core_size;
+
+	}
+}
+
+
+/* from module-elf32.c, but subverted a little */
+
+struct mips_hi16 {
+	struct mips_hi16 *next;
+	Elf32_Addr *addr;
+	Elf32_Addr value;
+};
+
+static struct mips_hi16 *mips_hi16_list;
+static unsigned int gp_offs, gp_addr;
+
+static int apply_r_mips_none(struct module *me, uint32_t *location,
+			     Elf32_Addr v)
+{
+	return 0;
+}
+
+static int apply_r_mips_gprel16(struct module *me, uint32_t *location,
+				Elf32_Addr v)
+{
+	int rel;
+
+	if( !(*location & 0xffff) ) {
+		rel = (int)v - gp_addr;
+	}
+	else {
+		/* .sbss + gp(relative) + offset */
+		/* kludge! */
+		rel =  (int)(short)((int)v + gp_offs +
+				    (int)(short)(*location & 0xffff) - gp_addr);
+	}
+
+	if( (rel > 32768) || (rel < -32768) ) {
+		printk(KERN_ERR
+		       "apply_r_mips_gprel16: relative address out of range 0x%x %d\n",
+		       rel, rel);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & 0xffff0000) | (rel & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_pc16(struct module *me, uint32_t *location,
+			     Elf32_Addr v)
+{
+	int rel;
+	rel = (((unsigned int)v - (unsigned int)location));
+	rel >>= 2;		// because the offset is in _instructions_ not bytes.
+	rel -= 1;		// and one instruction less due to the branch delay slot.
+
+	if( (rel > 32768) || (rel < -32768) ) {
+		printk(KERN_ERR
+		       "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & 0xffff0000) | (rel & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_32(struct module *me, uint32_t *location,
+			   Elf32_Addr v)
+{
+	*location += v;
+
+	return 0;
+}
+
+static int apply_r_mips_26(struct module *me, uint32_t *location,
+			   Elf32_Addr v)
+{
+	if (v % 4) {
+		printk(KERN_ERR "module %s: dangerous relocation mod4\n", me->name);
+		return -ENOEXEC;
+	}
+
+/* Not desperately convinced this is a good check of an overflow condition
+   anyway. But it gets in the way of handling undefined weak symbols which
+   we want to set to zero.
+   if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+   printk(KERN_ERR
+   "module %s: relocation overflow\n",
+   me->name);
+   return -ENOEXEC;
+   }
+*/
+
+	*location = (*location & ~0x03ffffff) |
+		((*location + (v >> 2)) & 0x03ffffff);
+	return 0;
+}
+
+static int apply_r_mips_hi16(struct module *me, uint32_t *location,
+			     Elf32_Addr v)
+{
+	struct mips_hi16 *n;
+
+	/*
+	 * We cannot relocate this one now because we don't know the value of
+	 * the carry we need to add.  Save the information, and let LO16 do the
+	 * actual relocation.
+	 */
+	n = kmalloc(sizeof *n, GFP_KERNEL);
+	if (!n)
+		return -ENOMEM;
+
+	n->addr = location;
+	n->value = v;
+	n->next = mips_hi16_list;
+	mips_hi16_list = n;
+
+	return 0;
+}
+
+static int apply_r_mips_lo16(struct module *me, uint32_t *location,
+			     Elf32_Addr v)
+{
+	unsigned long insnlo = *location;
+	Elf32_Addr val, vallo;
+
+	/* Sign extend the addend we extract from the lo insn.  */
+	vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+	if (mips_hi16_list != NULL) {
+		struct mips_hi16 *l;
+
+		l = mips_hi16_list;
+		while (l != NULL) {
+			struct mips_hi16 *next;
+			unsigned long insn;
+
+			/*
+			 * The value for the HI16 had best be the same.
+			 */
+			if (v != l->value) {
+				printk("%d != %d\n", v, l->value);
+				goto out_danger;
+			}
+
+
+			/*
+			 * Do the HI16 relocation.  Note that we actually don't
+			 * need to know anything about the LO16 itself, except
+			 * where to find the low 16 bits of the addend needed
+			 * by the LO16.
+			 */
+			insn = *l->addr;
+			val = ((insn & 0xffff) << 16) + vallo;
+			val += v;
+
+			/*
+			 * Account for the sign extension that will happen in
+			 * the low bits.
+			 */
+			val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
+
+			insn = (insn & ~0xffff) | val;
+			*l->addr = insn;
+
+			next = l->next;
+			kfree(l);
+			l = next;
+		}
+
+		mips_hi16_list = NULL;
+	}
+
+	/*
+	 * Ok, we're done with the HI16 relocs.  Now deal with the LO16.
+	 */
+	val = v + vallo;
+	insnlo = (insnlo & ~0xffff) | (val & 0xffff);
+	*location = insnlo;
+
+	return 0;
+
+out_danger:
+	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+
+	return -ENOEXEC;
+}
+
+static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
+				Elf32_Addr v) = {
+	[R_MIPS_NONE]	= apply_r_mips_none,
+	[R_MIPS_32]	= apply_r_mips_32,
+	[R_MIPS_26]	= apply_r_mips_26,
+	[R_MIPS_HI16]	= apply_r_mips_hi16,
+	[R_MIPS_LO16]	= apply_r_mips_lo16,
+	[R_MIPS_GPREL16] = apply_r_mips_gprel16,
+	[R_MIPS_PC16] = apply_r_mips_pc16
+};
+
+
+int apply_relocations(Elf32_Shdr *sechdrs,
+		      const char *strtab,
+		      unsigned int symindex,
+		      unsigned int relsec,
+		      struct module *me)
+{
+	Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+	unsigned int i;
+	Elf32_Addr v;
+	int res;
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		Elf32_Word r_info = rel[i].r_info;
+
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(r_info);
+
+		if (!sym->st_value) {
+			printk(KERN_DEBUG "%s: undefined weak symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			/* just print the warning, dont barf */
+		}
+
+		v = sym->st_value;
+
+		res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
+		if( res ) {
+			printk(KERN_DEBUG
+			       "relocation error 0x%x sym refer <%s> value 0x%x "
+			       "type 0x%x r_info 0x%x\n",
+			       (unsigned int)location, strtab + sym->st_name, v,
+			       r_info, ELF32_R_TYPE(r_info));
+		}
+
+		if (res)
+			return res;
+	}
+
+	return 0;
+}
+
+void save_gp_address(unsigned int secbase, unsigned int rel)
+{
+	gp_addr = secbase + rel;
+	gp_offs = gp_addr - (secbase & 0xffff0000);
+}
+/* end module-elf32.c */
+
+
+
+/* Change all symbols so that sh_value encodes the pointer directly. */
+static int simplify_symbols(Elf_Shdr * sechdrs,
+			    unsigned int symindex,
+			    const char *strtab,
+			    const char *secstrings,
+			    unsigned int nsecs, struct module *mod)
+{
+	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
+	unsigned long secbase, bssbase = 0;
+	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+	int ret = 0, size;
+
+	/* find the .bss section for COMMON symbols */
+	for (i = 0; i < nsecs; i++) {
+		if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0)
+			bssbase = sechdrs[i].sh_addr;
+	}
+
+	for (i = 1; i < n; i++) {
+		switch (sym[i].st_shndx) {
+		case SHN_COMMON:
+			/* Allocate space for the symbol in the .bss section. st_value is currently size.
+			   We want it to have the address of the symbol. */
+
+			size = sym[i].st_value;
+			sym[i].st_value = bssbase;
+
+			bssbase += size;
+			break;
+
+		case SHN_ABS:
+			/* Don't need to do anything */
+			break;
+
+		case SHN_UNDEF:
+			/* ret = -ENOENT; */
+			break;
+
+		case SHN_MIPS_SCOMMON:
+
+			printk(KERN_DEBUG
+			       "simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n",
+			       strtab + sym[i].st_name, sym[i].st_shndx);
+
+			// .sbss section
+			break;
+
+		default:
+			secbase = sechdrs[sym[i].st_shndx].sh_addr;
+
+			if (strncmp(strtab + sym[i].st_name, "_gp", 3) == 0) {
+				save_gp_address(secbase, sym[i].st_value);
+			}
+
+			sym[i].st_value += secbase;
+			break;
+		}
+
+	}
+
+	return ret;
+}
+
+#ifdef DEBUG_ELFLOADER
+static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,
+			    const char *strtab, struct module *mod)
+{
+	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
+	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+
+	printk(KERN_DEBUG "dump_elfsymbols: n %d\n", n);
+	for (i = 1; i < n; i++) {
+		printk(KERN_DEBUG " i %d name <%s> 0x%x\n", i,
+		       strtab + sym[i].st_name, sym[i].st_value);
+	}
+}
+#endif
+
+static void dump_tc(struct tc *t)
+{
+	printk(KERN_WARNING "VPE: TC index %d TCStatus 0x%lx halt 0x%lx\n",
+	       t->index, read_tc_c0_tcstatus(), read_tc_c0_tchalt());
+	printk(KERN_WARNING "VPE: tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+}
+
+static void dump_tclist(void)
+{
+	struct tc *t;
+
+	list_for_each_entry(t, &vpecontrol.tc_list, list) {
+		dump_tc(t);
+	}
+}
+
+/* We are prepared so configure and start the VPE... */
+int vpe_run(vpe_t * v)
+{
+	unsigned long val;
+	struct tc *t;
+
+	/* check we are the Master VPE */
+	val = read_c0_vpeconf0();
+	if (!(val & VPECONF0_MVP)) {
+		printk(KERN_WARNING
+		       "VPE: only Master VPE's are allowed to configure MT\n");
+		return -1;
+	}
+
+	/* disable MT (using dvpe) */
+	dvpe();
+
+	/* Put MVPE's into 'configuration state' */
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	if (!list_empty(&v->tc)) {
+		if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+			printk(KERN_WARNING "VPE: TC %d is already in use.\n",
+			       t->index);
+			return -ENOEXEC;
+		}
+	} else {
+		printk(KERN_WARNING "VPE: No TC's associated with VPE %d\n",
+		       v->minor);
+		return -ENOEXEC;
+	}
+
+	settc(t->index);
+
+	val = read_vpe_c0_vpeconf0();
+
+	/* should check it is halted, and not activated */
+	if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {
+		printk(KERN_WARNING "VPE: TC %d is already doing something!\n",
+		       t->index);
+
+		dump_tclist();
+		return -ENOEXEC;
+	}
+
+	/* Write the address we want it to start running from in the TCPC register. */
+	write_tc_c0_tcrestart((unsigned long)v->__start);
+
+	/* write the sivc_info address to tccontext */
+	write_tc_c0_tccontext((unsigned long)0);
+
+	/* Set up the XTC bit in vpeconf0 to point at our tc */
+	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (t->index << VPECONF0_XTC_SHIFT));
+
+	/* mark the TC as activated, not interrupt exempt and not dynamically allocatable */
+	val = read_tc_c0_tcstatus();
+	val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
+	write_tc_c0_tcstatus(val);
+
+	write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
+
+	/* set up VPE1 */
+	write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);	// no multiple TC's
+	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);	// enable this VPE
+
+	/*
+	 * The sde-kit passes 'memsize' to __start in $a3, so set something
+	 * here...
+	 * Or set $a3 (register 7) to zero and define DFLT_STACK_SIZE and
+	 * DFLT_HEAP_SIZE when you compile your program
+	 */
+
+	mttgpr(7, 0);
+
+	/* set config to be the same as vpe0, particularly kseg0 coherency alg */
+	write_vpe_c0_config(read_c0_config());
+
+	/* clear out any left overs from a previous program */
+	write_vpe_c0_cause(0);
+
+	/* take system out of configuration state */
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	/* clear interrupts enabled IE, ERL, EXL, and KSU from c0 status */
+	write_vpe_c0_status(read_vpe_c0_status() & ~(ST0_ERL | ST0_KSU | ST0_IE | ST0_EXL));
+
+	/* set it running */
+	evpe(EVPE_ENABLE);
+
+	return 0;
+}
+
+static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs,
+				      unsigned int symindex, const char *strtab,
+				      struct module *mod)
+{
+	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
+	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+
+	for (i = 1; i < n; i++) {
+		if (strcmp(strtab + sym[i].st_name, "__start") == 0) {
+			v->__start = sym[i].st_value;
+		}
+
+		if (strcmp(strtab + sym[i].st_name, "vpe_shared") == 0) {
+			v->shared_ptr = (void *)sym[i].st_value;
+		}
+	}
+
+	return 0;
+}
+
+/* Allocates a VPE with some program code space(the load address), copies the contents
+   of the program (p)buffer performing relocatations/etc, free's it when finished.
+*/
+int vpe_elfload(vpe_t * v)
+{
+	Elf_Ehdr *hdr;
+	Elf_Shdr *sechdrs;
+	long err = 0;
+	char *secstrings, *strtab = NULL;
+	unsigned int len, i, symindex = 0, strindex = 0;
+
+	struct module mod;	// so we can re-use the relocations code
+
+	memset(&mod, 0, sizeof(struct module));
+	strcpy(mod.name, "VPE dummy prog module");
+
+	hdr = (Elf_Ehdr *) v->pbuffer;
+	len = v->plen;
+
+	/* Sanity checks against insmoding binaries or wrong arch,
+	   weird elf version */
+	if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
+	    || hdr->e_type != ET_REL || !elf_check_arch(hdr)
+	    || hdr->e_shentsize != sizeof(*sechdrs)) {
+		printk(KERN_WARNING
+		       "VPE program, wrong arch or weird elf version\n");
+
+		return -ENOEXEC;
+	}
+
+	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
+		printk(KERN_ERR "VPE program length %u truncated\n", len);
+		return -ENOEXEC;
+	}
+
+	/* Convenience variables */
+	sechdrs = (void *)hdr + hdr->e_shoff;
+	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+	sechdrs[0].sh_addr = 0;
+
+	/* And these should exist, but gcc whinges if we don't init them */
+	symindex = strindex = 0;
+
+	for (i = 1; i < hdr->e_shnum; i++) {
+
+		if (sechdrs[i].sh_type != SHT_NOBITS
+		    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
+			printk(KERN_ERR "VPE program length %u truncated\n",
+			       len);
+			return -ENOEXEC;
+		}
+
+		/* Mark all sections sh_addr with their address in the
+		   temporary image. */
+		sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+
+		/* Internal symbols and strings. */
+		if (sechdrs[i].sh_type == SHT_SYMTAB) {
+			symindex = i;
+			strindex = sechdrs[i].sh_link;
+			strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+		}
+	}
+
+	layout_sections(&mod, hdr, sechdrs, secstrings);
+
+	v->load_addr = alloc_progmem(mod.core_size);
+	memset(v->load_addr, 0, mod.core_size);
+
+	printk("VPE elf_loader: loading to %p\n", v->load_addr);
+
+	for (i = 0; i < hdr->e_shnum; i++) {
+		void *dest;
+
+		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+			continue;
+
+		dest = v->load_addr + sechdrs[i].sh_entsize;
+
+		if (sechdrs[i].sh_type != SHT_NOBITS)
+			memcpy(dest, (void *)sechdrs[i].sh_addr,
+			       sechdrs[i].sh_size);
+		/* Update sh_addr to point to copy in image. */
+		sechdrs[i].sh_addr = (unsigned long)dest;
+	}
+
+	/* Fix up syms, so that st_value is a pointer to location. */
+	err =
+		simplify_symbols(sechdrs, symindex, strtab, secstrings,
+				 hdr->e_shnum, &mod);
+	if (err < 0) {
+		printk(KERN_WARNING "VPE: unable to simplify symbols\n");
+		goto cleanup;
+	}
+
+	/* Now do relocations. */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		const char *strtab = (char *)sechdrs[strindex].sh_addr;
+		unsigned int info = sechdrs[i].sh_info;
+
+		/* Not a valid relocation section? */
+		if (info >= hdr->e_shnum)
+			continue;
+
+		/* Don't bother with non-allocated sections */
+		if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+			continue;
+
+		if (sechdrs[i].sh_type == SHT_REL)
+			err =
+				apply_relocations(sechdrs, strtab, symindex, i, &mod);
+		else if (sechdrs[i].sh_type == SHT_RELA)
+			err = apply_relocate_add(sechdrs, strtab, symindex, i,
+						 &mod);
+		if (err < 0) {
+			printk(KERN_WARNING
+			       "vpe_elfload: error in relocations err %ld\n",
+			       err);
+			goto cleanup;
+		}
+	}
+
+	/* make sure it's physically written out */
+	flush_icache_range((unsigned long)v->load_addr,
+			   (unsigned long)v->load_addr + v->len);
+
+	if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+
+		printk(KERN_WARNING
+		       "VPE: program doesn't contain __start or vpe_shared symbols\n");
+		err = -ENOEXEC;
+	}
+
+	printk(" elf loaded\n");
+
+cleanup:
+	return err;
+}
+
+static void dump_vpe(vpe_t * v)
+{
+	struct tc *t;
+
+	printk(KERN_DEBUG "VPEControl 0x%lx\n", read_vpe_c0_vpecontrol());
+	printk(KERN_DEBUG "VPEConf0 0x%lx\n", read_vpe_c0_vpeconf0());
+
+	list_for_each_entry(t, &vpecontrol.tc_list, list) {
+		dump_tc(t);
+	}
+}
+
+/* checks for VPE is unused and gets ready to load program	 */
+static int vpe_open(struct inode *inode, struct file *filp)
+{
+	int minor;
+	vpe_t *v;
+
+	/* assume only 1 device at the mo. */
+	if ((minor = MINOR(inode->i_rdev)) != 1) {
+		printk(KERN_WARNING "VPE: only vpe1 is supported\n");
+		return -ENODEV;
+	}
+
+	if ((v = get_vpe(minor)) == NULL) {
+		printk(KERN_WARNING "VPE: unable to get vpe\n");
+		return -ENODEV;
+	}
+
+	if (v->state != VPE_STATE_UNUSED) {
+		unsigned long tmp;
+		struct tc *t;
+
+		printk(KERN_WARNING "VPE: device %d already in use\n", minor);
+
+		dvpe();
+		dump_vpe(v);
+
+		printk(KERN_WARNING "VPE: re-initialising %d\n", minor);
+
+		release_progmem(v->load_addr);
+
+		t = get_tc(minor);
+		settc(minor);
+		tmp = read_tc_c0_tcstatus();
+
+		/* mark not allocated and not dynamically allocatable */
+		tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+		tmp |= TCSTATUS_IXMT;	/* interrupt exempt */
+		write_tc_c0_tcstatus(tmp);
+
+		write_tc_c0_tchalt(TCHALT_H);
+
+	}
+
+	// allocate it so when we get write ops we know it's expected.
+	v->state = VPE_STATE_INUSE;
+
+	/* this of-course trashes what was there before... */
+	v->pbuffer = vmalloc(P_SIZE);
+	v->plen = P_SIZE;
+	v->load_addr = NULL;
+	v->len = 0;
+
+	return 0;
+}
+
+static int vpe_release(struct inode *inode, struct file *filp)
+{
+	int minor, ret = 0;
+	vpe_t *v;
+	Elf_Ehdr *hdr;
+
+	minor = MINOR(inode->i_rdev);
+	if ((v = get_vpe(minor)) == NULL)
+		return -ENODEV;
+
+	// simple case of fire and forget, so tell the VPE to run...
+
+	hdr = (Elf_Ehdr *) v->pbuffer;
+	if (memcmp(hdr->e_ident, ELFMAG, 4) == 0) {
+		if (vpe_elfload(v) >= 0)
+			vpe_run(v);
+		else {
+			printk(KERN_WARNING "VPE: ELF load failed.\n");
+			ret = -ENOEXEC;
+		}
+	} else {
+		printk(KERN_WARNING "VPE: only elf files are supported\n");
+		ret = -ENOEXEC;
+	}
+
+	// cleanup any temp buffers
+	if (v->pbuffer)
+		vfree(v->pbuffer);
+	v->plen = 0;
+	return ret;
+}
+
+static ssize_t vpe_write(struct file *file, const char __user * buffer,
+			 size_t count, loff_t * ppos)
+{
+	int minor;
+	size_t ret = count;
+	vpe_t *v;
+
+	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	if ((v = get_vpe(minor)) == NULL)
+		return -ENODEV;
+
+	if (v->pbuffer == NULL) {
+		printk(KERN_ERR "vpe_write: no pbuffer\n");
+		return -ENOMEM;
+	}
+
+	if ((count + v->len) > v->plen) {
+		printk(KERN_WARNING
+		       "VPE Loader: elf size too big. Perhaps strip uneeded symbols\n");
+		return -ENOMEM;
+	}
+
+	count -= copy_from_user(v->pbuffer + v->len, buffer, count);
+	if (!count) {
+		printk("vpe_write: copy_to_user failed\n");
+		return -EFAULT;
+	}
+
+	v->len += count;
+	return ret;
+}
+
+static struct file_operations vpe_fops = {
+	.owner = THIS_MODULE,
+	.open = vpe_open,
+	.release = vpe_release,
+	.write = vpe_write
+};
+
+/* module wrapper entry points */
+/* give me a vpe */
+vpe_handle vpe_alloc(void)
+{
+	int i;
+	struct vpe *v;
+
+	/* find a vpe */
+	for (i = 1; i < MAX_VPES; i++) {
+		if ((v = get_vpe(i)) != NULL) {
+			v->state = VPE_STATE_INUSE;
+			return v;
+		}
+	}
+	return NULL;
+}
+
+EXPORT_SYMBOL(vpe_alloc);
+
+/* start running from here */
+int vpe_start(vpe_handle vpe, unsigned long start)
+{
+	struct vpe *v = vpe;
+
+	v->__start = start;
+	return vpe_run(v);
+}
+
+EXPORT_SYMBOL(vpe_start);
+
+/* halt it for now */
+int vpe_stop(vpe_handle vpe)
+{
+	struct vpe *v = vpe;
+	struct tc *t;
+	unsigned int evpe_flags;
+
+	evpe_flags = dvpe();
+
+	if ((t = list_entry(v->tc.next, struct tc, tc)) != NULL) {
+
+		settc(t->index);
+		write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
+	}
+
+	evpe(evpe_flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(vpe_stop);
+
+/* I've done with it thank you */
+int vpe_free(vpe_handle vpe)
+{
+	struct vpe *v = vpe;
+	struct tc *t;
+	unsigned int evpe_flags;
+
+	if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+		return -ENOEXEC;
+	}
+
+	evpe_flags = dvpe();
+
+	/* Put MVPE's into 'configuration state' */
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	settc(t->index);
+	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA);
+
+	/* mark the TC unallocated and halt'ed */
+	write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A);
+	write_tc_c0_tchalt(TCHALT_H);
+
+	v->state = VPE_STATE_UNUSED;
+
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+	evpe(evpe_flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(vpe_free);
+
+void *vpe_get_shared(int index)
+{
+	struct vpe *v;
+
+	if ((v = get_vpe(index)) == NULL) {
+		printk(KERN_WARNING "vpe: invalid vpe index %d\n", index);
+		return NULL;
+	}
+
+	return v->shared_ptr;
+}
+
+EXPORT_SYMBOL(vpe_get_shared);
+
+static int __init vpe_module_init(void)
+{
+	struct vpe *v = NULL;
+	struct tc *t;
+	unsigned long val;
+	int i;
+
+	if (!cpu_has_mipsmt) {
+		printk("VPE loader: not a MIPS MT capable processor\n");
+		return -ENODEV;
+	}
+
+	if ((major = register_chrdev(VPE_MAJOR, module_name, &vpe_fops) < 0)) {
+		printk("VPE loader: unable to register character device\n");
+		return -EBUSY;
+	}
+
+	if (major == 0)
+		major = VPE_MAJOR;
+
+	dmt();
+	dvpe();
+
+	/* Put MVPE's into 'configuration state' */
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	/* dump_mtregs(); */
+
+	INIT_LIST_HEAD(&vpecontrol.vpe_list);
+	INIT_LIST_HEAD(&vpecontrol.tc_list);
+
+	val = read_c0_mvpconf0();
+	for (i = 0; i < ((val & MVPCONF0_PTC) + 1); i++) {
+		t = alloc_tc(i);
+
+		/* VPE's */
+		if (i < ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1) {
+			settc(i);
+
+			if ((v = alloc_vpe(i)) == NULL) {
+				printk(KERN_WARNING "VPE: unable to allocate VPE\n");
+				return -ENODEV;
+			}
+
+			list_add(&t->tc, &v->tc);	/* add the tc to the list of this vpe's tc's. */
+
+			/* deactivate all but vpe0 */
+			if (i != 0) {
+				unsigned long tmp = read_vpe_c0_vpeconf0();
+
+				tmp &= ~VPECONF0_VPA;
+
+				/* master VPE */
+				tmp |= VPECONF0_MVP;
+				write_vpe_c0_vpeconf0(tmp);
+			}
+
+			/* disable multi-threading with TC's */
+			write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
+
+			if (i != 0) {
+				write_vpe_c0_status((read_c0_status() &
+						     ~(ST0_IM | ST0_IE | ST0_KSU))
+						    | ST0_CU0);
+
+				/* set config to be the same as vpe0, particularly kseg0 coherency alg */
+				write_vpe_c0_config(read_c0_config());
+			}
+
+		}
+
+		/* TC's */
+		t->pvpe = v;	/* set the parent vpe */
+
+		if (i != 0) {
+			unsigned long tmp;
+
+			/* tc 0 will of course be running.... */
+			if (i == 0)
+				t->state = TC_STATE_RUNNING;
+
+			settc(i);
+
+			/* bind a TC to each VPE, May as well put all excess TC's
+			   on the last VPE */
+			if (i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1))
+				write_tc_c0_tcbind(read_tc_c0_tcbind() |
+						   ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT));
+			else
+				write_tc_c0_tcbind(read_tc_c0_tcbind() | i);
+
+			tmp = read_tc_c0_tcstatus();
+
+			/* mark not allocated and not dynamically allocatable */
+			tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+			tmp |= TCSTATUS_IXMT;	/* interrupt exempt */
+			write_tc_c0_tcstatus(tmp);
+
+			write_tc_c0_tchalt(TCHALT_H);
+		}
+	}
+
+	/* release config state */
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	return 0;
+}
+
+static void __exit vpe_module_exit(void)
+{
+	struct vpe *v, *n;
+
+	list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) {
+		if (v->state != VPE_STATE_UNUSED) {
+			release_vpe(v);
+		}
+	}
+
+	unregister_chrdev(major, module_name);
+}
+
+module_init(vpe_module_init);
+module_exit(vpe_module_exit);
+MODULE_DESCRIPTION("MIPS VPE Loader");
+MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/Kconfig b/arch/mips/lasat/Kconfig
new file mode 100644
index 0000000..1d2ee8a
--- /dev/null
+++ b/arch/mips/lasat/Kconfig
@@ -0,0 +1,15 @@
+config PICVUE
+	tristate "PICVUE LCD display driver"
+	depends on LASAT
+
+config PICVUE_PROC
+	tristate "PICVUE LCD display driver /proc interface"
+	depends on PICVUE
+
+config DS1603
+	bool "DS1603 RTC driver"
+	depends on LASAT
+
+config LASAT_SYSCTL
+	bool "LASAT sysctl interface"
+	depends on LASAT
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index c90da16..852a419 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -71,14 +71,13 @@
 }
 
 static struct hw_interrupt_type lasat_irq_type = {
-	"Lasat",
-	startup_lasat_irq,
-	shutdown_lasat_irq,
-	enable_lasat_irq,
-	disable_lasat_irq,
-	mask_and_ack_lasat_irq,
-	end_lasat_irq,
-	NULL
+	.typename = "Lasat",
+	.startup = startup_lasat_irq,
+	.shutdown = shutdown_lasat_irq,
+	.enable = enable_lasat_irq,
+	.disable = disable_lasat_irq,
+	.ack = mask_and_ack_lasat_irq,
+	.end = end_lasat_irq,
 };
 
 static inline int ls1bit32(unsigned int x)
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index f2604fa..dcd819d 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -155,7 +155,7 @@
 }
 #endif
 
-static int __init lasat_setup(void)
+void __init plat_setup(void)
 {
 	int i;
 	lasat_misc  = &lasat_misc_info[mips_machtype];
@@ -185,8 +185,4 @@
 	change_c0_status(ST0_BEV,0);
 
 	prom_printf("Lasat specific initialization complete\n");
-
-        return 0;
 }
-
-early_initcall(lasat_setup);
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
index 019ac8f..46519f4 100644
--- a/arch/mips/lib-32/dump_tlb.c
+++ b/arch/mips/lib-32/dump_tlb.c
@@ -20,16 +20,25 @@
 static inline const char *msk2str(unsigned int mask)
 {
 	switch (mask) {
-	case PM_4K:	return "4kb";
-	case PM_16K:	return "16kb";
-	case PM_64K:	return "64kb";
-	case PM_256K:	return "256kb";
+	case PM_4K:
+		return "4kb";
+	case PM_16K:
+		return "16kb";
+	case PM_64K:
+		return "64kb";
+	case PM_256K:
+		return "256kb";
 #ifndef CONFIG_CPU_VR41XX
-	case PM_1M:	return "1Mb";
-	case PM_4M:	return "4Mb";
-	case PM_16M:	return "16Mb";
-	case PM_64M:	return "64Mb";
-	case PM_256M:	return "256Mb";
+	case PM_1M:
+		return "1Mb";
+	case PM_4M:
+		return "4Mb";
+	case PM_16M:
+		return "16Mb";
+	case PM_64M:
+		return "64Mb";
+	case PM_256M:
+		return "256Mb";
 #endif
 	}
 
@@ -47,7 +56,7 @@
 	unsigned int pagemask, c0, c1, asid;
 	unsigned long long entrylo0, entrylo1;
 	unsigned long entryhi;
-	int	i;
+	int i;
 
 	asid = read_c0_entryhi() & 0xff;
 
@@ -58,7 +67,7 @@
 		tlb_read();
 		BARRIER();
 		pagemask = read_c0_pagemask();
-		entryhi  = read_c0_entryhi();
+		entryhi = read_c0_entryhi();
 		entrylo0 = read_c0_entrylo0();
 		entrylo1 = read_c0_entrylo1();
 
@@ -78,13 +87,11 @@
 			printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
 			       (entrylo0 << 6) & PAGE_MASK, c0,
 			       (entrylo0 & 4) ? 1 : 0,
-			       (entrylo0 & 2) ? 1 : 0,
-			       (entrylo0 & 1));
+			       (entrylo0 & 2) ? 1 : 0, (entrylo0 & 1));
 			printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
 			       (entrylo1 << 6) & PAGE_MASK, c1,
 			       (entrylo1 & 4) ? 1 : 0,
-			       (entrylo1 & 2) ? 1 : 0,
-			       (entrylo1 & 1));
+			       (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1));
 			printk("\n");
 		}
 	}
@@ -99,7 +106,7 @@
 
 void dump_tlb_wired(void)
 {
-	int	wired;
+	int wired;
 
 	wired = read_c0_wired();
 	printk("Wired: %d", wired);
@@ -138,9 +145,10 @@
 
 void dump_list_process(struct task_struct *t, void *address)
 {
-	pgd_t	*page_dir, *pgd;
-	pmd_t	*pmd;
-	pte_t	*pte, page;
+	pgd_t *page_dir, *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte, page;
 	unsigned long addr, val;
 
 	addr = (unsigned long) address;
@@ -152,21 +160,27 @@
 
 	if (addr > KSEG0)
 		page_dir = pgd_offset_k(0);
-	else
+	else if (t->mm) {
 		page_dir = pgd_offset(t->mm, 0);
-	printk("page_dir == %08x\n", (unsigned int) page_dir);
+		printk("page_dir == %08x\n", (unsigned int) page_dir);
+	} else
+		printk("Current thread has no mm\n");
 
 	if (addr > KSEG0)
 		pgd = pgd_offset_k(addr);
-	else
+	else if (t->mm) {
 		pgd = pgd_offset(t->mm, addr);
-	printk("pgd == %08x, ", (unsigned int) pgd);
+		printk("pgd == %08x, ", (unsigned int) pgd);
+		pud = pud_offset(pgd, addr);
+		printk("pud == %08x, ", (unsigned int) pud);
 
-	pmd = pmd_offset(pgd, addr);
-	printk("pmd == %08x, ", (unsigned int) pmd);
+		pmd = pmd_offset(pud, addr);
+		printk("pmd == %08x, ", (unsigned int) pmd);
 
-	pte = pte_offset(pmd, addr);
-	printk("pte == %08x, ", (unsigned int) pte);
+		pte = pte_offset(pmd, addr);
+		printk("pte == %08x, ", (unsigned int) pte);
+	} else
+		printk("Current thread has no mm\n");
 
 	page = *pte;
 #ifdef CONFIG_64BIT_PHYS_ADDR
@@ -176,14 +190,22 @@
 #endif
 
 	val = pte_val(page);
-	if (val & _PAGE_PRESENT) printk("present ");
-	if (val & _PAGE_READ) printk("read ");
-	if (val & _PAGE_WRITE) printk("write ");
-	if (val & _PAGE_ACCESSED) printk("accessed ");
-	if (val & _PAGE_MODIFIED) printk("modified ");
-	if (val & _PAGE_R4KBUG) printk("r4kbug ");
-	if (val & _PAGE_GLOBAL) printk("global ");
-	if (val & _PAGE_VALID) printk("valid ");
+	if (val & _PAGE_PRESENT)
+		printk("present ");
+	if (val & _PAGE_READ)
+		printk("read ");
+	if (val & _PAGE_WRITE)
+		printk("write ");
+	if (val & _PAGE_ACCESSED)
+		printk("accessed ");
+	if (val & _PAGE_MODIFIED)
+		printk("modified ");
+	if (val & _PAGE_R4KBUG)
+		printk("r4kbug ");
+	if (val & _PAGE_GLOBAL)
+		printk("global ");
+	if (val & _PAGE_VALID)
+		printk("valid ");
 	printk("\n");
 }
 
@@ -194,14 +216,16 @@
 
 unsigned int vtop(void *address)
 {
-	pgd_t	*pgd;
-	pmd_t	*pmd;
-	pte_t	*pte;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
 	unsigned int addr, paddr;
 
 	addr = (unsigned long) address;
 	pgd = pgd_offset(current->mm, addr);
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	pmd = pmd_offset(pud, addr);
 	pte = pte_offset(pmd, addr);
 	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
 	paddr |= (addr & ~PAGE_MASK);
@@ -214,9 +238,9 @@
 	int i;
 
 	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
+		printk("*%08lx == %08lx, ", (unsigned long) p, *p);
 		p++;
-		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
+		printk("*%08lx == %08lx\n", (unsigned long) p, *p);
 		p++;
 	}
 }
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
index a878224..4f2cb74 100644
--- a/arch/mips/lib-32/r3k_dump_tlb.c
+++ b/arch/mips/lib-32/r3k_dump_tlb.c
@@ -105,6 +105,7 @@
 void dump_list_process(struct task_struct *t, void *address)
 {
 	pgd_t	*page_dir, *pgd;
+	pud_t	*pud;
 	pmd_t	*pmd;
 	pte_t	*pte, page;
 	unsigned int addr;
@@ -121,7 +122,10 @@
 	pgd = pgd_offset(t->mm, addr);
 	printk("pgd == %08x, ", (unsigned int) pgd);
 
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	printk("pud == %08x, ", (unsigned int) pud);
+
+	pmd = pmd_offset(pud, addr);
 	printk("pmd == %08x, ", (unsigned int) pmd);
 
 	pte = pte_offset(pmd, addr);
@@ -149,13 +153,15 @@
 unsigned int vtop(void *address)
 {
 	pgd_t	*pgd;
+	pud_t	*pud;
 	pmd_t	*pmd;
 	pte_t	*pte;
 	unsigned int addr, paddr;
 
 	addr = (unsigned long) address;
 	pgd = pgd_offset(current->mm, addr);
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	pmd = pmd_offset(pud, addr);
 	pte = pte_offset(pmd, addr);
 	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
 	paddr |= (addr & ~PAGE_MASK);
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
index 42f88e0..11a5f01 100644
--- a/arch/mips/lib-64/dump_tlb.c
+++ b/arch/mips/lib-64/dump_tlb.c
@@ -140,6 +140,7 @@
 void dump_list_process(struct task_struct *t, void *address)
 {
 	pgd_t	*page_dir, *pgd;
+	pud_t	*pud;
 	pmd_t	*pmd;
 	pte_t	*pte, page;
 	unsigned long addr, val;
@@ -155,7 +156,10 @@
 	pgd = pgd_offset(t->mm, addr);
 	printk("pgd == %016lx\n", (unsigned long) pgd);
 
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	printk("pud == %016lx\n", (unsigned long) pud);
+
+	pmd = pmd_offset(pud, addr);
 	printk("pmd == %016lx\n", (unsigned long) pmd);
 
 	pte = pte_offset(pmd, addr);
@@ -184,13 +188,15 @@
 unsigned int vtop(void *address)
 {
 	pgd_t	*pgd;
+	pud_t	*pud;
 	pmd_t	*pmd;
 	pte_t	*pte;
 	unsigned int addr, paddr;
 
 	addr = (unsigned long) address;
 	pgd = pgd_offset(current->mm, addr);
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	pmd = pmd_offset(pud, addr);
 	pte = pte_offset(pmd, addr);
 	paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
 	paddr |= (addr & ~PAGE_MASK);
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 03730341..cf12caf 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,8 +2,8 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial_copy.o memcpy.o promlib.o \
-	   strlen_user.o strncpy_user.o strnlen_user.o
+lib-y	+= csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \
+	   strnlen_user.o uncached.o
 
 obj-y	+= iomap.o
 
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
index ffed0a6..6e9f366 100644
--- a/arch/mips/lib/csum_partial_copy.c
+++ b/arch/mips/lib/csum_partial_copy.c
@@ -16,8 +16,8 @@
 /*
  * copy while checksumming, otherwise like csum_partial
  */
-unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
-	int len, unsigned int sum)
+unsigned int csum_partial_copy_nocheck(const unsigned char *src,
+	unsigned char *dst, int len, unsigned int sum)
 {
 	/*
 	 * It's 2:30 am and I don't feel like doing it real ...
@@ -33,8 +33,8 @@
  * Copy from userspace and compute checksum.  If we catch an exception
  * then zero the rest of the buffer.
  */
-unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
-	int len, unsigned int sum, int *err_ptr)
+unsigned int csum_partial_copy_from_user (const unsigned char __user *src,
+	unsigned char *dst, int len, unsigned int sum, int *err_ptr)
 {
 	int missing;
 
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index a78865f..7f9aafa 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -13,6 +13,21 @@
  * Mnemonic names for arguments to memcpy/__copy_user
  */
 #include <linux/config.h>
+
+/*
+ * Hack to resolve longstanding prefetch issue
+ *
+ * Prefetching may be fatal on some systems if we're prefetching beyond the
+ * end of memory on some systems.  It's also a seriously bad idea on non
+ * dma-coherent systems.
+ */
+#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27)
+#undef CONFIG_CPU_HAS_PREFETCH
+#endif
+#ifdef CONFIG_MIPS_MALTA
+#undef CONFIG_CPU_HAS_PREFETCH
+#endif
+
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/regdef.h>
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c
new file mode 100644
index 0000000..98ce89f
--- /dev/null
+++ b/arch/mips/lib/uncached.c
@@ -0,0 +1,76 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Thiemo Seufer
+ * Copyright (C) 2005  MIPS Technologies, Inc.  All rights reserved.
+ *	Author: Maciej W. Rozycki <macro@mips.com>
+ */
+
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/bug.h>
+
+#ifndef CKSEG2
+#define CKSEG2 CKSSEG
+#endif
+#ifndef TO_PHYS_MASK
+#define TO_PHYS_MASK -1
+#endif
+
+/*
+ * FUNC is executed in one of the uncached segments, depending on its
+ * original address as follows:
+ *
+ * 1. If the original address is in CKSEG0 or CKSEG1, then the uncached
+ *    segment used is CKSEG1.
+ * 2. If the original address is in XKPHYS, then the uncached segment
+ *    used is XKPHYS(2).
+ * 3. Otherwise it's a bug.
+ *
+ * The same remapping is done with the stack pointer.  Stack handling
+ * works because we don't handle stack arguments or more complex return
+ * values, so we can avoid sharing the same stack area between a cached
+ * and the uncached mode.
+ */
+unsigned long __init run_uncached(void *func)
+{
+	register long sp __asm__("$sp");
+	register long ret __asm__("$2");
+	long lfunc = (long)func, ufunc;
+	long usp;
+
+	if (sp >= (long)CKSEG0 && sp < (long)CKSEG2)
+		usp = CKSEG1ADDR(sp);
+	else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
+		 (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0))
+		usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
+				     XKPHYS_TO_PHYS((long long)sp));
+	else {
+		BUG();
+		usp = sp;
+	}
+	if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2)
+		ufunc = CKSEG1ADDR(lfunc);
+	else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
+		 (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0))
+		ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
+				       XKPHYS_TO_PHYS((long long)lfunc));
+	else {
+		BUG();
+		ufunc = lfunc;
+	}
+
+	__asm__ __volatile__ (
+		"	move	$16, $sp\n"
+		"	move	$sp, %1\n"
+		"	jalr	%2\n"
+		"	move	$sp, $16"
+		: "=r" (ret)
+		: "r" (usp), "r" (ufunc)
+		: "$16", "$31");
+
+	return ret;
+}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 99c5506..aa5818a 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -70,7 +70,7 @@
 
 /* Further private data for which no space exists in mips_fpu_soft_struct */
 
-struct mips_fpu_emulator_private fpuemuprivate;
+struct mips_fpu_emulator_stats fpuemustats;
 
 /* Control registers */
 
@@ -79,7 +79,17 @@
 
 /* Convert Mips rounding mode (0..3) to IEEE library modes. */
 static const unsigned char ieee_rm[4] = {
-	IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+	[FPU_CSR_RN] = IEEE754_RN,
+	[FPU_CSR_RZ] = IEEE754_RZ,
+	[FPU_CSR_RU] = IEEE754_RU,
+	[FPU_CSR_RD] = IEEE754_RD,
+};
+/* Convert IEEE library modes to Mips rounding mode (0..3). */
+static const unsigned char mips_rm[4] = {
+	[IEEE754_RN] = FPU_CSR_RN,
+	[IEEE754_RZ] = FPU_CSR_RZ,
+	[IEEE754_RD] = FPU_CSR_RD,
+	[IEEE754_RU] = FPU_CSR_RU,
 };
 
 #if __mips >= 4
@@ -196,11 +206,11 @@
 static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
 {
 	mips_instruction ir;
-	vaddr_t emulpc, contpc;
+	void * emulpc, *contpc;
 	unsigned int cond;
 
-	if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
-		fpuemuprivate.stats.errors++;
+	if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+		fpuemustats.errors++;
 		return SIGBUS;
 	}
 
@@ -221,41 +231,39 @@
 		 * Linux MIPS branch emulator operates on context, updating the
 		 * cp0_epc.
 		 */
-		emulpc = REG_TO_VA(xcp->cp0_epc + 4);	/* Snapshot emulation target */
+		emulpc = (void *) (xcp->cp0_epc + 4);	/* Snapshot emulation target */
 
 		if (__compute_return_epc(xcp)) {
 #ifdef CP1DBG
 			printk("failed to emulate branch at %p\n",
-				REG_TO_VA(xcp->cp0_epc));
+				(void *) (xcp->cp0_epc));
 #endif
 			return SIGILL;
 		}
-		if (get_user(ir, (mips_instruction *) emulpc)) {
-			fpuemuprivate.stats.errors++;
+		if (get_user(ir, (mips_instruction __user *) emulpc)) {
+			fpuemustats.errors++;
 			return SIGBUS;
 		}
 		/* __compute_return_epc() will have updated cp0_epc */
-		contpc = REG_TO_VA xcp->cp0_epc;
+		contpc = (void *)  xcp->cp0_epc;
 		/* In order not to confuse ptrace() et al, tweak context */
-		xcp->cp0_epc = VA_TO_REG emulpc - 4;
-	}
-	else {
-		emulpc = REG_TO_VA xcp->cp0_epc;
-		contpc = REG_TO_VA(xcp->cp0_epc + 4);
+		xcp->cp0_epc = (unsigned long) emulpc - 4;
+	} else {
+		emulpc = (void *)  xcp->cp0_epc;
+		contpc = (void *) (xcp->cp0_epc + 4);
 	}
 
       emul:
-	fpuemuprivate.stats.emulated++;
+	fpuemustats.emulated++;
 	switch (MIPSInst_OPCODE(ir)) {
-#ifndef SINGLE_ONLY_FPU
 	case ldc1_op:{
-		u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
 			MIPSInst_SIMM(ir));
 		u64 val;
 
-		fpuemuprivate.stats.loads++;
+		fpuemustats.loads++;
 		if (get_user(val, va)) {
-			fpuemuprivate.stats.errors++;
+			fpuemustats.errors++;
 			return SIGBUS;
 		}
 		DITOREG(val, MIPSInst_RT(ir));
@@ -263,55 +271,42 @@
 	}
 
 	case sdc1_op:{
-		u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
 			MIPSInst_SIMM(ir));
 		u64 val;
 
-		fpuemuprivate.stats.stores++;
+		fpuemustats.stores++;
 		DIFROMREG(val, MIPSInst_RT(ir));
 		if (put_user(val, va)) {
-			fpuemuprivate.stats.errors++;
+			fpuemustats.errors++;
 			return SIGBUS;
 		}
 		break;
 	}
-#endif
 
 	case lwc1_op:{
-		u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+		u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
 			MIPSInst_SIMM(ir));
 		u32 val;
 
-		fpuemuprivate.stats.loads++;
+		fpuemustats.loads++;
 		if (get_user(val, va)) {
-			fpuemuprivate.stats.errors++;
+			fpuemustats.errors++;
 			return SIGBUS;
 		}
-#ifdef SINGLE_ONLY_FPU
-		if (MIPSInst_RT(ir) & 1) {
-			/* illegal register in single-float mode */
-			return SIGILL;
-		}
-#endif
 		SITOREG(val, MIPSInst_RT(ir));
 		break;
 	}
 
 	case swc1_op:{
-		u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+		u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] +
 			MIPSInst_SIMM(ir));
 		u32 val;
 
-		fpuemuprivate.stats.stores++;
-#ifdef SINGLE_ONLY_FPU
-		if (MIPSInst_RT(ir) & 1) {
-			/* illegal register in single-float mode */
-			return SIGILL;
-		}
-#endif
+		fpuemustats.stores++;
 		SIFROMREG(val, MIPSInst_RT(ir));
 		if (put_user(val, va)) {
-			fpuemuprivate.stats.errors++;
+			fpuemustats.errors++;
 			return SIGBUS;
 		}
 		break;
@@ -320,7 +315,7 @@
 	case cop1_op:
 		switch (MIPSInst_RS(ir)) {
 
-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64)
 		case dmfc_op:
 			/* copregister fs -> gpr[rt] */
 			if (MIPSInst_RT(ir) != 0) {
@@ -337,12 +332,6 @@
 
 		case mfc_op:
 			/* copregister rd -> gpr[rt] */
-#ifdef SINGLE_ONLY_FPU
-			if (MIPSInst_RD(ir) & 1) {
-				/* illegal register in single-float mode */
-				return SIGILL;
-			}
-#endif
 			if (MIPSInst_RT(ir) != 0) {
 				SIFROMREG(xcp->regs[MIPSInst_RT(ir)],
 					MIPSInst_RD(ir));
@@ -351,12 +340,6 @@
 
 		case mtc_op:
 			/* copregister rd <- rt */
-#ifdef SINGLE_ONLY_FPU
-			if (MIPSInst_RD(ir) & 1) {
-				/* illegal register in single-float mode */
-				return SIGILL;
-			}
-#endif
 			SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
 			break;
 
@@ -369,9 +352,10 @@
 			}
 			if (MIPSInst_RD(ir) == FPCREG_CSR) {
 				value = ctx->fcr31;
+				value = (value & ~0x3) | mips_rm[value & 0x3];
 #ifdef CSRTRACE
 				printk("%p gpr[%d]<-csr=%08x\n",
-					REG_TO_VA(xcp->cp0_epc),
+					(void *) (xcp->cp0_epc),
 					MIPSInst_RT(ir), value);
 #endif
 			}
@@ -398,14 +382,13 @@
 			if (MIPSInst_RD(ir) == FPCREG_CSR) {
 #ifdef CSRTRACE
 				printk("%p gpr[%d]->csr=%08x\n",
-					REG_TO_VA(xcp->cp0_epc),
+					(void *) (xcp->cp0_epc),
 					MIPSInst_RT(ir), value);
 #endif
-				ctx->fcr31 = value;
-				/* copy new rounding mode and
-				   flush bit to ieee library state! */
-				ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;
-				ieee754_csr.rm = ieee_rm[value & 0x3];
+				value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
+				ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
+				/* convert to ieee library modes */
+				ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3];
 			}
 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
 				return SIGFPE;
@@ -445,20 +428,20 @@
 				 * instruction
 				 */
 				xcp->cp0_epc += 4;
-				contpc = REG_TO_VA
+				contpc = (void *)
 					(xcp->cp0_epc +
 					(MIPSInst_SIMM(ir) << 2));
 
-				if (get_user(ir, (mips_instruction *)
-						REG_TO_VA xcp->cp0_epc)) {
-					fpuemuprivate.stats.errors++;
+				if (get_user(ir,
+				    (mips_instruction __user *) xcp->cp0_epc)) {
+					fpuemustats.errors++;
 					return SIGBUS;
 				}
 
 				switch (MIPSInst_OPCODE(ir)) {
 				case lwc1_op:
 				case swc1_op:
-#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+#if (__mips >= 2 || defined(__mips64))
 				case ldc1_op:
 				case sdc1_op:
 #endif
@@ -480,7 +463,7 @@
 				 * Single step the non-cp1
 				 * instruction in the dslot
 				 */
-				return mips_dsemul(xcp, ir, VA_TO_REG contpc);
+				return mips_dsemul(xcp, ir, (unsigned long) contpc);
 			}
 			else {
 				/* branch not taken */
@@ -539,8 +522,9 @@
 	}
 
 	/* we did it !! */
-	xcp->cp0_epc = VA_TO_REG(contpc);
+	xcp->cp0_epc = (unsigned long) contpc;
 	xcp->cp0_cause &= ~CAUSEF_BD;
+
 	return 0;
 }
 
@@ -570,7 +554,7 @@
 static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \
     ieee754##p t) \
 { \
-	struct ieee754_csr ieee754_csr_save; \
+	struct _ieee754_csr ieee754_csr_save; \
 	s = f1 (s, t); \
 	ieee754_csr_save = ieee754_csr; \
 	s = f2 (s, r); \
@@ -616,54 +600,38 @@
 {
 	unsigned rcsr = 0;	/* resulting csr */
 
-	fpuemuprivate.stats.cp1xops++;
+	fpuemustats.cp1xops++;
 
 	switch (MIPSInst_FMA_FFMT(ir)) {
 	case s_fmt:{		/* 0 */
 
 		ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
 		ieee754sp fd, fr, fs, ft;
-		u32 *va;
+		u32 __user *va;
 		u32 val;
 
 		switch (MIPSInst_FUNC(ir)) {
 		case lwxc1_op:
-			va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemuprivate.stats.loads++;
+			fpuemustats.loads++;
 			if (get_user(val, va)) {
-				fpuemuprivate.stats.errors++;
+				fpuemustats.errors++;
 				return SIGBUS;
 			}
-#ifdef SINGLE_ONLY_FPU
-			if (MIPSInst_FD(ir) & 1) {
-				/* illegal register in single-float
-				 * mode
-				 */
-				return SIGILL;
-			}
-#endif
 			SITOREG(val, MIPSInst_FD(ir));
 			break;
 
 		case swxc1_op:
-			va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemuprivate.stats.stores++;
-#ifdef SINGLE_ONLY_FPU
-			if (MIPSInst_FS(ir) & 1) {
-				/* illegal register in single-float
-				 * mode
-				 */
-				return SIGILL;
-			}
-#endif
+			fpuemustats.stores++;
 
 			SIFROMREG(val, MIPSInst_FS(ir));
 			if (put_user(val, va)) {
-				fpuemuprivate.stats.errors++;
+				fpuemustats.errors++;
 				return SIGBUS;
 			}
 			break;
@@ -699,8 +667,6 @@
 				rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
 
 			ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
-			if (ieee754_csr.nod)
-				ctx->fcr31 |= 0x1000000;
 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
 				/*printk ("SIGFPE: fpu csr = %08x\n",
 				   ctx->fcr31); */
@@ -715,34 +681,33 @@
 		break;
 	}
 
-#ifndef SINGLE_ONLY_FPU
 	case d_fmt:{		/* 1 */
 		ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
 		ieee754dp fd, fr, fs, ft;
-		u64 *va;
+		u64 __user *va;
 		u64 val;
 
 		switch (MIPSInst_FUNC(ir)) {
 		case ldxc1_op:
-			va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemuprivate.stats.loads++;
+			fpuemustats.loads++;
 			if (get_user(val, va)) {
-				fpuemuprivate.stats.errors++;
+				fpuemustats.errors++;
 				return SIGBUS;
 			}
 			DITOREG(val, MIPSInst_FD(ir));
 			break;
 
 		case sdxc1_op:
-			va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemuprivate.stats.stores++;
+			fpuemustats.stores++;
 			DIFROMREG(val, MIPSInst_FS(ir));
 			if (put_user(val, va)) {
-				fpuemuprivate.stats.errors++;
+				fpuemustats.errors++;
 				return SIGBUS;
 			}
 			break;
@@ -773,7 +738,6 @@
 		}
 		break;
 	}
-#endif
 
 	case 0x7:		/* 7 */
 		if (MIPSInst_FUNC(ir) != pfetch_op) {
@@ -810,7 +774,7 @@
 #endif
 	} rv;			/* resulting value */
 
-	fpuemuprivate.stats.cp1ops++;
+	fpuemustats.cp1ops++;
 	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
 	case s_fmt:{		/* 0 */
 		union {
@@ -834,7 +798,7 @@
 			goto scopbop;
 
 			/* unary  ops */
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
 		case fsqrt_op:
 			handler.u = ieee754sp_sqrt;
 			goto scopuop;
@@ -913,9 +877,6 @@
 		case fcvts_op:
 			return SIGILL;	/* not defined */
 		case fcvtd_op:{
-#ifdef SINGLE_ONLY_FPU
-			return SIGILL;	/* not defined */
-#else
 			ieee754sp fs;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
@@ -923,7 +884,6 @@
 			rfmt = d_fmt;
 			goto copcsr;
 		}
-#endif
 		case fcvtw_op:{
 			ieee754sp fs;
 
@@ -933,7 +893,7 @@
 			goto copcsr;
 		}
 
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
 		case fround_op:
 		case ftrunc_op:
 		case fceil_op:
@@ -950,7 +910,7 @@
 		}
 #endif /* __mips >= 2 */
 
-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64)
 		case fcvtl_op:{
 			ieee754sp fs;
 
@@ -974,7 +934,7 @@
 			rfmt = l_fmt;
 			goto copcsr;
 		}
-#endif /* __mips64 && !fpu(single) */
+#endif /* defined(__mips64) */
 
 		default:
 			if (MIPSInst_FUNC(ir) >= fcmp_op) {
@@ -1001,7 +961,6 @@
 		break;
 	}
 
-#ifndef SINGLE_ONLY_FPU
 	case d_fmt:{
 		union {
 			ieee754dp(*b) (ieee754dp, ieee754dp);
@@ -1024,7 +983,7 @@
 			goto dcopbop;
 
 			/* unary  ops */
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
 		case fsqrt_op:
 			handler.u = ieee754dp_sqrt;
 			goto dcopuop;
@@ -1108,7 +1067,7 @@
 			goto copcsr;
 		}
 
-#if __mips >= 2 || __mips64
+#if __mips >= 2 || defined(__mips64)
 		case fround_op:
 		case ftrunc_op:
 		case fceil_op:
@@ -1125,7 +1084,7 @@
 		}
 #endif
 
-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64)
 		case fcvtl_op:{
 			ieee754dp fs;
 
@@ -1149,7 +1108,7 @@
 			rfmt = l_fmt;
 			goto copcsr;
 		}
-#endif /* __mips >= 3 && !fpu(single) */
+#endif /* __mips >= 3 */
 
 		default:
 			if (MIPSInst_FUNC(ir) >= fcmp_op) {
@@ -1177,7 +1136,6 @@
 		}
 		break;
 	}
-#endif /* ifndef SINGLE_ONLY_FPU */
 
 	case w_fmt:{
 		ieee754sp fs;
@@ -1189,21 +1147,19 @@
 			rv.s = ieee754sp_fint(fs.bits);
 			rfmt = s_fmt;
 			goto copcsr;
-#ifndef SINGLE_ONLY_FPU
 		case fcvtd_op:
 			/* convert word to double precision real */
 			SPFROMREG(fs, MIPSInst_FS(ir));
 			rv.d = ieee754dp_fint(fs.bits);
 			rfmt = d_fmt;
 			goto copcsr;
-#endif
 		default:
 			return SIGILL;
 		}
 		break;
 	}
 
-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64)
 	case l_fmt:{
 		switch (MIPSInst_FUNC(ir)) {
 		case fcvts_op:
@@ -1256,18 +1212,16 @@
 			ctx->fcr31 &= ~cond;
 		break;
 	}
-#ifndef SINGLE_ONLY_FPU
 	case d_fmt:
 		DPTOREG(rv.d, MIPSInst_FD(ir));
 		break;
-#endif
 	case s_fmt:
 		SPTOREG(rv.s, MIPSInst_FD(ir));
 		break;
 	case w_fmt:
 		SITOREG(rv.w, MIPSInst_FD(ir));
 		break;
-#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)
+#if defined(__mips64)
 	case l_fmt:
 		DITOREG(rv.l, MIPSInst_FD(ir));
 		break;
@@ -1279,10 +1233,10 @@
 	return 0;
 }
 
-int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
+int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 	struct mips_fpu_soft_struct *ctx)
 {
-	gpreg_t oldepc, prevepc;
+	unsigned long oldepc, prevepc;
 	mips_instruction insn;
 	int sig = 0;
 
@@ -1290,19 +1244,24 @@
 	do {
 		prevepc = xcp->cp0_epc;
 
-		if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) {
-			fpuemuprivate.stats.errors++;
+		if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+			fpuemustats.errors++;
 			return SIGBUS;
 		}
 		if (insn == 0)
 			xcp->cp0_epc += 4;	/* skip nops */
 		else {
-			/* Update ieee754_csr. Only relevant if we have a
-			   h/w FPU */
-			ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;
-			ieee754_csr.rm = ieee_rm[ctx->fcr31 & 0x3];
-			ieee754_csr.cx = (ctx->fcr31 >> 12) & 0x1f;
+			/*
+			 * The 'ieee754_csr' is an alias of
+			 * ctx->fcr31.  No need to copy ctx->fcr31 to
+			 * ieee754_csr.  But ieee754_csr.rm is ieee
+			 * library modes. (not mips rounding mode)
+			 */
+			/* convert to ieee library modes */
+			ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
 			sig = cop1Emulate(xcp, ctx);
+			/* revert to mips rounding mode */
+			ieee754_csr.rm = mips_rm[ieee754_csr.rm];
 		}
 
 		if (cpu_has_fpu)
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c
index c35e871..032328c 100644
--- a/arch/mips/math-emu/dp_sqrt.c
+++ b/arch/mips/math-emu/dp_sqrt.c
@@ -37,7 +37,7 @@
 
 ieee754dp ieee754dp_sqrt(ieee754dp x)
 {
-	struct ieee754_csr oldcsr;
+	struct _ieee754_csr oldcsr;
 	ieee754dp y, z, t;
 	unsigned scalx, yh;
 	COMPXDP;
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index aa989c2..8079f3d 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -28,9 +28,6 @@
 #endif
 #define __mips 4
 
-extern struct mips_fpu_emulator_private fpuemuprivate;
-
-
 /*
  * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
  * we have to emulate the instruction in a COP1 branch delay slot.  Do
@@ -52,10 +49,10 @@
 	mips_instruction	emul;
 	mips_instruction	badinst;
 	mips_instruction	cookie;
-	gpreg_t			epc;
+	unsigned long		epc;
 };
 
-int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
+int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 {
 	extern asmlinkage void handle_dsemulret(void);
 	mips_instruction *dsemul_insns;
@@ -91,7 +88,7 @@
 	 */
 
 	/* Ensure that the two instructions are in the same cache line */
-	dsemul_insns = (mips_instruction *) REG_TO_VA ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
+	dsemul_insns = (mips_instruction *) ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
 	fr = (struct emuframe *) dsemul_insns;
 
 	/* Verify that the stack pointer is not competely insane */
@@ -104,11 +101,11 @@
 	err |= __put_user(cpc, &fr->epc);
 
 	if (unlikely(err)) {
-		fpuemuprivate.stats.errors++;
+		fpuemustats.errors++;
 		return SIGBUS;
 	}
 
-	regs->cp0_epc = VA_TO_REG & fr->emul;
+	regs->cp0_epc = (unsigned long) &fr->emul;
 
 	flush_cache_sigtramp((unsigned long)&fr->badinst);
 
@@ -118,7 +115,7 @@
 int do_dsemulret(struct pt_regs *xcp)
 {
 	struct emuframe *fr;
-	gpreg_t epc;
+	unsigned long epc;
 	u32 insn, cookie;
 	int err = 0;
 
@@ -141,7 +138,7 @@
 	err |= __get_user(cookie, &fr->cookie);
 
 	if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) {
-		fpuemuprivate.stats.errors++;
+		fpuemustats.errors++;
 		return 0;
 	}
 
diff --git a/arch/mips/math-emu/dsemul.h b/arch/mips/math-emu/dsemul.h
index dbd85f9..091f0e7 100644
--- a/arch/mips/math-emu/dsemul.h
+++ b/arch/mips/math-emu/dsemul.h
@@ -1,11 +1,5 @@
-typedef long gpreg_t;
-typedef void *vaddr_t;
-
-#define REG_TO_VA (vaddr_t)
-#define VA_TO_REG (gpreg_t)
-
-int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc);
-int do_dsemulret(struct pt_regs *xcp);
+extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc);
+extern int do_dsemulret(struct pt_regs *xcp);
 
 /* Instruction which will always cause an address error */
 #define AdELOAD 0x8c000001	/* lw $0,1($0) */
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c
index f0a364a..a93c45d 100644
--- a/arch/mips/math-emu/ieee754.c
+++ b/arch/mips/math-emu/ieee754.c
@@ -31,6 +31,8 @@
 
 
 #include "ieee754int.h"
+#include "ieee754sp.h"
+#include "ieee754dp.h"
 
 #define DP_EBIAS	1023
 #define DP_EMIN		(-1022)
@@ -40,20 +42,6 @@
 #define SP_EMIN		(-126)
 #define SP_EMAX		127
 
-/* indexed by class */
-const char *const ieee754_cname[] = {
-	"Normal",
-	"Zero",
-	"Denormal",
-	"Infinity",
-	"QNaN",
-	"SNaN",
-};
-
-/* the control status register
-*/
-struct ieee754_csr ieee754_csr;
-
 /* special constants
 */
 
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
index b8772f4..171f177 100644
--- a/arch/mips/math-emu/ieee754.h
+++ b/arch/mips/math-emu/ieee754.h
@@ -1,13 +1,8 @@
-/* single and double precision fp ops
- * missing extended precision.
-*/
 /*
  * MIPS floating point support
  * Copyright (C) 1994-2000 Algorithmics Ltd.
  * http://www.algor.co.uk
  *
- * ########################################################################
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -21,20 +16,18 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * ########################################################################
- */
-
-/**************************************************************************
  *  Nov 7, 2000
  *  Modification to allow integration with Linux kernel
  *
  *  Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
  *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- *************************************************************************/
+ */
+#ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H
+#define __ARCH_MIPS_MATH_EMU_IEEE754_H
 
-#ifdef __KERNEL__
-/* Going from Algorithmics to Linux native environment, add this */
+#include <asm/byteorder.h>
 #include <linux/types.h>
+#include <linux/sched.h>
 
 /*
  * Not very pretty, but the Linux kernel's normal va_list definition
@@ -44,18 +37,7 @@
 #include <stdarg.h>
 #endif
 
-#else
-
-/* Note that __KERNEL__ is taken to mean Linux kernel */
-
-#if #system(OpenBSD)
-#include <machine/types.h>
-#endif
-#include <machine/endian.h>
-
-#endif				/* __KERNEL__ */
-
-#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#ifdef __LITTLE_ENDIAN
 struct ieee754dp_konst {
 	unsigned mantlo:32;
 	unsigned manthi:20;
@@ -86,13 +68,14 @@
 } ieee754sp;
 #endif
 
-#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+#ifdef __BIG_ENDIAN
 struct ieee754dp_konst {
 	unsigned sign:1;
 	unsigned bexp:11;
 	unsigned manthi:20;
 	unsigned mantlo:32;
 };
+
 typedef union _ieee754dp {
 	struct ieee754dp_konst oparts;
 	struct {
@@ -222,7 +205,6 @@
 #define IEEE754_CLASS_INF	0x03
 #define IEEE754_CLASS_SNAN	0x04
 #define IEEE754_CLASS_QNAN	0x05
-extern const char *const ieee754_cname[];
 
 /* exception numbers */
 #define IEEE754_INEXACT			0x01
@@ -251,93 +233,109 @@
 
 /* "normal" comparisons
 */
-static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
 }
 
-static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
 {
 	return ieee754sp_cmp(x, y,
 			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
 }
 
-static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
 }
 
-static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_le(ieee754sp x, ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
 }
 
-static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
 }
 
 
-static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+static inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
 {
 	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
 }
 
-static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
 }
 
-static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
 {
 	return ieee754dp_cmp(x, y,
 			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
 }
 
-static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
 }
 
-static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_le(ieee754dp x, ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
 }
 
-static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
 }
 
-static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+static inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
 {
 	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
 }
 
 
-/* like strtod
-*/
+/*
+ * Like strtod
+ */
 ieee754dp ieee754dp_fstr(const char *s, char **endp);
 char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
 
 
-/* the control status register
-*/
-struct ieee754_csr {
-	unsigned pad:13;
+/*
+ * The control status register
+ */
+struct _ieee754_csr {
+#ifdef __BIG_ENDIAN
+	unsigned pad0:7;
 	unsigned nod:1;		/* set 1 for no denormalised numbers */
-	unsigned cx:5;		/* exceptions this operation */
+	unsigned c:1;		/* condition */
+	unsigned pad1:5;
+	unsigned cx:6;		/* exceptions this operation */
 	unsigned mx:5;		/* exception enable  mask */
 	unsigned sx:5;		/* exceptions total */
 	unsigned rm:2;		/* current rounding mode */
+#endif
+#ifdef __LITTLE_ENDIAN
+	unsigned rm:2;		/* current rounding mode */
+	unsigned sx:5;		/* exceptions total */
+	unsigned mx:5;		/* exception enable  mask */
+	unsigned cx:6;		/* exceptions this operation */
+	unsigned pad1:5;
+	unsigned c:1;		/* condition */
+	unsigned nod:1;		/* set 1 for no denormalised numbers */
+	unsigned pad0:7;
+#endif
 };
-extern struct ieee754_csr ieee754_csr;
+#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.soft.fcr31))
 
-static __inline unsigned ieee754_getrm(void)
+static inline unsigned ieee754_getrm(void)
 {
 	return (ieee754_csr.rm);
 }
-static __inline unsigned ieee754_setrm(unsigned rm)
+static inline unsigned ieee754_setrm(unsigned rm)
 {
 	return (ieee754_csr.rm = rm);
 }
@@ -345,14 +343,14 @@
 /*
  * get current exceptions
  */
-static __inline unsigned ieee754_getcx(void)
+static inline unsigned ieee754_getcx(void)
 {
 	return (ieee754_csr.cx);
 }
 
 /* test for current exception condition
  */
-static __inline int ieee754_cxtest(unsigned n)
+static inline int ieee754_cxtest(unsigned n)
 {
 	return (ieee754_csr.cx & n);
 }
@@ -360,21 +358,21 @@
 /*
  * get sticky exceptions
  */
-static __inline unsigned ieee754_getsx(void)
+static inline unsigned ieee754_getsx(void)
 {
 	return (ieee754_csr.sx);
 }
 
 /* clear sticky conditions
 */
-static __inline unsigned ieee754_clrsx(void)
+static inline unsigned ieee754_clrsx(void)
 {
 	return (ieee754_csr.sx = 0);
 }
 
 /* test for sticky exception condition
  */
-static __inline int ieee754_sxtest(unsigned n)
+static inline int ieee754_sxtest(unsigned n)
 {
 	return (ieee754_csr.sx & n);
 }
@@ -406,52 +404,34 @@
 #define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
 #define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
 
-/* return infinity with given sign
-*/
-#define ieee754dp_inf(sn)	\
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
-#define ieee754dp_zero(sn) \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
-#define ieee754dp_one(sn) \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
-#define ieee754dp_ten(sn) \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
-#define ieee754dp_indef() \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
-#define ieee754dp_max(sn) \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
-#define ieee754dp_min(sn) \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
-#define ieee754dp_mind(sn) \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
-#define ieee754dp_1e31() \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
-#define ieee754dp_1e63() \
-  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+/*
+ * Return infinity with given sign
+ */
+#define ieee754dp_inf(sn)     (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn)	(ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn)	(ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn)	(ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef()	(ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn)	(ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn)	(ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn)	(ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31()	(ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63()	(ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
 
-#define ieee754sp_inf(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
-#define ieee754sp_zero(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
-#define ieee754sp_one(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
-#define ieee754sp_ten(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
-#define ieee754sp_indef() \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
-#define ieee754sp_max(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
-#define ieee754sp_min(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
-#define ieee754sp_mind(sn) \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
-#define ieee754sp_1e31() \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
-#define ieee754sp_1e63() \
-  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+#define ieee754sp_inf(sn)     (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn)	(ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn)	(ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn)	(ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef()	(ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn)	(ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn)	(ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn)	(ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31()	(ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63()	(ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
 
-/* indefinite integer value
-*/
+/*
+ * Indefinite integer value
+ */
 #define ieee754si_indef()	INT_MAX
 #ifdef LONG_LONG_MAX
 #define ieee754di_indef()	LONG_LONG_MAX
@@ -487,3 +467,5 @@
 /* compat */
 #define ieee754dp_fix(x)	ieee754dp_tint(x)
 #define ieee754sp_fix(x)	ieee754sp_tint(x)
+
+#endif /* __ARCH_MIPS_MATH_EMU_IEEE754_H */
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
index 4002f0c..d187ab7 100644
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -27,8 +27,6 @@
 
 #include <asm/fpu_emulator.h>
 
-extern struct mips_fpu_emulator_private fpuemuprivate;
-
 #define SIGNALLING_NAN 0x7ff800007ff80000LL
 
 void fpu_emulator_init_fpu(void)
@@ -65,7 +63,6 @@
 			       &sc->sc_fpregs[i]);
 	}
 	err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
-	err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
 
 	return err;
 }
@@ -81,7 +78,6 @@
 			       &sc->sc_fpregs[i]);
 	}
 	err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
-	err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
 
 	return err;
 }
@@ -102,7 +98,6 @@
 			       &sc->sc_fpregs[i]);
 	}
 	err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
-	err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
 
 	return err;
 }
@@ -118,7 +113,6 @@
 			       &sc->sc_fpregs[i]);
 	}
 	err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
-	err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
 
 	return err;
 }
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index 19d4b07..bc0ebc6 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -76,14 +76,13 @@
 }
 
 static struct hw_interrupt_type atlas_irq_type = {
-	"Atlas",
-	startup_atlas_irq,
-	shutdown_atlas_irq,
-	enable_atlas_irq,
-	disable_atlas_irq,
-	mask_and_ack_atlas_irq,
-	end_atlas_irq,
-	NULL
+	.typename = "Atlas",
+	.startup = startup_atlas_irq,
+	.shutdown = shutdown_atlas_irq,
+	.enable = enable_atlas_irq,
+	.disable = disable_atlas_irq,
+	.ack = mask_and_ack_atlas_irq,
+	.end = end_atlas_irq,
 };
 
 static inline int ls1bit32(unsigned int x)
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 0a1dd9b..625843b 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -50,8 +50,10 @@
 	return "MIPS Atlas";
 }
 
-static int __init atlas_setup(void)
+void __init plat_setup(void)
 {
+	mips_pcibios_init();
+
 	ioport_resource.end = 0x7fffffff;
 
 	serial_init ();
@@ -64,12 +66,8 @@
 	board_time_init = mips_time_init;
 	board_timer_setup = mips_timer_setup;
 	rtc_get_time = mips_rtc_get_time;
-
-	return 0;
 }
 
-early_initcall(atlas_setup);
-
 static void __init serial_init(void)
 {
 #ifdef CONFIG_SERIAL_8250
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index 311155d..eab5a70 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
+ *	All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -22,18 +24,19 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 
-#include <asm/io.h>
 #include <asm/bootinfo.h>
+#include <asm/gt64120.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/generic.h>
-#ifdef CONFIG_MIPS_GT64120
-#include <asm/gt64120.h>
-#endif
-#include <asm/mips-boards/msc01_pci.h>
 #include <asm/mips-boards/bonito64.h>
-#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/msc01_pci.h>
+
 #include <asm/mips-boards/malta.h>
-#endif
 
 #ifdef CONFIG_KGDB
 extern int rs_kgdb_hook(int, int);
@@ -223,8 +226,34 @@
 }
 #endif
 
+void __init mips_nmi_setup (void)
+{
+	void *base;
+	extern char except_vec_nmi;
+
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa80) :
+		(void *)(CAC_BASE + 0x380);
+	memcpy(base, &except_vec_nmi, 0x80);
+	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+void __init mips_ejtag_setup (void)
+{
+	void *base;
+	extern char except_vec_ejtag_debug;
+
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa00) :
+		(void *)(CAC_BASE + 0x300);
+	memcpy(base, &except_vec_ejtag_debug, 0x80);
+	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
 void __init prom_init(void)
 {
+	u32 start, map, mask, data;
+
 	prom_argc = fw_arg0;
 	_prom_argv = (int *) fw_arg1;
 	_prom_envp = (int *) fw_arg2;
@@ -266,12 +295,15 @@
 #else
 		GT_WRITE(GT_PCI0_CMD_OFS, 0);
 #endif
+		/* Fix up PCI I/O mapping if necessary (for Atlas).  */
+		start = GT_READ(GT_PCI0IOLD_OFS);
+		map = GT_READ(GT_PCI0IOREMAP_OFS);
+		if ((start & map) != 0) {
+			map &= ~start;
+			GT_WRITE(GT_PCI0IOREMAP_OFS, map);
+		}
 
-#ifdef CONFIG_MIPS_MALTA
 		set_io_port_base(MALTA_GT_PORT_BASE);
-#else
-		set_io_port_base((unsigned long)ioremap(0, 0x20000000));
-#endif
 		break;
 
 	case MIPS_REVISION_CORID_CORE_EMUL_BON:
@@ -300,18 +332,21 @@
 			BONITO_BONGENCFG_BYTESWAP;
 #endif
 
-#ifdef CONFIG_MIPS_MALTA
 		set_io_port_base(MALTA_BONITO_PORT_BASE);
-#else
-		set_io_port_base((unsigned long)ioremap(0, 0x20000000));
-#endif
 		break;
 
 	case MIPS_REVISION_CORID_CORE_MSC:
 	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_FPGA3:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 		_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
 
+		mb();
+		MSC_READ(MSC01_PCI_CFG, data);
+		MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);
+		wmb();
+
+		/* Fix up lane swapping.  */
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 		MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
 #else
@@ -320,12 +355,23 @@
 			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
 			  MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
 #endif
+		/* Fix up target memory mapping.  */
+		MSC_READ(MSC01_PCI_BAR0, mask);
+		MSC_WRITE(MSC01_PCI_P2SCMSKL, mask & MSC01_PCI_BAR0_SIZE_MSK);
 
-#ifdef CONFIG_MIPS_MALTA
+		/* Don't handle target retries indefinitely.  */
+		if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==
+		    MSC01_PCI_CFG_MAXRTRY_MSK)
+			data = (data & ~(MSC01_PCI_CFG_MAXRTRY_MSK <<
+					 MSC01_PCI_CFG_MAXRTRY_SHF)) |
+			       ((MSC01_PCI_CFG_MAXRTRY_MSK - 1) <<
+				MSC01_PCI_CFG_MAXRTRY_SHF);
+
+		wmb();
+		MSC_WRITE(MSC01_PCI_CFG, data);
+		mb();
+
 		set_io_port_base(MALTA_MSC_PORT_BASE);
-#else
-		set_io_port_base((unsigned long)ioremap(0, 0x20000000));
-#endif
 		break;
 
 	default:
@@ -334,6 +380,9 @@
 		while(1);   /* We die here... */
 	}
 #endif
+	board_nmi_handler_setup = mips_nmi_setup;
+	board_ejtag_handler_setup = mips_ejtag_setup;
+
 	prom_printf("\nLINUX started...\n");
 	prom_init_cmdline();
 	prom_meminit();
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index 5ae2b43..2c8afd7 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/string.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -55,18 +56,30 @@
 {
 	char *memsize_str;
 	unsigned int memsize;
+	char cmdline[CL_SIZE], *ptr;
 
-	memsize_str = prom_getenv("memsize");
-	if (!memsize_str) {
-		prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
-		memsize = 0x02000000;
-	} else {
-#ifdef DEBUG
-		prom_printf("prom_memsize = %s\n", memsize_str);
-#endif
-		memsize = simple_strtol(memsize_str, NULL, 0);
+	/* Check the command line first for a memsize directive */
+	strcpy(cmdline, arcs_cmdline);
+	ptr = strstr(cmdline, "memsize=");
+	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
+		ptr = strstr(ptr, " memsize=");
+
+	if (ptr) {
+		memsize = memparse(ptr + 8, &ptr);
 	}
-
+	else {
+		/* otherwise look in the environment */
+		memsize_str = prom_getenv("memsize");
+		if (!memsize_str) {
+			prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
+			memsize = 0x02000000;
+		} else {
+#ifdef DEBUG
+			prom_printf("prom_memsize = %s\n", memsize_str);
+#endif
+			memsize = simple_strtol(memsize_str, NULL, 0);
+		}
+	}
 	memset(mdesc, 0, sizeof(mdesc));
 
 	mdesc[0].type = yamon_dontuse;
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
index 131f49b..a397ecb 100644
--- a/arch/mips/mips-boards/generic/mipsIRQ.S
+++ b/arch/mips/mips-boards/generic/mipsIRQ.S
@@ -29,6 +29,20 @@
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlasint.h>
+#define CASCADE_IRQ		MIPSCPU_INT_ATLAS
+#define CASCADE_DISPATCH	atlas_hw0_irqdispatch
+#endif
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/maltaint.h>
+#define CASCADE_IRQ		MIPSCPU_INT_I8259A
+#define CASCADE_DISPATCH	malta_hw0_irqdispatch
+#endif
+#ifdef CONFIG_MIPS_SEAD
+#include <asm/mips-boards/seadint.h>
+#endif
+
 /* A lot of complication here is taken away because:
  *
  * 1) We handle one interrupt and return, sitting in a loop and moving across
@@ -80,74 +94,62 @@
 
 	mfc0	s0, CP0_CAUSE		# get irq bits
 	mfc0	s1, CP0_STATUS		# get irq mask
+	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
 	and	s0, s1
 
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP2	# delay slot, check hw0 interrupt
-
-	/* Wheee, a timer interrupt. */
-	move	a0, sp
-	jal	mips_timer_interrupt
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-#if defined(CONFIG_MIPS_SEAD)
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check hw1 interrupt
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ 	.set	mips32
+	clz	a0, s0
+	.set	mips0
+	negu	a0
+	addu	a0, 31-CAUSEB_IP
+	bltz	a0, spurious
 #else
-	beq	a0, zero, 1f		# delay slot, check hw3 interrupt
- 	 andi	a0, s0, CAUSEF_IP5
+	beqz	s0, spurious
+	 li	a0, 7
+
+	and	t0, s0, 0xf000
+	sltiu	t0, t0, 1
+	sll	t0, 2
+	subu	a0, t0
+	sll	s0, t0
+
+	and	t0, s0, 0xc000
+	sltiu	t0, t0, 1
+	sll	t0, 1
+	subu	a0, t0
+	sll	s0, t0
+
+	and	t0, s0, 0x8000
+	sltiu	t0, t0, 1
+	# sll	t0, 0
+	subu	a0, t0
+	# sll	s0, t0
 #endif
 
-	/* Wheee, combined hardware level zero interrupt. */
-#if defined(CONFIG_MIPS_ATLAS)
-	jal	atlas_hw0_irqdispatch
-#elif defined(CONFIG_MIPS_MALTA)
-	jal	malta_hw0_irqdispatch
-#elif defined(CONFIG_MIPS_SEAD)
-	jal	sead_hw0_irqdispatch
+#ifdef CASCADE_IRQ
+	 li	a1, CASCADE_IRQ
+	bne	a0, a1, 1f
+	 addu	a0, MIPSCPU_INT_BASE
+
+	jal	CASCADE_DISPATCH
+	 move	 a0, sp
+
+	j	ret_from_irq
+	 nop
+1:
 #else
-#error "MIPS board not supported\n"
+	 addu	a0, MIPSCPU_INT_BASE
 #endif
-	 move	a0, sp			# delay slot
 
-	j	ret_from_irq
-	 nop				# delay slot
+	jal	do_IRQ
+	 move	a1, sp
 
-1:
-#if defined(CONFIG_MIPS_SEAD)
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP5	# delay slot, check hw3 interrupt
-	jal	sead_hw1_irqdispatch
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-1:
-#endif
-#if defined(CONFIG_MIPS_MALTA)
-	beq	a0, zero, 1f            # check hw3 (coreHI) interrupt
-	 nop
-	jal	corehi_irqdispatch
-	 move	a0, sp
 	j	ret_from_irq
 	 nop
-1:
-#endif
-	/*
-	 * Here by mistake?  This is possible, what can happen is that by the
-	 * time we take the exception the IRQ pin goes low, so just leave if
-	 * this is the case.
-	 */
-	move	a1,s0
-	PRINT("Got interrupt: c0_cause = %08x\n")
-	mfc0	a1, CP0_EPC
-	PRINT("c0_epc = %08x\n")
 
-	j	ret_from_irq
+
+spurious:
+	j	spurious_interrupt
 	 nop
 	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index 92c34bd..1f6f9df 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
+ *	All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
  *
  * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  *
@@ -19,65 +21,46 @@
  *
  * MIPS boards specific PCI support.
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/mips-boards/generic.h>
 #include <asm/gt64120.h>
+
+#include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
 #include <asm/mips-boards/msc01_pci.h>
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/malta.h>
-#endif
 
 static struct resource bonito64_mem_resource = {
 	.name	= "Bonito PCI MEM",
-	.start	= 0x10000000UL,
-	.end	= 0x1bffffffUL,
 	.flags	= IORESOURCE_MEM,
 };
 
 static struct resource bonito64_io_resource = {
-	.name	= "Bonito IO MEM",
-	.start	= 0x00002000UL,	/* avoid conflicts with YAMON allocated I/O addresses */
+	.name	= "Bonito PCI I/O",
+	.start	= 0x00000000UL,
 	.end	= 0x000fffffUL,
 	.flags	= IORESOURCE_IO,
 };
 
 static struct resource gt64120_mem_resource = {
-	.name	= "GT64120 PCI MEM",
-	.start	= 0x10000000UL,
-	.end	= 0x1bdfffffUL,
+	.name	= "GT-64120 PCI MEM",
 	.flags	= IORESOURCE_MEM,
 };
 
 static struct resource gt64120_io_resource = {
-	.name	= "GT64120 IO MEM",
-#ifdef CONFIG_MIPS_ATLAS
-	.start	= 0x18000000UL,
-	.end	= 0x181fffffUL,
-#endif
-#ifdef CONFIG_MIPS_MALTA
-	.start	= 0x00002000UL,
-	.end	= 0x001fffffUL,
-#endif
+	.name	= "GT-64120 PCI I/O",
 	.flags	= IORESOURCE_IO,
 };
 
 static struct resource msc_mem_resource = {
 	.name	= "MSC PCI MEM",
-	.start	= 0x10000000UL,
-	.end	= 0x1fffffffUL,
 	.flags	= IORESOURCE_MEM,
 };
 
 static struct resource msc_io_resource = {
-	.name	= "MSC IO MEM",
-	.start	= 0x00002000UL,
-	.end	= 0x007fffffUL,
+	.name	= "MSC PCI I/O",
 	.flags	= IORESOURCE_IO,
 };
 
@@ -89,7 +72,6 @@
 	.pci_ops	= &bonito64_pci_ops,
 	.io_resource	= &bonito64_io_resource,
 	.mem_resource	= &bonito64_mem_resource,
-	.mem_offset	= 0x10000000UL,
 	.io_offset	= 0x00000000UL,
 };
 
@@ -97,21 +79,18 @@
 	.pci_ops	= &gt64120_pci_ops,
 	.io_resource	= &gt64120_io_resource,
 	.mem_resource	= &gt64120_mem_resource,
-	.mem_offset	= 0x00000000UL,
-	.io_offset	= 0x00000000UL,
 };
 
-static struct pci_controller  msc_controller = {
+static struct pci_controller msc_controller = {
 	.pci_ops	= &msc_pci_ops,
 	.io_resource	= &msc_io_resource,
 	.mem_resource	= &msc_mem_resource,
-	.mem_offset	= 0x10000000UL,
-	.io_offset	= 0x00000000UL,
 };
 
-static int __init pcibios_init(void)
+void __init mips_pcibios_init(void)
 {
 	struct pci_controller *controller;
+	unsigned long start, end, map, start1, end1, map1, map2, map3, mask;
 
 	switch (mips_revision_corid) {
 	case MIPS_REVISION_CORID_QED_RM5261:
@@ -130,34 +109,140 @@
 			 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
 			 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
 			 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
-			 GT_PCI0_CFGADDR_CONFIGEN_BIT );
+			 GT_PCI0_CFGADDR_CONFIGEN_BIT);
 
 		/* Perform the write */
 		GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
 
+		/* Set up resource ranges from the controller's registers.  */
+		start = GT_READ(GT_PCI0M0LD_OFS);
+		end = GT_READ(GT_PCI0M0HD_OFS);
+		map = GT_READ(GT_PCI0M0REMAP_OFS);
+		end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
+		start1 = GT_READ(GT_PCI0M1LD_OFS);
+		end1 = GT_READ(GT_PCI0M1HD_OFS);
+		map1 = GT_READ(GT_PCI0M1REMAP_OFS);
+		end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
+		/* Cannot support multiple windows, use the wider.  */
+		if (end1 - start1 > end - start) {
+			start = start1;
+			end = end1;
+			map = map1;
+		}
+		mask = ~(start ^ end);
+                /* We don't support remapping with a discontiguous mask.  */
+		BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
+		       mask != ~((mask & -mask) - 1));
+		gt64120_mem_resource.start = start;
+		gt64120_mem_resource.end = end;
+		gt64120_controller.mem_offset = (start & mask) - (map & mask);
+		/* Addresses are 36-bit, so do shifts in the destinations.  */
+		gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
+		gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
+		gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
+		gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
+
+		start = GT_READ(GT_PCI0IOLD_OFS);
+		end = GT_READ(GT_PCI0IOHD_OFS);
+		map = GT_READ(GT_PCI0IOREMAP_OFS);
+		end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
+		mask = ~(start ^ end);
+                /* We don't support remapping with a discontiguous mask.  */
+		BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
+		       mask != ~((mask & -mask) - 1));
+		gt64120_io_resource.start = map & mask;
+		gt64120_io_resource.end = (map & mask) | ~mask;
+		gt64120_controller.io_offset = 0;
+		/* Addresses are 36-bit, so do shifts in the destinations.  */
+		gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
+		gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
+		gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
+
 		controller = &gt64120_controller;
 		break;
 
 	case MIPS_REVISION_CORID_BONITO64:
 	case MIPS_REVISION_CORID_CORE_20K:
 	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+		/* Set up resource ranges from the controller's registers.  */
+		map = BONITO_PCIMAP;
+		map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
+		       BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
+		map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
+		       BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
+		map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
+		       BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
+		/* Combine as many adjacent windows as possible.  */
+		map = map1;
+		start = BONITO_PCILO0_BASE;
+		end = 1;
+		if (map3 == map2 + 1) {
+			map = map2;
+			start = BONITO_PCILO1_BASE;
+			end++;
+		}
+		if (map2 == map1 + 1) {
+			map = map1;
+			start = BONITO_PCILO0_BASE;
+			end++;
+		}
+		bonito64_mem_resource.start = start;
+		bonito64_mem_resource.end = start +
+					    BONITO_PCIMAP_WINBASE(end) - 1;
+		bonito64_controller.mem_offset = start -
+						 BONITO_PCIMAP_WINBASE(map);
+
 		controller = &bonito64_controller;
 		break;
 
 	case MIPS_REVISION_CORID_CORE_MSC:
 	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_FPGA3:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+		/* Set up resource ranges from the controller's registers.  */
+		MSC_READ(MSC01_PCI_SC2PMBASL, start);
+		MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
+		MSC_READ(MSC01_PCI_SC2PMMAPL, map);
+		msc_mem_resource.start = start & mask;
+		msc_mem_resource.end = (start & mask) | ~mask;
+		msc_controller.mem_offset = (start & mask) - (map & mask);
+
+		MSC_READ(MSC01_PCI_SC2PIOBASL, start);
+		MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
+		MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
+		msc_io_resource.start = map & mask;
+		msc_io_resource.end = (map & mask) | ~mask;
+		msc_controller.io_offset = 0;
+		ioport_resource.end = ~mask;
+
+		/* If ranges overlap I/O takes precedence.  */
+		start = start & mask;
+		end = start | ~mask;
+		if ((start >= msc_mem_resource.start &&
+		     start <= msc_mem_resource.end) ||
+		    (end >= msc_mem_resource.start &&
+		     end <= msc_mem_resource.end)) {
+			/* Use the larger space.  */
+			start = max(start, msc_mem_resource.start);
+			end = min(end, msc_mem_resource.end);
+			if (start - msc_mem_resource.start >=
+			    msc_mem_resource.end - end)
+				msc_mem_resource.end = start - 1;
+			else
+				msc_mem_resource.start = end + 1;
+		}
+
 		controller = &msc_controller;
 		break;
 	default:
-		return 1;
+		return;
 	}
 
+	if (controller->io_resource->start < 0x00001000UL)	/* FIXME */
+		controller->io_resource->start = 0x00001000UL;
+
+	iomem_resource.end &= 0xfffffffffULL;			/* 64 GB */
 	ioport_resource.end = controller->io_resource->end;
 
 	register_pci_controller (controller);
-
-	return 0;
 }
-
-early_initcall(pcibios_init);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 1631544..72a12d9 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -31,22 +31,21 @@
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
 #include <asm/time.h>
 #include <asm/mc146818-time.h>
+#include <asm/msc01_ic.h>
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mc146818-time.h>
 
 unsigned long cpu_khz;
 
-#if defined(CONFIG_MIPS_SEAD)
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5)
-#else
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
-#endif
-
 #if defined(CONFIG_MIPS_ATLAS)
 static char display_string[] = "        LINUX ON ATLAS       ";
 #endif
@@ -59,20 +58,61 @@
 static unsigned int display_count = 0;
 #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
 
-#define MIPS_CPU_TIMER_IRQ (NR_IRQS-1)
-
 static unsigned int timer_tick_count=0;
+static int mips_cpu_timer_irq;
 
-void mips_timer_interrupt(struct pt_regs *regs)
+static inline void scroll_display_message(void)
 {
 	if ((timer_tick_count++ % HZ) == 0) {
 		mips_display_message(&display_string[display_count++]);
 		if (display_count == MAX_DISPLAY_COUNT)
-		        display_count = 0;
+			display_count = 0;
+	}
+}
 
+static void mips_timer_dispatch (struct pt_regs *regs)
+{
+	do_IRQ (mips_cpu_timer_irq, regs);
+}
+
+irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+#ifdef CONFIG_SMP
+	int cpu = smp_processor_id();
+
+	if (cpu == 0) {
+		/*
+		 * CPU 0 handles the global timer interrupt job and process accounting
+		 * resets count/compare registers to trigger next timer int.
+		 */
+		(void) timer_interrupt(irq, dev_id, regs);
+		scroll_display_message();
+	}
+	else {
+		/* Everyone else needs to reset the timer int here as
+		   ll_local_timer_interrupt doesn't */
+		/*
+		 * FIXME: need to cope with counter underflow.
+		 * More support needs to be added to kernel/time for
+		 * counter/timer interrupts on multiple CPU's
+		 */
+		write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+		/*
+		 * other CPUs should do profiling and process accounting
+		 */
+		local_timer_interrupt (irq, dev_id, regs);
 	}
 
-	ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs);
+	return IRQ_HANDLED;
+#else
+	irqreturn_t r;
+
+	r = timer_interrupt(irq, dev_id, regs);
+
+	scroll_display_message();
+
+	return r;
+#endif
 }
 
 /*
@@ -140,10 +180,8 @@
 
 	local_irq_save(flags);
 
-#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
         /* Set Data mode - binary. */
         CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-#endif
 
 	est_freq = estimate_cpu_frequency ();
 
@@ -157,11 +195,29 @@
 
 void __init mips_timer_setup(struct irqaction *irq)
 {
+	if (cpu_has_veic) {
+		set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
+	}
+	else {
+		if (cpu_has_vint)
+			set_vi_handler (MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+	}
+
+
 	/* we are using the cpu counter for timer interrupts */
-	irq->handler = no_action;     /* we use our own handler */
-	setup_irq(MIPS_CPU_TIMER_IRQ, irq);
+	irq->handler = mips_timer_interrupt;	/* we use our own handler */
+	setup_irq(mips_cpu_timer_irq, irq);
+
+#ifdef CONFIG_SMP
+	/* irq_desc(riptor) is a global resource, when the interrupt overlaps
+	   on seperate cpu's the first one tries to handle the second interrupt.
+	   The effect is that the int remains disabled on the second cpu.
+	   Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
+	irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
+#endif
 
         /* to generate the first timer interrupt */
 	write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
-	set_c0_status(ALLINTS);
 }
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index dd2db35..d06dc5ad 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -30,6 +30,7 @@
 #include <linux/random.h>
 
 #include <asm/i8259.h>
+#include <asm/irq_cpu.h>
 #include <asm/io.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
@@ -37,8 +38,10 @@
 #include <asm/gt64120.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/msc01_pci.h>
+#include <asm/msc01_ic.h>
 
 extern asmlinkage void mipsIRQ(void);
+extern void mips_timer_interrupt(void);
 
 static DEFINE_SPINLOCK(mips_irq_lock);
 
@@ -54,6 +57,7 @@
 	switch(mips_revision_corid) {
 	case MIPS_REVISION_CORID_CORE_MSC:
 	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_FPGA3:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 	        MSC_READ(MSC01_PCI_IACK, irq);
 		irq &= 0xff;
@@ -91,88 +95,86 @@
 	return irq;
 }
 
-static inline int get_int(int *irq)
+static inline int get_int(void)
 {
 	unsigned long flags;
-
+	int irq;
 	spin_lock_irqsave(&mips_irq_lock, flags);
 
-	*irq = mips_pcibios_iack();
+	irq = mips_pcibios_iack();
 
 	/*
-	 * IRQ7 is used to detect spurious interrupts.
-	 * The interrupt acknowledge cycle returns IRQ7, if no
-	 * interrupts is requested.
-	 * We can differentiate between this situation and a
-	 * "Normal" IRQ7 by reading the ISR.
+	 * The only way we can decide if an interrupt is spurious
+	 * is by checking the 8259 registers.  This needs a spinlock
+	 * on an SMP system,  so leave it up to the generic code...
 	 */
-	if (*irq == 7)
-	{
-		outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR,
-		     PIIX4_ICTLR1_OCW3);
-		if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) {
-			spin_unlock_irqrestore(&mips_irq_lock, flags);
-			printk("We got a spurious interrupt from PIIX4.\n");
-			atomic_inc(&irq_err_count);
-			return -1;    /* Spurious interrupt. */
-		}
-	}
 
 	spin_unlock_irqrestore(&mips_irq_lock, flags);
 
-	return 0;
+	return irq;
 }
 
 void malta_hw0_irqdispatch(struct pt_regs *regs)
 {
 	int irq;
 
-	if (get_int(&irq))
-	        return;  /* interrupt has already been cleared */
+	irq = get_int();
+	if (irq < 0)
+		return;  /* interrupt has already been cleared */
 
-	do_IRQ(irq, regs);
+	do_IRQ(MALTA_INT_BASE+irq, regs);
 }
 
 void corehi_irqdispatch(struct pt_regs *regs)
 {
-        unsigned int data,datahi;
-
-	/* Mask out corehi interrupt. */
-	clear_c0_status(IE_IRQ3);
+	unsigned int intrcause,datalo,datahi;
+        unsigned int pcimstat, intisr, inten, intpol, intedge, intsteer, pcicmd, pcibadaddr;
 
         printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n");
         printk("epc   : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n"
 , regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr);
+
+	/* Read all the registers and then print them as there is a
+	   problem with interspersed printk's upsetting the Bonito controller.
+	   Do it for the others too.
+	*/
+
         switch(mips_revision_corid) {
         case MIPS_REVISION_CORID_CORE_MSC:
         case MIPS_REVISION_CORID_CORE_FPGA2:
-	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+        case MIPS_REVISION_CORID_CORE_FPGA3:
+        case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+                ll_msc_irq(regs);
                 break;
         case MIPS_REVISION_CORID_QED_RM5261:
         case MIPS_REVISION_CORID_CORE_LV:
         case MIPS_REVISION_CORID_CORE_FPGA:
         case MIPS_REVISION_CORID_CORE_FPGAR2:
-                data = GT_READ(GT_INTRCAUSE_OFS);
-                printk("GT_INTRCAUSE = %08x\n", data);
-                data = GT_READ(GT_CPUERR_ADDRLO_OFS);
+                intrcause = GT_READ(GT_INTRCAUSE_OFS);
+                datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
                 datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
-                printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, data);
+                printk("GT_INTRCAUSE = %08x\n", intrcause);
+                printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo);
                 break;
         case MIPS_REVISION_CORID_BONITO64:
         case MIPS_REVISION_CORID_CORE_20K:
         case MIPS_REVISION_CORID_CORE_EMUL_BON:
-                data = BONITO_INTISR;
-                printk("BONITO_INTISR = %08x\n", data);
-                data = BONITO_INTEN;
-                printk("BONITO_INTEN = %08x\n", data);
-                data = BONITO_INTPOL;
-                printk("BONITO_INTPOL = %08x\n", data);
-                data = BONITO_INTEDGE;
-                printk("BONITO_INTEDGE = %08x\n", data);
-                data = BONITO_INTSTEER;
-                printk("BONITO_INTSTEER = %08x\n", data);
-                data = BONITO_PCICMD;
-                printk("BONITO_PCICMD = %08x\n", data);
+                pcibadaddr = BONITO_PCIBADADDR;
+                pcimstat = BONITO_PCIMSTAT;
+                intisr = BONITO_INTISR;
+                inten = BONITO_INTEN;
+                intpol = BONITO_INTPOL;
+                intedge = BONITO_INTEDGE;
+                intsteer = BONITO_INTSTEER;
+                pcicmd = BONITO_PCICMD;
+                printk("BONITO_INTISR = %08x\n", intisr);
+                printk("BONITO_INTEN = %08x\n", inten);
+                printk("BONITO_INTPOL = %08x\n", intpol);
+                printk("BONITO_INTEDGE = %08x\n", intedge);
+                printk("BONITO_INTSTEER = %08x\n", intsteer);
+                printk("BONITO_PCICMD = %08x\n", pcicmd);
+                printk("BONITO_PCIBADADDR = %08x\n", pcibadaddr);
+                printk("BONITO_PCIMSTAT = %08x\n", pcimstat);
                 break;
         }
 
@@ -180,8 +182,71 @@
         die("CoreHi interrupt", regs);
 }
 
+static struct irqaction i8259irq = {
+	.handler = no_action,
+	.name = "XT-PIC cascade"
+};
+
+static struct irqaction corehi_irqaction = {
+	.handler = no_action,
+	.name = "CoreHi"
+};
+
+msc_irqmap_t __initdata msc_irqmap[] = {
+	{MSC01C_INT_TMR,		MSC01_IRQ_EDGE, 0},
+	{MSC01C_INT_PCI,		MSC01_IRQ_LEVEL, 0},
+};
+int __initdata msc_nr_irqs = sizeof(msc_irqmap)/sizeof(msc_irqmap_t);
+
+msc_irqmap_t __initdata msc_eicirqmap[] = {
+	{MSC01E_INT_SW0,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_SW1,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_I8259A,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_SMI,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_COREHI,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_CORELO,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_TMR,		MSC01_IRQ_EDGE, 0},
+	{MSC01E_INT_PCI,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_PERFCTR,		MSC01_IRQ_LEVEL, 0},
+	{MSC01E_INT_CPUCTR,		MSC01_IRQ_LEVEL, 0}
+};
+int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t);
+
 void __init arch_init_irq(void)
 {
 	set_except_vector(0, mipsIRQ);
 	init_i8259_irqs();
+
+	if (!cpu_has_veic)
+		mips_cpu_irq_init (MIPSCPU_INT_BASE);
+
+        switch(mips_revision_corid) {
+        case MIPS_REVISION_CORID_CORE_MSC:
+        case MIPS_REVISION_CORID_CORE_FPGA2:
+        case MIPS_REVISION_CORID_CORE_FPGA3:
+        case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+		if (cpu_has_veic)
+			init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
+		else
+			init_msc_irqs (MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
+	}
+
+	if (cpu_has_veic) {
+		set_vi_handler (MSC01E_INT_I8259A, malta_hw0_irqdispatch);
+		set_vi_handler (MSC01E_INT_COREHI, corehi_irqdispatch);
+		setup_irq (MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq);
+		setup_irq (MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction);
+	}
+	else if (cpu_has_vint) {
+		set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
+		set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
+
+		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
+		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+	}
+	else {
+		set_except_vector(0, mipsIRQ);
+		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
+		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+	}
 }
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index df6db64..2209e8a 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -111,10 +111,12 @@
 }
 #endif
 
-static int __init malta_setup(void)
+void __init plat_setup(void)
 {
 	unsigned int i;
 
+	mips_pcibios_init();
+
 	/* Request I/O space for devices used on the Malta board. */
 	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
 		request_resource(&ioport_resource, standard_io_resources+i);
@@ -224,8 +226,4 @@
 	board_time_init = mips_time_init;
 	board_timer_setup = mips_timer_setup;
 	rtc_get_time = mips_rtc_get_time;
-
-	return 0;
 }
-
-early_initcall(malta_setup);
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index e510965..e1dd7e0 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -2,6 +2,7 @@
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
  * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2004  Maciej W. Rozycki
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -21,7 +22,9 @@
  */
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/interrupt.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/system.h>
 
 #include <asm/mips-boards/seadint.h>
 
@@ -39,13 +42,8 @@
 
 void __init arch_init_irq(void)
 {
-        /*
-         * Mask out all interrupt
-	 */
-	clear_c0_status(0x0000ff00);
+	mips_cpu_irq_init(0);
 
 	/* Now safe to set the exception vector. */
 	set_except_vector(0, mipsIRQ);
-
-	mips_cpu_irq_init(0);
 }
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index 29892b8..de90bec 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -57,8 +57,6 @@
 	mips_reboot_setup();
 }
 
-early_initcall(sead_setup);
-
 static void __init serial_init(void)
 {
 #ifdef CONFIG_SERIAL_8250
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mips-boards/sim/Makefile
new file mode 100644
index 0000000..5b977de
--- /dev/null
+++ b/arch/mips/mips-boards/sim/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+#
+# This program is free software; you can distribute 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 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.
+#
+
+obj-y := sim_setup.o sim_mem.o sim_time.o sim_printf.o sim_int.o sim_irq.o \
+	sim_cmdline.o
+obj-$(CONFIG_SMP) += sim_smp.o
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
new file mode 100644
index 0000000..fef9fbd
--- /dev/null
+++ b/arch/mips/mips-boards/sim/cmdline.c
@@ -0,0 +1,59 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute 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 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.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern int *_prom_argv;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
+
+char arcs_cmdline[CL_SIZE];
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+
+void  __init prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+	        strcpy(cp, prom_argv(actr));
+		cp += strlen(prom_argv(actr));
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+}
diff --git a/arch/mips/mips-boards/sim/sim_IRQ.c b/arch/mips/mips-boards/sim/sim_IRQ.c
new file mode 100644
index 0000000..9987a85
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_IRQ.c
@@ -0,0 +1,148 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * Interrupt exception dispatch code.
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * Note: On the SEAD board thing are a little bit different.
+ *       Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
+ *       wired to UART1.
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+	.text
+	.set	noreorder
+	.set	noat
+	.align	5
+	NESTED(mipsIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+
+	mfc0	s0, CP0_CAUSE		# get irq bits
+	mfc0	s1, CP0_STATUS		# get irq mask
+	and	s0, s1
+
+	/* First we check for r4k counter/timer IRQ. */
+	andi	a0, s0, CAUSEF_IP7
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP2	# delay slot, check hw0 interrupt
+
+	/* Wheee, a timer interrupt. */
+	move	a0, sp
+	jal	mips_timer_interrupt
+	 nop
+
+	j	ret_from_irq
+	 nop
+
+1:
+#if defined(CONFIG_MIPS_SEAD)
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP3	# delay slot, check hw1 interrupt
+#else
+	beq	a0, zero, 1f		# delay slot, check hw3 interrupt
+ 	 andi	a0, s0, CAUSEF_IP5
+#endif
+
+	/* Wheee, combined hardware level zero interrupt. */
+#if defined(CONFIG_MIPS_ATLAS)
+	jal	atlas_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_MALTA)
+	jal	malta_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_SEAD)
+	jal	sead_hw0_irqdispatch
+#else
+#error "MIPS board not supported\n"
+#endif
+	 move	a0, sp			# delay slot
+
+	j	ret_from_irq
+	 nop				# delay slot
+
+1:
+#if defined(CONFIG_MIPS_SEAD)
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP5	# delay slot, check hw3 interrupt
+	jal	sead_hw1_irqdispatch
+	 move	a0, sp			# delay slot
+	j	ret_from_irq
+	 nop				# delay slot
+1:
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+	beq	a0, zero, 1f            # check hw3 (coreHI) interrupt
+	 nop
+	jal	corehi_irqdispatch
+	 move	a0, sp
+	j	ret_from_irq
+	 nop
+1:
+#endif
+	/*
+	 * Here by mistake?  This is possible, what can happen is that by the
+	 * time we take the exception the IRQ pin goes low, so just leave if
+	 * this is the case.
+	 */
+	move	a1,s0
+	PRINT("Got interrupt: c0_cause = %08x\n")
+	mfc0	a1, CP0_EPC
+	PRINT("c0_epc = %08x\n")
+
+	j	ret_from_irq
+	 nop
+	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
new file mode 100644
index 0000000..9df37c6
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_cmdline.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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/init.h>
+#include <linux/string.h>
+#include <asm/bootinfo.h>
+
+extern char arcs_cmdline[];
+
+char * __init prom_getcmdline(void)
+{
+	return arcs_cmdline;
+}
+
+
+void  __init prom_init_cmdline(void)
+{
+    /* nothing to do */
+}
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
new file mode 100644
index 0000000..a4d0a2c
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/mips-boards/simint.h>
+
+
+extern void mips_cpu_irq_init(int);
+
+extern asmlinkage void simIRQ(void);
+
+asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+{
+	do_IRQ(2, regs);
+}
+
+void __init arch_init_irq(void)
+{
+	/* Now safe to set the exception vector. */
+	set_except_vector(0, simIRQ);
+
+	mips_cpu_irq_init(MIPSCPU_INT_BASE);
+}
diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S
new file mode 100644
index 0000000..835f038
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_irq.S
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * Interrupt exception dispatch code.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/mips-boards/simint.h>
+
+
+	.text
+	.set	noreorder
+	.set	noat
+	.align	5
+	NESTED(simIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+
+	mfc0	s0, CP0_CAUSE		# get irq bits
+	mfc0	s1, CP0_STATUS		# get irq mask
+	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
+	and	s0, s1
+
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ 	.set	mips32
+	clz	a0, s0
+	.set	mips0
+	negu	a0
+	addu	a0, 31-CAUSEB_IP
+	bltz	a0, spurious
+#else
+	beqz	s0, spurious
+	 li	a0, 7
+
+	and	t0, s0, 0xf000
+	sltiu	t0, t0, 1
+	sll	t0, 2
+	subu	a0, t0
+	sll	s0, t0
+
+	and	t0, s0, 0xc000
+	sltiu	t0, t0, 1
+	sll	t0, 1
+	subu	a0, t0
+	sll	s0, t0
+
+	and	t0, s0, 0x8000
+	sltiu	t0, t0, 1
+	# sll	t0, 0
+	subu	a0, t0
+	# sll	s0, t0
+#endif
+
+#ifdef CASCADE_IRQ
+	 li	a1, CASCADE_IRQ
+	bne	a0, a1, 1f
+	 addu	a0, MIPSCPU_INT_BASE
+
+	jal	CASCADE_DISPATCH
+	 move	 a0, sp
+
+	j	ret_from_irq
+	 nop
+1:
+#else
+	 addu	a0, MIPSCPU_INT_BASE
+#endif
+
+	jal	do_IRQ
+	 move	a1, sp
+
+	j	ret_from_irq
+	 nop
+
+
+spurious:
+	j	spurious_interrupt
+	 nop
+	END(simIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
new file mode 100644
index 0000000..0dbd743
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum simmem_memtypes {
+	simmem_reserved = 0,
+	simmem_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+	"SIM reserved memory",
+	"SIM free memory",
+};
+#endif
+
+/* References to section boundaries */
+extern char _end;
+
+#define PFN_ALIGN(x)    (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+	unsigned int memsize;
+
+	memsize = 0x02000000;
+	prom_printf("Setting default memory size 0x%08x\n", memsize);
+
+	memset(mdesc, 0, sizeof(mdesc));
+
+	mdesc[0].type = simmem_reserved;
+	mdesc[0].base = 0x00000000;
+	mdesc[0].size = 0x00001000;
+
+	mdesc[1].type = simmem_free;
+	mdesc[1].base = 0x00001000;
+	mdesc[1].size = 0x000ff000;
+
+	mdesc[2].type = simmem_reserved;
+	mdesc[2].base = 0x00100000;
+	mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
+
+	mdesc[3].type = simmem_free;
+	mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
+	mdesc[3].size = memsize - mdesc[3].base;
+
+	return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+	switch (type) {
+	case simmem_free:
+		return BOOT_MEM_RAM;
+	case simmem_reserved:
+	default:
+		return BOOT_MEM_RESERVED;
+	}
+}
+
+void __init prom_meminit(void)
+{
+	struct prom_pmemblock *p;
+
+	p = prom_getmdesc();
+
+	while (p->size) {
+		long type;
+		unsigned long base, size;
+
+		type = prom_memtype_classify (p->type);
+		base = p->base;
+		size = p->size;
+
+		add_memory_region(base, size, type);
+                p++;
+	}
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+	int i;
+	unsigned long freed = 0;
+	unsigned long addr;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		while (addr < boot_mem_map.map[i].addr
+			      + boot_mem_map.map[i].size) {
+			ClearPageReserved(virt_to_page(__va(addr)));
+			set_page_count(virt_to_page(__va(addr)), 1);
+			free_page((unsigned long)__va(addr));
+			addr += PAGE_SIZE;
+			freed += PAGE_SIZE;
+		}
+	}
+	printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+	return freed;
+}
diff --git a/arch/mips/mips-boards/sim/sim_printf.c b/arch/mips/mips-boards/sim/sim_printf.c
new file mode 100644
index 0000000..3ee5a0b
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_printf.c
@@ -0,0 +1,74 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+static inline unsigned int serial_in(int offset)
+{
+	return inb(0x3f8 + offset);
+}
+
+static inline void serial_out(int offset, int value)
+{
+	outb(value, 0x3f8 + offset);
+}
+
+int putPromChar(char c)
+{
+	while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
+		;
+
+	serial_out(UART_TX, c);
+
+	return 1;
+}
+
+char getPromChar(void)
+{
+	while (!(serial_in(UART_LSR) & 1))
+		;
+
+	return serial_in(UART_RX);
+}
+
+void prom_printf(char *fmt, ...)
+{
+	va_list args;
+	int l;
+	char *p, *buf_end;
+	char buf[1024];
+
+	va_start(args, fmt);
+	l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+	va_end(args);
+
+	buf_end = buf + l;
+
+	for (p = buf; p < buf_end; p++) {
+		/* Crude cr/nl handling is better than none */
+		if (*p == '\n')
+			putPromChar('\r');
+		putPromChar(*p);
+	}
+}
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
new file mode 100644
index 0000000..485d5a5
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_setup.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mips-boards/sim.h>
+#include <asm/mips-boards/simint.h>
+
+
+extern void sim_time_init(void);
+extern void sim_timer_setup(struct irqaction *irq);
+static void __init serial_init(void);
+unsigned int _isbonito = 0;
+
+extern void __init sanitize_tlb_entries(void);
+
+
+const char *get_system_type(void)
+{
+	return "MIPSsim";
+}
+
+void __init plat_setup(void)
+{
+	set_io_port_base(0xbfd00000);
+
+	serial_init();
+
+	board_time_init = sim_time_init;
+	board_timer_setup = sim_timer_setup;
+	prom_printf("Linux started...\n");
+
+#ifdef CONFIG_MT_SMP
+	sanitize_tlb_entries();
+#endif
+}
+
+void prom_init(void)
+{
+	set_io_port_base(0xbfd00000);
+
+	prom_printf("\nLINUX started...\n");
+	prom_init_cmdline();
+	prom_meminit();
+}
+
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+	struct uart_port s;
+
+	memset(&s, 0, sizeof(s));
+
+	s.iobase = 0x3f8;
+
+	/* hardware int 4 - the serial int, is CPU int 6
+	 but poll for now */
+	s.irq =  0;
+	s.uartclk = BASE_BAUD * 16;
+	s.flags = ASYNC_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	s.iotype = SERIAL_IO_PORT | ASYNC_SKIP_TEST;
+	s.regshift = 0;
+	s.timeout = 4;
+
+	if (early_serial_setup(&s) != 0) {
+		prom_printf(KERN_ERR "Serial setup failed!\n");
+	}
+
+#endif
+}
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
new file mode 100644
index 0000000..1982435
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ */
+/*
+ * Simulator Platform-specific hooks for SMP operation
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/smtc_ipi.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_send_ipi(int, int, unsigned int);
+
+	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+
+}
+
+/*
+ * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
+ */
+
+void __init prom_build_cpu_map(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	extern int mipsmt_build_cpu_map(int startslot);
+	int nextslot;
+
+	cpus_clear(phys_cpu_present_map);
+
+	/* Register the boot CPU */
+
+	smp_prepare_boot_cpu();
+
+	/*
+	 * As of November, 2004, MIPSsim only simulates one core
+	 * at a time.  However, that core may be a MIPS MT core
+	 * with multiple virtual processors and thread contexts.
+	 */
+
+	if (read_c0_config3() & (1<<2)) {
+		nextslot = mipsmt_build_cpu_map(1);
+	}
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	extern void smtc_boot_secondary(int cpu, struct task_struct *t);
+
+	smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_init_secondary(void);
+
+	smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ */
+
+void prom_prepare_cpus(unsigned int max_cpus)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void mipsmt_prepare_cpus(int c);
+	/*
+ 	 * As noted above, we can assume a single CPU for now
+	 * but it may be multithreaded.
+	 */
+
+	if (read_c0_config3() & (1<<2)) {
+		mipsmt_prepare_cpus(max_cpus);
+	}
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_smp_finish(void);
+
+	smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c
new file mode 100644
index 0000000..18b968c
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_time.c
@@ -0,0 +1,215 @@
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/mc146818-time.h>
+#include <asm/msc01_ic.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/simint.h>
+#include <asm/mc146818-time.h>
+#include <asm/smp.h>
+
+
+unsigned long cpu_khz;
+
+extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
+
+irqreturn_t sim_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+#ifdef CONFIG_SMP
+	int cpu = smp_processor_id();
+
+	/*
+	 * CPU 0 handles the global timer interrupt job
+	 * resets count/compare registers to trigger next timer int.
+	 */
+#ifndef CONFIG_MIPS_MT_SMTC
+	if (cpu == 0) {
+		timer_interrupt(irq, dev_id, regs);
+	}
+	else {
+		/* Everyone else needs to reset the timer int here as
+		   ll_local_timer_interrupt doesn't */
+		/*
+		 * FIXME: need to cope with counter underflow.
+		 * More support needs to be added to kernel/time for
+		 * counter/timer interrupts on multiple CPU's
+		 */
+		write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+	}
+#else /* SMTC */
+	/*
+	 *  In SMTC system, one Count/Compare set exists per VPE.
+	 *  Which TC within a VPE gets the interrupt is essentially
+	 *  random - we only know that it shouldn't be one with
+	 *  IXMT set. Whichever TC gets the interrupt needs to
+	 *  send special interprocessor interrupts to the other
+	 *  TCs to make sure that they schedule, etc.
+	 *
+	 *  That code is specific to the SMTC kernel, not to
+	 *  the simulation platform, so it's invoked from
+	 *  the general MIPS timer_interrupt routine.
+	 *
+	 * We have a problem in that the interrupt vector code
+	 * had to turn off the timer IM bit to avoid redundant
+	 * entries, but we may never get to mips_cpu_irq_end
+	 * to turn it back on again if the scheduler gets
+	 * involved.  So we clear the pending timer here,
+	 * and re-enable the mask...
+	 */
+
+	int vpflags = dvpe();
+	write_c0_compare (read_c0_count() - 1);
+	clear_c0_cause(0x100 << MIPSCPU_INT_CPUCTR);
+	set_c0_status(0x100 << MIPSCPU_INT_CPUCTR);
+	irq_enable_hazard();
+	evpe(vpflags);
+
+	if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id, regs);
+	else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+	smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+	/*
+	 * every CPU should do profiling and process accounting
+	 */
+ 	local_timer_interrupt (irq, dev_id, regs);
+	return IRQ_HANDLED;
+#else
+	return timer_interrupt (irq, dev_id, regs);
+#endif
+}
+
+
+
+/*
+ * Estimate CPU frequency.  Sets mips_counter_frequency as a side-effect
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+	unsigned int prid = read_c0_prid() & 0xffff00;
+	unsigned int count;
+
+#if 1
+	/*
+	 * hardwire the board frequency to 12MHz.
+	 */
+
+	if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
+	    (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count = 12000000;
+	else
+		count =  6000000;
+#else
+	unsigned int flags;
+
+	local_irq_save(flags);
+
+	/* Start counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	/* Start r4k counter. */
+	write_c0_count(0);
+
+	/* Read counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	count = read_c0_count();
+
+	/* restore interrupts */
+	local_irq_restore(flags);
+#endif
+
+	mips_hpt_frequency = count;
+
+	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+		count *= 2;
+
+	count += 5000;    /* round */
+	count -= count%10000;
+
+	return count;
+}
+
+void __init sim_time_init(void)
+{
+	unsigned int est_freq, flags;
+
+	local_irq_save(flags);
+
+
+        /* Set Data mode - binary. */
+	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+
+	est_freq = estimate_cpu_frequency ();
+
+	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+	       (est_freq%1000000)*100/1000000);
+
+        cpu_khz = est_freq / 1000;
+
+	local_irq_restore(flags);
+}
+
+static int mips_cpu_timer_irq;
+
+static void mips_timer_dispatch (struct pt_regs *regs)
+{
+	do_IRQ (mips_cpu_timer_irq, regs);
+}
+
+
+void __init sim_timer_setup(struct irqaction *irq)
+{
+	if (cpu_has_veic) {
+		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
+	}
+	else {
+		if (cpu_has_vint)
+			set_vi_handler(MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+	}
+
+	/* we are using the cpu counter for timer interrupts */
+	irq->handler = sim_timer_interrupt;
+	setup_irq(mips_cpu_timer_irq, irq);
+
+#ifdef CONFIG_SMP
+	/* irq_desc(riptor) is a global resource, when the interrupt overlaps
+	   on seperate cpu's the first one tries to handle the second interrupt.
+	   The effect is that the int remains disabled on the second cpu.
+	   Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
+	irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
+#endif
+
+	/* to generate the first timer interrupt */
+	write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+}
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index b56a0ab..b0178da 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -22,7 +22,7 @@
 obj-$(CONFIG_CPU_RM7000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_RM9000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= c-sb1.o cerr-sb1.o cex-sb1.o pg-sb1.o \
-				   tlb-sb1.o
+				   tlb-r4k.o
 obj-$(CONFIG_CPU_TX39XX)	+= c-tx39.o pg-r4k.o tlb-r3k.o
 obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index c659f99..27f4fa2 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -221,12 +221,14 @@
 					   struct mm_struct *mm)
 {
 	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	unsigned long physpage;
 
 	pgd = pgd_offset(mm, addr);
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	pmd = pmd_offset(pud, addr);
 	pte = pte_offset(pmd, addr);
 
 	if ((physpage = pte_val(*pte)) & _PAGE_VALID)
@@ -317,7 +319,7 @@
 	r3k_flush_dcache_range(start, start + size);
 }
 
-void __init ld_mmu_r23000(void)
+void __init r3k_cache_init(void)
 {
 	extern void build_clear_page(void);
 	extern void build_copy_page(void);
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 5ea84bc..38223b4 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -16,6 +16,7 @@
 
 #include <asm/bcache.h>
 #include <asm/bootinfo.h>
+#include <asm/cache.h>
 #include <asm/cacheops.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -26,8 +27,14 @@
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/war.h>
+#include <asm/cacheflush.h> /* for run_uncached() */
 
-static unsigned long icache_size, dcache_size, scache_size;
+/*
+ * Must die.
+ */
+static unsigned long icache_size __read_mostly;
+static unsigned long dcache_size __read_mostly;
+static unsigned long scache_size __read_mostly;
 
 /*
  * Dummy cache handling routines for machines without boardcaches
@@ -43,8 +50,8 @@
 
 struct bcache_ops *bcops = &no_sc_ops;
 
-#define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x2010)
-#define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x2020)
+#define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
+#define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
 
 #define R4600_HIT_CACHEOP_WAR_IMPL					\
 do {									\
@@ -190,12 +197,12 @@
 	if (ic_lsize == 16)
 		r4k_blast_icache_page_indexed = blast_icache16_page_indexed;
 	else if (ic_lsize == 32) {
-		if (TX49XX_ICACHE_INDEX_INV_WAR)
-			r4k_blast_icache_page_indexed =
-				tx49_blast_icache32_page_indexed;
-		else if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
+		if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
 			r4k_blast_icache_page_indexed =
 				blast_icache32_r4600_v1_page_indexed;
+		else if (TX49XX_ICACHE_INDEX_INV_WAR)
+			r4k_blast_icache_page_indexed =
+				tx49_blast_icache32_page_indexed;
 		else
 			r4k_blast_icache_page_indexed =
 				blast_icache32_page_indexed;
@@ -361,24 +368,33 @@
 
 struct flush_cache_page_args {
 	struct vm_area_struct *vma;
-	unsigned long page;
+	unsigned long addr;
 };
 
 static inline void local_r4k_flush_cache_page(void *args)
 {
 	struct flush_cache_page_args *fcp_args = args;
 	struct vm_area_struct *vma = fcp_args->vma;
-	unsigned long page = fcp_args->page;
+	unsigned long addr = fcp_args->addr;
 	int exec = vma->vm_flags & VM_EXEC;
 	struct mm_struct *mm = vma->vm_mm;
 	pgd_t *pgdp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 
-	page &= PAGE_MASK;
-	pgdp = pgd_offset(mm, page);
-	pmdp = pmd_offset(pgdp, page);
-	ptep = pte_offset(pmdp, page);
+	/*
+	 * If ownes no valid ASID yet, cannot possibly have gotten
+	 * this page into the cache.
+	 */
+	if (cpu_context(smp_processor_id(), mm) == 0)
+		return;
+
+	addr &= PAGE_MASK;
+	pgdp = pgd_offset(mm, addr);
+	pudp = pud_offset(pgdp, addr);
+	pmdp = pmd_offset(pudp, addr);
+	ptep = pte_offset(pmdp, addr);
 
 	/*
 	 * If the page isn't marked valid, the page cannot possibly be
@@ -395,12 +411,12 @@
 	 */
 	if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
 		if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
-			r4k_blast_dcache_page(page);
+			r4k_blast_dcache_page(addr);
 			if (exec && !cpu_icache_snoops_remote_store)
-				r4k_blast_scache_page(page);
+				r4k_blast_scache_page(addr);
 		}
 		if (exec)
-			r4k_blast_icache_page(page);
+			r4k_blast_icache_page(addr);
 
 		return;
 	}
@@ -409,36 +425,30 @@
 	 * Do indexed flush, too much work to get the (possible) TLB refills
 	 * to work correctly.
 	 */
-	page = INDEX_BASE + (page & (dcache_size - 1));
+	addr = INDEX_BASE + (addr & (dcache_size - 1));
 	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
-		r4k_blast_dcache_page_indexed(page);
+		r4k_blast_dcache_page_indexed(addr);
 		if (exec && !cpu_icache_snoops_remote_store)
-			r4k_blast_scache_page_indexed(page);
+			r4k_blast_scache_page_indexed(addr);
 	}
 	if (exec) {
 		if (cpu_has_vtag_icache) {
 			int cpu = smp_processor_id();
 
-			if (cpu_context(cpu, vma->vm_mm) != 0)
-				drop_mmu_context(vma->vm_mm, cpu);
+			if (cpu_context(cpu, mm) != 0)
+				drop_mmu_context(mm, cpu);
 		} else
-			r4k_blast_icache_page_indexed(page);
+			r4k_blast_icache_page_indexed(addr);
 	}
 }
 
-static void r4k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
+static void r4k_flush_cache_page(struct vm_area_struct *vma,
+	unsigned long addr, unsigned long pfn)
 {
 	struct flush_cache_page_args args;
 
-	/*
-	 * If ownes no valid ASID yet, cannot possibly have gotten
-	 * this page into the cache.
-	 */
-	if (cpu_context(smp_processor_id(), vma->vm_mm) == 0)
-		return;
-
 	args.vma = vma;
-	args.page = page;
+	args.addr = addr;
 
 	on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
 }
@@ -454,16 +464,16 @@
 }
 
 struct flush_icache_range_args {
-	unsigned long start;
-	unsigned long end;
+	unsigned long __user start;
+	unsigned long __user end;
 };
 
 static inline void local_r4k_flush_icache_range(void *args)
 {
 	struct flush_icache_range_args *fir_args = args;
-	unsigned long dc_lsize = current_cpu_data.dcache.linesz;
-	unsigned long ic_lsize = current_cpu_data.icache.linesz;
-	unsigned long sc_lsize = current_cpu_data.scache.linesz;
+	unsigned long dc_lsize = cpu_dcache_line_size();
+	unsigned long ic_lsize = cpu_icache_line_size();
+	unsigned long sc_lsize = cpu_scache_line_size();
 	unsigned long start = fir_args->start;
 	unsigned long end = fir_args->end;
 	unsigned long addr, aend;
@@ -472,6 +482,7 @@
 		if (end - start > dcache_size) {
 			r4k_blast_dcache();
 		} else {
+			R4600_HIT_CACHEOP_WAR_IMPL;
 			addr = start & ~(dc_lsize - 1);
 			aend = (end - 1) & ~(dc_lsize - 1);
 
@@ -492,7 +503,7 @@
 				aend = (end - 1) & ~(sc_lsize - 1);
 
 				while (1) {
-					/* Hit_Writeback_Inv_D */
+					/* Hit_Writeback_Inv_SD */
 					protected_writeback_scache_line(addr);
 					if (addr == aend)
 						break;
@@ -517,7 +528,8 @@
 	}
 }
 
-static void r4k_flush_icache_range(unsigned long start, unsigned long end)
+static void r4k_flush_icache_range(unsigned long __user start,
+	unsigned long __user end)
 {
 	struct flush_icache_range_args args;
 
@@ -525,6 +537,7 @@
 	args.end = end;
 
 	on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
+	instruction_hazard();
 }
 
 /*
@@ -613,7 +626,7 @@
 	BUG_ON(size == 0);
 
 	if (cpu_has_subset_pcaches) {
-		unsigned long sc_lsize = current_cpu_data.scache.linesz;
+		unsigned long sc_lsize = cpu_scache_line_size();
 
 		if (size >= scache_size) {
 			r4k_blast_scache();
@@ -639,7 +652,7 @@
 	if (size >= dcache_size) {
 		r4k_blast_dcache();
 	} else {
-		unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+		unsigned long dc_lsize = cpu_dcache_line_size();
 
 		R4600_HIT_CACHEOP_WAR_IMPL;
 		a = addr & ~(dc_lsize - 1);
@@ -663,7 +676,7 @@
 	BUG_ON(size == 0);
 
 	if (cpu_has_subset_pcaches) {
-		unsigned long sc_lsize = current_cpu_data.scache.linesz;
+		unsigned long sc_lsize = cpu_scache_line_size();
 
 		if (size >= scache_size) {
 			r4k_blast_scache();
@@ -684,7 +697,7 @@
 	if (size >= dcache_size) {
 		r4k_blast_dcache();
 	} else {
-		unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+		unsigned long dc_lsize = cpu_dcache_line_size();
 
 		R4600_HIT_CACHEOP_WAR_IMPL;
 		a = addr & ~(dc_lsize - 1);
@@ -708,9 +721,9 @@
  */
 static void local_r4k_flush_cache_sigtramp(void * arg)
 {
-	unsigned long ic_lsize = current_cpu_data.icache.linesz;
-	unsigned long dc_lsize = current_cpu_data.dcache.linesz;
-	unsigned long sc_lsize = current_cpu_data.scache.linesz;
+	unsigned long ic_lsize = cpu_icache_line_size();
+	unsigned long dc_lsize = cpu_dcache_line_size();
+	unsigned long sc_lsize = cpu_scache_line_size();
 	unsigned long addr = (unsigned long) arg;
 
 	R4600_HIT_CACHEOP_WAR_IMPL;
@@ -762,6 +775,7 @@
 
 	for (addr = INDEX_BASE; addr <= INDEX_BASE + 4096; addr += ic_lsize) {
 		__asm__ __volatile__ (
+			".set push\n\t"
 			".set noreorder\n\t"
 			".set mips3\n\t"
 			"cache\t%1, 0(%0)\n\t"
@@ -776,8 +790,7 @@
 			"cache\t%1, 0x1000(%0)\n\t"
 			"cache\t%1, 0x2000(%0)\n\t"
 			"cache\t%1, 0x3000(%0)\n\t"
-			".set\tmips0\n\t"
-			".set\treorder\n\t"
+			".set pop\n"
 			:
 			: "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill));
 	}
@@ -1011,9 +1024,19 @@
 	 * normally they'd suffer from aliases but magic in the hardware deals
 	 * with that for us so we don't need to take care ourselves.
 	 */
-	if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000)
-		if (c->dcache.waysize > PAGE_SIZE)
-		        c->dcache.flags |= MIPS_CACHE_ALIASES;
+	switch (c->cputype) {
+	case CPU_20KC:
+	case CPU_25KF:
+	case CPU_R10000:
+	case CPU_R12000:
+	case CPU_SB1:
+		break;
+	case CPU_24K:
+		if (!(read_c0_config7() & (1 << 16)))
+	default:
+			if (c->dcache.waysize > PAGE_SIZE)
+				c->dcache.flags |= MIPS_CACHE_ALIASES;
+	}
 
 	switch (c->cputype) {
 	case CPU_20KC:
@@ -1024,7 +1047,11 @@
 		c->icache.flags |= MIPS_CACHE_VTAG;
 		break;
 
+	case CPU_AU1000:
 	case CPU_AU1500:
+	case CPU_AU1100:
+	case CPU_AU1550:
+	case CPU_AU1200:
 		c->icache.flags |= MIPS_CACHE_IC_F_DC;
 		break;
 	}
@@ -1102,7 +1129,6 @@
 	return 1;
 }
 
-typedef int (*probe_func_t)(unsigned long);
 extern int r5k_sc_init(void);
 extern int rm7k_sc_init(void);
 
@@ -1110,7 +1136,6 @@
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 	unsigned int config = read_c0_config();
-	probe_func_t probe_scache_kseg1;
 	int sc_present = 0;
 
 	/*
@@ -1123,8 +1148,7 @@
 	case CPU_R4000MC:
 	case CPU_R4400SC:
 	case CPU_R4400MC:
-		probe_scache_kseg1 = (probe_func_t) (CKSEG1ADDR(&probe_scache));
-		sc_present = probe_scache_kseg1(config);
+		sc_present = run_uncached(probe_scache);
 		if (sc_present)
 			c->options |= MIPS_CPU_CACHE_CDEX_S;
 		break;
@@ -1198,7 +1222,7 @@
 	}
 }
 
-void __init ld_mmu_r4xx0(void)
+void __init r4k_cache_init(void)
 {
 	extern void build_clear_page(void);
 	extern void build_copy_page(void);
@@ -1206,15 +1230,11 @@
 	struct cpuinfo_mips *c = &current_cpu_data;
 
 	/* Default cache error handler for R4000 and R5000 family */
-	memcpy((void *)(CAC_BASE   + 0x100), &except_vec2_generic, 0x80);
-	memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_generic, 0x80);
+	set_uncached_handler (0x100, &except_vec2_generic, 0x80);
 
 	probe_pcache();
 	setup_scache();
 
-	if (c->dcache.sets * c->dcache.ways > PAGE_SIZE)
-		c->dcache.flags |= MIPS_CACHE_ALIASES;
-
 	r4k_blast_dcache_page_setup();
 	r4k_blast_dcache_page_indexed_setup();
 	r4k_blast_dcache_setup();
@@ -1252,9 +1272,8 @@
 	_dma_cache_inv		= r4k_dma_cache_inv;
 #endif
 
-	__flush_cache_all();
-	coherency_setup();
-
 	build_clear_page();
 	build_copy_page();
+	local_r4k___flush_cache_all(NULL);
+	coherency_setup();
 }
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 502f68c..2f08b53 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -235,7 +235,7 @@
 /*
  * Invalidate all caches on this CPU
  */
-static void local_sb1___flush_cache_all(void)
+static void __attribute_used__ local_sb1___flush_cache_all(void)
 {
 	__sb1_writeback_inv_dcache_all();
 	__sb1_flush_icache_all();
@@ -492,19 +492,17 @@
 }
 
 /*
- * This is called from loadmmu.c.  We have to set up all the
+ * This is called from cache.c.  We have to set up all the
  * memory management function pointers, as well as initialize
  * the caches and tlbs
  */
-void ld_mmu_sb1(void)
+void sb1_cache_init(void)
 {
 	extern char except_vec2_sb1;
 	extern char handle_vec2_sb1;
 
 	/* Special cache error handler for SB1 */
-	memcpy((void *)(CAC_BASE   + 0x100), &except_vec2_sb1, 0x80);
-	memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_sb1, 0x80);
-	memcpy((void *)CKSEG1ADDR(&handle_vec2_sb1), &handle_vec2_sb1, 0x80);
+	set_uncached_handler (0x100, &except_vec2_sb1, 0x80);
 
 	probe_cache_sizes();
 
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index ff5afab..0a97a94 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -167,15 +167,16 @@
 static void tx39_flush_cache_range(struct vm_area_struct *vma,
 	unsigned long start, unsigned long end)
 {
-	struct mm_struct *mm = vma->vm_mm;
+	int exec;
 
-	if (!cpu_has_dc_aliases)
+	if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
 		return;
 
-	if (cpu_context(smp_processor_id(), mm) != 0) {
+	exec = vma->vm_flags & VM_EXEC;
+	if (cpu_has_dc_aliases || exec)
 		tx39_blast_dcache();
+	if (exec)
 		tx39_blast_icache();
-	}
 }
 
 static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
@@ -183,6 +184,7 @@
 	int exec = vma->vm_flags & VM_EXEC;
 	struct mm_struct *mm = vma->vm_mm;
 	pgd_t *pgdp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 
@@ -195,7 +197,8 @@
 
 	page &= PAGE_MASK;
 	pgdp = pgd_offset(mm, page);
-	pmdp = pmd_offset(pgdp, page);
+	pudp = pud_offset(pgdp, page);
+	pmdp = pmd_offset(pudp, page);
 	ptep = pte_offset(pmdp, page);
 
 	/*
@@ -407,7 +410,7 @@
 	}
 }
 
-void __init ld_mmu_tx39(void)
+void __init tx39_cache_init(void)
 {
 	extern void build_clear_page(void);
 	extern void build_copy_page(void);
@@ -490,4 +493,5 @@
 
 	build_clear_page();
 	build_copy_page();
+	tx39h_flush_icache_all();
 }
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 1d95cdb..314701a 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -23,8 +23,10 @@
 void (*flush_cache_mm)(struct mm_struct *mm);
 void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end);
-void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
-void (*flush_icache_range)(unsigned long start, unsigned long end);
+void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
+	unsigned long pfn);
+void (*flush_icache_range)(unsigned long __user start,
+	unsigned long __user end);
 void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
 /* MIPS specific cache operations */
@@ -32,6 +34,8 @@
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
 
+EXPORT_SYMBOL(flush_data_cache_page);
+
 #ifdef CONFIG_DMA_NONCOHERENT
 
 /* DMA cache operations. */
@@ -49,10 +53,12 @@
  * We could optimize the case where the cache argument is not BCACHE but
  * that seems very atypical use ...
  */
-asmlinkage int sys_cacheflush(unsigned long addr, unsigned long int bytes,
-	unsigned int cache)
+asmlinkage int sys_cacheflush(unsigned long __user addr,
+	unsigned long bytes, unsigned int cache)
 {
-	if (!access_ok(VERIFY_WRITE, (void *) addr, bytes))
+	if (bytes == 0)
+		return 0;
+	if (!access_ok(VERIFY_WRITE, (void __user *) addr, bytes))
 		return -EFAULT;
 
 	flush_icache_range(addr, addr + bytes);
@@ -100,58 +106,48 @@
 	}
 }
 
-extern void ld_mmu_r23000(void);
-extern void ld_mmu_r4xx0(void);
-extern void ld_mmu_tx39(void);
-extern void ld_mmu_r6000(void);
-extern void ld_mmu_tfp(void);
-extern void ld_mmu_andes(void);
-extern void ld_mmu_sb1(void);
+#define __weak __attribute__((weak))
+
+static char cache_panic[] __initdata = "Yeee, unsupported cache architecture.";
 
 void __init cpu_cache_init(void)
 {
-	if (cpu_has_4ktlb) {
-#if defined(CONFIG_CPU_R4X00)  || defined(CONFIG_CPU_VR41XX) || \
-    defined(CONFIG_CPU_R4300)  || defined(CONFIG_CPU_R5000)  || \
-    defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432)  || \
-    defined(CONFIG_CPU_R5500)  || defined(CONFIG_CPU_MIPS32) || \
-    defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \
-    defined(CONFIG_CPU_RM7000) || defined(CONFIG_CPU_RM9000)
-		ld_mmu_r4xx0();
-#endif
-	} else switch (current_cpu_data.cputype) {
-#ifdef CONFIG_CPU_R3000
-	case CPU_R2000:
-	case CPU_R3000:
-	case CPU_R3000A:
-	case CPU_R3081E:
-		ld_mmu_r23000();
-		break;
-#endif
-#ifdef CONFIG_CPU_TX39XX
-	case CPU_TX3912:
-	case CPU_TX3922:
-	case CPU_TX3927:
-		ld_mmu_tx39();
-		break;
-#endif
-#ifdef CONFIG_CPU_R10000
-	case CPU_R10000:
-	case CPU_R12000:
-		ld_mmu_r4xx0();
-		break;
-#endif
-#ifdef CONFIG_CPU_SB1
-	case CPU_SB1:
-		ld_mmu_sb1();
-		break;
-#endif
+	if (cpu_has_3k_cache) {
+		extern void __weak r3k_cache_init(void);
 
-	case CPU_R8000:
-		panic("R8000 is unsupported");
-		break;
-
-	default:
-		panic("Yeee, unsupported cache architecture.");
+		r3k_cache_init();
+		return;
 	}
+	if (cpu_has_6k_cache) {
+		extern void __weak r6k_cache_init(void);
+
+		r6k_cache_init();
+		return;
+	}
+	if (cpu_has_4k_cache) {
+		extern void __weak r4k_cache_init(void);
+
+		r4k_cache_init();
+		return;
+	}
+	if (cpu_has_8k_cache) {
+		extern void __weak r8k_cache_init(void);
+
+		r8k_cache_init();
+		return;
+	}
+	if (cpu_has_tx39_cache) {
+		extern void __weak tx39_cache_init(void);
+
+		tx39_cache_init();
+		return;
+	}
+	if (cpu_has_sb1_cache) {
+		extern void __weak sb1_cache_init(void);
+
+		sb1_cache_init();
+		return;
+	}
+
+	panic(cache_panic);
 }
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
index 7166ffe..1cf3c60 100644
--- a/arch/mips/mm/cerr-sb1.c
+++ b/arch/mips/mm/cerr-sb1.c
@@ -19,13 +19,19 @@
 #include <linux/sched.h>
 #include <asm/mipsregs.h>
 #include <asm/sibyte/sb1250.h>
-
-#ifndef CONFIG_SIBYTE_BUS_WATCHER
-#include <asm/io.h>
 #include <asm/sibyte/sb1250_regs.h>
+
+#if !defined(CONFIG_SIBYTE_BUS_WATCHER) || defined(CONFIG_SIBYTE_BW_TRACE)
+#include <asm/io.h>
 #include <asm/sibyte/sb1250_scd.h>
 #endif
 
+/*
+ * We'd like to dump the L2_ECC_TAG register on errors, but errata make
+ * that unsafe... So for now we don't.  (BCM1250/BCM112x erratum SOC-48.)
+ */
+#undef DUMP_L2_ECC_TAG_ON_ERROR
+
 /* SB1 definitions */
 
 /* XXX should come from config1 XXX */
@@ -139,12 +145,18 @@
 static void check_bus_watcher(void)
 {
 	uint32_t status, l2_err, memio_err;
+#ifdef DUMP_L2_ECC_TAG_ON_ERROR
+	uint64_t l2_tag;
+#endif
 
 	/* Destructive read, clears register and interrupt */
 	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
 	/* Bit 31 is always on, but there's no #define for that */
 	if (status & ~(1UL << 31)) {
 		l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
+#ifdef DUMP_L2_ECC_TAG_ON_ERROR
+		l2_tag = in64(IO_SPACE_BASE | A_L2_ECC_TAG);
+#endif
 		memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
 		prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
 		prom_printf("\nLast recorded signature:\n");
@@ -153,6 +165,9 @@
 		       (int)(G_SCD_BERR_TID(status) >> 6),
 		       (int)G_SCD_BERR_RID(status),
 		       (int)G_SCD_BERR_DCODE(status));
+#ifdef DUMP_L2_ECC_TAG_ON_ERROR
+		prom_printf("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
+#endif
 	} else {
 		prom_printf("Bus watcher indicates no error\n");
 	}
@@ -166,6 +181,16 @@
 	uint64_t cerr_dpa;
 	uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res;
 
+#ifdef CONFIG_SIBYTE_BW_TRACE
+	/* Freeze the trace buffer now */
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+	csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG);
+#else
+	csr_out32(M_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG);
+#endif
+	prom_printf("Trace buffer frozen\n");
+#endif
+
 	prom_printf("Cache error exception on CPU %x:\n",
 		    (read_c0_prid() >> 25) & 0x7);
 
@@ -229,11 +254,19 @@
 
 	check_bus_watcher();
 
-	while (1);
 	/*
-	 * This tends to make things get really ugly; let's just stall instead.
-	 *    panic("Can't handle the cache error!");
+	 * Calling panic() when a fatal cache error occurs scrambles the
+	 * state of the system (and the cache), making it difficult to
+	 * investigate after the fact.  However, if you just stall the CPU,
+	 * the other CPU may keep on running, which is typically very
+	 * undesirable.
 	 */
+#ifdef CONFIG_SB1_CERR_STALL
+	while (1)
+		;
+#else
+	panic("unhandled cache error");
+#endif
 }
 
 
@@ -434,7 +467,8 @@
 };
 
 #define DC_TAG_VALID(state) \
-    (((state) == 0xf) || ((state) == 0x13) || ((state) == 0x19) || ((state == 0x16)) || ((state) == 0x1c))
+    (((state) == 0x0) || ((state) == 0xf) || ((state) == 0x13) || \
+     ((state) == 0x19) || ((state) == 0x16) || ((state) == 0x1c))
 
 static char *dc_state_str(unsigned char state)
 {
@@ -505,6 +539,7 @@
 			uint64_t datalo;
 			uint32_t datalohi, datalolo, datahi;
 			int offset;
+			char bad_ecc = 0;
 
 			for (offset = 0; offset < 4; offset++) {
 				/* Index-load-data-D */
@@ -525,8 +560,7 @@
 				ecc = dc_ecc(datalo);
 				if (ecc != datahi) {
 					int bits = 0;
-					prom_printf("  ** bad ECC (%02x %02x) ->",
-						    datahi, ecc);
+					bad_ecc |= 1 << (3-offset);
 					ecc ^= datahi;
 					while (ecc) {
 						if (ecc & 1) bits++;
@@ -537,6 +571,10 @@
 				prom_printf("  %02X-%016llX", datahi, datalo);
 			}
 			prom_printf("\n");
+			if (bad_ecc)
+				prom_printf("  dwords w/ bad ECC: %d %d %d %d\n",
+					    !!(bad_ecc & 8), !!(bad_ecc & 4),
+					    !!(bad_ecc & 2), !!(bad_ecc & 1));
 		}
 	}
 	return res;
diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S
index 2c3a23a..0e71580 100644
--- a/arch/mips/mm/cex-sb1.S
+++ b/arch/mips/mm/cex-sb1.S
@@ -64,6 +64,10 @@
 	sd	k0,0x170($0)
 	sd	k1,0x178($0)
 
+#if CONFIG_SB1_CEX_ALWAYS_FATAL
+	j	handle_vec2_sb1
+	 nop
+#else
 	/*
 	 * M_ERRCTL_RECOVERABLE is bit 31, which makes it easy to tell
 	 * if we can fast-path out of here for a h/w-recovered error.
@@ -134,6 +138,7 @@
 	/* Unrecoverable Icache or Dcache error; log it and/or fail */
 	j	handle_vec2_sb1
 	 nop
+#endif
 
 END(except_vec2_sb1)
 
diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c
index 97a50d3..f6b3c72 100644
--- a/arch/mips/mm/dma-coherent.c
+++ b/arch/mips/mm/dma-coherent.c
@@ -9,16 +9,16 @@
  */
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/dma-mapping.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/pci.h>
 
 #include <asm/cache.h>
 #include <asm/io.h>
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
 	/* ignore region specifiers */
@@ -39,7 +39,7 @@
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 	__attribute__((alias("dma_alloc_noncoherent")));
 
 EXPORT_SYMBOL(dma_alloc_coherent);
diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c
index aa7c94b..8da19fd 100644
--- a/arch/mips/mm/dma-ip27.c
+++ b/arch/mips/mm/dma-ip27.c
@@ -22,7 +22,7 @@
 	pdev_to_baddr(to_pci_dev(dev), (addr))
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
 
@@ -44,7 +44,7 @@
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 	__attribute__((alias("dma_alloc_noncoherent")));
 
 EXPORT_SYMBOL(dma_alloc_coherent);
diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c
index 2cbe196..a7e3072 100644
--- a/arch/mips/mm/dma-ip32.c
+++ b/arch/mips/mm/dma-ip32.c
@@ -37,7 +37,7 @@
 #define RAM_OFFSET_MASK	0x3fffffff
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
 	/* ignore region specifiers */
@@ -61,7 +61,7 @@
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
 
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
index 59e54f1..cd4ea84 100644
--- a/arch/mips/mm/dma-noncoherent.c
+++ b/arch/mips/mm/dma-noncoherent.c
@@ -24,7 +24,7 @@
  */
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
 	/* ignore region specifiers */
@@ -45,7 +45,7 @@
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-	dma_addr_t * dma_handle, int gfp)
+	dma_addr_t * dma_handle, gfp_t gfp)
 {
 	void *ret;
 
@@ -105,22 +105,7 @@
 {
 	unsigned long addr = (unsigned long) ptr;
 
-	switch (direction) {
-	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
-		break;
-
-	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
-		break;
-
-	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
-		break;
-
-	default:
-		BUG();
-	}
+	__dma_sync(addr, size, direction);
 
 	return virt_to_phys(ptr);
 }
@@ -133,22 +118,7 @@
 	unsigned long addr;
 	addr = dma_addr + PAGE_OFFSET;
 
-	switch (direction) {
-	case DMA_TO_DEVICE:
-		//dma_cache_wback(addr, size);
-		break;
-
-	case DMA_FROM_DEVICE:
-		//dma_cache_inv(addr, size);
-		break;
-
-	case DMA_BIDIRECTIONAL:
-		//dma_cache_wback_inv(addr, size);
-		break;
-
-	default:
-		BUG();
-	}
+	//__dma_sync(addr, size, direction);
 }
 
 EXPORT_SYMBOL(dma_unmap_single);
@@ -164,10 +134,11 @@
 		unsigned long addr;
 
 		addr = (unsigned long) page_address(sg->page);
-		if (addr)
+		if (addr) {
 			__dma_sync(addr + sg->offset, sg->length, direction);
-		sg->dma_address = (dma_addr_t)
-			(page_to_phys(sg->page) + sg->offset);
+			sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
+					  + sg->offset;
+		}
 	}
 
 	return nents;
@@ -218,9 +189,8 @@
 
 	for (i = 0; i < nhwentries; i++, sg++) {
 		addr = (unsigned long) page_address(sg->page);
-		if (!addr)
-			continue;
-		dma_cache_wback_inv(addr + sg->offset, sg->length);
+		if (addr)
+			__dma_sync(addr + sg->offset, sg->length, direction);
 	}
 }
 
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index ec8077c..2d9624f 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -25,6 +25,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
+#include <asm/highmem.h>		/* For VMALLOC_END */
 
 /*
  * This routine handles page faults.  It determines the address,
@@ -57,7 +58,7 @@
 	 * only copy the information from the master page table,
 	 * nothing more.
 	 */
-	if (unlikely(address >= VMALLOC_START))
+	if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END))
 		goto vmalloc_fault;
 
 	/*
@@ -140,7 +141,7 @@
 		info.si_signo = SIGSEGV;
 		info.si_errno = 0;
 		/* info.si_code has been set above */
-		info.si_addr = (void *) address;
+		info.si_addr = (void __user *) address;
 		force_sig_info(SIGSEGV, &info, tsk);
 		return;
 	}
@@ -196,7 +197,7 @@
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *) address;
+	info.si_addr = (void __user *) address;
 	force_sig_info(SIGBUS, &info, tsk);
 
 	return;
@@ -212,6 +213,7 @@
 		 */
 		int offset = __pgd_offset(address);
 		pgd_t *pgd, *pgd_k;
+		pud_t *pud, *pud_k;
 		pmd_t *pmd, *pmd_k;
 		pte_t *pte_k;
 
@@ -222,8 +224,13 @@
 			goto no_context;
 		set_pgd(pgd, *pgd_k);
 
-		pmd = pmd_offset(pgd, address);
-		pmd_k = pmd_offset(pgd_k, address);
+		pud = pud_offset(pgd, address);
+		pud_k = pud_offset(pgd_k, address);
+		if (!pud_present(*pud_k))
+			goto no_context;
+
+		pmd = pmd_offset(pud, address);
+		pmd_k = pmd_offset(pud_k, address);
 		if (!pmd_present(*pmd_k))
 			goto no_context;
 		set_pmd(pmd, *pmd_k);
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index dd5e2e3..1f7b37b 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -83,6 +83,25 @@
 	preempt_check_resched();
 }
 
+/*
+ * This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	inc_preempt_count();
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
+	flush_tlb_one(vaddr);
+
+	return (void*) vaddr;
+}
+
 struct page *__kmap_atomic_to_page(void *ptr)
 {
 	unsigned long idx, vaddr = (unsigned long)ptr;
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index dc6830b..f75ab74 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -83,7 +83,7 @@
 pgprot_t kmap_prot;
 
 #define kmap_get_fixmap_pte(vaddr)					\
-	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
 
 static void __init kmap_init(void)
 {
@@ -96,36 +96,42 @@
 	kmap_prot = PAGE_KERNEL;
 }
 
-#ifdef CONFIG_64BIT
-static void __init fixrange_init(unsigned long start, unsigned long end,
+#ifdef CONFIG_32BIT
+void __init fixrange_init(unsigned long start, unsigned long end,
 	pgd_t *pgd_base)
 {
 	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
-	int i, j;
+	int i, j, k;
 	unsigned long vaddr;
 
 	vaddr = start;
 	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
+	j = __pud_offset(vaddr);
+	k = __pmd_offset(vaddr);
 	pgd = pgd_base + i;
 
 	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-		pmd = (pmd_t *)pgd;
-		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-			if (pmd_none(*pmd)) {
-				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-				set_pmd(pmd, __pmd(pte));
-				if (pte != pte_offset_kernel(pmd, 0))
-					BUG();
+		pud = (pud_t *)pgd;
+		for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+			pmd = (pmd_t *)pud;
+			for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+				if (pmd_none(*pmd)) {
+					pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+					set_pmd(pmd, __pmd(pte));
+					if (pte != pte_offset_kernel(pmd, 0))
+						BUG();
+				}
+				vaddr += PMD_SIZE;
 			}
-			vaddr += PMD_SIZE;
+			k = 0;
 		}
 		j = 0;
 	}
 }
-#endif /* CONFIG_64BIT */
+#endif /* CONFIG_32BIT */
 #endif /* CONFIG_HIGHMEM */
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index adf3522..3101d1d 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -55,7 +55,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -77,11 +77,15 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
+		pud_t *pud;
 		pmd_t *pmd;
-		pmd = pmd_alloc(&init_mm, dir, address);
+
 		error = -ENOMEM;
+		pud = pud_alloc(&init_mm, dir, address);
+		if (!pud)
+			break;
+		pmd = pmd_alloc(&init_mm, pud, address);
 		if (!pmd)
 			break;
 		if (remap_area_pmd(pmd, address, end - address,
@@ -91,21 +95,11 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return error;
 }
 
 /*
- * Allow physical addresses to be fixed up to help 36 bit peripherals.
- */
-phys_t __attribute__ ((weak))
-fixup_bigphys_addr(phys_t phys_addr, phys_t size)
-{
-	return phys_addr;
-}
-
-/*
  * Generic mapping function (not visible outside):
  */
 
@@ -121,7 +115,7 @@
 
 #define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
 
-void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
+void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
 {
 	struct vm_struct * area;
 	unsigned long offset;
@@ -141,7 +135,7 @@
 	 */
 	if (IS_LOW512(phys_addr) && IS_LOW512(last_addr) &&
 	    flags == _CACHE_UNCACHED)
-		return (void *) KSEG1ADDR(phys_addr);
+		return (void __iomem *) CKSEG1ADDR(phys_addr);
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
@@ -177,10 +171,10 @@
 		return NULL;
 	}
 
-	return (void *) (offset + (char *)addr);
+	return (void __iomem *) (offset + (char *)addr);
 }
 
-#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1)
+#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
 
 void __iounmap(volatile void __iomem *addr)
 {
@@ -190,10 +184,8 @@
 		return;
 
 	p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
-	if (!p) {
+	if (!p)
 		printk(KERN_ERR "iounmap: bad address %p\n", addr);
-		return;
-	}
 
         kfree(p);
 }
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
index 9f8b165..f51e180 100644
--- a/arch/mips/mm/pg-r4k.c
+++ b/arch/mips/mm/pg-r4k.c
@@ -25,7 +25,10 @@
 #include <asm/cpu.h>
 #include <asm/war.h>
 
-#define half_scache_line_size()		(cpu_scache_line_size() >> 1)
+#define half_scache_line_size()	(cpu_scache_line_size() >> 1)
+#define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
+#define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
+
 
 /*
  * Maximum sizes:
@@ -198,15 +201,15 @@
 	if (store_offset & (cpu_dcache_line_size() - 1))
 		return;
 
-	if (R4600_V1_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2010)) {
+	if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
 		build_nop();
 		build_nop();
 		build_nop();
 		build_nop();
 	}
 
-	if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
-		build_insn_word(0x8c200000);	/* lw      $zero, ($at) */
+	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
+		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
 
 	mi.c_format.opcode     = cache_op;
 	mi.c_format.rs         = 4;		/* $a0 */
@@ -361,7 +364,7 @@
 
 	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0));
 
-	if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
 
 dest = label();
@@ -404,9 +407,6 @@
 
 	build_jr_ra();
 
-	flush_icache_range((unsigned long)&clear_page_array,
-	                   (unsigned long) epc);
-
 	BUG_ON(epc > clear_page_array + ARRAY_SIZE(clear_page_array));
 }
 
@@ -420,7 +420,7 @@
 
 	build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0));
 
-	if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
 
 dest = label();
@@ -482,8 +482,5 @@
 
 	build_jr_ra();
 
-	flush_icache_range((unsigned long)&copy_page_array,
-	                   (unsigned long) epc);
-
 	BUG_ON(epc > copy_page_array + ARRAY_SIZE(copy_page_array));
 }
diff --git a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c
index 1b6df71..148c65b 100644
--- a/arch/mips/mm/pg-sb1.c
+++ b/arch/mips/mm/pg-sb1.c
@@ -60,7 +60,8 @@
 	"	.set	noreorder	\n"
 #ifdef CONFIG_CPU_HAS_PREFETCH
 	"	daddiu	%0, %0, 128	\n"
-	"	pref	" SB1_PREF_STORE_STREAMED_HINT ", -128(%0)  \n"  /* Prefetch the first 4 lines */
+	"	pref	" SB1_PREF_STORE_STREAMED_HINT ", -128(%0)  \n"
+					     /* Prefetch the first 4 lines */
 	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -96(%0)  \n"
 	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -64(%0)  \n"
 	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -32(%0)  \n"
@@ -106,7 +107,8 @@
 #ifdef CONFIG_CPU_HAS_PREFETCH
 	"	daddiu	%0, %0, 128	\n"
 	"	daddiu	%1, %1, 128	\n"
-	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ", -128(%0)\n"  /* Prefetch the first 4 lines */
+	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ", -128(%0)\n"
+					     /* Prefetch the first 4 lines */
 	"	pref	" SB1_PREF_STORE_STREAMED_HINT ", -128(%1)\n"
 	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ",  -96(%0)\n"
 	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -96(%1)\n"
@@ -207,66 +209,73 @@
 	u64 pad_b;
 } dmadscr_t;
 
-static dmadscr_t page_descr[NR_CPUS] __attribute__((aligned(SMP_CACHE_BYTES)));
+static dmadscr_t page_descr[DM_NUM_CHANNELS]
+	__attribute__((aligned(SMP_CACHE_BYTES)));
 
 void sb1_dma_init(void)
 {
-	int cpu = smp_processor_id();
-	u64 base_val = CPHYSADDR(&page_descr[cpu]) | V_DM_DSCR_BASE_RINGSZ(1);
+	int i;
 
-	bus_writeq(base_val,
-		   (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
-	bus_writeq(base_val | M_DM_DSCR_BASE_RESET,
-		   (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
-	bus_writeq(base_val | M_DM_DSCR_BASE_ENABL,
-		   (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+	for (i = 0; i < DM_NUM_CHANNELS; i++) {
+		const u64 base_val = CPHYSADDR(&page_descr[i]) |
+				     V_DM_DSCR_BASE_RINGSZ(1);
+		volatile void *base_reg =
+			IOADDR(A_DM_REGISTER(i, R_DM_DSCR_BASE));
+
+		__raw_writeq(base_val, base_reg);
+		__raw_writeq(base_val | M_DM_DSCR_BASE_RESET, base_reg);
+		__raw_writeq(base_val | M_DM_DSCR_BASE_ENABL, base_reg);
+	}
 }
 
 void clear_page(void *page)
 {
-	int cpu = smp_processor_id();
+	u64 to_phys = CPHYSADDR(page);
+	unsigned int cpu = smp_processor_id();
 
-	/* if the page is above Kseg0, use old way */
+	/* if the page is not in KSEG0, use old way */
 	if ((long)KSEGX(page) != (long)CKSEG0)
 		return clear_page_cpu(page);
 
-	page_descr[cpu].dscr_a = CPHYSADDR(page) | M_DM_DSCRA_ZERO_MEM | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
+	page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_ZERO_MEM |
+				 M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
 	page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
-	bus_writeq(1, (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
+	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 
 	/*
 	 * Don't really want to do it this way, but there's no
 	 * reliable way to delay completion detection.
 	 */
-	while (!(bus_readq((void *)(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) &
-			   M_DM_DSCR_BASE_INTERRUPT))))
+	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
+		 & M_DM_DSCR_BASE_INTERRUPT))
 		;
-	bus_readq((void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 }
 
 void copy_page(void *to, void *from)
 {
-	unsigned long from_phys = CPHYSADDR(from);
-	unsigned long to_phys = CPHYSADDR(to);
-	int cpu = smp_processor_id();
+	u64 from_phys = CPHYSADDR(from);
+	u64 to_phys = CPHYSADDR(to);
+	unsigned int cpu = smp_processor_id();
 
-	/* if either page is above Kseg0, use old way */
+	/* if any page is not in KSEG0, use old way */
 	if ((long)KSEGX(to) != (long)CKSEG0
 	    || (long)KSEGX(from) != (long)CKSEG0)
 		return copy_page_cpu(to, from);
 
-	page_descr[cpu].dscr_a = CPHYSADDR(to_phys) | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
-	page_descr[cpu].dscr_b = CPHYSADDR(from_phys) | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
-	bus_writeq(1, (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
+	page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_L2C_DEST |
+				 M_DM_DSCRA_INTERRUPT;
+	page_descr[cpu].dscr_b = from_phys | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
+	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 
 	/*
 	 * Don't really want to do it this way, but there's no
 	 * reliable way to delay completion detection.
 	 */
-	while (!(bus_readq((void *)(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) &
-				    M_DM_DSCR_BASE_INTERRUPT))))
+	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
+		 & M_DM_DSCR_BASE_INTERRUPT))
 		;
-	bus_readq((void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 }
 
 #else /* !CONFIG_SIBYTE_DMA_PAGEOPS */
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index 4f07f81..4a3c491 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
+#include <asm/fixmap.h>
 #include <asm/pgtable.h>
 
 void pgd_init(unsigned long page)
@@ -29,42 +30,12 @@
 	}
 }
 
-#ifdef CONFIG_HIGHMEM
-static void __init fixrange_init (unsigned long start, unsigned long end,
-	pgd_t *pgd_base)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-	int i, j;
-	unsigned long vaddr;
-
-	vaddr = start;
-	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
-	pgd = pgd_base + i;
-
-	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-		pmd = (pmd_t *)pgd;
-		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-			if (pmd_none(*pmd)) {
-				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-				set_pmd(pmd, __pmd((unsigned long)pte));
-				if (pte != pte_offset_kernel(pmd, 0))
-					BUG();
-			}
-			vaddr += PMD_SIZE;
-		}
-		j = 0;
-	}
-}
-#endif
-
 void __init pagetable_init(void)
 {
 #ifdef CONFIG_HIGHMEM
 	unsigned long vaddr;
 	pgd_t *pgd, *pgd_base;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 #endif
@@ -90,7 +61,8 @@
 	fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
 
 	pgd = swapper_pg_dir + __pgd_offset(vaddr);
-	pmd = pmd_offset(pgd, vaddr);
+	pud = pud_offset(pgd, vaddr);
+	pmd = pmd_offset(pud, vaddr);
 	pte = pte_offset_kernel(pmd, vaddr);
 	pkmap_page_table = pte;
 #endif
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 4e92f93..9e8ff8b 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -15,6 +15,7 @@
 #include <asm/cacheops.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/cacheflush.h> /* for run_uncached() */
 
 /* Primary cache parameters. */
 #define sc_lsize	32
@@ -96,25 +97,13 @@
 }
 
 /*
- * This function is executed in the uncached segment CKSEG1.
- * It must not touch the stack, because the stack pointer still points
- * into CKSEG0.
- *
- * Three options:
- *	- Write it in assembly and guarantee that we don't use the stack.
- *	- Disable caching for CKSEG0 before calling it.
- *	- Pray that GCC doesn't randomly start using the stack.
- *
- * This being Linux, we obviously take the least sane of those options -
- * following DaveM's lead in c-r4k.c
- *
- * It seems we get our kicks from relying on unguaranteed behaviour in GCC
+ * This function is executed in uncached address space.
  */
 static __init void __rm7k_sc_enable(void)
 {
 	int i;
 
-	set_c0_config(1 << 3);				/* CONF_SE */
+	set_c0_config(RM7K_CONF_SE);
 
 	write_c0_taglo(0);
 	write_c0_taghi(0);
@@ -127,24 +116,22 @@
 		      ".set mips0\n\t"
 		      ".set reorder"
 		      :
-		      : "r" (KSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
+		      : "r" (CKSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
 	}
 }
 
 static __init void rm7k_sc_enable(void)
 {
-	void (*func)(void) = (void *) KSEG1ADDR(&__rm7k_sc_enable);
-
-	if (read_c0_config() & 0x08)			/* CONF_SE */
+	if (read_c0_config() & RM7K_CONF_SE)
 		return;
 
-	printk(KERN_INFO "Enabling secondary cache...");
-	func();
+	printk(KERN_INFO "Enabling secondary cache...\n");
+	run_uncached(__rm7k_sc_enable);
 }
 
 static void rm7k_sc_disable(void)
 {
-	clear_c0_config(1<<3);				/* CONF_SE */
+	clear_c0_config(RM7K_CONF_SE);
 }
 
 struct bcache_ops rm7k_sc_ops = {
@@ -158,19 +145,19 @@
 {
 	unsigned int config = read_c0_config();
 
-	if ((config >> 31) & 1)		/* Bit 31 set -> no S-Cache */
+	if ((config & RM7K_CONF_SC))
 		return;
 
 	printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
 	       (scache_size >> 10), sc_lsize);
 
-	if (!((config >> 3) & 1))	/* CONF_SE */
+	if (!(config & RM7K_CONF_SE))
 		rm7k_sc_enable();
 
 	/*
 	 * While we're at it let's deal with the tertiary cache.
 	 */
-	if (!((config >> 17) & 1)) {
+	if (!(config & RM7K_CONF_TC)) {
 
 		/*
 		 * We can't enable the L3 cache yet. There may be board-specific
@@ -183,9 +170,9 @@
 		 * to probe it.
 		 */
 		printk(KERN_INFO "Tertiary cache present, %s enabled\n",
-		       config&(1<<12) ? "already" : "not (yet)");
+		       (config & RM7K_CONF_TE) ? "already" : "not (yet)");
 
-		if ((config >> 12) & 1)
+		if ((config & RM7K_CONF_TE))
 			rm7k_tcache_enabled = 1;
 	}
 
diff --git a/arch/mips/mm/tlb-andes.c b/arch/mips/mm/tlb-andes.c
index 167e08e..3f422a8 100644
--- a/arch/mips/mm/tlb-andes.c
+++ b/arch/mips/mm/tlb-andes.c
@@ -195,6 +195,7 @@
 {
 	unsigned long flags;
 	pgd_t *pgdp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 	int idx, pid;
@@ -220,7 +221,8 @@
 	write_c0_entryhi(address | (pid));
 	pgdp = pgd_offset(vma->vm_mm, address);
 	tlb_probe();
-	pmdp = pmd_offset(pgdp, address);
+	pudp = pud_offset(pgdp, address);
+	pmdp = pmd_offset(pudp, address);
 	idx = read_c0_index();
 	ptep = pte_offset_map(pmdp, address);
 	write_c0_entrylo0(pte_val(*ptep++) >> 6);
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 59d38bc..8297970 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -21,6 +21,12 @@
 
 extern void build_tlb_refill_handler(void);
 
+/*
+ * Make sure all entries differ.  If they're not different
+ * MIPS32 will take revenge ...
+ */
+#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+
 /* CP0 hazard avoidance. */
 #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
 				     "nop; nop; nop; nop; nop; nop;\n\t" \
@@ -42,11 +48,8 @@
 
 	/* Blast 'em all away. */
 	while (entry < current_cpu_data.tlbsize) {
-		/*
-		 * Make sure all entries differ.  If they're not different
-		 * MIPS32 will take revenge ...
-		 */
-		write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+		/* Make sure all entries differ. */
+		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
 		write_c0_index(entry);
 		mtc0_tlbw_hazard();
 		tlb_write_indexed();
@@ -57,12 +60,21 @@
 	local_irq_restore(flags);
 }
 
+/* All entries common to a mm share an asid.  To effectively flush
+   these entries, we just bump the asid. */
 void local_flush_tlb_mm(struct mm_struct *mm)
 {
-	int cpu = smp_processor_id();
+	int cpu;
 
-	if (cpu_context(cpu, mm) != 0)
-		drop_mmu_context(mm,cpu);
+	preempt_disable();
+
+	cpu = smp_processor_id();
+
+	if (cpu_context(cpu, mm) != 0) {
+		drop_mmu_context(mm, cpu);
+	}
+
+	preempt_enable();
 }
 
 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
@@ -75,9 +87,9 @@
 		unsigned long flags;
 		int size;
 
-		local_irq_save(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		size = (size + 1) >> 1;
+		local_irq_save(flags);
 		if (size <= current_cpu_data.tlbsize/2) {
 			int oldpid = read_c0_entryhi();
 			int newpid = cpu_asid(cpu, mm);
@@ -99,8 +111,7 @@
 				if (idx < 0)
 					continue;
 				/* Make sure all entries differ. */
-				write_c0_entryhi(CKSEG0 +
-				                 (idx << (PAGE_SHIFT + 1)));
+				write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 				mtc0_tlbw_hazard();
 				tlb_write_indexed();
 			}
@@ -118,9 +129,9 @@
 	unsigned long flags;
 	int size;
 
-	local_irq_save(flags);
 	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 	size = (size + 1) >> 1;
+	local_irq_save(flags);
 	if (size <= current_cpu_data.tlbsize / 2) {
 		int pid = read_c0_entryhi();
 
@@ -142,7 +153,7 @@
 			if (idx < 0)
 				continue;
 			/* Make sure all entries differ. */
-			write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+			write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 			mtc0_tlbw_hazard();
 			tlb_write_indexed();
 		}
@@ -176,7 +187,7 @@
 		if (idx < 0)
 			goto finish;
 		/* Make sure all entries differ. */
-		write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 		mtc0_tlbw_hazard();
 		tlb_write_indexed();
 		tlbw_use_hazard();
@@ -197,8 +208,8 @@
 	int oldpid, idx;
 
 	local_irq_save(flags);
-	page &= (PAGE_MASK << 1);
 	oldpid = read_c0_entryhi();
+	page &= (PAGE_MASK << 1);
 	write_c0_entryhi(page);
 	mtc0_tlbw_hazard();
 	tlb_probe();
@@ -208,7 +219,7 @@
 	write_c0_entrylo1(0);
 	if (idx >= 0) {
 		/* Make sure all entries differ. */
-		write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
 		mtc0_tlbw_hazard();
 		tlb_write_indexed();
 		tlbw_use_hazard();
@@ -227,6 +238,7 @@
 {
 	unsigned long flags;
 	pgd_t *pgdp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 	int idx, pid;
@@ -237,35 +249,34 @@
 	if (current->active_mm != vma->vm_mm)
 		return;
 
-	pid = read_c0_entryhi() & ASID_MASK;
-
 	local_irq_save(flags);
+
+	pid = read_c0_entryhi() & ASID_MASK;
 	address &= (PAGE_MASK << 1);
 	write_c0_entryhi(address | pid);
 	pgdp = pgd_offset(vma->vm_mm, address);
 	mtc0_tlbw_hazard();
 	tlb_probe();
 	BARRIER;
-	pmdp = pmd_offset(pgdp, address);
+	pudp = pud_offset(pgdp, address);
+	pmdp = pmd_offset(pudp, address);
 	idx = read_c0_index();
 	ptep = pte_offset_map(pmdp, address);
 
- #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
- 	write_c0_entrylo0(ptep->pte_high);
- 	ptep++;
- 	write_c0_entrylo1(ptep->pte_high);
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
+	write_c0_entrylo0(ptep->pte_high);
+	ptep++;
+	write_c0_entrylo1(ptep->pte_high);
 #else
-  	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-  	write_c0_entrylo1(pte_val(*ptep) >> 6);
+	write_c0_entrylo0(pte_val(*ptep++) >> 6);
+	write_c0_entrylo1(pte_val(*ptep) >> 6);
 #endif
-	write_c0_entryhi(address | pid);
 	mtc0_tlbw_hazard();
 	if (idx < 0)
 		tlb_write_random();
 	else
 		tlb_write_indexed();
 	tlbw_use_hazard();
-	write_c0_entryhi(pid);
 	local_irq_restore(flags);
 }
 
@@ -357,7 +368,8 @@
 	old_pagemask = read_c0_pagemask();
 	wired = read_c0_wired();
 	if (--temp_tlb_entry < wired) {
-		printk(KERN_WARNING "No TLB space left for add_temporary_entry\n");
+		printk(KERN_WARNING
+		       "No TLB space left for add_temporary_entry\n");
 		ret = -ENOSPC;
 		goto out;
 	}
@@ -388,7 +400,7 @@
 	 * is not supported, we assume R4k style.  Cpu probing already figured
 	 * out the number of tlb entries.
 	 */
-	if ((c->processor_id  & 0xff0000) == PRID_COMP_LEGACY)
+	if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
 		return;
 
 	reg = read_c0_config1();
diff --git a/arch/mips/mm/tlb-sb1.c b/arch/mips/mm/tlb-sb1.c
deleted file mode 100644
index 6256caf..0000000
--- a/arch/mips/mm/tlb-sb1.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-#include <linux/init.h>
-#include <asm/mmu_context.h>
-#include <asm/bootinfo.h>
-#include <asm/cpu.h>
-
-extern void build_tlb_refill_handler(void);
-
-#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
-
-/* Dump the current entry* and pagemask registers */
-static inline void dump_cur_tlb_regs(void)
-{
-	unsigned int entryhihi, entryhilo, entrylo0hi, entrylo0lo, entrylo1hi;
-	unsigned int entrylo1lo, pagemask;
-
-	__asm__ __volatile__ (
-		".set push             \n"
-		".set noreorder        \n"
-		".set mips64           \n"
-		".set noat             \n"
-		"     tlbr             \n"
-		"     dmfc0  $1, $10   \n"
-		"     dsrl32 %0, $1, 0 \n"
-		"     sll    %1, $1, 0 \n"
-		"     dmfc0  $1, $2    \n"
-		"     dsrl32 %2, $1, 0 \n"
-		"     sll    %3, $1, 0 \n"
-		"     dmfc0  $1, $3    \n"
-		"     dsrl32 %4, $1, 0 \n"
-		"     sll    %5, $1, 0 \n"
-		"     mfc0   %6, $5    \n"
-		".set pop              \n"
-		: "=r" (entryhihi), "=r" (entryhilo),
-		  "=r" (entrylo0hi), "=r" (entrylo0lo),
-		  "=r" (entrylo1hi), "=r" (entrylo1lo),
-		  "=r" (pagemask));
-
-	printk("%08X%08X %08X%08X %08X%08X %08X",
-	       entryhihi, entryhilo,
-	       entrylo0hi, entrylo0lo,
-	       entrylo1hi, entrylo1lo,
-	       pagemask);
-}
-
-void sb1_dump_tlb(void)
-{
-	unsigned long old_ctx;
-	unsigned long flags;
-	int entry;
-	local_irq_save(flags);
-	old_ctx = read_c0_entryhi();
-	printk("Current TLB registers state:\n"
-	       "      EntryHi       EntryLo0          EntryLo1     PageMask  Index\n"
-	       "--------------------------------------------------------------------\n");
-	dump_cur_tlb_regs();
-	printk(" %08X\n", read_c0_index());
-	printk("\n\nFull TLB Dump:\n"
-	       "Idx      EntryHi       EntryLo0          EntryLo1     PageMask\n"
-	       "--------------------------------------------------------------\n");
-	for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
-		write_c0_index(entry);
-		printk("\n%02i ", entry);
-		dump_cur_tlb_regs();
-	}
-	printk("\n");
-	write_c0_entryhi(old_ctx);
-	local_irq_restore(flags);
-}
-
-void local_flush_tlb_all(void)
-{
-	unsigned long flags;
-	unsigned long old_ctx;
-	int entry;
-
-	local_irq_save(flags);
-	/* Save old context and create impossible VPN2 value */
-	old_ctx = read_c0_entryhi() & ASID_MASK;
-	write_c0_entrylo0(0);
-	write_c0_entrylo1(0);
-
-	entry = read_c0_wired();
-	while (entry < current_cpu_data.tlbsize) {
-		write_c0_entryhi(UNIQUE_ENTRYHI(entry));
-		write_c0_index(entry);
-		tlb_write_indexed();
-		entry++;
-	}
-	write_c0_entryhi(old_ctx);
-	local_irq_restore(flags);
-}
-
-
-/*
- * Use a bogus region of memory (starting at 0) to sanitize the TLB's.
- * Use increments of the maximum page size (16MB), and check for duplicate
- * entries before doing a given write.  Then, when we're safe from collisions
- * with the firmware, go back and give all the entries invalid addresses with
- * the normal flush routine.  Wired entries will be killed as well!
- */
-static void __init sb1_sanitize_tlb(void)
-{
-	int entry;
-	long addr = 0;
-
-	long inc = 1<<24;  /* 16MB */
-	/* Save old context and create impossible VPN2 value */
-	write_c0_entrylo0(0);
-	write_c0_entrylo1(0);
-	for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
-		do {
-			addr += inc;
-			write_c0_entryhi(addr);
-			tlb_probe();
-		} while ((int)(read_c0_index()) >= 0);
-		write_c0_index(entry);
-		tlb_write_indexed();
-	}
-	/* Now that we know we're safe from collisions, we can safely flush
-	   the TLB with the "normal" routine. */
-	local_flush_tlb_all();
-}
-
-void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-	unsigned long end)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long flags;
-	int cpu;
-
-	local_irq_save(flags);
-	cpu = smp_processor_id();
-	if (cpu_context(cpu, mm) != 0) {
-		int size;
-		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-		size = (size + 1) >> 1;
-		if (size <= (current_cpu_data.tlbsize/2)) {
-			int oldpid = read_c0_entryhi() & ASID_MASK;
-			int newpid = cpu_asid(cpu, mm);
-
-			start &= (PAGE_MASK << 1);
-			end += ((PAGE_SIZE << 1) - 1);
-			end &= (PAGE_MASK << 1);
-			while (start < end) {
-				int idx;
-
-				write_c0_entryhi(start | newpid);
-				start += (PAGE_SIZE << 1);
-				tlb_probe();
-				idx = read_c0_index();
-				write_c0_entrylo0(0);
-				write_c0_entrylo1(0);
-				write_c0_entryhi(UNIQUE_ENTRYHI(idx));
-				if (idx < 0)
-					continue;
-				tlb_write_indexed();
-			}
-			write_c0_entryhi(oldpid);
-		} else {
-			drop_mmu_context(mm, cpu);
-		}
-	}
-	local_irq_restore(flags);
-}
-
-void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
-{
-	unsigned long flags;
-	int size;
-
-	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-	size = (size + 1) >> 1;
-
-	local_irq_save(flags);
-	if (size <= (current_cpu_data.tlbsize/2)) {
-		int pid = read_c0_entryhi();
-
-		start &= (PAGE_MASK << 1);
-		end += ((PAGE_SIZE << 1) - 1);
-		end &= (PAGE_MASK << 1);
-
-		while (start < end) {
-			int idx;
-
-			write_c0_entryhi(start);
-			start += (PAGE_SIZE << 1);
-			tlb_probe();
-			idx = read_c0_index();
-			write_c0_entrylo0(0);
-			write_c0_entrylo1(0);
-			write_c0_entryhi(UNIQUE_ENTRYHI(idx));
-			if (idx < 0)
-				continue;
-			tlb_write_indexed();
-		}
-		write_c0_entryhi(pid);
-	} else {
-		local_flush_tlb_all();
-	}
-	local_irq_restore(flags);
-}
-
-void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-	unsigned long flags;
-	int cpu = smp_processor_id();
-
-	local_irq_save(flags);
-	if (cpu_context(cpu, vma->vm_mm) != 0) {
-		int oldpid, newpid, idx;
-		newpid = cpu_asid(cpu, vma->vm_mm);
-		page &= (PAGE_MASK << 1);
-		oldpid = read_c0_entryhi() & ASID_MASK;
-		write_c0_entryhi(page | newpid);
-		tlb_probe();
-		idx = read_c0_index();
-		write_c0_entrylo0(0);
-		write_c0_entrylo1(0);
-		if (idx < 0)
-			goto finish;
-		/* Make sure all entries differ. */
-		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
-		tlb_write_indexed();
-	finish:
-		write_c0_entryhi(oldpid);
-	}
-	local_irq_restore(flags);
-}
-
-/*
- * Remove one kernel space TLB entry.  This entry is assumed to be marked
- * global so we don't do the ASID thing.
- */
-void local_flush_tlb_one(unsigned long page)
-{
-	unsigned long flags;
-	int oldpid, idx;
-
-	page &= (PAGE_MASK << 1);
-	oldpid = read_c0_entryhi() & ASID_MASK;
-
-	local_irq_save(flags);
-	write_c0_entryhi(page);
-	tlb_probe();
-	idx = read_c0_index();
-	if (idx >= 0) {
-		/* Make sure all entries differ. */
-		write_c0_entryhi(UNIQUE_ENTRYHI(idx));
-		write_c0_entrylo0(0);
-		write_c0_entrylo1(0);
-		tlb_write_indexed();
-	}
-
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-}
-
-/* All entries common to a mm share an asid.  To effectively flush
-   these entries, we just bump the asid. */
-void local_flush_tlb_mm(struct mm_struct *mm)
-{
-	int cpu;
-
-	preempt_disable();
-
-	cpu = smp_processor_id();
-
-	if (cpu_context(cpu, mm) != 0) {
-		drop_mmu_context(mm, cpu);
-	}
-
-	preempt_enable();
-}
-
-/* Stolen from mips32 routines */
-
-void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
-{
-	unsigned long flags;
-	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
-	int idx, pid;
-
-	/*
-	 * Handle debugger faulting in for debugee.
-	 */
-	if (current->active_mm != vma->vm_mm)
-		return;
-
-	local_irq_save(flags);
-
-	pid = read_c0_entryhi() & ASID_MASK;
-	address &= (PAGE_MASK << 1);
-	write_c0_entryhi(address | (pid));
-	pgdp = pgd_offset(vma->vm_mm, address);
-	tlb_probe();
-	pmdp = pmd_offset(pgdp, address);
-	idx = read_c0_index();
-	ptep = pte_offset_map(pmdp, address);
-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
-	if (idx < 0) {
-		tlb_write_random();
-	} else {
-		tlb_write_indexed();
-	}
-	local_irq_restore(flags);
-}
-
-void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-	unsigned long entryhi, unsigned long pagemask)
-{
-	unsigned long flags;
-	unsigned long wired;
-	unsigned long old_pagemask;
-	unsigned long old_ctx;
-
-	local_irq_save(flags);
-	old_ctx = read_c0_entryhi() & 0xff;
-	old_pagemask = read_c0_pagemask();
-	wired = read_c0_wired();
-	write_c0_wired(wired + 1);
-	write_c0_index(wired);
-
-	write_c0_pagemask(pagemask);
-	write_c0_entryhi(entryhi);
-	write_c0_entrylo0(entrylo0);
-	write_c0_entrylo1(entrylo1);
-	tlb_write_indexed();
-
-	write_c0_entryhi(old_ctx);
-	write_c0_pagemask(old_pagemask);
-
-	local_flush_tlb_all();
-	local_irq_restore(flags);
-}
-
-/*
- * This is called from loadmmu.c.  We have to set up all the
- * memory management function pointers, as well as initialize
- * the caches and tlbs
- */
-void tlb_init(void)
-{
-	write_c0_pagemask(PM_DEFAULT_MASK);
-	write_c0_wired(0);
-
-	/*
-	 * We don't know what state the firmware left the TLB's in, so this is
-	 * the ultra-conservative way to flush the TLB's and avoid machine
-	 * check exceptions due to duplicate TLB entries
-	 */
-	sb1_sanitize_tlb();
-
-	build_tlb_refill_handler();
-}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 6569be3..0f94858 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -6,6 +6,7 @@
  * Synthesize TLB refill handlers at runtime.
  *
  * Copyright (C) 2004,2005 by Thiemo Seufer
+ * Copyright (C) 2005  Maciej W. Rozycki
  */
 
 #include <stdarg.h>
@@ -91,7 +92,7 @@
 	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
 	insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
 	insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
-	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
+	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
 	insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
 	insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
 	insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
@@ -134,7 +135,6 @@
 	{ insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
 	{ insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
 	{ insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE },
-	{ insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
 	{ insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD },
 	{ insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 },
 	{ insn_j, M(j_op,0,0,0,0,0), JIMM },
@@ -366,7 +366,6 @@
 I_u2u1u3(_dsll32);
 I_u2u1u3(_dsra);
 I_u2u1u3(_dsrl);
-I_u2u1u3(_dsrl32);
 I_u3u1u2(_dsubu);
 I_0(_eret);
 I_u1(_j);
@@ -412,7 +411,6 @@
 	label_nopage_tlbm,
 	label_smp_pgtable_change,
 	label_r3000_write_probe_fail,
-	label_r3000_write_probe_ok
 };
 
 struct label {
@@ -445,7 +443,6 @@
 L_LA(_nopage_tlbm)
 L_LA(_smp_pgtable_change)
 L_LA(_r3000_write_probe_fail)
-L_LA(_r3000_write_probe_ok)
 
 /* convenience macros for instructions */
 #ifdef CONFIG_64BIT
@@ -490,7 +487,7 @@
 static __init int __attribute__((unused)) in_compat_space_p(long addr)
 {
 	/* Is this address in 32bit compat space? */
-	return (((addr) & 0xffffffff00000000) == 0xffffffff00000000);
+	return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
 }
 
 static __init int __attribute__((unused)) rel_highest(long val)
@@ -734,7 +731,7 @@
 	if (p > tlb_handler + 32)
 		panic("TLB refill handler space exceeded");
 
-	printk("Synthesized TLB handler (%u instructions).\n",
+	printk("Synthesized TLB refill handler (%u instructions).\n",
 	       (unsigned int)(p - tlb_handler));
 #ifdef DEBUG_TLB
 	{
@@ -746,7 +743,6 @@
 #endif
 
 	memcpy((void *)CAC_BASE, tlb_handler, 0x80);
-	flush_icache_range(CAC_BASE, CAC_BASE + 0x80);
 }
 
 /*
@@ -783,6 +779,8 @@
 static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p)
 {
 	switch (current_cpu_data.cputype) {
+	/* Found by experiment: R4600 v2.0 needs this, too.  */
+	case CPU_R4600:
 	case CPU_R5000:
 	case CPU_R5000A:
 	case CPU_NEVADA:
@@ -834,12 +832,20 @@
 	case CPU_R4700:
 	case CPU_R5000:
 	case CPU_R5000A:
+		i_nop(p);
+		tlbw(p);
+		i_nop(p);
+		break;
+
+	case CPU_R4300:
 	case CPU_5KC:
 	case CPU_TX49XX:
 	case CPU_AU1000:
 	case CPU_AU1100:
 	case CPU_AU1500:
 	case CPU_AU1550:
+	case CPU_AU1200:
+	case CPU_PR4450:
 		i_nop(p);
 		tlbw(p);
 		break;
@@ -848,6 +854,7 @@
 	case CPU_R12000:
 	case CPU_4KC:
 	case CPU_SB1:
+	case CPU_SB1A:
 	case CPU_4KSC:
 	case CPU_20KC:
 	case CPU_25KF:
@@ -875,6 +882,7 @@
 
 	case CPU_4KEC:
 	case CPU_24K:
+	case CPU_34K:
 		i_ehb(p);
 		tlbw(p);
 		break;
@@ -911,6 +919,7 @@
 
 	case CPU_VR4131:
 	case CPU_VR4133:
+	case CPU_R5432:
 		i_nop(p);
 		i_nop(p);
 		tlbw(p);
@@ -942,34 +951,29 @@
 	/* No i_nop needed here, since the next insn doesn't touch TMP. */
 
 #ifdef CONFIG_SMP
+# ifdef CONFIG_BUILD_ELF64
 	/*
-	 * 64 bit SMP has the lower part of &pgd_current[smp_processor_id()]
+	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
 	 * stored in CONTEXT.
 	 */
-	if (in_compat_space_p(pgdc)) {
-		i_dmfc0(p, ptr, C0_CONTEXT);
-		i_dsra(p, ptr, ptr, 23);
-		i_ld(p, ptr, 0, ptr);
-	} else {
-#ifdef CONFIG_BUILD_ELF64
-		i_dmfc0(p, ptr, C0_CONTEXT);
-		i_dsrl(p, ptr, ptr, 23);
-		i_dsll(p, ptr, ptr, 3);
-		i_LA_mostly(p, tmp, pgdc);
-		i_daddu(p, ptr, ptr, tmp);
-		i_dmfc0(p, tmp, C0_BADVADDR);
-		i_ld(p, ptr, rel_lo(pgdc), ptr);
-#else
-		i_dmfc0(p, ptr, C0_CONTEXT);
-		i_lui(p, tmp, rel_highest(pgdc));
-		i_dsll(p, ptr, ptr, 9);
-		i_daddiu(p, tmp, tmp, rel_higher(pgdc));
-		i_dsrl32(p, ptr, ptr, 0);
-		i_and(p, ptr, ptr, tmp);
-		i_dmfc0(p, tmp, C0_BADVADDR);
-		i_ld(p, ptr, 0, ptr);
-#endif
-	}
+	i_dmfc0(p, ptr, C0_CONTEXT);
+	i_dsrl(p, ptr, ptr, 23);
+	i_LA_mostly(p, tmp, pgdc);
+	i_daddu(p, ptr, ptr, tmp);
+	i_dmfc0(p, tmp, C0_BADVADDR);
+	i_ld(p, ptr, rel_lo(pgdc), ptr);
+# else
+	/*
+	 * 64 bit SMP running in compat space has the lower part of
+	 * &pgd_current[smp_processor_id()] stored in CONTEXT.
+	 */
+	if (!in_compat_space_p(pgdc))
+		panic("Invalid page directory address!");
+
+	i_dmfc0(p, ptr, C0_CONTEXT);
+	i_dsra(p, ptr, ptr, 23);
+	i_ld(p, ptr, 0, ptr);
+# endif
 #else
 	i_LA_mostly(p, ptr, pgdc);
 	i_ld(p, ptr, rel_lo(pgdc), ptr);
@@ -1026,7 +1030,6 @@
 	i_mfc0(p, ptr, C0_CONTEXT);
 	i_LA_mostly(p, tmp, pgdc);
 	i_srl(p, ptr, ptr, 23);
-	i_sll(p, ptr, ptr, 2);
 	i_addu(p, ptr, tmp, ptr);
 #else
 	i_LA_mostly(p, ptr, pgdc);
@@ -1245,13 +1248,19 @@
 	{
 		int i;
 
-		for (i = 0; i < 64; i++)
-			printk("%08x\n", final_handler[i]);
+		f = final_handler;
+#ifdef CONFIG_64BIT
+		if (final_len > 32)
+			final_len = 64;
+		else
+			f = final_handler + 32;
+#endif /* CONFIG_64BIT */
+		for (i = 0; i < final_len; i++)
+			printk("%08x\n", f[i]);
 	}
 #endif
 
 	memcpy((void *)CAC_BASE, final_handler, 0x100);
-	flush_icache_range(CAC_BASE, CAC_BASE + 0x100);
 }
 
 /*
@@ -1277,37 +1286,41 @@
 u32 __tlb_handler_align handle_tlbm[FASTPATH_SIZE];
 
 static void __init
-iPTE_LW(u32 **p, struct label **l, unsigned int pte, int offset,
-	unsigned int ptr)
+iPTE_LW(u32 **p, struct label **l, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_lld(p, pte, offset, ptr);
+		i_lld(p, pte, 0, ptr);
 	else
 # endif
-		i_LL(p, pte, offset, ptr);
+		i_LL(p, pte, 0, ptr);
 #else
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_ld(p, pte, offset, ptr);
+		i_ld(p, pte, 0, ptr);
 	else
 # endif
-		i_LW(p, pte, offset, ptr);
+		i_LW(p, pte, 0, ptr);
 #endif
 }
 
 static void __init
-iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, int offset,
-	unsigned int ptr)
+iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, unsigned int ptr,
+	unsigned int mode)
 {
+#ifdef CONFIG_64BIT_PHYS_ADDR
+	unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY);
+#endif
+
+	i_ori(p, pte, pte, mode);
 #ifdef CONFIG_SMP
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_scd(p, pte, offset, ptr);
+		i_scd(p, pte, 0, ptr);
 	else
 # endif
-		i_SC(p, pte, offset, ptr);
+		i_SC(p, pte, 0, ptr);
 
 	if (r10000_llsc_war())
 		il_beqzl(p, r, pte, label_smp_pgtable_change);
@@ -1318,7 +1331,7 @@
 	if (!cpu_has_64bits) {
 		/* no i_nop needed */
 		i_ll(p, pte, sizeof(pte_t) / 2, ptr);
-		i_ori(p, pte, pte, _PAGE_VALID);
+		i_ori(p, pte, pte, hwmode);
 		i_sc(p, pte, sizeof(pte_t) / 2, ptr);
 		il_beqz(p, r, pte, label_smp_pgtable_change);
 		/* no i_nop needed */
@@ -1331,15 +1344,15 @@
 #else
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (cpu_has_64bits)
-		i_sd(p, pte, offset, ptr);
+		i_sd(p, pte, 0, ptr);
 	else
 # endif
-		i_SW(p, pte, offset, ptr);
+		i_SW(p, pte, 0, ptr);
 
 # ifdef CONFIG_64BIT_PHYS_ADDR
 	if (!cpu_has_64bits) {
 		i_lw(p, pte, sizeof(pte_t) / 2, ptr);
-		i_ori(p, pte, pte, _PAGE_VALID);
+		i_ori(p, pte, pte, hwmode);
 		i_sw(p, pte, sizeof(pte_t) / 2, ptr);
 		i_lw(p, pte, 0, ptr);
 	}
@@ -1359,7 +1372,7 @@
 	i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
 	i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
 	il_bnez(p, r, pte, lid);
-	iPTE_LW(p, l, pte, 0, ptr);
+	iPTE_LW(p, l, pte, ptr);
 }
 
 /* Make PTE valid, store result in PTR. */
@@ -1367,8 +1380,9 @@
 build_make_valid(u32 **p, struct reloc **r, unsigned int pte,
 		 unsigned int ptr)
 {
-	i_ori(p, pte, pte, _PAGE_VALID | _PAGE_ACCESSED);
-	iPTE_SW(p, r, pte, 0, ptr);
+	unsigned int mode = _PAGE_VALID | _PAGE_ACCESSED;
+
+	iPTE_SW(p, r, pte, ptr, mode);
 }
 
 /*
@@ -1382,7 +1396,7 @@
 	i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
 	i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
 	il_bnez(p, r, pte, lid);
-	iPTE_LW(p, l, pte, 0, ptr);
+	iPTE_LW(p, l, pte, ptr);
 }
 
 /* Make PTE writable, update software status bits as well, then store
@@ -1392,9 +1406,10 @@
 build_make_write(u32 **p, struct reloc **r, unsigned int pte,
 		 unsigned int ptr)
 {
-	i_ori(p, pte, pte,
-	      _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
-	iPTE_SW(p, r, pte, 0, ptr);
+	unsigned int mode = (_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID
+			     | _PAGE_DIRTY);
+
+	iPTE_SW(p, r, pte, ptr, mode);
 }
 
 /*
@@ -1407,41 +1422,48 @@
 {
 	i_andi(p, pte, pte, _PAGE_WRITE);
 	il_beqz(p, r, pte, lid);
-	iPTE_LW(p, l, pte, 0, ptr);
+	iPTE_LW(p, l, pte, ptr);
 }
 
 /*
  * R3000 style TLB load/store/modify handlers.
  */
 
-/* This places the pte in the page table at PTR into ENTRYLO0. */
+/*
+ * This places the pte into ENTRYLO0 and writes it with tlbwi.
+ * Then it returns.
+ */
 static void __init
-build_r3000_pte_reload(u32 **p, unsigned int ptr)
+build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp)
 {
-	i_lw(p, ptr, 0, ptr);
-	i_nop(p); /* load delay */
-	i_mtc0(p, ptr, C0_ENTRYLO0);
-	i_nop(p); /* cp0 delay */
+	i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
+	i_mfc0(p, tmp, C0_EPC); /* cp0 delay */
+	i_tlbwi(p);
+	i_jr(p, tmp);
+	i_rfe(p); /* branch delay */
 }
 
 /*
- * The index register may have the probe fail bit set,
- * because we would trap on access kseg2, i.e. without refill.
+ * This places the pte into ENTRYLO0 and writes it with tlbwi
+ * or tlbwr as appropriate.  This is because the index register
+ * may have the probe fail bit set as a result of a trap on a
+ * kseg2 access, i.e. without refill.  Then it returns.
  */
 static void __init
-build_r3000_tlb_write(u32 **p, struct label **l, struct reloc **r,
-		      unsigned int tmp)
+build_r3000_tlb_reload_write(u32 **p, struct label **l, struct reloc **r,
+			     unsigned int pte, unsigned int tmp)
 {
 	i_mfc0(p, tmp, C0_INDEX);
-	i_nop(p); /* cp0 delay */
-	il_bltz(p, r, tmp, label_r3000_write_probe_fail);
-	i_nop(p); /* branch delay */
-	i_tlbwi(p);
-	il_b(p, r, label_r3000_write_probe_ok);
-	i_nop(p); /* branch delay */
+	i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */
+	il_bltz(p, r, tmp, label_r3000_write_probe_fail); /* cp0 delay */
+	i_mfc0(p, tmp, C0_EPC); /* branch delay */
+	i_tlbwi(p); /* cp0 delay */
+	i_jr(p, tmp);
+	i_rfe(p); /* branch delay */
 	l_r3000_write_probe_fail(l, *p);
-	i_tlbwr(p);
-	l_r3000_write_probe_ok(l, *p);
+	i_tlbwr(p); /* cp0 delay */
+	i_jr(p, tmp);
+	i_rfe(p); /* branch delay */
 }
 
 static void __init
@@ -1461,17 +1483,7 @@
 	i_andi(p, pte, pte, 0xffc); /* load delay */
 	i_addu(p, ptr, ptr, pte);
 	i_lw(p, pte, 0, ptr);
-	i_nop(p); /* load delay */
-	i_tlbp(p);
-}
-
-static void __init
-build_r3000_tlbchange_handler_tail(u32 **p, unsigned int tmp)
-{
-	i_mfc0(p, tmp, C0_EPC);
-	i_nop(p); /* cp0 delay */
-	i_jr(p, tmp);
-	i_rfe(p); /* branch delay */
+	i_tlbp(p); /* load delay */
 }
 
 static void __init build_r3000_tlb_load_handler(void)
@@ -1486,10 +1498,9 @@
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
+	i_nop(&p); /* load delay */
 	build_make_valid(&p, &r, K0, K1);
-	build_r3000_pte_reload(&p, K1);
-	build_r3000_tlb_write(&p, &l, &r, K0);
-	build_r3000_tlbchange_handler_tail(&p, K0);
+	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
 	l_nopage_tlbl(&l, p);
 	i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
@@ -1506,13 +1517,10 @@
 	{
 		int i;
 
-		for (i = 0; i < FASTPATH_SIZE; i++)
+		for (i = 0; i < (p - handle_tlbl); i++)
 			printk("%08x\n", handle_tlbl[i]);
 	}
 #endif
-
-	flush_icache_range((unsigned long)handle_tlbl,
-			   (unsigned long)handle_tlbl + FASTPATH_SIZE * sizeof(u32));
 }
 
 static void __init build_r3000_tlb_store_handler(void)
@@ -1527,10 +1535,9 @@
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
+	i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
-	build_r3000_pte_reload(&p, K1);
-	build_r3000_tlb_write(&p, &l, &r, K0);
-	build_r3000_tlbchange_handler_tail(&p, K0);
+	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
 	l_nopage_tlbs(&l, p);
 	i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
@@ -1547,13 +1554,10 @@
 	{
 		int i;
 
-		for (i = 0; i < FASTPATH_SIZE; i++)
+		for (i = 0; i < (p - handle_tlbs); i++)
 			printk("%08x\n", handle_tlbs[i]);
 	}
 #endif
-
-	flush_icache_range((unsigned long)handle_tlbs,
-			   (unsigned long)handle_tlbs + FASTPATH_SIZE * sizeof(u32));
 }
 
 static void __init build_r3000_tlb_modify_handler(void)
@@ -1568,10 +1572,9 @@
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
+	i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
-	build_r3000_pte_reload(&p, K1);
-	i_tlbwi(&p);
-	build_r3000_tlbchange_handler_tail(&p, K0);
+	build_r3000_pte_reload_tlbwi(&p, K0, K1);
 
 	l_nopage_tlbm(&l, p);
 	i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
@@ -1588,13 +1591,10 @@
 	{
 		int i;
 
-		for (i = 0; i < FASTPATH_SIZE; i++)
+		for (i = 0; i < (p - handle_tlbm); i++)
 			printk("%08x\n", handle_tlbm[i]);
 	}
 #endif
-
-	flush_icache_range((unsigned long)handle_tlbm,
-			   (unsigned long)handle_tlbm + FASTPATH_SIZE * sizeof(u32));
 }
 
 /*
@@ -1620,7 +1620,7 @@
 #ifdef CONFIG_SMP
 	l_smp_pgtable_change(l, *p);
 # endif
-	iPTE_LW(p, l, pte, 0, ptr); /* get even pte */
+	iPTE_LW(p, l, pte, ptr); /* get even pte */
 	build_tlb_probe_entry(p);
 }
 
@@ -1680,13 +1680,10 @@
 	{
 		int i;
 
-		for (i = 0; i < FASTPATH_SIZE; i++)
+		for (i = 0; i < (p - handle_tlbl); i++)
 			printk("%08x\n", handle_tlbl[i]);
 	}
 #endif
-
-	flush_icache_range((unsigned long)handle_tlbl,
-			   (unsigned long)handle_tlbl + FASTPATH_SIZE * sizeof(u32));
 }
 
 static void __init build_r4000_tlb_store_handler(void)
@@ -1719,13 +1716,10 @@
 	{
 		int i;
 
-		for (i = 0; i < FASTPATH_SIZE; i++)
+		for (i = 0; i < (p - handle_tlbs); i++)
 			printk("%08x\n", handle_tlbs[i]);
 	}
 #endif
-
-	flush_icache_range((unsigned long)handle_tlbs,
-			   (unsigned long)handle_tlbs + FASTPATH_SIZE * sizeof(u32));
 }
 
 static void __init build_r4000_tlb_modify_handler(void)
@@ -1759,13 +1753,10 @@
 	{
 		int i;
 
-		for (i = 0; i < FASTPATH_SIZE; i++)
+		for (i = 0; i < (p - handle_tlbm); i++)
 			printk("%08x\n", handle_tlbm[i]);
 	}
 #endif
-
-	flush_icache_range((unsigned long)handle_tlbm,
-			   (unsigned long)handle_tlbm + FASTPATH_SIZE * sizeof(u32));
 }
 
 void __init build_tlb_refill_handler(void)
@@ -1813,3 +1804,13 @@
 		}
 	}
 }
+
+void __init flush_tlb_handlers(void)
+{
+	flush_icache_range((unsigned long)handle_tlbl,
+			   (unsigned long)handle_tlbl + sizeof(handle_tlbl));
+	flush_icache_range((unsigned long)handle_tlbs,
+			   (unsigned long)handle_tlbs + sizeof(handle_tlbs));
+	flush_icache_range((unsigned long)handle_tlbm,
+			   (unsigned long)handle_tlbm + sizeof(handle_tlbm));
+}
diff --git a/arch/mips/momentum/Kconfig b/arch/mips/momentum/Kconfig
new file mode 100644
index 0000000..70a61cf
--- /dev/null
+++ b/arch/mips/momentum/Kconfig
@@ -0,0 +1,6 @@
+config JAGUAR_DMALOW
+	bool "Low DMA Mode"
+	depends on MOMENCO_JAGUAR_ATX
+	help
+	  Select to Y if jump JP5 is set on your board, N otherwise.  Normally
+	  the jumper is set, so if you feel unsafe, just say Y.
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
index 14ae2e7..aae7a80 100644
--- a/arch/mips/momentum/jaguar_atx/prom.c
+++ b/arch/mips/momentum/jaguar_atx/prom.c
@@ -236,8 +236,9 @@
 #endif
 }
 
-void __init prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 90288cf..768bf44 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -351,7 +351,7 @@
 
 arch_initcall(ja_pci_init);
 
-static int  __init momenco_jaguar_atx_setup(void)
+void __init plat_setup(void)
 {
 	unsigned int tmpword;
 
@@ -467,8 +467,4 @@
 
 	}
 #endif
-
-	return 0;
 }
-
-early_initcall(momenco_jaguar_atx_setup);
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
index c4fa9c5..9803daa 100644
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ b/arch/mips/momentum/ocelot_3/prom.c
@@ -239,8 +239,9 @@
 #endif
 }
 
-void __init prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index ce2efcb..a7803e0 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -307,7 +307,7 @@
 
 arch_initcall(ja_pci_init);
 
-static int __init momenco_ocelot_3_setup(void)
+void __init plat_setup(void)
 {
 	unsigned int tmpword;
 
@@ -391,8 +391,4 @@
 
 	/* Support for 128 MB memory */
 	add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM);
-
-	return 0;
 }
-
-early_initcall(momenco_ocelot_3_setup);
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
index dea48b3..bd88578 100644
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ b/arch/mips/momentum/ocelot_c/cpci-irq.c
@@ -129,14 +129,13 @@
 #define shutdown_cpci_irq	disable_cpci_irq
 
 struct hw_interrupt_type cpci_irq_type = {
-	"CPCI/FPGA",
-	startup_cpci_irq,
-	shutdown_cpci_irq,
-	enable_cpci_irq,
-	disable_cpci_irq,
-	mask_and_ack_cpci_irq,
-	end_cpci_irq,
-	NULL
+	.typename = "CPCI/FPGA",
+	.startup = startup_cpci_irq,
+	.shutdown = shutdown_cpci_irq,
+	.enable = enable_cpci_irq,
+	.disable = disable_cpci_irq,
+	.ack = mask_and_ack_cpci_irq,
+	.end = end_cpci_irq,
 };
 
 void cpci_irq_init(void)
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index 844ddd0..ce70fc9 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -222,7 +222,7 @@
 	rtc_set_time = m48t37y_set_time;
 }
 
-static void __init momenco_ocelot_c_setup(void)
+void __init plat_setup(void)
 {
 	unsigned int tmpword;
 
@@ -340,8 +340,6 @@
 	}
 }
 
-early_initcall(momenco_ocelot_c_setup);
-
 #ifndef CONFIG_64BIT
 /* This needs to be one of the first initcalls, because no I/O port access
    can work before this */
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
index ebe1507..755bde5 100644
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ b/arch/mips/momentum/ocelot_c/uart-irq.c
@@ -122,14 +122,13 @@
 #define shutdown_uart_irq	disable_uart_irq
 
 struct hw_interrupt_type uart_irq_type = {
-	"UART/FPGA",
-	startup_uart_irq,
-	shutdown_uart_irq,
-	enable_uart_irq,
-	disable_uart_irq,
-	mask_and_ack_uart_irq,
-	end_uart_irq,
-	NULL
+	.typename = "UART/FPGA",
+	.startup = startup_uart_irq,
+	.shutdown = shutdown_uart_irq,
+	.enable = enable_uart_irq,
+	.disable = disable_uart_irq,
+	.ack = mask_and_ack_uart_irq,
+	.end = end_uart_irq,
 };
 
 void uart_irq_init(void)
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
index 38a78ab..6336751 100644
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -160,7 +160,7 @@
 	printk("Done\n");
 }
 
-static int  __init momenco_ocelot_g_setup(void)
+void __init plat_setup(void)
 {
 	void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache);
 	unsigned int tmpword;
@@ -240,12 +240,8 @@
 
 	/* FIXME: Fix up the DiskOnChip mapping */
 	MV_WRITE(0x468, 0xfef73);
-
-	return 0;
 }
 
-early_initcall(momenco_ocelot_g_setup);
-
 /* This needs to be one of the first initcalls, because no I/O port access
    can work before this */
 
diff --git a/arch/mips/oprofile/Kconfig b/arch/mips/oprofile/Kconfig
index 19d3773..55feaf7 100644
--- a/arch/mips/oprofile/Kconfig
+++ b/arch/mips/oprofile/Kconfig
@@ -11,7 +11,7 @@
 
 config OPROFILE
 	tristate "OProfile system profiling (EXPERIMENTAL)"
-	depends on PROFILING
+	depends on PROFILING && EXPERIMENTAL
 	help
 	  OProfile is a profiling system capable of profiling the
 	  whole system, include the kernel, kernel modules, libraries,
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index ab65ce3..dd2cc42 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -3,7 +3,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004 by Ralf Baechle
+ * Copyright (C) 2004, 2005 Ralf Baechle
+ * Copyright (C) 2005 MIPS Technologies, Inc.
  */
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -45,10 +46,10 @@
 		oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
 		oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
 		oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
-		/* Dummies.  */
 		oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
 		oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
 		oprofilefs_create_ulong(sb, dir, "exl", &ctr[i].exl);
+		/* Dummy.  */
 		oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
 	}
 
@@ -68,9 +69,10 @@
 	on_each_cpu(model->cpu_stop, NULL, 0, 1);
 }
 
-void __init oprofile_arch_init(struct oprofile_operations *ops)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
 	struct op_mips_model *lmodel = NULL;
+	int res;
 
 	switch (current_cpu_data.cputype) {
 	case CPU_24K:
@@ -83,21 +85,25 @@
 	};
 
 	if (!lmodel)
-		return;
+		return -ENODEV;
 
-	if (lmodel->init())
-		return;
+	res = lmodel->init();
+	if (res)
+		return res;
 
 	model = lmodel;
 
-	ops->create_files = op_mips_create_files;
-	ops->setup = op_mips_setup;
-	ops->start = op_mips_start;
-	ops->stop = op_mips_stop;
-	ops->cpu_type = lmodel->cpu_type;
+	ops->create_files	= op_mips_create_files;
+	ops->setup		= op_mips_setup;
+	//ops->shutdown         = op_mips_shutdown;
+	ops->start		= op_mips_start;
+	ops->stop		= op_mips_stop;
+	ops->cpu_type		= lmodel->cpu_type;
 
 	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
 	       lmodel->cpu_type);
+
+	return 0;
 }
 
 void oprofile_arch_exit(void)
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
index 9f5cdff..f012155 100644
--- a/arch/mips/oprofile/op_impl.h
+++ b/arch/mips/oprofile/op_impl.h
@@ -10,6 +10,11 @@
 #ifndef OP_IMPL_H
 #define OP_IMPL_H 1
 
+struct pt_regs;
+
+extern void null_perf_irq(struct pt_regs *regs);
+extern void (*perf_irq)(struct pt_regs *regs);
+
 /* Per-counter configuration as set via oprofilefs.  */
 struct op_counter_config {
 	unsigned long enabled;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
new file mode 100644
index 0000000..d36b64d
--- /dev/null
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -0,0 +1,215 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004, 2005 by Ralf Baechle
+ * Copyright (C) 2005 by MIPS Technologies, Inc.
+ */
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include "op_impl.h"
+
+#define M_PERFCTL_EXL			(1UL    <<  0)
+#define M_PERFCTL_KERNEL		(1UL    <<  1)
+#define M_PERFCTL_SUPERVISOR		(1UL    <<  2)
+#define M_PERFCTL_USER			(1UL    <<  3)
+#define M_PERFCTL_INTERRUPT_ENABLE	(1UL    <<  4)
+#define M_PERFCTL_EVENT(event)		((event) << 5)
+#define M_PERFCTL_WIDE			(1UL    << 30)
+#define M_PERFCTL_MORE			(1UL    << 31)
+
+#define M_COUNTER_OVERFLOW		(1UL    << 31)
+
+struct op_mips_model op_model_mipsxx;
+
+static struct mipsxx_register_config {
+	unsigned int control[4];
+	unsigned int counter[4];
+} reg;
+
+/* Compute all of the registers in preparation for enabling profiling.  */
+
+static void mipsxx_reg_setup(struct op_counter_config *ctr)
+{
+	unsigned int counters = op_model_mipsxx.num_counters;
+	int i;
+
+	/* Compute the performance counter control word.  */
+	/* For now count kernel and user mode */
+	for (i = 0; i < counters; i++) {
+		reg.control[i] = 0;
+		reg.counter[i] = 0;
+
+		if (!ctr[i].enabled)
+			continue;
+
+		reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) |
+		                 M_PERFCTL_INTERRUPT_ENABLE;
+		if (ctr[i].kernel)
+			reg.control[i] |= M_PERFCTL_KERNEL;
+		if (ctr[i].user)
+			reg.control[i] |= M_PERFCTL_USER;
+		if (ctr[i].exl)
+			reg.control[i] |= M_PERFCTL_EXL;
+		reg.counter[i] = 0x80000000 - ctr[i].count;
+	}
+}
+
+/* Program all of the registers in preparation for enabling profiling.  */
+
+static void mipsxx_cpu_setup (void *args)
+{
+	unsigned int counters = op_model_mipsxx.num_counters;
+
+	switch (counters) {
+	case 4:
+		write_c0_perfctrl3(0);
+		write_c0_perfcntr3(reg.counter[3]);
+	case 3:
+		write_c0_perfctrl2(0);
+		write_c0_perfcntr2(reg.counter[2]);
+	case 2:
+		write_c0_perfctrl1(0);
+		write_c0_perfcntr1(reg.counter[1]);
+	case 1:
+		write_c0_perfctrl0(0);
+		write_c0_perfcntr0(reg.counter[0]);
+	}
+}
+
+/* Start all counters on current CPU */
+static void mipsxx_cpu_start(void *args)
+{
+	unsigned int counters = op_model_mipsxx.num_counters;
+
+	switch (counters) {
+	case 4:
+		write_c0_perfctrl3(reg.control[3]);
+	case 3:
+		write_c0_perfctrl2(reg.control[2]);
+	case 2:
+		write_c0_perfctrl1(reg.control[1]);
+	case 1:
+		write_c0_perfctrl0(reg.control[0]);
+	}
+}
+
+/* Stop all counters on current CPU */
+static void mipsxx_cpu_stop(void *args)
+{
+	unsigned int counters = op_model_mipsxx.num_counters;
+
+	switch (counters) {
+	case 4:
+		write_c0_perfctrl3(0);
+	case 3:
+		write_c0_perfctrl2(0);
+	case 2:
+		write_c0_perfctrl1(0);
+	case 1:
+		write_c0_perfctrl0(0);
+	}
+}
+
+static void mipsxx_perfcount_handler(struct pt_regs *regs)
+{
+	unsigned int counters = op_model_mipsxx.num_counters;
+	unsigned int control;
+	unsigned int counter;
+
+	switch (counters) {
+#define HANDLE_COUNTER(n)						\
+	case n + 1:							\
+		control = read_c0_perfctrl ## n();			\
+		counter = read_c0_perfcntr ## n();			\
+		if ((control & M_PERFCTL_INTERRUPT_ENABLE) &&		\
+		    (counter & M_COUNTER_OVERFLOW)) {			\
+			oprofile_add_sample(regs, n);			\
+			write_c0_perfcntr ## n(reg.counter[n]);		\
+		}
+	HANDLE_COUNTER(3)
+	HANDLE_COUNTER(2)
+	HANDLE_COUNTER(1)
+	HANDLE_COUNTER(0)
+	}
+}
+
+#define M_CONFIG1_PC	(1 << 4)
+
+static inline int n_counters(void)
+{
+	if (!(read_c0_config1() & M_CONFIG1_PC))
+		return 0;
+	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
+		return 1;
+	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
+		return 2;
+	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
+		return 3;
+
+	return 4;
+}
+
+static inline void reset_counters(int counters)
+{
+	switch (counters) {
+	case 4:
+		write_c0_perfctrl3(0);
+		write_c0_perfcntr3(0);
+	case 3:
+		write_c0_perfctrl2(0);
+		write_c0_perfcntr2(0);
+	case 2:
+		write_c0_perfctrl1(0);
+		write_c0_perfcntr1(0);
+	case 1:
+		write_c0_perfctrl0(0);
+		write_c0_perfcntr0(0);
+	}
+}
+
+static int __init mipsxx_init(void)
+{
+	int counters;
+
+	counters = n_counters();
+	if (counters == 0)
+		return -ENODEV;
+
+	reset_counters(counters);
+
+	op_model_mipsxx.num_counters = counters;
+	switch (current_cpu_data.cputype) {
+	case CPU_24K:
+		op_model_mipsxx.cpu_type = "mips/24K";
+		break;
+
+	default:
+		printk(KERN_ERR "Profiling unsupported for this CPU\n");
+
+		return -ENODEV;
+	}
+
+	perf_irq = mipsxx_perfcount_handler;
+
+	return 0;
+}
+
+static void mipsxx_exit(void)
+{
+	reset_counters(op_model_mipsxx.num_counters);
+
+	perf_irq = null_perf_irq;
+}
+
+struct op_mips_model op_model_mipsxx = {
+	.reg_setup	= mipsxx_reg_setup,
+	.cpu_setup	= mipsxx_cpu_setup,
+	.init		= mipsxx_init,
+	.exit		= mipsxx_exit,
+	.cpu_start	= mipsxx_cpu_start,
+	.cpu_stop	= mipsxx_cpu_stop,
+};
diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c
index bee4779..9b75e41 100644
--- a/arch/mips/oprofile/op_model_rm9000.c
+++ b/arch/mips/oprofile/op_model_rm9000.c
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2004 by Ralf Baechle
  */
+#include <linux/init.h>
 #include <linux/oprofile.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
@@ -114,7 +115,7 @@
 	return IRQ_HANDLED;
 }
 
-static int rm9000_init(void)
+static int __init rm9000_init(void)
 {
 	return request_irq(rm9000_perfcount_irq, rm9000_perfcount_handler,
 	                   0, "Perfcounter", NULL);
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 83d81c9..7b74683 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_MIPS_IVR)		+= fixup-ivr.o
 obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
+obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o
 obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o
 obj-$(CONFIG_MOMENCO_OCELOT)	+= fixup-ocelot.o pci-ocelot.o
@@ -45,11 +46,13 @@
 obj-$(CONFIG_SGI_IP27)		+= pci-ip27.o
 obj-$(CONFIG_SGI_IP32)		+= fixup-ip32.o ops-mace.o pci-ip32.o
 obj-$(CONFIG_SIBYTE_SB1250)	+= fixup-sb1250.o pci-sb1250.o
+obj-$(CONFIG_SIBYTE_BCM1x80)	+= pci-bcm1480.o pci-bcm1480ht.o
 obj-$(CONFIG_SNI_RM200_PCI)	+= fixup-sni.o ops-sni.o
 obj-$(CONFIG_TANBAC_TB0219)	+= fixup-tb0219.o
 obj-$(CONFIG_TANBAC_TB0226)	+= fixup-tb0226.o
 obj-$(CONFIG_TANBAC_TB0287)	+= fixup-tb0287.o
 obj-$(CONFIG_TOSHIBA_JMR3927)	+= fixup-jmr3927.o pci-jmr3927.o
 obj-$(CONFIG_TOSHIBA_RBTX4927)	+= fixup-rbtx4927.o ops-tx4927.o
+obj-$(CONFIG_TOSHIBA_RBTX4938)	+= fixup-tx4938.o ops-tx4938.o
 obj-$(CONFIG_VICTOR_MPC30X)	+= fixup-mpc30x.o
 obj-$(CONFIG_ZAO_CAPCELLA)	+= fixup-capcella.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index 2406835..87920b2 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -1,14 +1,37 @@
+/*
+ * Copyright (C) 2003, 2004  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2005  MIPS Technologies, Inc.  All rights reserved.
+ *	Author:	 Maciej W. Rozycki <macro@mips.com>
+ *
+ *  This program is free software; you can distribute 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 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/config.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+
 #include <asm/mips-boards/atlasint.h>
 
-#define INTD		ATLASINT_INTD
-#define INTC		ATLASINT_INTC
-#define INTB		ATLASINT_INTB
+#define PCIA		ATLASINT_PCIA
+#define PCIB		ATLASINT_PCIB
+#define PCIC		ATLASINT_PCIC
+#define PCID		ATLASINT_PCID
 #define INTA		ATLASINT_INTA
-#define SCSI		ATLASINT_SCSI
+#define INTB		ATLASINT_INTB
 #define ETH		ATLASINT_ETH
+#define INTC		ATLASINT_INTC
+#define SCSI		ATLASINT_SCSI
+#define INTD		ATLASINT_INTD
 
 static char irq_tab[][5] __initdata = {
 	/*      INTA    INTB    INTC    INTD */
@@ -27,13 +50,13 @@
 	{0,	0,	0,	0,	0 },	/* 12: Unused */
 	{0,	0,	0,	0,	0 },	/* 13: Unused */
 	{0,	0,	0,	0,	0 },	/* 14: Unused */
-	{0,	0,	0,	0,	0 },	/* 15: Unused */
+	{0,	PCIA,	PCIB,	PCIC,	PCID },	/* 15: cPCI (behind 21150) */
 	{0,	SCSI,	0,	0,	0 },	/* 16: SYM53C810A SCSI */
 	{0,	0,	0,	0,	0 },	/* 17: Core */
-	{0,	INTA,	INTB,	INTC,	INTD },	/* 18: PCI Slot 1 */
-	{0,	ETH,	0,	0,	0 },	/* 19: SAA9730 Ethernet */
-	{0,	0,	0,	0,	0 },	/* 20: PCI Slot 3 */
-	{0,	0,	0,	0,	0 }	/* 21: PCI Slot 4 */
+	{0,	INTA,	INTB,	INTC,	INTD },	/* 18: PCI Slot */
+	{0,	ETH,	0,	0,	0 },	/* 19: SAA9730 Eth. et al. */
+	{0,	0,	0,	0,	0 },	/* 20: Unused */
+	{0,	0,	0,	0,	0 }	/* 21: Unused */
 };
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
index 39fe2b1..c2f8304 100644
--- a/arch/mips/pci/fixup-au1000.c
+++ b/arch/mips/pci/fixup-au1000.c
@@ -26,7 +26,6 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -34,82 +33,7 @@
 
 #include <asm/mach-au1x00/au1000.h>
 
-/*
- * Shortcut
- */
-#ifdef CONFIG_SOC_AU1500
-#define INTA AU1000_PCI_INTA
-#define INTB AU1000_PCI_INTB
-#define INTC AU1000_PCI_INTC
-#define INTD AU1000_PCI_INTD
-#endif
-
-#ifdef CONFIG_SOC_AU1550
-#define INTA AU1550_PCI_INTA
-#define INTB AU1550_PCI_INTB
-#define INTC AU1550_PCI_INTC
-#define INTD AU1550_PCI_INTD
-#endif
-
-#define INTX    0xFF /* not valid */
-
-#ifdef CONFIG_MIPS_DB1500
-static char irq_tab_alchemy[][5] __initdata = {
- [12] =	{ -1, INTA, INTX, INTX, INTX},   /* IDSEL 12 - HPT371   */
- [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
-};
-#endif
-
-#ifdef CONFIG_MIPS_BOSPORUS
-static char irq_tab_alchemy[][5] __initdata = {
- [11] =	{ -1, INTA, INTB, INTX, INTX},   /* IDSEL 11 - miniPCI  */
- [12] =	{ -1, INTA, INTX, INTX, INTX},   /* IDSEL 12 - SN1741   */
- [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
-};
-#endif
-
-#ifdef CONFIG_MIPS_MIRAGE
-static char irq_tab_alchemy[][5] __initdata = {
- [11] =	{ -1, INTD, INTX, INTX, INTX},   /* IDSEL 11 - SMI VGX */
- [12] =	{ -1, INTX, INTX, INTC, INTX},   /* IDSEL 12 - PNX1300 */
- [13] =	{ -1, INTA, INTB, INTX, INTX},   /* IDSEL 13 - miniPCI */
-};
-#endif
-
-#ifdef CONFIG_MIPS_DB1550
-static char irq_tab_alchemy[][5] __initdata = {
- [11] =	{ -1, INTC, INTX, INTX, INTX},   /* IDSEL 11 - on-board HPT371    */
- [12] =	{ -1, INTB, INTC, INTD, INTA},   /* IDSEL 12 - PCI slot 2 (left)  */
- [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot 1 (right) */
-};
-#endif
-
-#ifdef CONFIG_MIPS_PB1500
-static char irq_tab_alchemy[][5] __initdata = {
- [12] = { -1, INTA, INTX, INTX, INTX},   /* IDSEL 12 - HPT370   */
- [13] = { -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
-};
-#endif
-
-#ifdef CONFIG_MIPS_PB1550
-static char irq_tab_alchemy[][5] __initdata = {
- [12] =	{ -1, INTB, INTC, INTD, INTA},   /* IDSEL 12 - PCI slot 2 (left)  */
- [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot 1 (right) */
-};
-#endif
-
-#ifdef CONFIG_MIPS_MTX1
-static char irq_tab_alchemy[][5] __initdata = {
- [0] = { -1, INTA, INTB, INTX, INTX},   /* IDSEL 00 - AdapterA-Slot0 (top)    */
- [1] = { -1, INTB, INTA, INTX, INTX},   /* IDSEL 01 - AdapterA-Slot1 (bottom) */
- [2] = { -1, INTC, INTD, INTX, INTX},   /* IDSEL 02 - AdapterB-Slot0 (top)    */
- [3] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 03 - AdapterB-Slot1 (bottom) */
- [4] = { -1, INTA, INTB, INTX, INTX},   /* IDSEL 04 - AdapterC-Slot0 (top)    */
- [5] = { -1, INTB, INTA, INTX, INTX},   /* IDSEL 05 - AdapterC-Slot1 (bottom) */
- [6] = { -1, INTC, INTD, INTX, INTX},   /* IDSEL 06 - AdapterD-Slot0 (top)    */
- [7] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 07 - AdapterD-Slot1 (bottom) */
-};
-#endif
+extern char irq_tab_alchemy[][5];
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index 57e1ca2..909292f 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -21,6 +21,20 @@
 
 extern int cobalt_board_id;
 
+static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
+{
+	if (dev->devfn == PCI_DEVFN(0, 0) &&
+		(dev->class >> 8) == PCI_CLASS_MEMORY_OTHER) {
+
+		dev->class = (PCI_CLASS_BRIDGE_HOST << 8) | (dev->class & 0xff);
+
+		printk(KERN_INFO "Galileo: fixed bridge class\n");
+	}
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
+	 qube_raq_galileo_early_fixup);
+
 static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
 {
 	unsigned short cfgword;
@@ -48,6 +62,9 @@
 {
 	unsigned short galileo_id;
 
+	if (dev->devfn != PCI_DEVFN(0, 0))
+		return;
+
 	/* Fix PCI latency-timer and cache-line-size values in Galileo
 	 * host bridge.
 	 */
@@ -55,6 +72,13 @@
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
 
 	/*
+	 * The code described by the comment below has been removed
+	 * as it causes bus mastering by the Ethernet controllers
+	 * to break under any kind of network load. We always set
+	 * the retry timeouts to their maximum.
+	 *
+	 * --x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--
+	 *
 	 * On all machines prior to Q2, we had the STOP line disconnected
 	 * from Galileo to VIA on PCI.  The new Galileo does not function
 	 * correctly unless we have it connected.
@@ -64,21 +88,43 @@
 	 */
 	pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
 	galileo_id &= 0xff;	/* mask off class info */
+
+ 	printk(KERN_INFO "Galileo: revision %u\n", galileo_id);
+
+#if 0
 	if (galileo_id >= 0x10) {
 		/* New Galileo, assumes PCI stop line to VIA is connected. */
 		GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS);
-	} else if (galileo_id == 0x1 || galileo_id == 0x2) {
+	} else if (galileo_id == 0x1 || galileo_id == 0x2)
+#endif
+	{
 		signed int timeo;
 		/* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */
 		timeo = GALILEO_INL(GT_PCI0_TOR_OFS);
 		/* Old Galileo, assumes PCI STOP line to VIA is disconnected. */
-		GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS);
+		GALILEO_OUTL(
+			(0xff << 16) |		/* retry count */
+			(0xff << 8) |		/* timeout 1   */
+			0xff,			/* timeout 0   */
+			GT_PCI0_TOR_OFS);
+
+		/* enable PCI retry exceeded interrupt */
+		GALILEO_OUTL(GALILEO_INTR_RETRY_CTR | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS);
 	}
 }
 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
 	 qube_raq_galileo_fixup);
 
+static char irq_tab_qube1[] __initdata = {
+  [COBALT_PCICONF_CPU]     = 0,
+  [COBALT_PCICONF_ETH0]    = COBALT_QUBE1_ETH0_IRQ,
+  [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ,
+  [COBALT_PCICONF_VIA]     = 0,
+  [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
+  [COBALT_PCICONF_ETH1]    = 0
+};
+
 static char irq_tab_cobalt[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
   [COBALT_PCICONF_ETH0]    = COBALT_ETH0_IRQ,
@@ -99,6 +145,9 @@
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+	if (cobalt_board_id < COBALT_BRD_ID_QUBE2)
+		return irq_tab_qube1[slot];
+
 	if (cobalt_board_id == COBALT_BRD_ID_RAQ2)
 		return irq_tab_raq2[slot];
 
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
new file mode 100644
index 0000000..4256b3b
--- /dev/null
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -0,0 +1,57 @@
+/*
+ *  Philips PNX8550 pci fixups.
+ *
+ *  Copyright 2005 Embedded Alley Solutions, Inc
+ *  source@embeddealley.com
+ *
+ *  This program is free software; you can distribute 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 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/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach-pnx8550/pci.h>
+#include <asm/mach-pnx8550/int.h>
+
+
+#undef	DEBUG
+#ifdef 	DEBUG
+#define	DBG(x...)	printk(x)
+#else
+#define	DBG(x...)
+#endif
+
+extern char irq_tab_jbs[][5];
+
+void __init pcibios_fixup_resources(struct pci_dev *dev)
+{
+	/* no need to fixup IO resources */
+}
+
+void __init pcibios_fixup(void)
+{
+	/* nothing to do here */
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_tab_jbs[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff --git a/arch/mips/pci/fixup-tx4938.c b/arch/mips/pci/fixup-tx4938.c
new file mode 100644
index 0000000..f455520
--- /dev/null
+++ b/arch/mips/pci/fixup-tx4938.c
@@ -0,0 +1,92 @@
+/*
+ * Toshiba rbtx4938 pci routines
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/tx4938/rbtx4938.h>
+
+extern struct pci_controller tx4938_pci_controller[];
+
+int pci_get_irq(struct pci_dev *dev, int pin)
+{
+	int irq = pin;
+	u8 slot = PCI_SLOT(dev->devfn);
+	struct pci_controller *controller = (struct pci_controller *)dev->sysdata;
+
+	if (controller == &tx4938_pci_controller[1]) {
+		/* TX4938 PCIC1 */
+		switch (slot) {
+		case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
+			if (tx4938_ccfgptr->pcfg & TX4938_PCFG_ETH0_SEL)
+				return RBTX4938_IRQ_IRC + TX4938_IR_ETH0;
+			break;
+		case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
+			if (tx4938_ccfgptr->pcfg & TX4938_PCFG_ETH1_SEL)
+				return RBTX4938_IRQ_IRC + TX4938_IR_ETH1;
+			break;
+		}
+		return 0;
+	}
+
+	/* IRQ rotation */
+	irq--;	/* 0-3 */
+	if (dev->bus->parent == NULL &&
+	    (slot == TX4938_PCIC_IDSEL_AD_TO_SLOT(23))) {
+		/* PCI CardSlot (IDSEL=A23) */
+		/* PCIA => PCIA (IDSEL=A23) */
+		irq = (irq + 0 + slot) % 4;
+	} else {
+		/* PCI Backplane */
+		irq = (irq + 33 - slot) % 4;
+	}
+	irq++;	/* 1-4 */
+
+	switch (irq) {
+	case 1:
+		irq = RBTX4938_IRQ_IOC_PCIA;
+		break;
+	case 2:
+		irq = RBTX4938_IRQ_IOC_PCIB;
+		break;
+	case 3:
+		irq = RBTX4938_IRQ_IOC_PCIC;
+		break;
+	case 4:
+		irq = RBTX4938_IRQ_IOC_PCID;
+		break;
+	}
+	return irq;
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	unsigned char irq = 0;
+
+	irq = pci_get_irq(dev, pin);
+
+	printk(KERN_INFO "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n",
+	       dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn),
+	       PCI_FUNC(dev->devfn), irq);
+
+	return irq;
+}
+
+/*
+ * Do platform specific device initialization at pci_enable_device() time
+ */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
diff --git a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c
index c1c91ca..be14201 100644
--- a/arch/mips/pci/ops-au1000.c
+++ b/arch/mips/pci/ops-au1000.c
@@ -50,11 +50,6 @@
 
 int (*board_pci_idsel)(unsigned int devsel, int assert);
 
-/* CP0 hazard avoidance. */
-#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
-				     "nop; nop; nop; nop;\t" \
-				     ".set reorder\n\t")
-
 void mod_wired_entry(int entry, unsigned long entrylo0,
 		unsigned long entrylo1, unsigned long entryhi,
 		unsigned long pagemask)
@@ -66,16 +61,12 @@
 	old_ctx = read_c0_entryhi() & 0xff;
 	old_pagemask = read_c0_pagemask();
 	write_c0_index(entry);
-	BARRIER;
 	write_c0_pagemask(pagemask);
 	write_c0_entryhi(entryhi);
 	write_c0_entrylo0(entrylo0);
 	write_c0_entrylo1(entrylo1);
-	BARRIER;
 	tlb_write_indexed();
-	BARRIER;
 	write_c0_entryhi(old_ctx);
-	BARRIER;
 	write_c0_pagemask(old_pagemask);
 }
 
@@ -128,9 +119,8 @@
 		last_entryLo0  = last_entryLo1 = 0xffffffff;
 	}
 
-	/* Since the Au1xxx doesn't do the idsel timing exactly to spec,
-	 * many board vendors implement their own off-chip idsel, so call
-	 * it now.  If it doesn't succeed, may as well bail out at this point.
+	/* Allow board vendors to implement their own off-chip idsel.
+	 * If it doesn't succeed, may as well bail out at this point.
 	 */
 	if (board_pci_idsel) {
 		if (board_pci_idsel(device, 1) == 0) {
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index 4b4e086..dc35270 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
+ *	All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -17,7 +19,6 @@
  *
  * MIPS boards specific PCI support.
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -57,13 +58,6 @@
 		return -1;
 	}
 
-#ifdef CONFIG_MIPS_BOARDS_GEN
-	if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) {
-		/* MIPS Core boards have Bonito connected as device 17 */
-		return -1;
-	}
-#endif
-
 	/* Clear cause register bits */
 	BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
 			  BONITO_PCICMD_MTABORT_CLR);
diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c
index c5b0fc1..c180793 100644
--- a/arch/mips/pci/ops-gt64111.c
+++ b/arch/mips/pci/ops-gt64111.c
@@ -18,15 +18,15 @@
 #include <asm/cobalt/cobalt.h>
 
 /*
- * Accessing device 31 hangs the GT64120.  Not sure if this will also hang
- * the GT64111, let's be paranoid for now.
+ * Device 31 on the GT64111 is used to generate PCI special
+ * cycles, so we shouldn't expected to find a device there ...
  */
 static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn)
 {
-	if (bus->number == 0 && devfn == PCI_DEVFN(31, 0))
-		return -1;
+	if (bus->number == 0 && PCI_SLOT(devfn) < 31)
+		return 0;
 
-	return 0;
+	return -1;
 }
 
 static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn,
diff --git a/arch/mips/pci/ops-gt64120.c b/arch/mips/pci/ops-gt64120.c
index 7b99dfa..6335844 100644
--- a/arch/mips/pci/ops-gt64120.c
+++ b/arch/mips/pci/ops-gt64120.c
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
+ *	All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -43,10 +45,6 @@
 	unsigned char busnum = bus->number;
 	u32 intr;
 
-	if ((busnum == 0) && (PCI_SLOT(devfn) == 0))
-		/* Galileo itself is devfn 0, don't move it around */
-		return -1;
-
 	if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
 		return -1;	/* Because of a bug in the galileo (for slot 31). */
 
diff --git a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c
index 7bc0996..5d9fbb0 100644
--- a/arch/mips/pci/ops-msc.c
+++ b/arch/mips/pci/ops-msc.c
@@ -21,7 +21,6 @@
  * MIPS boards specific PCI support.
  *
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -49,34 +48,17 @@
 	struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
 {
 	unsigned char busnum = bus->number;
-	unsigned char type;
 	u32 intr;
 
-#ifdef CONFIG_MIPS_BOARDS_GEN
-	if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) {
-		/* MIPS Core boards have SOCit connected as device 17 */
-		return -1;
-	}
-#endif
-
 	/* Clear status register bits. */
 	MSC_WRITE(MSC01_PCI_INTSTAT,
 		  (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
 
-	/* Setup address */
-	if (busnum == 0)
-		type = 0;	/* Type 0 */
-	else
-		type = 1;	/* Type 1 */
-
 	MSC_WRITE(MSC01_PCI_CFGADDR,
 		  ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
-		   (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF)
-		   | (PCI_FUNC(devfn) <<
-		      MSC01_PCI_CFGADDR_FNUM_SHF) | ((where /
-						      4) <<
-						     MSC01_PCI_CFGADDR_RNUM_SHF)
-		   | (type)));
+		   (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) |
+		   (PCI_FUNC(devfn) << MSC01_PCI_CFGADDR_FNUM_SHF) |
+		   ((where / 4) << MSC01_PCI_CFGADDR_RNUM_SHF)));
 
 	/* Perform access */
 	if (access_type == PCI_ACCESS_WRITE)
@@ -86,15 +68,12 @@
 
 	/* Detect Master/Target abort */
 	MSC_READ(MSC01_PCI_INTSTAT, intr);
-	if (intr & (MSC01_PCI_INTCFG_MA_BIT |
-		    MSC01_PCI_INTCFG_TA_BIT)) {
+	if (intr & (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)) {
 		/* Error occurred */
 
 		/* Clear bits */
-		MSC_READ(MSC01_PCI_INTSTAT, intr);
 		MSC_WRITE(MSC01_PCI_INTSTAT,
-			  (MSC01_PCI_INTCFG_MA_BIT |
-			   MSC01_PCI_INTCFG_TA_BIT));
+			  (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
 
 		return -1;
 	}
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
index a716992..a8d38dc 100644
--- a/arch/mips/pci/ops-nile4.c
+++ b/arch/mips/pci/ops-nile4.c
@@ -15,7 +15,7 @@
 
 volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
 
-static spinlock_t nile4_pci_lock;
+static DEFINE_SPINLOCK(nile4_pci_lock);
 
 static int nile4_pcibios_config_access(unsigned char access_type,
 	struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
diff --git a/arch/mips/pci/ops-pnx8550.c b/arch/mips/pci/ops-pnx8550.c
new file mode 100644
index 0000000..454b65c
--- /dev/null
+++ b/arch/mips/pci/ops-pnx8550.c
@@ -0,0 +1,284 @@
+/*
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *
+ *  2.6 port, Embedded Alley Solutions, Inc
+ *
+ *  Based on:
+ *  Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+
+#include <asm/mach-pnx8550/pci.h>
+#include <asm/mach-pnx8550/glb.h>
+#include <asm/debug.h>
+
+
+static inline void clear_status(void)
+{
+	unsigned long pci_stat;
+
+	pci_stat = inl(PCI_BASE | PCI_GPPM_STATUS);
+	outl(pci_stat, PCI_BASE | PCI_GPPM_ICLR);
+}
+
+static inline unsigned int
+calc_cfg_addr(struct pci_bus *bus, unsigned int devfn, int where)
+{
+	unsigned int addr;
+
+	addr = ((bus->number > 0) ? (((bus->number & 0xff) << PCI_CFG_BUS_SHIFT) | 1) : 0);
+	addr |= ((devfn & 0xff) << PCI_CFG_FUNC_SHIFT) | (where & 0xfc);
+
+	return addr;
+}
+
+static int
+config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int where, unsigned int pci_mode, unsigned int *val)
+{
+	unsigned int flags;
+	unsigned long loops = 0;
+	unsigned long ioaddr = calc_cfg_addr(bus, devfn, where);
+
+	local_irq_save(flags);
+	/*Clear pending interrupt status */
+	if (inl(PCI_BASE | PCI_GPPM_STATUS)) {
+		clear_status();
+		while (!(inl(PCI_BASE | PCI_GPPM_STATUS) == 0)) ;
+	}
+
+	outl(ioaddr, PCI_BASE | PCI_GPPM_ADDR);
+
+	if ((pci_cmd == PCI_CMD_IOW) || (pci_cmd == PCI_CMD_CONFIG_WRITE))
+		outl(*val, PCI_BASE | PCI_GPPM_WDAT);
+
+	outl(INIT_PCI_CYCLE | pci_cmd | (pci_mode & PCI_BYTE_ENABLE_MASK),
+	     PCI_BASE | PCI_GPPM_CTRL);
+
+	loops =
+	    ((loops_per_jiffy *
+	      PCI_IO_JIFFIES_TIMEOUT) >> (PCI_IO_JIFFIES_SHIFT));
+	while (1) {
+		if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_DONE) {
+			if ((pci_cmd == PCI_CMD_IOR) ||
+			    (pci_cmd == PCI_CMD_CONFIG_READ))
+				*val = inl(PCI_BASE | PCI_GPPM_RDAT);
+			clear_status();
+			local_irq_restore(flags);
+			return PCIBIOS_SUCCESSFUL;
+		} else if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_R_MABORT) {
+			break;
+		}
+
+		loops--;
+		if (loops == 0) {
+			printk("%s : Arbiter Locked.\n", __FUNCTION__);
+		}
+	}
+
+	clear_status();
+	if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) {
+		printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n",
+		       __FUNCTION__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr,
+		       pci_cmd);
+	}
+
+	if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_CONFIG_READ))
+		*val = 0xffffffff;
+	local_irq_restore(flags);
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int
+read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val)
+{
+	unsigned int data = 0;
+	int err;
+
+	if (bus == 0)
+		return -1;
+
+	err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
+	switch (where & 0x03) {
+	case 0:
+		*val = (unsigned char)(data & 0x000000ff);
+		break;
+	case 1:
+		*val = (unsigned char)((data & 0x0000ff00) >> 8);
+		break;
+	case 2:
+		*val = (unsigned char)((data & 0x00ff0000) >> 16);
+		break;
+	case 3:
+		*val = (unsigned char)((data & 0xff000000) >> 24);
+		break;
+	}
+
+	return err;
+}
+
+static int
+read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val)
+{
+	unsigned int data = 0;
+	int err;
+
+	if (bus == 0)
+		return -1;
+
+	if (where & 0x01)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(3 << (where & 3)), &data);
+	switch (where & 0x02) {
+	case 0:
+		*val = (unsigned short)(data & 0x0000ffff);
+		break;
+	case 2:
+		*val = (unsigned short)((data & 0xffff0000) >> 16);
+		break;
+	}
+
+	return err;
+}
+
+static int
+read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
+{
+	int err;
+	if (bus == 0)
+		return -1;
+
+	if (where & 0x03)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, 0, val);
+
+	return err;
+}
+
+static int
+write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
+{
+	unsigned int data = (unsigned int)val;
+	int err;
+
+	if (bus == 0)
+		return -1;
+
+	switch (where & 0x03) {
+	case 1:
+		data = (data << 8);
+		break;
+	case 2:
+		data = (data << 16);
+		break;
+	case 3:
+		data = (data << 24);
+		break;
+	default:
+		break;
+	}
+
+	err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
+
+	return err;
+}
+
+static int
+write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
+{
+	unsigned int data = (unsigned int)val;
+	int err;
+
+	if (bus == 0)
+		return -1;
+
+	if (where & 0x01)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	switch (where & 0x02) {
+	case 2:
+		data = (data << 16);
+		break;
+	default:
+		break;
+	}
+	err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(3 << (where & 3)), &data);
+
+	return err;
+}
+
+static int
+write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
+{
+	int err;
+	if (bus == 0)
+		return -1;
+
+	if (where & 0x03)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, 0, &val);
+
+	return err;
+}
+
+static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
+{
+	switch (size) {
+	case 1: {
+			u8 _val;
+			int rc = read_config_byte(bus, devfn, where, &_val);
+			*val = _val;
+			return rc;
+		}
+       case 2: {
+			u16 _val;
+			int rc = read_config_word(bus, devfn, where, &_val);
+			*val = _val;
+			return rc;
+		}
+	default:
+		return read_config_dword(bus, devfn, where, val);
+	}
+}
+
+static int config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+	switch (size) {
+	case 1:
+		return write_config_byte(bus, devfn, where, (u8) val);
+	case 2:
+		return write_config_word(bus, devfn, where, (u16) val);
+	default:
+		return write_config_dword(bus, devfn, where, val);
+	}
+}
+
+struct pci_ops pnx8550_pci_ops = {
+	config_read,
+	config_write
+};
diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c
new file mode 100644
index 0000000..4c0dcfc
--- /dev/null
+++ b/arch/mips/pci/ops-tx4938.c
@@ -0,0 +1,198 @@
+/*
+ * Define the pci_ops for the Toshiba rbtx4938
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/tx4938/rbtx4938.h>
+
+/* initialize in setup */
+struct resource pci_io_resource = {
+	.name	= "pci IO space",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_IO
+};
+
+/* initialize in setup */
+struct resource pci_mem_resource = {
+	.name	= "pci memory space",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_MEM
+};
+
+struct resource tx4938_pcic1_pci_io_resource = {
+       	.name	= "PCI1 IO",
+       	.start	= 0,
+       	.end	= 0,
+       	.flags	= IORESOURCE_IO
+};
+struct resource tx4938_pcic1_pci_mem_resource = {
+       	.name	= "PCI1 mem",
+       	.start	= 0,
+       	.end	= 0,
+       	.flags	= IORESOURCE_MEM
+};
+
+static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+{
+	if (bus > 0) {
+		/* Type 1 configuration */
+		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
+	} else {
+		if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
+			return -1;
+
+		/* Type 0 configuration */
+		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
+	}
+	/* clear M_ABORT and Disable M_ABORT Int. */
+	tx4938_pcicptr->pcistatus =
+	    (tx4938_pcicptr->pcistatus & 0x0000ffff) |
+	    (PCI_STATUS_REC_MASTER_ABORT << 16);
+	tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+
+	return 0;
+}
+
+static int check_abort(int flags)
+{
+	int code = PCIBIOS_SUCCESSFUL;
+	/* wait write cycle completion before checking error status */
+	while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
+				;
+	if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+		tx4938_pcicptr->pcistatus =
+		    (tx4938_pcicptr->
+		     pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
+						<< 16);
+		tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+		code = PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	return code;
+}
+
+static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 * val)
+{
+	int flags, retval, dev, busno, func;
+
+	dev = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+
+	/* check if the bus is top-level */
+	if (bus->parent != NULL)
+		busno = bus->number;
+	else {
+		busno = 0;
+	}
+
+	if (mkaddr(busno, devfn, where, &flags))
+		return -1;
+
+	switch (size) {
+	case 1:
+		*val = *(volatile u8 *) ((ulong) & tx4938_pcicptr->g2pcfgdata |
+#ifdef __BIG_ENDIAN
+			      ((where & 3) ^ 3));
+#else
+			      (where & 3));
+#endif
+		break;
+	case 2:
+		*val = *(volatile u16 *) ((ulong) & tx4938_pcicptr->g2pcfgdata |
+#ifdef __BIG_ENDIAN
+				((where & 3) ^ 2));
+#else
+				(where & 3));
+#endif
+		break;
+	case 4:
+		*val = tx4938_pcicptr->g2pcfgdata;
+		break;
+	}
+
+	retval = check_abort(flags);
+	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
+		*val = 0xffffffff;
+
+	return retval;
+}
+
+static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+						int size, u32 val)
+{
+	int flags, dev, busno, func;
+
+	busno = bus->number;
+	dev = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+
+	/* check if the bus is top-level */
+	if (bus->parent != NULL) {
+		busno = bus->number;
+	} else {
+		busno = 0;
+	}
+
+	if (mkaddr(busno, devfn, where, &flags))
+		return -1;
+
+	switch (size) {
+	case 1:
+		*(volatile u8 *) ((ulong) & tx4938_pcicptr->g2pcfgdata |
+#ifdef __BIG_ENDIAN
+			  ((where & 3) ^ 3)) = val;
+#else
+			  (where & 3)) = val;
+#endif
+		break;
+	case 2:
+		*(volatile u16 *) ((ulong) & tx4938_pcicptr->g2pcfgdata |
+#ifdef __BIG_ENDIAN
+			((where & 0x3) ^ 0x2)) = val;
+#else
+			(where & 3)) = val;
+#endif
+		break;
+	case 4:
+		tx4938_pcicptr->g2pcfgdata = val;
+		break;
+	}
+
+	return check_abort(flags);
+}
+
+struct pci_ops tx4938_pci_ops = {
+	tx4938_pcibios_read_config,
+	tx4938_pcibios_write_config
+};
+
+struct pci_controller tx4938_pci_controller[] = {
+	/* h/w only supports devices 0x00 to 0x14 */
+	{
+		.pci_ops        = &tx4938_pci_ops,
+		.io_resource    = &pci_io_resource,
+		.mem_resource   = &pci_mem_resource,
+	},
+	/* h/w only supports devices 0x00 to 0x14 */
+	{
+		.pci_ops        = &tx4938_pci_ops,
+		.io_resource    = &tx4938_pcic1_pci_io_resource,
+		.mem_resource   = &tx4938_pcic1_pci_mem_resource,
+        }
+};
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
new file mode 100644
index 0000000..f194b4e
--- /dev/null
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2001,2002,2005 Broadcom Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * BCM1x80/1x55-specific PCI support
+ *
+ * This module provides the glue between Linux's PCI subsystem
+ * and the hardware.  We basically provide glue for accessing
+ * configuration space, and set up the translation for I/O
+ * space accesses.
+ *
+ * To access configuration space, we use ioremap.  In the 32-bit
+ * kernel, this consumes either 4 or 8 page table pages, and 16MB of
+ * kernel mapped memory.  Hopefully neither of these should be a huge
+ * problem.
+ *
+ * XXX: AT THIS TIME, ONLY the NATIVE PCI-X INTERFACE IS SUPPORTED.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_scd.h>
+#include <asm/sibyte/board.h>
+#include <asm/io.h>
+
+/*
+ * Macros for calculating offsets into config space given a device
+ * structure or dev/fun/reg
+ */
+#define CFGOFFSET(bus,devfn,where) (((bus)<<16)+((devfn)<<8)+(where))
+#define CFGADDR(bus,devfn,where)   CFGOFFSET((bus)->number,(devfn),where)
+
+static void *cfg_space;
+
+#define PCI_BUS_ENABLED	1
+#define PCI_DEVICE_MODE	2
+
+static int bcm1480_bus_status = 0;
+
+#define PCI_BRIDGE_DEVICE  0
+
+/*
+ * Read/write 32-bit values in config space.
+ */
+static inline u32 READCFG32(u32 addr)
+{
+	return *(u32 *)(cfg_space + (addr&~3));
+}
+
+static inline void WRITECFG32(u32 addr, u32 data)
+{
+	*(u32 *)(cfg_space + (addr & ~3)) = data;
+}
+
+int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return dev->irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
+/*
+ * Some checks before doing config cycles:
+ * In PCI Device Mode, hide everything on bus 0 except the LDT host
+ * bridge.  Otherwise, access is controlled by bridge MasterEn bits.
+ */
+static int bcm1480_pci_can_access(struct pci_bus *bus, int devfn)
+{
+	u32 devno;
+
+	if (!(bcm1480_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE)))
+		return 0;
+
+	if (bus->number == 0) {
+		devno = PCI_SLOT(devfn);
+ 		if (bcm1480_bus_status & PCI_DEVICE_MODE)
+			return 0;
+		else
+			return 1;
+	} else
+		return 1;
+}
+
+/*
+ * Read/write access functions for various sizes of values
+ * in config space.  Return all 1's for disallowed accesses
+ * for a kludgy but adequate simulation of master aborts.
+ */
+
+static int bcm1480_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 * val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (bcm1480_pci_can_access(bus, devfn))
+		data = READCFG32(CFGADDR(bus, devfn, where));
+	else
+		data = 0xFFFFFFFF;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int bcm1480_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 val)
+{
+	u32 cfgaddr = CFGADDR(bus, devfn, where);
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (!bcm1480_pci_can_access(bus, devfn))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	data = READCFG32(cfgaddr);
+
+	if (size == 1)
+		data = (data & ~(0xff << ((where & 3) << 3))) |
+		    (val << ((where & 3) << 3));
+	else if (size == 2)
+		data = (data & ~(0xffff << ((where & 3) << 3))) |
+		    (val << ((where & 3) << 3));
+	else
+		data = val;
+
+	WRITECFG32(cfgaddr, data);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops bcm1480_pci_ops = {
+	bcm1480_pcibios_read,
+	bcm1480_pcibios_write,
+};
+
+static struct resource bcm1480_mem_resource = {
+	.name	= "BCM1480 PCI MEM",
+	.start	= 0x30000000UL,
+	.end	= 0x3fffffffUL,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource bcm1480_io_resource = {
+	.name	= "BCM1480 PCI I/O",
+	.start	= 0x2c000000UL,
+	.end	= 0x2dffffffUL,
+	.flags	= IORESOURCE_IO,
+};
+
+struct pci_controller bcm1480_controller = {
+	.pci_ops	= &bcm1480_pci_ops,
+	.mem_resource	= &bcm1480_mem_resource,
+	.io_resource	= &bcm1480_io_resource,
+};
+
+
+static int __init bcm1480_pcibios_init(void)
+{
+	uint32_t cmdreg;
+	uint64_t reg;
+	extern int pci_probe_only;
+
+	/* CFE will assign PCI resources */
+	pci_probe_only = 1;
+
+	/* Avoid ISA compat ranges.  */
+	PCIBIOS_MIN_IO = 0x00008000UL;
+	PCIBIOS_MIN_MEM = 0x01000000UL;
+
+	/* Set I/O resource limits. - unlimited for now to accomodate HT */
+	ioport_resource.end = 0xffffffffUL;
+	iomem_resource.end = 0xffffffffUL;
+
+	cfg_space = ioremap(A_BCM1480_PHYS_PCI_CFG_MATCH_BITS, 16*1024*1024);
+
+	/*
+	 * See if the PCI bus has been configured by the firmware.
+	 */
+	reg = *((volatile uint64_t *) IOADDR(A_SCD_SYSTEM_CFG));
+	if (!(reg & M_BCM1480_SYS_PCI_HOST)) {
+		bcm1480_bus_status |= PCI_DEVICE_MODE;
+	} else {
+		cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0),
+					     PCI_COMMAND));
+		if (!(cmdreg & PCI_COMMAND_MASTER)) {
+			printk
+			    ("PCI: Skipping PCI probe.  Bus is not initialized.\n");
+			iounmap(cfg_space);
+			return 1; /* XXX */
+		}
+		bcm1480_bus_status |= PCI_BUS_ENABLED;
+	}
+
+	/* turn on ExpMemEn */
+	cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40));
+	printk("PCIFeatureCtrl = %x\n", cmdreg);
+	WRITECFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40),
+			cmdreg | 0x10);
+	cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40));
+	printk("PCIFeatureCtrl = %x\n", cmdreg);
+
+	/*
+	 * Establish mappings in KSEG2 (kernel virtual) to PCI I/O
+	 * space.  Use "match bytes" policy to make everything look
+	 * little-endian.  So, you need to also set
+	 * CONFIG_SWAP_IO_SPACE, but this is the combination that
+	 * works correctly with most of Linux's drivers.
+	 * XXX ehs: Should this happen in PCI Device mode?
+	 */
+
+	set_io_port_base((unsigned long)
+		ioremap(A_BCM1480_PHYS_PCI_IO_MATCH_BYTES, 65536));
+	isa_slot_offset = (unsigned long)
+		ioremap(A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES, 1024*1024);
+
+	register_pci_controller(&bcm1480_controller);
+
+#ifdef CONFIG_VGA_CONSOLE
+	take_over_console(&vga_con,0,MAX_NR_CONSOLES-1,1);
+#endif
+	return 0;
+}
+
+arch_initcall(bcm1480_pcibios_init);
diff --git a/arch/mips/pci/pci-bcm1480ht.c b/arch/mips/pci/pci-bcm1480ht.c
new file mode 100644
index 0000000..aca4a2e
--- /dev/null
+++ b/arch/mips/pci/pci-bcm1480ht.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2001,2002,2005 Broadcom Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * BCM1480/1455-specific HT support (looking like PCI)
+ *
+ * This module provides the glue between Linux's PCI subsystem
+ * and the hardware.  We basically provide glue for accessing
+ * configuration space, and set up the translation for I/O
+ * space accesses.
+ *
+ * To access configuration space, we use ioremap.  In the 32-bit
+ * kernel, this consumes either 4 or 8 page table pages, and 16MB of
+ * kernel mapped memory.  Hopefully neither of these should be a huge
+ * problem.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_scd.h>
+#include <asm/sibyte/board.h>
+#include <asm/io.h>
+
+/*
+ * Macros for calculating offsets into config space given a device
+ * structure or dev/fun/reg
+ */
+#define CFGOFFSET(bus,devfn,where) (((bus)<<16)+((devfn)<<8)+(where))
+#define CFGADDR(bus,devfn,where)   CFGOFFSET((bus)->number,(devfn),where)
+
+static void *ht_cfg_space;
+
+#define PCI_BUS_ENABLED	1
+#define PCI_DEVICE_MODE	2
+
+static int bcm1480ht_bus_status = 0;
+
+#define PCI_BRIDGE_DEVICE  0
+#define HT_BRIDGE_DEVICE   1
+
+/*
+ * HT's level-sensitive interrupts require EOI, which is generated
+ * through a 4MB memory-mapped region
+ */
+unsigned long ht_eoi_space;
+
+/*
+ * Read/write 32-bit values in config space.
+ */
+static inline u32 READCFG32(u32 addr)
+{
+	return *(u32 *)(ht_cfg_space + (addr&~3));
+}
+
+static inline void WRITECFG32(u32 addr, u32 data)
+{
+	*(u32 *)(ht_cfg_space + (addr & ~3)) = data;
+}
+
+/*
+ * Some checks before doing config cycles:
+ * In PCI Device Mode, hide everything on bus 0 except the LDT host
+ * bridge.  Otherwise, access is controlled by bridge MasterEn bits.
+ */
+static int bcm1480ht_can_access(struct pci_bus *bus, int devfn)
+{
+	u32 devno;
+
+	if (!(bcm1480ht_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE)))
+		return 0;
+
+	if (bus->number == 0) {
+		devno = PCI_SLOT(devfn);
+ 		if (bcm1480ht_bus_status & PCI_DEVICE_MODE)
+			return 0;
+	}
+	return 1;
+}
+
+/*
+ * Read/write access functions for various sizes of values
+ * in config space.  Return all 1's for disallowed accesses
+ * for a kludgy but adequate simulation of master aborts.
+ */
+
+static int bcm1480ht_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 * val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (bcm1480ht_can_access(bus, devfn))
+		data = READCFG32(CFGADDR(bus, devfn, where));
+	else
+		data = 0xFFFFFFFF;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int bcm1480ht_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+				   int where, int size, u32 val)
+{
+	u32 cfgaddr = CFGADDR(bus, devfn, where);
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (!bcm1480ht_can_access(bus, devfn))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	data = READCFG32(cfgaddr);
+
+	if (size == 1)
+		data = (data & ~(0xff << ((where & 3) << 3))) |
+		    (val << ((where & 3) << 3));
+	else if (size == 2)
+		data = (data & ~(0xffff << ((where & 3) << 3))) |
+		    (val << ((where & 3) << 3));
+	else
+		data = val;
+
+	WRITECFG32(cfgaddr, data);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int bcm1480ht_pcibios_get_busno(void)
+{
+	return 0;
+}
+
+struct pci_ops bcm1480ht_pci_ops = {
+	.read	= bcm1480ht_pcibios_read,
+	.write	= bcm1480ht_pcibios_write,
+};
+
+static struct resource bcm1480ht_mem_resource = {
+	.name	= "BCM1480 HT MEM",
+	.start	= 0x40000000UL,
+	.end	= 0x5fffffffUL,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource bcm1480ht_io_resource = {
+	.name	= "BCM1480 HT I/O",
+	.start	= 0x00000000UL,
+	.end	= 0x01ffffffUL,
+	.flags	= IORESOURCE_IO,
+};
+
+struct pci_controller bcm1480ht_controller = {
+	.pci_ops	= &bcm1480ht_pci_ops,
+	.mem_resource	= &bcm1480ht_mem_resource,
+	.io_resource	= &bcm1480ht_io_resource,
+	.index		= 1,
+	.get_busno	= bcm1480ht_pcibios_get_busno,
+};
+
+static int __init bcm1480ht_pcibios_init(void)
+{
+	uint32_t cmdreg;
+
+	ht_cfg_space = ioremap(A_BCM1480_PHYS_HT_CFG_MATCH_BITS, 16*1024*1024);
+
+	/*
+	 * See if the PCI bus has been configured by the firmware.
+	 */
+	cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0),
+				     PCI_COMMAND));
+	if (!(cmdreg & PCI_COMMAND_MASTER)) {
+		printk("HT: Skipping HT probe. Bus is not initialized.\n");
+		iounmap(ht_cfg_space);
+		return 1; /* XXX */
+	}
+	bcm1480ht_bus_status |= PCI_BUS_ENABLED;
+
+	ht_eoi_space = (unsigned long)
+		ioremap(A_BCM1480_PHYS_HT_SPECIAL_MATCH_BYTES,
+			4 * 1024 * 1024);
+
+	register_pci_controller(&bcm1480ht_controller);
+
+	return 0;
+}
+
+arch_initcall(bcm1480ht_pcibios_init);
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 068e0e5..efc96ce 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -485,5 +485,12 @@
 	pci_disable_swapping(d);
 }
 
+int pcibus_to_node(struct pci_bus *bus)
+{
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+
+	return bc->nasid;
+}
+
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
 	pci_fixup_ioc3);
diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c
index 000dc6a..180af89 100644
--- a/arch/mips/pci/pci-ip32.c
+++ b/arch/mips/pci/pci-ip32.c
@@ -136,7 +136,9 @@
 	BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0,
 			   "MACE PCI error", NULL));
 
-	ioport_resource.end = mace_pci_io_resource.end;
+	iomem_resource = mace_pci_mem_resource;
+	ioport_resource = mace_pci_io_resource;
+
 	register_pci_controller(&mace_pci_controller);
 
 	return 0;
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
index ae3cc4b..88fb191 100644
--- a/arch/mips/pci/pci-lasat.c
+++ b/arch/mips/pci/pci-lasat.c
@@ -7,12 +7,8 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
 #include <asm/bootinfo.h>
 
 extern struct pci_ops nile4_pci_ops;
@@ -20,14 +16,14 @@
 static struct resource lasat_pci_mem_resource = {
 	.name	= "LASAT PCI MEM",
 	.start	= 0x18000000,
-	.end	= 0x19FFFFFF,
+	.end	= 0x19ffffff,
 	.flags	= IORESOURCE_MEM,
 };
 
 static struct resource lasat_pci_io_resource = {
 	.name	= "LASAT PCI IO",
 	.start	= 0x1a000000,
-	.end	= 0x1bFFFFFF,
+	.end	= 0x1bffffff,
 	.flags	= IORESOURCE_IO,
 };
 
@@ -38,23 +34,25 @@
 
 static int __init lasat_pci_setup(void)
 {
- 	printk("PCI: starting\n");
+	printk("PCI: starting\n");
 
-        switch (mips_machtype) {
-            case MACH_LASAT_100:
+	switch (mips_machtype) {
+	case MACH_LASAT_100:
                 lasat_pci_controller.pci_ops = &gt64120_pci_ops;
                 break;
-            case MACH_LASAT_200:
+	case MACH_LASAT_200:
                 lasat_pci_controller.pci_ops = &nile4_pci_ops;
                 break;
-            default:
+	default:
                 panic("pcibios_init: mips_machtype incorrect");
         }
 
 	register_pci_controller(&lasat_pci_controller);
-        return 0;
+
+	return 0;
 }
-early_initcall(lasat_pci_setup);
+
+arch_initcall(lasat_pci_setup);
 
 #define LASATINT_ETH1   0
 #define LASATINT_ETH0   1
@@ -68,24 +66,22 @@
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-    switch (slot) {
-        case 1:
-            return LASATINT_PCIA;   /* Expansion Module 0 */
-        case 2:
-            return LASATINT_PCIB;   /* Expansion Module 1 */
-        case 3:
-            return LASATINT_PCIC;   /* Expansion Module 2 */
-        case 4:
-            return LASATINT_ETH1;   /* Ethernet 1 (LAN 2) */
-        case 5:
-            return LASATINT_ETH0;   /* Ethernet 0 (LAN 1) */
-        case 6:
-            return LASATINT_HDC;    /* IDE controller */
-        default:
-            return 0xff;            /* Illegal */
-    }
+	switch (slot) {
+	case 1:
+	case 2:
+	case 3:
+		return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4);
+	case 4:
+		return LASATINT_ETH1;   /* Ethernet 1 (LAN 2) */
+	case 5:
+		return LASATINT_ETH0;   /* Ethernet 0 (LAN 1) */
+	case 6:
+		return LASATINT_HDC;    /* IDE controller */
+	default:
+		return 0xff;            /* Illegal */
+	}
 
-    return -1;
+	return -1;
 }
 
 /* Do platform specific device initialization at pci_enable_device() time */
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index a8d499b..21402ff 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -127,15 +127,20 @@
 		if (!hose->iommu)
 			PCI_DMA_BUS_IS_PHYS = 1;
 
+		if (hose->get_busno && pci_probe_only)
+			next_busno = (*hose->get_busno)();
+
 		bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
 		hose->bus = bus;
 		hose->need_domain_info = need_domain_info;
-		next_busno = bus->subordinate + 1;
-		/* Don't allow 8-bit bus number overflow inside the hose -
-		   reserve some space for bridges. */
-		if (next_busno > 224) {
-			next_busno = 0;
-			need_domain_info = 1;
+		if (bus) {
+			next_busno = bus->subordinate + 1;
+			/* Don't allow 8-bit bus number overflow inside the hose -
+			   reserve some space for bridges. */
+			if (next_busno > 224) {
+				next_busno = 0;
+				need_domain_info = 1;
+			}
 		}
 		continue;
 
@@ -164,7 +169,7 @@
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
-	for(idx=0; idx<6; idx++) {
+	for (idx=0; idx < PCI_NUM_RESOURCES; idx++) {
 		/* Only set up the requested stuff */
 		if (!(mask & (1<<idx)))
 			continue;
diff --git a/arch/mips/philips/pnx8550/common/Kconfig b/arch/mips/philips/pnx8550/common/Kconfig
new file mode 100644
index 0000000..072572d
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/Kconfig
@@ -0,0 +1 @@
+# Place holder
diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
new file mode 100644
index 0000000..6e38f3b
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/Makefile
@@ -0,0 +1,27 @@
+#
+# Per Hallsmark, per.hallsmark@mvista.com
+#
+# ########################################################################
+#
+# This program is free software; you can distribute 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 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.
+#
+# #######################################################################
+#
+# Makefile for the PNX8550 specific kernel interface routines
+# under Linux.
+#
+
+obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/philips/pnx8550/common/gdb_hook.c b/arch/mips/philips/pnx8550/common/gdb_hook.c
new file mode 100644
index 0000000..ad4624f
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/gdb_hook.c
@@ -0,0 +1,109 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * ########################################################################
+ *
+ * This is the interface to the remote debugger stub.
+ *
+ */
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_ip3106.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+
+#include <uart.h>
+
+static struct serial_state rs_table[IP3106_NR_PORTS] = {
+};
+static struct async_struct kdb_port_info = {0};
+
+void rs_kgdb_hook(int tty_no)
+{
+	struct serial_state *ser = &rs_table[tty_no];
+
+	kdb_port_info.state = ser;
+	kdb_port_info.magic = SERIAL_MAGIC;
+	kdb_port_info.port  = tty_no;
+	kdb_port_info.flags = ser->flags;
+
+	/*
+	 * Clear all interrupts
+	 */
+	/* Clear all the transmitter FIFO counters (pointer and status) */
+	ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
+	/* Clear all the receiver FIFO counters (pointer and status) */
+	ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
+	/* Clear all interrupts */
+	ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
+		IP3106_UART_INT_ALLTX;
+
+	/*
+	 * Now, initialize the UART
+	 */
+	ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
+	ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
+}
+
+int putDebugChar(char c)
+{
+	/* Wait until FIFO not full */
+	while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
+		;
+	/* Send one char */
+	ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
+
+	return 1;
+}
+
+char getDebugChar(void)
+{
+	char ch;
+
+	/* Wait until there is a char in the FIFO */
+	while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
+					IP3106_UART_FIFO_RXFIFO) >> 8))
+		;
+	/* Read one char */
+	ch = ip3106_fifo(UART_BASE, kdb_port_info.port) &
+		IP3106_UART_FIFO_RBRTHR;
+	/* Advance the RX FIFO read pointer */
+	ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
+	return (ch);
+}
+
+void rs_disable_debug_interrupts(void)
+{
+	ip3106_ien(UART_BASE, kdb_port_info.port) = 0; /* Disable all interrupts */
+}
+
+void rs_enable_debug_interrupts(void)
+{
+	/* Clear all the transmitter FIFO counters (pointer and status) */
+	ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
+	/* Clear all the receiver FIFO counters (pointer and status) */
+	ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
+	/* Clear all interrupts */
+	ip3106_iclr(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX |
+		IP3106_UART_INT_ALLTX;
+	ip3106_ien(UART_BASE, kdb_port_info.port)  = IP3106_UART_INT_ALLRX; /* Enable RX interrupts */
+}
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
new file mode 100644
index 0000000..5461449
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -0,0 +1,293 @@
+/*
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ * Ported to 2.6.
+ *
+ * Per Hallsmark, per.hallsmark@mvista.com
+ * Copyright (C) 2000, 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ *
+ * Cleaned up and bug fixing: Pete Popov, ppopov@embeddedalley.com
+ *
+ *  This program is free software; you can distribute 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 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/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/gdb-stub.h>
+#include <int.h>
+#include <uart.h>
+
+extern asmlinkage void cp0_irqdispatch(void);
+
+static DEFINE_SPINLOCK(irq_lock);
+
+/* default prio for interrupts */
+/* first one is a no-no so therefore always prio 0 (disabled) */
+static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
+	0, 1, 1, 1, 1, 15, 1, 1, 1, 1,	//   0 -  9
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	//  10 - 19
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	//  20 - 29
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	//  30 - 39
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	//  40 - 49
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 1,	//  50 - 59
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	//  60 - 69
+	1			//  70
+};
+
+void hw0_irqdispatch(int irq, struct pt_regs *regs)
+{
+	/* find out which interrupt */
+	irq = PNX8550_GIC_VECTOR_0 >> 3;
+
+	if (irq == 0) {
+		printk("hw0_irqdispatch: irq 0, spurious interrupt?\n");
+		return;
+	}
+	do_IRQ(PNX8550_INT_GIC_MIN + irq, regs);
+}
+
+
+void timer_irqdispatch(int irq, struct pt_regs *regs)
+{
+	irq = (0x01c0 & read_c0_config7()) >> 6;
+
+	if (irq == 0) {
+		printk("timer_irqdispatch: irq 0, spurious interrupt?\n");
+		return;
+	}
+
+	if (irq & 0x1) {
+		do_IRQ(PNX8550_INT_TIMER1, regs);
+	}
+	if (irq & 0x2) {
+		do_IRQ(PNX8550_INT_TIMER2, regs);
+	}
+	if (irq & 0x4) {
+		do_IRQ(PNX8550_INT_TIMER3, regs);
+	}
+}
+
+static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+{
+	unsigned long status = read_c0_status();
+
+	status &= ~((clr_mask & 0xFF) << 8);
+	status |= (set_mask & 0xFF) << 8;
+
+	write_c0_status(status);
+}
+
+static inline void mask_gic_int(unsigned int irq_nr)
+{
+	/* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */
+	PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */
+}
+
+static inline void unmask_gic_int(unsigned int irq_nr)
+{
+	/* set prio mask to lower four bits and enable interrupt */
+	PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr];
+}
+
+static inline void mask_irq(unsigned int irq_nr)
+{
+	if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
+		modify_cp0_intmask(1 << irq_nr, 0);
+	} else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
+		(irq_nr <= PNX8550_INT_GIC_MAX)) {
+		mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
+	} else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
+		(irq_nr <= PNX8550_INT_TIMER_MAX)) {
+		modify_cp0_intmask(1 << 7, 0);
+	} else {
+		printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
+	}
+}
+
+static inline void unmask_irq(unsigned int irq_nr)
+{
+	if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
+		modify_cp0_intmask(0, 1 << irq_nr);
+	} else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
+		(irq_nr <= PNX8550_INT_GIC_MAX)) {
+		unmask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
+	} else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
+		(irq_nr <= PNX8550_INT_TIMER_MAX)) {
+		modify_cp0_intmask(0, 1 << 7);
+	} else {
+		printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
+	}
+}
+
+#define pnx8550_disable pnx8550_ack
+static void pnx8550_ack(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_lock, flags);
+	mask_irq(irq);
+	spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+#define pnx8550_enable pnx8550_unmask
+static void pnx8550_unmask(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_lock, flags);
+	unmask_irq(irq);
+	spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static unsigned int startup_irq(unsigned int irq_nr)
+{
+	pnx8550_unmask(irq_nr);
+	return 0;
+}
+
+static void shutdown_irq(unsigned int irq_nr)
+{
+	pnx8550_ack(irq_nr);
+	return;
+}
+
+int pnx8550_set_gic_priority(int irq, int priority)
+{
+	int gic_irq = irq-PNX8550_INT_GIC_MIN;
+	int prev_priority = PNX8550_GIC_REQ(gic_irq) & 0xf;
+
+        gic_prio[gic_irq] = priority;
+	PNX8550_GIC_REQ(gic_irq) |= (0x10000000 | gic_prio[gic_irq]);
+
+	return prev_priority;
+}
+
+static inline void mask_and_ack_level_irq(unsigned int irq)
+{
+	pnx8550_disable(irq);
+	return;
+}
+
+static void end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+		pnx8550_enable(irq);
+	}
+}
+
+static struct hw_interrupt_type level_irq_type = {
+	.typename =	"PNX Level IRQ",
+	.startup =	startup_irq,
+	.shutdown =	shutdown_irq,
+	.enable =	pnx8550_enable,
+	.disable =	pnx8550_disable,
+	.ack =		mask_and_ack_level_irq,
+	.end =		end_irq,
+};
+
+static struct irqaction gic_action = {
+	.handler =	no_action,
+	.flags =	SA_INTERRUPT,
+	.name =		"GIC",
+};
+
+static struct irqaction timer_action = {
+	.handler =	no_action,
+	.flags =	SA_INTERRUPT,
+	.name =		"Timer",
+};
+
+void __init arch_init_irq(void)
+{
+	int i;
+	int configPR;
+
+	/* init of cp0 interrupts */
+	set_except_vector(0, cp0_irqdispatch);
+
+	for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
+		irq_desc[i].handler = &level_irq_type;
+		pnx8550_ack(i);	/* mask the irq just in case  */
+	}
+
+	/* init of GIC/IPC interrupts */
+	/* should be done before cp0 since cp0 init enables the GIC int */
+	for (i = PNX8550_INT_GIC_MIN; i <= PNX8550_INT_GIC_MAX; i++) {
+		int gic_int_line = i - PNX8550_INT_GIC_MIN;
+		if (gic_int_line == 0 )
+			continue;	// don't fiddle with int 0
+		/*
+		 * enable change of TARGET, ENABLE and ACTIVE_LOW bits
+		 * set TARGET        0 to route through hw0 interrupt
+		 * set ACTIVE_LOW    0 active high  (correct?)
+		 *
+		 * We really should setup an interrupt description table
+		 * to do this nicely.
+		 * Note, PCI INTA is active low on the bus, but inverted
+		 * in the GIC, so to us it's active high.
+		 */
+#ifdef CONFIG_PNX8550_V2PCI
+		if (gic_int_line == (PNX8550_INT_GPIO0 - PNX8550_INT_GIC_MIN)) {
+			/* PCI INT through gpio 8, which is setup in
+			 * pnx8550_setup.c and routed to GPIO
+ 			 * Interrupt Level 0 (GPIO Connection 58).
+			 * Set it active low. */
+
+			PNX8550_GIC_REQ(gic_int_line) = 0x1E020000;
+		} else
+#endif
+		{
+			PNX8550_GIC_REQ(i - PNX8550_INT_GIC_MIN) = 0x1E000000;
+		}
+
+		/* mask/priority is still 0 so we will not get any
+		 * interrupts until it is unmasked */
+
+		irq_desc[i].handler = &level_irq_type;
+	}
+
+	/* Priority level 0 */
+	PNX8550_GIC_PRIMASK_0 = PNX8550_GIC_PRIMASK_1 = 0;
+
+	/* Set int vector table address */
+	PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0;
+
+	irq_desc[MIPS_CPU_GIC_IRQ].handler = &level_irq_type;
+	setup_irq(MIPS_CPU_GIC_IRQ, &gic_action);
+
+	/* init of Timer interrupts */
+	for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++) {
+		irq_desc[i].handler = &level_irq_type;
+	}
+
+	/* Stop Timer 1-3 */
+	configPR = read_c0_config7();
+	configPR |= 0x00000038;
+	write_c0_config7(configPR);
+
+	irq_desc[MIPS_CPU_TIMER_IRQ].handler = &level_irq_type;
+	setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action);
+}
+
+EXPORT_SYMBOL(pnx8550_set_gic_priority);
diff --git a/arch/mips/philips/pnx8550/common/mipsIRQ.S b/arch/mips/philips/pnx8550/common/mipsIRQ.S
new file mode 100644
index 0000000..338bffd
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/mipsIRQ.S
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2002 Philips, Inc. All rights.
+ * Copyright (c) 2002 Red Hat, Inc. All rights.
+ *
+ * This software may be freely redistributed under the terms of the
+ * GNU General Public License.
+ *
+ * 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.
+ *
+ * Based upon arch/mips/galileo-boards/ev64240/int-handler.S
+ *
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * cp0_irqdispatch
+ *
+ *    Code to handle in-core interrupt exception.
+ */
+
+		.align	5
+		.set	reorder
+		.set	noat
+		NESTED(cp0_irqdispatch, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+		mfc0	t0,CP0_CAUSE
+		mfc0	t2,CP0_STATUS
+
+		and	t0,t2
+
+		andi	t1,t0,STATUSF_IP2 /* int0 hardware line */
+		bnez	t1,ll_hw0_irq
+		nop
+
+		andi	t1,t0,STATUSF_IP7 /* int5 hardware line */
+		bnez	t1,ll_timer_irq
+		nop
+
+		/* wrong alarm or masked ... */
+
+		j	spurious_interrupt
+		nop
+		END(cp0_irqdispatch)
+
+		.align	5
+		.set	reorder
+ll_hw0_irq:
+		li	a0,2
+		move	a1,sp
+		jal	hw0_irqdispatch
+		nop
+		j	ret_from_irq
+		nop
+
+		.align	5
+		.set	reorder
+ll_timer_irq:
+		mfc0	t3,CP0_CONFIG,7
+		andi	t4,t3,0x01c0
+		beqz	t4,ll_timer_out
+		nop
+		li	a0,7
+		move	a1,sp
+		jal	timer_irqdispatch
+		nop
+
+ll_timer_out:	j	ret_from_irq
+		nop
diff --git a/arch/mips/philips/pnx8550/common/pci.c b/arch/mips/philips/pnx8550/common/pci.c
new file mode 100644
index 0000000..baa6905
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/pci.c
@@ -0,0 +1,133 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <pci.h>
+#include <glb.h>
+#include <nand.h>
+
+static struct resource pci_io_resource = {
+	"pci IO space",
+	(u32)(PNX8550_PCIIO + 0x1000),	/* reserve regacy I/O space */
+	(u32)(PNX8550_PCIIO + PNX8550_PCIIO_SIZE),
+	IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+	"pci memory space",
+	(u32)(PNX8550_PCIMEM),
+	(u32)(PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1),
+	IORESOURCE_MEM
+};
+
+extern struct pci_ops pnx8550_pci_ops;
+
+static struct pci_controller pnx8550_controller = {
+	.pci_ops	= &pnx8550_pci_ops,
+	.io_resource	= &pci_io_resource,
+	.mem_resource	= &pci_mem_resource,
+};
+
+/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
+static inline unsigned long get_system_mem_size(void)
+{
+	/* Read IP2031_RANK0_ADDR_LO */
+	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
+	/* Read IP2031_RANK1_ADDR_HI */
+	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
+
+	return dram_r1_hi - dram_r0_lo + 1;
+}
+
+static int __init pnx8550_pci_setup(void)
+{
+	int pci_mem_code;
+	int mem_size = get_system_mem_size() >> 20;
+
+	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
+	   Bit 1:Enable DAC Powerdown
+	  -> 0:DACs are enabled and are working normally
+	     1:DACs are powerdown
+	   Bit 0:Enable of PCI inta output
+	  -> 0 = Disable PCI inta output
+	     1 = Enable PCI inta output
+	*/
+	PNX8550_GLB2_ENAB_INTA_O = 0;
+
+	/* Calc the PCI mem size code */
+	if (mem_size >= 128)
+		pci_mem_code = SIZE_128M;
+	else if (mem_size >= 64)
+		pci_mem_code = SIZE_64M;
+	else if (mem_size >= 32)
+		pci_mem_code = SIZE_32M;
+	else
+		pci_mem_code = SIZE_16M;
+
+	/* Set PCI_XIO registers */
+	outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
+	outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
+	outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
+	outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
+
+	/* Send memory transaction via PCI_BASE2 */
+	outl(0x00000001, PCI_BASE | PCI_IO);
+
+	/* Unlock the setup register */
+	outl(0xca, PCI_BASE | PCI_UNLOCKREG);
+
+	/*
+	 * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
+	 * to work, and in order for bus_to_baddr to work without any
+	 * hacks.
+	 */
+	outl(0x00000000, PCI_BASE | PCI_BASE10);
+
+	/*
+	 *These two bars are set by default or the boot code.
+	 * However, it's safer to set them here so we're not boot
+	 * code dependent.
+	 */
+	outl(0x1be00000, PCI_BASE | PCI_BASE14);  /* PNX MMIO */
+	outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18);  /* XIO      */
+
+	outl(PCI_EN_TA |
+	     PCI_EN_PCI2MMI |
+	     PCI_EN_XIO |
+	     PCI_SETUP_BASE18_SIZE(SIZE_32M) |
+	     PCI_SETUP_BASE18_EN |
+	     PCI_SETUP_BASE14_EN |
+	     PCI_SETUP_BASE10_PREF |
+	     PCI_SETUP_BASE10_SIZE(pci_mem_code) |
+	     PCI_SETUP_CFGMANAGE_EN |
+	     PCI_SETUP_PCIARB_EN,
+	     PCI_BASE |
+	     PCI_SETUP);	/* PCI_SETUP */
+	outl(0x00000000, PCI_BASE | PCI_CTRL);	/* PCI_CONTROL */
+
+	register_pci_controller(&pnx8550_controller);
+
+	return 0;
+}
+
+arch_initcall(pnx8550_pci_setup);
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
new file mode 100644
index 0000000..8aa9bd6
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -0,0 +1,135 @@
+/*
+ * Platform device support for Philips PNX8550 SoCs
+ *
+ * Copyright 2005, Embedded Alley Solutions, Inc
+ *
+ * Based on arch/mips/au1000/common/platform.c
+ * Platform device support for Au1x00 SoCs.
+ *
+ * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+#include <linux/serial.h>
+#include <linux/serial_ip3106.h>
+
+#include <int.h>
+#include <usb.h>
+#include <uart.h>
+
+extern struct uart_ops ip3106_pops;
+
+static struct resource pnx8550_usb_ohci_resources[] = {
+	[0] = {
+		.start		= PNX8550_USB_OHCI_OP_BASE,
+		.end		= PNX8550_USB_OHCI_OP_BASE +
+				  PNX8550_USB_OHCI_OP_LEN,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= PNX8550_INT_USB,
+		.end		= PNX8550_INT_USB,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource pnx8550_uart_resources[] = {
+	[0] = {
+		.start		= PNX8550_UART_PORT0,
+		.end		= PNX8550_UART_PORT0 + 0xfff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= PNX8550_UART_INT(0),
+		.end		= PNX8550_UART_INT(0),
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= PNX8550_UART_PORT1,
+		.end		= PNX8550_UART_PORT1 + 0xfff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[3] = {
+		.start		= PNX8550_UART_INT(1),
+		.end		= PNX8550_UART_INT(1),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+struct ip3106_port ip3106_ports[] = {
+	[0] = {
+		.port   = {
+			.type		= PORT_IP3106,
+			.iotype		= SERIAL_IO_MEM,
+			.membase	= (void __iomem *)PNX8550_UART_PORT0,
+			.mapbase	= PNX8550_UART_PORT0,
+			.irq		= PNX8550_UART_INT(0),
+			.uartclk	= 3692300,
+			.fifosize	= 16,
+			.ops		= &ip3106_pops,
+			.flags		= ASYNC_BOOT_AUTOCONF,
+			.line		= 0,
+		},
+	},
+	[1] = {
+		.port   = {
+			.type		= PORT_IP3106,
+			.iotype		= SERIAL_IO_MEM,
+			.membase	= (void __iomem *)PNX8550_UART_PORT1,
+			.mapbase	= PNX8550_UART_PORT1,
+			.irq		= PNX8550_UART_INT(1),
+			.uartclk	= 3692300,
+			.fifosize	= 16,
+			.ops		= &ip3106_pops,
+			.flags		= ASYNC_BOOT_AUTOCONF,
+			.line		= 1,
+		},
+	},
+};
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+static u64 uart_dmamask = ~(u32)0;
+
+static struct platform_device pnx8550_usb_ohci_device = {
+	.name		= "pnx8550-ohci",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &ohci_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(pnx8550_usb_ohci_resources),
+	.resource	= pnx8550_usb_ohci_resources,
+};
+
+static struct platform_device pnx8550_uart_device = {
+	.name		= "ip3106-uart",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &uart_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data = ip3106_ports,
+	},
+	.num_resources	= ARRAY_SIZE(pnx8550_uart_resources),
+	.resource	= pnx8550_uart_resources,
+};
+
+static struct platform_device *pnx8550_platform_devices[] __initdata = {
+	&pnx8550_usb_ohci_device,
+	&pnx8550_uart_device,
+};
+
+int pnx8550_platform_init(void)
+{
+	return platform_add_devices(pnx8550_platform_devices,
+			            ARRAY_SIZE(pnx8550_platform_devices));
+}
+
+arch_initcall(pnx8550_platform_init);
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
new file mode 100644
index 0000000..72a0167
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -0,0 +1,113 @@
+/*
+ *  This program is free software; you can distribute 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 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/init.h>
+#include <linux/proc_fs.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+
+#include <asm/io.h>
+#include <asm/gdb-stub.h>
+#include <int.h>
+#include <uart.h>
+
+
+static int pnx8550_timers_read (char* page, char** start, off_t offset, int count, int* eof, void* data)
+{
+        int len = 0;
+	int configPR = read_c0_config7();
+
+        if (offset==0) {
+		len += sprintf(&page[len],"Timer:       count,  compare, tc, status\n");
+                len += sprintf(&page[len],"    1: %11i, %8i,  %1i, %s\n",
+			       read_c0_count(), read_c0_compare(),
+			      (configPR>>6)&0x1, ((configPR>>3)&0x1)? "off":"on");
+                len += sprintf(&page[len],"    2: %11i, %8i,  %1i, %s\n",
+			       read_c0_count2(), read_c0_compare2(),
+			      (configPR>>7)&0x1, ((configPR>>4)&0x1)? "off":"on");
+                len += sprintf(&page[len],"    3: %11i, %8i,  %1i, %s\n",
+			       read_c0_count3(), read_c0_compare3(),
+			      (configPR>>8)&0x1, ((configPR>>5)&0x1)? "off":"on");
+        }
+
+        return len;
+}
+
+static int pnx8550_registers_read (char* page, char** start, off_t offset, int count, int* eof, void* data)
+{
+        int len = 0;
+
+        if (offset==0) {
+                len += sprintf(&page[len],"config1:   %#10.8x\n",read_c0_config1());
+                len += sprintf(&page[len],"config2:   %#10.8x\n",read_c0_config2());
+                len += sprintf(&page[len],"config3:   %#10.8x\n",read_c0_config3());
+                len += sprintf(&page[len],"configPR:  %#10.8x\n",read_c0_config7());
+                len += sprintf(&page[len],"status:    %#10.8x\n",read_c0_status());
+                len += sprintf(&page[len],"cause:     %#10.8x\n",read_c0_cause());
+                len += sprintf(&page[len],"count:     %#10.8x\n",read_c0_count());
+                len += sprintf(&page[len],"count_2:   %#10.8x\n",read_c0_count2());
+                len += sprintf(&page[len],"count_3:   %#10.8x\n",read_c0_count3());
+                len += sprintf(&page[len],"compare:   %#10.8x\n",read_c0_compare());
+                len += sprintf(&page[len],"compare_2: %#10.8x\n",read_c0_compare2());
+                len += sprintf(&page[len],"compare_3: %#10.8x\n",read_c0_compare3());
+        }
+
+        return len;
+}
+
+static struct proc_dir_entry* pnx8550_dir        = NULL;
+static struct proc_dir_entry* pnx8550_timers     = NULL;
+static struct proc_dir_entry* pnx8550_registers  = NULL;
+
+static int pnx8550_proc_init( void )
+{
+
+	// Create /proc/pnx8550
+        pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
+        if (pnx8550_dir){
+                pnx8550_dir->nlink = 1;
+        }
+        else {
+                printk(KERN_ERR "Can't create pnx8550 proc dir\n");
+                return -1;
+        }
+
+	// Create /proc/pnx8550/timers
+        pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
+        if (pnx8550_timers){
+                pnx8550_timers->nlink = 1;
+                pnx8550_timers->read_proc = pnx8550_timers_read;
+        }
+        else {
+                printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
+        }
+
+	// Create /proc/pnx8550/registers
+        pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
+        if (pnx8550_registers){
+                pnx8550_registers->nlink = 1;
+                pnx8550_registers->read_proc = pnx8550_registers_read;
+        }
+        else {
+                printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
+        }
+
+	return 0;
+}
+
+__initcall(pnx8550_proc_init);
diff --git a/arch/mips/philips/pnx8550/common/prom.c b/arch/mips/philips/pnx8550/common/prom.c
new file mode 100644
index 0000000..70aac97
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/prom.c
@@ -0,0 +1,138 @@
+/*
+ *
+ * Per Hallsmark, per.hallsmark@mvista.com
+ *
+ * Based on jmr3927/common/prom.c
+ *
+ * 2004 (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.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/serial_ip3106.h>
+
+#include <asm/bootinfo.h>
+#include <uart.h>
+
+/* #define DEBUG_CMDLINE */
+
+extern int prom_argc;
+extern char **prom_argv, **prom_envp;
+
+typedef struct
+{
+    char *name;
+/*    char *val; */
+}t_env_var;
+
+
+char * prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+void  prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+	        strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+}
+
+char *prom_getenv(char *envname)
+{
+	/*
+	 * Return a pointer to the given environment variable.
+	 * Environment variables are stored in the form of "memsize=64".
+	 */
+
+	t_env_var *env = (t_env_var *)prom_envp;
+	int i;
+
+	i = strlen(envname);
+
+	while(env->name) {
+		if(strncmp(envname, env->name, i) == 0) {
+			return(env->name + strlen(envname) + 1);
+		}
+		env++;
+	}
+	return(NULL);
+}
+
+inline unsigned char str2hexnum(unsigned char c)
+{
+	if(c >= '0' && c <= '9')
+		return c - '0';
+	if(c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if(c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	return 0; /* foo */
+}
+
+inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+	int i;
+
+	for(i = 0; i < 6; i++) {
+		unsigned char num;
+
+		if((*str == '.') || (*str == ':'))
+			str++;
+		num = str2hexnum(*str++) << 4;
+		num |= (str2hexnum(*str++));
+		ea[i] = num;
+	}
+}
+
+int get_ethernet_addr(char *ethernet_addr)
+{
+        char *ethaddr_str;
+
+        ethaddr_str = prom_getenv("ethaddr");
+	if (!ethaddr_str) {
+	        printk("ethaddr not set in boot prom\n");
+		return -1;
+	}
+	str2eaddr(ethernet_addr, ethaddr_str);
+	return 0;
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+	return 0;
+}
+
+extern int pnx8550_console_port;
+
+/* used by prom_printf */
+void prom_putchar(char c)
+{
+	if (pnx8550_console_port != -1) {
+		/* Wait until FIFO not full */
+		while( ((ip3106_fifo(UART_BASE, pnx8550_console_port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
+			;
+		/* Send one char */
+		ip3106_fifo(UART_BASE, pnx8550_console_port) = c;
+	}
+}
+
+EXPORT_SYMBOL(prom_getcmdline);
+EXPORT_SYMBOL(get_ethernet_addr);
+EXPORT_SYMBOL(str2eaddr);
diff --git a/arch/mips/philips/pnx8550/common/reset.c b/arch/mips/philips/pnx8550/common/reset.c
new file mode 100644
index 0000000..7b2cbc5
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/reset.c
@@ -0,0 +1,49 @@
+/*.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * ########################################################################
+ *
+ * Reset the PNX8550 board.
+ *
+ */
+#include <linux/slab.h>
+#include <asm/reboot.h>
+#include <glb.h>
+
+void pnx8550_machine_restart(char *command)
+{
+	char head[] = "************* Machine restart *************";
+	char foot[] = "*******************************************";
+
+	printk("\n\n");
+	printk("%s\n", head);
+	if (command != NULL)
+		printk("* %s\n", command);
+	printk("%s\n", foot);
+
+	PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST;
+}
+
+void pnx8550_machine_halt(void)
+{
+	printk("*** Machine halt. (Not implemented) ***\n");
+}
+
+void pnx8550_machine_power_off(void)
+{
+	printk("*** Machine power off.  (Not implemented) ***\n");
+}
diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c
new file mode 100644
index 0000000..ee6bf72
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/setup.c
@@ -0,0 +1,149 @@
+/*
+ *
+ * 2.6 port, Embedded Alley Solutions, Inc
+ *
+ *  Based on Per Hallsmark, per.hallsmark@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/serial_ip3106.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/time.h>
+
+#include <glb.h>
+#include <int.h>
+#include <pci.h>
+#include <uart.h>
+#include <nand.h>
+
+extern void prom_printf(char *fmt, ...);
+
+extern void __init board_setup(void);
+extern void pnx8550_machine_restart(char *);
+extern void pnx8550_machine_halt(void);
+extern void pnx8550_machine_power_off(void);
+extern struct resource ioport_resource;
+extern struct resource iomem_resource;
+extern void (*board_time_init)(void);
+extern void pnx8550_time_init(void);
+extern void (*board_timer_setup)(struct irqaction *irq);
+extern void pnx8550_timer_setup(struct irqaction *irq);
+extern void rs_kgdb_hook(int tty_no);
+extern void prom_printf(char *fmt, ...);
+extern char *prom_getcmdline(void);
+
+struct resource standard_io_resources[] = {
+	{"dma1", 0x00, 0x1f, IORESOURCE_BUSY},
+	{"timer", 0x40, 0x5f, IORESOURCE_BUSY},
+	{"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY},
+	{"dma2", 0xc0, 0xdf, IORESOURCE_BUSY},
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+extern struct resource pci_io_resource;
+extern struct resource pci_mem_resource;
+
+/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
+unsigned long get_system_mem_size(void)
+{
+	/* Read IP2031_RANK0_ADDR_LO */
+	unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
+	/* Read IP2031_RANK1_ADDR_HI */
+	unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
+
+	return dram_r1_hi - dram_r0_lo + 1;
+}
+
+int pnx8550_console_port = -1;
+
+void __init plat_setup(void)
+{
+	int i;
+	char* argptr;
+
+	board_setup();  /* board specific setup */
+
+        _machine_restart = pnx8550_machine_restart;
+        _machine_halt = pnx8550_machine_halt;
+        _machine_power_off = pnx8550_machine_power_off;
+
+	board_time_init = pnx8550_time_init;
+	board_timer_setup = pnx8550_timer_setup;
+
+	/* Clear the Global 2 Register, PCI Inta Output Enable Registers
+	   Bit 1:Enable DAC Powerdown
+	  -> 0:DACs are enabled and are working normally
+	     1:DACs are powerdown
+	   Bit 0:Enable of PCI inta output
+	  -> 0 = Disable PCI inta output
+	     1 = Enable PCI inta output
+	*/
+	PNX8550_GLB2_ENAB_INTA_O = 0;
+
+	/* IO/MEM resources. */
+	set_io_port_base(KSEG1);
+	ioport_resource.start = 0;
+	ioport_resource.end = ~0;
+	iomem_resource.start = 0;
+	iomem_resource.end = ~0;
+
+	/* Request I/O space for devices on this board */
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, standard_io_resources + i);
+
+	/* Place the Mode Control bit for GPIO pin 16 in primary function */
+	/* Pin 16 is used by UART1, UA1_TX                                */
+	outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
+			(PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
+			PNX8550_GPIO_MC1);
+
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
+		argptr += strlen("console=ttyS");
+		pnx8550_console_port = *argptr == '0' ? 0 : 1;
+
+		/* We must initialize the UART (console) before prom_printf */
+		/* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
+		ip3106_lcr(UART_BASE, pnx8550_console_port) =
+			IP3106_UART_LCR_8BIT;
+		ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
+	}
+
+#ifdef CONFIG_KGDB
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+		int line;
+		argptr += strlen("kgdb=ttyS");
+		line = *argptr == '0' ? 0 : 1;
+		rs_kgdb_hook(line);
+		prom_printf("KGDB: Using ttyS%i for session, "
+				"please connect your debugger\n", line ? 1 : 0);
+	}
+#endif
+	return;
+}
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
new file mode 100644
index 0000000..70664ea
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/time.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2001, 2002, 2003 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Common time service routines for MIPS machines. See
+ * Documents/MIPS/README.txt.
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/hardirq.h>
+#include <asm/div64.h>
+#include <asm/debug.h>
+
+#include <int.h>
+#include <cm.h>
+
+extern unsigned int mips_hpt_frequency;
+
+/*
+ * pnx8550_time_init() - it does the following things:
+ *
+ * 1) board_time_init() -
+ * 	a) (optional) set up RTC routines,
+ *      b) (optional) calibrate and set the mips_hpt_frequency
+ *	    (only needed if you intended to use fixed_rate_gettimeoffset
+ *	     or use cpu counter as timer interrupt source)
+ */
+
+void pnx8550_time_init(void)
+{
+	unsigned int             n;
+	unsigned int             m;
+	unsigned int             p;
+	unsigned int             pow2p;
+
+        /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */
+        /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1:  FIXME) */
+
+        n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16;
+        m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8;
+        p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2;
+	pow2p = (1 << p);
+
+	db_assert(m != 0 && pow2p != 0);
+
+        /*
+	 * Compute the frequency as in the PNX8550 User Manual 1.0, p.186
+	 * (a.k.a. 8-10).  Divide by HZ for a timer offset that results in
+	 * HZ timer interrupts per second.
+	 */
+	mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
+}
+
+/*
+ * pnx8550_timer_setup() - it does the following things:
+ *
+ * 5) board_timer_setup() -
+ *	a) (optional) over-write any choices made above by time_init().
+ *	b) machine specific code should setup the timer irqaction.
+ *	c) enable the timer interrupt
+ */
+
+void __init pnx8550_timer_setup(struct irqaction *irq)
+{
+	int configPR;
+
+	setup_irq(PNX8550_INT_TIMER1, irq);
+
+	/* Start timer1 */
+	configPR = read_c0_config7();
+	configPR &= ~0x00000008;
+	write_c0_config7(configPR);
+
+	/* Timer 2 stop */
+	configPR = read_c0_config7();
+	configPR |= 0x00000010;
+	write_c0_config7(configPR);
+
+	write_c0_count2(0);
+	write_c0_compare2(0xffffffff);
+
+	/* Timer 3 stop */
+	configPR = read_c0_config7();
+	configPR |= 0x00000020;
+	write_c0_config7(configPR);
+}
diff --git a/arch/mips/philips/pnx8550/jbs/Makefile b/arch/mips/philips/pnx8550/jbs/Makefile
new file mode 100644
index 0000000..e8228db
--- /dev/null
+++ b/arch/mips/philips/pnx8550/jbs/Makefile
@@ -0,0 +1,4 @@
+
+# Makefile for the Philips JBS Board.
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/philips/pnx8550/jbs/board_setup.c b/arch/mips/philips/pnx8550/jbs/board_setup.c
new file mode 100644
index 0000000..f92826e
--- /dev/null
+++ b/arch/mips/philips/pnx8550/jbs/board_setup.c
@@ -0,0 +1,65 @@
+/*
+ *  JBS Specific board startup routines.
+ *
+ *  Copyright 2005, Embedded Alley Solutions, 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.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+
+#include <glb.h>
+
+/* CP0 hazard avoidance. */
+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+				     "nop; nop; nop; nop; nop; nop;\n\t" \
+				     ".set reorder\n\t")
+
+void __init board_setup(void)
+{
+	unsigned long config0, configpr;
+
+	config0 = read_c0_config();
+
+	/* clear all three cache coherency fields */
+	config0 &= ~(0x7 | (7<<25) | (7<<28));
+	config0 |= (CONF_CM_DEFAULT | (CONF_CM_DEFAULT<<25) |
+			(CONF_CM_DEFAULT<<28));
+	write_c0_config(config0);
+	BARRIER;
+
+	configpr = read_c0_config7();
+	configpr |= (1<<19); /* enable tlb */
+	write_c0_config7(configpr);
+	BARRIER;
+}
diff --git a/arch/mips/philips/pnx8550/jbs/init.c b/arch/mips/philips/pnx8550/jbs/init.c
new file mode 100644
index 0000000..85f4491
--- /dev/null
+++ b/arch/mips/philips/pnx8550/jbs/init.c
@@ -0,0 +1,57 @@
+/*
+ *
+ *  Copyright 2005 Embedded Alley Solutions, Inc
+ *  source@embeddedalley.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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void  __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+	return "Philips PNX8550/JBS";
+}
+
+void __init prom_init(void)
+{
+
+	unsigned long memsize;
+
+	mips_machgroup = MACH_GROUP_PHILIPS;
+	mips_machtype = MACH_PHILIPS_JBS;
+
+	//memsize = 0x02800000; /* Trimedia uses memory above */
+	memsize = 0x08000000; /* Trimedia uses memory above */
+	add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/philips/pnx8550/jbs/irqmap.c b/arch/mips/philips/pnx8550/jbs/irqmap.c
new file mode 100644
index 0000000..f78e042
--- /dev/null
+++ b/arch/mips/philips/pnx8550/jbs/irqmap.c
@@ -0,0 +1,36 @@
+/*
+ *  Philips JBS board irqmap.
+ *
+ *  Copyright 2005 Embedded Alley Solutions, Inc
+ *  source@embeddealley.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  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
+ *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
+ *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+
+#include <linux/init.h>
+#include <int.h>
+
+char irq_tab_jbs[][5] __initdata = {
+ [8] =	{ -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+ [9] =	{ -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+ [17] =	{ -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
+};
+
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
new file mode 100644
index 0000000..24d514c
--- /dev/null
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -0,0 +1,3 @@
+config HYPERTRANSPORT
+	bool "Hypertransport Support for PMC-Sierra Yosemite"
+	depends on PMC_YOSEMITE
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
index c19f01a..a312883 100644
--- a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
@@ -34,7 +34,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <asm/pci.h>
 #include <asm/io.h>
 #include <linux/init.h>
diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c
index d22c9ff..5aec405 100644
--- a/arch/mips/pmc-sierra/yosemite/ht-irq.c
+++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <asm/pci.h>
 
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
index dad228d..54b65a8 100644
--- a/arch/mips/pmc-sierra/yosemite/ht.c
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -28,7 +28,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include <asm/pci.h>
 #include <asm/io.h>
 
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
index 1fb3e69..555bfacf 100644
--- a/arch/mips/pmc-sierra/yosemite/prom.c
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -132,8 +132,9 @@
 	prom_grab_secondary();
 }
 
-void __init prom_free_prom_memory(void)
+unsigned long __init prom_free_prom_memory(void)
 {
+	return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 7225bbf..bdc2ab5 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -212,7 +212,7 @@
 	py_rtc_setup();
 }
 
-static int __init pmc_yosemite_setup(void)
+void __init plat_setup(void)
 {
 	board_time_init = yosemite_time_init;
 	late_time_init = py_late_time_init;
@@ -228,8 +228,4 @@
 	OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
 	OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
 #endif
-
-	return 0;
 }
-
-early_initcall(pmc_yosemite_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 1d3b073..0527170 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -9,7 +9,7 @@
 
 #define LAUNCHSTACK_SIZE 256
 
-static spinlock_t launch_lock __initdata;
+static __initdata DEFINE_SPINLOCK(launch_lock);
 
 static unsigned long secondary_sp __initdata;
 static unsigned long secondary_gp __initdata;
diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c
index 1a80eee..022eb1a 100644
--- a/arch/mips/qemu/q-setup.c
+++ b/arch/mips/qemu/q-setup.c
@@ -4,6 +4,11 @@
 
 #define QEMU_PORT_BASE 0xb4000000
 
+const char *get_system_type(void)
+{
+	return "Qemu";
+}
+
 static void __init qemu_timer_setup(struct irqaction *irq)
 {
 	/* set the clock to 100 Hz */
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index fa0e719..b198201 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -29,6 +29,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
@@ -37,42 +38,29 @@
 #include <asm/sgi/mc.h>
 #include <asm/sgi/ip22.h>
 
-#define EISA_MAX_SLOTS		  4
+/* I2 has four EISA slots. */
+#define IP22_EISA_MAX_SLOTS	  4
 #define EISA_MAX_IRQ             16
 
-#define EISA_TO_PHYS(x)  (0x00080000 | (x))
-#define EISA_TO_KSEG1(x) ((void *) KSEG1ADDR(EISA_TO_PHYS((x))))
+#define EIU_MODE_REG     0x0001ffc0
+#define EIU_STAT_REG     0x0001ffc4
+#define EIU_PREMPT_REG   0x0001ffc8
+#define EIU_QUIET_REG    0x0001ffcc
+#define EIU_INTRPT_ACK   0x00010004
 
-#define EIU_MODE_REG     0x0009ffc0
-#define EIU_STAT_REG     0x0009ffc4
-#define EIU_PREMPT_REG   0x0009ffc8
-#define EIU_QUIET_REG    0x0009ffcc
-#define EIU_INTRPT_ACK   0x00090004
-
-#define EISA_DMA1_STATUS            8
-#define EISA_INT1_CTRL           0x20
-#define EISA_INT1_MASK           0x21
-#define EISA_INT2_CTRL           0xA0
-#define EISA_INT2_MASK           0xA1
-#define EISA_DMA2_STATUS         0xD0
-#define EISA_DMA2_WRITE_SINGLE   0xD4
-#define EISA_EXT_NMI_RESET_CTRL 0x461
-#define EISA_INT1_EDGE_LEVEL    0x4D0
-#define EISA_INT2_EDGE_LEVEL    0x4D1
-#define EISA_VENDOR_ID_OFFSET   0xC80
-
-#define EIU_WRITE_32(x,y) { *((u32 *) KSEG1ADDR(x)) = (u32) (y); mb(); }
-#define EIU_READ_8(x) *((u8 *) KSEG1ADDR(x))
-#define EISA_WRITE_8(x,y) { *((u8 *) EISA_TO_KSEG1(x)) = (u8) (y); mb(); }
-#define EISA_READ_8(x) *((u8 *) EISA_TO_KSEG1(x))
-
-static char *decode_eisa_sig(u8 * sig)
+static char __init *decode_eisa_sig(unsigned long addr)
 {
-	static char sig_str[8];
-	u16 rev;
+        static char sig_str[EISA_SIG_LEN];
+	u8 sig[4];
+        u16 rev;
+	int i;
 
-	if (sig[0] & 0x80)
-		return NULL;
+	for (i = 0; i < 4; i++) {
+		sig[i] = inb (addr + i);
+
+		if (!i && (sig[0] & 0x80))
+			return NULL;
+	}
 
 	sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);
 	sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);
@@ -83,23 +71,26 @@
 	return sig_str;
 }
 
-static void ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	u8 eisa_irq;
 	u8 dma1, dma2;
 
-	eisa_irq = EIU_READ_8(EIU_INTRPT_ACK);
-	dma1 = EISA_READ_8(EISA_DMA1_STATUS);
-	dma2 = EISA_READ_8(EISA_DMA2_STATUS);
+	eisa_irq = inb(EIU_INTRPT_ACK);
+	dma1 = inb(EISA_DMA1_STATUS);
+	dma2 = inb(EISA_DMA2_STATUS);
 
-	if (eisa_irq >= EISA_MAX_IRQ) {
-		/* Oops, Bad Stuff Happened... */
-		printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq);
-
-		EISA_WRITE_8(EISA_INT2_CTRL, 0x20);
-		EISA_WRITE_8(EISA_INT1_CTRL, 0x20);
-	} else
+	if (eisa_irq < EISA_MAX_IRQ) {
 		do_IRQ(eisa_irq, regs);
+		return IRQ_HANDLED;
+	}
+
+	/* Oops, Bad Stuff Happened... */
+	printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq);
+
+	outb(0x20, EISA_INT2_CTRL);
+	outb(0x20, EISA_INT1_CTRL);
+	return IRQ_NONE;
 }
 
 static void enable_eisa1_irq(unsigned int irq)
@@ -109,9 +100,9 @@
 
 	local_irq_save(flags);
 
-	mask = EISA_READ_8(EISA_INT1_MASK);
+	mask = inb(EISA_INT1_MASK);
 	mask &= ~((u8) (1 << irq));
-	EISA_WRITE_8(EISA_INT1_MASK, mask);
+	outb(mask, EISA_INT1_MASK);
 
 	local_irq_restore(flags);
 }
@@ -122,9 +113,9 @@
 
 	/* Only use edge interrupts for EISA */
 
-	edge = EISA_READ_8(EISA_INT1_EDGE_LEVEL);
+	edge = inb(EISA_INT1_EDGE_LEVEL);
 	edge &= ~((u8) (1 << irq));
-	EISA_WRITE_8(EISA_INT1_EDGE_LEVEL, edge);
+	outb(edge, EISA_INT1_EDGE_LEVEL);
 
 	enable_eisa1_irq(irq);
 	return 0;
@@ -134,9 +125,9 @@
 {
 	u8 mask;
 
-	mask = EISA_READ_8(EISA_INT1_MASK);
+	mask = inb(EISA_INT1_MASK);
 	mask |= ((u8) (1 << irq));
-	EISA_WRITE_8(EISA_INT1_MASK, mask);
+	outb(mask, EISA_INT1_MASK);
 }
 
 #define shutdown_eisa1_irq	disable_eisa1_irq
@@ -145,7 +136,7 @@
 {
 	disable_eisa1_irq(irq);
 
-	EISA_WRITE_8(EISA_INT1_CTRL, 0x20);
+	outb(0x20, EISA_INT1_CTRL);
 }
 
 static void end_eisa1_irq(unsigned int irq)
@@ -171,9 +162,9 @@
 
 	local_irq_save(flags);
 
-	mask = EISA_READ_8(EISA_INT2_MASK);
+	mask = inb(EISA_INT2_MASK);
 	mask &= ~((u8) (1 << (irq - 8)));
-	EISA_WRITE_8(EISA_INT2_MASK, mask);
+	outb(mask, EISA_INT2_MASK);
 
 	local_irq_restore(flags);
 }
@@ -184,9 +175,9 @@
 
 	/* Only use edge interrupts for EISA */
 
-	edge = EISA_READ_8(EISA_INT2_EDGE_LEVEL);
+	edge = inb(EISA_INT2_EDGE_LEVEL);
 	edge &= ~((u8) (1 << (irq - 8)));
-	EISA_WRITE_8(EISA_INT2_EDGE_LEVEL, edge);
+	outb(edge, EISA_INT2_EDGE_LEVEL);
 
 	enable_eisa2_irq(irq);
 	return 0;
@@ -196,9 +187,9 @@
 {
 	u8 mask;
 
-	mask = EISA_READ_8(EISA_INT2_MASK);
+	mask = inb(EISA_INT2_MASK);
 	mask |= ((u8) (1 << (irq - 8)));
-	EISA_WRITE_8(EISA_INT2_MASK, mask);
+	outb(mask, EISA_INT2_MASK);
 }
 
 #define shutdown_eisa2_irq	disable_eisa2_irq
@@ -207,8 +198,7 @@
 {
 	disable_eisa2_irq(irq);
 
-	EISA_WRITE_8(EISA_INT2_CTRL, 0x20);
-	EISA_WRITE_8(EISA_INT1_CTRL, 0x20);
+	outb(0x20, EISA_INT2_CTRL);
 }
 
 static void end_eisa2_irq(unsigned int irq)
@@ -241,7 +231,6 @@
 {
 	int i, c;
 	char *str;
-	u8 *slot_addr;
 
 	if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
 		printk(KERN_INFO "EISA: bus not present.\n");
@@ -249,11 +238,8 @@
 	}
 
 	printk(KERN_INFO "EISA: Probing bus...\n");
-	for (c = 0, i = 1; i <= EISA_MAX_SLOTS; i++) {
-		slot_addr =
-		    (u8 *) EISA_TO_KSEG1((0x1000 * i) +
-					 EISA_VENDOR_ID_OFFSET);
-		if ((str = decode_eisa_sig(slot_addr))) {
+	for (c = 0, i = 1; i <= IP22_EISA_MAX_SLOTS; i++) {
+		if ((str = decode_eisa_sig(0x1000 * i + EISA_VENDOR_ID_OFFSET))) {
 			printk(KERN_INFO "EISA: slot %d : %s detected.\n",
 			       i, str);
 			c++;
@@ -268,25 +254,25 @@
 	   Please wave your favorite dead chicken over the busses */
 
 	/* First say hello to the EIU */
-	EIU_WRITE_32(EIU_PREMPT_REG, 0x0000FFFF);
-	EIU_WRITE_32(EIU_QUIET_REG, 1);
-	EIU_WRITE_32(EIU_MODE_REG, 0x40f3c07F);
+	outl(0x0000FFFF, EIU_PREMPT_REG);
+	outl(1, EIU_QUIET_REG);
+	outl(0x40f3c07F, EIU_MODE_REG);
 
 	/* Now be nice to the EISA chipset */
-	EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 1);
-	for (i = 0; i < 10000; i++);	/* Wait long enough for the dust to settle */
-	EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 0);
-	EISA_WRITE_8(EISA_INT1_CTRL, 0x11);
-	EISA_WRITE_8(EISA_INT2_CTRL, 0x11);
-	EISA_WRITE_8(EISA_INT1_MASK, 0);
-	EISA_WRITE_8(EISA_INT2_MASK, 8);
-	EISA_WRITE_8(EISA_INT1_MASK, 4);
-	EISA_WRITE_8(EISA_INT2_MASK, 2);
-	EISA_WRITE_8(EISA_INT1_MASK, 1);
-	EISA_WRITE_8(EISA_INT2_MASK, 1);
-	EISA_WRITE_8(EISA_INT1_MASK, 0xfb);
-	EISA_WRITE_8(EISA_INT2_MASK, 0xff);
-	EISA_WRITE_8(EISA_DMA2_WRITE_SINGLE, 0);
+	outb(1, EISA_EXT_NMI_RESET_CTRL);
+	udelay(50);	/* Wait long enough for the dust to settle */
+	outb(0, EISA_EXT_NMI_RESET_CTRL);
+	outb(0x11, EISA_INT1_CTRL);
+	outb(0x11, EISA_INT2_CTRL);
+	outb(0, EISA_INT1_MASK);
+	outb(8, EISA_INT2_MASK);
+	outb(4, EISA_INT1_MASK);
+	outb(2, EISA_INT2_MASK);
+	outb(1, EISA_INT1_MASK);
+	outb(1, EISA_INT2_MASK);
+	outb(0xfb, EISA_INT1_MASK);
+	outb(0xff, EISA_INT2_MASK);
+	outb(0, EISA_DMA2_WRITE_SINGLE);
 
 	for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) {
 		irq_desc[i].status = IRQ_DISABLED;
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 0e96a5d..5e59b4c 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -53,7 +53,7 @@
 extern void ip22_be_init(void) __init;
 extern void ip22_time_init(void) __init;
 
-static int __init ip22_setup(void)
+void __init plat_setup(void)
 {
 	char *ctype;
 
@@ -137,8 +137,4 @@
 		}
 	}
 #endif
-
-	return 0;
 }
-
-early_initcall(ip22_setup);
diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig
new file mode 100644
index 0000000..7b0bc44
--- /dev/null
+++ b/arch/mips/sgi-ip27/Kconfig
@@ -0,0 +1,54 @@
+#config SGI_SN0_XXL
+#	bool "IP27 XXL"
+#	depends on SGI_IP27
+#	  This options adds support for userspace processes upto 16TB size.
+#	  Normally the limit is just .5TB.
+
+config SGI_SN0_N_MODE
+	bool "IP27 N-Mode"
+	depends on SGI_IP27
+	help
+	  The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
+	  configured in either N-Modes which allows for more nodes or M-Mode
+	  which allows for more memory.  Your system is most probably
+	  running in M-Mode, so you should say N here.
+
+config ARCH_DISCONTIGMEM_ENABLE
+	bool
+	default y if SGI_IP27
+	help
+	  Say Y to upport efficient handling of discontiguous physical memory,
+	  for architectures which are either NUMA (Non-Uniform Memory Access)
+	  or have huge holes in the physical address space for other reasons.
+	  See <file:Documentation/vm/numa> for more.
+
+config NUMA
+	bool "NUMA Support"
+	depends on SGI_IP27
+	help
+	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+	  Access).  This option is for configuring high-end multiprocessor
+	  server machines.  If in doubt, say N.
+
+config MAPPED_KERNEL
+	bool "Mapped kernel support"
+	depends on SGI_IP27
+	help
+	  Change the way a Linux kernel is loaded into memory on a MIPS64
+	  machine.  This is required in order to support text replication and
+	  NUMA.  If you need to understand it, read the source code.
+
+config REPLICATE_KTEXT
+	bool "Kernel text replication support"
+	depends on SGI_IP27
+	help
+	  Say Y here to enable replicating the kernel text across multiple
+	  nodes in a NUMA cluster.  This trades memory for speed.
+
+config REPLICATE_EXHANDLERS
+	bool "Exception handler replication support"
+	depends on SGI_IP27
+	help
+	  Say Y here to enable replicating the kernel exception handlers
+	  across multiple nodes in a NUMA cluster. This trades memory for
+	  speed.
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index e1829a5..07631a9 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/signal.h>	/* for SIGBUS */
 
 #include <asm/module.h>
 #include <asm/sn/addrs.h>
diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
index d97f5b5..3e1ac29 100644
--- a/arch/mips/sgi-ip27/ip27-console.c
+++ b/arch/mips/sgi-ip27/ip27-console.c
@@ -30,8 +30,10 @@
 static inline struct ioc3_uartregs *console_uart(void)
 {
 	struct ioc3 *ioc3;
+	nasid_t nasid;
 
-	ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base;
+	nasid = (master_nasid == INVALID_NASID) ? get_nasid() : master_nasid;
+	ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(nasid)->memory_base;
 
 	return &ioc3->sregs.uarta;
 }
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
index 6dcee5c..8651a0e 100644
--- a/arch/mips/sgi-ip27/ip27-init.c
+++ b/arch/mips/sgi-ip27/ip27-init.c
@@ -56,12 +56,12 @@
 {
 	struct hub_data *hub = hub_data(cnode);
 	nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+	int i;
 
 	cpu_set(smp_processor_id(), hub->h_cpus);
 
 	if (test_and_set_bit(cnode, hub_init_mask))
 		return;
-
 	/*
 	 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
 	 */
@@ -88,6 +88,24 @@
 		__flush_cache_all();
 	}
 #endif
+
+	/*
+	 * Some interrupts are reserved by hardware or by software convention.
+	 * Mark these as reserved right away so they won't be used accidently
+	 * later.
+	 */
+	for (i = 0; i <= BASE_PCI_IRQ; i++) {
+		__set_bit(i, hub->irq_alloc_mask);
+		LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i);
+	}
+
+	__set_bit(IP_PEND0_6_63, hub->irq_alloc_mask);
+	LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);
+
+	for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
+		__set_bit(i, hub->irq_alloc_mask);
+		LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i);
+	}
 }
 
 void __init per_cpu_init(void)
@@ -104,30 +122,12 @@
 
 	clear_c0_status(ST0_IM);
 
+	per_hub_init(cnode);
+
 	for (i = 0; i < LEVELS_PER_SLICE; i++)
 		si->level_to_irq[i] = -1;
 
 	/*
-	 * Some interrupts are reserved by hardware or by software convention.
-	 * Mark these as reserved right away so they won't be used accidently
-	 * later.
-	 */
-	for (i = 0; i <= BASE_PCI_IRQ; i++) {
-		__set_bit(i, si->irq_alloc_mask);
-		LOCAL_HUB_S(PI_INT_PEND_MOD, i);
-	}
-
-	__set_bit(IP_PEND0_6_63, si->irq_alloc_mask);
-	LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);
-
-	for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
-		__set_bit(i, si->irq_alloc_mask + 1);
-		LOCAL_HUB_S(PI_INT_PEND_MOD, i);
-	}
-
-	LOCAL_HUB_L(PI_INT_PEND0);
-
-	/*
 	 * We use this so we can find the local hub's data as fast as only
 	 * possible.
 	 */
@@ -140,8 +140,6 @@
 	install_cpu_nmi_handler(cputoslice(cpu));
 
 	set_c0_status(SRB_DEV0 | SRB_DEV1);
-
-	per_hub_init(cnode);
 }
 
 /*
@@ -198,7 +196,7 @@
 extern void ip27_time_init(void);
 extern void ip27_reboot_setup(void);
 
-static int __init ip27_setup(void)
+void __init plat_setup(void)
 {
 	hubreg_t p, e, n_mode;
 	nasid_t nid;
@@ -245,8 +243,4 @@
 	set_io_port_base(IO_BASE);
 
 	board_time_init = ip27_time_init;
-
-	return 0;
 }
-
-early_initcall(ip27_setup);
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 61817a1..73e5e52 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -5,6 +5,9 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 1999 - 2001 Kanoj Sarcar
  */
+
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/irq.h>
@@ -14,11 +17,11 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/irq.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
 #include <linux/bitops.h>
@@ -37,13 +40,6 @@
 #include <asm/sn/hub.h>
 #include <asm/sn/intr.h>
 
-#undef DEBUG_IRQ
-#ifdef DEBUG_IRQ
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
 /*
  * Linux has a controller-independent x86 interrupt architecture.
  * every controller has a 'controller-template', that is used
@@ -74,14 +70,15 @@
 
 static inline int alloc_level(int cpu, int irq)
 {
+	struct hub_data *hub = hub_data(cpu_to_node(cpu));
 	struct slice_data *si = cpu_data[cpu].data;
-	int level;				/* pre-allocated entries */
+	int level;
 
-	level = find_first_zero_bit(si->irq_alloc_mask, LEVELS_PER_SLICE);
+	level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE);
 	if (level >= LEVELS_PER_SLICE)
 		panic("Cpu %d flooded with devices\n", cpu);
 
-	__set_bit(level, si->irq_alloc_mask);
+	__set_bit(level, hub->irq_alloc_mask);
 	si->level_to_irq[level] = irq;
 
 	return level;
@@ -216,9 +213,11 @@
 {
 	nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
 	struct slice_data *si = cpu_data[cpu].data;
+	unsigned long flags;
 
-	__set_bit(bit, si->irq_enable_mask);
+	set_bit(bit, si->irq_enable_mask);
 
+	local_irq_save(flags);
 	if (!cputoslice(cpu)) {
 		REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);
 		REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]);
@@ -226,6 +225,7 @@
 		REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]);
 		REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]);
 	}
+	local_irq_restore(flags);
 
 	return 0;
 }
@@ -235,7 +235,7 @@
 	nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
 	struct slice_data *si = cpu_data[cpu].data;
 
-	__clear_bit(bit, si->irq_enable_mask);
+	clear_bit(bit, si->irq_enable_mask);
 
 	if (!cputoslice(cpu)) {
 		REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);
@@ -261,7 +261,7 @@
 	bc = IRQ_TO_BRIDGE(irq);
 	bridge = bc->base;
 
-	DBG("bridge_startup(): irq= 0x%x  pin=%d\n", irq, pin);
+	pr_debug("bridge_startup(): irq= 0x%x  pin=%d\n", irq, pin);
 	/*
 	 * "map" irq to a swlevel greater than 6 since the first 6 bits
 	 * of INT_PEND0 are taken
@@ -298,12 +298,13 @@
 static void shutdown_bridge_irq(unsigned int irq)
 {
 	struct bridge_controller *bc = IRQ_TO_BRIDGE(irq);
+	struct hub_data *hub = hub_data(cpu_to_node(bc->irq_cpu));
 	bridge_t *bridge = bc->base;
 	struct slice_data *si = cpu_data[bc->irq_cpu].data;
 	int pin, swlevel;
 	cpuid_t cpu;
 
-	DBG("bridge_shutdown: irq 0x%x\n", irq);
+	pr_debug("bridge_shutdown: irq 0x%x\n", irq);
 	pin = SLOT_FROM_PCI_IRQ(irq);
 
 	/*
@@ -313,7 +314,7 @@
 	swlevel = find_level(&cpu, irq);
 	intr_disconnect_level(cpu, swlevel);
 
-	__clear_bit(swlevel, si->irq_alloc_mask);
+	__clear_bit(swlevel, hub->irq_alloc_mask);
 	si->level_to_irq[swlevel] = -1;
 
 	bridge->b_int_enable &= ~(1 << pin);
@@ -433,25 +434,24 @@
 	int slice = LOCAL_HUB_L(PI_CPU_NUM);
 	int cpu = smp_processor_id();
 	struct slice_data *si = cpu_data[cpu].data;
-	hubreg_t mask, set;
+	struct hub_data *hub = hub_data(cpu_to_node(cpu));
+	int resched, call;
+
+	resched = CPU_RESCHED_A_IRQ + slice;
+	__set_bit(resched, hub->irq_alloc_mask);
+	__set_bit(resched, si->irq_enable_mask);
+	LOCAL_HUB_CLR_INTR(resched);
+
+	call = CPU_CALL_A_IRQ + slice;
+	__set_bit(call, hub->irq_alloc_mask);
+	__set_bit(call, si->irq_enable_mask);
+	LOCAL_HUB_CLR_INTR(call);
 
 	if (slice == 0) {
-		LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ);
-		LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
-		mask = LOCAL_HUB_L(PI_INT_MASK0_A);	/* Slice A */
-		set = (1UL << CPU_RESCHED_A_IRQ) | (1UL << CPU_CALL_A_IRQ);
-		mask |= set;
-		si->irq_enable_mask[0] |= set;
-		si->irq_alloc_mask[0] |= set;
-		LOCAL_HUB_S(PI_INT_MASK0_A, mask);
+		LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]);
+		LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]);
 	} else {
-		LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ);
-		LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
-		mask = LOCAL_HUB_L(PI_INT_MASK0_B);	/* Slice B */
-		set = (1UL << CPU_RESCHED_B_IRQ) | (1UL << CPU_CALL_B_IRQ);
-		mask |= set;
-		si->irq_enable_mask[1] |= set;
-		si->irq_alloc_mask[1] |= set;
-		LOCAL_HUB_S(PI_INT_MASK0_B, mask);
+		LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]);
+		LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]);
 	}
 }
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index 17f768c..3a8291b 100644
--- a/arch/mips/sgi-ip27/ip27-smp.c
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -127,37 +127,28 @@
 	printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes());
 }
 
-static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend,
-	int base_level)
+static __init void intr_clear_all(nasid_t nasid)
 {
-	volatile hubreg_t bits;
 	int i;
 
-	/* Check pending interrupts */
-	if ((bits = HUB_L(pend)) != 0)
-		for (i = 0; i < N_INTPEND_BITS; i++)
-			if (bits & (1 << i))
-				LOCAL_HUB_CLR_INTR(base_level + i);
-}
-
-static void intr_clear_all(nasid_t nasid)
-{
 	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
 	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
 	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
 	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
-	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
-	                INT_PEND0_BASELVL);
-	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
-	                INT_PEND1_BASELVL);
+
+	for (i = 0; i < 128; i++)
+		REMOTE_HUB_CLR_INTR(nasid, i);
 }
 
 void __init prom_prepare_cpus(unsigned int max_cpus)
 {
 	cnodeid_t	cnode;
 
-	for_each_online_node(cnode)
+	for_each_online_node(cnode) {
+		if (cnode == 0)
+			continue;
 		intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+	}
 
 	replicate_kernel_text();
 
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index fc3a8e9..2eb22d69 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -163,14 +163,13 @@
 #define mask_and_ack_cpu_irq disable_cpu_irq
 
 static struct hw_interrupt_type ip32_cpu_interrupt = {
-	"IP32 CPU",
-	startup_cpu_irq,
-	shutdown_cpu_irq,
-	enable_cpu_irq,
-	disable_cpu_irq,
-	mask_and_ack_cpu_irq,
-	end_cpu_irq,
-	NULL
+	.typename = "IP32 CPU",
+	.startup = startup_cpu_irq,
+	.shutdown = shutdown_cpu_irq,
+	.enable = enable_cpu_irq,
+	.disable = disable_cpu_irq,
+	.ack = mask_and_ack_cpu_irq,
+	.end = end_cpu_irq,
 };
 
 /*
@@ -234,14 +233,13 @@
 #define shutdown_crime_irq disable_crime_irq
 
 static struct hw_interrupt_type ip32_crime_interrupt = {
-	"IP32 CRIME",
-	startup_crime_irq,
-	shutdown_crime_irq,
-	enable_crime_irq,
-	disable_crime_irq,
-	mask_and_ack_crime_irq,
-	end_crime_irq,
-	NULL
+	.typename = "IP32 CRIME",
+	.startup = startup_crime_irq,
+	.shutdown = shutdown_crime_irq,
+	.enable = enable_crime_irq,
+	.disable = disable_crime_irq,
+	.ack = mask_and_ack_crime_irq,
+	.end = end_crime_irq,
 };
 
 /*
@@ -294,14 +292,13 @@
 #define mask_and_ack_macepci_irq disable_macepci_irq
 
 static struct hw_interrupt_type ip32_macepci_interrupt = {
-	"IP32 MACE PCI",
-	startup_macepci_irq,
-	shutdown_macepci_irq,
-	enable_macepci_irq,
-	disable_macepci_irq,
-	mask_and_ack_macepci_irq,
-	end_macepci_irq,
-	NULL
+	.typename = "IP32 MACE PCI",
+	.startup = startup_macepci_irq,
+	.shutdown = shutdown_macepci_irq,
+	.enable = enable_macepci_irq,
+	.disable = disable_macepci_irq,
+	.ack = mask_and_ack_macepci_irq,
+	.end = end_macepci_irq,
 };
 
 /* This is used for MACE ISA interrupts.  That means bits 4-6 in the
@@ -425,14 +422,13 @@
 #define shutdown_maceisa_irq disable_maceisa_irq
 
 static struct hw_interrupt_type ip32_maceisa_interrupt = {
-	"IP32 MACE ISA",
-	startup_maceisa_irq,
-	shutdown_maceisa_irq,
-	enable_maceisa_irq,
-	disable_maceisa_irq,
-	mask_and_ack_maceisa_irq,
-	end_maceisa_irq,
-	NULL
+	.typename = "IP32 MACE ISA",
+	.startup = startup_maceisa_irq,
+	.shutdown = shutdown_maceisa_irq,
+	.enable = enable_maceisa_irq,
+	.disable = disable_maceisa_irq,
+	.ack = mask_and_ack_maceisa_irq,
+	.end = end_maceisa_irq,
 };
 
 /* This is used for regular non-ISA, non-PCI MACE interrupts.  That means
@@ -476,14 +472,13 @@
 #define mask_and_ack_mace_irq disable_mace_irq
 
 static struct hw_interrupt_type ip32_mace_interrupt = {
-	"IP32 MACE",
-	startup_mace_irq,
-	shutdown_mace_irq,
-	enable_mace_irq,
-	disable_mace_irq,
-	mask_and_ack_mace_irq,
-	end_mace_irq,
-	NULL
+	.typename = "IP32 MACE",
+	.startup = startup_mace_irq,
+	.shutdown = shutdown_mace_irq,
+	.enable = enable_mace_irq,
+	.disable = disable_mace_irq,
+	.ack = mask_and_ack_mace_irq,
+	.end = end_mace_irq,
 };
 
 static void ip32_unknown_interrupt(struct pt_regs *regs)
diff --git a/arch/mips/sgi-ip32/ip32-memory.c b/arch/mips/sgi-ip32/ip32-memory.c
index fc76ca9..d37d40a 100644
--- a/arch/mips/sgi-ip32/ip32-memory.c
+++ b/arch/mips/sgi-ip32/ip32-memory.c
@@ -36,8 +36,8 @@
 		if (base + size > (256 << 20))
 			base += CRIME_HI_MEM_BASE;
 
-		printk("CRIME MC: bank %u base 0x%016lx size %luMB\n",
-			bank, base, size);
+		printk("CRIME MC: bank %u base 0x%016lx size %luMiB\n",
+			bank, base, size >> 20);
 		add_memory_region (base, size, BOOT_MEM_RAM);
 	}
 }
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 8d270be..d10a269 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -92,7 +92,7 @@
 	setup_irq(IP32_R4K_TIMER_IRQ, irq);
 }
 
-static int __init ip32_setup(void)
+void __init plat_setup(void)
 {
 	board_be_init = ip32_be_init;
 
@@ -152,8 +152,4 @@
 		}
 	}
 #endif
-
-	return 0;
 }
-
-early_initcall(ip32_setup);
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
new file mode 100644
index 0000000..de46f62
--- /dev/null
+++ b/arch/mips/sibyte/Kconfig
@@ -0,0 +1,161 @@
+config SIBYTE_SB1250
+	bool
+	select HW_HAS_PCI
+	select SIBYTE_HAS_LDT
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1120
+	bool
+	select SIBYTE_BCM112X
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1125
+	bool
+	select HW_HAS_PCI
+	select SIBYTE_BCM112X
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1125H
+	bool
+	select HW_HAS_PCI
+	select SIBYTE_BCM112X
+	select SIBYTE_HAS_LDT
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM112X
+	bool
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1x80
+	bool
+	select HW_HAS_PCI
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1x55
+	bool
+	select HW_HAS_PCI
+	select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_SB1xxx_SOC
+	bool
+	depends on EXPERIMENTAL
+	select DMA_COHERENT
+	select SIBYTE_CFE
+	select SWAP_IO_SPACE
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+
+choice
+	prompt "SiByte SOC Stepping"
+	depends on SIBYTE_SB1xxx_SOC
+
+config CPU_SB1_PASS_1
+	bool "1250 Pass1"
+	depends on SIBYTE_SB1250
+	select CPU_HAS_PREFETCH
+
+config CPU_SB1_PASS_2_1250
+	bool "1250 An"
+	depends on SIBYTE_SB1250
+	select CPU_SB1_PASS_2
+	help
+	  Also called BCM1250 Pass 2
+
+config CPU_SB1_PASS_2_2
+	bool "1250 Bn"
+	depends on SIBYTE_SB1250
+	select CPU_HAS_PREFETCH
+	help
+	  Also called BCM1250 Pass 2.2
+
+config CPU_SB1_PASS_4
+	bool "1250 Cn"
+	depends on SIBYTE_SB1250
+	select CPU_HAS_PREFETCH
+	help
+	  Also called BCM1250 Pass 3
+
+config CPU_SB1_PASS_2_112x
+	bool "112x Hybrid"
+	depends on SIBYTE_BCM112X
+	select CPU_SB1_PASS_2
+
+config CPU_SB1_PASS_3
+	bool "112x An"
+	depends on SIBYTE_BCM112X
+	select CPU_HAS_PREFETCH
+
+endchoice
+
+config CPU_SB1_PASS_2
+	bool
+
+config SIBYTE_HAS_LDT
+	bool
+	depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H)
+	default y
+
+config SIMULATION
+	bool "Running under simulation"
+	depends on SIBYTE_SB1xxx_SOC
+	help
+	  Build a kernel suitable for running under the GDB simulator.
+	  Primarily adjusts the kernel's notion of time.
+
+config CONFIG_SB1_CEX_ALWAYS_FATAL
+	bool "All cache exceptions considered fatal (no recovery attempted)"
+	depends on SIBYTE_SB1xxx_SOC
+
+config CONFIG_SB1_CERR_STALL
+	bool "Stall (rather than panic) on fatal cache error"
+	depends on SIBYTE_SB1xxx_SOC
+
+config SIBYTE_CFE
+	bool "Booting from CFE"
+	depends on SIBYTE_SB1xxx_SOC
+	help
+	  Make use of the CFE API for enumerating available memory,
+	  controlling secondary CPUs, and possibly console output.
+
+config SIBYTE_CFE_CONSOLE
+	bool "Use firmware console"
+	depends on SIBYTE_CFE
+	help
+	  Use the CFE API's console write routines during boot.  Other console
+	  options (VT console, sb1250 duart console, etc.) should not be
+	  configured.
+
+config SIBYTE_STANDALONE
+	bool
+	depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
+	default y
+
+config SIBYTE_STANDALONE_RAM_SIZE
+	int "Memory size (in megabytes)"
+	depends on SIBYTE_STANDALONE
+	default "32"
+
+config SIBYTE_BUS_WATCHER
+	bool "Support for Bus Watcher statistics"
+	depends on SIBYTE_SB1xxx_SOC
+	help
+	  Handle and keep statistics on the bus error interrupts (COR_ECC,
+	  BAD_ECC, IO_BUS).
+
+config SIBYTE_BW_TRACE
+	bool "Capture bus trace before bus error"
+	depends on SIBYTE_BUS_WATCHER
+	help
+	  Run a continuous bus trace, dumping the raw data as soon as
+	  a ZBbus error is detected.  Cannot work if ZBbus profiling
+	  is turned on, and also will interfere with JTAG-based trace
+	  buffer activity.  Raw buffer data is dumped to console, and
+	  must be processed off-line.
+
+config SIBYTE_SB1250_PROF
+	bool "Support for SB1/SOC profiling - SB1/SCD perf counters"
+	depends on SIBYTE_SB1xxx_SOC
+
+config SIBYTE_TBPROF
+	bool "Support for ZBbus profiling"
+	depends on SIBYTE_SB1xxx_SOC
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
new file mode 100644
index 0000000..538d5a5
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -0,0 +1,5 @@
+obj-y := setup.o irq.o irq_handler.o time.o
+
+obj-$(CONFIG_SMP)			+= smp.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
new file mode 100644
index 0000000..b2a1ba5
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/errno.h>
+#include <asm/signal.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#include <asm/sibyte/bcm1480_scd.h>
+
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/sb1250.h>
+
+/*
+ * These are the routines that handle all the low level interrupt stuff.
+ * Actions handled here are: initialization of the interrupt map, requesting of
+ * interrupt lines by handlers, dispatching if interrupts to handlers, probing
+ * for interrupt lines
+ */
+
+
+#define shutdown_bcm1480_irq	disable_bcm1480_irq
+static void end_bcm1480_irq(unsigned int irq);
+static void enable_bcm1480_irq(unsigned int irq);
+static void disable_bcm1480_irq(unsigned int irq);
+static unsigned int startup_bcm1480_irq(unsigned int irq);
+static void ack_bcm1480_irq(unsigned int irq);
+#ifdef CONFIG_SMP
+static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask);
+#endif
+
+#ifdef CONFIG_PCI
+extern unsigned long ht_eoi_space;
+#endif
+
+#ifdef CONFIG_KGDB
+#include <asm/gdb-stub.h>
+extern void breakpoint(void);
+static int kgdb_irq;
+#ifdef CONFIG_GDB_CONSOLE
+extern void register_gdb_console(void);
+#endif
+
+/* kgdb is on when configured.  Pass "nokgdb" kernel arg to turn it off */
+static int kgdb_flag = 1;
+static int __init nokgdb(char *str)
+{
+	kgdb_flag = 0;
+	return 1;
+}
+__setup("nokgdb", nokgdb);
+
+/* Default to UART1 */
+int kgdb_port = 1;
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+extern char sb1250_duart_present[];
+#endif
+#endif
+
+static struct hw_interrupt_type bcm1480_irq_type = {
+	.typename = "BCM1480-IMR",
+	.startup = startup_bcm1480_irq,
+	.shutdown = shutdown_bcm1480_irq,
+	.enable = enable_bcm1480_irq,
+	.disable = disable_bcm1480_irq,
+	.ack = ack_bcm1480_irq,
+	.end = end_bcm1480_irq,
+#ifdef CONFIG_SMP
+	.set_affinity = bcm1480_set_affinity
+#endif
+};
+
+/* Store the CPU id (not the logical number) */
+int bcm1480_irq_owner[BCM1480_NR_IRQS];
+
+DEFINE_SPINLOCK(bcm1480_imr_lock);
+
+void bcm1480_mask_irq(int cpu, int irq)
+{
+	unsigned long flags;
+	u64 cur_ints,hl_spacing;
+
+	spin_lock_irqsave(&bcm1480_imr_lock, flags);
+	hl_spacing = 0;
+	if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) {
+		hl_spacing = BCM1480_IMR_HL_SPACING;
+		irq -= BCM1480_NR_IRQS_HALF;
+	}
+	cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+	cur_ints |= (((u64) 1) << irq);
+	____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+	spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+}
+
+void bcm1480_unmask_irq(int cpu, int irq)
+{
+	unsigned long flags;
+	u64 cur_ints,hl_spacing;
+
+	spin_lock_irqsave(&bcm1480_imr_lock, flags);
+	hl_spacing = 0;
+	if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) {
+		hl_spacing = BCM1480_IMR_HL_SPACING;
+		irq -= BCM1480_NR_IRQS_HALF;
+	}
+	cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+	cur_ints &= ~(((u64) 1) << irq);
+	____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+	spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+}
+
+#ifdef CONFIG_SMP
+static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
+{
+	int i = 0, old_cpu, cpu, int_on;
+	u64 cur_ints;
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
+	unsigned int irq_dirty;
+
+	i = first_cpu(mask);
+	if (next_cpu(i, mask) <= NR_CPUS) {
+		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
+		return;
+	}
+
+	/* Convert logical CPU to physical CPU */
+	cpu = cpu_logical_map(i);
+
+	/* Protect against other affinity changers and IMR manipulation */
+	spin_lock_irqsave(&desc->lock, flags);
+	spin_lock(&bcm1480_imr_lock);
+
+	/* Swizzle each CPU's IMR (but leave the IP selection alone) */
+	old_cpu = bcm1480_irq_owner[irq];
+	irq_dirty = irq;
+	if ((irq_dirty >= BCM1480_NR_IRQS_HALF) && (irq_dirty <= BCM1480_NR_IRQS)) {
+		irq_dirty -= BCM1480_NR_IRQS_HALF;
+	}
+
+	int k;
+	for (k=0; k<2; k++) { /* Loop through high and low interrupt mask register */
+		cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(old_cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+		int_on = !(cur_ints & (((u64) 1) << irq_dirty));
+		if (int_on) {
+			/* If it was on, mask it */
+			cur_ints |= (((u64) 1) << irq_dirty);
+			____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(old_cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+		}
+		bcm1480_irq_owner[irq] = cpu;
+		if (int_on) {
+			/* unmask for the new CPU */
+			cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+			cur_ints &= ~(((u64) 1) << irq_dirty);
+			____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+		}
+	}
+	spin_unlock(&bcm1480_imr_lock);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+#endif
+
+
+/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
+extern void bcm1480_irq_handler(void);
+
+/*****************************************************************************/
+
+static unsigned int startup_bcm1480_irq(unsigned int irq)
+{
+	bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+
+	return 0;		/* never anything pending */
+}
+
+
+static void disable_bcm1480_irq(unsigned int irq)
+{
+	bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
+}
+
+static void enable_bcm1480_irq(unsigned int irq)
+{
+	bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+}
+
+
+static void ack_bcm1480_irq(unsigned int irq)
+{
+	u64 pending;
+	unsigned int irq_dirty;
+
+	/*
+	 * If the interrupt was an HT interrupt, now is the time to
+	 * clear it.  NOTE: we assume the HT bridge was set up to
+	 * deliver the interrupts to all CPUs (which makes affinity
+	 * changing easier for us)
+	 */
+	irq_dirty = irq;
+	if ((irq_dirty >= BCM1480_NR_IRQS_HALF) && (irq_dirty <= BCM1480_NR_IRQS)) {
+		irq_dirty -= BCM1480_NR_IRQS_HALF;
+	}
+	int k;
+	for (k=0; k<2; k++) { /* Loop through high and low LDT interrupts */
+		pending = __raw_readq(IOADDR(A_BCM1480_IMR_REGISTER(bcm1480_irq_owner[irq],
+						R_BCM1480_IMR_LDT_INTERRUPT_H + (k*BCM1480_IMR_HL_SPACING))));
+		pending &= ((u64)1 << (irq_dirty));
+		if (pending) {
+#ifdef CONFIG_SMP
+			int i;
+			for (i=0; i<NR_CPUS; i++) {
+				/*
+				 * Clear for all CPUs so an affinity switch
+				 * doesn't find an old status
+				 */
+				__raw_writeq(pending, IOADDR(A_BCM1480_IMR_REGISTER(cpu_logical_map(i),
+								R_BCM1480_IMR_LDT_INTERRUPT_CLR_H + (k*BCM1480_IMR_HL_SPACING))));
+			}
+#else
+			__raw_writeq(pending, IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_LDT_INTERRUPT_CLR_H + (k*BCM1480_IMR_HL_SPACING))));
+#endif
+
+			/*
+			 * Generate EOI.  For Pass 1 parts, EOI is a nop.  For
+			 * Pass 2, the LDT world may be edge-triggered, but
+			 * this EOI shouldn't hurt.  If they are
+			 * level-sensitive, the EOI is required.
+			 */
+#ifdef CONFIG_PCI
+			if (ht_eoi_space)
+				*(uint32_t *)(ht_eoi_space+(irq<<16)+(7<<2)) = 0;
+#endif
+		}
+	}
+	bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
+}
+
+
+static void end_bcm1480_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+	}
+}
+
+
+void __init init_bcm1480_irqs(void)
+{
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 1;
+		if (i < BCM1480_NR_IRQS) {
+			irq_desc[i].handler = &bcm1480_irq_type;
+			bcm1480_irq_owner[i] = 0;
+		} else {
+			irq_desc[i].handler = &no_irq_type;
+		}
+	}
+}
+
+
+static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id,
+	struct pt_regs *regs)
+{
+	return IRQ_NONE;
+}
+
+static struct irqaction bcm1480_dummy_action = {
+	.handler = bcm1480_dummy_handler,
+	.flags   = 0,
+	.mask    = CPU_MASK_NONE,
+	.name    = "bcm1480-private",
+	.next    = NULL,
+	.dev_id  = 0
+};
+
+int bcm1480_steal_irq(int irq)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
+	int retval = 0;
+
+	if (irq >= BCM1480_NR_IRQS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&desc->lock,flags);
+	/* Don't allow sharing at all for these */
+	if (desc->action != NULL)
+		retval = -EBUSY;
+	else {
+		desc->action = &bcm1480_dummy_action;
+		desc->depth = 0;
+	}
+	spin_unlock_irqrestore(&desc->lock,flags);
+	return 0;
+}
+
+/*
+ *  init_IRQ is called early in the boot sequence from init/main.c.  It
+ *  is responsible for setting up the interrupt mapper and installing the
+ *  handler that will be responsible for dispatching interrupts to the
+ *  "right" place.
+ */
+/*
+ * For now, map all interrupts to IP[2].  We could save
+ * some cycles by parceling out system interrupts to different
+ * IP lines, but keep it simple for bringup.  We'll also direct
+ * all interrupts to a single CPU; we should probably route
+ * PCI and LDT to one cpu and everything else to the other
+ * to balance the load a bit.
+ *
+ * On the second cpu, everything is set to IP5, which is
+ * ignored, EXCEPT the mailbox interrupt.  That one is
+ * set to IP[2] so it is handled.  This is needed so we
+ * can do cross-cpu function calls, as requred by SMP
+ */
+
+#define IMR_IP2_VAL	K_BCM1480_INT_MAP_I0
+#define IMR_IP3_VAL	K_BCM1480_INT_MAP_I1
+#define IMR_IP4_VAL	K_BCM1480_INT_MAP_I2
+#define IMR_IP5_VAL	K_BCM1480_INT_MAP_I3
+#define IMR_IP6_VAL	K_BCM1480_INT_MAP_I4
+
+void __init arch_init_irq(void)
+{
+
+	unsigned int i, cpu;
+	u64 tmp;
+	unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+		STATUSF_IP1 | STATUSF_IP0;
+
+	/* Default everything to IP2 */
+	/* Start with _high registers which has no bit 0 interrupt source */
+	for (i = 1; i < BCM1480_NR_IRQS_HALF; i++) {	/* was I0 */
+		for (cpu = 0; cpu < 4; cpu++) {
+			__raw_writeq(IMR_IP2_VAL,
+				     IOADDR(A_BCM1480_IMR_REGISTER(cpu,
+								   R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (i << 3)));
+		}
+	}
+
+	/* Now do _low registers */
+	for (i = 0; i < BCM1480_NR_IRQS_HALF; i++) {
+		for (cpu = 0; cpu < 4; cpu++) {
+			__raw_writeq(IMR_IP2_VAL,
+				     IOADDR(A_BCM1480_IMR_REGISTER(cpu,
+								   R_BCM1480_IMR_INTERRUPT_MAP_BASE_L) + (i << 3)));
+		}
+	}
+
+	init_bcm1480_irqs();
+
+	/*
+	 * Map the high 16 bits of mailbox_0 registers to IP[3], for
+	 * inter-cpu messages
+	 */
+	/* Was I1 */
+	for (cpu = 0; cpu < 4; cpu++) {
+		__raw_writeq(IMR_IP3_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
+						 (K_BCM1480_INT_MBOX_0_0 << 3)));
+        }
+
+
+	/* Clear the mailboxes.  The firmware may leave them dirty */
+	for (cpu = 0; cpu < 4; cpu++) {
+		__raw_writeq(0xffffffffffffffffULL,
+			     IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_0_CLR_CPU)));
+		__raw_writeq(0xffffffffffffffffULL,
+			     IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_1_CLR_CPU)));
+	}
+
+
+	/* Mask everything except the high 16 bit of mailbox_0 registers for all cpus */
+	tmp = ~((u64) 0) ^ ( (((u64) 1) << K_BCM1480_INT_MBOX_0_0));
+	for (cpu = 0; cpu < 4; cpu++) {
+		__raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_H)));
+	}
+	tmp = ~((u64) 0);
+	for (cpu = 0; cpu < 4; cpu++) {
+		__raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_L)));
+	}
+
+	bcm1480_steal_irq(K_BCM1480_INT_MBOX_0_0);
+
+	/*
+	 * Note that the timer interrupts are also mapped, but this is
+	 * done in bcm1480_time_init().  Also, the profiling driver
+	 * does its own management of IP7.
+	 */
+
+#ifdef CONFIG_KGDB
+	imask |= STATUSF_IP6;
+#endif
+	/* Enable necessary IPs, disable the rest */
+	change_c0_status(ST0_IM, imask);
+	set_except_vector(0, bcm1480_irq_handler);
+
+#ifdef CONFIG_KGDB
+	if (kgdb_flag) {
+		kgdb_irq = K_BCM1480_INT_UART_0 + kgdb_port;
+
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+		sb1250_duart_present[kgdb_port] = 0;
+#endif
+		/* Setup uart 1 settings, mapper */
+		/* QQQ FIXME */
+		__raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
+
+		bcm1480_steal_irq(kgdb_irq);
+		__raw_writeq(IMR_IP6_VAL,
+			     IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
+			     (kgdb_irq<<3));
+		bcm1480_unmask_irq(0, kgdb_irq);
+
+#ifdef CONFIG_GDB_CONSOLE
+		register_gdb_console();
+#endif
+		prom_printf("Waiting for GDB on UART port %d\n", kgdb_port);
+		set_debug_traps();
+		breakpoint();
+	}
+#endif
+}
+
+#ifdef CONFIG_KGDB
+
+#include <linux/delay.h>
+
+#define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+
+void bcm1480_kgdb_interrupt(struct pt_regs *regs)
+{
+	/*
+	 * Clear break-change status (allow some time for the remote
+	 * host to stop the break, since we would see another
+	 * interrupt on the end-of-break too)
+	 */
+	kstat.irqs[smp_processor_id()][kgdb_irq]++;
+	mdelay(500);
+	duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
+				M_DUART_RX_EN | M_DUART_TX_EN);
+	set_async_breakpoint(&regs->cp0_epc);
+}
+
+#endif 	/* CONFIG_KGDB */
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
new file mode 100644
index 0000000..408db88
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/irq_handler.S
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * bcm1480_irq_handler() is the routine that is actually called when an
+ * interrupt occurs.  It is installed as the exception vector handler in
+ * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
+ *
+ * In the handle we figure out which interrupts need handling, and use that
+ * to call the dispatcher, which will take care of actually calling
+ * registered handlers
+ *
+ * Note that we take care of all raised interrupts in one go at the handler.
+ * This is more BSDish than the Indy code, and also, IMHO, more sane.
+ */
+#include <linux/config.h>
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/sibyte/sb1250_defs.h>
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+/*
+ * What a pain. We have to be really careful saving the upper 32 bits of any
+ * register across function calls if we don't want them trashed--since were
+ * running in -o32, the calling routing never saves the full 64 bits of a
+ * register across a function call.  Being the interrupt handler, we're
+ * guaranteed that interrupts are disabled during this code so we don't have
+ * to worry about random interrupts blasting the high 32 bits.
+ */
+
+	.text
+	.set	push
+	.set	noreorder
+	.set	noat
+	.set	mips64
+	#.set	mips4
+	.align	5
+	NESTED(bcm1480_irq_handler, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+	/* Set compare to count to silence count/compare timer interrupts */
+	mfc0	t1, CP0_COUNT
+	mtc0	t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
+#endif
+	/* Read cause */
+	mfc0	s0, CP0_CAUSE
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+	/* Cpu performance counter interrupt is routed to IP[7] */
+	andi	t1, s0, CAUSEF_IP7
+	beqz	t1, 0f
+	 srl	t1, s0, (CAUSEB_BD-2)	/* Shift BD bit to bit 2 */
+	and	t1, t1, 0x4		/* mask to get just BD bit */
+#ifdef CONFIG_MIPS64
+	dmfc0	a0, CP0_EPC
+	daddu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
+#else
+	mfc0	a0, CP0_EPC
+	addu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
+#endif
+	jal	sbprof_cpu_intr
+	 nop
+	j	ret_from_irq
+	 nop
+0:
+#endif
+
+	/* Timer interrupt is routed to IP[4] */
+	andi	t1, s0, CAUSEF_IP4
+	beqz	t1, 1f
+	 nop
+	jal	bcm1480_timer_interrupt
+	 move	a0, sp			/* Pass the registers along */
+	j	ret_from_irq
+	 nop				/* delay slot  */
+1:
+
+#ifdef CONFIG_SMP
+	/* Mailbox interrupt is routed to IP[3] */
+	andi	 t1, s0, CAUSEF_IP3
+	beqz	 t1, 2f
+	 nop
+	jal	 bcm1480_mailbox_interrupt
+	 move	 a0, sp
+	j	 ret_from_irq
+	 nop				/* delay slot  */
+2:
+#endif
+
+#ifdef CONFIG_KGDB
+	/* KGDB (uart 1) interrupt is routed to IP[6] */
+	andi	 t1, s0, CAUSEF_IP6
+	beqz	 t1, 3f
+	 nop				/* delay slot  */
+	jal	 bcm1480_kgdb_interrupt
+	 move	 a0, sp
+	j	 ret_from_irq
+	 nop				/* delay slot  */
+3:
+#endif
+
+	and	 t1, s0, CAUSEF_IP2
+	beqz	 t1, 9f
+	 nop
+
+	/*
+	 * Default...we've hit an IP[2] interrupt, which means we've got
+	 * to check the 1480 interrupt registers to figure out what to do
+	 * Need to detect which CPU we're on, now that smp_affinity is
+	 * supported.
+	 */
+	PTR_LA	 v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
+#ifdef CONFIG_SMP
+	lw	 t1, TI_CPU($28)
+	sll	 t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
+	addu	 v0, v0, t1
+#endif
+
+	/* Read IP[2] status (get both high and low halves of status) */
+	ld	 s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
+	ld	 s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
+
+	move	 s2, zero	/* intr number  */
+	li	 s3, 64
+
+	beqz	 s0, 9f		/* No interrupts.  Return.  */
+	 move	 a1, sp
+
+	xori	 s4, s0, 1	/* if s0 (_H) == 1, it's a low intr, so...  */
+	movz	 s2, s3, s4	/* start the intr number at 64, and  */
+	movz	 s0, s1, s4	/* look at the low status value.  */
+
+	dclz	 s1, s0		/* Find the next interrupt.  */
+	dsubu	 a0, zero, s1
+	daddiu	 a0, a0, 63
+	jal	 do_IRQ
+	 daddu	 a0, a0, s2
+
+9:	j	 ret_from_irq
+	 nop
+
+	.set pop
+	END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
new file mode 100644
index 0000000..d90a0b8
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_scd.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+unsigned int sb1_pass;
+unsigned int soc_pass;
+unsigned int soc_type;
+unsigned int periph_rev;
+unsigned int zbbus_mhz;
+
+static unsigned int part_type;
+
+static char *soc_str;
+static char *pass_str;
+
+static inline int setup_bcm1x80_bcm1x55(void);
+
+/* Setup code likely to be common to all SiByte platforms */
+
+static inline int sys_rev_decode(void)
+{
+	int ret = 0;
+
+	switch (soc_type) {
+	    case K_SYS_SOC_TYPE_BCM1x80:
+		if (part_type == K_SYS_PART_BCM1480)
+		    soc_str = "BCM1480";
+		else if (part_type == K_SYS_PART_BCM1280)
+		    soc_str = "BCM1280";
+		else
+		    soc_str = "BCM1x80";
+		ret = setup_bcm1x80_bcm1x55();
+		break;
+
+	    case K_SYS_SOC_TYPE_BCM1x55:
+		if (part_type == K_SYS_PART_BCM1455)
+		    soc_str = "BCM1455";
+		else if (part_type == K_SYS_PART_BCM1255)
+		    soc_str = "BCM1255";
+		else
+		    soc_str = "BCM1x55";
+		ret = setup_bcm1x80_bcm1x55();
+		break;
+
+	    default:
+		prom_printf("Unknown part type %x\n", part_type);
+		ret = 1;
+		break;
+	}
+	return ret;
+}
+
+static inline int setup_bcm1x80_bcm1x55(void)
+{
+	int ret = 0;
+
+	switch (soc_pass) {
+	    case K_SYS_REVISION_BCM1480_S0:
+		periph_rev = 1;
+		pass_str = "S0 (pass1)";
+		break;
+	    case K_SYS_REVISION_BCM1480_A1:
+		periph_rev = 1;
+		pass_str = "A1 (pass1)";
+		break;
+	    case K_SYS_REVISION_BCM1480_A2:
+		periph_rev = 1;
+		pass_str = "A2 (pass1)";
+		break;
+	    case K_SYS_REVISION_BCM1480_A3:
+		periph_rev = 1;
+		pass_str = "A3 (pass1)";
+		break;
+	    case K_SYS_REVISION_BCM1480_B0:
+		periph_rev = 1;
+		pass_str = "B0 (pass2)";
+		break;
+	    default:
+		prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+		periph_rev = 1;
+		pass_str = "Unknown Revision";
+		break;
+	}
+	return ret;
+}
+
+void bcm1480_setup(void)
+{
+	uint64_t sys_rev;
+	int plldiv;
+
+	sb1_pass = read_c0_prid() & 0xff;
+	sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
+	soc_type = SYS_SOC_TYPE(sys_rev);
+	part_type = G_SYS_PART(sys_rev);
+	soc_pass = G_SYS_REVISION(sys_rev);
+
+	if (sys_rev_decode()) {
+		prom_printf("Restart after failure to identify SiByte chip\n");
+		machine_restart(NULL);
+	}
+
+	plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+	zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
+
+	prom_printf("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n",
+		    soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
+	prom_printf("Board type: %s\n", get_system_type());
+}
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
new file mode 100644
index 0000000..584a4b3
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2001,2002,2004 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+extern void smp_call_function_interrupt(void);
+
+/*
+ * These are routines for dealing with the bcm1480 smp capabilities
+ * independent of board/firmware
+ */
+
+static void *mailbox_0_set_regs[] = {
+	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+};
+
+static void *mailbox_0_clear_regs[] = {
+	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+};
+
+static void *mailbox_0_regs[] = {
+	IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+	IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+	IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+	IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+};
+
+/*
+ * SMP init and finish on secondary CPUs
+ */
+void bcm1480_smp_init(void)
+{
+	unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+		STATUSF_IP1 | STATUSF_IP0;
+
+	/* Set interrupt mask, but don't enable */
+	change_c0_status(ST0_IM, imask);
+}
+
+void bcm1480_smp_finish(void)
+{
+	extern void bcm1480_time_init(void);
+	bcm1480_time_init();
+	local_irq_enable();
+}
+
+/*
+ * These are routines for dealing with the sb1250 smp capabilities
+ * independent of board/firmware
+ */
+
+/*
+ * Simple enough; everything is set up, so just poke the appropriate mailbox
+ * register, and we should be set
+ */
+void core_send_ipi(int cpu, unsigned int action)
+{
+	__raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
+}
+
+void bcm1480_mailbox_interrupt(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	unsigned int action;
+
+	kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
+	/* Load the mailbox register to figure out what we're supposed to do */
+	action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
+
+	/* Clear the mailbox to clear the interrupt */
+	__raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]);
+
+	/*
+	 * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
+	 * interrupt will do the reschedule for us
+	 */
+
+	if (action & SMP_CALL_FUNCTION)
+		smp_call_function_interrupt();
+}
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
new file mode 100644
index 0000000..e545752
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2000,2001,2004 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * These are routines to set up and handle interrupts from the
+ * bcm1480 general purpose timer 0.  We're using the timer as a
+ * system clock, so we set it up to run at 100 Hz.  On every
+ * interrupt, we update our idea of what the time of day is,
+ * then call do_timer() in the architecture-independent kernel
+ * code to do general bookkeeping (e.g. update jiffies, run
+ * bottom halves, etc.)
+ */
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#include <asm/sibyte/bcm1480_scd.h>
+
+#include <asm/sibyte/sb1250.h>
+
+
+#define IMR_IP2_VAL	K_BCM1480_INT_MAP_I0
+#define IMR_IP3_VAL	K_BCM1480_INT_MAP_I1
+#define IMR_IP4_VAL	K_BCM1480_INT_MAP_I2
+
+extern int bcm1480_steal_irq(int irq);
+
+void bcm1480_time_init(void)
+{
+	int cpu = smp_processor_id();
+	int irq = K_BCM1480_INT_TIMER_0+cpu;
+
+	/* Only have 4 general purpose timers */
+	if (cpu > 3) {
+		BUG();
+	}
+
+	if (!cpu) {
+		/* Use our own gettimeoffset() routine */
+		do_gettimeoffset = bcm1480_gettimeoffset;
+	}
+
+	bcm1480_mask_irq(cpu, irq);
+
+	/* Map the timer interrupt to ip[4] of this cpu */
+	__raw_writeq(IMR_IP4_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H)
+	      + (irq<<3)));
+
+	/* the general purpose timer ticks at 1 Mhz independent of the rest of the system */
+	/* Disable the timer and set up the count */
+	__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+	__raw_writeq(
+#ifndef CONFIG_SIMULATION
+		1000000/HZ
+#else
+		50000/HZ
+#endif
+		, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+
+	/* Set the timer running */
+	__raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
+	      IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+
+	bcm1480_unmask_irq(cpu, irq);
+	bcm1480_steal_irq(irq);
+	/*
+	 * This interrupt is "special" in that it doesn't use the request_irq
+	 * way to hook the irq line.  The timer interrupt is initialized early
+	 * enough to make this a major pain, and it's also firing enough to
+	 * warrant a bit of special case code.  bcm1480_timer_interrupt is
+	 * called directly from irq_handler.S when IP[4] is set during an
+	 * interrupt
+	 */
+}
+
+#include <asm/sibyte/sb1250.h>
+
+void bcm1480_timer_interrupt(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	int irq = K_BCM1480_INT_TIMER_0+cpu;
+
+	/* Reset the timer */
+	__raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
+	      IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+
+	/*
+	 * CPU 0 handles the global timer interrupt job
+	 */
+	if (cpu == 0) {
+		ll_timer_interrupt(irq, regs);
+	}
+
+	/*
+	 * every CPU should do profiling and process accouting
+	 */
+	ll_local_timer_interrupt(irq, regs);
+}
+
+/*
+ * We use our own do_gettimeoffset() instead of the generic one,
+ * because the generic one does not work for SMP case.
+ * In addition, since we use general timer 0 for system time,
+ * we can get accurate intra-jiffy offset without calibration.
+ */
+unsigned long bcm1480_gettimeoffset(void)
+{
+	unsigned long count =
+		__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+
+	return 1000000/HZ - count;
+}
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
index e44ce1a..e848512 100644
--- a/arch/mips/sibyte/cfe/smp.c
+++ b/arch/mips/sibyte/cfe/smp.c
@@ -70,8 +70,15 @@
  */
 void prom_init_secondary(void)
 {
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+	extern void bcm1480_smp_init(void);
+	bcm1480_smp_init();
+#elif defined(CONFIG_SIBYTE_SB1250)
 	extern void sb1250_smp_init(void);
 	sb1250_smp_init();
+#else
+#error invalid SMP configuration
+#endif
 }
 
 /*
@@ -80,8 +87,15 @@
  */
 void prom_smp_finish(void)
 {
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+	extern void bcm1480_smp_finish(void);
+	bcm1480_smp_finish();
+#elif defined(CONFIG_SIBYTE_SB1250)
 	extern void sb1250_smp_finish(void);
 	sb1250_smp_finish();
+#else
+#error invalid SMP configuration
+#endif
 }
 
 /*
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
index 7f813ae..992e0d8 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -28,6 +28,8 @@
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/reboot.h>
+#include <linux/smp_lock.h>
+#include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/sibyte/sb1250.h>
@@ -64,24 +66,25 @@
 	u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
 	/* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
 	   trigger start of trace.  XXX vary sampling period */
-	bus_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
-	scdperfcnt = bus_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+	__raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
+	scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
 	/* Unfortunately, in Pass 2 we must clear all counters to knock down
 	   a previous interrupt request.  This means that bus profiling
 	   requires ALL of the SCD perf counters. */
-	bus_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) | // keep counters 0,2,3 as is
-		   M_SPC_CFG_ENABLE |		 // enable counting
-		   M_SPC_CFG_CLEAR |		 // clear all counters
-		   V_SPC_CFG_SRC1(1),		 // counter 1 counts cycles
-		   IOADDR(A_SCD_PERF_CNT_CFG));
-	bus_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
+	__raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) |
+						// keep counters 0,2,3 as is
+		     M_SPC_CFG_ENABLE |		// enable counting
+		     M_SPC_CFG_CLEAR |		// clear all counters
+		     V_SPC_CFG_SRC1(1),		// counter 1 counts cycles
+		     IOADDR(A_SCD_PERF_CNT_CFG));
+	__raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
 	/* Reset the trace buffer */
-	bus_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+	__raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 #if 0 && defined(M_SCD_TRACE_CFG_FORCECNT)
 	/* XXXKW may want to expose control to the data-collector */
 	tb_options |= M_SCD_TRACE_CFG_FORCECNT;
 #endif
-	bus_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
+	__raw_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
 	sbp.tb_armed = 1;
 }
 
@@ -93,23 +96,30 @@
 		/* XXX should use XKPHYS to make writes bypass L2 */
 		u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
 		/* Read out trace */
-		bus_writeq(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));
+		__raw_writeq(M_SCD_TRACE_CFG_START_READ,
+			     IOADDR(A_SCD_TRACE_CFG));
 		__asm__ __volatile__ ("sync" : : : "memory");
 		/* Loop runs backwards because bundles are read out in reverse order */
 		for (i = 256 * 6; i > 0; i -= 6) {
 			// Subscripts decrease to put bundle in the order
 			//   t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi
-			p[i-1] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 hi
-			p[i-2] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 lo
-			p[i-3] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 hi
-			p[i-4] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 lo
-			p[i-5] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 hi
-			p[i-6] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 lo
+			p[i - 1] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+								// read t2 hi
+			p[i - 2] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+								// read t2 lo
+			p[i - 3] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+								// read t1 hi
+			p[i - 4] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+								// read t1 lo
+			p[i - 5] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+								// read t0 hi
+			p[i - 6] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+								// read t0 lo
 		}
 		if (!sbp.tb_enable) {
 			DBG(printk(DEVNAME ": tb_intr shutdown\n"));
-			bus_writeq(M_SCD_TRACE_CFG_RESET,
-				   IOADDR(A_SCD_TRACE_CFG));
+			__raw_writeq(M_SCD_TRACE_CFG_RESET,
+				     IOADDR(A_SCD_TRACE_CFG));
 			sbp.tb_armed = 0;
 			wake_up(&sbp.tb_sync);
 		} else {
@@ -118,7 +128,7 @@
 	} else {
 		/* No more trace buffer samples */
 		DBG(printk(DEVNAME ": tb_intr full\n"));
-		bus_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+		__raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 		sbp.tb_armed = 0;
 		if (!sbp.tb_enable) {
 			wake_up(&sbp.tb_sync);
@@ -152,13 +162,11 @@
 		return -EBUSY;
 	}
 	/* Make sure there isn't a perf-cnt interrupt waiting */
-	scdperfcnt = bus_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+	scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
 	/* Disable and clear counters, override SRC_1 */
-	bus_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) |
-		   M_SPC_CFG_ENABLE |
-		   M_SPC_CFG_CLEAR |
-		   V_SPC_CFG_SRC1(1),
-		   IOADDR(A_SCD_PERF_CNT_CFG));
+	__raw_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) |
+		     M_SPC_CFG_ENABLE | M_SPC_CFG_CLEAR | V_SPC_CFG_SRC1(1),
+		     IOADDR(A_SCD_PERF_CNT_CFG));
 
 	/* We grab this interrupt to prevent others from trying to use
            it, even though we don't want to service the interrupts
@@ -172,55 +180,55 @@
 	/* I need the core to mask these, but the interrupt mapper to
 	   pass them through.  I am exploiting my knowledge that
 	   cp0_status masks out IP[5]. krw */
-	bus_writeq(K_INT_MAP_I3,
-		   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-			  (K_INT_PERF_CNT << 3)));
+	__raw_writeq(K_INT_MAP_I3,
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+			    (K_INT_PERF_CNT << 3)));
 
 	/* Initialize address traps */
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_1));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_2));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_3));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_1));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_2));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_3));
 
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3));
 
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2));
-	bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2));
+	__raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
 
 	/* Initialize Trace Event 0-7 */
 	//				when interrupt
-	bus_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
+	__raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
 
 	/* Initialize Trace Sequence 0-7 */
 	//				     Start on event 0 (interrupt)
-	bus_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
-		   IOADDR(A_SCD_TRACE_SEQUENCE_0));
+	__raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
+		     IOADDR(A_SCD_TRACE_SEQUENCE_0));
 	//			  dsamp when d used | asamp when a used
-	bus_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
-		   K_SCD_TRSEQ_TRIGGER_ALL,
-		   IOADDR(A_SCD_TRACE_SEQUENCE_1));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6));
-	bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
+	__raw_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
+		     K_SCD_TRSEQ_TRIGGER_ALL,
+		     IOADDR(A_SCD_TRACE_SEQUENCE_1));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6));
+	__raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
 
 	/* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */
-	bus_writeq((1ULL << K_INT_PERF_CNT),
-		   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
+	__raw_writeq(1ULL << K_INT_PERF_CNT,
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
 
 	arm_tb();
 
@@ -231,6 +239,7 @@
 
 int sbprof_zbprof_stop(void)
 {
+	DEFINE_WAIT(wait);
 	DBG(printk(DEVNAME ": stopping\n"));
 
 	if (sbp.tb_enable) {
@@ -240,7 +249,9 @@
 		   this sleep happens. */
 		if (sbp.tb_armed) {
 			DBG(printk(DEVNAME ": wait for disarm\n"));
-			interruptible_sleep_on(&sbp.tb_sync);
+			prepare_to_wait(&sbp.tb_sync, &wait, TASK_INTERRUPTIBLE);
+			schedule();
+			finish_wait(&sbp.tb_sync, &wait);
 			DBG(printk(DEVNAME ": disarm complete\n"));
 		}
 		free_irq(K_INT_TRACE_FREEZE, &sbp);
@@ -333,13 +344,13 @@
 	return count;
 }
 
-static int sbprof_tb_ioctl(struct inode *inode,
-			   struct file *filp,
-			   unsigned int command,
-			   unsigned long arg)
+static long sbprof_tb_ioctl(struct file *filp,
+			    unsigned int command,
+			    unsigned long arg)
 {
 	int error = 0;
 
+	lock_kernel();
 	switch (command) {
 	case SBPROF_ZBSTART:
 		error = sbprof_zbprof_start(filp);
@@ -348,13 +359,17 @@
 		error = sbprof_zbprof_stop();
 		break;
 	case SBPROF_ZBWAITFULL:
-		interruptible_sleep_on(&sbp.tb_read);
+		DEFINE_WAIT(wait);
+		prepare_to_wait(&sbp.tb_read, &wait, TASK_INTERRUPTIBLE);
+		schedule();
+		finish_wait(&sbp.tb_read, &wait);
 		/* XXXKW check if interrupted? */
 		return put_user(TB_FULL, (int *) arg);
 	default:
 		error = -EINVAL;
 		break;
 	}
+	unlock_kernel();
 
 	return error;
 }
@@ -364,7 +379,8 @@
 	.open		= sbprof_tb_open,
 	.release	= sbprof_tb_release,
 	.read		= sbprof_tb_read,
-	.ioctl		= sbprof_tb_ioctl,
+	.unlocked_ioctl	= sbprof_tb_ioctl,
+	.compat_ioctl	= sbprof_tb_ioctl,
 	.mmap		= NULL,
 };
 
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c
index 1a97e31..482dee0 100644
--- a/arch/mips/sibyte/sb1250/bus_watcher.c
+++ b/arch/mips/sibyte/sb1250/bus_watcher.c
@@ -189,7 +189,7 @@
 
 	for (i=0; i<256*6; i++)
 		printk("%016llx\n",
-		       (unsigned long long)bus_readq(IOADDR(A_SCD_TRACE_READ)));
+		       (long long)__raw_readq(IOADDR(A_SCD_TRACE_READ)));
 
 	csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
 	csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 2725b26..589537b 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -53,7 +53,7 @@
 static unsigned int startup_sb1250_irq(unsigned int irq);
 static void ack_sb1250_irq(unsigned int irq);
 #ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, unsigned long mask);
+static void sb1250_set_affinity(unsigned int irq, cpumask_t mask);
 #endif
 
 #ifdef CONFIG_SIBYTE_HAS_LDT
@@ -71,17 +71,15 @@
 #endif
 
 static struct hw_interrupt_type sb1250_irq_type = {
-	"SB1250-IMR",
-	startup_sb1250_irq,
-	shutdown_sb1250_irq,
-	enable_sb1250_irq,
-	disable_sb1250_irq,
-	ack_sb1250_irq,
-	end_sb1250_irq,
+	.typename = "SB1250-IMR",
+	.startup = startup_sb1250_irq,
+	.shutdown = shutdown_sb1250_irq,
+	.enable = enable_sb1250_irq,
+	.disable = disable_sb1250_irq,
+	.ack = ack_sb1250_irq,
+	.end = end_sb1250_irq,
 #ifdef CONFIG_SMP
-	sb1250_set_affinity
-#else
-	NULL
+	.set_affinity = sb1250_set_affinity
 #endif
 };
 
@@ -96,11 +94,11 @@
 	u64 cur_ints;
 
 	spin_lock_irqsave(&sb1250_imr_lock, flags);
-	cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
-				      R_IMR_INTERRUPT_MASK));
+	cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
+					R_IMR_INTERRUPT_MASK));
 	cur_ints |= (((u64) 1) << irq);
-	__bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
-				      R_IMR_INTERRUPT_MASK));
+	____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+					R_IMR_INTERRUPT_MASK));
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
 }
 
@@ -110,32 +108,25 @@
 	u64 cur_ints;
 
 	spin_lock_irqsave(&sb1250_imr_lock, flags);
-	cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
-				      R_IMR_INTERRUPT_MASK));
+	cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
+					R_IMR_INTERRUPT_MASK));
 	cur_ints &= ~(((u64) 1) << irq);
-	__bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
-				      R_IMR_INTERRUPT_MASK));
+	____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+					R_IMR_INTERRUPT_MASK));
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
 }
 
 #ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, unsigned long mask)
+static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
 {
 	int i = 0, old_cpu, cpu, int_on;
 	u64 cur_ints;
 	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	while (mask) {
-		if (mask & 1) {
-			mask >>= 1;
-			break;
-		}
-		mask >>= 1;
-		i++;
-	}
+	i = first_cpu(mask);
 
-	if (mask) {
+	if (cpus_weight(mask) > 1) {
 		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
 		return;
 	}
@@ -149,23 +140,23 @@
 
 	/* Swizzle each CPU's IMR (but leave the IP selection alone) */
 	old_cpu = sb1250_irq_owner[irq];
-	cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(old_cpu) +
-			       R_IMR_INTERRUPT_MASK));
+	cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(old_cpu) +
+					R_IMR_INTERRUPT_MASK));
 	int_on = !(cur_ints & (((u64) 1) << irq));
 	if (int_on) {
 		/* If it was on, mask it */
 		cur_ints |= (((u64) 1) << irq);
-		__bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) +
-					      R_IMR_INTERRUPT_MASK));
+		____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) +
+					R_IMR_INTERRUPT_MASK));
 	}
 	sb1250_irq_owner[irq] = cpu;
 	if (int_on) {
 		/* unmask for the new CPU */
-		cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
-				       R_IMR_INTERRUPT_MASK));
+		cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
+					R_IMR_INTERRUPT_MASK));
 		cur_ints &= ~(((u64) 1) << irq);
-		__bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
-					      R_IMR_INTERRUPT_MASK));
+		____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+					R_IMR_INTERRUPT_MASK));
 	}
 	spin_unlock(&sb1250_imr_lock);
 	spin_unlock_irqrestore(&desc->lock, flags);
@@ -208,8 +199,8 @@
 	 * deliver the interrupts to all CPUs (which makes affinity
 	 * changing easier for us)
 	 */
-	pending = bus_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
-						  R_IMR_LDT_INTERRUPT)));
+	pending = __raw_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
+						    R_IMR_LDT_INTERRUPT)));
 	pending &= ((u64)1 << (irq));
 	if (pending) {
 		int i;
@@ -224,8 +215,8 @@
 			 * Clear for all CPUs so an affinity switch
 			 * doesn't find an old status
 			 */
-			bus_writeq(pending,
-				   IOADDR(A_IMR_REGISTER(cpu,
+			__raw_writeq(pending,
+				     IOADDR(A_IMR_REGISTER(cpu,
 						R_IMR_LDT_INTERRUPT_CLR)));
 		}
 
@@ -340,12 +331,14 @@
 
 	/* Default everything to IP2 */
 	for (i = 0; i < SB1250_NR_IRQS; i++) {	/* was I0 */
-		bus_writeq(IMR_IP2_VAL,
-			   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-				  (i << 3)));
-		bus_writeq(IMR_IP2_VAL,
-			   IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
-				  (i << 3)));
+		__raw_writeq(IMR_IP2_VAL,
+			     IOADDR(A_IMR_REGISTER(0,
+						   R_IMR_INTERRUPT_MAP_BASE) +
+				    (i << 3)));
+		__raw_writeq(IMR_IP2_VAL,
+			     IOADDR(A_IMR_REGISTER(1,
+						   R_IMR_INTERRUPT_MAP_BASE) +
+				    (i << 3)));
 	}
 
 	init_sb1250_irqs();
@@ -355,23 +348,23 @@
 	 * inter-cpu messages
 	 */
 	/* Was I1 */
-	bus_writeq(IMR_IP3_VAL,
-		   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-			  (K_INT_MBOX_0 << 3)));
-	bus_writeq(IMR_IP3_VAL,
-		   IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
-			  (K_INT_MBOX_0 << 3)));
+	__raw_writeq(IMR_IP3_VAL,
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+			    (K_INT_MBOX_0 << 3)));
+	__raw_writeq(IMR_IP3_VAL,
+		     IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
+			    (K_INT_MBOX_0 << 3)));
 
 	/* Clear the mailboxes.  The firmware may leave them dirty */
-	bus_writeq(0xffffffffffffffffULL,
-		   IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
-	bus_writeq(0xffffffffffffffffULL,
-		   IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
+	__raw_writeq(0xffffffffffffffffULL,
+		     IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
+	__raw_writeq(0xffffffffffffffffULL,
+		     IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
 
 	/* Mask everything except the mailbox registers for both cpus */
 	tmp = ~((u64) 0) ^ (((u64) 1) << K_INT_MBOX_0);
-	bus_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
-	bus_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
+	__raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
+	__raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
 
 	sb1250_steal_irq(K_INT_MBOX_0);
 
@@ -396,12 +389,14 @@
 		sb1250_duart_present[kgdb_port] = 0;
 #endif
 		/* Setup uart 1 settings, mapper */
-		bus_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
+		__raw_writeq(M_DUART_IMR_BRK,
+			     IOADDR(A_DUART_IMRREG(kgdb_port)));
 
 		sb1250_steal_irq(kgdb_irq);
-		bus_writeq(IMR_IP6_VAL,
-			   IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
-				  (kgdb_irq<<3)));
+		__raw_writeq(IMR_IP6_VAL,
+			     IOADDR(A_IMR_REGISTER(0,
+						   R_IMR_INTERRUPT_MAP_BASE) +
+				    (kgdb_irq << 3)));
 		sb1250_unmask_irq(0, kgdb_irq);
 	}
 #endif
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index f8c605b..df2e266 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -153,7 +153,7 @@
 	int bad_config = 0;
 
 	sb1_pass = read_c0_prid() & 0xff;
-	sys_rev = bus_readq(IOADDR(A_SCD_SYSTEM_REVISION));
+	sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
 	soc_type = SYS_SOC_TYPE(sys_rev);
 	soc_pass = G_SYS_REVISION(sys_rev);
 
@@ -162,7 +162,7 @@
 		machine_restart(NULL);
 	}
 
-	plldiv = G_SYS_PLL_DIV(bus_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+	plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
 	zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
 
 	prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index be91b39..f859db0 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -29,18 +29,18 @@
 #include <asm/sibyte/sb1250_int.h>
 
 static void *mailbox_set_regs[] = {
-	(void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU),
-	(void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU)
+	IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU),
+	IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU)
 };
 
 static void *mailbox_clear_regs[] = {
-	(void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU),
-	(void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU)
+	IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU),
+	IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU)
 };
 
 static void *mailbox_regs[] = {
-	(void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU),
-	(void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU)
+	IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU),
+	IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU)
 };
 
 /*
@@ -73,7 +73,7 @@
  */
 void core_send_ipi(int cpu, unsigned int action)
 {
-	bus_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
+	__raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
 }
 
 void sb1250_mailbox_interrupt(struct pt_regs *regs)
@@ -83,10 +83,10 @@
 
 	kstat_this_cpu.irqs[K_INT_MBOX_0]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
-	action = (__bus_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
+	action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
 
 	/* Clear the mailbox to clear the interrupt */
-	__bus_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
+	____raw_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
 
 	/*
 	 * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 8b4c848..511c89d 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -67,24 +67,24 @@
 	sb1250_mask_irq(cpu, irq);
 
 	/* Map the timer interrupt to ip[4] of this cpu */
-	bus_writeq(IMR_IP4_VAL,
-		   IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
-			  (irq << 3)));
+	__raw_writeq(IMR_IP4_VAL,
+		     IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
+			    (irq << 3)));
 
 	/* the general purpose timer ticks at 1 Mhz independent if the rest of the system */
 	/* Disable the timer and set up the count */
-	bus_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+	__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 #ifdef CONFIG_SIMULATION
-	bus_writeq(50000 / HZ,
-		   IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+	__raw_writeq(50000 / HZ,
+		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #else
-	bus_writeq(1000000/HZ,
-		   IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+	__raw_writeq(1000000 / HZ,
+		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
 #endif
 
 	/* Set the timer running */
-	bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
-		   IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+	__raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
 	sb1250_unmask_irq(cpu, irq);
 	sb1250_steal_irq(irq);
@@ -100,25 +100,25 @@
 
 void sb1250_timer_interrupt(struct pt_regs *regs)
 {
-	extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
 	int cpu = smp_processor_id();
 	int irq = K_INT_TIMER_0 + cpu;
 
 	/* Reset the timer */
-	__bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
-		     IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+	____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+		       IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
-	/*
-	 * CPU 0 handles the global timer interrupt job
-	 */
 	if (cpu == 0) {
+		/*
+		 * CPU 0 handles the global timer interrupt job
+		 */
 		ll_timer_interrupt(irq, regs);
 	}
-
-	/*
-	 * every CPU should do profiling and process accouting
-	 */
-	ll_local_timer_interrupt(irq, regs);
+	else {
+		/*
+		 * other CPUs should just do profiling and process accounting
+		 */
+		ll_local_timer_interrupt(irq, regs);
+	}
 }
 
 /*
@@ -130,7 +130,7 @@
 unsigned long sb1250_gettimeoffset(void)
 {
 	unsigned long count =
-		bus_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+		__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
 
 	return 1000000/HZ - count;
  }
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index a686bb7..5b4fc26 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -82,59 +82,60 @@
 #define M41T81REG_SQW	0x13		/* square wave register */
 
 #define M41T81_CCR_ADDRESS	0x68
-#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
+
+#define SMB_CSR(reg)	IOADDR(A_SMB_REGISTER(1, reg))
 
 static int m41t81_read(uint8_t addr)
 {
-	while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+	while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
 		;
 
-	bus_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
-	bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE),
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
+	__raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE,
+		     SMB_CSR(R_SMB_START));
 
-	while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+	while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
 		;
 
-	bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+		     SMB_CSR(R_SMB_START));
 
-	while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+	while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
 		;
 
-	if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+	if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
 		/* Clear error bit by writing a 1 */
-		bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+		__raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
 		return -1;
 	}
 
-	return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+	return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
 }
 
 static int m41t81_write(uint8_t addr, int b)
 {
-	while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+	while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
 		;
 
-	bus_writeq((addr & 0xFF), SMB_CSR(R_SMB_CMD));
-	bus_writeq((b & 0xff), SMB_CSR(R_SMB_DATA));
-	bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
+	__raw_writeq(b & 0xff, SMB_CSR(R_SMB_DATA));
+	__raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+		     SMB_CSR(R_SMB_START));
 
-	while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+	while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
 		;
 
-	if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+	if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
 		/* Clear error bit by writing a 1 */
-		bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+		__raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
 		return -1;
 	}
 
 	/* read the same byte again to make sure it is written */
-	bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+		     SMB_CSR(R_SMB_START));
 
-	while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+	while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
 		;
 
 	return 0;
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
index 981d21f..d9ff932 100644
--- a/arch/mips/sibyte/swarm/rtc_xicor1241.c
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -57,52 +57,52 @@
 
 #define X1241_CCR_ADDRESS	0x6F
 
-#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
+#define SMB_CSR(reg)	IOADDR(A_SMB_REGISTER(1, reg))
 
 static int xicor_read(uint8_t addr)
 {
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-	bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
-	bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
-	bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
+	__raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
+	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+		     SMB_CSR(R_SMB_START));
 
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-	bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+		     SMB_CSR(R_SMB_START));
 
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-        if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
                 /* Clear error bit by writing a 1 */
-                bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
                 return -1;
         }
 
-	return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+	return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
 }
 
 static int xicor_write(uint8_t addr, int b)
 {
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-	bus_writeq(addr, SMB_CSR(R_SMB_CMD));
-	bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
-	bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(addr, SMB_CSR(R_SMB_CMD));
+	__raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
+	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
+		     SMB_CSR(R_SMB_START));
 
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-        if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
                 /* Clear error bit by writing a 1 */
-                bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
                 return -1;
         } else {
 		return 0;
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 4daeaa4..b614ca0 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
  * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  *
  * This program is free software; you can redistribute it and/or
@@ -39,11 +39,23 @@
 #include <asm/time.h>
 #include <asm/traps.h>
 #include <asm/sibyte/sb1250.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 #include <asm/sibyte/sb1250_regs.h>
+#else
+#error invalid SiByte board configuation
+#endif
 #include <asm/sibyte/sb1250_genbus.h>
 #include <asm/sibyte/board.h>
 
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+extern void bcm1480_setup(void);
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 extern void sb1250_setup(void);
+#else
+#error invalid SiByte board configuation
+#endif
 
 extern int xicor_probe(void);
 extern int xicor_set_time(unsigned long);
@@ -66,27 +78,34 @@
          */
 
         /* We only need to setup the generic timer */
-        sb1250_time_init();
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+	bcm1480_time_init();
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+	sb1250_time_init();
+#else
+#error invalid SiByte board configuation
+#endif
 }
 
 int swarm_be_handler(struct pt_regs *regs, int is_fixup)
 {
 	if (!is_fixup && (regs->cp0_cause & 4)) {
 		/* Data bus error - print PA */
-#ifdef CONFIG_64BIT
-		printk("DBE physical address: %010lx\n",
+		printk("DBE physical address: %010Lx\n",
 		       __read_64bit_c0_register($26, 1));
-#else
-		printk("DBE physical address: %010llx\n",
-		       __read_64bit_c0_split($26, 1));
-#endif
 	}
 	return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
 }
 
-static int __init swarm_setup(void)
+void __init plat_setup(void)
 {
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+	bcm1480_setup();
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 	sb1250_setup();
+#else
+#error invalid SiByte board configuation
+#endif
 
 	panic_timeout = 5;  /* For debug.  */
 
@@ -133,12 +152,8 @@
        };
        /* XXXKW for CFE, get lines/cols from environment */
 #endif
-
-	return 0;
 }
 
-early_initcall(swarm_setup);
-
 #ifdef LEDS_PHYS
 
 #ifdef CONFIG_SIBYTE_CARMEL
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
index c1f1a9d..97c73c7 100644
--- a/arch/mips/sibyte/swarm/time.c
+++ b/arch/mips/sibyte/swarm/time.c
@@ -79,48 +79,48 @@
 
 static int xicor_read(uint8_t addr)
 {
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-	bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
-	bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
-	bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
+	__raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
+	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+		     SMB_CSR(R_SMB_START));
 
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-	bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+		     SMB_CSR(R_SMB_START));
 
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-        if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
                 /* Clear error bit by writing a 1 */
-                bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
                 return -1;
         }
 
-	return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+	return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
 }
 
 static int xicor_write(uint8_t addr, int b)
 {
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-	bus_writeq(addr, SMB_CSR(R_SMB_CMD));
-	bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
-	bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
-		   SMB_CSR(R_SMB_START));
+	__raw_writeq(addr, SMB_CSR(R_SMB_CMD));
+	__raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
+	__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
+		     SMB_CSR(R_SMB_START));
 
-        while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+        while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
                 ;
 
-        if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+        if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
                 /* Clear error bit by writing a 1 */
-                bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+                __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
                 return -1;
         } else {
 		return 0;
@@ -228,8 +228,8 @@
 	/* Establish communication with the Xicor 1241 RTC */
 	/* XXXKW how do I share the SMBus with the I2C subsystem? */
 
-	bus_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
-	bus_writeq(0, SMB_CSR(R_SMB_CONTROL));
+	__raw_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
+	__raw_writeq(0, SMB_CSR(R_SMB_CONTROL));
 
 	if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
 		printk("x1241: couldn't detect on SWARM SMBus 1\n");
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 141a310..952038a 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -58,14 +58,13 @@
 }
 
 static struct hw_interrupt_type pciasic_irq_type = {
-	"ASIC-PCI",
-	startup_pciasic_irq,
-	shutdown_pciasic_irq,
-	enable_pciasic_irq,
-	disable_pciasic_irq,
-	mask_and_ack_pciasic_irq,
-	end_pciasic_irq,
-	NULL
+	.typename = "ASIC-PCI",
+	.startup = startup_pciasic_irq,
+	.shutdown = shutdown_pciasic_irq,
+	.enable = enable_pciasic_irq,
+	.disable = disable_pciasic_irq,
+	.ack = mask_and_ack_pciasic_irq,
+	.end = end_pciasic_irq,
 };
 
 /*
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 1b3f8a0..262c856 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -167,7 +167,7 @@
 	rtc_set_time = mc146818_set_rtc_mmss;
 }
 
-static int __init sni_rm200_pci_setup(void)
+void __init plat_setup(void)
 {
 	sni_pcimt_detect();
 	sni_pcimt_sc_init();
@@ -196,8 +196,4 @@
 #ifdef CONFIG_PCI
 	register_pci_controller(&sni_controller);
 #endif
-
-	return 0;
 }
-
-early_initcall(sni_rm200_pci_setup);
diff --git a/arch/mips/tx4927/Kconfig b/arch/mips/tx4927/Kconfig
new file mode 100644
index 0000000..5fbbe12
--- /dev/null
+++ b/arch/mips/tx4927/Kconfig
@@ -0,0 +1,3 @@
+config TOSHIBA_FPCIB0
+	bool "FPCIB0 Backplane Support"
+	depends on TOSHIBA_RBTX4927
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
index 26d7c53..77c3b66 100644
--- a/arch/mips/tx4927/common/tx4927_setup.c
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -64,7 +64,7 @@
 }
 
 
-static void __init tx4927_setup(void)
+void __init plat_setup(void)
 {
 	board_time_init = tx4927_time_init;
 	board_timer_setup = tx4927_timer_setup;
@@ -76,12 +76,8 @@
 		toshiba_rbtx4927_setup();
 	}
 #endif
-
-	return;
 }
 
-early_initcall(tx4927_setup);
-
 void __init tx4927_time_init(void)
 {
 
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index fc07205..990fcb2 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -77,6 +77,11 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #endif
+#ifdef CONFIG_SERIAL_TXX9
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#endif
 
 #undef TOSHIBA_RBTX4927_SETUP_DEBUG
 
@@ -920,12 +925,30 @@
 
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_SERIAL_TXX9
+	{
+		extern int early_serial_txx9_setup(struct uart_port *port);
+		int i;
+		struct uart_port req;
+		for(i = 0; i < 2; i++) {
+			memset(&req, 0, sizeof(req));
+			req.line = i;
+			req.iotype = UPIO_MEM;
+			req.membase = (char *)(0xff1ff300 + i * 0x100);
+			req.mapbase = 0xff1ff300 + i * 0x100;
+			req.irq = 32 + i;
+			req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+			req.uartclk = 50000000;
+			early_serial_txx9_setup(&req);
+		}
+	}
 #ifdef CONFIG_SERIAL_TXX9_CONSOLE
         argptr = prom_getcmdline();
         if (strstr(argptr, "console=") == NULL) {
                 strcat(argptr, " console=ttyS0,38400");
         }
 #endif
+#endif
 
 #ifdef CONFIG_ROOT_NFS
         argptr = prom_getcmdline();
diff --git a/arch/mips/tx4938/Kconfig b/arch/mips/tx4938/Kconfig
new file mode 100644
index 0000000..d90e9cd
--- /dev/null
+++ b/arch/mips/tx4938/Kconfig
@@ -0,0 +1,24 @@
+if TOSHIBA_RBTX4938
+
+comment "Multiplex Pin Select"
+choice
+	prompt "PIO[58:61]"
+	default TOSHIBA_RBTX4938_MPLEX_PIO58_61
+
+config TOSHIBA_RBTX4938_MPLEX_PIO58_61
+	bool "PIO"
+config TOSHIBA_RBTX4938_MPLEX_NAND
+	bool "NAND"
+config TOSHIBA_RBTX4938_MPLEX_ATA
+	bool "ATA"
+
+endchoice
+
+config TX4938_NAND_BOOT
+	depends on EXPERIMENTAL && TOSHIBA_RBTX4938_MPLEX_NAND
+	bool "NAND Boot Support (EXPERIMENTAL)"
+	help
+	  This is only for Toshiba RBTX4938 reference board, which has NAND IPL.
+	  Select this option if you need to use NAND boot.
+
+endif
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
new file mode 100644
index 0000000..74c95c5
--- /dev/null
+++ b/arch/mips/tx4938/common/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for common code for Toshiba TX4927 based systems
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+obj-y	+= prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o
+obj-$(CONFIG_KGDB) += dbgio.o
+
diff --git a/arch/mips/tx4938/common/dbgio.c b/arch/mips/tx4938/common/dbgio.c
new file mode 100644
index 0000000..bea59ff
--- /dev/null
+++ b/arch/mips/tx4938/common/dbgio.c
@@ -0,0 +1,50 @@
+/*
+ * linux/arch/mips/tx4938/common/dbgio.c
+ *
+ * kgdb interface for gdb
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * Copyright 2005 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 as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ *
+ * Support for TX4938 in 2.6 - Hiroshi DOYU <Hiroshi_DOYU@montavista.co.jp>
+ */
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/tx4938/tx4938_mips.h>
+
+extern u8 txx9_sio_kdbg_rd(void);
+extern int txx9_sio_kdbg_wr( u8 ch );
+
+u8 getDebugChar(void)
+{
+	return (txx9_sio_kdbg_rd());
+}
+
+int putDebugChar(u8 byte)
+{
+	return (txx9_sio_kdbg_wr(byte));
+}
+
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
new file mode 100644
index 0000000..4f90d7f
--- /dev/null
+++ b/arch/mips/tx4938/common/irq.c
@@ -0,0 +1,424 @@
+/*
+ * linux/arch/mps/tx4938/common/irq.c
+ *
+ * Common tx4938 irq handler
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/irq.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/tx4938/rbtx4938.h>
+
+/**********************************************************************************/
+/* Forwad definitions for all pic's                                               */
+/**********************************************************************************/
+
+static unsigned int tx4938_irq_cp0_startup(unsigned int irq);
+static void tx4938_irq_cp0_shutdown(unsigned int irq);
+static void tx4938_irq_cp0_enable(unsigned int irq);
+static void tx4938_irq_cp0_disable(unsigned int irq);
+static void tx4938_irq_cp0_mask_and_ack(unsigned int irq);
+static void tx4938_irq_cp0_end(unsigned int irq);
+
+static unsigned int tx4938_irq_pic_startup(unsigned int irq);
+static void tx4938_irq_pic_shutdown(unsigned int irq);
+static void tx4938_irq_pic_enable(unsigned int irq);
+static void tx4938_irq_pic_disable(unsigned int irq);
+static void tx4938_irq_pic_mask_and_ack(unsigned int irq);
+static void tx4938_irq_pic_end(unsigned int irq);
+
+/**********************************************************************************/
+/* Kernel structs for all pic's                                                   */
+/**********************************************************************************/
+DEFINE_SPINLOCK(tx4938_cp0_lock);
+DEFINE_SPINLOCK(tx4938_pic_lock);
+
+#define TX4938_CP0_NAME "TX4938-CP0"
+static struct hw_interrupt_type tx4938_irq_cp0_type = {
+	.typename = TX4938_CP0_NAME,
+	.startup = tx4938_irq_cp0_startup,
+	.shutdown = tx4938_irq_cp0_shutdown,
+	.enable = tx4938_irq_cp0_enable,
+	.disable = tx4938_irq_cp0_disable,
+	.ack = tx4938_irq_cp0_mask_and_ack,
+	.end = tx4938_irq_cp0_end,
+	.set_affinity = NULL
+};
+
+#define TX4938_PIC_NAME "TX4938-PIC"
+static struct hw_interrupt_type tx4938_irq_pic_type = {
+	.typename = TX4938_PIC_NAME,
+	.startup = tx4938_irq_pic_startup,
+	.shutdown = tx4938_irq_pic_shutdown,
+	.enable = tx4938_irq_pic_enable,
+	.disable = tx4938_irq_pic_disable,
+	.ack = tx4938_irq_pic_mask_and_ack,
+	.end = tx4938_irq_pic_end,
+	.set_affinity = NULL
+};
+
+static struct irqaction tx4938_irq_pic_action = {
+	.handler = no_action,
+	.flags = 0,
+	.mask = CPU_MASK_NONE,
+	.name = TX4938_PIC_NAME
+};
+
+/**********************************************************************************/
+/* Functions for cp0                                                              */
+/**********************************************************************************/
+
+#define tx4938_irq_cp0_mask(irq) ( 1 << ( irq-TX4938_IRQ_CP0_BEG+8 ) )
+
+static void __init
+tx4938_irq_cp0_init(void)
+{
+	int i;
+
+	for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &tx4938_irq_cp0_type;
+	}
+
+	return;
+}
+
+static unsigned int
+tx4938_irq_cp0_startup(unsigned int irq)
+{
+	tx4938_irq_cp0_enable(irq);
+
+	return (0);
+}
+
+static void
+tx4938_irq_cp0_shutdown(unsigned int irq)
+{
+	tx4938_irq_cp0_disable(irq);
+}
+
+static void
+tx4938_irq_cp0_enable(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx4938_cp0_lock, flags);
+
+	set_c0_status(tx4938_irq_cp0_mask(irq));
+
+	spin_unlock_irqrestore(&tx4938_cp0_lock, flags);
+}
+
+static void
+tx4938_irq_cp0_disable(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx4938_cp0_lock, flags);
+
+	clear_c0_status(tx4938_irq_cp0_mask(irq));
+
+	spin_unlock_irqrestore(&tx4938_cp0_lock, flags);
+
+	return;
+}
+
+static void
+tx4938_irq_cp0_mask_and_ack(unsigned int irq)
+{
+	tx4938_irq_cp0_disable(irq);
+
+	return;
+}
+
+static void
+tx4938_irq_cp0_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		tx4938_irq_cp0_enable(irq);
+	}
+
+	return;
+}
+
+/**********************************************************************************/
+/* Functions for pic                                                              */
+/**********************************************************************************/
+
+u32
+tx4938_irq_pic_addr(int irq)
+{
+	/* MVMCP -- need to formulize this */
+	irq -= TX4938_IRQ_PIC_BEG;
+
+	switch (irq) {
+	case 17:
+	case 16:
+	case 1:
+	case 0:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL0));
+		}
+	case 19:
+	case 18:
+	case 3:
+	case 2:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL1));
+		}
+	case 21:
+	case 20:
+	case 5:
+	case 4:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL2));
+		}
+	case 23:
+	case 22:
+	case 7:
+	case 6:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL3));
+		}
+	case 25:
+	case 24:
+	case 9:
+	case 8:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL4));
+		}
+	case 27:
+	case 26:
+	case 11:
+	case 10:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL5));
+		}
+	case 29:
+	case 28:
+	case 13:
+	case 12:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL6));
+		}
+	case 31:
+	case 30:
+	case 15:
+	case 14:{
+			return (TX4938_MKA(TX4938_IRC_IRLVL7));
+		}
+	}
+
+	return (0);
+}
+
+u32
+tx4938_irq_pic_mask(int irq)
+{
+	/* MVMCP -- need to formulize this */
+	irq -= TX4938_IRQ_PIC_BEG;
+
+	switch (irq) {
+	case 31:
+	case 29:
+	case 27:
+	case 25:
+	case 23:
+	case 21:
+	case 19:
+	case 17:{
+			return (0x07000000);
+		}
+	case 30:
+	case 28:
+	case 26:
+	case 24:
+	case 22:
+	case 20:
+	case 18:
+	case 16:{
+			return (0x00070000);
+		}
+	case 15:
+	case 13:
+	case 11:
+	case 9:
+	case 7:
+	case 5:
+	case 3:
+	case 1:{
+			return (0x00000700);
+		}
+	case 14:
+	case 12:
+	case 10:
+	case 8:
+	case 6:
+	case 4:
+	case 2:
+	case 0:{
+			return (0x00000007);
+		}
+	}
+	return (0x00000000);
+}
+
+static void
+tx4938_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, unsigned set_bits)
+{
+	unsigned long val = 0;
+
+	val = TX4938_RD(pic_reg);
+	val &= (~clr_bits);
+	val |= (set_bits);
+	TX4938_WR(pic_reg, val);
+	mmiowb();
+	TX4938_RD(pic_reg);
+
+	return;
+}
+
+static void __init
+tx4938_irq_pic_init(void)
+{
+	unsigned long flags;
+	int i;
+
+	for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 2;
+		irq_desc[i].handler = &tx4938_irq_pic_type;
+	}
+
+	setup_irq(TX4938_IRQ_NEST_PIC_ON_CP0, &tx4938_irq_pic_action);
+
+	spin_lock_irqsave(&tx4938_pic_lock, flags);
+
+	TX4938_WR(0xff1ff640, 0x6);	/* irq level mask -- only accept hightest */
+	TX4938_WR(0xff1ff600, TX4938_RD(0xff1ff600) | 0x1);	/* irq enable */
+
+	spin_unlock_irqrestore(&tx4938_pic_lock, flags);
+
+	return;
+}
+
+static unsigned int
+tx4938_irq_pic_startup(unsigned int irq)
+{
+	tx4938_irq_pic_enable(irq);
+
+	return (0);
+}
+
+static void
+tx4938_irq_pic_shutdown(unsigned int irq)
+{
+	tx4938_irq_pic_disable(irq);
+
+	return;
+}
+
+static void
+tx4938_irq_pic_enable(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx4938_pic_lock, flags);
+
+	tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), 0,
+			      tx4938_irq_pic_mask(irq));
+
+	spin_unlock_irqrestore(&tx4938_pic_lock, flags);
+
+	return;
+}
+
+static void
+tx4938_irq_pic_disable(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tx4938_pic_lock, flags);
+
+	tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq),
+			      tx4938_irq_pic_mask(irq), 0);
+
+	spin_unlock_irqrestore(&tx4938_pic_lock, flags);
+
+	return;
+}
+
+static void
+tx4938_irq_pic_mask_and_ack(unsigned int irq)
+{
+	tx4938_irq_pic_disable(irq);
+
+	return;
+}
+
+static void
+tx4938_irq_pic_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		tx4938_irq_pic_enable(irq);
+	}
+
+	return;
+}
+
+/**********************************************************************************/
+/* Main init functions                                                            */
+/**********************************************************************************/
+
+void __init
+tx4938_irq_init(void)
+{
+	extern asmlinkage void tx4938_irq_handler(void);
+
+	tx4938_irq_cp0_init();
+	tx4938_irq_pic_init();
+	set_except_vector(0, tx4938_irq_handler);
+
+	return;
+}
+
+int
+tx4938_irq_nested(void)
+{
+	int sw_irq = 0;
+	u32 level2;
+
+	level2 = TX4938_RD(0xff1ff6a0);
+	if ((level2 & 0x10000) == 0) {
+		level2 &= 0x1f;
+		sw_irq = TX4938_IRQ_PIC_BEG + level2;
+		if (sw_irq == 26) {
+			{
+				extern int toshiba_rbtx4938_irq_nested(int sw_irq);
+				sw_irq = toshiba_rbtx4938_irq_nested(sw_irq);
+			}
+		}
+	}
+
+	wbflush();
+	return (sw_irq);
+}
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S
new file mode 100644
index 0000000..1b2f72b
--- /dev/null
+++ b/arch/mips/tx4938/common/irq_handler.S
@@ -0,0 +1,84 @@
+/*
+ * linux/arch/mips/tx4938/common/handler.S
+ *
+ * Primary interrupt handler for tx4938 based systems
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/tx4938/rbtx4938.h>
+
+
+		.align	5
+		NESTED(tx4938_irq_handler, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+
+		mfc0	t0, CP0_CAUSE
+		mfc0	t1, CP0_STATUS
+		and	t0, t1
+
+		andi	t1, t0, STATUSF_IP7	/* cpu timer */
+		bnez	t1, ll_ip7
+
+		/* IP6..IP3 multiplexed -- do not use */
+
+		andi	t1, t0, STATUSF_IP2	/* tx4938 pic */
+		bnez	t1, ll_ip2
+
+		andi	t1, t0, STATUSF_IP1	/* user line 1 */
+		bnez	t1, ll_ip1
+
+		andi	t1, t0, STATUSF_IP0	/* user line 0 */
+		bnez	t1, ll_ip0
+
+		.set	reorder
+
+		nop
+		END(tx4938_irq_handler)
+
+		.align	5
+
+
+ll_ip7:
+		li	a0, TX4938_IRQ_CPU_TIMER
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+
+ll_ip2:
+		jal	tx4938_irq_nested
+		nop
+		beqz	v0, goto_spurious_interrupt
+		nop
+		move	a0, v0
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+goto_spurious_interrupt:
+		j	ret_from_irq
+
+ll_ip1:
+		li	a0, TX4938_IRQ_USER1
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
+
+ll_ip0:
+		li	a0, TX4938_IRQ_USER0
+		move	a1, sp
+		jal	do_IRQ
+		j	ret_from_irq
diff --git a/arch/mips/tx4938/common/prom.c b/arch/mips/tx4938/common/prom.c
new file mode 100644
index 0000000..3189a65
--- /dev/null
+++ b/arch/mips/tx4938/common/prom.c
@@ -0,0 +1,129 @@
+/*
+ * linux/arch/mips/tx4938/common/prom.c
+ *
+ * common tx4938 memory interface
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/tx4938/tx4938.h>
+
+static unsigned int __init
+tx4938_process_sdccr(u64 * addr)
+{
+	u64 val;
+	unsigned int sdccr_ce;
+	unsigned int sdccr_rs;
+	unsigned int sdccr_cs;
+	unsigned int sdccr_mw;
+	unsigned int rs = 0;
+	unsigned int cs = 0;
+	unsigned int mw = 0;
+	unsigned int bc = 4;
+	unsigned int msize = 0;
+
+	val = (*((vu64 *) (addr)));
+
+	/* MVMCP -- need #defs for these bits masks */
+	sdccr_ce = ((val & (1 << 10)) >> 10);
+	sdccr_rs = ((val & (3 << 5)) >> 5);
+	sdccr_cs = ((val & (7 << 2)) >> 2);
+	sdccr_mw = ((val & (1 << 0)) >> 0);
+
+	if (sdccr_ce) {
+		switch (sdccr_rs) {
+		case 0:{
+				rs = 2048;
+				break;
+			}
+		case 1:{
+				rs = 4096;
+				break;
+			}
+		case 2:{
+				rs = 8192;
+				break;
+			}
+		default:{
+				rs = 0;
+				break;
+			}
+		}
+		switch (sdccr_cs) {
+		case 0:{
+				cs = 256;
+				break;
+			}
+		case 1:{
+				cs = 512;
+				break;
+			}
+		case 2:{
+				cs = 1024;
+				break;
+			}
+		case 3:{
+				cs = 2048;
+				break;
+			}
+		case 4:{
+				cs = 4096;
+				break;
+			}
+		default:{
+				cs = 0;
+				break;
+			}
+		}
+		switch (sdccr_mw) {
+		case 0:{
+				mw = 8;
+				break;
+			}	/* 8 bytes = 64 bits */
+		case 1:{
+				mw = 4;
+				break;
+			}	/* 4 bytes = 32 bits */
+		}
+	}
+
+	/*           bytes per chip    MB per chip          bank count */
+	msize = (((rs * cs * mw) / (1024 * 1024)) * (bc));
+
+	/* MVMCP -- bc hard coded to 4 from table 9.3.1     */
+	/*          boad supports bc=2 but no way to detect */
+
+	return (msize);
+}
+
+unsigned int __init
+tx4938_get_mem_size(void)
+{
+	unsigned int c0;
+	unsigned int c1;
+	unsigned int c2;
+	unsigned int c3;
+	unsigned int total;
+
+	/* MVMCP -- need #defs for these registers */
+	c0 = tx4938_process_sdccr((u64 *) 0xff1f8000);
+	c1 = tx4938_process_sdccr((u64 *) 0xff1f8008);
+	c2 = tx4938_process_sdccr((u64 *) 0xff1f8010);
+	c3 = tx4938_process_sdccr((u64 *) 0xff1f8018);
+	total = c0 + c1 + c2 + c3;
+
+	return (total);
+}
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
new file mode 100644
index 0000000..d249edb
--- /dev/null
+++ b/arch/mips/tx4938/common/rtc_rx5c348.c
@@ -0,0 +1,202 @@
+/*
+ * RTC routines for RICOH Rx5C348 SPI chip.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/time.h>
+#include <asm/time.h>
+#include <asm/tx4938/spi.h>
+
+#define	EPOCH		2000
+
+/* registers */
+#define Rx5C348_REG_SECOND	0
+#define Rx5C348_REG_MINUTE	1
+#define Rx5C348_REG_HOUR	2
+#define Rx5C348_REG_WEEK	3
+#define Rx5C348_REG_DAY	4
+#define Rx5C348_REG_MONTH	5
+#define Rx5C348_REG_YEAR	6
+#define Rx5C348_REG_ADJUST	7
+#define Rx5C348_REG_ALARM_W_MIN	8
+#define Rx5C348_REG_ALARM_W_HOUR	9
+#define Rx5C348_REG_ALARM_W_WEEK	10
+#define Rx5C348_REG_ALARM_D_MIN	11
+#define Rx5C348_REG_ALARM_D_HOUR	12
+#define Rx5C348_REG_CTL1	14
+#define Rx5C348_REG_CTL2	15
+
+/* register bits */
+#define Rx5C348_BIT_PM	0x20	/* REG_HOUR */
+#define Rx5C348_BIT_Y2K	0x80	/* REG_MONTH */
+#define Rx5C348_BIT_24H	0x20	/* REG_CTL1 */
+#define Rx5C348_BIT_XSTP	0x10	/* REG_CTL2 */
+
+/* commands */
+#define Rx5C348_CMD_W(addr)	(((addr) << 4) | 0x08)	/* single write */
+#define Rx5C348_CMD_R(addr)	(((addr) << 4) | 0x0c)	/* single read */
+#define Rx5C348_CMD_MW(addr)	(((addr) << 4) | 0x00)	/* burst write */
+#define Rx5C348_CMD_MR(addr)	(((addr) << 4) | 0x04)	/* burst read */
+
+static struct spi_dev_desc srtc_dev_desc = {
+	.baud 		= 1000000,	/* 1.0Mbps @ Vdd 2.0V */
+	.tcss		= 31,
+	.tcsh		= 1,
+	.tcsr		= 62,
+	/* 31us for Tcss (62us for Tcsr) is required for carry operation) */
+	.byteorder	= 1,		/* MSB-First */
+	.polarity	= 0,		/* High-Active */
+	.phase		= 1,		/* Shift-Then-Sample */
+
+};
+static int srtc_chipid;
+static int srtc_24h;
+
+static inline int
+spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
+{
+	unsigned char *inbufs[1], *outbufs[1];
+	unsigned int incounts[2], outcounts[2];
+	inbufs[0] = inbuf;
+	incounts[0] = count;
+	incounts[1] = 0;
+	outbufs[0] = outbuf;
+	outcounts[0] = count;
+	outcounts[1] = 0;
+	return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
+			   inbufs, incounts, outbufs, outcounts, 0);
+}
+
+/*
+ * Conversion between binary and BCD.
+ */
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+/* RTC-dependent code for time.c */
+
+static int
+rtc_rx5c348_set_time(unsigned long t)
+{
+	unsigned char inbuf[8];
+	struct rtc_time tm;
+	u8 year, month, day, hour, minute, second, century;
+
+	/* convert */
+	to_tm(t, &tm);
+
+	year = tm.tm_year % 100;
+	month = tm.tm_mon+1;	/* tm_mon starts from 0 to 11 */
+	day = tm.tm_mday;
+	hour = tm.tm_hour;
+	minute = tm.tm_min;
+	second = tm.tm_sec;
+	century = tm.tm_year / 100;
+
+	inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
+	BIN_TO_BCD(second);
+	inbuf[1] = second;
+	BIN_TO_BCD(minute);
+	inbuf[2] = minute;
+
+	if (srtc_24h) {
+		BIN_TO_BCD(hour);
+		inbuf[3] = hour;
+	} else {
+		/* hour 0 is AM12, noon is PM12 */
+		inbuf[3] = 0;
+		if (hour >= 12)
+			inbuf[3] = Rx5C348_BIT_PM;
+		hour = (hour + 11) % 12 + 1;
+		BIN_TO_BCD(hour);
+		inbuf[3] |= hour;
+	}
+	inbuf[4] = 0;	/* ignore week */
+	BIN_TO_BCD(day);
+	inbuf[5] = day;
+	BIN_TO_BCD(month);
+	inbuf[6] = month;
+	if (century >= 20)
+		inbuf[6] |= Rx5C348_BIT_Y2K;
+	BIN_TO_BCD(year);
+	inbuf[7] = year;
+	/* write in one transfer to avoid data inconsistency */
+	return spi_rtc_io(inbuf, NULL, 8);
+}
+
+static unsigned long
+rtc_rx5c348_get_time(void)
+{
+	unsigned char inbuf[8], outbuf[8];
+	unsigned int year, month, day, hour, minute, second;
+
+	inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
+	memset(inbuf + 1, 0, 7);
+	/* read in one transfer to avoid data inconsistency */
+	if (spi_rtc_io(inbuf, outbuf, 8))
+		return 0;
+	second = outbuf[1];
+	BCD_TO_BIN(second);
+	minute = outbuf[2];
+	BCD_TO_BIN(minute);
+	if (srtc_24h) {
+		hour = outbuf[3];
+		BCD_TO_BIN(hour);
+	} else {
+		hour = outbuf[3] & ~Rx5C348_BIT_PM;
+		BCD_TO_BIN(hour);
+		hour %= 12;
+		if (outbuf[3] & Rx5C348_BIT_PM)
+			hour += 12;
+	}
+	day = outbuf[5];
+	BCD_TO_BIN(day);
+	month = outbuf[6] & ~Rx5C348_BIT_Y2K;
+	BCD_TO_BIN(month);
+	year = outbuf[7];
+	BCD_TO_BIN(year);
+	year += EPOCH;
+
+	return mktime(year, month, day, hour, minute, second);
+}
+
+void __init
+rtc_rx5c348_init(int chipid)
+{
+	unsigned char inbuf[2], outbuf[2];
+	srtc_chipid = chipid;
+	/* turn on RTC if it is not on */
+	inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
+	inbuf[1] = 0;
+	spi_rtc_io(inbuf, outbuf, 2);
+	if (outbuf[1] & Rx5C348_BIT_XSTP) {
+		inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
+		inbuf[1] = 0;
+		spi_rtc_io(inbuf, NULL, 2);
+	}
+
+	inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
+	inbuf[1] = 0;
+	spi_rtc_io(inbuf, outbuf, 2);
+	if (outbuf[1] & Rx5C348_BIT_24H)
+		srtc_24h = 1;
+
+	/* set the function pointers */
+	rtc_get_time = rtc_rx5c348_get_time;
+	rtc_set_time = rtc_rx5c348_set_time;
+}
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c
new file mode 100644
index 0000000..fc99295
--- /dev/null
+++ b/arch/mips/tx4938/common/setup.c
@@ -0,0 +1,91 @@
+/*
+ * linux/arch/mips/tx4938/common/setup.c
+ *
+ * common tx4938 setup routines
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/irq.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/time.h>
+#include <asm/tx4938/rbtx4938.h>
+
+extern void toshiba_rbtx4938_setup(void);
+extern void rbtx4938_time_init(void);
+
+void __init tx4938_setup(void);
+void __init tx4938_time_init(void);
+void __init tx4938_timer_setup(struct irqaction *irq);
+void dump_cp0(char *key);
+
+void (*__wbflush) (void);
+
+static void
+tx4938_write_buffer_flush(void)
+{
+	mmiowb();
+
+	__asm__ __volatile__(
+		".set	push\n\t"
+		".set	noreorder\n\t"
+		"lw	$0,%0\n\t"
+		"nop\n\t"
+		".set	pop"
+		: /* no output */
+		: "m" (*(int *)KSEG1)
+		: "memory");
+}
+
+void __init
+plat_setup(void)
+{
+	board_time_init = tx4938_time_init;
+	board_timer_setup = tx4938_timer_setup;
+	__wbflush = tx4938_write_buffer_flush;
+	toshiba_rbtx4938_setup();
+}
+
+void __init
+tx4938_time_init(void)
+{
+	rbtx4938_time_init();
+}
+
+void __init
+tx4938_timer_setup(struct irqaction *irq)
+{
+	u32 count;
+	u32 c1;
+	u32 c2;
+
+	setup_irq(TX4938_IRQ_CPU_TIMER, irq);
+
+	c1 = read_c0_count();
+	count = c1 + (mips_hpt_frequency / HZ);
+	write_c0_compare(count);
+	c2 = read_c0_count();
+}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
new file mode 100644
index 0000000..2269412
--- /dev/null
+++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for common code for Toshiba TX4927 based systems
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+obj-y	+= prom.o setup.o irq.o spi_eeprom.o spi_txx9.o
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
new file mode 100644
index 0000000..230f5a9
--- /dev/null
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -0,0 +1,244 @@
+/*
+ * linux/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+ *
+ * Toshiba RBTX4938 specific interrupt handlers
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+/*
+IRQ  Device
+
+16   TX4938-CP0/00 Software 0
+17   TX4938-CP0/01 Software 1
+18   TX4938-CP0/02 Cascade TX4938-CP0
+19   TX4938-CP0/03 Multiplexed -- do not use
+20   TX4938-CP0/04 Multiplexed -- do not use
+21   TX4938-CP0/05 Multiplexed -- do not use
+22   TX4938-CP0/06 Multiplexed -- do not use
+23   TX4938-CP0/07 CPU TIMER
+
+24   TX4938-PIC/00
+25   TX4938-PIC/01
+26   TX4938-PIC/02 Cascade RBTX4938-IOC
+27   TX4938-PIC/03 RBTX4938 RTL-8019AS Ethernet
+28   TX4938-PIC/04
+29   TX4938-PIC/05 TX4938 ETH1
+30   TX4938-PIC/06 TX4938 ETH0
+31   TX4938-PIC/07
+32   TX4938-PIC/08 TX4938 SIO 0
+33   TX4938-PIC/09 TX4938 SIO 1
+34   TX4938-PIC/10 TX4938 DMA0
+35   TX4938-PIC/11 TX4938 DMA1
+36   TX4938-PIC/12 TX4938 DMA2
+37   TX4938-PIC/13 TX4938 DMA3
+38   TX4938-PIC/14
+39   TX4938-PIC/15
+40   TX4938-PIC/16 TX4938 PCIC
+41   TX4938-PIC/17 TX4938 TMR0
+42   TX4938-PIC/18 TX4938 TMR1
+43   TX4938-PIC/19 TX4938 TMR2
+44   TX4938-PIC/20
+45   TX4938-PIC/21
+46   TX4938-PIC/22 TX4938 PCIERR
+47   TX4938-PIC/23
+48   TX4938-PIC/24
+49   TX4938-PIC/25
+50   TX4938-PIC/26
+51   TX4938-PIC/27
+52   TX4938-PIC/28
+53   TX4938-PIC/29
+54   TX4938-PIC/30
+55   TX4938-PIC/31 TX4938 SPI
+
+56 RBTX4938-IOC/00 PCI-D
+57 RBTX4938-IOC/01 PCI-C
+58 RBTX4938-IOC/02 PCI-B
+59 RBTX4938-IOC/03 PCI-A
+60 RBTX4938-IOC/04 RTC
+61 RBTX4938-IOC/05 ATA
+62 RBTX4938-IOC/06 MODEM
+63 RBTX4938-IOC/07 SWINT
+*/
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <linux/version.h>
+#include <linux/bootmem.h>
+#include <asm/tx4938/rbtx4938.h>
+
+static unsigned int toshiba_rbtx4938_irq_ioc_startup(unsigned int irq);
+static void toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq);
+static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
+static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
+static void toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq);
+static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq);
+
+DEFINE_SPINLOCK(toshiba_rbtx4938_ioc_lock);
+
+#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
+static struct hw_interrupt_type toshiba_rbtx4938_irq_ioc_type = {
+	.typename = TOSHIBA_RBTX4938_IOC_NAME,
+	.startup = toshiba_rbtx4938_irq_ioc_startup,
+	.shutdown = toshiba_rbtx4938_irq_ioc_shutdown,
+	.enable = toshiba_rbtx4938_irq_ioc_enable,
+	.disable = toshiba_rbtx4938_irq_ioc_disable,
+	.ack = toshiba_rbtx4938_irq_ioc_mask_and_ack,
+	.end = toshiba_rbtx4938_irq_ioc_end,
+	.set_affinity = NULL
+};
+
+#define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000
+#define TOSHIBA_RBTX4938_IOC_INTR_STAT 0xb7f0200a
+
+int
+toshiba_rbtx4938_irq_nested(int sw_irq)
+{
+	u8 level3;
+
+	level3 = reg_rd08(TOSHIBA_RBTX4938_IOC_INTR_STAT) & 0xff;
+	if (level3) {
+		/* must use fls so onboard ATA has priority */
+		sw_irq = TOSHIBA_RBTX4938_IRQ_IOC_BEG + fls(level3) - 1;
+	}
+
+	wbflush();
+	return sw_irq;
+}
+
+static struct irqaction toshiba_rbtx4938_irq_ioc_action = {
+	.handler = no_action,
+	.flags = 0,
+	.mask = CPU_MASK_NONE,
+	.name = TOSHIBA_RBTX4938_IOC_NAME,
+};
+
+/**********************************************************************************/
+/* Functions for ioc                                                              */
+/**********************************************************************************/
+static void __init
+toshiba_rbtx4938_irq_ioc_init(void)
+{
+	int i;
+
+	for (i = TOSHIBA_RBTX4938_IRQ_IOC_BEG;
+	     i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 3;
+		irq_desc[i].handler = &toshiba_rbtx4938_irq_ioc_type;
+	}
+
+	setup_irq(RBTX4938_IRQ_IOCINT,
+		  &toshiba_rbtx4938_irq_ioc_action);
+}
+
+static unsigned int
+toshiba_rbtx4938_irq_ioc_startup(unsigned int irq)
+{
+	toshiba_rbtx4938_irq_ioc_enable(irq);
+
+	return 0;
+}
+
+static void
+toshiba_rbtx4938_irq_ioc_shutdown(unsigned int irq)
+{
+	toshiba_rbtx4938_irq_ioc_disable(irq);
+}
+
+static void
+toshiba_rbtx4938_irq_ioc_enable(unsigned int irq)
+{
+	unsigned long flags;
+	volatile unsigned char v;
+
+	spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags);
+
+	v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
+	v |= (1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
+	TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
+	mmiowb();
+	TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
+
+	spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags);
+}
+
+static void
+toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
+{
+	unsigned long flags;
+	volatile unsigned char v;
+
+	spin_lock_irqsave(&toshiba_rbtx4938_ioc_lock, flags);
+
+	v = TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
+	v &= ~(1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG));
+	TX4938_WR08(TOSHIBA_RBTX4938_IOC_INTR_ENAB, v);
+	mmiowb();
+	TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
+
+	spin_unlock_irqrestore(&toshiba_rbtx4938_ioc_lock, flags);
+}
+
+static void
+toshiba_rbtx4938_irq_ioc_mask_and_ack(unsigned int irq)
+{
+	toshiba_rbtx4938_irq_ioc_disable(irq);
+}
+
+static void
+toshiba_rbtx4938_irq_ioc_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		toshiba_rbtx4938_irq_ioc_enable(irq);
+	}
+}
+
+extern void __init txx9_spi_irqinit(int irc_irq);
+
+void __init arch_init_irq(void)
+{
+	extern void tx4938_irq_init(void);
+
+	/* Now, interrupt control disabled, */
+	/* all IRC interrupts are masked, */
+	/* all IRC interrupt mode are Low Active. */
+
+	/* mask all IOC interrupts */
+	*rbtx4938_imask_ptr = 0;
+
+	/* clear SoftInt interrupts */
+	*rbtx4938_softint_ptr = 0;
+	tx4938_irq_init();
+	toshiba_rbtx4938_irq_ioc_init();
+	/* Onboard 10M Ether: High Active */
+	TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040);
+
+	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) {
+		txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI);
+        }
+
+	wbflush();
+}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/prom.c b/arch/mips/tx4938/toshiba_rbtx4938/prom.c
new file mode 100644
index 0000000..7df8b32
--- /dev/null
+++ b/arch/mips/tx4938/toshiba_rbtx4938/prom.c
@@ -0,0 +1,78 @@
+/*
+ * linux/arch/mips/tx4938/toshiba_rbtx4938/prom.c
+ *
+ * rbtx4938 specific prom routines
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/tx4938/tx4938.h>
+
+void __init prom_init_cmdline(void)
+{
+	int argc = (int) fw_arg0;
+	char **argv = (char **) fw_arg1;
+	int i;
+
+	/* ignore all built-in args if any f/w args given */
+	if (argc > 1) {
+		*arcs_cmdline = '\0';
+	}
+
+	for (i = 1; i < argc; i++) {
+		if (i != 1) {
+			strcat(arcs_cmdline, " ");
+		}
+		strcat(arcs_cmdline, argv[i]);
+	}
+}
+
+void __init prom_init(void)
+{
+	extern int tx4938_get_mem_size(void);
+	int msize;
+#ifndef CONFIG_TX4938_NAND_BOOT
+	prom_init_cmdline();
+#endif
+	mips_machgroup = MACH_GROUP_TOSHIBA;
+	mips_machtype = MACH_TOSHIBA_RBTX4938;
+
+	msize = tx4938_get_mem_size();
+	add_memory_region(0, msize << 20, BOOT_MEM_RAM);
+
+	return;
+}
+
+unsigned long  __init prom_free_prom_memory(void)
+{
+	return 0;
+}
+
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+	return;
+}
+
+const char *get_system_type(void)
+{
+	return "Toshiba RBTX4938";
+}
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
new file mode 100644
index 0000000..9f1dcc8
--- /dev/null
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -0,0 +1,1035 @@
+/*
+ * linux/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+ *
+ * Setup pointers to hardware-dependent routines.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <asm/wbflush.h>
+#include <asm/reboot.h>
+#include <asm/irq.h>
+#include <asm/time.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/tx4938/rbtx4938.h>
+#ifdef CONFIG_SERIAL_TXX9
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#endif
+
+extern void rbtx4938_time_init(void) __init;
+extern char * __init prom_getcmdline(void);
+static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr);
+
+/* These functions are used for rebooting or halting the machine*/
+extern void rbtx4938_machine_restart(char *command);
+extern void rbtx4938_machine_halt(void);
+extern void rbtx4938_machine_power_off(void);
+
+/* clocks */
+unsigned int txx9_master_clock;
+unsigned int txx9_cpu_clock;
+unsigned int txx9_gbus_clock;
+
+unsigned long rbtx4938_ce_base[8];
+unsigned long rbtx4938_ce_size[8];
+int txboard_pci66_mode;
+static int tx4938_pcic_trdyto;	/* default: disabled */
+static int tx4938_pcic_retryto;	/* default: disabled */
+static int tx4938_ccfg_toeon = 1;
+
+struct tx4938_pcic_reg *pcicptrs[4] = {
+       tx4938_pcicptr  /* default setting for TX4938 */
+};
+
+static struct {
+	unsigned long base;
+	unsigned long size;
+} phys_regions[16] __initdata;
+static int num_phys_regions  __initdata;
+
+#define PHYS_REGION_MINSIZE	0x10000
+
+void rbtx4938_machine_halt(void)
+{
+        printk(KERN_NOTICE "System Halted\n");
+	local_irq_disable();
+
+	while (1)
+		__asm__(".set\tmips3\n\t"
+			"wait\n\t"
+			".set\tmips0");
+}
+
+void rbtx4938_machine_power_off(void)
+{
+        rbtx4938_machine_halt();
+        /* no return */
+}
+
+void rbtx4938_machine_restart(char *command)
+{
+	local_irq_disable();
+
+	printk("Rebooting...");
+	*rbtx4938_softresetlock_ptr = 1;
+	*rbtx4938_sfvol_ptr = 1;
+	*rbtx4938_softreset_ptr = 1;
+	wbflush();
+
+	while(1);
+}
+
+void __init
+txboard_add_phys_region(unsigned long base, unsigned long size)
+{
+	if (num_phys_regions >= ARRAY_SIZE(phys_regions)) {
+		printk("phys_region overflow\n");
+		return;
+	}
+	phys_regions[num_phys_regions].base = base;
+	phys_regions[num_phys_regions].size = size;
+	num_phys_regions++;
+}
+unsigned long __init
+txboard_find_free_phys_region(unsigned long begin, unsigned long end,
+			      unsigned long size)
+{
+	unsigned long base;
+	int i;
+
+	for (base = begin / size * size; base < end; base += size) {
+		for (i = 0; i < num_phys_regions; i++) {
+			if (phys_regions[i].size &&
+			    base <= phys_regions[i].base + (phys_regions[i].size - 1) &&
+			    base + (size - 1) >= phys_regions[i].base)
+				break;
+		}
+		if (i == num_phys_regions)
+			return base;
+	}
+	return 0;
+}
+unsigned long __init
+txboard_find_free_phys_region_shrink(unsigned long begin, unsigned long end,
+				     unsigned long *size)
+{
+	unsigned long sz, base;
+	for (sz = *size; sz >= PHYS_REGION_MINSIZE; sz /= 2) {
+		base = txboard_find_free_phys_region(begin, end, sz);
+		if (base) {
+			*size = sz;
+			return base;
+		}
+	}
+	return 0;
+}
+unsigned long __init
+txboard_request_phys_region_range(unsigned long begin, unsigned long end,
+				  unsigned long size)
+{
+	unsigned long base;
+	base = txboard_find_free_phys_region(begin, end, size);
+	if (base)
+		txboard_add_phys_region(base, size);
+	return base;
+}
+unsigned long __init
+txboard_request_phys_region(unsigned long size)
+{
+	unsigned long base;
+	unsigned long begin = 0, end = 0x20000000;	/* search low 512MB */
+	base = txboard_find_free_phys_region(begin, end, size);
+	if (base)
+		txboard_add_phys_region(base, size);
+	return base;
+}
+unsigned long __init
+txboard_request_phys_region_shrink(unsigned long *size)
+{
+	unsigned long base;
+	unsigned long begin = 0, end = 0x20000000;	/* search low 512MB */
+	base = txboard_find_free_phys_region_shrink(begin, end, size);
+	if (base)
+		txboard_add_phys_region(base, *size);
+	return base;
+}
+
+#ifdef CONFIG_PCI
+void __init
+tx4938_pcic_setup(struct tx4938_pcic_reg *pcicptr,
+		  struct pci_controller *channel,
+		  unsigned long pci_io_base,
+		  int extarb)
+{
+	int i;
+
+	/* Disable All Initiator Space */
+	pcicptr->pciccfg &= ~(TX4938_PCIC_PCICCFG_G2PMEN(0)|
+			      TX4938_PCIC_PCICCFG_G2PMEN(1)|
+			      TX4938_PCIC_PCICCFG_G2PMEN(2)|
+			      TX4938_PCIC_PCICCFG_G2PIOEN);
+
+	/* GB->PCI mappings */
+	pcicptr->g2piomask = (channel->io_resource->end - channel->io_resource->start) >> 4;
+	pcicptr->g2piogbase = pci_io_base |
+#ifdef __BIG_ENDIAN
+		TX4938_PCIC_G2PIOGBASE_ECHG
+#else
+		TX4938_PCIC_G2PIOGBASE_BSDIS
+#endif
+		;
+	pcicptr->g2piopbase = 0;
+	for (i = 0; i < 3; i++) {
+		pcicptr->g2pmmask[i] = 0;
+		pcicptr->g2pmgbase[i] = 0;
+		pcicptr->g2pmpbase[i] = 0;
+	}
+	if (channel->mem_resource->end) {
+		pcicptr->g2pmmask[0] = (channel->mem_resource->end - channel->mem_resource->start) >> 4;
+		pcicptr->g2pmgbase[0] = channel->mem_resource->start |
+#ifdef __BIG_ENDIAN
+			TX4938_PCIC_G2PMnGBASE_ECHG
+#else
+			TX4938_PCIC_G2PMnGBASE_BSDIS
+#endif
+			;
+		pcicptr->g2pmpbase[0] = channel->mem_resource->start;
+	}
+	/* PCI->GB mappings (I/O 256B) */
+	pcicptr->p2giopbase = 0; /* 256B */
+	pcicptr->p2giogbase = 0;
+	/* PCI->GB mappings (MEM 512MB (64MB on R1.x)) */
+	pcicptr->p2gm0plbase = 0;
+	pcicptr->p2gm0pubase = 0;
+	pcicptr->p2gmgbase[0] = 0 |
+		TX4938_PCIC_P2GMnGBASE_TMEMEN |
+#ifdef __BIG_ENDIAN
+		TX4938_PCIC_P2GMnGBASE_TECHG
+#else
+		TX4938_PCIC_P2GMnGBASE_TBSDIS
+#endif
+		;
+	/* PCI->GB mappings (MEM 16MB) */
+	pcicptr->p2gm1plbase = 0xffffffff;
+	pcicptr->p2gm1pubase = 0xffffffff;
+	pcicptr->p2gmgbase[1] = 0;
+	/* PCI->GB mappings (MEM 1MB) */
+	pcicptr->p2gm2pbase = 0xffffffff; /* 1MB */
+	pcicptr->p2gmgbase[2] = 0;
+
+	pcicptr->pciccfg &= TX4938_PCIC_PCICCFG_GBWC_MASK;
+	/* Enable Initiator Memory Space */
+	if (channel->mem_resource->end)
+		pcicptr->pciccfg |= TX4938_PCIC_PCICCFG_G2PMEN(0);
+	/* Enable Initiator I/O Space */
+	if (channel->io_resource->end)
+		pcicptr->pciccfg |= TX4938_PCIC_PCICCFG_G2PIOEN;
+	/* Enable Initiator Config */
+	pcicptr->pciccfg |=
+		TX4938_PCIC_PCICCFG_ICAEN |
+		TX4938_PCIC_PCICCFG_TCAR;
+
+	/* Do not use MEMMUL, MEMINF: YMFPCI card causes M_ABORT. */
+	pcicptr->pcicfg1 = 0;
+
+	pcicptr->g2ptocnt &= ~0xffff;
+
+	if (tx4938_pcic_trdyto >= 0) {
+		pcicptr->g2ptocnt &= ~0xff;
+		pcicptr->g2ptocnt |= (tx4938_pcic_trdyto & 0xff);
+	}
+
+	if (tx4938_pcic_retryto >= 0) {
+		pcicptr->g2ptocnt &= ~0xff00;
+		pcicptr->g2ptocnt |= ((tx4938_pcic_retryto<<8) & 0xff00);
+	}
+
+	/* Clear All Local Bus Status */
+	pcicptr->pcicstatus = TX4938_PCIC_PCICSTATUS_ALL;
+	/* Enable All Local Bus Interrupts */
+	pcicptr->pcicmask = TX4938_PCIC_PCICSTATUS_ALL;
+	/* Clear All Initiator Status */
+	pcicptr->g2pstatus = TX4938_PCIC_G2PSTATUS_ALL;
+	/* Enable All Initiator Interrupts */
+	pcicptr->g2pmask = TX4938_PCIC_G2PSTATUS_ALL;
+	/* Clear All PCI Status Error */
+	pcicptr->pcistatus =
+		(pcicptr->pcistatus & 0x0000ffff) |
+		(TX4938_PCIC_PCISTATUS_ALL << 16);
+	/* Enable All PCI Status Error Interrupts */
+	pcicptr->pcimask = TX4938_PCIC_PCISTATUS_ALL;
+
+	if (!extarb) {
+		/* Reset Bus Arbiter */
+		pcicptr->pbacfg = TX4938_PCIC_PBACFG_RPBA;
+		pcicptr->pbabm = 0;
+		/* Enable Bus Arbiter */
+		pcicptr->pbacfg = TX4938_PCIC_PBACFG_PBAEN;
+	}
+
+      /* PCIC Int => IRC IRQ16 */
+	pcicptr->pcicfg2 =
+		    (pcicptr->pcicfg2 & 0xffffff00) | TX4938_IR_PCIC;
+
+	pcicptr->pcistatus = PCI_COMMAND_MASTER |
+		PCI_COMMAND_MEMORY |
+		PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+}
+
+int __init
+tx4938_report_pciclk(void)
+{
+	unsigned long pcode = TX4938_REV_PCODE();
+	int pciclk = 0;
+	printk("TX%lx PCIC --%s PCICLK:",
+	       pcode,
+	       (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI66) ? " PCI66" : "");
+	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_PCICLKEN_ALL) {
+
+		switch ((unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIDIVMODE_MASK) {
+		case TX4938_CCFG_PCIDIVMODE_4:
+			pciclk = txx9_cpu_clock / 4; break;
+		case TX4938_CCFG_PCIDIVMODE_4_5:
+			pciclk = txx9_cpu_clock * 2 / 9; break;
+		case TX4938_CCFG_PCIDIVMODE_5:
+			pciclk = txx9_cpu_clock / 5; break;
+		case TX4938_CCFG_PCIDIVMODE_5_5:
+			pciclk = txx9_cpu_clock * 2 / 11; break;
+		case TX4938_CCFG_PCIDIVMODE_8:
+			pciclk = txx9_cpu_clock / 8; break;
+		case TX4938_CCFG_PCIDIVMODE_9:
+			pciclk = txx9_cpu_clock / 9; break;
+		case TX4938_CCFG_PCIDIVMODE_10:
+			pciclk = txx9_cpu_clock / 10; break;
+		case TX4938_CCFG_PCIDIVMODE_11:
+			pciclk = txx9_cpu_clock / 11; break;
+		}
+		printk("Internal(%dMHz)", pciclk / 1000000);
+	} else {
+		printk("External");
+		pciclk = -1;
+	}
+	printk("\n");
+	return pciclk;
+}
+
+void __init set_tx4938_pcicptr(int ch, struct tx4938_pcic_reg *pcicptr)
+{
+	pcicptrs[ch] = pcicptr;
+}
+
+struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch)
+{
+       return pcicptrs[ch];
+}
+
+static struct pci_dev *fake_pci_dev(struct pci_controller *hose,
+                                    int top_bus, int busnr, int devfn)
+{
+	static struct pci_dev dev;
+	static struct pci_bus bus;
+
+	dev.sysdata = (void *)hose;
+	dev.devfn = devfn;
+	bus.number = busnr;
+	bus.ops = hose->pci_ops;
+	bus.parent = NULL;
+	dev.bus = &bus;
+
+	return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type)                                    \
+static int early_##rw##_config_##size(struct pci_controller *hose,      \
+        int top_bus, int bus, int devfn, int offset, type value)        \
+{                                                                       \
+        return pci_##rw##_config_##size(                                \
+                fake_pci_dev(hose, top_bus, bus, devfn),                \
+                offset, value);                                         \
+}
+
+EARLY_PCI_OP(read, word, u16 *)
+
+int txboard_pci66_check(struct pci_controller *hose, int top_bus, int current_bus)
+{
+	u32 pci_devfn;
+	unsigned short vid;
+	int devfn_start = 0;
+	int devfn_stop = 0xff;
+	int cap66 = -1;
+	u16 stat;
+
+	printk("PCI: Checking 66MHz capabilities...\n");
+
+	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
+		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
+				       PCI_VENDOR_ID, &vid);
+
+		if (vid == 0xffff) continue;
+
+		/* check 66MHz capability */
+		if (cap66 < 0)
+			cap66 = 1;
+		if (cap66) {
+			early_read_config_word(hose, top_bus, current_bus, pci_devfn,
+					       PCI_STATUS, &stat);
+			if (!(stat & PCI_STATUS_66MHZ)) {
+				printk(KERN_DEBUG "PCI: %02x:%02x not 66MHz capable.\n",
+				       current_bus, pci_devfn);
+				cap66 = 0;
+				break;
+			}
+		}
+	}
+	return cap66 > 0;
+}
+
+int __init
+tx4938_pciclk66_setup(void)
+{
+	int pciclk;
+
+	/* Assert M66EN */
+	tx4938_ccfgptr->ccfg |= TX4938_CCFG_PCI66;
+	/* Double PCICLK (if possible) */
+	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_PCICLKEN_ALL) {
+		unsigned int pcidivmode =
+			tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIDIVMODE_MASK;
+		switch (pcidivmode) {
+		case TX4938_CCFG_PCIDIVMODE_8:
+		case TX4938_CCFG_PCIDIVMODE_4:
+			pcidivmode = TX4938_CCFG_PCIDIVMODE_4;
+			pciclk = txx9_cpu_clock / 4;
+			break;
+		case TX4938_CCFG_PCIDIVMODE_9:
+		case TX4938_CCFG_PCIDIVMODE_4_5:
+			pcidivmode = TX4938_CCFG_PCIDIVMODE_4_5;
+			pciclk = txx9_cpu_clock * 2 / 9;
+			break;
+		case TX4938_CCFG_PCIDIVMODE_10:
+		case TX4938_CCFG_PCIDIVMODE_5:
+			pcidivmode = TX4938_CCFG_PCIDIVMODE_5;
+			pciclk = txx9_cpu_clock / 5;
+			break;
+		case TX4938_CCFG_PCIDIVMODE_11:
+		case TX4938_CCFG_PCIDIVMODE_5_5:
+		default:
+			pcidivmode = TX4938_CCFG_PCIDIVMODE_5_5;
+			pciclk = txx9_cpu_clock * 2 / 11;
+			break;
+		}
+		tx4938_ccfgptr->ccfg =
+			(tx4938_ccfgptr->ccfg & ~TX4938_CCFG_PCIDIVMODE_MASK)
+			| pcidivmode;
+		printk(KERN_DEBUG "PCICLK: ccfg:%08lx\n",
+		       (unsigned long)tx4938_ccfgptr->ccfg);
+	} else {
+		pciclk = -1;
+	}
+	return pciclk;
+}
+
+extern struct pci_controller tx4938_pci_controller[];
+static int __init tx4938_pcibios_init(void)
+{
+	unsigned long mem_base[2];
+	unsigned long mem_size[2] = {TX4938_PCIMEM_SIZE_0,TX4938_PCIMEM_SIZE_1}; /* MAX 128M,64K */
+	unsigned long io_base[2];
+	unsigned long io_size[2] = {TX4938_PCIIO_SIZE_0,TX4938_PCIIO_SIZE_1}; /* MAX 16M,64K */
+	/* TX4938 PCIC1: 64K MEM/IO is enough for ETH0,ETH1 */
+	int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);
+
+	PCIBIOS_MIN_IO = 0x00001000UL;
+	PCIBIOS_MIN_MEM = 0x01000000UL;
+
+	mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);
+	io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);
+
+	printk("TX4938 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n",
+	       (unsigned short)(tx4938_pcicptr->pciid >> 16),
+	       (unsigned short)(tx4938_pcicptr->pciid & 0xffff),
+	       (unsigned short)(tx4938_pcicptr->pciccrev & 0xff),
+	       extarb ? "External" : "Internal");
+
+	/* setup PCI area */
+	tx4938_pci_controller[0].io_resource->start = io_base[0];
+	tx4938_pci_controller[0].io_resource->end = (io_base[0] + io_size[0]) - 1;
+	tx4938_pci_controller[0].mem_resource->start = mem_base[0];
+	tx4938_pci_controller[0].mem_resource->end = mem_base[0] + mem_size[0] - 1;
+
+	set_tx4938_pcicptr(0, tx4938_pcicptr);
+
+	register_pci_controller(&tx4938_pci_controller[0]);
+
+	if (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI66) {
+		printk("TX4938_CCFG_PCI66 already configured\n");
+		txboard_pci66_mode = -1; /* already configured */
+	}
+
+	/* Reset PCI Bus */
+	*rbtx4938_pcireset_ptr = 0;
+	/* Reset PCIC */
+	tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST;
+	if (txboard_pci66_mode > 0)
+		tx4938_pciclk66_setup();
+	mdelay(10);
+	/* clear PCIC reset */
+	tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST;
+	*rbtx4938_pcireset_ptr = 1;
+	wbflush();
+	tx4938_report_pcic_status1(tx4938_pcicptr);
+
+	tx4938_report_pciclk();
+	tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb);
+	if (txboard_pci66_mode == 0 &&
+	    txboard_pci66_check(&tx4938_pci_controller[0], 0, 0)) {
+		/* Reset PCI Bus */
+		*rbtx4938_pcireset_ptr = 0;
+		/* Reset PCIC */
+		tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST;
+		tx4938_pciclk66_setup();
+		mdelay(10);
+		/* clear PCIC reset */
+		tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST;
+		*rbtx4938_pcireset_ptr = 1;
+		wbflush();
+		/* Reinitialize PCIC */
+		tx4938_report_pciclk();
+		tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb);
+	}
+
+	mem_base[1] = txboard_request_phys_region_shrink(&mem_size[1]);
+	io_base[1] = txboard_request_phys_region_shrink(&io_size[1]);
+	/* Reset PCIC1 */
+	tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIC1RST;
+	/* PCI1DMD==0 => PCI1CLK==GBUSCLK/2 => PCI66 */
+	if (!(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI1DMD))
+		tx4938_ccfgptr->ccfg |= TX4938_CCFG_PCI1_66;
+	else
+		tx4938_ccfgptr->ccfg &= ~TX4938_CCFG_PCI1_66;
+	mdelay(10);
+	/* clear PCIC1 reset */
+	tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIC1RST;
+	tx4938_report_pcic_status1(tx4938_pcic1ptr);
+
+	printk("TX4938 PCIC1 -- DID:%04x VID:%04x RID:%02x",
+	       (unsigned short)(tx4938_pcic1ptr->pciid >> 16),
+	       (unsigned short)(tx4938_pcic1ptr->pciid & 0xffff),
+	       (unsigned short)(tx4938_pcic1ptr->pciccrev & 0xff));
+	printk("%s PCICLK:%dMHz\n",
+	       (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI1_66) ? " PCI66" : "",
+	       txx9_gbus_clock /
+	       ((tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI1DMD) ? 4 : 2) /
+	       1000000);
+
+	/* assumption: CPHYSADDR(mips_io_port_base) == io_base[0] */
+	tx4938_pci_controller[1].io_resource->start =
+		io_base[1] - io_base[0];
+	tx4938_pci_controller[1].io_resource->end =
+		io_base[1] - io_base[0] + io_size[1] - 1;
+	tx4938_pci_controller[1].mem_resource->start = mem_base[1];
+	tx4938_pci_controller[1].mem_resource->end =
+		mem_base[1] + mem_size[1] - 1;
+	set_tx4938_pcicptr(1, tx4938_pcic1ptr);
+
+	register_pci_controller(&tx4938_pci_controller[1]);
+
+	tx4938_pcic_setup(tx4938_pcic1ptr, &tx4938_pci_controller[1], io_base[1], extarb);
+
+	/* map ioport 0 to PCI I/O space address 0 */
+	set_io_port_base(KSEG1 + io_base[0]);
+
+	return 0;
+}
+
+arch_initcall(tx4938_pcibios_init);
+
+#endif /* CONFIG_PCI */
+
+/* SPI support */
+
+/* chip select for SPI devices */
+#define	SEEPROM1_CS	7	/* PIO7 */
+#define	SEEPROM2_CS	0	/* IOC */
+#define	SEEPROM3_CS	1	/* IOC */
+#define	SRTC_CS	2	/* IOC */
+
+static int rbtx4938_spi_cs_func(int chipid, int on)
+{
+	unsigned char bit;
+	switch (chipid) {
+	case RBTX4938_SEEPROM1_CHIPID:
+		if (on)
+			tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS);
+		else
+			tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
+		return 0;
+		break;
+	case RBTX4938_SEEPROM2_CHIPID:
+		bit = (1 << SEEPROM2_CS);
+		break;
+	case RBTX4938_SEEPROM3_CHIPID:
+		bit = (1 << SEEPROM3_CS);
+		break;
+	case RBTX4938_SRTC_CHIPID:
+		bit = (1 << SRTC_CS);
+		break;
+	default:
+		return -ENODEV;
+	}
+	/* bit1,2,4 are low active, bit3 is high active */
+	*rbtx4938_spics_ptr =
+		(*rbtx4938_spics_ptr & ~bit) |
+		((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit);
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
+
+int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr)
+{
+	struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata;
+	static unsigned char dat[17];
+	static int read_dat = 0;
+	int ch = 0;
+
+	if (channel != &tx4938_pci_controller[1])
+		return -ENODEV;
+	/* TX4938 PCIC1 */
+	switch (PCI_SLOT(dev->devfn)) {
+	case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
+		ch = 0;
+		break;
+	case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
+		ch = 1;
+		break;
+	default:
+		return -ENODEV;
+	}
+	if (!read_dat) {
+		unsigned char sum;
+		int i;
+		read_dat = 1;
+		/* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
+		if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID,
+				    0, dat, sizeof(dat))) {
+			printk(KERN_ERR "seeprom: read error.\n");
+		} else {
+			if (strcmp(dat, "MAC") != 0)
+				printk(KERN_WARNING "seeprom: bad signature.\n");
+			for (i = 0, sum = 0; i < sizeof(dat); i++)
+				sum += dat[i];
+			if (sum)
+				printk(KERN_WARNING "seeprom: bad checksum.\n");
+		}
+	}
+	memcpy(addr, &dat[4 + 6 * ch], 6);
+	return 0;
+}
+#endif /* CONFIG_PCI */
+
+extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on));
+static void __init rbtx4938_spi_setup(void)
+{
+	/* set SPI_SEL */
+	tx4938_ccfgptr->pcfg |= TX4938_PCFG_SPI_SEL;
+	/* chip selects for SPI devices */
+	tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
+	tx4938_pioptr->dir |= (1 << SEEPROM1_CS);
+	txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func);
+}
+
+static struct resource rbtx4938_fpga_resource;
+
+static char pcode_str[8];
+static struct resource tx4938_reg_resource = {
+	pcode_str, TX4938_REG_BASE, TX4938_REG_BASE+TX4938_REG_SIZE, IORESOURCE_MEM
+};
+
+void __init tx4938_board_setup(void)
+{
+	int i;
+	unsigned long divmode;
+	int cpuclk = 0;
+	unsigned long pcode = TX4938_REV_PCODE();
+
+	ioport_resource.start = 0x1000;
+	ioport_resource.end = 0xffffffff;
+	iomem_resource.start = 0x1000;
+	iomem_resource.end = 0xffffffff;	/* expand to 4GB */
+
+	sprintf(pcode_str, "TX%lx", pcode);
+	/* SDRAMC,EBUSC are configured by PROM */
+	for (i = 0; i < 8; i++) {
+		if (!(tx4938_ebuscptr->cr[i] & 0x8))
+			continue;	/* disabled */
+ 		rbtx4938_ce_base[i] = (unsigned long)TX4938_EBUSC_BA(i);
+		txboard_add_phys_region(rbtx4938_ce_base[i], TX4938_EBUSC_SIZE(i));
+	}
+
+	/* clocks */
+	if (txx9_master_clock) {
+		/* calculate gbus_clock and cpu_clock from master_clock */
+		divmode = (unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_DIVMODE_MASK;
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_8:
+		case TX4938_CCFG_DIVMODE_10:
+		case TX4938_CCFG_DIVMODE_12:
+		case TX4938_CCFG_DIVMODE_16:
+		case TX4938_CCFG_DIVMODE_18:
+			txx9_gbus_clock = txx9_master_clock * 4; break;
+		default:
+			txx9_gbus_clock = txx9_master_clock;
+		}
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_2:
+		case TX4938_CCFG_DIVMODE_8:
+			cpuclk = txx9_gbus_clock * 2; break;
+		case TX4938_CCFG_DIVMODE_2_5:
+		case TX4938_CCFG_DIVMODE_10:
+			cpuclk = txx9_gbus_clock * 5 / 2; break;
+		case TX4938_CCFG_DIVMODE_3:
+		case TX4938_CCFG_DIVMODE_12:
+			cpuclk = txx9_gbus_clock * 3; break;
+		case TX4938_CCFG_DIVMODE_4:
+		case TX4938_CCFG_DIVMODE_16:
+			cpuclk = txx9_gbus_clock * 4; break;
+		case TX4938_CCFG_DIVMODE_4_5:
+		case TX4938_CCFG_DIVMODE_18:
+			cpuclk = txx9_gbus_clock * 9 / 2; break;
+		}
+		txx9_cpu_clock = cpuclk;
+	} else {
+		if (txx9_cpu_clock == 0) {
+			txx9_cpu_clock = 300000000;	/* 300MHz */
+		}
+		/* calculate gbus_clock and master_clock from cpu_clock */
+		cpuclk = txx9_cpu_clock;
+		divmode = (unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_DIVMODE_MASK;
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_2:
+		case TX4938_CCFG_DIVMODE_8:
+			txx9_gbus_clock = cpuclk / 2; break;
+		case TX4938_CCFG_DIVMODE_2_5:
+		case TX4938_CCFG_DIVMODE_10:
+			txx9_gbus_clock = cpuclk * 2 / 5; break;
+		case TX4938_CCFG_DIVMODE_3:
+		case TX4938_CCFG_DIVMODE_12:
+			txx9_gbus_clock = cpuclk / 3; break;
+		case TX4938_CCFG_DIVMODE_4:
+		case TX4938_CCFG_DIVMODE_16:
+			txx9_gbus_clock = cpuclk / 4; break;
+		case TX4938_CCFG_DIVMODE_4_5:
+		case TX4938_CCFG_DIVMODE_18:
+			txx9_gbus_clock = cpuclk * 2 / 9; break;
+		}
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_8:
+		case TX4938_CCFG_DIVMODE_10:
+		case TX4938_CCFG_DIVMODE_12:
+		case TX4938_CCFG_DIVMODE_16:
+		case TX4938_CCFG_DIVMODE_18:
+			txx9_master_clock = txx9_gbus_clock / 4; break;
+		default:
+			txx9_master_clock = txx9_gbus_clock;
+		}
+	}
+	/* change default value to udelay/mdelay take reasonable time */
+	loops_per_jiffy = txx9_cpu_clock / HZ / 2;
+
+	/* CCFG */
+	/* clear WatchDogReset,BusErrorOnWrite flag (W1C) */
+	tx4938_ccfgptr->ccfg |= TX4938_CCFG_WDRST | TX4938_CCFG_BEOW;
+	/* clear PCIC1 reset */
+	if (tx4938_ccfgptr->clkctr & TX4938_CLKCTR_PCIC1RST)
+		tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIC1RST;
+
+	/* enable Timeout BusError */
+	if (tx4938_ccfg_toeon)
+		tx4938_ccfgptr->ccfg |= TX4938_CCFG_TOE;
+
+	/* DMA selection */
+	tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_DMASEL_ALL;
+
+	/* Use external clock for external arbiter */
+	if (!(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB))
+		tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_PCICLKEN_ALL;
+
+	printk("%s -- %dMHz(M%dMHz) CRIR:%08lx CCFG:%Lx PCFG:%Lx\n",
+	       pcode_str,
+	       cpuclk / 1000000, txx9_master_clock / 1000000,
+	       (unsigned long)tx4938_ccfgptr->crir,
+	       tx4938_ccfgptr->ccfg,
+	       tx4938_ccfgptr->pcfg);
+
+	printk("%s SDRAMC --", pcode_str);
+	for (i = 0; i < 4; i++) {
+		unsigned long long cr = tx4938_sdramcptr->cr[i];
+		unsigned long ram_base, ram_size;
+		if (!((unsigned long)cr & 0x00000400))
+			continue;	/* disabled */
+		ram_base = (unsigned long)(cr >> 49) << 21;
+		ram_size = ((unsigned long)(cr >> 33) + 1) << 21;
+		if (ram_base >= 0x20000000)
+			continue;	/* high memory (ignore) */
+		printk(" CR%d:%016Lx", i, cr);
+		txboard_add_phys_region(ram_base, ram_size);
+	}
+	printk(" TR:%09Lx\n", tx4938_sdramcptr->tr);
+
+	/* SRAM */
+	if (pcode == 0x4938 && tx4938_sramcptr->cr & 1) {
+		unsigned int size = 0x800;
+		unsigned long base =
+			(tx4938_sramcptr->cr >> (39-11)) & ~(size - 1);
+		 txboard_add_phys_region(base, size);
+	}
+
+	/* IRC */
+	/* disable interrupt control */
+	tx4938_ircptr->cer = 0;
+
+	/* TMR */
+	/* disable all timers */
+	for (i = 0; i < TX4938_NR_TMR; i++) {
+		tx4938_tmrptr(i)->tcr  = 0x00000020;
+		tx4938_tmrptr(i)->tisr = 0;
+		tx4938_tmrptr(i)->cpra = 0xffffffff;
+		tx4938_tmrptr(i)->itmr = 0;
+		tx4938_tmrptr(i)->ccdr = 0;
+		tx4938_tmrptr(i)->pgmr = 0;
+	}
+
+	/* enable DMA */
+	TX4938_WR64(0xff1fb150, TX4938_DMA_MCR_MSTEN);
+	TX4938_WR64(0xff1fb950, TX4938_DMA_MCR_MSTEN);
+
+	/* PIO */
+	tx4938_pioptr->maskcpu = 0;
+	tx4938_pioptr->maskext = 0;
+
+	/* TX4938 internal registers */
+	if (request_resource(&iomem_resource, &tx4938_reg_resource))
+		printk("request resource for internal registers failed\n");
+}
+
+#ifdef CONFIG_PCI
+static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr)
+{
+	unsigned short pcistatus = (unsigned short)(pcicptr->pcistatus >> 16);
+	unsigned long g2pstatus = pcicptr->g2pstatus;
+	unsigned long pcicstatus = pcicptr->pcicstatus;
+	static struct {
+		unsigned long flag;
+		const char *str;
+	} pcistat_tbl[] = {
+		{ PCI_STATUS_DETECTED_PARITY,	"DetectedParityError" },
+		{ PCI_STATUS_SIG_SYSTEM_ERROR,	"SignaledSystemError" },
+		{ PCI_STATUS_REC_MASTER_ABORT,	"ReceivedMasterAbort" },
+		{ PCI_STATUS_REC_TARGET_ABORT,	"ReceivedTargetAbort" },
+		{ PCI_STATUS_SIG_TARGET_ABORT,	"SignaledTargetAbort" },
+		{ PCI_STATUS_PARITY,	"MasterParityError" },
+	}, g2pstat_tbl[] = {
+		{ TX4938_PCIC_G2PSTATUS_TTOE,	"TIOE" },
+		{ TX4938_PCIC_G2PSTATUS_RTOE,	"RTOE" },
+	}, pcicstat_tbl[] = {
+		{ TX4938_PCIC_PCICSTATUS_PME,	"PME" },
+		{ TX4938_PCIC_PCICSTATUS_TLB,	"TLB" },
+		{ TX4938_PCIC_PCICSTATUS_NIB,	"NIB" },
+		{ TX4938_PCIC_PCICSTATUS_ZIB,	"ZIB" },
+		{ TX4938_PCIC_PCICSTATUS_PERR,	"PERR" },
+		{ TX4938_PCIC_PCICSTATUS_SERR,	"SERR" },
+		{ TX4938_PCIC_PCICSTATUS_GBE,	"GBE" },
+		{ TX4938_PCIC_PCICSTATUS_IWB,	"IWB" },
+	};
+	int i;
+
+	printk("pcistat:%04x(", pcistatus);
+	for (i = 0; i < ARRAY_SIZE(pcistat_tbl); i++)
+		if (pcistatus & pcistat_tbl[i].flag)
+			printk("%s ", pcistat_tbl[i].str);
+	printk("), g2pstatus:%08lx(", g2pstatus);
+	for (i = 0; i < ARRAY_SIZE(g2pstat_tbl); i++)
+		if (g2pstatus & g2pstat_tbl[i].flag)
+			printk("%s ", g2pstat_tbl[i].str);
+	printk("), pcicstatus:%08lx(", pcicstatus);
+	for (i = 0; i < ARRAY_SIZE(pcicstat_tbl); i++)
+		if (pcicstatus & pcicstat_tbl[i].flag)
+			printk("%s ", pcicstat_tbl[i].str);
+	printk(")\n");
+}
+
+void tx4938_report_pcic_status(void)
+{
+	int i;
+	struct tx4938_pcic_reg *pcicptr;
+	for (i = 0; (pcicptr = get_tx4938_pcicptr(i)) != NULL; i++)
+		tx4938_report_pcic_status1(pcicptr);
+}
+
+#endif /* CONFIG_PCI */
+
+/* We use onchip r4k counter or TMR timer as our system wide timer
+ * interrupt running at 100HZ. */
+
+extern void __init rtc_rx5c348_init(int chipid);
+void __init rbtx4938_time_init(void)
+{
+	rtc_rx5c348_init(RBTX4938_SRTC_CHIPID);
+	mips_hpt_frequency = txx9_cpu_clock / 2;
+}
+
+void __init toshiba_rbtx4938_setup(void)
+{
+	unsigned long long pcfg;
+	char *argptr;
+
+	iomem_resource.end = 0xffffffff;	/* 4GB */
+
+	if (txx9_master_clock == 0)
+		txx9_master_clock = 25000000; /* 25MHz */
+	tx4938_board_setup();
+	/* setup irq stuff */
+	TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000000);	/* irq trigger */
+	TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM1), 0x00000000);	/* irq trigger */
+	/* setup serial stuff */
+	TX4938_WR(0xff1ff314, 0x00000000);	/* h/w flow control off */
+	TX4938_WR(0xff1ff414, 0x00000000);	/* h/w flow control off */
+
+#ifndef CONFIG_PCI
+	set_io_port_base(RBTX4938_ETHER_BASE);
+#endif
+
+#ifdef CONFIG_SERIAL_TXX9
+	{
+		extern int early_serial_txx9_setup(struct uart_port *port);
+		int i;
+		struct uart_port req;
+		for(i = 0; i < 2; i++) {
+			memset(&req, 0, sizeof(req));
+			req.line = i;
+			req.iotype = UPIO_MEM;
+			req.membase = (char *)(0xff1ff300 + i * 0x100);
+			req.mapbase = 0xff1ff300 + i * 0x100;
+			req.irq = 32 + i;
+			req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+			req.uartclk = 50000000;
+			early_serial_txx9_setup(&req);
+		}
+	}
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+        argptr = prom_getcmdline();
+        if (strstr(argptr, "console=") == NULL) {
+                strcat(argptr, " console=ttyS0,38400");
+        }
+#endif
+#endif
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61
+	printk("PIOSEL: disabling both ata and nand selection\n");
+	local_irq_disable();
+	tx4938_ccfgptr->pcfg &= ~(TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL);
+#endif
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND
+	printk("PIOSEL: enabling nand selection\n");
+	tx4938_ccfgptr->pcfg |= TX4938_PCFG_NDF_SEL;
+	tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_ATA_SEL;
+#endif
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA
+	printk("PIOSEL: enabling ata selection\n");
+	tx4938_ccfgptr->pcfg |= TX4938_PCFG_ATA_SEL;
+	tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_NDF_SEL;
+#endif
+
+#ifdef CONFIG_IP_PNP
+	argptr = prom_getcmdline();
+	if (strstr(argptr, "ip=") == NULL) {
+		strcat(argptr, " ip=any");
+	}
+#endif
+
+
+#ifdef CONFIG_FB
+	{
+		conswitchp = &dummy_con;
+	}
+#endif
+
+	rbtx4938_spi_setup();
+	pcfg = tx4938_ccfgptr->pcfg;	/* updated */
+	/* fixup piosel */
+	if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) ==
+	    TX4938_PCFG_ATA_SEL) {
+		*rbtx4938_piosel_ptr = (*rbtx4938_piosel_ptr & 0x03) | 0x04;
+	}
+	else if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) ==
+	    TX4938_PCFG_NDF_SEL) {
+		*rbtx4938_piosel_ptr = (*rbtx4938_piosel_ptr & 0x03) | 0x08;
+	}
+	else {
+		*rbtx4938_piosel_ptr &= ~(0x08 | 0x04);
+	}
+
+	rbtx4938_fpga_resource.name = "FPGA Registers";
+	rbtx4938_fpga_resource.start = CPHYSADDR(RBTX4938_FPGA_REG_ADDR);
+	rbtx4938_fpga_resource.end = CPHYSADDR(RBTX4938_FPGA_REG_ADDR) + 0xffff;
+	rbtx4938_fpga_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (request_resource(&iomem_resource, &rbtx4938_fpga_resource))
+		printk("request resource for fpga failed\n");
+
+	/* disable all OnBoard I/O interrupts */
+	*rbtx4938_imask_ptr = 0;
+
+	_machine_restart = rbtx4938_machine_restart;
+	_machine_halt = rbtx4938_machine_halt;
+	_machine_power_off = rbtx4938_machine_power_off;
+
+	*rbtx4938_led_ptr = 0xff;
+	printk("RBTX4938 --- FPGA(Rev %02x)", *rbtx4938_fpga_rev_ptr);
+	printk(" DIPSW:%02x,%02x\n",
+	       *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr);
+}
+
+#ifdef CONFIG_PROC_FS
+extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid);
+static int __init tx4938_spi_proc_setup(void)
+{
+	struct proc_dir_entry *tx4938_spi_eeprom_dir;
+
+	tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0);
+
+	if (!tx4938_spi_eeprom_dir)
+		return -ENOMEM;
+
+	/* don't allow user access to RBTX4938_SEEPROM1_CHIPID
+	 * as it contains eth0 and eth1 MAC addresses
+	 */
+	spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID);
+	spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID);
+
+	return 0;
+}
+
+__initcall(tx4938_spi_proc_setup);
+#endif
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
new file mode 100644
index 0000000..951a208
--- /dev/null
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
@@ -0,0 +1,219 @@
+/*
+ * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <asm/tx4938/spi.h>
+#include <asm/tx4938/tx4938.h>
+
+/* ATMEL 250x0 instructions */
+#define	ATMEL_WREN	0x06
+#define	ATMEL_WRDI	0x04
+#define ATMEL_RDSR	0x05
+#define ATMEL_WRSR	0x01
+#define	ATMEL_READ	0x03
+#define	ATMEL_WRITE	0x02
+
+#define ATMEL_SR_BSY	0x01
+#define ATMEL_SR_WEN	0x02
+#define ATMEL_SR_BP0	0x04
+#define ATMEL_SR_BP1	0x08
+
+DEFINE_SPINLOCK(spi_eeprom_lock);
+
+static struct spi_dev_desc seeprom_dev_desc = {
+	.baud 		= 1500000,	/* 1.5Mbps */
+	.tcss		= 1,
+	.tcsh		= 1,
+	.tcsr		= 1,
+	.byteorder	= 1,		/* MSB-First */
+	.polarity	= 0,		/* High-Active */
+	.phase		= 0,		/* Sample-Then-Shift */
+
+};
+static inline int
+spi_eeprom_io(int chipid,
+	      unsigned char **inbufs, unsigned int *incounts,
+	      unsigned char **outbufs, unsigned int *outcounts)
+{
+	return txx9_spi_io(chipid, &seeprom_dev_desc,
+			   inbufs, incounts, outbufs, outcounts, 0);
+}
+
+int spi_eeprom_write_enable(int chipid, int enable)
+{
+	unsigned char inbuf[1];
+	unsigned char *inbufs[1];
+	unsigned int incounts[2];
+	unsigned long flags;
+	int stat;
+	inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
+	inbufs[0] = inbuf;
+	incounts[0] = sizeof(inbuf);
+	incounts[1] = 0;
+	spin_lock_irqsave(&spi_eeprom_lock, flags);
+	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
+	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
+	return stat;
+}
+
+static int spi_eeprom_read_status_nolock(int chipid)
+{
+	unsigned char inbuf[2], outbuf[2];
+	unsigned char *inbufs[1], *outbufs[1];
+	unsigned int incounts[2], outcounts[2];
+	int stat;
+	inbuf[0] = ATMEL_RDSR;
+	inbuf[1] = 0;
+	inbufs[0] = inbuf;
+	incounts[0] = sizeof(inbuf);
+	incounts[1] = 0;
+	outbufs[0] = outbuf;
+	outcounts[0] = sizeof(outbuf);
+	outcounts[1] = 0;
+	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
+	if (stat < 0)
+		return stat;
+	return outbuf[1];
+}
+
+int spi_eeprom_read_status(int chipid)
+{
+	unsigned long flags;
+	int stat;
+	spin_lock_irqsave(&spi_eeprom_lock, flags);
+	stat = spi_eeprom_read_status_nolock(chipid);
+	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
+	return stat;
+}
+
+int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
+{
+	unsigned char inbuf[2];
+	unsigned char *inbufs[2], *outbufs[2];
+	unsigned int incounts[2], outcounts[3];
+	unsigned long flags;
+	int stat;
+	inbuf[0] = ATMEL_READ;
+	inbuf[1] = address;
+	inbufs[0] = inbuf;
+	inbufs[1] = NULL;
+	incounts[0] = sizeof(inbuf);
+	incounts[1] = 0;
+	outbufs[0] = NULL;
+	outbufs[1] = buf;
+	outcounts[0] = 2;
+	outcounts[1] = len;
+	outcounts[2] = 0;
+	spin_lock_irqsave(&spi_eeprom_lock, flags);
+	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
+	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
+	return stat;
+}
+
+int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
+{
+	unsigned char inbuf[2];
+	unsigned char *inbufs[2];
+	unsigned int incounts[3];
+	unsigned long flags;
+	int i, stat;
+
+	if (address / 8 != (address + len - 1) / 8)
+		return -EINVAL;
+	stat = spi_eeprom_write_enable(chipid, 1);
+	if (stat < 0)
+		return stat;
+	stat = spi_eeprom_read_status(chipid);
+	if (stat < 0)
+		return stat;
+	if (!(stat & ATMEL_SR_WEN))
+		return -EPERM;
+
+	inbuf[0] = ATMEL_WRITE;
+	inbuf[1] = address;
+	inbufs[0] = inbuf;
+	inbufs[1] = buf;
+	incounts[0] = sizeof(inbuf);
+	incounts[1] = len;
+	incounts[2] = 0;
+	spin_lock_irqsave(&spi_eeprom_lock, flags);
+	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
+	if (stat < 0)
+		goto unlock_return;
+
+	/* write start.  max 10ms */
+	for (i = 10; i > 0; i--) {
+		int stat = spi_eeprom_read_status_nolock(chipid);
+		if (stat < 0)
+			goto unlock_return;
+		if (!(stat & ATMEL_SR_BSY))
+			break;
+		mdelay(1);
+	}
+	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
+	if (i == 0)
+		return -EIO;
+	return len;
+ unlock_return:
+	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
+	return stat;
+}
+
+#ifdef CONFIG_PROC_FS
+#define MAX_SIZE	0x80	/* for ATMEL 25010 */
+static int spi_eeprom_read_proc(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	unsigned int size = MAX_SIZE;
+	if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
+		size = 0;
+	return size;
+}
+
+static int spi_eeprom_write_proc(struct file *file, const char *buffer,
+				 unsigned long count, void *data)
+{
+	unsigned int size = MAX_SIZE;
+	int i;
+	if (file->f_pos >= size)
+		return -EIO;
+	if (file->f_pos + count > size)
+		count = size - file->f_pos;
+	for (i = 0; i < count; i += 8) {
+		int len = count - i < 8 ? count - i : 8;
+		if (spi_eeprom_write((int)data, file->f_pos,
+				     (unsigned char *)buffer, len) < 0) {
+			count = -EIO;
+			break;
+		}
+		buffer += len;
+		file->f_pos += len;
+	}
+	return count;
+}
+
+__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
+{
+	struct proc_dir_entry *entry;
+	char name[128];
+	sprintf(name, "seeprom-%d", chipid);
+	entry = create_proc_entry(name, 0600, dir);
+	if (entry) {
+		entry->read_proc = spi_eeprom_read_proc;
+		entry->write_proc = spi_eeprom_write_proc;
+		entry->data = (void *)chipid;
+	}
+}
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
new file mode 100644
index 0000000..fae3136
--- /dev/null
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
@@ -0,0 +1,159 @@
+/*
+ * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <asm/tx4938/spi.h>
+#include <asm/tx4938/tx4938.h>
+
+static int (*txx9_spi_cs_func)(int chipid, int on);
+static DEFINE_SPINLOCK(txx9_spi_lock);
+
+extern unsigned int txx9_gbus_clock;
+
+#define SPI_FIFO_SIZE	4
+
+void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
+{
+	txx9_spi_cs_func = cs_func;
+	/* enter config mode */
+	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
+}
+
+static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
+static void txx9_spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* disable rx intr */
+	tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
+	wake_up(&txx9_spi_wait);
+}
+static struct irqaction txx9_spi_action = {
+	txx9_spi_interrupt, 0, 0, "spi", NULL, NULL,
+};
+
+void __init txx9_spi_irqinit(int irc_irq)
+{
+	setup_irq(irc_irq, &txx9_spi_action);
+}
+
+int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
+		unsigned char **inbufs, unsigned int *incounts,
+		unsigned char **outbufs, unsigned int *outcounts,
+		int cansleep)
+{
+	unsigned int incount, outcount;
+	unsigned char *inp, *outp;
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&txx9_spi_lock, flags);
+	if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
+		spin_unlock_irqrestore(&txx9_spi_lock, flags);
+		return -EBUSY;
+	}
+	/* enter config mode */
+	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
+	tx4938_spiptr->cr0 =
+		(desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
+		(desc->polarity ? TXx9_SPCR0_SPOL : 0) |
+		(desc->phase ? TXx9_SPCR0_SPHA : 0) |
+		0x08;
+	tx4938_spiptr->cr1 =
+		(((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
+		0x08 /* 8 bit only */;
+	/* enter active mode */
+	tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
+	spin_unlock_irqrestore(&txx9_spi_lock, flags);
+
+	/* CS ON */
+	if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
+		spin_unlock_irqrestore(&txx9_spi_lock, flags);
+		return ret;
+	}
+	udelay(desc->tcss);
+
+	/* do scatter IO */
+	inp = inbufs ? *inbufs : NULL;
+	outp = outbufs ? *outbufs : NULL;
+	incount = 0;
+	outcount = 0;
+	while (1) {
+		unsigned char data;
+		unsigned int count;
+		int i;
+		if (!incount) {
+			incount = incounts ? *incounts++ : 0;
+			inp = (incount && inbufs) ? *inbufs++ : NULL;
+		}
+		if (!outcount) {
+			outcount = outcounts ? *outcounts++ : 0;
+			outp = (outcount && outbufs) ? *outbufs++ : NULL;
+		}
+		if (!inp && !outp)
+			break;
+		count = SPI_FIFO_SIZE;
+		if (incount)
+			count = min(count, incount);
+		if (outcount)
+			count = min(count, outcount);
+
+		/* now tx must be idle... */
+		while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
+			;
+
+		tx4938_spiptr->cr0 =
+			(tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
+			((count - 1) << 12);
+		if (cansleep) {
+			/* enable rx intr */
+			tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
+		}
+		/* send */
+		for (i = 0; i < count; i++)
+			tx4938_spiptr->dr = inp ? *inp++ : 0;
+		/* wait all rx data */
+		if (cansleep) {
+			wait_event(txx9_spi_wait,
+				   tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
+		} else {
+			while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
+				;
+		}
+		/* receive */
+		for (i = 0; i < count; i++) {
+			data = tx4938_spiptr->dr;
+			if (outp)
+				*outp++ = data;
+		}
+		if (incount)
+			incount -= count;
+		if (outcount)
+			outcount -= count;
+	}
+
+	/* CS OFF */
+	udelay(desc->tcsh);
+	txx9_spi_cs_func(chipid, 0);
+	udelay(desc->tcsr);
+
+	spin_lock_irqsave(&txx9_spi_lock, flags);
+	/* enter config mode */
+	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
+	spin_unlock_irqrestore(&txx9_spi_lock, flags);
+
+	return 0;
+}
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
new file mode 100644
index 0000000..a7add16
--- /dev/null
+++ b/arch/mips/vr41xx/Kconfig
@@ -0,0 +1,88 @@
+config CASIO_E55
+	bool "Support for CASIO CASSIOPEIA E-10/15/55/65"
+	depends on MACH_VR41XX
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select ISA
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config IBM_WORKPAD
+	bool "Support for IBM WorkPad z50"
+	depends on MACH_VR41XX
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select ISA
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config NEC_CMBVR4133
+	bool "Support for NEC CMB-VR4133"
+	depends on MACH_VR41XX
+	select CPU_VR41XX
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select HW_HAS_PCI
+
+config ROCKHOPPER
+	bool "Support for Rockhopper baseboard"
+	depends on NEC_CMBVR4133
+	select I8259
+	select HAVE_STD_PC_SERIAL_PORT
+
+config TANBAC_TB022X
+	bool "Support for TANBAC VR4131 multichip module and TANBAC VR4131DIMM"
+	depends on MACH_VR41XX
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  The TANBAC VR4131 multichip module(TB0225) and
+	  the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms
+	  manufactured by TANBAC.
+	  Please refer to <http://www.tanbac.co.jp/>
+	  about VR4131 multichip module and VR4131DIMM.
+
+config TANBAC_TB0226
+	bool "Support for TANBAC Mbase(TB0226)"
+	depends on TANBAC_TB022X
+	select GPIO_VR41XX
+	help
+	  The TANBAC Mbase(TB0226) is a MIPS-based platform
+	  manufactured by TANBAC.
+	  Please refer to <http://www.tanbac.co.jp/> about Mbase.
+
+config TANBAC_TB0287
+	bool "Support for TANBAC Mini-ITX DIMM base(TB0287)"
+	depends on TANBAC_TB022X
+	help
+	  The TANBAC Mini-ITX DIMM base(TB0287) is a MIPS-based platform
+	  manufactured by TANBAC.
+	  Please refer to <http://www.tanbac.co.jp/> about Mini-ITX DIMM base.
+
+config VICTOR_MPC30X
+	bool "Support for Victor MP-C303/304"
+	depends on MACH_VR41XX
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config ZAO_CAPCELLA
+	bool "Support for ZAO Networks Capcella"
+	depends on MACH_VR41XX
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config PCI_VR41XX
+	bool "Add PCI control unit support of NEC VR4100 series"
+	depends on MACH_VR41XX && HW_HAS_PCI
+	default y
+	select PCI
+
+config VRC4173
+	tristate "Add NEC VRC4173 companion chip support"
+	depends on MACH_VR41XX && PCI_VR41XX
+	help
+	  The NEC VRC4173 is a companion chip for NEC VR4122/VR4131.
diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c
index fcd3cb8..d758e43 100644
--- a/arch/mips/vr41xx/common/cmu.c
+++ b/arch/mips/vr41xx/common/cmu.c
@@ -69,7 +69,7 @@
 
 static void __iomem *cmu_base;
 static uint16_t cmuclkmsk, cmuclkmsk2;
-static spinlock_t cmu_lock;
+static DEFINE_SPINLOCK(cmu_lock);
 
 #define cmu_read(offset)		readw(cmu_base + (offset))
 #define cmu_write(offset, value)	writew((value), cmu_base + (offset))
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index e03be89..578f649 100644
--- a/arch/mips/vr41xx/common/init.c
+++ b/arch/mips/vr41xx/common/init.c
@@ -58,6 +58,14 @@
 	board_timer_setup = setup_timer_irq;
 }
 
+void __init plat_setup(void)
+{
+	vr41xx_calculate_clock_frequency();
+
+	timer_init();
+	iomem_resource_init();
+}
+
 void __init prom_init(void)
 {
 	int argc, i;
@@ -71,12 +79,6 @@
 		if (i < (argc - 1))
 			strcat(arcs_cmdline, " ");
 	}
-
-	vr41xx_calculate_clock_frequency();
-
-	timer_init();
-
-	iomem_resource_init();
 }
 
 unsigned long __init prom_free_prom_memory (void)
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
index ba58764..462a9af 100644
--- a/arch/mips/vr41xx/common/vrc4173.c
+++ b/arch/mips/vr41xx/common/vrc4173.c
@@ -81,8 +81,8 @@
 static int vrc4173_initialized;
 static uint16_t vrc4173_cmuclkmsk;
 static uint16_t vrc4173_selectreg;
-static spinlock_t vrc4173_cmu_lock;
-static spinlock_t vrc4173_giu_lock;
+static DEFINE_SPINLOCK(vrc4173_cmu_lock);
+static DEFINE_SPINLOCK(vrc4173_giu_lock);
 
 static inline void set_cmusrst(uint16_t val)
 {
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/setup.c b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
index db686ce..53272a5 100644
--- a/arch/mips/vr41xx/nec-cmbvr4133/setup.c
+++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
@@ -56,7 +56,7 @@
 
 extern void i8259_init(void);
 
-static int __init nec_cmbvr4133_setup(void)
+static void __init nec_cmbvr4133_setup(void)
 {
 #ifdef CONFIG_ROCKHOPPER
 	extern void disable_pcnet(void);
@@ -90,7 +90,4 @@
 #ifdef CONFIG_ROCKHOPPER
 	i8259_init();
 #endif
-	return 0;
 }
-
-early_initcall(nec_cmbvr4133_setup);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 0b07922..874a283 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -47,10 +47,10 @@
 
 config ISA_DMA_API
 	bool
-	default y
 
 config ARCH_MAY_HAVE_PC_FDC
 	bool
+	depends on BROKEN
 	default y
 
 source "init/Kconfig"
@@ -154,13 +154,14 @@
 
 config ARCH_DISCONTIGMEM_ENABLE
 	bool "Discontiguous memory support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on 64BIT && EXPERIMENTAL
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
+source "kernel/Kconfig.hz"
 source "mm/Kconfig"
 
 config PREEMPT
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 3b339b1..9b7e424 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -20,7 +20,8 @@
 CHECKFLAGS	+= -D__hppa__=1
 
 ifdef CONFIG_64BIT
-CROSS_COMPILE	:= hppa64-linux-
+CROSS_COMPILE	:= $(shell if [ -x /usr/bin/hppa64-linux-gnu-gcc ]; then \
+			echo hppa64-linux-gnu-; else echo hppa64-linux-; fi)
 UTS_MACHINE	:= parisc64
 CHECKFLAGS	+= -D__LP64__=1 -m64
 else
@@ -34,6 +35,14 @@
 
 OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
 
+GCC_VERSION     := $(call cc-version)
+ifneq ($(shell if [ -z $(GCC_VERSION) ] ; then echo "bad"; fi ;),)
+$(error Sorry, couldn't find ($(cc-version)).)
+endif
+ifneq ($(shell if [ $(GCC_VERSION) -lt 0303 ] ; then echo "bad"; fi ;),)
+$(error Sorry, your compiler is too old ($(GCC_VERSION)).  GCC v3.3 or above is required.)
+endif
+
 cflags-y	:= -pipe
 
 # These flags should be implied by an hppa-linux configuration, but they
@@ -43,7 +52,7 @@
 # Currently we save and restore fpregs on all kernel entry/interruption paths.
 # If that gets optimized, we might need to disable the use of fpregs in the
 # kernel.
-#cflags-y	+= -mdisable-fpregs
+cflags-y	+= -mdisable-fpregs
 
 # Without this, "ld -r" results in .text sections that are too big
 # (> 0x40000) for branches to reach stubs.
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
index 6efaa92..3e013f5 100644
--- a/arch/parisc/configs/712_defconfig
+++ b/arch/parisc/configs/712_defconfig
@@ -1,12 +1,16 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan  5 13:20:32 2005
+# Linux kernel version: 2.6.14-rc5-pa1
+# Fri Oct 21 23:04:34 2005
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
 CONFIG_STACK_GROWSUP=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -15,35 +19,40 @@
 # CONFIG_CLEAN_COMPILE is not set
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,9 +74,18 @@
 # CONFIG_PA7300LC is not set
 # CONFIG_PA8X00 is not set
 CONFIG_PA11=y
-# CONFIG_64BIT is not set
 # CONFIG_SMP is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+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_PREEMPT is not set
 # CONFIG_HPUX is not set
 
@@ -81,8 +99,6 @@
 # CONFIG_GSC_WAX is not set
 # CONFIG_EISA is not set
 # CONFIG_PCI is not set
-CONFIG_CHASSIS_LCD_LED=y
-# CONFIG_PDC_CHASSIS is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -90,12 +106,15 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
+# PCI Hotplug Support
 #
 
 #
-# PCI Hotplug Support
+# PA-RISC specific drivers
 #
+CONFIG_CHASSIS_LCD_LED=y
+# CONFIG_PDC_CHASSIS is not set
+CONFIG_PDC_STABLE=y
 
 #
 # Executable file formats
@@ -104,137 +123,7 @@
 CONFIG_BINFMT_MISC=m
 
 #
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_FW_LOADER=y
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-CONFIG_PARPORT_GSC=y
-# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_PARIDE is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-CONFIG_SCSI_LASI700=y
-CONFIG_53C700_MEM_MAPPED=y
-CONFIG_53C700_LE_ON_BE=y
-# CONFIG_SCSI_ZALON is not set
-CONFIG_SCSI_DEBUG=m
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-# CONFIG_MD_RAID10 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-# CONFIG_BLK_DEV_DM is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Networking support
+# Networking
 #
 CONFIG_NET=y
 
@@ -243,12 +132,14 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
@@ -262,8 +153,10 @@
 CONFIG_INET_ESP=m
 # CONFIG_INET_IPCOMP is not set
 CONFIG_INET_TUNNEL=m
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
 
 #
 # IP: Virtual Server Configuration
@@ -272,6 +165,7 @@
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
 
 #
 # IP: Netfilter Configuration
@@ -279,11 +173,14 @@
 CONFIG_IP_NF_CONNTRACK=m
 # CONFIG_IP_NF_CT_ACCT is not set
 CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
 CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_LIMIT=m
@@ -307,21 +204,23 @@
 # CONFIG_IP_NF_MATCH_ADDRTYPE is not set
 # CONFIG_IP_NF_MATCH_REALM is not set
 CONFIG_IP_NF_MATCH_SCTP=m
+# CONFIG_IP_NF_MATCH_DCCP is not set
 CONFIG_IP_NF_MATCH_COMMENT=m
 CONFIG_IP_NF_MATCH_CONNMARK=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
+# 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=m
 CONFIG_IP_NF_TARGET_SAME=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
 CONFIG_IP_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_NAT_IRC=m
 CONFIG_IP_NF_NAT_FTP=m
@@ -333,6 +232,7 @@
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_TARGET_TTL is not set
 CONFIG_IP_NF_TARGET_CONNMARK=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
@@ -340,10 +240,11 @@
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -362,10 +263,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 # CONFIG_NET_CLS_ROUTE is not set
 
@@ -373,17 +270,162 @@
 # Network testing
 #
 CONFIG_NET_PKTGEN=m
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+CONFIG_SCSI_LASI700=y
+CONFIG_53C700_LE_ON_BE=y
+# CONFIG_SCSI_ZALON is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -391,6 +433,7 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 CONFIG_LASI_82596=y
+# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -414,6 +457,7 @@
 #
 # CONFIG_STRIP is not set
 # CONFIG_ATMEL is not set
+# CONFIG_HOSTAP is not set
 
 #
 # Wan interfaces
@@ -431,6 +475,8 @@
 # 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
 
 #
 # ISDN subsystem
@@ -460,19 +506,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PARKBD is not set
-CONFIG_SERIO_GSCPS2=y
-CONFIG_HP_SDC=y
-CONFIG_HIL_MLC=y
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -483,6 +516,7 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_HIL_OLD=y
 # CONFIG_KEYBOARD_HIL is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
@@ -494,6 +528,19 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_GSCPS2=y
+CONFIG_HP_SDC=y
+CONFIG_HIL_MLC=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -511,7 +558,6 @@
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -546,12 +592,14 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -562,10 +610,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -579,28 +637,36 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_STI=y
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
-CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=128
 CONFIG_DUMMY_CONSOLE_ROWS=48
-CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_STI_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 # CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
 # CONFIG_FONT_PEARL_8x8 is not set
 # CONFIG_FONT_ACORN_8x8 is not set
 # CONFIG_FONT_MINI_4x6 is not set
 # CONFIG_FONT_SUN8x16 is not set
 # CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
 
 #
 # Logo configuration
@@ -610,6 +676,7 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_PARISC_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -657,10 +724,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -671,10 +734,20 @@
 # CONFIG_MMC is not set
 
 #
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
@@ -682,20 +755,24 @@
 # CONFIG_REISERFS_FS is not set
 CONFIG_JFS_FS=m
 # CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -722,14 +799,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-# CONFIG_TMPFS_SECURITY is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -754,16 +828,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
@@ -778,6 +855,7 @@
 # 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
@@ -838,13 +916,19 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
 
 #
 # Security options
@@ -865,6 +949,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -882,9 +967,14 @@
 CONFIG_CRYPTO_TEST=m
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index 30fc03e..955ef50 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4-pa1
-# Wed Feb 16 11:32:49 2005
+# Linux kernel version: 2.6.14-rc5-pa1
+# Fri Oct 21 23:04:54 2005
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -10,6 +10,7 @@
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -19,26 +20,32 @@
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -48,6 +55,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -74,7 +82,19 @@
 CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+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_PREEMPT is not set
 CONFIG_COMPAT=y
 CONFIG_NR_CPUS=8
@@ -85,7 +105,7 @@
 # CONFIG_GSC is not set
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
@@ -96,6 +116,8 @@
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
+# CONFIG_PCMCIA_LOAD_CIS is not set
+CONFIG_PCMCIA_IOCTL=y
 CONFIG_CARDBUS=y
 
 #
@@ -104,7 +126,6 @@
 CONFIG_YENTA=m
 CONFIG_PD6729=m
 CONFIG_I82092=m
-CONFIG_TCIC=m
 CONFIG_PCCARD_NONSTATIC=m
 
 #
@@ -127,6 +148,203 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+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_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# 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=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+CONFIG_IP_NF_MATCH_SCTP=m
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+# 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=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_LIMIT is not set
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP6_NF_MATCH_OWNER is not set
+# CONFIG_IP6_NF_MATCH_MARK is not set
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+# CONFIG_IP6_NF_MATCH_LENGTH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_MARK is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_RAW=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID3 is not set
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_LLC=m
+CONFIG_LLC2=m
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
 # Device Drivers
 #
 
@@ -139,6 +357,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -169,7 +392,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=6144
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -189,6 +411,7 @@
 #
 # SCSI device support
 #
+CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -201,6 +424,7 @@
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -215,6 +439,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=m
 CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -229,14 +454,12 @@
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
@@ -246,8 +469,6 @@
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 CONFIG_SCSI_QLOGIC_FC=m
 # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
@@ -258,7 +479,9 @@
 # CONFIG_SCSI_QLA22XX is not set
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
-CONFIG_SCSI_QLA6312=m
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 CONFIG_SCSI_DEBUG=m
@@ -288,8 +511,11 @@
 #
 # Fusion MPT device support
 #
-CONFIG_FUSION=m
-CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_MAX_SGE=128
 CONFIG_FUSION_CTL=m
 
 #
@@ -303,153 +529,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-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_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=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_LLC=m
-CONFIG_LLC2=m
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -457,12 +543,18 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
 CONFIG_NET_VENDOR_3COM=y
 CONFIG_VORTEX=m
 CONFIG_TYPHOON=m
@@ -479,6 +571,7 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 CONFIG_PCMCIA_XIRCOM=m
 # CONFIG_PCMCIA_XIRTULIP is not set
 CONFIG_HP100=m
@@ -489,48 +582,43 @@
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
-CONFIG_EEPRO100=m
+# CONFIG_EEPRO100 is not set
 CONFIG_E100=m
-CONFIG_E100_NAPI=y
 # CONFIG_FEALNX is not set
-CONFIG_NATSEMI=m
+# CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_8139CP is not set
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_8139TOO is not set
 # CONFIG_SIS900 is not set
-CONFIG_EPIC100=m
+# CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
-CONFIG_VIA_RHINE=m
-CONFIG_VIA_RHINE_MMIO=y
+# CONFIG_VIA_RHINE is not set
 
 #
 # Ethernet (1000 Mbit)
 #
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
-CONFIG_DL2K=m
+# CONFIG_DL2K is not set
 CONFIG_E1000=m
 CONFIG_E1000_NAPI=y
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
-CONFIG_IXGB=m
-CONFIG_IXGB_NAPI=y
-CONFIG_S2IO=m
-CONFIG_S2IO_NAPI=y
-# CONFIG_2BUFF_MODE is not set
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
@@ -560,6 +648,7 @@
 CONFIG_HERMES=m
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
+# CONFIG_NORTEL_HERMES is not set
 CONFIG_PCI_HERMES=m
 # CONFIG_ATMEL is not set
 
@@ -567,6 +656,7 @@
 # Wireless 802.11b Pcmcia/Cardbus cards support
 #
 CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
 CONFIG_AIRO_CS=m
 CONFIG_PCMCIA_WL3501=m
 
@@ -574,6 +664,7 @@
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
 # CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
 CONFIG_NET_WIRELESS=y
 
 #
@@ -607,6 +698,8 @@
 # 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
@@ -633,13 +726,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -649,6 +735,12 @@
 # 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
@@ -667,7 +759,6 @@
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -677,6 +768,7 @@
 CONFIG_PDC_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 
@@ -708,6 +800,11 @@
 CONFIG_MAX_RAW_DEVS=256
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -718,10 +815,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -742,6 +849,7 @@
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
+# CONFIG_STI_CONSOLE is not set
 
 #
 # Sound
@@ -751,13 +859,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -772,17 +876,18 @@
 #
 # InfiniBand support
 #
-CONFIG_INFINIBAND=m
-CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
-CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
@@ -794,22 +899,20 @@
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 CONFIG_XFS_FS=m
 CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -836,13 +939,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -867,15 +968,18 @@
 #
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_NFS_DIRECTIO=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -890,6 +994,7 @@
 # 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
@@ -906,15 +1011,15 @@
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
+# CONFIG_NLS_CODEPAGE_852 is not set
 # CONFIG_NLS_CODEPAGE_855 is not set
 # CONFIG_NLS_CODEPAGE_857 is not set
 # CONFIG_NLS_CODEPAGE_860 is not set
 # CONFIG_NLS_CODEPAGE_861 is not set
 # CONFIG_NLS_CODEPAGE_862 is not set
-CONFIG_NLS_CODEPAGE_863=m
+# CONFIG_NLS_CODEPAGE_863 is not set
 # CONFIG_NLS_CODEPAGE_864 is not set
-CONFIG_NLS_CODEPAGE_865=m
+# CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
@@ -926,10 +1031,10 @@
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
@@ -950,11 +1055,15 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_IOREMAP is not set
@@ -974,25 +1083,26 @@
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
 CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
 CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
@@ -1004,6 +1114,7 @@
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
index 46c9511..8819e7e 100644
--- a/arch/parisc/configs/b180_defconfig
+++ b/arch/parisc/configs/b180_defconfig
@@ -1,12 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan  5 13:35:54 2005
+# Linux kernel version: 2.6.14-rc5-pa1
+# Fri Oct 21 23:06:10 2005
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
 CONFIG_STACK_GROWSUP=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 
 #
 # Code maturity level options
@@ -14,33 +17,39 @@
 # CONFIG_EXPERIMENTAL is not set
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -60,8 +69,14 @@
 # CONFIG_PA7300LC is not set
 # CONFIG_PA8X00 is not set
 CONFIG_PA11=y
-# CONFIG_64BIT is not set
 # CONFIG_SMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_HPUX is not set
 
@@ -78,11 +93,25 @@
 CONFIG_ISA=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_GSC_DINO=y
 # CONFIG_PCI_LBA is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# PA-RISC specific drivers
+#
 CONFIG_CHASSIS_LCD_LED=y
 # CONFIG_PDC_CHASSIS is not set
+CONFIG_PDC_STABLE=y
 
 #
 # Executable file formats
@@ -91,6 +120,64 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER 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_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
 # Device Drivers
 #
 
@@ -99,9 +186,15 @@
 #
 CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -111,10 +204,8 @@
 #
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_CML1=y
 # CONFIG_PARPORT_SERIAL is not set
 CONFIG_PARPORT_GSC=y
-# CONFIG_PARPORT_OTHER is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -125,19 +216,17 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -149,6 +238,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -158,6 +248,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -170,6 +261,7 @@
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -183,16 +275,16 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
@@ -202,14 +294,11 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
 # CONFIG_SCSI_IPS is not set
@@ -219,7 +308,6 @@
 # CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_NCR53C406A is not set
 CONFIG_SCSI_LASI700=y
-CONFIG_53C700_MEM_MAPPED=y
 CONFIG_53C700_LE_ON_BE=y
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
@@ -231,7 +319,6 @@
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -240,12 +327,12 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -263,6 +350,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID5=y
+CONFIG_MD_RAID6=y
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
 # CONFIG_BLK_DEV_DM is not set
@@ -271,6 +359,9 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -283,58 +374,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE 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_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_NETFILTER 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
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -347,6 +388,11 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -354,8 +400,8 @@
 # CONFIG_LASI_82596 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_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 
@@ -369,6 +415,7 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
@@ -384,12 +431,15 @@
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -413,12 +463,12 @@
 #
 # Wireless 802.11b ISA/PCI cards support
 #
-# CONFIG_AIRO is not set
 # CONFIG_HERMES is not set
 
 #
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
+# CONFIG_HOSTAP is not set
 CONFIG_NET_WIRELESS=y
 
 #
@@ -435,6 +485,8 @@
 # CONFIG_PPP_BSDCOMP is not set
 # CONFIG_SLIP is not set
 # CONFIG_NET_FC is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -464,23 +516,12 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PARKBD is not set
-CONFIG_SERIO_GSCPS2=y
-# CONFIG_HP_SDC is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
+# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES is not set
 # CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
@@ -488,7 +529,7 @@
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
 CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_INPORT is not set
 # CONFIG_MOUSE_LOGIBM is not set
@@ -502,6 +543,19 @@
 # CONFIG_HP_SDC_RTC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_GSCPS2=y
+# CONFIG_HP_SDC is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -519,8 +573,11 @@
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
 
 #
 # Non-8250 serial port support
@@ -529,6 +586,7 @@
 # CONFIG_PDC_CONSOLE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -555,11 +613,14 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -570,10 +631,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -587,6 +658,11 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -595,6 +671,7 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_STI=y
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
@@ -606,18 +683,19 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_STI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -630,6 +708,7 @@
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_LOGO_PARISC_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -639,13 +718,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -658,23 +733,36 @@
 # CONFIG_MMC is not set
 
 #
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -697,11 +785,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -719,15 +806,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_TCP=y
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SMB_FS is not set
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -785,13 +876,19 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
 
 #
 # Security options
@@ -815,6 +912,7 @@
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -832,8 +930,13 @@
 # CONFIG_CRYPTO_TEST is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index 67aca6c..9d86b6b 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -1,12 +1,16 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan  5 13:26:49 2005
+# Linux kernel version: 2.6.14-rc5-pa1
+# Fri Oct 21 23:06:31 2005
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
 CONFIG_STACK_GROWSUP=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -15,26 +19,31 @@
 # CONFIG_CLEAN_COMPILE is not set
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +53,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -66,10 +76,19 @@
 CONFIG_PA8X00=y
 CONFIG_PA20=y
 CONFIG_PREFETCH=y
-# CONFIG_PARISC64 is not set
 # CONFIG_64BIT is not set
 # CONFIG_SMP is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+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_PREEMPT is not set
 # CONFIG_HPUX is not set
 
@@ -79,13 +98,10 @@
 # CONFIG_GSC is not set
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
-CONFIG_SUPERIO=y
-CONFIG_CHASSIS_LCD_LED=y
-# CONFIG_PDC_CHASSIS is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -93,21 +109,205 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
 
 #
+# PA-RISC specific drivers
+#
+CONFIG_SUPERIO=y
+CONFIG_CHASSIS_LCD_LED=y
+# CONFIG_PDC_CHASSIS is not set
+CONFIG_PDC_STABLE=y
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+# CONFIG_NETFILTER_NETLINK 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=m
+CONFIG_IP_NF_AMANDA=m
+# 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=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# 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=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_LIMIT is not set
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_MULTIPORT is not set
+CONFIG_IP6_NF_MATCH_OWNER=m
+# CONFIG_IP6_NF_MATCH_MARK is not set
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_AHESP is not set
+CONFIG_IP6_NF_MATCH_LENGTH=m
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+# CONFIG_IP6_NF_TARGET_NFQUEUE is not set
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_MARK is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_RAW is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
 # Device Drivers
 #
 
@@ -120,6 +320,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -141,14 +346,14 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_CRYPTOLOOP=m
 # 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 is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -158,6 +363,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -201,6 +407,7 @@
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
 CONFIG_BLK_DEV_NS87415=y
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
@@ -218,6 +425,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -230,6 +438,7 @@
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -242,7 +451,9 @@
 # SCSI Transport Attributes
 #
 CONFIG_SCSI_SPI_ATTRS=y
-CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -258,25 +469,26 @@
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
 CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=m
+# CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 CONFIG_SCSI_SATA_PROMISE=m
+# CONFIG_SCSI_SATA_QSTOR is not set
 # CONFIG_SCSI_SATA_SX4 is not set
 CONFIG_SCSI_SATA_SIL=m
 # CONFIG_SCSI_SATA_SIS is not set
 # CONFIG_SCSI_SATA_ULI is not set
 CONFIG_SCSI_SATA_VIA=m
 # CONFIG_SCSI_SATA_VITESSE is not set
-# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
@@ -286,20 +498,17 @@
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
-CONFIG_SCSI_QLOGIC_1280=m
-# CONFIG_SCSI_QLOGIC_1280_1040 is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA21XX is not set
 # CONFIG_SCSI_QLA22XX is not set
-CONFIG_SCSI_QLA2300=m
-CONFIG_SCSI_QLA2322=m
-CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -316,19 +525,24 @@
 # CONFIG_MD_RAID10 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_MD_RAID6 is not set
-CONFIG_MD_MULTIPATH=y
+# CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
 
 #
 # Fusion MPT device support
 #
-CONFIG_FUSION=m
-CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_MAX_SGE=128
 CONFIG_FUSION_CTL=m
 
 #
@@ -342,151 +556,13 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-CONFIG_NETFILTER_DEBUG=y
-
-#
-# 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_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-# 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_COMMENT is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT 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_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=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-# CONFIG_IP_NF_RAW is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_LLC=m
-CONFIG_LLC2=m
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -494,12 +570,18 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
-CONFIG_HAPPYMEAL=m
+# CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
 
 #
@@ -514,28 +596,22 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
+# CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
-CONFIG_ADAPTEC_STARFIRE=m
-# CONFIG_ADAPTEC_STARFIRE_NAPI is not set
-CONFIG_B44=m
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
-CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
+# CONFIG_EEPRO100 is not set
 CONFIG_E100=m
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
-CONFIG_NATSEMI=m
+# CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_8139CP is not set
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_8139TOO is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -554,15 +630,18 @@
 # 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_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
-CONFIG_IXGB=y
-CONFIG_IXGB_NAPI=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
 #
@@ -593,6 +672,8 @@
 # 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
@@ -622,16 +703,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=m
-CONFIG_SERIO_SERPORT=m
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -649,6 +720,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=m
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -666,7 +747,6 @@
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
@@ -676,6 +756,7 @@
 # CONFIG_PDC_CONSOLE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -698,12 +779,16 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -714,10 +799,20 @@
 # CONFIG_W1 is not set
 
 #
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -731,6 +826,11 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -739,6 +839,7 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_STI=y
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
@@ -751,18 +852,20 @@
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_PM3 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
-CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_STI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -775,6 +878,7 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_PARISC_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -784,7 +888,78 @@
 #
 # Advanced Linux Sound Architecture
 #
-# CONFIG_SND is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_AD1889=y
+# CONFIG_SND_AD1889_OPL3 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
 
 #
 # Open Sound System
@@ -794,6 +969,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 
@@ -804,23 +981,23 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 CONFIG_USB_PRINTER=m
 
@@ -829,12 +1006,11 @@
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
+# 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=y
-CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_USBAT=y
 CONFIG_USB_STORAGE_SDDR09=y
 CONFIG_USB_STORAGE_SDDR55=y
 CONFIG_USB_STORAGE_JUMPSHOT=y
@@ -846,21 +1022,25 @@
 CONFIG_USB_HIDINPUT=y
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
-CONFIG_USB_AIPTEK=m
-CONFIG_USB_WACOM=m
-CONFIG_USB_KBTAB=m
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
 #
 CONFIG_USB_MDC800=m
 CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
 
 #
 # USB Multimedia devices
@@ -879,6 +1059,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
 
 #
 # USB port drivers
@@ -894,7 +1075,6 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 CONFIG_USB_LEGOTOWER=m
@@ -903,10 +1083,12 @@
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
@@ -920,27 +1102,41 @@
 # CONFIG_MMC is not set
 
 #
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
 # CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -966,13 +1162,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -996,16 +1190,19 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 # CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -1014,6 +1211,7 @@
 # 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
@@ -1074,13 +1272,19 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
 
 #
 # Security options
@@ -1092,21 +1296,22 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_HMAC is not set
 CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
+# CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
 # CONFIG_CRYPTO_KHAZAD is not set
@@ -1117,9 +1322,14 @@
 CONFIG_CRYPTO_TEST=m
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=m
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
index fdae21c5..f38a462 100644
--- a/arch/parisc/defconfig
+++ b/arch/parisc/defconfig
@@ -1,38 +1,56 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc5-pa1
+# Fri Oct 21 23:01:33 2005
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
 CONFIG_STACK_GROWSUP=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_AUDIT is not set
 # CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -45,10 +63,21 @@
 CONFIG_PA7000=y
 # CONFIG_PA7100LC is not set
 # CONFIG_PA7200 is not set
+# CONFIG_PA7300LC is not set
 # CONFIG_PA8X00 is not set
 CONFIG_PA11=y
-# CONFIG_64BIT is not set
 # CONFIG_SMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+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_PREEMPT is not set
 # CONFIG_HPUX is not set
 
@@ -65,14 +94,29 @@
 # CONFIG_ISA is not set
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_GSC_DINO=y
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PA-RISC specific drivers
+#
 CONFIG_SUPERIO=y
 CONFIG_CHASSIS_LCD_LED=y
 CONFIG_PDC_CHASSIS=y
+CONFIG_PDC_STABLE=y
 
 #
 # Executable file formats
@@ -81,15 +125,97 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE 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_IEEE80211 is not set
+
+#
 # Device Drivers
 #
 
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -99,12 +225,10 @@
 #
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_CML1=y
 # CONFIG_PARPORT_SERIAL is not set
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
 CONFIG_PARPORT_GSC=y
-# CONFIG_PARPORT_OTHER is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -114,18 +238,31 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 # 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=4096
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -135,6 +272,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -147,53 +285,59 @@
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
 #
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
 CONFIG_SCSI_LASI700=y
-CONFIG_53C700_MEM_MAPPED=y
 CONFIG_53C700_LE_ON_BE=y
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_ZALON=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
 CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -202,7 +346,8 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -217,15 +362,20 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
 # CONFIG_MD_RAID6 is not set
 # CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
 # CONFIG_BLK_DEV_DM is not set
 
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -238,80 +388,23 @@
 # CONFIG_I2O is not set
 
 #
-# Macintosh device drivers
+# Network device support
 #
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q 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_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
 CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -321,6 +414,7 @@
 CONFIG_LASI_82596=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_SMC is not set
 
@@ -336,6 +430,7 @@
 # CONFIG_DE4X5 is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
@@ -361,30 +456,37 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_ACENIC is not set
-CONFIG_DL2K=y
+CONFIG_ACENIC=y
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
 # CONFIG_E1000 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_SK98LIN is not set
-# CONFIG_TIGON3 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -399,38 +501,30 @@
 #
 # Wireless 802.11b ISA/PCI cards support
 #
-CONFIG_AIRO=y
 # CONFIG_HERMES is not set
 # CONFIG_ATMEL is not set
-CONFIG_NET_WIRELESS=y
 
 #
-# Token Ring devices
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP 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
@@ -460,10 +554,56 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
+# Input Device Drivers
 #
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_HIL_OLD=y
+CONFIG_KEYBOARD_HIL=y
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_HIL is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_DB9 is not set
+# CONFIG_JOYSTICK_GAMECON is not set
+# CONFIG_JOYSTICK_TURBOGRAFX is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_HP_SDC_RTC=y
+
+#
+# Hardware I/O ports
+#
 CONFIG_SERIO=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_PARKBD is not set
@@ -471,38 +611,8 @@
 CONFIG_HP_SDC=y
 CONFIG_HIL_MLC=y
 # CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_KEYBOARD_HIL=y
-CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_HIL is not set
-CONFIG_INPUT_JOYSTICK=y
-# CONFIG_JOYSTICK_IFORCE is not set
-# CONFIG_JOYSTICK_WARRIOR is not set
-# CONFIG_JOYSTICK_MAGELLAN is not set
-# CONFIG_JOYSTICK_SPACEORB is not set
-# CONFIG_JOYSTICK_SPACEBALL is not set
-# CONFIG_JOYSTICK_STINGER is not set
-# CONFIG_JOYSTICK_TWIDDLER is not set
-# CONFIG_JOYSTICK_DB9 is not set
-# CONFIG_JOYSTICK_GAMECON is not set
-# CONFIG_JOYSTICK_TURBOGRAFX is not set
-# CONFIG_INPUT_JOYDUMP is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_GUNZE is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_PCSPKR is not set
-# CONFIG_INPUT_UINPUT is not set
-CONFIG_HP_SDC_RTC=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
 
 #
 # Character devices
@@ -522,16 +632,16 @@
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
 # CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_MUX is not set
-# CONFIG_PDC_CONSOLE is not set
+CONFIG_SERIAL_MUX=y
+CONFIG_SERIAL_MUX_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -541,12 +651,6 @@
 # CONFIG_TIPAR is not set
 
 #
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
@@ -555,7 +659,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -565,21 +668,40 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -593,34 +715,45 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_STI=y
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
+CONFIG_STI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -629,6 +762,7 @@
 # Logo configuration
 #
 # CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -638,17 +772,94 @@
 #
 # Advanced Linux Sound Architecture
 #
-# CONFIG_SND is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_AD1889=y
+# CONFIG_SND_AD1889_OPL3 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# GSC devices
+#
+CONFIG_SND_HARMONY=y
 
 #
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
-# CONFIG_SOUND_HARMONY is not set
 
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 
@@ -658,26 +869,36 @@
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH 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_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # 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 is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB Input Devices
 #
 # CONFIG_USB_HID is not set
 
@@ -688,16 +909,23 @@
 # CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -709,13 +937,15 @@
 #
 
 #
-# USB Network adaptors
+# 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_USB_ZD1201 is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -732,12 +962,21 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL 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_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
 
 #
 # USB Gadget Support
@@ -745,22 +984,41 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -773,7 +1031,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -781,11 +1040,11 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -809,23 +1068,28 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # 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
@@ -861,6 +1125,7 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -885,17 +1150,24 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_RWLOCK is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -909,6 +1181,8 @@
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -916,11 +1190,23 @@
 # CONFIG_CRYPTO_AES is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index f46a07a..a065349 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -27,6 +27,7 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
+#include <asm/sections.h>
 
 int split_tlb;
 int dcache_stride;
@@ -207,6 +208,9 @@
 
 	/* "New and Improved" version from Jim Hull 
 	 *	(1 << (cc_block-1)) * (cc_line << (4 + cnf.cc_shift))
+	 * The following CAFL_STRIDE is an optimized version, see
+	 * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023625.html
+	 * http://lists.parisc-linux.org/pipermail/parisc-linux/2004-June/023671.html
 	 */
 #define CAFL_STRIDE(cnf) (cnf.cc_line << (3 + cnf.cc_block + cnf.cc_shift))
 	dcache_stride = CAFL_STRIDE(cache_info.dc_conf);
@@ -266,7 +270,6 @@
 	unsigned long offset;
 	unsigned long addr;
 	pgoff_t pgoff;
-	pte_t *pte;
 	unsigned long pfn = page_to_pfn(page);
 
 
@@ -297,21 +300,16 @@
 		 * taking a page fault if the pte doesn't exist.
 		 * This is just for speed.  If the page translation
 		 * isn't there, there's no point exciting the
-		 * nadtlb handler into a nullification frenzy */
-
-
-  		if(!(pte = translation_exists(mpnt, addr)))
-			continue;
-
-		/* make sure we really have this page: the private
+		 * nadtlb handler into a nullification frenzy.
+		 *
+		 * Make sure we really have this page: the private
 		 * mappings may cover this area but have COW'd this
-		 * particular page */
-		if(pte_pfn(*pte) != pfn)
-  			continue;
-
-		__flush_cache_page(mpnt, addr);
-
-		break;
+		 * particular page.
+		 */
+  		if (translation_exists(mpnt, addr, pfn)) {
+			__flush_cache_page(mpnt, addr);
+			break;
+		}
 	}
 	flush_dcache_mmap_unlock(mapping);
 }
@@ -339,17 +337,15 @@
 void parisc_setup_cache_timing(void)
 {
 	unsigned long rangetime, alltime;
-	extern char _text;	/* start of kernel code, defined by linker */
-	extern char _end;	/* end of BSS, defined by linker */
 	unsigned long size;
 
 	alltime = mfctl(16);
 	flush_data_cache();
 	alltime = mfctl(16) - alltime;
 
-	size = (unsigned long)(&_end - _text);
+	size = (unsigned long)(_end - _text);
 	rangetime = mfctl(16);
-	flush_kernel_dcache_range((unsigned long)&_text, size);
+	flush_kernel_dcache_range((unsigned long)_text, size);
 	rangetime = mfctl(16) - rangetime;
 
 	printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n",
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index d34bbe7..988844a 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -46,36 +46,51 @@
 	.bus_id = "parisc",
 };
 
-#define for_each_padev(padev) \
-	for (padev = next_dev(&root); padev != NULL; \
-			padev = next_dev(&padev->dev))
+static inline int check_dev(struct device *dev)
+{
+	if (dev->bus == &parisc_bus_type) {
+		struct parisc_device *pdev;
+		pdev = to_parisc_device(dev);
+		return pdev->id.hw_type != HPHW_FAULTY;
+	}
+	return 1;
+}
 
-#define check_dev(padev) \
-	(padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev)
+static struct device *
+parse_tree_node(struct device *parent, int index, struct hardware_path *modpath);
+
+struct recurse_struct {
+	void * obj;
+	int (*fn)(struct device *, void *);
+};
+
+static int descend_children(struct device * dev, void * data)
+{
+	struct recurse_struct * recurse_data = (struct recurse_struct *)data;
+
+	if (recurse_data->fn(dev, recurse_data->obj))
+		return 1;
+	else
+		return device_for_each_child(dev, recurse_data, descend_children);
+}
 
 /**
- * next_dev - enumerates registered devices
- * @dev: the previous device returned from next_dev
+ *	for_each_padev - Iterate over all devices in the tree
+ *	@fn:	Function to call for each device.
+ *	@data:	Data to pass to the called function.
  *
- * next_dev does a depth-first search of the tree, returning parents
- * before children.  Returns NULL when there are no more devices.
+ *	This performs a depth-first traversal of the tree, calling the
+ *	function passed for each node.  It calls the function for parents
+ *	before children.
  */
-static struct parisc_device *next_dev(struct device *dev)
+
+static int for_each_padev(int (*fn)(struct device *, void *), void * data)
 {
-	if (!list_empty(&dev->children)) {
-		dev = list_to_dev(dev->children.next);
-		return check_dev(to_parisc_device(dev));
-	}
-
-	while (dev != &root) {
-		if (dev->node.next != &dev->parent->children) {
-			dev = list_to_dev(dev->node.next);
-			return to_parisc_device(dev);
-		}
-		dev = dev->parent;
-	}
-
-	return NULL;
+	struct recurse_struct recurse_data = {
+		.obj	= data,
+		.fn	= fn,
+	};
+	return device_for_each_child(&root, &recurse_data, descend_children);
 }
 
 /**
@@ -105,12 +120,6 @@
 	return 0;
 }
 
-static void claim_device(struct parisc_driver *driver, struct parisc_device *dev)
-{
-	dev->driver = driver;
-	request_mem_region(dev->hpa, 0x1000, driver->name);
-}
-
 static int parisc_driver_probe(struct device *dev)
 {
 	int rc;
@@ -119,8 +128,8 @@
 
 	rc = pa_drv->probe(pa_dev);
 
-	if(!rc)
-		claim_device(pa_drv, pa_dev);
+	if (!rc)
+		pa_dev->driver = pa_drv;
 
 	return rc;
 }
@@ -131,7 +140,6 @@
 	struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
 	if (pa_drv->remove)
 		pa_drv->remove(pa_dev);
-	release_mem_region(pa_dev->hpa, 0x1000);
 
 	return 0;
 }
@@ -173,6 +181,24 @@
 }
 EXPORT_SYMBOL(register_parisc_driver);
 
+
+struct match_count {
+	struct parisc_driver * driver;
+	int count;
+};
+
+static int match_and_count(struct device * dev, void * data)
+{
+	struct match_count * m = data;
+	struct parisc_device * pdev = to_parisc_device(dev);
+
+	if (check_dev(dev)) {
+		if (match_device(m->driver, pdev))
+			m->count++;
+	}
+	return 0;
+}
+
 /**
  * count_parisc_driver - count # of devices this driver would match
  * @driver: the PA-RISC driver to try
@@ -182,15 +208,14 @@
  */
 int count_parisc_driver(struct parisc_driver *driver)
 {
-	struct parisc_device *device;
-	int cnt = 0;
+	struct match_count m = {
+		.driver	= driver,
+		.count	= 0,
+	};
 
-	for_each_padev(device) {
-		if (match_device(driver, device))
-			cnt++;
-	}
+	for_each_padev(match_and_count, &m);
 
-	return cnt;
+	return m.count;
 }
 
 
@@ -206,14 +231,34 @@
 }
 EXPORT_SYMBOL(unregister_parisc_driver);
 
+struct find_data {
+	unsigned long hpa;
+	struct parisc_device * dev;
+};
+
+static int find_device(struct device * dev, void * data)
+{
+	struct parisc_device * pdev = to_parisc_device(dev);
+	struct find_data * d = (struct find_data*)data;
+
+	if (check_dev(dev)) {
+		if (pdev->hpa.start == d->hpa) {
+			d->dev = pdev;
+			return 1;
+		}
+	}
+	return 0;
+}
+
 static struct parisc_device *find_device_by_addr(unsigned long hpa)
 {
-	struct parisc_device *dev;
-	for_each_padev(dev) {
-		if (dev->hpa == hpa)
-			return dev;
-	}
-	return NULL;
+	struct find_data d = {
+		.hpa	= hpa,
+	};
+	int ret;
+
+	ret = for_each_padev(find_device, &d);
+	return ret ? d.dev : NULL;
 }
 
 /**
@@ -387,6 +432,23 @@
 	return dev;
 }
 
+struct match_id_data {
+	char id;
+	struct parisc_device * dev;
+};
+
+static int match_by_id(struct device * dev, void * data)
+{
+	struct parisc_device * pdev = to_parisc_device(dev);
+	struct match_id_data * d = data;
+
+	if (pdev->hw_path == d->id) {
+		d->dev = pdev;
+		return 1;
+	}
+	return 0;
+}
+
 /**
  * alloc_tree_node - returns a device entry in the iotree
  * @parent: the parent node in the tree
@@ -397,15 +459,13 @@
  */
 static struct parisc_device * alloc_tree_node(struct device *parent, char id)
 {
-	struct device *dev;
-
-	list_for_each_entry(dev, &parent->children, node) {
-		struct parisc_device *padev = to_parisc_device(dev);
-		if (padev->hw_path == id)
-			return padev;
-	}
-
-	return create_tree_node(id, parent);
+	struct match_id_data d = {
+		.id = id,
+	};
+	if (device_for_each_child(parent, &d, match_by_id))
+		return d.dev;
+	else
+		return create_tree_node(id, parent);
 }
 
 static struct parisc_device *create_parisc_device(struct hardware_path *modpath)
@@ -439,10 +499,8 @@
 
 	dev = create_parisc_device(mod_path);
 	if (dev->id.hw_type != HPHW_FAULTY) {
-		char p[64];
-		print_pa_hwpath(dev, p);
 		printk("Two devices have hardware path %s.  Please file a bug with HP.\n"
-			"In the meantime, you could try rearranging your cards.\n", p);
+			"In the meantime, you could try rearranging your cards.\n", parisc_pathname(dev));
 		return NULL;
 	}
 
@@ -451,12 +509,27 @@
 	dev->id.hversion_rev = iodc_data[1] & 0x0f;
 	dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) |
 			(iodc_data[5] << 8) | iodc_data[6];
-	dev->hpa = hpa;
+	dev->hpa.name = parisc_pathname(dev);
+	dev->hpa.start = hpa;
+	if (hpa == 0xf4000000 || hpa == 0xf6000000 ||
+	    hpa == 0xf8000000 || hpa == 0xfa000000) {
+		dev->hpa.end = hpa + 0x01ffffff;
+	} else {
+		dev->hpa.end = hpa + 0xfff;
+	}
+	dev->hpa.flags = IORESOURCE_MEM;
 	name = parisc_hardware_description(&dev->id);
 	if (name) {
 		strlcpy(dev->name, name, sizeof(dev->name));
 	}
 
+	/* Silently fail things like mouse ports which are subsumed within
+	 * the keyboard controller
+	 */
+	if ((hpa & 0xfff) == 0 && insert_resource(&iomem_resource, &dev->hpa))
+		printk("Unable to claim HPA %lx for device %s\n",
+				hpa, name);
+
 	return dev;
 }
 
@@ -555,6 +628,33 @@
 	return (curr->hw_path == id);
 }
 
+struct parse_tree_data {
+	int index;
+	struct hardware_path * modpath;
+	struct device * dev;
+};
+
+static int check_parent(struct device * dev, void * data)
+{
+	struct parse_tree_data * d = data;
+
+	if (check_dev(dev)) {
+		if (dev->bus == &parisc_bus_type) {
+			if (match_parisc_device(dev, d->index, d->modpath))
+				d->dev = dev;
+		} else if (is_pci_dev(dev)) {
+			if (match_pci_device(dev, d->index, d->modpath))
+				d->dev = dev;
+		} else if (dev->bus == NULL) {
+			/* we are on a bus bridge */
+			struct device *new = parse_tree_node(dev, d->index, d->modpath);
+			if (new)
+				d->dev = new;
+		}
+	}
+	return d->dev != NULL;
+}
+
 /**
  * parse_tree_node - returns a device entry in the iotree
  * @parent: the parent node in the tree
@@ -568,24 +668,18 @@
 static struct device *
 parse_tree_node(struct device *parent, int index, struct hardware_path *modpath)
 {
-	struct device *device;
-	 
-	list_for_each_entry(device, &parent->children, node) {
-		if (device->bus == &parisc_bus_type) {
-			if (match_parisc_device(device, index, modpath))
-				return device;
-		} else if (is_pci_dev(device)) {
-			if (match_pci_device(device, index, modpath))
-				return device;
-		} else if (device->bus == NULL) {
-			/* we are on a bus bridge */
-			struct device *new = parse_tree_node(device, index, modpath);
-			if (new)
-				return new;
-		}
-	}
+	struct parse_tree_data d = {
+		.index          = index,
+		.modpath        = modpath,
+	};
 
-	return NULL;
+	struct recurse_struct recurse_data = {
+		.obj	= &d,
+		.fn	= check_parent,
+	};
+
+	device_for_each_child(parent, &recurse_data, descend_children);
+	return d.dev;
 }
 
 /**
@@ -636,7 +730,7 @@
         ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT))
 
 #define IS_LOWER_PORT(dev) \
-        ((gsc_readl(dev->hpa + offsetof(struct bc_module, io_status)) \
+        ((gsc_readl(dev->hpa.start + offsetof(struct bc_module, io_status)) \
                 & BC_PORT_MASK) == BC_LOWER_PORT)
 
 #define MAX_NATIVE_DEVICES 64
@@ -645,8 +739,8 @@
 #define FLEX_MASK 	F_EXTEND(0xfffc0000)
 #define IO_IO_LOW	offsetof(struct bc_module, io_io_low)
 #define IO_IO_HIGH	offsetof(struct bc_module, io_io_high)
-#define READ_IO_IO_LOW(dev)  (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_LOW)
-#define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_HIGH)
+#define READ_IO_IO_LOW(dev)  (unsigned long)(signed int)gsc_readl(dev->hpa.start + IO_IO_LOW)
+#define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa.start + IO_IO_HIGH)
 
 static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
                             struct device *parent);
@@ -655,10 +749,10 @@
 {
 	unsigned long io_io_low, io_io_high;
 
-	if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
+	if (!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
 		return;
 
-	if(dev->id.hw_type == HPHW_IOA) {
+	if (dev->id.hw_type == HPHW_IOA) {
 		io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16);
 		io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET;
 	} else {
@@ -731,7 +825,7 @@
 
 	print_pa_hwpath(dev, hw_path);
 	printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
-		++count, dev->name, dev->hpa, hw_path, dev->id.hw_type,
+		++count, dev->name, dev->hpa.start, hw_path, dev->id.hw_type,
 		dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
 
 	if (dev->num_addrs) {
@@ -753,13 +847,20 @@
 	get_device(&root);
 }
 
+
+static int print_one_device(struct device * dev, void * data)
+{
+	struct parisc_device * pdev = to_parisc_device(dev);
+
+	if (check_dev(dev))
+		print_parisc_device(pdev);
+	return 0;
+}
+
 /**
  * print_parisc_devices - Print out a list of devices found in this system
  */
 void print_parisc_devices(void)
 {
-	struct parisc_device *dev;
-	for_each_padev(dev) {
-		print_parisc_device(dev);
-	}
+	for_each_padev(print_one_device, NULL);
 }
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index be0f07f..c7e66ee 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -30,14 +30,14 @@
  *  - save registers to kernel stack and handle in assembly or C */
 
 
+#include <asm/psw.h>
 #include <asm/assembly.h>	/* for LDREG/STREG defines */
 #include <asm/pgtable.h>
-#include <asm/psw.h>
 #include <asm/signal.h>
 #include <asm/unistd.h>
 #include <asm/thread_info.h>
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define CMPIB           cmpib,*
 #define CMPB            cmpb,*
 #define COND(x)		*x
@@ -67,19 +67,22 @@
 
 	/* Switch to virtual mapping, trashing only %r1 */
 	.macro  virt_map
-	rsm     PSW_SM_Q,%r0
-	tovirt_r1 %r29
-	mfsp	%sr7, %r1
-	or,=    %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
-	mtsp	%r1, %sr3
+	/* pcxt_ssm_bug */
+	rsm	PSW_SM_I, %r0	/* barrier for "Relied upon Translation */
 	mtsp	%r0, %sr4
 	mtsp	%r0, %sr5
+	mfsp	%sr7, %r1
+	or,=    %r0,%r1,%r0	/* Only save sr7 in sr3 if sr7 != 0 */
+	mtsp	%r1, %sr3
+	tovirt_r1 %r29
+	load32	KERNEL_PSW, %r1
+
+	rsm     PSW_SM_QUIET,%r0	/* second "heavy weight" ctl op */
 	mtsp	%r0, %sr6
 	mtsp	%r0, %sr7
-	load32	KERNEL_PSW, %r1
-	mtctl	%r1, %cr22
 	mtctl	%r0, %cr17	/* Clear IIASQ tail */
 	mtctl	%r0, %cr17	/* Clear IIASQ head */
+	mtctl	%r1, %ipsw
 	load32	4f, %r1
 	mtctl	%r1, %cr18	/* Set IIAOQ tail */
 	ldo	4(%r1), %r1
@@ -214,7 +217,7 @@
 	va  = r8	/* virtual address for which the trap occured */
 	spc = r24	/* space for which the trap occured */
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 
 	/*
 	 * itlb miss interruption handler (parisc 1.1 - 32 bit)
@@ -236,7 +239,7 @@
 
 	.macro	itlb_20 code
 	mfctl	%pcsq, spc
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	b       itlb_miss_20w
 #else
 	b	itlb_miss_20
@@ -246,7 +249,7 @@
 	.align		32
 	.endm
 	
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	/*
 	 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
 	 *
@@ -283,7 +286,7 @@
 	.macro	naitlb_20 code
 
 	mfctl	%isr,spc
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	b       itlb_miss_20w
 #else
 	b	itlb_miss_20
@@ -296,7 +299,7 @@
 	.align		32
 	.endm
 	
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	/*
 	 * dtlb miss interruption handler (parisc 1.1 - 32 bit)
 	 */
@@ -318,7 +321,7 @@
 	.macro	dtlb_20 code
 
 	mfctl	%isr, spc
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	b       dtlb_miss_20w
 #else
 	b	dtlb_miss_20
@@ -328,7 +331,7 @@
 	.align		32
 	.endm
 	
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	/* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
 
 	.macro	nadtlb_11 code
@@ -346,7 +349,7 @@
 	.macro	nadtlb_20 code
 
 	mfctl	%isr,spc
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	b       nadtlb_miss_20w
 #else
 	b       nadtlb_miss_20
@@ -356,7 +359,7 @@
 	.align		32
 	.endm
 	
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	/*
 	 * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
 	 */
@@ -378,7 +381,7 @@
 	.macro	dbit_20 code
 
 	mfctl	%isr,spc
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	b       dbit_trap_20w
 #else
 	b	dbit_trap_20
@@ -391,7 +394,7 @@
 	/* The following are simple 32 vs 64 bit instruction
 	 * abstractions for the macros */
 	.macro		EXTR	reg1,start,length,reg2
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	extrd,u		\reg1,32+\start,\length,\reg2
 #else
 	extrw,u		\reg1,\start,\length,\reg2
@@ -399,7 +402,7 @@
 	.endm
 
 	.macro		DEP	reg1,start,length,reg2
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depd		\reg1,32+\start,\length,\reg2
 #else
 	depw		\reg1,\start,\length,\reg2
@@ -407,7 +410,7 @@
 	.endm
 
 	.macro		DEPI	val,start,length,reg
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi		\val,32+\start,\length,\reg
 #else
 	depwi		\val,\start,\length,\reg
@@ -418,7 +421,7 @@
 	 * fault.  We have to extract this and place it in the va,
 	 * zeroing the corresponding bits in the space register */
 	.macro		space_adjust	spc,va,tmp
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	extrd,u		\spc,63,SPACEID_SHIFT,\tmp
 	depd		%r0,63,SPACEID_SHIFT,\spc
 	depd		\tmp,31,SPACEID_SHIFT,\va
@@ -476,7 +479,7 @@
 	bb,>=,n		\pmd,_PxD_PRESENT_BIT,\fault
 	DEP		%r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
 	copy		\pmd,%r9
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	shld		%r9,PxD_VALUE_SHIFT,\pmd
 #else
 	shlw		%r9,PxD_VALUE_SHIFT,\pmd
@@ -607,7 +610,7 @@
 	.macro		do_alias	spc,tmp,tmp1,va,pte,prot,fault
 	cmpib,COND(<>),n 0,\spc,\fault
 	ldil		L%(TMPALIAS_MAP_START),\tmp
-#if defined(__LP64__) && (TMPALIAS_MAP_START >= 0x80000000)
+#if defined(CONFIG_64BIT) && (TMPALIAS_MAP_START >= 0x80000000)
 	/* on LP64, ldi will sign extend into the upper 32 bits,
 	 * which is behaviour we don't want */
 	depdi		0,31,32,\tmp
@@ -621,7 +624,7 @@
 	 * OK, it is in the temp alias region, check whether "from" or "to".
 	 * Check "subtle" note in pacache.S re: r23/r26.
 	 */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	extrd,u,*=	\va,41,1,%r0
 #else
 	extrw,u,=	\va,9,1,%r0
@@ -688,7 +691,7 @@
 	def		30
 	def		31
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 
 	.export fault_vector_11
 	
@@ -761,7 +764,7 @@
 
 	copy	%r30, %r1
 	ldo	PT_SZ_ALGN(%r30),%r30
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* Yo, function pointers in wide mode are little structs... -PB */
 	ldd	24(%r26), %r2
 	STREG	%r2, PT_GR27(%r1)	/* Store childs %dp */
@@ -777,7 +780,7 @@
 	or	%r26, %r24, %r26      /* will have kernel mappings.	 */
 	ldi	1, %r25			/* stack_start, signals kernel thread */
 	stw	%r0, -52(%r30)	     	/* user_tid */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 	BL	do_fork, %r2
@@ -806,7 +809,7 @@
 
 	LDREG	TI_TASK-THREAD_SZ_ALGN(%r30), %r1
 	LDREG	TASK_PT_GR25(%r1), %r26
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	LDREG	TASK_PT_GR27(%r1), %r27
 	LDREG	TASK_PT_GR22(%r1), %r22
 #endif
@@ -814,11 +817,16 @@
 	ble	0(%sr7, %r1)
 	copy	%r31, %r2
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 	loadgp				/* Thread could have been in a module */
 #endif
+#ifndef CONFIG_64BIT
 	b	sys_exit
+#else
+	load32	sys_exit, %r1
+	bv	%r0(%r1)
+#endif
 	ldi	0, %r26
 
 	.import	sys_execve, code
@@ -830,7 +838,7 @@
 	STREG	%r26, PT_GR26(%r16)
 	STREG	%r25, PT_GR25(%r16)
 	STREG	%r24, PT_GR24(%r16)
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 	BL	sys_execve, %r2
@@ -855,6 +863,7 @@
 _switch_to:
 	STREG	 %r2, -RP_OFFSET(%r30)
 
+	callee_save_float
 	callee_save
 
 	load32	_switch_to_ret, %r2
@@ -871,6 +880,7 @@
 _switch_to_ret:
 	mtctl	%r0, %cr0		/* Needed for single stepping */
 	callee_rest
+	callee_rest_float
 
 	LDREG	-RP_OFFSET(%r30), %r2
 	bv	%r0(%r2)
@@ -888,9 +898,6 @@
 	 * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
 	 * adjust IASQ[0..1].
 	 *
-	 * Note that the following code uses a "relied upon translation".
-	 * See the parisc ACD for details. The ssm is necessary due to a
-	 * PCXT bug.
 	 */
 
 	.align 4096
@@ -911,7 +918,7 @@
 	STREG	%r19,PT_IAOQ1(%r16)
 	LDREG   PT_PSW(%r16),%r19
 	load32	USER_PSW_MASK,%r1
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	load32	USER_PSW_HI_MASK,%r20
 	depd    %r20,31,32,%r1
 #endif
@@ -955,7 +962,7 @@
 	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
 	** irq_stat[] is defined using ____cacheline_aligned.
 	*/
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	shld	%r1, 6, %r20
 #else
 	shlw	%r1, 5, %r20
@@ -963,9 +970,6 @@
 	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
-	LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
-	cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
-
 intr_check_resched:
 
 	/* check for reschedule */
@@ -985,24 +989,19 @@
 	rest_fp         %r1
 	rest_general    %r29
 
-	/* Create a "relied upon translation" PA 2.0 Arch. F-5 */
-	ssm		0,%r0
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
+	/* inverse of virt_map */
+	pcxt_ssm_bug
+	rsm             PSW_SM_QUIET,%r0	/* prepare for rfi */
 	tophys_r1       %r29
-	rsm             (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
 
 	/* Restore space id's and special cr's from PT_REGS
-	 * structure pointed to by r29 */
+	 * structure pointed to by r29
+	 */
 	rest_specials	%r29
 
-	/* Important: Note that rest_stack restores r29
-	 * last (we are using it)! It also restores r1 and r30. */
+	/* IMPORTANT: rest_stack restores r29 last (we are using it)!
+	 * It also restores r1 and r30.
+	 */
 	rest_stack
 
 	rfi
@@ -1015,17 +1014,6 @@
 	nop
 	nop
 
-	.import do_softirq,code
-intr_do_softirq:
-	bl      do_softirq,%r2
-#ifdef __LP64__
-	ldo	-16(%r30),%r29		/* Reference param save area */
-#else
-	nop
-#endif
-	b       intr_check_resched
-	nop
-
 	.import schedule,code
 intr_do_resched:
 	/* Only do reschedule if we are returning to user space */
@@ -1036,12 +1024,17 @@
 	CMPIB= 0,%r20,intr_restore /* backward */
 	nop
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 
 	ldil	L%intr_check_sig, %r2
+#ifndef CONFIG_64BIT
 	b	schedule
+#else
+	load32	schedule, %r20
+	bv	%r0(%r20)
+#endif
 	ldo	R%intr_check_sig(%r2), %r2
 
 
@@ -1064,7 +1057,7 @@
 
 	copy	%r0, %r24			/* unsigned long in_syscall */
 	copy	%r16, %r25			/* struct pt_regs *regs */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
 #endif
 
@@ -1088,7 +1081,7 @@
 	mfctl	%cr31,%r1
 	copy	%r30,%r17
 	/* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi	0,63,15,%r17
 #else
 	depi	0,31,15,%r17
@@ -1115,7 +1108,7 @@
 
 	ldil	L%intr_return, %r2
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29	/* Reference param save area */
 #endif
 
@@ -1153,15 +1146,17 @@
 
 	CMPIB=,n        6,%r26,skip_save_ior
 
-	/* save_specials left ipsw value in r8 for us to test */
 
 	mfctl           %cr20, %r16 /* isr */
+	nop		/* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */
 	mfctl           %cr21, %r17 /* ior */
 
-#ifdef __LP64__
+
+#ifdef CONFIG_64BIT
 	/*
 	 * If the interrupted code was running with W bit off (32 bit),
 	 * clear the b bits (bits 0 & 1) in the ior.
+	 * save_specials left ipsw value in r8 for us to test.
 	 */
 	extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
 	depdi           0,1,2,%r17
@@ -1192,7 +1187,7 @@
 	loadgp
 
 	copy		%r29, %r25	/* arg1 is pt_regs */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo		-16(%r30),%r29	/* Reference param save area */
 #endif
 
@@ -1230,7 +1225,7 @@
 	spc  = r24	/* space for which the trap occured */
 	ptp = r25	/* page directory/page table pointer */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
 dtlb_miss_20w:
 	space_adjust	spc,va,t0
@@ -1487,10 +1482,10 @@
 	add,l           %r1,%r24,%r1           /* doesn't affect c/b bits */
 
 nadtlb_nullify:
-	mfctl           %cr22,%r8              /* Get ipsw */
+	mfctl           %ipsw,%r8
 	ldil            L%PSW_N,%r9
 	or              %r8,%r9,%r8            /* Set PSW_N */
-	mtctl           %r8,%cr22
+	mtctl           %r8,%ipsw
 
 	rfir
 	nop
@@ -1521,7 +1516,7 @@
 	nop
 
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 itlb_miss_20w:
 
 	/*
@@ -1588,7 +1583,7 @@
 
 #endif
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
 dbit_trap_20w:
 	space_adjust	spc,va,t0
@@ -1797,7 +1792,7 @@
 
 	STREG	%r2,-RP_OFFSET(%r30)
 	ldo	FRAME_SIZE(%r30),%r30
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 
@@ -1847,7 +1842,7 @@
 
 	STREG	%r2,-RP_OFFSET(%r30)
 	ldo	FRAME_SIZE(%r30),%r30
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 
@@ -1869,7 +1864,7 @@
 
 	STREG	%r2,-RP_OFFSET(%r30)
 	ldo	FRAME_SIZE(%r30),%r30
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 
@@ -1897,10 +1892,10 @@
 
 	STREG %r2,-RP_OFFSET(%r30)
 	ldo FRAME_SIZE(%r30),%r30
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
-	bl \execve,%r2
+	BL \execve,%r2
 	copy %r1,%arg0
 
 	ldo -FRAME_SIZE(%r30),%r30
@@ -1923,7 +1918,7 @@
 sys_execve_wrapper:
 	execve_wrapper sys_execve
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	.export sys32_execve_wrapper
 	.import sys32_execve
 
@@ -1937,7 +1932,7 @@
 	ldo	TASK_REGS(%r26),%r26	/* get pt regs */
 	/* Don't save regs, we are going to restore them from sigcontext. */
 	STREG	%r2, -RP_OFFSET(%r30)
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	FRAME_SIZE(%r30), %r30
 	BL	sys_rt_sigreturn,%r2
 	ldo	-16(%r30),%r29		/* Reference param save area */
@@ -1968,7 +1963,7 @@
 	ldo	TASK_REGS(%r1),%r24	/* get pt regs */
 	LDREG	TASK_PT_GR30(%r24),%r24
 	STREG	%r2, -RP_OFFSET(%r30)
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	FRAME_SIZE(%r30), %r30
 	b,l	do_sigaltstack,%r2
 	ldo	-16(%r30),%r29		/* Reference param save area */
@@ -1982,7 +1977,7 @@
 	bv	%r0(%r2)
 	nop
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	.export sys32_sigaltstack_wrapper
 sys32_sigaltstack_wrapper:
 	/* Get the user stack pointer */
@@ -2006,7 +2001,7 @@
 	reg_save %r24
 
 	STREG	%r2, -RP_OFFSET(%r30)
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	FRAME_SIZE(%r30), %r30
 	b,l	sys_rt_sigsuspend,%r2
 	ldo	-16(%r30),%r29		/* Reference param save area */
@@ -2079,7 +2074,7 @@
 	ldw     TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
 
 	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	shld	%r26, 6, %r20
 #else
 	shlw	%r26, 5, %r20
@@ -2087,9 +2082,6 @@
 	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
-	LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
-	cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
-
 syscall_check_resched:
 
 	/* check for reschedule */
@@ -2144,7 +2136,7 @@
 
 	depi	3,31,2,%r31			   /* ensure return to user mode. */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* decide whether to reset the wide mode bit
 	 *
 	 * For a syscall, the W bit is stored in the lowest bit
@@ -2227,20 +2219,10 @@
 	b	intr_restore
 	nop
 
-	.import do_softirq,code
-syscall_do_softirq:
-	bl      do_softirq,%r2
-	nop
-	/* NOTE: We enable I-bit incase we schedule later,
-	 * and we might be going back to userspace if we were
-	 * traced. */
-	b       syscall_check_resched
-	ssm     PSW_SM_I, %r0  /* do_softirq returns with I bit off */
-
 	.import schedule,code
 syscall_do_resched:
 	BL	schedule,%r2
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #else
 	nop
@@ -2260,7 +2242,7 @@
 
 	ldi	1, %r24				/* unsigned long in_syscall */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
 #endif
 	BL	do_signal,%r2
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index f244fb2..553f8fe 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -83,15 +83,15 @@
 int parisc_narrow_firmware = 1;
 #endif
 
-/* on all currently-supported platforms, IODC I/O calls are always
- * 32-bit calls, and MEM_PDC calls are always the same width as the OS.
- * This means Cxxx boxes can't run wide kernels right now. -PB
+/* On most currently-supported platforms, IODC I/O calls are 32-bit calls
+ * and MEM_PDC calls are always the same width as the OS.
+ * Some PAT boxes may have 64-bit IODC I/O.
  *
- * CONFIG_PDC_NARROW has been added to allow 64-bit kernels to run on
- * systems with 32-bit MEM_PDC calls. This will allow wide kernels to
- * run on Cxxx boxes now. -RB
- *
- * Note that some PAT boxes may have 64-bit IODC I/O...
+ * Ryan Bradetich added the now obsolete CONFIG_PDC_NARROW to allow
+ * 64-bit kernels to run on systems with 32-bit MEM_PDC calls.
+ * This allowed wide kernels to run on Cxxx boxes.
+ * We now detect 32-bit-only PDC and dynamically switch to 32-bit mode
+ * when running a 64-bit kernel on such boxes (e.g. C200 or C360).
  */
 
 #ifdef __LP64__
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 28405ed..0b47afc 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -12,7 +12,7 @@
  * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
  */
 
-#include <linux/autoconf.h>	/* for CONFIG_SMP */
+#include <linux/config.h>	/* for CONFIG_SMP */
 
 #include <asm/asm-offsets.h>
 #include <asm/psw.h>
@@ -36,10 +36,10 @@
 	.align	4
 	.import init_thread_union,data
 	.import fault_vector_20,code    /* IVA parisc 2.0 32 bit */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
 	.import	$global$		/* forward declaration */
-#endif /*!LP64*/
+#endif /*!CONFIG_64BIT*/
 	.export stext
 	.export _stext,data		/* Kernel want it this way! */
 _stext:
@@ -76,7 +76,7 @@
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
 	mtctl		%r4,%cr25	/* Initialize user root pointer */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* Set pmd in pgd */
 	load32		PA(pmd0),%r5
 	shrd            %r5,PxD_VALUE_SHIFT,%r3	
@@ -99,7 +99,7 @@
 	stw		%r3,0(%r4)
 	ldo		(ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
 	addib,>		-1,%r1,1b
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo             ASM_PMD_ENTRY_SIZE(%r4),%r4
 #else
 	ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
@@ -170,7 +170,7 @@
 	stw		%r0,0x28(%r0)	/* MEM_RENDEZ_HI */
 #endif /*CONFIG_SMP*/
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	tophys_r1	%sp
 
 	/* Save the rfi target address */
@@ -224,8 +224,6 @@
 	mtctl	%r0,%cr12
 	mtctl	%r0,%cr13
 
-	/* Prepare to RFI! Man all the cannons! */
-
 	/* Initialize the global data pointer */
 	loadgp
 
@@ -235,7 +233,7 @@
 	 * following short sequence of instructions can determine this
 	 * (without being illegal on a PA1.1 machine).
 	 */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	ldi		32,%r10
 	mtctl		%r10,%cr11
 	.level 2.0
@@ -248,52 +246,22 @@
 
 $is_pa20:
 	.level		LEVEL /* restore 1.1 || 2.0w */
-#endif /*!LP64*/
+#endif /*!CONFIG_64BIT*/
 	load32		PA(fault_vector_20),%r10
 
 $install_iva:
 	mtctl		%r10,%cr14
 
-#ifdef __LP64__
-	b		aligned_rfi
+	b		aligned_rfi  /* Prepare to RFI! Man all the cannons! */
 	nop
 
-	.align          256
+	.align 128
 aligned_rfi:
-	ssm             0,0
-	nop             /* 1 */
-	nop             /* 2 */
-	nop             /* 3 */
-	nop             /* 4 */
-	nop             /* 5 */
-	nop             /* 6 */
-	nop             /* 7 */
-	nop             /* 8 */
-#endif
+	pcxt_ssm_bug
 
-#ifdef __LP64__ /* move to psw.h? */
-#define		PSW_BITS	PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R
-#else
-#define		PSW_BITS	PSW_SM_Q
-#endif
+	rsm		PSW_SM_QUIET,%r0	/* off troublesome PSW bits */
+	/* Don't need NOPs, have 8 compliant insn before rfi */
 
-$rfi:	
-	/* turn off troublesome PSW bits */
-	rsm		PSW_BITS,%r0
-
-	/* kernel PSW:
-	 *  - no interruptions except HPMC and TOC (which are handled by PDC)
-	 *  - Q bit set (IODC / PDC interruptions)
-	 *  - big-endian
-	 *  - virtually mapped
-	 */
-	load32		KERNEL_PSW,%r10
-	mtctl		%r10,%ipsw
-
-	/* Set the space pointers for the post-RFI world
-	** Clear the two-level IIA Space Queue, effectively setting
-	** Kernel space.
-	*/
 	mtctl		%r0,%cr17	/* Clear IIASQ tail */
 	mtctl		%r0,%cr17	/* Clear IIASQ head */
 
@@ -301,8 +269,11 @@
 	mtctl		%r11,%cr18	/* IIAOQ head */
 	ldo		4(%r11),%r11
 	mtctl		%r11,%cr18	/* IIAOQ tail */
+
+	load32		KERNEL_PSW,%r10
+	mtctl		%r10,%ipsw
 	
-	/* Jump to hyperspace */
+	/* Jump through hyperspace to Virt Mode */
 	rfi
 	nop
 
@@ -313,7 +284,7 @@
 	.import smp_init_current_idle_task,data
 	.import	smp_callin,code
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 smp_callin_rtn:
         .proc
 	.callinfo
@@ -321,7 +292,7 @@
 	nop
 	nop
         .procend
-#endif /*!LP64*/
+#endif /*!CONFIG_64BIT*/
 
 /***************************************************************************
 * smp_slave_stext is executed by all non-monarch Processors when the Monarch
@@ -356,7 +327,7 @@
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
 	mtctl		%r4,%cr25	/* Initialize user root pointer */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* Setup PDCE_PROC entry */
 	copy            %arg0,%r3
 #else
@@ -373,7 +344,7 @@
 
 	.procend
 #endif /* CONFIG_SMP */
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	.data
 
 	.align	4
@@ -383,4 +354,4 @@
 	.size	$global$,4
 $global$:	
 	.word 0
-#endif /*!LP64*/
+#endif /*!CONFIG_64BIT*/
diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
index 1d3824b..0a33110 100644
--- a/arch/parisc/kernel/ioctl32.c
+++ b/arch/parisc/kernel/ioctl32.c
@@ -104,12 +104,9 @@
 	}
 
 out:
-	if (kversion.name)
-		kfree(kversion.name);
-	if (kversion.date)
-		kfree(kversion.date);
-	if (kversion.desc)
-		kfree(kversion.desc);
+	kfree(kversion.name);
+	kfree(kversion.date);
+	kfree(kversion.desc);
 	return ret;
 }
 
@@ -166,9 +163,7 @@
 			ret = -EFAULT;
 	}
 
-	if (karg.unique != NULL)
-		kfree(karg.unique);
-
+	kfree(karg.unique);
 	return ret;
 }
 
@@ -265,7 +260,6 @@
 	}
 
 	kfree(karg.list);
-
 	return ret;
 }
 
@@ -305,7 +299,6 @@
 
 out:
 	kfree(karg.list);
-
 	return ret;
 }
 
@@ -494,15 +487,10 @@
 	}
 
 out:
-	if (karg.send_indices)
-		kfree(karg.send_indices);
-	if (karg.send_sizes)
-		kfree(karg.send_sizes);
-	if (karg.request_indices)
-		kfree(karg.request_indices);
-	if (karg.request_sizes)
-		kfree(karg.request_sizes);
-
+	kfree(karg.send_indices);
+	kfree(karg.send_sizes);
+	kfree(karg.request_indices);
+	kfree(karg.request_sizes);
 	return ret;
 }
 
@@ -555,9 +543,7 @@
 			ret = -EFAULT;
 	}
 
-	if (karg.contexts)
-		kfree(karg.contexts);
-
+	kfree(karg.contexts);
 	return ret;
 }
 
@@ -575,11 +561,6 @@
 #define DECLARES
 #include "compat_ioctl.c"
 
-/* Might be moved to compat_ioctl.h with some ifdefs... */
-COMPATIBLE_IOCTL(TIOCSTART)
-COMPATIBLE_IOCTL(TIOCSTOP)
-COMPATIBLE_IOCTL(TIOCSLTC)
-
 /* PA-specific ioctls */
 COMPATIBLE_IOCTL(PA_PERF_ON)
 COMPATIBLE_IOCTL(PA_PERF_OFF)
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 77e03bc..9534ee1 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -26,7 +26,7 @@
  *       can be used.
  */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define ADDIB	addib,*
 #define CMPB	cmpb,*
 #define ANDCM	andcm,*
@@ -40,8 +40,10 @@
 	.level	2.0
 #endif
 
-#include <asm/assembly.h>
+#include <linux/config.h>
+
 #include <asm/psw.h>
+#include <asm/assembly.h>
 #include <asm/pgtable.h>
 #include <asm/cache.h>
 
@@ -62,32 +64,23 @@
 	 * to happen in real mode with all interruptions disabled.
 	 */
 
-	/*
-	 * Once again, we do the rfi dance ... some day we need examine
-	 * all of our uses of this type of code and see what can be
-	 * consolidated.
-	 */
+	/* pcxt_ssm_bug	- relied upon translation! PA 2.0 Arch. F-4 and F-5 */
+	rsm	PSW_SM_I, %r19		/* save I-bit state */
+	load32		PA(1f), %r1
+	nop
+	nop
+	nop
+	nop
+	nop
 
-	rsm		PSW_SM_I, %r19		/* relied upon translation! PA 2.0 Arch. F-5 */
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	
-	rsm		PSW_SM_Q, %r0		/* Turn off Q bit to load iia queue */
-	ldil		L%REAL_MODE_PSW, %r1
-	ldo		R%REAL_MODE_PSW(%r1), %r1
-	mtctl		%r1, %cr22
+	rsm		PSW_SM_Q, %r0		/* prep to load iia queue */
 	mtctl		%r0, %cr17		/* Clear IIASQ tail */
 	mtctl		%r0, %cr17		/* Clear IIASQ head */
-	ldil		L%PA(1f), %r1
-	ldo		R%PA(1f)(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ head */
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ tail */
+	load32		REAL_MODE_PSW, %r1
+	mtctl           %r1, %ipsw
 	rfi
 	nop
 
@@ -178,29 +171,36 @@
 	ADDIB>		-1, %r22, fdtoneloop	/* Outer loop count decr */
 	add		%r21, %r20, %r20	/* increment space */
 
+
 fdtdone:
+	/*
+	 * Switch back to virtual mode
+	 */
+	/* pcxt_ssm_bug */
+	rsm		PSW_SM_I, %r0
+	load32		2f, %r1
+	nop
+	nop
+	nop
+	nop
+	nop
 
-	/* Switch back to virtual mode */
-
-	rsm		PSW_SM_Q, %r0		/* clear Q bit to load iia queue */
-	ldil		L%KERNEL_PSW, %r1
-	ldo		R%KERNEL_PSW(%r1), %r1
-	or		%r1, %r19, %r1		/* Set I bit if set on entry */
-	mtctl		%r1, %cr22
+	rsm		PSW_SM_Q, %r0		/* prep to load iia queue */
 	mtctl		%r0, %cr17		/* Clear IIASQ tail */
 	mtctl		%r0, %cr17		/* Clear IIASQ head */
-	ldil		L%(2f), %r1
-	ldo		R%(2f)(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ head */
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ tail */
+	load32		KERNEL_PSW, %r1
+	or		%r1, %r19, %r1	/* I-bit to state on entry */
+	mtctl		%r1, %ipsw	/* restore I-bit (entire PSW) */
 	rfi
 	nop
 
 2:      bv		%r0(%r2)
 	nop
-	.exit
 
+	.exit
 	.procend
 
 	.export flush_instruction_cache_local,code
@@ -227,7 +227,7 @@
 
 fimanyloop:					/* Loop if LOOP >= 2 */
 	ADDIB>		-1, %r31, fimanyloop	/* Adjusted inner loop decr */
-	fice            0(%sr1, %arg0)
+	fice            %r0(%sr1, %arg0)
 	fice,m		%arg1(%sr1, %arg0)	/* Last fice and addr adjust */
 	movb,tr		%arg3, %r31, fimanyloop	/* Re-init inner loop count */
 	ADDIB<=,n	-1, %arg2, fisync	/* Outer loop decr */
@@ -238,7 +238,7 @@
 
 fisync:
 	sync
-	mtsm		%r22
+	mtsm		%r22			/* restore I-bit */
 	bv		%r0(%r2)
 	nop
 	.exit
@@ -269,7 +269,7 @@
 
 fdmanyloop:					/* Loop if LOOP >= 2 */
 	ADDIB>		-1, %r31, fdmanyloop	/* Adjusted inner loop decr */
-	fdce		0(%sr1, %arg0)
+	fdce		%r0(%sr1, %arg0)
 	fdce,m		%arg1(%sr1, %arg0)	/* Last fdce and addr adjust */
 	movb,tr		%arg3, %r31, fdmanyloop	/* Re-init inner loop count */
 	ADDIB<=,n	-1, %arg2, fdsync	/* Outer loop decr */
@@ -281,7 +281,7 @@
 fdsync:
 	syncdma
 	sync
-	mtsm		%r22
+	mtsm		%r22			/* restore I-bit */
 	bv		%r0(%r2)
 	nop
 	.exit
@@ -296,7 +296,7 @@
 	.callinfo NO_CALLS
 	.entry
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
 	 * Unroll the loop by hand and arrange insn appropriately.
 	 * GCC probably can do this just as well.
@@ -351,7 +351,11 @@
 	std		%r22, 120(%r26)
 	ldo		128(%r26), %r26
 
-	ADDIB>		-1, %r1, 1b		/* bundle 10 */
+	/* conditional branches nullify on forward taken branch, and on
+	 * non-taken backward branch. Note that .+4 is a backwards branch.
+	 * The ldd should only get executed if the branch is taken.
+	 */
+	ADDIB>,n	-1, %r1, 1b		/* bundle 10 */
 	ldd		0(%r25), %r19		/* start next loads */
 
 #else
@@ -363,10 +367,10 @@
 	 * the full 64 bit register values on interrupt, we can't
 	 * use ldd/std on a 32 bit kernel.
 	 */
+	ldw		0(%r25), %r19
 	ldi		64, %r1		/* PAGE_SIZE/64 == 64 */
 
 1:
-	ldw		0(%r25), %r19
 	ldw		4(%r25), %r20
 	ldw		8(%r25), %r21
 	ldw		12(%r25), %r22
@@ -396,11 +400,12 @@
 	ldw		60(%r25), %r22
 	stw		%r19, 48(%r26)
 	stw		%r20, 52(%r26)
+	ldo		64(%r25), %r25
 	stw		%r21, 56(%r26)
 	stw		%r22, 60(%r26)
 	ldo		64(%r26), %r26
-	ADDIB>		-1, %r1, 1b
-	ldo		64(%r25), %r25
+	ADDIB>,n	-1, %r1, 1b
+	ldw		0(%r25), %r19
 #endif
 	bv		%r0(%r2)
 	nop
@@ -456,7 +461,7 @@
 	sub		%r25, %r1, %r23		/* move physical addr into non shadowed reg */
 
 	ldil		L%(TMPALIAS_MAP_START), %r28
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	extrd,u		%r26,56,32, %r26		/* convert phys addr to tlb insert format */
 	extrd,u		%r23,56,32, %r23		/* convert phys addr to tlb insert format */
 	depd		%r24,63,22, %r28		/* Form aliased virtual address 'to' */
@@ -543,7 +548,7 @@
 	tophys_r1	%r26
 
 	ldil		L%(TMPALIAS_MAP_START), %r28
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #if (TMPALIAS_MAP_START >= 0x80000000)
 	depdi		0, 31,32, %r28		/* clear any sign extension */
 #endif
@@ -560,7 +565,7 @@
 
 	pdtlb		0(%r28)
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldi		32, %r1			/* PAGE_SIZE/128 == 32 */
 
 	/* PREFETCH (Write) has not (yet) been proven to help here */
@@ -585,7 +590,7 @@
 	ADDIB>		-1, %r1, 1b
 	ldo		128(%r28), %r28
 
-#else	/* ! __LP64 */
+#else	/* ! CONFIG_64BIT */
 
 	ldi		64, %r1			/* PAGE_SIZE/64 == 64 */
 
@@ -608,7 +613,7 @@
 	stw		%r0, 60(%r28)
 	ADDIB>		-1, %r1, 1b
 	ldo		64(%r28), %r28
-#endif	/* __LP64 */
+#endif	/* CONFIG_64BIT */
 
 	bv		%r0(%r2)
 	nop
@@ -626,7 +631,7 @@
 	ldil		L%dcache_stride, %r1
 	ldw		R%dcache_stride(%r1), %r23
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r25
@@ -670,7 +675,7 @@
 	ldil		L%dcache_stride, %r1
 	ldw		R%dcache_stride(%r1), %r23
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi,z		1,63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1,31-PAGE_SHIFT,1, %r25
@@ -714,7 +719,7 @@
 	ldil		L%dcache_stride, %r1
 	ldw		R%dcache_stride(%r1), %r23
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r25
@@ -759,7 +764,7 @@
 	ldil		L%dcache_stride, %r1
 	ldw		R%dcache_stride(%r1), %r23
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r25
@@ -807,7 +812,7 @@
 	tophys_r1		%r26
 
 	ldil		L%(TMPALIAS_MAP_START), %r28
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
 	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
 	depdi		0, 63,12, %r28		/* Clear any offset bits */
@@ -824,7 +829,7 @@
 	ldil		L%dcache_stride, %r1
 	ldw		R%dcache_stride(%r1), %r23
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r29
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r29
@@ -935,7 +940,7 @@
 	ldil		L%icache_stride, %r1
 	ldw		R%icache_stride(%r1), %r23
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r25
@@ -944,23 +949,23 @@
 	sub		%r25, %r23, %r25
 
 
-1:      fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
-	fic,m		%r23(%r26)
+1:      fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
+	fic,m		%r23(%sr4, %r26)
 	CMPB<<		%r26, %r25, 1b
-	fic,m		%r23(%r26)
+	fic,m		%r23(%sr4, %r26)
 
 	sync
 	bv		%r0(%r2)
@@ -982,17 +987,18 @@
 	ANDCM		%r26, %r21, %r26
 
 1:      CMPB<<,n	%r26, %r25, 1b
-	fic,m		%r23(%r26)
+	fic,m		%r23(%sr4, %r26)
 
 	sync
 	bv		%r0(%r2)
 	nop
 	.exit
-
 	.procend
 
-	.align	128
-
+	/* align should cover use of rfi in disable_sr_hashing_asm and
+	 * srdis_done.
+	 */
+	.align	256
 	.export disable_sr_hashing_asm,code
 
 disable_sr_hashing_asm:
@@ -1000,28 +1006,26 @@
 	.callinfo NO_CALLS
 	.entry
 
-	/* Switch to real mode */
+	/*
+	 * Switch to real mode
+	 */
+	/* pcxt_ssm_bug */
+	rsm		PSW_SM_I, %r0
+	load32		PA(1f), %r1
+	nop
+	nop
+	nop
+	nop
+	nop
 
-	ssm		0, %r0			/* relied upon translation! */
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	
-	rsm		(PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */
-	ldil		L%REAL_MODE_PSW, %r1
-	ldo		R%REAL_MODE_PSW(%r1), %r1
-	mtctl		%r1, %cr22
+	rsm		PSW_SM_Q, %r0		/* prep to load iia queue */
 	mtctl		%r0, %cr17		/* Clear IIASQ tail */
 	mtctl		%r0, %cr17		/* Clear IIASQ head */
-	ldil		L%PA(1f), %r1
-	ldo		R%PA(1f)(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ head */
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ tail */
+	load32		REAL_MODE_PSW, %r1
+	mtctl		%r1, %ipsw
 	rfi
 	nop
 
@@ -1053,27 +1057,31 @@
 
 srdis_pa20:
 
-	/* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
+	/* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
 
 	.word		0x144008bc		/* mfdiag %dr2, %r28 */
 	depdi		0, 54,1, %r28		/* clear DIAG_SPHASH_ENAB (bit 54) */
 	.word		0x145c1840		/* mtdiag %r28, %dr2 */
 
+
 srdis_done:
-
 	/* Switch back to virtual mode */
+	rsm		PSW_SM_I, %r0		/* prep to load iia queue */
+	load32 	   	2f, %r1
+	nop
+	nop
+	nop
+	nop
+	nop
 
-	rsm		PSW_SM_Q, %r0		/* clear Q bit to load iia queue */
-	ldil		L%KERNEL_PSW, %r1
-	ldo		R%KERNEL_PSW(%r1), %r1
-	mtctl		%r1, %cr22
+	rsm		PSW_SM_Q, %r0		/* prep to load iia queue */
 	mtctl		%r0, %cr17		/* Clear IIASQ tail */
 	mtctl		%r0, %cr17		/* Clear IIASQ head */
-	ldil 	   	L%(2f), %r1
-	ldo     	R%(2f)(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ head */
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18		/* IIAOQ tail */
+	load32		KERNEL_PSW, %r1
+	mtctl		%r1, %ipsw
 	rfi
 	nop
 
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index 368cc09..f94a02e 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -31,7 +31,7 @@
 #include <asm/page.h>	/* get_order */
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
-
+#include <asm/tlbflush.h>	/* for purge_tlb_*() macros */
 
 static struct proc_dir_entry * proc_gsc_root = NULL;
 static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
@@ -114,7 +114,7 @@
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, vaddr);
+		pte_t * pte = pte_alloc_kernel(pmd, vaddr);
 		if (!pte)
 			return -ENOMEM;
 		if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr))
@@ -333,23 +333,33 @@
 static int __init
 pcxl_dma_init(void)
 {
-    if (pcxl_dma_start == 0)
-	return 0;
+	if (pcxl_dma_start == 0)
+		return 0;
 
-    spin_lock_init(&pcxl_res_lock);
-    pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
-    pcxl_res_hint = 0;
-    pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
+	spin_lock_init(&pcxl_res_lock);
+	pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
+	pcxl_res_hint = 0;
+	pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
 					    get_order(pcxl_res_size));
-    memset(pcxl_res_map, 0, pcxl_res_size);
-    proc_gsc_root = proc_mkdir("gsc", 0);
-    create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info);
-    return 0;
+	memset(pcxl_res_map, 0, pcxl_res_size);
+	proc_gsc_root = proc_mkdir("gsc", 0);
+	if (!proc_gsc_root)
+    		printk(KERN_WARNING
+			"pcxl_dma_init: Unable to create gsc /proc dir entry\n");
+	else {
+		struct proc_dir_entry* ent;
+		ent = create_proc_info_entry("pcxl_dma", 0,
+				proc_gsc_root, pcxl_proc_info);
+		if (!ent)
+			printk(KERN_WARNING
+				"pci-dma.c: Unable to create pcxl_dma /proc entry.\n");
+	}
+	return 0;
 }
 
 __initcall(pcxl_dma_init);
 
-static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+static void * pa11_dma_alloc_consistent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
 {
 	unsigned long vaddr;
 	unsigned long paddr;
@@ -502,13 +512,13 @@
 };
 
 static void *fail_alloc_consistent(struct device *dev, size_t size,
-				   dma_addr_t *dma_handle, int flag)
+				   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return NULL;
 }
 
 static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size,
-					  dma_addr_t *dma_handle, int flag)
+					  dma_addr_t *dma_handle, gfp_t flag)
 {
 	void *addr = NULL;
 
@@ -545,16 +555,16 @@
 
 static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
 {
+#if 0
 	u_long i = 0;
 	unsigned long *res_ptr = (u_long *)pcxl_res_map;
-	unsigned long total_pages = pcxl_res_size << 3;        /* 8 bits per byte */
+#endif
+	unsigned long total_pages = pcxl_res_size << 3;   /* 8 bits per byte */
 
-	sprintf(buf, "\nDMA Mapping Area size    : %d bytes (%d pages)\n",
-		PCXL_DMA_MAP_SIZE,
-		(pcxl_res_size << 3) ); /* 1 bit per page */
+	sprintf(buf, "\nDMA Mapping Area size    : %d bytes (%ld pages)\n",
+		PCXL_DMA_MAP_SIZE, total_pages);
 	
-	sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
-		buf, pcxl_res_size, pcxl_res_size << 3);   /* 8 bits per byte */
+	sprintf(buf, "%sResource bitmap : %d bytes\n", buf, pcxl_res_size);
 
 	strcat(buf,  "     	  total:    free:    used:   % used:\n");
 	sprintf(buf, "%sblocks  %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
@@ -564,7 +574,8 @@
 	sprintf(buf, "%spages   %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
 		total_pages - pcxl_used_pages, pcxl_used_pages,
 		(pcxl_used_pages * 100 / total_pages));
-	
+
+#if 0
 	strcat(buf, "\nResource bitmap:");
 
 	for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
@@ -572,6 +583,7 @@
 		    strcat(buf,"\n   ");
 		sprintf(buf, "%s %08lx", buf, *res_ptr);
 	}
+#endif
 	strcat(buf, "\n");
 	return strlen(buf);
 }
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index e6a891a..88cba49 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -202,7 +202,8 @@
 pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
 {
 	if (!r->parent) {
-		printk(KERN_EMERG "PCI: Tell willy he's wrong\n");
+		printk(KERN_EMERG "PCI: resource not parented! [%lx-%lx]\n",
+				r->start, r->end);
 		r->parent = hba_res;
 
 		/* reverse link is harder *sigh*  */
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 01f676d..215d78c 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -41,7 +41,7 @@
 
 /* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. 
  * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
-#undef EARLY_BOOTUP_DEBUG
+#define EARLY_BOOTUP_DEBUG
 
 
 #include <linux/config.h>
@@ -49,14 +49,8 @@
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/major.h>
 #include <linux/tty.h>
-#include <asm/page.h>
-#include <asm/types.h>
-#include <asm/system.h>
 #include <asm/pdc.h>		/* for iodc_call() proto and friends */
 
 
@@ -96,7 +90,6 @@
 }
 
 #if defined(CONFIG_PDC_CONSOLE)
-#define PDC_CONSOLE_DEVICE pdc_console_device
 static struct tty_driver * pdc_console_device (struct console *c, int *index)
 {
 	extern struct tty_driver console_driver;
@@ -104,22 +97,19 @@
 	return &console_driver;
 }
 #else
-#define PDC_CONSOLE_DEVICE NULL
+#define pdc_console_device NULL
 #endif
 
 static struct console pdc_cons = {
 	.name =		"ttyB",
 	.write =	pdc_console_write,
-	.device =	PDC_CONSOLE_DEVICE,
+	.device =	pdc_console_device,
 	.setup =	pdc_console_setup,
-	.flags =	CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
+	.flags =	CON_BOOT | CON_PRINTBUFFER | CON_ENABLED,
 	.index =	-1,
 };
 
 static int pdc_console_initialized;
-extern unsigned long con_start;	/* kernel/printk.c */
-extern unsigned long log_end;	/* kernel/printk.c */
-
 
 static void pdc_console_init_force(void)
 {
@@ -146,27 +136,11 @@
 }
 
 
-/* Unregister the pdc console with the printk console layer */
-void pdc_console_die(void)
-{
-	if (!pdc_console_initialized)
-		return;
-	--pdc_console_initialized;
-
-	printk(KERN_INFO "Switching from PDC console\n");
-
-	/* Don't repeat what we've already printed */
-	con_start = log_end;
-
-	unregister_console(&pdc_cons);
-}
-
-
 /*
  * Used for emergencies. Currently only used if an HPMC occurs. If an
  * HPMC occurs, it is possible that the current console may not be
- * properly initialed after the PDC IO reset. This routine unregisters all
- * of the current consoles, reinitializes the pdc console and
+ * properly initialised after the PDC IO reset. This routine unregisters
+ * all of the current consoles, reinitializes the pdc console and
  * registers it.
  */
 
@@ -177,13 +151,13 @@
 	if (pdc_console_initialized)
 		return;
 
+	/* If we've already seen the output, don't bother to print it again */
+	if (console_drivers != NULL)
+		pdc_cons.flags &= ~CON_PRINTBUFFER;
+
 	while ((console = console_drivers) != NULL)
 		unregister_console(console_drivers);
 
-	/* Don't repeat what we've already printed */
-	con_start = log_end;
-	
 	/* force registering the pdc console */
 	pdc_console_init_force();
 }
-
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index b3ad0a5..44670d6 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -746,7 +746,8 @@
 	uint64_t *bptr;
 	uint32_t dwords;
 	uint32_t *intrigue_rdr;
-	uint64_t *intrigue_bitmask, tmp64, proc_hpa;
+	uint64_t *intrigue_bitmask, tmp64;
+	void __iomem *runway;
 	struct rdr_tbl_ent *tentry;
 	int i;
 
@@ -798,15 +799,16 @@
 		return -1;
 	}
 
-	proc_hpa = cpu_device->hpa;
+	runway = ioremap(cpu_device->hpa.start, 4096);
 
 	/* Merge intrigue bits into Runway STATUS 0 */
-	tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecfffffffffffful;
-	__raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), proc_hpa + RUNWAY_STATUS);
+	tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful;
+	__raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), 
+		     runway + RUNWAY_STATUS);
 	
 	/* Write RUNWAY DEBUG registers */
 	for (i = 0; i < 8; i++) {
-		__raw_writeq(*memaddr++, proc_hpa + RUNWAY_DEBUG + i);
+		__raw_writeq(*memaddr++, runway + RUNWAY_DEBUG);
 	}
 
 	return 0; 
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 46b7593..7fdca87 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -9,7 +9,7 @@
  *    Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
  *    Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
  *    Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com>
- *    Copyright (C) 2000 Richard Hirst <rhirst with parisc-lixux.org>
+ *    Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org>
  *    Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
  *    Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org>
  *    Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
@@ -245,7 +245,17 @@
 sys_clone(unsigned long clone_flags, unsigned long usp,
 	  struct pt_regs *regs)
 {
-	int __user *user_tid = (int __user *)regs->gr[26];
+  	/* Arugments from userspace are:
+	   r26 = Clone flags.
+	   r25 = Child stack.
+	   r24 = parent_tidptr.
+	   r23 = Is the TLS storage descriptor 
+	   r22 = child_tidptr 
+	   
+	   However, these last 3 args are only examined
+	   if the proper flags are set. */
+	int __user *child_tidptr;
+	int __user *parent_tidptr;
 
 	/* usp must be word aligned.  This also prevents users from
 	 * passing in the value 1 (which is the signal for a special
@@ -253,10 +263,20 @@
 	usp = ALIGN(usp, 4);
 
 	/* A zero value for usp means use the current stack */
-	if(usp == 0)
-		usp = regs->gr[30];
+	if (usp == 0)
+	  usp = regs->gr[30];
 
-	return do_fork(clone_flags, usp, regs, 0, user_tid, NULL);
+	if (clone_flags & CLONE_PARENT_SETTID)
+	  parent_tidptr = (int __user *)regs->gr[24];
+	else
+	  parent_tidptr = NULL;
+	
+	if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID))
+	  child_tidptr = (int __user *)regs->gr[22];
+	else
+	  child_tidptr = NULL;
+
+	return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr);
 }
 
 int
@@ -332,6 +352,10 @@
 		} else {
 			cregs->kpc = (unsigned long) &child_return;
 		}
+		/* Setup thread TLS area from the 4th parameter in clone */
+		if (clone_flags & CLONE_SETTLS)
+		  cregs->cr27 = pregs->gr[23];
+	
 	}
 
 	return 0;
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 13b721c..4f5bbcf 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -92,7 +92,7 @@
 	 * May get overwritten by PAT code.
 	 */
 	cpuid = boot_cpu_data.cpu_count;
-	txn_addr = dev->hpa;	/* for legacy PDC */
+	txn_addr = dev->hpa.start;	/* for legacy PDC */
 
 #ifdef __LP64__
 	if (is_pdc_pat()) {
@@ -122,7 +122,7 @@
  * boot time (ie shutdown a CPU from an OS perspective).
  */
 		/* get the cpu number */
-		status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa);
+		status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start);
 
 		BUG_ON(PDC_OK != status);
 
@@ -130,7 +130,7 @@
 			printk(KERN_WARNING "IGNORING CPU at 0x%x,"
 				" cpu_slot_id > NR_CPUS"
 				" (%ld > %d)\n",
-				dev->hpa, cpu_info.cpu_num, NR_CPUS);
+				dev->hpa.start, cpu_info.cpu_num, NR_CPUS);
 			/* Ignore CPU since it will only crash */
 			boot_cpu_data.cpu_count--;
 			return 1;
@@ -149,7 +149,7 @@
 
 	p->loops_per_jiffy = loops_per_jiffy;
 	p->dev = dev;		/* Save IODC data in case we need it */
-	p->hpa = dev->hpa;	/* save CPU hpa */
+	p->hpa = dev->hpa.start;	/* save CPU hpa */
 	p->cpuid = cpuid;	/* save CPU id */
 	p->txn_addr = txn_addr;	/* save CPU IRQ address */
 #ifdef CONFIG_SMP
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index f3428e5..18130c3 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -78,7 +78,7 @@
 	pa_psw(child)->l = 0;
 }
 
-long sys_ptrace(long request, pid_t pid, long addr, long data)
+long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	long ret;
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
index 8dd5def..8c2859c 100644
--- a/arch/parisc/kernel/real2.S
+++ b/arch/parisc/kernel/real2.S
@@ -7,8 +7,10 @@
  * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
  *
  */
-#include <asm/assembly.h>
+#include <linux/config.h>
+
 #include <asm/psw.h>
+#include <asm/assembly.h>
 
 	.section	.bss
 	.export real_stack
@@ -20,7 +22,7 @@
 real64_stack:
 	.block	8192
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #  define REG_SZ 8
 #else
 #  define REG_SZ 4
@@ -50,7 +52,7 @@
 
 real32_call_asm:
 	STREG	%rp, -RP_OFFSET(%sp)	/* save RP */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	callee_save
 	ldo	2*REG_SZ(%sp), %sp	/* room for a couple more saves */
 	STREG	%r27, -1*REG_SZ(%sp)
@@ -77,7 +79,7 @@
 	b,l	save_control_regs,%r2		/* modifies r1, r2, r28 */
 	nop
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	rsm	PSW_SM_W, %r0		/* go narrow */
 #endif
 
@@ -85,7 +87,7 @@
 	bv	0(%r31)
 	nop
 ric_ret:
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ssm	PSW_SM_W, %r0		/* go wide */
 #endif
 	/* restore CRs before going virtual in case we page fault */
@@ -97,7 +99,7 @@
 
 	tovirt_r1 %sp
 	LDREG	-REG_SZ(%sp), %sp	/* restore SP */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	LDREG	-1*REG_SZ(%sp), %r27
 	LDREG	-2*REG_SZ(%sp), %r29
 	ldo	-2*REG_SZ(%sp), %sp
@@ -143,24 +145,21 @@
 /* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
  * more general-purpose use by the several places which need RFIs
  */
-	.align 128
 	.text
+	.align 128
 rfi_virt2real:
 	/* switch to real mode... */
-	ssm		0,0		/* See "relied upon translation" */
-	nop				/* PA 2.0 Arch. F-5 */
-	nop
-	nop
+	rsm		PSW_SM_I,%r0
+	load32		PA(rfi_v2r_1), %r1
 	nop
 	nop
 	nop
 	nop
 	nop
 	
-	rsm             (PSW_SM_Q|PSW_SM_I),%r0  /* disable Q & I bits to load iia queue */
+	rsm             PSW_SM_Q,%r0  /* disable Q & I bits to load iia queue */
 	mtctl		%r0, %cr17	/* Clear IIASQ tail */
 	mtctl		%r0, %cr17	/* Clear IIASQ head */
-	load32		PA(rfi_v2r_1), %r1
 	mtctl		%r1, %cr18	/* IIAOQ head */
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18	/* IIAOQ tail */
@@ -184,10 +183,8 @@
 	.text
 	.align 128
 rfi_real2virt:
-	ssm		0,0		/* See "relied upon translation" */
-	nop				/* PA 2.0 Arch. F-5 */
-	nop
-	nop
+	rsm		PSW_SM_I,%r0
+	load32		(rfi_r2v_1), %r1
 	nop
 	nop
 	nop
@@ -197,7 +194,6 @@
 	rsm             PSW_SM_Q,%r0    /* disable Q bit to load iia queue */
 	mtctl		%r0, %cr17	/* Clear IIASQ tail */
 	mtctl		%r0, %cr17	/* Clear IIASQ head */
-	load32		(rfi_r2v_1), %r1
 	mtctl		%r1, %cr18	/* IIAOQ head */
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18	/* IIAOQ tail */
@@ -218,7 +214,7 @@
 	bv	0(%r2)
 	nop
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 
 /************************ 64-bit real-mode calls ***********************/
 /* This is only usable in wide kernels right now and will probably stay so */
@@ -296,7 +292,7 @@
 	**	comparing function pointers.
 	*/
 __canonicalize_funcptr_for_compare:
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	bve (%r2)
 #else
 	bv %r0(%r2)
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 0224651..82c24e6 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -490,15 +490,7 @@
 
 give_sigsegv:
 	DBG(1,"setup_rt_frame: sending SIGSEGV\n");
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	si.si_signo = SIGSEGV;
-	si.si_errno = 0;
-	si.si_code = SI_KERNEL;
-	si.si_pid = current->pid;
-	si.si_uid = current->uid;
-	si.si_addr = frame;
-	force_sig_info(SIGSEGV, &si, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -633,10 +625,14 @@
 			put_user(0xe0008200, &usp[3]);
 			put_user(0x34140000, &usp[4]);
 
-			/* Stack is 64-byte aligned, and we only 
-			 * need to flush 1 cache line */
-			asm("fdc 0(%%sr3, %0)\n"
-			    "fic 0(%%sr3, %0)\n"
+			/* Stack is 64-byte aligned, and we only need
+			 * to flush 1 cache line.
+			 * Flushing one cacheline is cheap.
+			 * "sync" on bigger (> 4 way) boxes is not.
+			 */
+			asm("fdc %%r0(%%sr3, %0)\n"
+			    "sync\n"
+			    "fic %%r0(%%sr3, %0)\n"
 			    "sync\n"
 			    : : "r"(regs->gr[30]));
 
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index bcc7e83..5db3be4 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -18,7 +18,7 @@
 */
 #undef ENTRY_SYS_CPUS	/* syscall support for iCOD-like functionality */
 
-#include <linux/autoconf.h>
+#include <linux/config.h>
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 8c7a718..b29b76b4 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -6,6 +6,7 @@
  * thanks to Philipp Rumpf, Mike Shaver and various others
  * sorry about the wall, puffin..
  */
+#include <linux/config.h> /* for CONFIG_SMP */
 
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
@@ -22,15 +23,13 @@
 	 */
 #define KILL_INSN	break	0,0
 
-#include <linux/config.h> /* for CONFIG_SMP */
-
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	.level          2.0w
 #else
 	.level		1.1
 #endif
 
-#ifndef __LP64__
+#ifndef CONFIG_64BIT
 	.macro fixup_branch,lbl
 	b	    \lbl
 	.endm
@@ -103,7 +102,7 @@
 	mfsp    %sr7,%r1                        /* save user sr7 */
 	mtsp    %r1,%sr3                        /* and store it in sr3 */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* for now we can *always* set the W bit on entry to the syscall
 	 * since we don't support wide userland processes.  We could
 	 * also save the current SM other than in r0 and restore it on
@@ -155,7 +154,7 @@
 	STREG	%r19, TASK_PT_GR19(%r1)
 
 	LDREGM	-FRAME_SIZE(%r30), %r2		/* get users sp back */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	extrd,u	%r2,63,1,%r19			/* W hidden in bottom bit */
 #if 0
 	xor	%r19,%r2,%r2			/* clear bottom bit */
@@ -186,7 +185,7 @@
 
 	loadgp
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
 	copy	%r19,%r2			/* W bit back to r2 */
 #else
@@ -205,7 +204,7 @@
 	/* Note!  We cannot use the syscall table that is mapped
 	nearby since the gateway page is mapped execute-only. */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldil	L%sys_call_table, %r1
 	or,=	%r2,%r2,%r2
 	addil	L%(sys_call_table64-sys_call_table), %r1
@@ -321,7 +320,7 @@
 	LDREG   TASK_PT_GR25(%r1), %r25
 	LDREG   TASK_PT_GR24(%r1), %r24
 	LDREG   TASK_PT_GR23(%r1), %r23
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	LDREG   TASK_PT_GR22(%r1), %r22
 	LDREG   TASK_PT_GR21(%r1), %r21
 	ldo	-16(%r30),%r29			/* Reference param save area */
@@ -350,7 +349,7 @@
 tracesys_exit:
 	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	LDREG	TI_TASK(%r1), %r1
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
 #endif
 	bl	syscall_trace, %r2
@@ -371,7 +370,7 @@
 tracesys_sigexit:
 	ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	LDREG	0(%r1), %r1
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
 #endif
 	bl	syscall_trace, %r2
@@ -404,7 +403,7 @@
 	gate	.+8, %r0
 	depi	3, 31, 2, %r31	/* Ensure we return to userspace */
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* FIXME: If we are a 64-bit kernel just
 	 *        turn this on unconditionally.
 	 */
@@ -440,7 +439,7 @@
 	/* Fall through: Return to userspace */
 
 lws_exit:
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* decide whether to reset the wide mode bit
 	 *
 	 * For a syscall, the W bit is stored in the lowest bit
@@ -486,7 +485,7 @@
 
 	/* ELF64 Process entry path */
 lws_compare_and_swap64:
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	b,n	lws_compare_and_swap
 #else
 	/* If we are not a 64-bit kernel, then we don't
@@ -497,7 +496,7 @@
 
 	/* ELF32 Process entry path */
 lws_compare_and_swap32:
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* Clip all the input registers */
 	depdi	0, 31, 32, %r26
 	depdi	0, 31, 32, %r25
@@ -608,7 +607,7 @@
 	   the other for the store. Either return -EFAULT.
 	   Each of the entries must be relocated. */
 	.section __ex_table,"aw"
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* Pad the address calculation */
 	.word	0,(2b - linux_gateway_page)
 	.word	0,(3b - linux_gateway_page)
@@ -619,7 +618,7 @@
 	.previous
 
 	.section __ex_table,"aw"
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* Pad the address calculation */
 	.word	0,(1b - linux_gateway_page)
 	.word	0,(3b - linux_gateway_page)
@@ -638,7 +637,7 @@
 
 	/* Relocate symbols assuming linux_gateway_page is mapped
 	   to virtual address 0x0 */
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/* FIXME: The code will always be on the gateay page
 		  and thus it will be on the first 4k, the
 		  assembler seems to think that the final
@@ -666,7 +665,7 @@
 sys_call_table:
 #include "syscall_table.S"
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	.align 4096
 	.export sys_call_table64
 .Lsys_call_table64:
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index dcfa4d3..32cbc04 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -35,7 +35,7 @@
 #undef ENTRY_UHOH
 #undef ENTRY_COMP
 #undef ENTRY_OURS
-#if defined(__LP64__) && !defined(SYSCALL_TABLE_64BIT)
+#if defined(CONFIG_64BIT) && !defined(SYSCALL_TABLE_64BIT)
 /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
  * narrow palinux.  Use ENTRY_DIFF for those where a 32-bit specific
  * implementation is required on wide palinux.  Use ENTRY_COMP where
@@ -46,7 +46,7 @@
 #define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
 #define ENTRY_OURS(_name_) .dword parisc_##_name_
 #define ENTRY_COMP(_name_) .dword compat_sys_##_name_
-#elif defined(__LP64__) && defined(SYSCALL_TABLE_64BIT)
+#elif defined(CONFIG_64BIT) && defined(SYSCALL_TABLE_64BIT)
 #define ENTRY_SAME(_name_) .dword sys_##_name_
 #define ENTRY_DIFF(_name_) .dword sys_##_name_
 #define ENTRY_UHOH(_name_) .dword sys_##_name_
@@ -368,5 +368,11 @@
 	ENTRY_COMP(mbind)		/* 260 */
 	ENTRY_COMP(get_mempolicy)
 	ENTRY_COMP(set_mempolicy)
+	ENTRY_SAME(ni_syscall)	/* 263: reserved for vserver */
+	ENTRY_SAME(add_key)
+	ENTRY_SAME(request_key)		/* 265 */
+	ENTRY_SAME(keyctl)
+	ENTRY_SAME(ioprio_set)
+	ENTRY_SAME(ioprio_get)
 	/* Nothing yet */
 
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 7ff67f8..cded256 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -33,10 +33,6 @@
 
 #include <linux/timex.h>
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 /* xtime and wall_jiffies keep wall-clock time */
 extern unsigned long wall_jiffies;
 
@@ -89,14 +85,6 @@
 		}
 	}
     
-#ifdef CONFIG_CHASSIS_LCD_LED
-	/* Only schedule the led tasklet on cpu 0, and only if it
-	 * is enabled.
-	 */
-	if (cpu == 0 && !atomic_read(&led_tasklet.count))
-		tasklet_schedule(&led_tasklet);
-#endif
-
 	/* check soft power switch status */
 	if (cpu == 0 && !atomic_read(&power_tasklet.count))
 		tasklet_schedule(&power_tasklet);
@@ -104,6 +92,24 @@
 	return IRQ_HANDLED;
 }
 
+
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (regs->gr[0] & PSW_N)
+		pc -= 4;
+
+#ifdef CONFIG_SMP
+	if (in_lock_functions(pc))
+		pc = regs->gr[2];
+#endif
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+
+
 /*** converted from ia64 ***/
 /*
  * Return the number of micro-seconds that elapsed since the last
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index d2e5b22..15914f0 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -74,7 +74,10 @@
 	char *level;
 	unsigned long cr30;
 	unsigned long cr31;
-
+	/* carlos says that gcc understands better memory in a struct,
+	 * and it makes our life easier with fpregs -- T-Bone */
+	struct { u32 sw[2]; } s;
+	
 	level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
 
 	printk("%s\n", level); /* don't want to have that pretty register dump messed up */
@@ -103,11 +106,33 @@
 		printk("%s\n", buf);
 	}
 
-#if RIDICULOUSLY_VERBOSE
-	for (i = 0; i < 32; i += 2)
-		printk("%sFR%02d : %016lx  FR%2d : %016lx", level, i,
-				regs->fr[i], i+1, regs->fr[i+1]);
-#endif
+	/* FR are 64bit everywhere. Need to use asm to get the content
+	 * of fpsr/fper1, and we assume that we won't have a FP Identify
+	 * in our way, otherwise we're screwed.
+	 * The fldd is used to restore the T-bit if there was one, as the
+	 * store clears it anyway.
+	 * BTW, PA2.0 book says "thou shall not use fstw on FPSR/FPERs". */ 
+	__asm__ (
+		"fstd %%fr0,0(%1)	\n\t"
+		"fldd 0(%1),%%fr0	\n\t"
+		: "=m" (s) : "r" (&s) : "%r0"
+		);
+
+	printk("%s\n", level);
+	printk("%s      VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level);
+	printbinary(buf, s.sw[0], 32);
+	printk("%sFPSR: %s\n", level, buf);
+	printk("%sFPER1: %08x\n", level, s.sw[1]);
+
+	/* here we'll print fr0 again, tho it'll be meaningless */
+	for (i = 0; i < 32; i += 4) {
+		int j;
+		p = buf;
+		p += sprintf(p, "%sfr%02d-%02d ", level, i, i + 3);
+		for (j = 0; j < 4; j++)
+			p += sprintf(p, " %016llx", (i+j) == 0 ? 0 : regs->fr[i+j]);
+		printk("%s\n", buf);
+	}
 
 	cr30 = mfctl(30);
 	cr31 = mfctl(31);
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index 62eea35..eaae8a0 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -513,15 +513,18 @@
 	register int flop=0;	/* true if this is a flop */
 
 	/* log a message with pacing */
-	if (user_mode(regs))
-	{
-		if (unaligned_count > 5 && jiffies - last_time > 5*HZ)
-		{
+	if (user_mode(regs)) {
+		if (current->thread.flags & PARISC_UAC_SIGBUS) {
+			goto force_sigbus;
+		}
+
+		if (unaligned_count > 5 && jiffies - last_time > 5*HZ) {
 			unaligned_count = 0;
 			last_time = jiffies;
 		}
-		if (++unaligned_count < 5)
-		{
+
+		if (!(current->thread.flags & PARISC_UAC_NOPRINT) 
+		    && ++unaligned_count < 5) {
 			char buf[256];
 			sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
 				current->comm, current->pid, regs->ior, regs->iaoq[0]);
@@ -530,6 +533,7 @@
 			show_regs(regs);
 #endif		
 		}
+
 		if (!unaligned_enabled)
 			goto force_sigbus;
 	}
diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
index 1b91612..e0661c2 100644
--- a/arch/parisc/lib/fixup.S
+++ b/arch/parisc/lib/fixup.S
@@ -35,7 +35,7 @@
 	extrd,u \t2,63,32,\t2
 #endif
 	/* t2 = &__per_cpu_offset[smp_processor_id()]; */
-	LDREG,s \t2(\t1),\t2 
+	LDREGX \t2(\t1),\t2 
 	addil LT%per_cpu__exception_data,%r27
 	LDREG RT%per_cpu__exception_data(%r1),\t1
 	/* t1 = &__get_cpu_var(exception_data) */
@@ -53,6 +53,8 @@
 	.endm
 #endif
 
+	.level LEVEL
+
 	.text
 	.section .fixup, "ax"
 
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index feb1b9f..b709803 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -339,6 +339,7 @@
 	pds = (double *)pcs;
 	pdd = (double *)pcd;
 
+#if 0
 	/* Copy 8 doubles at a time */
 	while (len >= 8*sizeof(double)) {
 		register double r1, r2, r3, r4, r5, r6, r7, r8;
@@ -366,6 +367,7 @@
 		fstdma(d_space, r8, pdd, pmc_store_exc);
 		len -= 8*sizeof(double);
 	}
+#endif
 
 	pws = (unsigned int *)pds;
 	pwd = (unsigned int *)pdd;
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 2886ad7..29b998e 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -505,7 +505,9 @@
 
 		for (j = node_start_pfn(i); j < node_end_pfn(i); j++) {
 			struct page *p;
+			unsigned long flags;
 
+			pgdat_resize_lock(NODE_DATA(i), &flags);
 			p = nid_page_nr(i, j) - node_start_pfn(i);
 
 			total++;
@@ -517,6 +519,7 @@
 				free++;
 			else
 				shared += page_count(p) - 1;
+			pgdat_resize_unlock(NODE_DATA(i), &flags);
         	}
 	}
 #endif
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index f2df502..5c7a1b3 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -52,7 +52,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(NULL, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -75,10 +75,9 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd;
-		pmd = pmd_alloc(dir, address);
+		pmd = pmd_alloc(&init_mm, dir, address);
 		error = -ENOMEM;
 		if (!pmd)
 			break;
@@ -89,7 +88,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return error;
 }
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index e43e8ef..117b000 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -102,6 +102,83 @@
 }
 EXPORT_SYMBOL(phys_mem_access_prot);
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+void online_page(struct page *page)
+{
+	ClearPageReserved(page);
+	free_cold_page(page);
+	totalram_pages++;
+	num_physpages++;
+}
+
+/*
+ * This works only for the non-NUMA case.  Later, we'll need a lookup
+ * to convert from real physical addresses to nid, that doesn't use
+ * pfn_to_nid().
+ */
+int __devinit add_memory(u64 start, u64 size)
+{
+	struct pglist_data *pgdata = NODE_DATA(0);
+	struct zone *zone;
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+
+	/* this should work for most non-highmem platforms */
+	zone = pgdata->node_zones;
+
+	return __add_pages(zone, start_pfn, nr_pages);
+
+	return 0;
+}
+
+/*
+ * First pass at this code will check to determine if the remove
+ * request is within the RMO.  Do not allow removal within the RMO.
+ */
+int __devinit remove_memory(u64 start, u64 size)
+{
+	struct zone *zone;
+	unsigned long start_pfn, end_pfn, nr_pages;
+
+	start_pfn = start >> PAGE_SHIFT;
+	nr_pages = size >> PAGE_SHIFT;
+	end_pfn = start_pfn + nr_pages;
+
+	printk("%s(): Attempting to remove memoy in range "
+			"%lx to %lx\n", __func__, start, start+size);
+	/*
+	 * check for range within RMO
+	 */
+	zone = page_zone(pfn_to_page(start_pfn));
+
+	printk("%s(): memory will be removed from "
+			"the %s zone\n", __func__, zone->name);
+
+	/*
+	 * not handling removing memory ranges that
+	 * overlap multiple zones yet
+	 */
+	if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages))
+		goto overlap;
+
+	/* make sure it is NOT in RMO */
+	if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) {
+		printk("%s(): range to be removed must NOT be in RMO!\n",
+			__func__);
+		goto in_rmo;
+	}
+
+	return __remove_pages(zone, start_pfn, nr_pages);
+
+overlap:
+	printk("%s(): memory range to be removed overlaps "
+		"multiple zones!!!\n", __func__);
+in_rmo:
+	return -1;
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
 void show_mem(void)
 {
 	unsigned long total = 0, reserved = 0;
@@ -115,6 +192,8 @@
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
+		unsigned long flags;
+		pgdat_resize_lock(pgdat, &flags);
 		for (i = 0; i < pgdat->node_spanned_pages; i++) {
 			page = pgdat_page_nr(pgdat, i);
 			total++;
@@ -127,6 +206,7 @@
 			else if (page_count(page))
 				shared += page_count(page) - 1;
 		}
+		pgdat_resize_unlock(pgdat, &flags);
 	}
 	printk("%ld pages of RAM\n", total);
 #ifdef CONFIG_HIGHMEM
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 484d24f..b79a782 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -104,7 +104,6 @@
 	unsigned long vsid;
 
 	if (mem_init_done) {
-		spin_lock(&init_mm.page_table_lock);
 		pgdp = pgd_offset_k(ea);
 		pudp = pud_alloc(&init_mm, pgdp, ea);
 		if (!pudp)
@@ -112,12 +111,11 @@
 		pmdp = pmd_alloc(&init_mm, pudp, ea);
 		if (!pmdp)
 			return -ENOMEM;
-		ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
+		ptep = pte_alloc_kernel(pmdp, ea);
 		if (!ptep)
 			return -ENOMEM;
 		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
 							  __pgprot(flags)));
-		spin_unlock(&init_mm.page_table_lock);
 	} else {
 		unsigned long va, vpn, hash, hpteg;
 
diff --git a/arch/ppc/8xx_io/cs4218.h b/arch/ppc/8xx_io/cs4218.h
index a3c38c5..f1c7392 100644
--- a/arch/ppc/8xx_io/cs4218.h
+++ b/arch/ppc/8xx_io/cs4218.h
@@ -78,7 +78,7 @@
     const char *name2;
     void (*open)(void);
     void (*release)(void);
-    void *(*dma_alloc)(unsigned int, int);
+    void *(*dma_alloc)(unsigned int, gfp_t);
     void (*dma_free)(void *, unsigned int);
     int (*irqinit)(void);
 #ifdef MODULE
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 2ca9ec7..532caa3 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -318,7 +318,7 @@
 
 static struct cs_sound_settings sound;
 
-static void *CS_Alloc(unsigned int size, int flags);
+static void *CS_Alloc(unsigned int size, gfp_t flags);
 static void CS_Free(void *ptr, unsigned int size);
 static int CS_IrqInit(void);
 #ifdef MODULE
@@ -959,7 +959,7 @@
 
 /*** Low level stuff *********************************************************/
 
-static void *CS_Alloc(unsigned int size, int flags)
+static void *CS_Alloc(unsigned int size, gfp_t flags)
 {
 	int	order;
 
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
index 8edee80..685fd0d 100644
--- a/arch/ppc/kernel/dma-mapping.c
+++ b/arch/ppc/kernel/dma-mapping.c
@@ -115,7 +115,7 @@
 };
 
 static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, int gfp)
+vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
 {
 	unsigned long addr = head->vm_start, end = head->vm_end - size;
 	unsigned long flags;
@@ -173,7 +173,7 @@
  * virtual and bus address for that space.
  */
 void *
-__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp)
+__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
 {
 	struct page *page;
 	struct vm_region *c;
@@ -335,8 +335,6 @@
 	pte_t *pte;
 	int ret = 0;
 
-	spin_lock(&init_mm.page_table_lock);
-
 	do {
 		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
 		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
@@ -347,7 +345,7 @@
 		}
 		WARN_ON(!pmd_none(*pmd));
 
-		pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+		pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
 		if (!pte) {
 			printk(KERN_ERR "%s: no pte tables\n", __func__);
 			ret = -ENOMEM;
@@ -357,8 +355,6 @@
 		consistent_pte = pte;
 	} while (0);
 
-	spin_unlock(&init_mm.page_table_lock);
-
 	return ret;
 }
 
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 76f44ce..53ea723 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -66,11 +66,6 @@
 
 #include <asm/time.h>
 
-/* XXX false sharing with below? */
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 unsigned long disarm_decr[NR_CPUS];
 
 extern struct timezone sys_tz;
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
index b7bcbc2..4d006aa 100644
--- a/arch/ppc/mm/4xx_mmu.c
+++ b/arch/ppc/mm/4xx_mmu.c
@@ -110,13 +110,11 @@
 		pmd_t *pmdp;
 		unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
 
-		spin_lock(&init_mm.page_table_lock);
 		pmdp = pmd_offset(pgd_offset_k(v), v);
 		pmd_val(*pmdp++) = val;
 		pmd_val(*pmdp++) = val;
 		pmd_val(*pmdp++) = val;
 		pmd_val(*pmdp++) = val;
-		spin_unlock(&init_mm.page_table_lock);
 
 		v += LARGE_PAGE_SIZE_16M;
 		p += LARGE_PAGE_SIZE_16M;
@@ -127,10 +125,8 @@
 		pmd_t *pmdp;
 		unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
 
-		spin_lock(&init_mm.page_table_lock);
 		pmdp = pmd_offset(pgd_offset_k(v), v);
 		pmd_val(*pmdp) = val;
-		spin_unlock(&init_mm.page_table_lock);
 
 		v += LARGE_PAGE_SIZE_4M;
 		p += LARGE_PAGE_SIZE_4M;
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 81a3d74..6ea9185 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -114,9 +114,9 @@
 	struct page *ptepage;
 
 #ifdef CONFIG_HIGHPTE
-	int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+	gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
 #else
-	int flags = GFP_KERNEL | __GFP_REPEAT;
+	gfp_t flags = GFP_KERNEL | __GFP_REPEAT;
 #endif
 
 	ptepage = alloc_pages(flags, 0);
@@ -280,18 +280,16 @@
 	pte_t *pg;
 	int err = -ENOMEM;
 
-	spin_lock(&init_mm.page_table_lock);
 	/* Use upper 10 bits of VA to index the first level map */
 	pd = pmd_offset(pgd_offset_k(va), va);
 	/* Use middle 10 bits of VA to index the second-level map */
-	pg = pte_alloc_kernel(&init_mm, pd, va);
+	pg = pte_alloc_kernel(pd, va);
 	if (pg != 0) {
 		err = 0;
 		set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
 		if (mem_init_done)
 			flush_HPTE(0, va, pmd_val(*pd));
 	}
-	spin_unlock(&init_mm.page_table_lock);
 	return err;
 }
 
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
index 2cc12b0..b6a66d5 100644
--- a/arch/ppc/platforms/hdpu.c
+++ b/arch/ppc/platforms/hdpu.c
@@ -609,11 +609,6 @@
 }
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
 static void
 hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
 {
diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/ppc64/kernel/hvcserver.c
index bde8f42..4d58417 100644
--- a/arch/ppc64/kernel/hvcserver.c
+++ b/arch/ppc64/kernel/hvcserver.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/slab.h>
+
 #include <asm/hvcall.h>
 #include <asm/hvcserver.h>
 #include <asm/io.h>
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
index a8005db..ba4a899 100644
--- a/arch/ppc64/kernel/ioctl32.c
+++ b/arch/ppc64/kernel/ioctl32.c
@@ -39,9 +39,7 @@
 #include <linux/compat_ioctl.h>
 #define DECLARES
 #include "compat_ioctl.c"
-COMPATIBLE_IOCTL(TIOCSTART)
-COMPATIBLE_IOCTL(TIOCSTOP)
-COMPATIBLE_IOCTL(TIOCSLTC)
+
 /* Little p (/dev/rtc, /dev/envctrl, etc.) */
 COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */
 COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
index efa985f..4aacf52 100644
--- a/arch/ppc64/kernel/vdso.c
+++ b/arch/ppc64/kernel/vdso.c
@@ -176,13 +176,13 @@
 		return NOPAGE_SIGBUS;
 
 	/*
-	 * Last page is systemcfg, special handling here, no get_page() a
-	 * this is a reserved page
+	 * Last page is systemcfg.
 	 */
 	if ((vma->vm_end - address) <= PAGE_SIZE)
-		return virt_to_page(systemcfg);
+		pg = virt_to_page(systemcfg);
+	else
+		pg = virt_to_page(vbase + offset);
 
-	pg = virt_to_page(vbase + offset);
 	get_page(pg);
 	DBG(" ->page count: %d\n", page_count(pg));
 
@@ -259,7 +259,7 @@
 	 * gettimeofday will be totally dead. It's fine to use that for setting
 	 * breakpoints in the vDSO code pages though
 	 */
-	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_RESERVED;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
 	vma->vm_ops = &vdso_vmops;
@@ -603,6 +603,8 @@
 		ClearPageReserved(pg);
 		get_page(pg);
 	}
+
+	get_page(virt_to_page(systemcfg));
 }
 
 int in_gate_area_no_task(unsigned long addr)
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
index 24a1e9f..6504c4e 100644
--- a/arch/s390/kernel/compat_ioctl.c
+++ b/arch/s390/kernel/compat_ioctl.c
@@ -18,6 +18,8 @@
 #include <asm/dasd.h>
 #include <asm/cmb.h>
 #include <asm/tape390.h>
+#include <asm/ccwdev.h>
+#include "../../../drivers/s390/char/raw3270.h"
 
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
 				unsigned long arg, struct file *f)
@@ -62,6 +64,13 @@
 COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
 COMPATIBLE_IOCTL(BIODASDREADALLCMB)
 
+COMPATIBLE_IOCTL(TUBICMD)
+COMPATIBLE_IOCTL(TUBOCMD)
+COMPATIBLE_IOCTL(TUBGETI)
+COMPATIBLE_IOCTL(TUBGETO)
+COMPATIBLE_IOCTL(TUBSETMOD)
+COMPATIBLE_IOCTL(TUBGETMOD)
+
 COMPATIBLE_IOCTL(TAPE390_DISPLAY)
 
 /* s390 doesn't need handlers here */
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 55654b6..039354d 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -485,7 +485,9 @@
 #
         .org  0x10000
 startup:basr  %r13,0                     # get base
-.LPG1:  lctl  %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
+.LPG1:	l     %r1, .Lget_ipl_device_addr-.LPG1(%r13)
+	basr  %r14, %r1
+	lctl  %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
 	la    %r12,_pstart-.LPG1(%r13)   # pointer to parameter area
 					 # move IPL device to lowcore
         mvc   __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
@@ -560,6 +562,9 @@
 	mr    %r2,%r1			# mem size in bytes in %r3
 	b     .Lfchunk-.LPG1(%r13)
 
+	.align 4
+.Lget_ipl_device_addr:
+	.long .Lget_ipl_device
 .Lpmask:
 	.byte 0
 .align 8
@@ -755,6 +760,63 @@
 	.global _pend
 _pend:	
 
+.Lget_ipl_device:
+	basr  %r12,0
+.LPG2:	l     %r1,0xb8			# get sid
+	sll   %r1,15			# test if subchannel is enabled
+	srl   %r1,31
+	ltr   %r1,%r1
+	bz    0(%r14)			# subchannel disabled
+	l     %r1,0xb8
+	la    %r5,.Lipl_schib-.LPG2(%r12)
+	stsch 0(%r5)		        # get schib of subchannel
+	bnz   0(%r14)			# schib not available
+	tm    5(%r5),0x01		# devno valid?
+	bno   0(%r14)
+	la    %r6,ipl_parameter_flags-.LPG2(%r12)
+	oi    3(%r6),0x01		# set flag
+	la    %r2,ipl_devno-.LPG2(%r12)
+	mvc   0(2,%r2),6(%r5)		# store devno
+	tm    4(%r5),0x80		# qdio capable device?
+	bno   0(%r14)
+	oi    3(%r6),0x02		# set flag
+
+	# copy ipl parameters
+
+	lhi   %r0,4096
+	l     %r2,20(%r0)		# get address of parameter list
+	lhi   %r3,IPL_PARMBLOCK_ORIGIN
+	st    %r3,20(%r0)
+	lhi   %r4,1
+	cr    %r2,%r3			# start parameters < destination ?
+	jl    0f
+	lhi   %r1,1			# copy direction is upwards
+	j     1f
+0:	lhi   %r1,-1			# copy direction is downwards
+	ar    %r2,%r0
+	ar    %r3,%r0
+	ar    %r2,%r1
+	ar    %r3,%r1
+1:	mvc   0(1,%r3),0(%r2)		# finally copy ipl parameters
+	ar    %r3,%r1
+	ar    %r2,%r1
+	sr    %r0,%r4
+	jne   1b
+	b     0(%r14)
+
+	.align 4
+.Lipl_schib:
+	.rept 13
+	.long 0
+	.endr
+
+	.globl ipl_parameter_flags
+ipl_parameter_flags:
+	.long 0
+	.globl ipl_devno
+ipl_devno:
+	.word 0
+
 #ifdef CONFIG_SHARED_KERNEL
 	.org   0x100000
 #endif
@@ -764,11 +826,11 @@
 #
         .globl _stext
 _stext:	basr  %r13,0                    # get base
-.LPG2:
+.LPG3:
 #
 # Setup stack
 #
-        l     %r15,.Linittu-.LPG2(%r13)
+        l     %r15,.Linittu-.LPG3(%r13)
 	mvc   __LC_CURRENT(4),__TI_task(%r15)
         ahi   %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
         st    %r15,__LC_KERNEL_STACK    # set end of kernel stack
@@ -782,8 +844,8 @@
         lctl   %c0,%c15,0(%r15)
 
 #
-        lam    0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess
-        l      %r14,.Lstart-.LPG2(%r13)
+        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
+        l      %r14,.Lstart-.LPG3(%r13)
         basr   %r14,%r14                # call start_kernel
 #
 # We returned from start_kernel ?!? PANIK
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index c9ff040..193aafa 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -484,6 +484,8 @@
 startup:basr  %r13,0                     # get base
 .LPG1:  sll   %r13,1                     # remove high order bit
         srl   %r13,1
+	l     %r1,.Lget_ipl_device_addr-.LPG1(%r13)
+	basr  %r14,%r1
         lhi   %r1,1                      # mode 1 = esame
         slr   %r0,%r0                    # set cpuid to zero
         sigp  %r1,%r0,0x12               # switch to esame mode
@@ -556,6 +558,9 @@
 	mlgr  %r2,%r1			# mem size in bytes in %r3
 	b     .Lfchunk-.LPG1(%r13)
 
+	.align 4
+.Lget_ipl_device_addr:
+	.long .Lget_ipl_device
 .Lpmask:
 	.byte 0
 	.align 8
@@ -746,6 +751,63 @@
 	.global _pend
 _pend:	
 
+.Lget_ipl_device:
+	basr  %r12,0
+.LPG2:	l     %r1,0xb8			# get sid
+	sll   %r1,15			# test if subchannel is enabled
+	srl   %r1,31
+	ltr   %r1,%r1
+	bz    0(%r14)			# subchannel disabled
+	l     %r1,0xb8
+	la    %r5,.Lipl_schib-.LPG2(%r12)
+	stsch 0(%r5)		        # get schib of subchannel
+	bnz   0(%r14)			# schib not available
+	tm    5(%r5),0x01		# devno valid?
+	bno   0(%r14)
+	la    %r6,ipl_parameter_flags-.LPG2(%r12)
+	oi    3(%r6),0x01		# set flag
+	la    %r2,ipl_devno-.LPG2(%r12)
+	mvc   0(2,%r2),6(%r5)		# store devno
+	tm    4(%r5),0x80		# qdio capable device?
+	bno   0(%r14)
+	oi    3(%r6),0x02		# set flag
+
+	# copy ipl parameters
+
+	lhi   %r0,4096
+	l     %r2,20(%r0)		# get address of parameter list
+	lhi   %r3,IPL_PARMBLOCK_ORIGIN
+	st    %r3,20(%r0)
+	lhi   %r4,1
+	cr    %r2,%r3			# start parameters < destination ?
+	jl    0f
+	lhi   %r1,1			# copy direction is upwards
+	j     1f
+0:	lhi   %r1,-1			# copy direction is downwards
+	ar    %r2,%r0
+	ar    %r3,%r0
+	ar    %r2,%r1
+	ar    %r3,%r1
+1:	mvc   0(1,%r3),0(%r2)		# finally copy ipl parameters
+	ar    %r3,%r1
+	ar    %r2,%r1
+	sr    %r0,%r4
+	jne   1b
+	b     0(%r14)
+
+	.align 4
+.Lipl_schib:
+	.rept 13
+	.long 0
+	.endr
+
+	.globl ipl_parameter_flags
+ipl_parameter_flags:
+	.long 0
+	.globl ipl_devno
+ipl_devno:
+	.word 0
+
 #ifdef CONFIG_SHARED_KERNEL
 	.org   0x100000
 #endif
@@ -755,7 +817,7 @@
 #
         .globl _stext
 _stext:	basr  %r13,0                    # get base
-.LPG2:
+.LPG3:
 #
 # Setup stack
 #
@@ -774,7 +836,7 @@
         lctlg  %c0,%c15,0(%r15)
 
 #
-        lam    0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess
+        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
         brasl  %r14,start_kernel        # go to C code
 #
 # We returned from start_kernel ?!? PANIK
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 5204778..31e7b19 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -36,6 +36,7 @@
 #include <linux/console.h>
 #include <linux/seq_file.h>
 #include <linux/kernel_stat.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -685,3 +686,188 @@
 	.show	= show_cpuinfo,
 };
 
+#define DEFINE_IPL_ATTR(_name, _format, _value)			\
+static ssize_t ipl_##_name##_show(struct subsystem *subsys,	\
+		char *page)					\
+{								\
+	return sprintf(page, _format, _value);			\
+}								\
+static struct subsys_attribute ipl_##_name##_attr =		\
+	__ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL);
+
+DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long)
+		IPL_PARMBLOCK_START->fcp.wwpn);
+DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long)
+		IPL_PARMBLOCK_START->fcp.lun);
+DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long)
+		IPL_PARMBLOCK_START->fcp.bootprog);
+DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long)
+		IPL_PARMBLOCK_START->fcp.br_lba);
+
+enum ipl_type_type {
+	ipl_type_unknown,
+	ipl_type_ccw,
+	ipl_type_fcp,
+};
+
+static enum ipl_type_type
+get_ipl_type(void)
+{
+	struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
+
+	if (!IPL_DEVNO_VALID)
+		return ipl_type_unknown;
+	if (!IPL_PARMBLOCK_VALID)
+		return ipl_type_ccw;
+	if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION)
+		return ipl_type_unknown;
+	if (ipl->fcp.pbt != IPL_TYPE_FCP)
+		return ipl_type_unknown;
+	return ipl_type_fcp;
+}
+
+static ssize_t
+ipl_type_show(struct subsystem *subsys, char *page)
+{
+	switch (get_ipl_type()) {
+	case ipl_type_ccw:
+		return sprintf(page, "ccw\n");
+	case ipl_type_fcp:
+		return sprintf(page, "fcp\n");
+	default:
+		return sprintf(page, "unknown\n");
+	}
+}
+
+static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type);
+
+static ssize_t
+ipl_device_show(struct subsystem *subsys, char *page)
+{
+	struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
+
+	switch (get_ipl_type()) {
+	case ipl_type_ccw:
+		return sprintf(page, "0.0.%04x\n", ipl_devno);
+	case ipl_type_fcp:
+		return sprintf(page, "0.0.%04x\n", ipl->fcp.devno);
+	default:
+		return 0;
+	}
+}
+
+static struct subsys_attribute ipl_device_attr =
+	__ATTR(device, S_IRUGO, ipl_device_show, NULL);
+
+static struct attribute *ipl_fcp_attrs[] = {
+	&ipl_type_attr.attr,
+	&ipl_device_attr.attr,
+	&ipl_wwpn_attr.attr,
+	&ipl_lun_attr.attr,
+	&ipl_bootprog_attr.attr,
+	&ipl_br_lba_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ipl_fcp_attr_group = {
+	.attrs = ipl_fcp_attrs,
+};
+
+static struct attribute *ipl_ccw_attrs[] = {
+	&ipl_type_attr.attr,
+	&ipl_device_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ipl_ccw_attr_group = {
+	.attrs = ipl_ccw_attrs,
+};
+
+static struct attribute *ipl_unknown_attrs[] = {
+	&ipl_type_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ipl_unknown_attr_group = {
+	.attrs = ipl_unknown_attrs,
+};
+
+static ssize_t
+ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	unsigned int size = IPL_PARMBLOCK_SIZE;
+
+	if (off > size)
+		return 0;
+	if (off + count > size)
+		count = size - off;
+
+	memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count);
+	return count;
+}
+
+static struct bin_attribute ipl_parameter_attr = {
+	.attr = {
+		.name = "binary_parameter",
+		.mode = S_IRUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = PAGE_SIZE,
+	.read = &ipl_parameter_read,
+};
+
+static ssize_t
+ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	unsigned int size =  IPL_PARMBLOCK_START->fcp.scp_data_len;
+	void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data;
+
+	if (off > size)
+		return 0;
+	if (off + count > size)
+		count = size - off;
+
+	memcpy(buf, scp_data + off, count);
+	return count;
+}
+
+static struct bin_attribute ipl_scp_data_attr = {
+	.attr = {
+		.name = "scp_data",
+		.mode = S_IRUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = PAGE_SIZE,
+	.read = &ipl_scp_data_read,
+};
+
+static decl_subsys(ipl, NULL, NULL);
+
+static int __init
+ipl_device_sysfs_register(void) {
+	int rc;
+
+	rc = firmware_register(&ipl_subsys);
+	if (rc)
+		return rc;
+
+	switch (get_ipl_type()) {
+	case ipl_type_ccw:
+		sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group);
+		break;
+	case ipl_type_fcp:
+		sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
+		sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+				      &ipl_parameter_attr);
+		sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+				      &ipl_scp_data_attr);
+		break;
+	default:
+		sysfs_create_group(&ipl_subsys.kset.kobj,
+				   &ipl_unknown_attr_group);
+		break;
+	}
+	return 0;
+}
+
+__initcall(ipl_device_sysfs_register);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 2fd75da..9a1d958 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -49,10 +49,6 @@
 
 #define TICK_SIZE tick
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 static ext_int_info_t ext_int_info_cc;
 static u64 init_timer_cc;
 static u64 jiffies_timer_cc;
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index fa07265..22a895e 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -24,7 +24,6 @@
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
 
-#define VTIMER_MAGIC (TIMER_MAGIC + 1)
 static ext_int_info_t ext_int_info_timer;
 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
@@ -277,20 +276,12 @@
 
 void init_virt_timer(struct vtimer_list *timer)
 {
-	timer->magic = VTIMER_MAGIC;
 	timer->function = NULL;
 	INIT_LIST_HEAD(&timer->entry);
 	spin_lock_init(&timer->lock);
 }
 EXPORT_SYMBOL(init_virt_timer);
 
-static inline int check_vtimer(struct vtimer_list *timer)
-{
-	if (timer->magic != VTIMER_MAGIC)
-		return -EINVAL;
-	return 0;
-}
-
 static inline int vtimer_pending(struct vtimer_list *timer)
 {
 	return (!list_empty(&timer->entry));
@@ -346,7 +337,7 @@
 
 static inline int prepare_vtimer(struct vtimer_list *timer)
 {
-	if (check_vtimer(timer) || !timer->function) {
+	if (!timer->function) {
 		printk("add_virt_timer: uninitialized timer\n");
 		return -EINVAL;
 	}
@@ -414,7 +405,7 @@
 	unsigned long flags;
 	int cpu;
 
-	if (check_vtimer(timer) || !timer->function) {
+	if (!timer->function) {
 		printk("mod_virt_timer: uninitialized timer\n");
 		return	-EINVAL;
 	}
@@ -481,11 +472,6 @@
 	unsigned long flags;
 	struct vtimer_queue *vt_list;
 
-	if (check_vtimer(timer)) {
-		printk("del_virt_timer: timer not initialized\n");
-		return -EINVAL;
-	}
-
 	/* check if timer is pending */
 	if (!vtimer_pending(timer))
 		return 0;
diff --git a/arch/s390/mm/ioremap.c b/arch/s390/mm/ioremap.c
index c6c39d8..0f6e9ec 100644
--- a/arch/s390/mm/ioremap.c
+++ b/arch/s390/mm/ioremap.c
@@ -58,7 +58,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -80,7 +80,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd;
 		pmd = pmd_alloc(&init_mm, dir, address);
@@ -94,7 +93,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return 0;
 }
diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c
index 1efc18e..6107405 100644
--- a/arch/sh/boards/renesas/rts7751r2d/mach.c
+++ b/arch/sh/boards/renesas/rts7751r2d/mach.c
@@ -23,7 +23,7 @@
 extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
 extern int rts7751r2d_irq_demux(int irq);
 
-extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
 extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
 /*
diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c
index 5b92585..3d9a02c 100644
--- a/arch/sh/cchips/voyagergx/consistent.c
+++ b/arch/sh/cchips/voyagergx/consistent.c
@@ -31,7 +31,7 @@
 #define OHCI_SRAM_SIZE	0x10000
 
 void *voyagergx_consistent_alloc(struct device *dev, size_t size,
-				 dma_addr_t *handle, int flag)
+				 dma_addr_t *handle, gfp_t flag)
 {
 	struct list_head *list = &voya_alloc_list;
 	struct voya_alloc_entry *entry;
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index 71a6d4e..6e3b58b 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/sysdev.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include <asm/dma.h>
 
 static struct sysdev_class dma_sysclass = {
diff --git a/arch/sh/drivers/pci/dma-dreamcast.c b/arch/sh/drivers/pci/dma-dreamcast.c
index 83de7ef..e12418b 100644
--- a/arch/sh/drivers/pci/dma-dreamcast.c
+++ b/arch/sh/drivers/pci/dma-dreamcast.c
@@ -33,7 +33,7 @@
 static int gapspci_dma_used = 0;
 
 void *dreamcast_consistent_alloc(struct device *dev, size_t size,
-				 dma_addr_t *dma_handle, int flag)
+				 dma_addr_t *dma_handle, gfp_t flag)
 {
 	unsigned long buf;
 
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
index e0b384b..47abf6e 100644
--- a/arch/sh/kernel/cpufreq.c
+++ b/arch/sh/kernel/cpufreq.c
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/cpumask.h>
 #include <linux/smp.h>
+#include <linux/sched.h>	/* set_cpus_allowed() */
 
 #include <asm/processor.h>
 #include <asm/watchdog.h>
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index b28919b..1fbe5a4 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -80,7 +80,7 @@
 	/* nothing to do.. */
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	struct user * dummy = NULL;
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 02ca699..671b876 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -56,10 +56,6 @@
 #define TICK_SIZE (tick_nsec / 1000)
 DEFINE_SPINLOCK(tmu0_lock);
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 /* XXX: Can we initialize this in a routine somewhere?  Dreamcast doesn't want
  * these routines anywhere... */
 #ifdef CONFIG_SH_RTC
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index 1f7af0c..df3a9e4 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -11,7 +11,7 @@
 #include <linux/dma-mapping.h>
 #include <asm/io.h>
 
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle)
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
 {
 	struct page *page, *end, *free;
 	void *ret;
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 7abba21..775f86c 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -194,10 +194,13 @@
 			       unsigned long address)
 {
 	unsigned long addrmax = P4SEG;
-	pgd_t *dir;
+	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t entry;
+	struct mm_struct *mm;
+	spinlock_t *ptl;
+	int ret = 1;
 
 #ifdef CONFIG_SH_KGDB
 	if (kgdb_nofault && kgdb_bus_err_hook)
@@ -208,28 +211,28 @@
 	addrmax = P4SEG_STORE_QUE + 0x04000000;
 #endif
 
-	if (address >= P3SEG && address < addrmax)
-		dir = pgd_offset_k(address);
-	else if (address >= TASK_SIZE)
+	if (address >= P3SEG && address < addrmax) {
+		pgd = pgd_offset_k(address);
+		mm = NULL;
+	} else if (address >= TASK_SIZE)
 		return 1;
-	else if (!current->mm)
+	else if (!(mm = current->mm))
 		return 1;
 	else
-		dir = pgd_offset(current->mm, address);
+		pgd = pgd_offset(mm, address);
 
-	pmd = pmd_offset(dir, address);
-	if (pmd_none(*pmd))
+	pmd = pmd_offset(pgd, address);
+	if (pmd_none_or_clear_bad(pmd))
 		return 1;
-	if (pmd_bad(*pmd)) {
-		pmd_ERROR(*pmd);
-		pmd_clear(pmd);
-		return 1;
-	}
-	pte = pte_offset_kernel(pmd, address);
+	if (mm)
+		pte = pte_offset_map_lock(mm, pmd, address, &ptl);
+	else
+		pte = pte_offset_kernel(pmd, address);
+
 	entry = *pte;
 	if (pte_none(entry) || pte_not_present(entry)
 	    || (writeaccess && !pte_write(entry)))
-		return 1;
+		goto unlock;
 
 	if (writeaccess)
 		entry = pte_mkdirty(entry);
@@ -251,8 +254,11 @@
 
 	set_pte(pte, entry);
 	update_mmu_cache(NULL, address, entry);
-
-	return 0;
+	ret = 0;
+unlock:
+	if (mm)
+		pte_unmap_unlock(pte, ptl);
+	return ret;
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index 95bb1a6..6b7a768 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -54,8 +54,6 @@
 	return pte;
 }
 
-#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
-
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 		     pte_t *ptep, pte_t entry)
 {
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index 9f490c2..e794e27 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -57,7 +57,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -79,7 +79,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd;
 		pmd = pmd_alloc(&init_mm, dir, address);
@@ -93,7 +92,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return error;
 }
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index fd20009..71f2eec 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -121,7 +121,7 @@
 	return 0;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index f4a62a1..870fe53 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -116,8 +116,6 @@
 
 extern unsigned long wall_jiffies;
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
 static unsigned long tmu_base, rtc_base;
 unsigned long cprc_base;
 
@@ -253,6 +251,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(do_settimeofday);
 
 static int set_rtc_time(unsigned long nowtime)
 {
diff --git a/arch/sh64/mm/cache.c b/arch/sh64/mm/cache.c
index 3b87e25..c0c1b21 100644
--- a/arch/sh64/mm/cache.c
+++ b/arch/sh64/mm/cache.c
@@ -584,32 +584,36 @@
 	}
 }
 
-static void sh64_dcache_purge_user_page(struct mm_struct *mm, unsigned long eaddr)
+static void sh64_dcache_purge_user_pages(struct mm_struct *mm,
+				unsigned long addr, unsigned long end)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t entry;
+	spinlock_t *ptl;
 	unsigned long paddr;
 
-	/* NOTE : all the callers of this have mm->page_table_lock held, so the
-	   following page table traversal is safe even on SMP/pre-emptible. */
+	if (!mm)
+		return; /* No way to find physical address of page */
 
-	if (!mm) return; /* No way to find physical address of page */
-	pgd = pgd_offset(mm, eaddr);
-	if (pgd_bad(*pgd)) return;
+	pgd = pgd_offset(mm, addr);
+	if (pgd_bad(*pgd))
+		return;
 
-	pmd = pmd_offset(pgd, eaddr);
-	if (pmd_none(*pmd) || pmd_bad(*pmd)) return;
+	pmd = pmd_offset(pgd, addr);
+	if (pmd_none(*pmd) || pmd_bad(*pmd))
+		return;
 
-	pte = pte_offset_kernel(pmd, eaddr);
-	entry = *pte;
-	if (pte_none(entry) || !pte_present(entry)) return;
-
-	paddr = pte_val(entry) & PAGE_MASK;
-
-	sh64_dcache_purge_coloured_phy_page(paddr, eaddr);
-
+	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+	do {
+		entry = *pte;
+		if (pte_none(entry) || !pte_present(entry))
+			continue;
+		paddr = pte_val(entry) & PAGE_MASK;
+		sh64_dcache_purge_coloured_phy_page(paddr, addr);
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+	pte_unmap_unlock(pte - 1, ptl);
 }
 /****************************************************************************/
 
@@ -668,7 +672,7 @@
 	int n_pages;
 
 	n_pages = ((end - start) >> PAGE_SHIFT);
-	if (n_pages >= 64) {
+	if (n_pages >= 64 || ((start ^ (end - 1)) & PMD_MASK)) {
 #if 1
 		sh64_dcache_purge_all();
 #else
@@ -707,20 +711,10 @@
 		}
 #endif
 	} else {
-		/* 'Small' range */
-		unsigned long aligned_start;
-		unsigned long eaddr;
-		unsigned long last_page_start;
-
-		aligned_start = start & PAGE_MASK;
-		/* 'end' is 1 byte beyond the end of the range */
-		last_page_start = (end - 1) & PAGE_MASK;
-
-		eaddr = aligned_start;
-		while (eaddr <= last_page_start) {
-			sh64_dcache_purge_user_page(mm, eaddr);
-			eaddr += PAGE_SIZE;
-		}
+		/* Small range, covered by a single page table page */
+		start &= PAGE_MASK;	/* should already be so */
+		end = PAGE_ALIGN(end);	/* should already be so */
+		sh64_dcache_purge_user_pages(mm, start, end);
 	}
 	return;
 }
@@ -880,9 +874,7 @@
 	   addresses from the user address space specified by mm, after writing
 	   back any dirty data.
 
-	   Note(1), 'end' is 1 byte beyond the end of the range to flush.
-
-	   Note(2), this is called with mm->page_table_lock held.*/
+	   Note, 'end' is 1 byte beyond the end of the range to flush. */
 
 	sh64_dcache_purge_user_range(mm, start, end);
 	sh64_icache_inv_user_page_range(mm, start, end);
@@ -898,7 +890,7 @@
 	   the I-cache must be searched too in case the page in question is
 	   both writable and being executed from (e.g. stack trampolines.)
 
-	   Note(1), this is called with mm->page_table_lock held.
+	   Note, this is called with pte lock held.
 	   */
 
 	sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT);
diff --git a/arch/sh64/mm/hugetlbpage.c b/arch/sh64/mm/hugetlbpage.c
index dcd9c8a..ed6a505 100644
--- a/arch/sh64/mm/hugetlbpage.c
+++ b/arch/sh64/mm/hugetlbpage.c
@@ -54,41 +54,31 @@
 	return pte;
 }
 
-#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
-
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-			 struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t entry)
 {
-	unsigned long i;
-	pte_t entry;
-
-	add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-
-	if (write_access)
-		entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
-						       vma->vm_page_prot)));
-	else
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
-	entry = pte_mkyoung(entry);
-	mk_pte_huge(entry);
+	int i;
 
 	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		set_pte(page_table, entry);
-		page_table++;
-
+		set_pte_at(mm, addr, ptep, entry);
+		ptep++;
+		addr += PAGE_SIZE;
 		pte_val(entry) += PAGE_SIZE;
 	}
 }
 
-pte_t huge_ptep_get_and_clear(pte_t *ptep)
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep)
 {
 	pte_t entry;
+	int i;
 
 	entry = *ptep;
 
 	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		pte_clear(pte);
-		pte++;
+		pte_clear(mm, addr, ptep);
+		addr += PAGE_SIZE;
+		ptep++;
 	}
 
 	return entry;
@@ -106,79 +96,6 @@
 	return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-			    struct vm_area_struct *vma)
-{
-	pte_t *src_pte, *dst_pte, entry;
-	struct page *ptepage;
-	unsigned long addr = vma->vm_start;
-	unsigned long end = vma->vm_end;
-	int i;
-
-	while (addr < end) {
-		dst_pte = huge_pte_alloc(dst, addr);
-		if (!dst_pte)
-			goto nomem;
-		src_pte = huge_pte_offset(src, addr);
-		BUG_ON(!src_pte || pte_none(*src_pte));
-		entry = *src_pte;
-		ptepage = pte_page(entry);
-		get_page(ptepage);
-		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			set_pte(dst_pte, entry);
-			pte_val(entry) += PAGE_SIZE;
-			dst_pte++;
-		}
-		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-		addr += HPAGE_SIZE;
-	}
-	return 0;
-
-nomem:
-	return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-			struct page **pages, struct vm_area_struct **vmas,
-			unsigned long *position, int *length, int i)
-{
-	unsigned long vaddr = *position;
-	int remainder = *length;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-
-	while (vaddr < vma->vm_end && remainder) {
-		if (pages) {
-			pte_t *pte;
-			struct page *page;
-
-			pte = huge_pte_offset(mm, vaddr);
-
-			/* hugetlb should be locked, and hence, prefaulted */
-			BUG_ON(!pte || pte_none(*pte));
-
-			page = pte_page(*pte);
-
-			WARN_ON(!PageCompound(page));
-
-			get_page(page);
-			pages[i] = page;
-		}
-
-		if (vmas)
-			vmas[i] = vma;
-
-		vaddr += PAGE_SIZE;
-		--remainder;
-		++i;
-	}
-
-	*length = remainder;
-	*position = vaddr;
-
-	return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
 			      unsigned long address, int write)
 {
@@ -195,84 +112,3 @@
 {
 	return NULL;
 }
-
-void unmap_hugepage_range(struct vm_area_struct *vma,
-			  unsigned long start, unsigned long end)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long address;
-	pte_t *pte;
-	struct page *page;
-	int i;
-
-	BUG_ON(start & (HPAGE_SIZE - 1));
-	BUG_ON(end & (HPAGE_SIZE - 1));
-
-	for (address = start; address < end; address += HPAGE_SIZE) {
-		pte = huge_pte_offset(mm, address);
-		BUG_ON(!pte);
-		if (pte_none(*pte))
-			continue;
-		page = pte_page(*pte);
-		put_page(page);
-		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			pte_clear(mm, address+(i*PAGE_SIZE), pte);
-			pte++;
-		}
-	}
-	add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-	flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
-
-	BUG_ON(vma->vm_start & ~HPAGE_MASK);
-	BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (!pte_none(*pte))
-			continue;
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				free_huge_page(page);
-				goto out;
-			}
-		}
-		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-	}
-out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
-}
diff --git a/arch/sh64/mm/ioremap.c b/arch/sh64/mm/ioremap.c
index f4003da..fb1866f 100644
--- a/arch/sh64/mm/ioremap.c
+++ b/arch/sh64/mm/ioremap.c
@@ -79,7 +79,7 @@
 		BUG();
 
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -101,7 +101,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
 		error = -ENOMEM;
@@ -115,7 +114,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return 0;
 }
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 36a4069..25e31d5 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -497,8 +497,8 @@
 				 * CheerIO makes a similar conversion.
 				 * See ebus.c for details.
 				 *
-				 * Note that check_region()/request_region()
-				 * work for these devices.
+				 * Note that request_region()
+				 * works for these devices.
 				 *
 				 * XXX Neat trick, but it's a *bad* idea
 				 * to shit into regions like that.
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 279a626..24814d5 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -45,10 +45,6 @@
 
 extern unsigned long wall_jiffies;
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 DEFINE_SPINLOCK(rtc_lock);
 enum sparc_clock_type sp_clock_typ;
 DEFINE_SPINLOCK(mostek_lock);
diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c
index 20ccb95..9604893 100644
--- a/arch/sparc/mm/generic.c
+++ b/arch/sparc/mm/generic.c
@@ -73,14 +73,16 @@
 	int space = GET_IOSPACE(pfn);
 	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
 
+	/* See comment in mm/memory.c remap_pfn_range */
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+
 	prot = __pgprot(pg_iobits);
 	offset -= from;
 	dir = pgd_offset(mm, from);
 	flush_cache_range(vma, beg, end);
 
-	spin_lock(&mm->page_table_lock);
 	while (from < end) {
-		pmd_t *pmd = pmd_alloc(current->mm, dir, from);
+		pmd_t *pmd = pmd_alloc(mm, dir, from);
 		error = -ENOMEM;
 		if (!pmd)
 			break;
@@ -90,7 +92,6 @@
 		from = (from + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	spin_unlock(&mm->page_table_lock);
 
 	flush_tlb_range(vma, beg, end);
 	return error;
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index b2854ef..edf52d0 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -241,7 +241,6 @@
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
 
-	set_mm_counter(current->mm, rss, 0);
 	current->mm->mmap = NULL;
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 43fc317..e6a0032 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -475,9 +475,6 @@
 #include <linux/compat_ioctl.h>
 #define DECLARES
 #include "compat_ioctl.c"
-COMPATIBLE_IOCTL(TIOCSTART)
-COMPATIBLE_IOCTL(TIOCSTOP)
-COMPATIBLE_IOCTL(TIOCSLTC)
 COMPATIBLE_IOCTL(FBIOGTYPE)
 COMPATIBLE_IOCTL(FBIOSATTR)
 COMPATIBLE_IOCTL(FBIOGATTR)
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 3f08a32..38c5525 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -55,10 +55,6 @@
 
 extern unsigned long wall_jiffies;
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 static void __iomem *mstk48t08_regs;
 static void __iomem *mstk48t59_regs;
 
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index c954d91..112c316 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -127,14 +127,16 @@
 	int space = GET_IOSPACE(pfn);
 	unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
 
+	/* See comment in mm/memory.c remap_pfn_range */
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+
 	prot = __pgprot(pg_iobits);
 	offset -= from;
 	dir = pgd_offset(mm, from);
 	flush_cache_range(vma, beg, end);
 
-	spin_lock(&mm->page_table_lock);
 	while (from < end) {
-		pud_t *pud = pud_alloc(current->mm, dir, from);
+		pud_t *pud = pud_alloc(mm, dir, from);
 		error = -ENOMEM;
 		if (!pud)
 			break;
@@ -144,8 +146,7 @@
 		from = (from + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
-	flush_tlb_range(vma, beg, end);
-	spin_unlock(&mm->page_table_lock);
 
+	flush_tlb_range(vma, beg, end);
 	return error;
 }
diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c
index 90ca99d..8b104be 100644
--- a/arch/sparc64/mm/tlb.c
+++ b/arch/sparc64/mm/tlb.c
@@ -18,8 +18,7 @@
 
 /* Heavily inspired by the ppc64 code.  */
 
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) =
-	{ NULL, 0, 0, 0, 0, 0, { 0 }, { NULL }, };
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, };
 
 void flush_tlb_pending(void)
 {
@@ -72,7 +71,7 @@
 
 no_cache_flush:
 
-	if (mp->tlb_frozen)
+	if (mp->fullmm)
 		return;
 
 	nr = mp->tlb_nr;
@@ -97,7 +96,7 @@
 	unsigned long nr = mp->tlb_nr;
 	long s = start, e = end, vpte_base;
 
-	if (mp->tlb_frozen)
+	if (mp->fullmm)
 		return;
 
 	/* If start is greater than end, that is a real problem.  */
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index d7c1c76..fc6669e 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -49,7 +49,7 @@
 
 #else
 
-extern void * mykmalloc(size_t s, int gfp);
+extern void * mykmalloc(size_t s, gfp_t gfp);
 extern void mykfree(void *);
 
 #endif
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index aaad29c..b84e545 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -39,7 +39,7 @@
 
 #else
 
-void * mykmalloc(size_t s, int gfp)
+void * mykmalloc(size_t s, gfp_t gfp)
 {
 	static char * page;
 	static size_t free;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 684e1f8..cd06ed7 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -27,10 +27,6 @@
 	bool
 	default y
 
-config RWSEM_GENERIC_SPINLOCK
-	bool
-	default y
-
 config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
@@ -40,6 +36,12 @@
 	bool
 	default y
 
+menu "Host processor type and features"
+
+source "arch/i386/Kconfig.cpu"
+
+endmenu
+
 menu "UML-specific options"
 
 config MODE_TT
diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64
index bd35e59..aae19bc 100644
--- a/arch/um/Kconfig.x86_64
+++ b/arch/um/Kconfig.x86_64
@@ -6,6 +6,11 @@
 	bool
 	default y
 
+#XXX: this is so in the underlying arch, but it's wrong!!!
+config RWSEM_GENERIC_SPINLOCK
+	bool
+	default y
+
 config SEMAPHORE_SLEEPERS
 	bool
 	default y
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 2ee8a28..aef7c50 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -29,6 +29,12 @@
 
 CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
 
-ifneq ($(CONFIG_GPROF),y)
-ARCH_CFLAGS += -DUM_FASTCALL
-endif
+# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
+include $(srctree)/arch/i386/Makefile.cpu
+
+# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
+cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
+
+CFLAGS += $(cflags-y)
+USER_CFLAGS += $(cflags-y)
+
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index a0d5b74..57bd79e 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -11,7 +11,6 @@
 /* Not declared on x86, incompatible declarations on x86_64, so these have
  * to go here rather than in sys_call_table.c
  */
-extern syscall_handler_t sys_ptrace;
 extern syscall_handler_t sys_rt_sigaction;
 
 extern syscall_handler_t old_mmap_i386;
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h
index 45d7da6..8efc1e0 100644
--- a/arch/um/include/tlb.h
+++ b/arch/um/include/tlb.h
@@ -34,7 +34,6 @@
 	} u;
 };
 
-extern void mprotect_kernel_vm(int w);
 extern void force_flush_all(void);
 extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                              unsigned long end_addr, int force,
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index ea008b0..462cc9d 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -252,7 +252,7 @@
 #endif
 }
 
-struct page *arch_validate(struct page *page, int mask, int order)
+struct page *arch_validate(struct page *page, gfp_t mask, int order)
 {
 	unsigned long addr, zero = 0;
 	int i;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index ea65db6..34b54a3 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -80,7 +80,7 @@
 unsigned long alloc_stack(int order, int atomic)
 {
 	unsigned long page;
-	int flags = GFP_KERNEL;
+	gfp_t flags = GFP_KERNEL;
 
 	if (atomic)
 		flags = GFP_ATOMIC;
@@ -222,6 +222,7 @@
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
+	pte_t ptent;
 
 	if(task->mm == NULL) 
 		return(ERR_PTR(-EINVAL));
@@ -238,12 +239,13 @@
 		return(ERR_PTR(-EINVAL));
 
 	pte = pte_offset_kernel(pmd, addr);
-	if(!pte_present(*pte)) 
+	ptent = *pte;
+	if(!pte_present(ptent))
 		return(ERR_PTR(-EINVAL));
 
 	if(pte_out != NULL)
-		*pte_out = *pte;
-	return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK));
+		*pte_out = ptent;
+	return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
 }
 
 char *current_cmd(void)
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 240143b..9e5e39c 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -28,7 +28,6 @@
 	pmd_t *pmd;
 	pte_t *pte;
 
-	spin_lock(&mm->page_table_lock);
 	pgd = pgd_offset(mm, proc);
 	pud = pud_alloc(mm, pgd, proc);
 	if (!pud)
@@ -63,7 +62,6 @@
 	*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
 	*pte = pte_mkexec(*pte);
 	*pte = pte_wrprotect(*pte);
-	spin_unlock(&mm->page_table_lock);
 	return(0);
 
  out_pmd:
@@ -71,7 +69,6 @@
  out_pte:
 	pmd_free(pmd);
  out:
-	spin_unlock(&mm->page_table_lock);
 	return(-ENOMEM);
 }
 
@@ -147,6 +144,7 @@
 
 	if(!proc_mm || !ptrace_faultinfo){
 		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_page_state(nr_page_table_pages);
 #ifdef CONFIG_3_LEVEL_PGTABLES
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 4e08f75..020ca79 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -22,10 +22,6 @@
 #include "mode.h"
 #include "os.h"
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 int hz(void)
 {
 	return(HZ);
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index f1d85db..ae6217c 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -74,42 +74,6 @@
                 atomic_inc(&vmchange_seq);
 }
 
-static void protect_vm_page(unsigned long addr, int w, int must_succeed)
-{
-	int err;
-
-	err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed);
-	if(err == 0) return;
-	else if((err == -EFAULT) || (err == -ENOMEM)){
-		flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
-		protect_vm_page(addr, w, 1);
-	}
-	else panic("protect_vm_page : protect failed, errno = %d\n", err);
-}
-
-void mprotect_kernel_vm(int w)
-{
-	struct mm_struct *mm;
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned long addr;
-	
-	mm = &init_mm;
-	for(addr = start_vm; addr < end_vm;){
-		pgd = pgd_offset(mm, addr);
-		pud = pud_offset(pgd, addr);
-		pmd = pmd_offset(pud, addr);
-		if(pmd_present(*pmd)){
-			pte = pte_offset_kernel(pmd, addr);
-			if(pte_present(*pte)) protect_vm_page(addr, w, 0);
-			addr += PAGE_SIZE;
-		}
-		else addr += PMD_SIZE;
-	}
-}
-
 void flush_tlb_kernel_vm_tt(void)
 {
         flush_tlb_kernel_range(start_vm, end_vm);
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index 4726b87..d6077ff 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -113,7 +113,7 @@
 	return 1;
 }
 
-int sys_ptrace(long request, long pid, long addr, long data)
+long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int rval;
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
index ea3fd88..c1e85c2 100644
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -26,10 +26,6 @@
 
 #include "mach.h"
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 #define TICK_SIZE	(tick_nsec / 1000)
 
 /*
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 3e6780f..93c60f4 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -314,7 +314,6 @@
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
 	current->mm->cached_hole_size = 0;
 
-	set_mm_counter(current->mm, rss, 0);
 	current->mm->mmap = NULL;
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
index 419758f..4ba0e29 100644
--- a/arch/x86_64/ia32/ia32_ioctl.c
+++ b/arch/x86_64/ia32/ia32_ioctl.c
@@ -12,40 +12,11 @@
 #define INCLUDES
 #include <linux/syscalls.h>
 #include "compat_ioctl.c"
-#include <asm/mtrr.h>
 #include <asm/ia32.h>
 
 #define CODE
 #include "compat_ioctl.c"
   
-#ifndef TIOCGDEV
-#define TIOCGDEV       _IOR('T',0x32, unsigned int)
-#endif
-static int tiocgdev(unsigned fd, unsigned cmd,  unsigned int __user *ptr) 
-{ 
-
-	struct file *file;
-	struct tty_struct *real_tty;
-	int fput_needed, ret;
-
-	file = fget_light(fd, &fput_needed);
-	if (!file)
-		return -EBADF;
-
-	ret = -EINVAL;
-	if (file->f_op->ioctl != tty_ioctl)
-		goto out;
-	real_tty = (struct tty_struct *)file->private_data;
-	if (!real_tty) 	
-		goto out;
-
-	ret = put_user(new_encode_dev(tty_devnum(real_tty)), ptr); 
-
-out:
-	fput_light(file, fput_needed);
-	return ret;
-} 
-
 #define RTC_IRQP_READ32	_IOR('p', 0x0b, unsigned int)	 /* Read IRQ rate   */
 #define RTC_IRQP_SET32	_IOW('p', 0x0c, unsigned int)	 /* Set IRQ rate    */
 #define RTC_EPOCH_READ32	_IOR('p', 0x0d, unsigned)	 /* Read epoch      */
@@ -85,90 +56,6 @@
 	return sys_ioctl(fd,cmd,arg); 
 } 
 
-/* /proc/mtrr ioctls */
-
-
-struct mtrr_sentry32
-{
-    compat_ulong_t base;    /*  Base address     */
-    compat_uint_t size;    /*  Size of region   */
-    compat_uint_t type;     /*  Type of region   */
-};
-
-struct mtrr_gentry32
-{
-    compat_ulong_t regnum;   /*  Register number  */
-    compat_uint_t base;    /*  Base address     */
-    compat_uint_t size;    /*  Size of region   */
-    compat_uint_t type;     /*  Type of region   */
-};
-
-#define	MTRR_IOCTL_BASE	'M'
-
-#define MTRRIOC32_ADD_ENTRY        _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry32)
-#define MTRRIOC32_SET_ENTRY        _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry32)
-#define MTRRIOC32_DEL_ENTRY        _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry32)
-#define MTRRIOC32_GET_ENTRY        _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
-#define MTRRIOC32_KILL_ENTRY       _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry32)
-#define MTRRIOC32_ADD_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry32)
-#define MTRRIOC32_SET_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry32)
-#define MTRRIOC32_DEL_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry32)
-#define MTRRIOC32_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
-#define MTRRIOC32_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
-
-
-static int mtrr_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg)
-{ 
-	struct mtrr_gentry g;
-	struct mtrr_sentry s;
-	int get = 0, err = 0; 
-	struct mtrr_gentry32 __user *g32 = (struct mtrr_gentry32 __user *)arg; 
-	mm_segment_t oldfs = get_fs(); 
-
-	switch (cmd) { 
-#define SET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; break 
-#define GET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; get=1; break
-		SET(ADD);
-		SET(SET); 
-		SET(DEL);
-		GET(GET); 
-		SET(KILL);
-		SET(ADD_PAGE); 
-		SET(SET_PAGE); 
-		SET(DEL_PAGE); 
-		GET(GET_PAGE); 
-		SET(KILL_PAGE); 
-	} 
-	
-	if (get) { 
-		err = get_user(g.regnum, &g32->regnum);
-		err |= get_user(g.base, &g32->base);
-		err |= get_user(g.size, &g32->size);
-		err |= get_user(g.type, &g32->type); 
-
-		arg = (unsigned long)&g; 
-	} else { 
-		struct mtrr_sentry32 __user *s32 = (struct mtrr_sentry32 __user *)arg;
-		err = get_user(s.base, &s32->base);
-		err |= get_user(s.size, &s32->size);
-		err |= get_user(s.type, &s32->type);
-
-		arg = (unsigned long)&s; 
-	} 
-	if (err) return err;
-	
-	set_fs(KERNEL_DS); 
-	err = sys_ioctl(fd, cmd, arg); 
-	set_fs(oldfs); 
-		
-	if (!err && get) { 
-		err = put_user(g.base, &g32->base);
-		err |= put_user(g.size, &g32->size);
-		err |= put_user(g.regnum, &g32->regnum);
-		err |= put_user(g.type, &g32->type); 
-	} 
-	return err;
-} 
 
 #define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) }, 
 #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
@@ -185,7 +72,6 @@
 COMPATIBLE_IOCTL(FIOQSIZE)
 
 /* And these ioctls need translation */
-HANDLE_IOCTL(TIOCGDEV, tiocgdev)
 /* realtime device */
 HANDLE_IOCTL(RTC_IRQP_READ,  rtc32_ioctl)
 HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl)
@@ -193,17 +79,6 @@
 HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl)
 HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl)
 /* take care of sizeof(sizeof()) breakage */
-/* mtrr */
-HANDLE_IOCTL(MTRRIOC32_ADD_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_SET_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_DEL_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_GET_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_KILL_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_ADD_PAGE_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_SET_PAGE_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_DEL_PAGE_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_GET_PAGE_ENTRY, mtrr_ioctl32)
-HANDLE_IOCTL(MTRRIOC32_KILL_PAGE_ENTRY, mtrr_ioctl32)
 }; 
 
 int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index b2a238b..c6c9791 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -494,7 +494,7 @@
 void thermal_interrupt(void);
 void i8254_timer_resume(void);
 
-static void setup_timer(void)
+static void setup_timer_hardware(void)
 {
 	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
 	udelay(10);
@@ -505,13 +505,13 @@
 
 static int timer_resume(struct sys_device *dev)
 {
-	setup_timer();
+	setup_timer_hardware();
 	return 0;
 }
 
 void i8254_timer_resume(void)
 {
-	setup_timer();
+	setup_timer_hardware();
 }
 
 static struct sysdev_class timer_sysclass = {
@@ -594,7 +594,7 @@
 	 * Set the clock to HZ Hz, we already have a valid
 	 * vector now:
 	 */
-	setup_timer();
+	setup_timer_hardware();
 
 	if (!acpi_ioapic)
 		setup_irq(2, &irq2);
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index cf0a031..88be97c 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -187,7 +187,7 @@
 
 /* Allocate DMA memory on node near device */
 noinline
-static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
+static void *dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
 {
 	struct page *page;
 	int node;
@@ -204,7 +204,7 @@
  */
 void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   unsigned gfp)
+		   gfp_t gfp)
 {
 	void *memory;
 	unsigned long dma_mask = 0;
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index 67d90b8..5a981dc 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -24,7 +24,7 @@
  */
 
 void *dma_alloc_coherent(struct device *hwdev, size_t size,
-			 dma_addr_t *dma_handle, unsigned gfp)
+			 dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret;
 	u64 mask;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index cb28df1..da0bc3e 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -1213,7 +1213,7 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
-		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
+		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", NULL, "est",
 		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index f066c6a..fd2bef7 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -63,13 +63,12 @@
 	__save_processor_state(&saved_context);
 }
 
-static void
-do_fpu_end(void)
+static void do_fpu_end(void)
 {
-        /* restore FPU regs if necessary */
-	/* Do it out of line so that gcc does not move cr0 load to some stupid place */
-        kernel_fpu_end();
-	mxcsr_feature_mask_init();
+	/*
+	 * Restore FPU regs if necessary
+	 */
+	kernel_fpu_end();
 }
 
 void __restore_processor_state(struct saved_context *ctxt)
@@ -148,57 +147,7 @@
 
 pgd_t *temp_level4_pgt;
 
-static void **pages;
-
-static inline void *__add_page(void)
-{
-	void **c;
-
-	c = (void **)get_usable_page(GFP_ATOMIC);
-	if (c) {
-		*c = pages;
-		pages = c;
-	}
-	return c;
-}
-
-static inline void *__next_page(void)
-{
-	void **c;
-
-	c = pages;
-	if (c) {
-		pages = *c;
-		*c = NULL;
-	}
-	return c;
-}
-
-/*
- * Try to allocate as many usable pages as needed and daisy chain them.
- * If one allocation fails, free the pages allocated so far
- */
-static int alloc_usable_pages(unsigned long n)
-{
-	void *p;
-
-	pages = NULL;
-	do
-		if (!__add_page())
-			break;
-	while (--n);
-	if (n) {
-		p = __next_page();
-		while (p) {
-			free_page((unsigned long)p);
-			p = __next_page();
-		}
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static void res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
 {
 	long i, j;
 
@@ -212,7 +161,9 @@
 		if (paddr >= end)
 			break;
 
-		pmd = (pmd_t *)__next_page();
+		pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
+		if (!pmd)
+			return -ENOMEM;
 		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
 		for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
 			unsigned long pe;
@@ -224,13 +175,17 @@
 			set_pmd(pmd, __pmd(pe));
 		}
 	}
+	return 0;
 }
 
-static void set_up_temporary_mappings(void)
+static int set_up_temporary_mappings(void)
 {
 	unsigned long start, end, next;
+	int error;
 
-	temp_level4_pgt = (pgd_t *)__next_page();
+	temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
+	if (!temp_level4_pgt)
+		return -ENOMEM;
 
 	/* It is safe to reuse the original kernel mapping */
 	set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
@@ -241,29 +196,27 @@
 	end = (unsigned long)pfn_to_kaddr(end_pfn);
 
 	for (; start < end; start = next) {
-		pud_t *pud = (pud_t *)__next_page();
+		pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+		if (!pud)
+			return -ENOMEM;
 		next = start + PGDIR_SIZE;
 		if (next > end)
 			next = end;
-		res_phys_pud_init(pud, __pa(start), __pa(next));
+		if ((error = res_phys_pud_init(pud, __pa(start), __pa(next))))
+			return error;
 		set_pgd(temp_level4_pgt + pgd_index(start),
 			mk_kernel_pgd(__pa(pud)));
 	}
+	return 0;
 }
 
 int swsusp_arch_resume(void)
 {
-	unsigned long n;
+	int error;
 
-	n = ((end_pfn << PAGE_SHIFT) + PUD_SIZE - 1) >> PUD_SHIFT;
-	n += (n + PTRS_PER_PUD - 1) / PTRS_PER_PUD + 1;
-	pr_debug("swsusp_arch_resume(): pages needed = %lu\n", n);
-	if (alloc_usable_pages(n)) {
-		free_eaten_memory();
-		return -ENOMEM;
-	}
 	/* We have got enough memory and from now on we cannot recover */
-	set_up_temporary_mappings();
+	if ((error = set_up_temporary_mappings()))
+		return error;
 	restore_image();
 	return 0;
 }
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 703acde..fdaddc4 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -42,10 +42,6 @@
 #include <asm/apic.h>
 #endif
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
-
 #ifdef CONFIG_CPU_FREQ
 static void cpufreq_delayed_get(void);
 #endif
@@ -481,9 +477,9 @@
 static unsigned int cyc2ns_scale;
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
-static inline void set_cyc2ns_scale(unsigned long cpu_mhz)
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
 {
-	cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
+	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
 }
 
 static inline unsigned long long cycles_2_ns(unsigned long long cyc)
@@ -655,7 +651,7 @@
 			vxtime.tsc_quot = (1000L << 32) / cpu_khz;
 	}
 	
-	set_cyc2ns_scale(cpu_khz_ref / 1000);
+	set_cyc2ns_scale(cpu_khz_ref);
 
 	return 0;
 }
@@ -939,7 +935,7 @@
 	rdtscll_sync(&vxtime.last_tsc);
 	setup_irq(0, &irq0);
 
-	set_cyc2ns_scale(cpu_khz / 1000);
+	set_cyc2ns_scale(cpu_khz);
 
 #ifndef CONFIG_SMP
 	time_init_gtod();
@@ -1093,6 +1089,7 @@
 static unsigned long PIE_count;
 
 static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
+static unsigned int hpet_t1_cmp; /* cached comparator register */
 
 int is_hpet_enabled(void)
 {
@@ -1129,10 +1126,12 @@
 	cnt = hpet_readl(HPET_COUNTER);
 	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
 	hpet_writel(cnt, HPET_T1_CMP);
+	hpet_t1_cmp = cnt;
 	local_irq_restore(flags);
 
 	cfg = hpet_readl(HPET_T1_CFG);
-	cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT;
+	cfg &= ~HPET_TN_PERIODIC;
+	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
 	hpet_writel(cfg, HPET_T1_CFG);
 
 	return 1;
@@ -1142,8 +1141,12 @@
 {
 	unsigned int cfg, cnt;
 
-	if (!(PIE_on | AIE_on | UIE_on))
+	if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
+		cfg = hpet_readl(HPET_T1_CFG);
+		cfg &= ~HPET_TN_ENABLE;
+		hpet_writel(cfg, HPET_T1_CFG);
 		return;
+	}
 
 	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
 		hpet_rtc_int_freq = PIE_freq;
@@ -1151,15 +1154,10 @@
 		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
 
 	/* It is more accurate to use the comparator value than current count.*/
-	cnt = hpet_readl(HPET_T1_CMP);
+	cnt = hpet_t1_cmp;
 	cnt += hpet_tick*HZ/hpet_rtc_int_freq;
 	hpet_writel(cnt, HPET_T1_CMP);
-
-	cfg = hpet_readl(HPET_T1_CFG);
-	cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T1_CFG);
-
-	return;
+	hpet_t1_cmp = cnt;
 }
 
 /*
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 6972df4..ecf7acb 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -60,7 +60,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -105,7 +105,6 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		pud_t *pud;
 		pud = pud_alloc(&init_mm, pgd, address);
@@ -119,7 +118,6 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		pgd++;
 	} while (address && (address < end));
-	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
 	return error;
 }
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index 84fde25..1ff8226 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -29,7 +29,7 @@
  */
 
 void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
 	void *ret;
 
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
index 03674da..a179307 100644
--- a/arch/xtensa/kernel/platform.c
+++ b/arch/xtensa/kernel/platform.c
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <asm/platform.h>
 #include <asm/timex.h>
+#include <asm/param.h>		/* HZ */
 
 #define _F(r,f,a,b)							\
 	r __platform_##f a b;                                   	\
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 2659efd..1446074 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -45,7 +45,7 @@
 	/* Nothing to do.. */
 }
 
-int sys_ptrace(long request, long pid, long addr, long data)
+long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret = -EPERM;
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 8e423d1..cb6e38e 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -29,9 +29,6 @@
 
 extern volatile unsigned long wall_jiffies;
 
-u64 jiffies_64 = INITIAL_JIFFIES;
-EXPORT_SYMBOL(jiffies_64);
-
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 EXPORT_SYMBOL(rtc_lock);
 
diff --git a/crypto/api.c b/crypto/api.c
index 959c4e5..40ae42e 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -215,7 +215,10 @@
 	if (alg->cra_alignmask & (alg->cra_alignmask + 1))
 		return -EINVAL;
 
-	if (alg->cra_alignmask > PAGE_SIZE)
+	if (alg->cra_alignmask & alg->cra_blocksize)
+		return -EINVAL;
+
+	if (alg->cra_blocksize > PAGE_SIZE)
 		return -EINVAL;
 	
 	down_write(&crypto_alg_sem);
diff --git a/crypto/hmac.c b/crypto/hmac.c
index da0456b..46120de 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -18,18 +18,15 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 #include "internal.h"
 
 static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen)
 {
 	struct scatterlist tmp;
 	
-	tmp.page = virt_to_page(key);
-	tmp.offset = offset_in_page(key);
-	tmp.length = keylen;
+	sg_set_buf(&tmp, key, keylen);
 	crypto_digest_digest(tfm, &tmp, 1, key);
-		
 }
 
 int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
@@ -69,9 +66,7 @@
 	for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
 		ipad[i] ^= 0x36;
 
-	tmp.page = virt_to_page(ipad);
-	tmp.offset = offset_in_page(ipad);
-	tmp.length = crypto_tfm_alg_blocksize(tfm);
+	sg_set_buf(&tmp, ipad, crypto_tfm_alg_blocksize(tfm));
 	
 	crypto_digest_init(tfm);
 	crypto_digest_update(tfm, &tmp, 1);
@@ -103,16 +98,12 @@
 	for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
 		opad[i] ^= 0x5c;
 
-	tmp.page = virt_to_page(opad);
-	tmp.offset = offset_in_page(opad);
-	tmp.length = crypto_tfm_alg_blocksize(tfm);
+	sg_set_buf(&tmp, opad, crypto_tfm_alg_blocksize(tfm));
 
 	crypto_digest_init(tfm);
 	crypto_digest_update(tfm, &tmp, 1);
 	
-	tmp.page = virt_to_page(out);
-	tmp.offset = offset_in_page(out);
-	tmp.length = crypto_tfm_alg_digestsize(tfm);
+	sg_set_buf(&tmp, out, crypto_tfm_alg_digestsize(tfm));
 	
 	crypto_digest_update(tfm, &tmp, 1);
 	crypto_digest_final(tfm, out);
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 6863941..53f4ee8 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -21,7 +21,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/crypto.h>
 #include <linux/highmem.h>
@@ -86,7 +86,6 @@
 static void test_hash(char *algo, struct hash_testvec *template,
 		      unsigned int tcount)
 {
-	char *p;
 	unsigned int i, j, k, temp;
 	struct scatterlist sg[8];
 	char result[64];
@@ -116,10 +115,7 @@
 		printk("test %u:\n", i + 1);
 		memset(result, 0, 64);
 
-		p = hash_tv[i].plaintext;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = hash_tv[i].psize;
+		sg_set_buf(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize);
 
 		crypto_digest_init(tfm);
 		if (tfm->crt_u.digest.dit_setkey) {
@@ -154,10 +150,8 @@
 				       hash_tv[i].plaintext + temp,
 				       hash_tv[i].tap[k]);
 				temp += hash_tv[i].tap[k];
-				p = &xbuf[IDX[k]];
-				sg[k].page = virt_to_page(p);
-				sg[k].offset = offset_in_page(p);
-				sg[k].length = hash_tv[i].tap[k];
+				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+					    hash_tv[i].tap[k]);
 			}
 
 			crypto_digest_digest(tfm, sg, hash_tv[i].np, result);
@@ -179,7 +173,6 @@
 static void test_hmac(char *algo, struct hmac_testvec *template,
 		      unsigned int tcount)
 {
-	char *p;
 	unsigned int i, j, k, temp;
 	struct scatterlist sg[8];
 	char result[64];
@@ -210,11 +203,8 @@
 		printk("test %u:\n", i + 1);
 		memset(result, 0, sizeof (result));
 
-		p = hmac_tv[i].plaintext;
 		klen = hmac_tv[i].ksize;
-		sg[0].page = virt_to_page(p);
-		sg[0].offset = offset_in_page(p);
-		sg[0].length = hmac_tv[i].psize;
+		sg_set_buf(&sg[0], hmac_tv[i].plaintext, hmac_tv[i].psize);
 
 		crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result);
 
@@ -243,10 +233,8 @@
 				       hmac_tv[i].plaintext + temp,
 				       hmac_tv[i].tap[k]);
 				temp += hmac_tv[i].tap[k];
-				p = &xbuf[IDX[k]];
-				sg[k].page = virt_to_page(p);
-				sg[k].offset = offset_in_page(p);
-				sg[k].length = hmac_tv[i].tap[k];
+				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+					    hmac_tv[i].tap[k]);
 			}
 
 			crypto_hmac(tfm, hmac_tv[i].key, &klen, sg,
@@ -270,7 +258,7 @@
 {
 	unsigned int ret, i, j, k, temp;
 	unsigned int tsize;
-	char *p, *q;
+	char *q;
 	struct crypto_tfm *tfm;
 	char *key;
 	struct cipher_testvec *cipher_tv;
@@ -330,10 +318,8 @@
 					goto out;
 			}
 
-			p = cipher_tv[i].input;
-			sg[0].page = virt_to_page(p);
-			sg[0].offset = offset_in_page(p);
-			sg[0].length = cipher_tv[i].ilen;
+			sg_set_buf(&sg[0], cipher_tv[i].input,
+				   cipher_tv[i].ilen);
 
 			if (!mode) {
 				crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
@@ -389,10 +375,8 @@
 				       cipher_tv[i].input + temp,
 				       cipher_tv[i].tap[k]);
 				temp += cipher_tv[i].tap[k];
-				p = &xbuf[IDX[k]];
-				sg[k].page = virt_to_page(p);
-				sg[k].offset = offset_in_page(p);
-				sg[k].length = cipher_tv[i].tap[k];
+				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+					   cipher_tv[i].tap[k]);
 			}
 
 			if (!mode) {
@@ -431,14 +415,12 @@
 static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p,
 			       int blen, int sec)
 {
-	struct scatterlist sg[8];
+	struct scatterlist sg[1];
 	unsigned long start, end;
 	int bcount;
 	int ret;
 
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = blen;
+	sg_set_buf(sg, p, blen);
 
 	for (start = jiffies, end = start + sec * HZ, bcount = 0;
 	     time_before(jiffies, end); bcount++) {
@@ -459,14 +441,12 @@
 static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p,
 			      int blen)
 {
-	struct scatterlist sg[8];
+	struct scatterlist sg[1];
 	unsigned long cycles = 0;
 	int ret = 0;
 	int i;
 
-	sg[0].page = virt_to_page(p);
-	sg[0].offset = offset_in_page(p);
-	sg[0].length = blen;
+	sg_set_buf(sg, p, blen);
 
 	local_bh_disable();
 	local_irq_disable();
@@ -709,9 +689,7 @@
 	for (i = 0; i < NUMVEC; i++) {
 		for (j = 0; j < VECSIZE; j++)
 			test_vec[i][j] = ++b;
-		sg[i].page = virt_to_page(test_vec[i]);
-		sg[i].offset = offset_in_page(test_vec[i]);
-		sg[i].length = VECSIZE;
+		sg_set_buf(&sg[i], test_vec[i], VECSIZE);
 	}
 
 	seed = SEEDTESTVAL;
diff --git a/drivers/Makefile b/drivers/Makefile
index 1a109a6..65670be 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,7 +5,7 @@
 # Rewritten to use lists instead of if-statements.
 #
 
-obj-$(CONFIG_PCI)		+= pci/
+obj-$(CONFIG_PCI)		+= pci/ usb/
 obj-$(CONFIG_PARISC)		+= parisc/
 obj-y				+= video/
 obj-$(CONFIG_ACPI)		+= acpi/
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index 2b850e5..e26f007 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -9,6 +9,7 @@
  *
  *  Driver for PCF8583 RTC & RAM chip
  */
+#include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -32,7 +33,8 @@
 	.forces			= forces,
 };
 
-#define DAT(x) ((unsigned int)(x->dev.driver_data))
+#define set_ctrl(x, v) i2c_set_clientdata(x, (void *)(unsigned int)(v))
+#define get_ctrl(x)    ((unsigned int)i2c_get_clientdata(x))
 
 static int
 pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
@@ -40,8 +42,17 @@
 	struct i2c_client *c;
 	unsigned char buf[1], ad[1] = { 0 };
 	struct i2c_msg msgs[2] = {
-		{ addr, 0,        1, ad  },
-		{ addr, I2C_M_RD, 1, buf }
+		{
+			.addr = addr,
+			.flags = 0,
+			.len = 1,
+			.buf = ad,
+		}, {
+			.addr = addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = buf,
+		}
 	};
 
 	c = kmalloc(sizeof(*c), GFP_KERNEL);
@@ -54,7 +65,7 @@
 	c->driver	= &pcf8583_driver;
 
 	if (i2c_transfer(c->adapter, msgs, 2) == 2)
-		DAT(c) = buf[0];
+		set_ctrl(c, buf[0]);
 
 	return i2c_attach_client(c);
 }
@@ -78,8 +89,17 @@
 {
 	unsigned char buf[8], addr[1] = { 1 };
 	struct i2c_msg msgs[2] = {
-		{ client->addr, 0,        1, addr },
-		{ client->addr, I2C_M_RD, 6, buf  }
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 6,
+			.buf = buf,
+		}
 	};
 	int ret = -EIO;
 
@@ -113,7 +133,7 @@
 	int ret, len = 6;
 
 	buf[0] = 0;
-	buf[1] = DAT(client) | 0x80;
+	buf[1] = get_ctrl(client) | 0x80;
 	buf[2] = BIN_TO_BCD(dt->cs);
 	buf[3] = BIN_TO_BCD(dt->secs);
 	buf[4] = BIN_TO_BCD(dt->mins);
@@ -129,7 +149,7 @@
 	if (ret == len)
 		ret = 0;
 
-	buf[1] = DAT(client);
+	buf[1] = get_ctrl(client);
 	i2c_master_send(client, (char *)buf, 2);
 
 	return ret;
@@ -138,7 +158,7 @@
 static int
 pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
 {
-	*ctrl = DAT(client);
+	*ctrl = get_ctrl(client);
 	return 0;
 }
 
@@ -149,7 +169,7 @@
 
 	buf[0] = 0;
 	buf[1] = *ctrl;
-	DAT(client) = *ctrl;
+	set_ctrl(client, *ctrl);
 
 	return i2c_master_send(client, (char *)buf, 2);
 }
@@ -159,15 +179,23 @@
 {
 	unsigned char addr[1];
 	struct i2c_msg msgs[2] = {
-		{ client->addr, 0,        1, addr },
-		{ client->addr, I2C_M_RD, 0, mem->data }
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = mem->nr,
+			.buf = mem->data,
+		}
 	};
 
 	if (mem->loc < 8)
 		return -EINVAL;
 
 	addr[0] = mem->loc;
-	msgs[1].len = mem->nr;
 
 	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
 }
@@ -177,15 +205,23 @@
 {
 	unsigned char addr[1];
 	struct i2c_msg msgs[2] = {
-		{ client->addr, 0, 1, addr },
-		{ client->addr, 0, 0, mem->data }
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_NOSTART,
+			.len = mem->nr,
+			.buf = mem->data,
+		}
 	};
 
 	if (mem->loc < 8)
 		return -EINVAL;
 
 	addr[0] = mem->loc;
-	msgs[1].len = mem->nr;
 
 	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
 }
@@ -234,4 +270,14 @@
 	return i2c_add_driver(&pcf8583_driver);
 }
 
-__initcall(pcf8583_init);
+static __exit void pcf8583_exit(void)
+{
+	i2c_del_driver(&pcf8583_driver);
+}
+
+module_init(pcf8583_init);
+module_exit(pcf8583_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 01a1bd2..2143609 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -200,8 +200,7 @@
 	 * Note: Assume that this function returns zero on success
 	 */
 	result = add_memory(mem_device->start_addr,
-			    (mem_device->end_addr - mem_device->start_addr) + 1,
-			    mem_device->read_write_attribute);
+			    (mem_device->end_addr - mem_device->start_addr) + 1);
 	if (result) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n"));
 		mem_device->state = MEMORY_INVALID_STATE;
@@ -259,7 +258,7 @@
 	 * Ask the VM to offline this memory range.
 	 * Note: Assume that this function returns zero on success
 	 */
-	result = remove_memory(start, len, attr);
+	result = remove_memory(start, len);
 	if (result) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
 		return_VALUE(result);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 26a3a40..161db4a 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -37,6 +37,7 @@
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
+#include <linux/sched.h>	/* need_resched() */
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index aee50b4..930427f 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -158,7 +158,15 @@
 	return -EINVAL;
 }
 
+static int acpi_pm_state_valid(suspend_state_t pm_state)
+{
+	u32 acpi_state = acpi_suspend_states[pm_state];
+
+	return sleep_states[acpi_state];
+}
+
 static struct pm_ops acpi_pm_ops = {
+	.valid = acpi_pm_state_valid,
 	.prepare = acpi_pm_prepare,
 	.enter = acpi_pm_enter,
 	.finish = acpi_pm_finish,
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 66d9c46..f12898d 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -7,6 +7,7 @@
 obj-y			+= power/
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
+obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
 
 ifeq ($(CONFIG_DEBUG_DRIVER),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 6b2eb6f..2a7d7ae 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -19,6 +19,8 @@
 #include <linux/list.h>
 #include <linux/module.h>
 
+#include "base.h"
+
 /* This is a private structure used to tie the classdev and the
  * container .. it should never be visible outside this file */
 struct internal_container {
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 783752b..e3b548d 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -1,3 +1,15 @@
+
+/* initialisation functions */
+
+extern int devices_init(void);
+extern int buses_init(void);
+extern int classes_init(void);
+extern int firmware_init(void);
+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_remove_device(struct device * dev);
 
diff --git a/drivers/base/class.c b/drivers/base/class.c
index ce23dc8..db65fd0 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/kdev_t.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -99,7 +100,8 @@
 
 void class_put(struct class * cls)
 {
-	subsys_put(&cls->subsys);
+	if (cls)
+		subsys_put(&cls->subsys);
 }
 
 
@@ -165,14 +167,25 @@
 
 static void class_create_release(struct class *cls)
 {
+	pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
 	kfree(cls);
 }
 
 static void class_device_create_release(struct class_device *class_dev)
 {
+	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
 	kfree(class_dev);
 }
 
+/* needed to allow these devices to have parent class devices */
+static int class_device_create_hotplug(struct class_device *class_dev,
+				       char **envp, int num_envp,
+				       char *buffer, int buffer_size)
+{
+	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
+	return 0;
+}
+
 /**
  * class_create - create a struct class structure
  * @owner: pointer to the module that is to "own" this struct class
@@ -301,10 +314,12 @@
 	kfree(cd->devt_attr);
 	cd->devt_attr = NULL;
 
-	if (cls->release)
+	if (cd->release)
+		cd->release(cd);
+	else if (cls->release)
 		cls->release(cd);
 	else {
-		printk(KERN_ERR "Device class '%s' does not have a release() function, "
+		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);
@@ -382,14 +397,18 @@
 	buffer = &buffer[length];
 	buffer_size -= length;
 
-	if (class_dev->class->hotplug) {
-		/* have the bus specific function add its stuff */
-		retval = class_dev->class->hotplug (class_dev, envp, num_envp,
-						    buffer, buffer_size);
-			if (retval) {
-			pr_debug ("%s - hotplug() returned %d\n",
-				  __FUNCTION__, retval);
-		}
+	if (class_dev->hotplug) {
+		/* have the class device specific function add its stuff */
+		retval = class_dev->hotplug(class_dev, envp, num_envp,
+					    buffer, buffer_size);
+		if (retval)
+			pr_debug("class_dev->hotplug() returned %d\n", retval);
+	} else if (class_dev->class->hotplug) {
+		/* have the class specific function add its stuff */
+		retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+						   buffer, buffer_size);
+		if (retval)
+			pr_debug("class->hotplug() returned %d\n", retval);
 	}
 
 	return retval;
@@ -442,6 +461,13 @@
 	return print_dev_t(buf, class_dev->devt);
 }
 
+static ssize_t store_uevent(struct class_device *class_dev,
+			    const char *buf, size_t count)
+{
+	kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+	return count;
+}
+
 void class_device_initialize(struct class_device *class_dev)
 {
 	kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -469,34 +495,45 @@
 
 int class_device_add(struct class_device *class_dev)
 {
-	struct class * parent = NULL;
-	struct class_interface * class_intf;
+	struct class *parent_class = NULL;
+	struct class_device *parent_class_dev = NULL;
+	struct class_interface *class_intf;
 	char *class_name = NULL;
-	int error;
+	int error = -EINVAL;
 
 	class_dev = class_device_get(class_dev);
 	if (!class_dev)
 		return -EINVAL;
 
-	if (!strlen(class_dev->class_id)) {
-		error = -EINVAL;
+	if (!strlen(class_dev->class_id))
 		goto register_done;
-	}
 
-	parent = class_get(class_dev->class);
+	parent_class = class_get(class_dev->class);
+	if (!parent_class)
+		goto register_done;
+	parent_class_dev = class_device_get(class_dev->parent);
 
 	pr_debug("CLASS: registering class device: ID = '%s'\n",
 		 class_dev->class_id);
 
 	/* first, register with generic layer. */
 	kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
-	if (parent)
-		class_dev->kobj.parent = &parent->subsys.kset.kobj;
+	if (parent_class_dev)
+		class_dev->kobj.parent = &parent_class_dev->kobj;
+	else
+		class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
 
-	if ((error = kobject_add(&class_dev->kobj)))
+	error = kobject_add(&class_dev->kobj);
+	if (error)
 		goto register_done;
 
 	/* add the needed attributes to this device */
+	class_dev->uevent_attr.attr.name = "uevent";
+	class_dev->uevent_attr.attr.mode = S_IWUSR;
+	class_dev->uevent_attr.attr.owner = parent_class->owner;
+	class_dev->uevent_attr.store = store_uevent;
+	class_device_create_file(class_dev, &class_dev->uevent_attr);
+
 	if (MAJOR(class_dev->devt)) {
 		struct class_device_attribute *attr;
 		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
@@ -505,12 +542,10 @@
 			kobject_del(&class_dev->kobj);
 			goto register_done;
 		}
-
 		attr->attr.name = "dev";
 		attr->attr.mode = S_IRUGO;
-		attr->attr.owner = parent->owner;
+		attr->attr.owner = parent_class->owner;
 		attr->show = show_dev;
-		attr->store = NULL;
 		class_device_create_file(class_dev, attr);
 		class_dev->devt_attr = attr;
 	}
@@ -524,20 +559,23 @@
 				  class_name);
 	}
 
-	/* notify any interfaces this device is now here */
-	if (parent) {
-		down(&parent->sem);
-		list_add_tail(&class_dev->node, &parent->children);
-		list_for_each_entry(class_intf, &parent->interfaces, node)
-			if (class_intf->add)
-				class_intf->add(class_dev);
-		up(&parent->sem);
-	}
 	kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
 
+	/* notify any interfaces this device is now here */
+	if (parent_class) {
+		down(&parent_class->sem);
+		list_add_tail(&class_dev->node, &parent_class->children);
+		list_for_each_entry(class_intf, &parent_class->interfaces, node)
+			if (class_intf->add)
+				class_intf->add(class_dev, class_intf);
+		up(&parent_class->sem);
+	}
+
  register_done:
-	if (error && parent)
-		class_put(parent);
+	if (error) {
+		class_put(parent_class);
+		class_device_put(parent_class_dev);
+	}
 	class_device_put(class_dev);
 	kfree(class_name);
 	return error;
@@ -552,21 +590,28 @@
 /**
  * class_device_create - creates a class device and registers it with sysfs
  * @cs: 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.
  * @dev: the dev_t for the char device to be added.
  * @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
  * class_device will be created in sysfs, registered to the specified
- * class.  A "dev" file will be created, showing the dev_t for the
- * device.  The pointer to the struct class_device will be returned from
- * the call.  Any further sysfs files that might be required can be
- * created using this pointer.
+ * class.
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct class_device is passed in, the newly
+ * created struct class_device will be a child of that device in sysfs.
+ * The pointer to the struct class_device will be returned from the
+ * call.  Any further sysfs files that might be required can be created
+ * using this pointer.
  *
  * Note: the struct class passed to this function must have previously
  * been created with a call to class_create().
  */
-struct class_device *class_device_create(struct class *cls, dev_t devt,
+struct class_device *class_device_create(struct class *cls,
+					 struct class_device *parent,
+					 dev_t devt,
 					 struct device *device, char *fmt, ...)
 {
 	va_list args;
@@ -585,6 +630,9 @@
 	class_dev->devt = devt;
 	class_dev->dev = device;
 	class_dev->class = cls;
+	class_dev->parent = parent;
+	class_dev->release = class_device_create_release;
+	class_dev->hotplug = class_device_create_hotplug;
 
 	va_start(args, fmt);
 	vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -602,17 +650,18 @@
 
 void class_device_del(struct class_device *class_dev)
 {
-	struct class * parent = class_dev->class;
-	struct class_interface * class_intf;
+	struct class *parent_class = class_dev->class;
+	struct class_device *parent_device = class_dev->parent;
+	struct class_interface *class_intf;
 	char *class_name = NULL;
 
-	if (parent) {
-		down(&parent->sem);
+	if (parent_class) {
+		down(&parent_class->sem);
 		list_del_init(&class_dev->node);
-		list_for_each_entry(class_intf, &parent->interfaces, node)
+		list_for_each_entry(class_intf, &parent_class->interfaces, node)
 			if (class_intf->remove)
-				class_intf->remove(class_dev);
-		up(&parent->sem);
+				class_intf->remove(class_dev, class_intf);
+		up(&parent_class->sem);
 	}
 
 	if (class_dev->dev) {
@@ -620,6 +669,7 @@
 		sysfs_remove_link(&class_dev->kobj, "device");
 		sysfs_remove_link(&class_dev->dev->kobj, class_name);
 	}
+	class_device_remove_file(class_dev, &class_dev->uevent_attr);
 	if (class_dev->devt_attr)
 		class_device_remove_file(class_dev, class_dev->devt_attr);
 	class_device_remove_attrs(class_dev);
@@ -627,8 +677,8 @@
 	kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
 	kobject_del(&class_dev->kobj);
 
-	if (parent)
-		class_put(parent);
+	class_device_put(parent_device);
+	class_put(parent_class);
 	kfree(class_name);
 }
 
@@ -708,7 +758,8 @@
 
 void class_device_put(struct class_device *class_dev)
 {
-	kobject_put(&class_dev->kobj);
+	if (class_dev)
+		kobject_put(&class_dev->kobj);
 }
 
 
@@ -728,7 +779,7 @@
 	list_add_tail(&class_intf->node, &parent->interfaces);
 	if (class_intf->add) {
 		list_for_each_entry(class_dev, &parent->children, node)
-			class_intf->add(class_dev);
+			class_intf->add(class_dev, class_intf);
 	}
 	up(&parent->sem);
 
@@ -747,7 +798,7 @@
 	list_del_init(&class_intf->node);
 	if (class_intf->remove) {
 		list_for_each_entry(class_dev, &parent->children, node)
-			class_intf->remove(class_dev);
+			class_intf->remove(class_dev, class_intf);
 	}
 	up(&parent->sem);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6ab73f5..8615b42 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -154,6 +154,13 @@
 	.hotplug =	dev_hotplug,
 };
 
+static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	kobject_hotplug(&dev->kobj, KOBJ_ADD);
+	return count;
+}
+
 /**
  *	device_subsys - structure to be registered with kobject core.
  */
@@ -225,6 +232,7 @@
 		   klist_children_put);
 	INIT_LIST_HEAD(&dev->dma_pools);
 	init_MUTEX(&dev->sem);
+	device_init_wakeup(dev, 0);
 }
 
 /**
@@ -258,6 +266,14 @@
 
 	if ((error = kobject_add(&dev->kobj)))
 		goto Error;
+
+	dev->uevent_attr.attr.name = "uevent";
+	dev->uevent_attr.attr.mode = S_IWUSR;
+	if (dev->driver)
+		dev->uevent_attr.attr.owner = dev->driver->owner;
+	dev->uevent_attr.store = store_uevent;
+	device_create_file(dev, &dev->uevent_attr);
+
 	kobject_hotplug(&dev->kobj, KOBJ_ADD);
 	if ((error = device_pm_add(dev)))
 		goto PMError;
@@ -349,6 +365,7 @@
 
 	if (parent)
 		klist_del(&dev->knode_parent);
+	device_remove_file(dev, &dev->uevent_attr);
 
 	/* Notify the platform of the removal, in case they
 	 * need to do anything...
@@ -390,11 +407,11 @@
 
 /**
  *	device_for_each_child - device child iterator.
- *	@dev:	parent struct device.
+ *	@parent: parent struct device.
  *	@data:	data for the callback.
  *	@fn:	function to be called for each device.
  *
- *	Iterate over @dev's child devices, and call @fn for each,
+ *	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
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index b79badd..a958447 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -9,12 +9,15 @@
 #include <linux/topology.h>
 #include <linux/device.h>
 
+#include "base.h"
 
 struct sysdev_class cpu_sysdev_class = {
 	set_kset_name("cpu"),
 };
 EXPORT_SYMBOL(cpu_sysdev_class);
 
+static struct sys_device *cpu_sys_devices[NR_CPUS];
+
 #ifdef CONFIG_HOTPLUG_CPU
 int __attribute__((weak)) smp_prepare_cpu (int cpu)
 {
@@ -63,6 +66,7 @@
 }
 void unregister_cpu(struct cpu *cpu, struct node *root)
 {
+	int logical_cpu = cpu->sysdev.id;
 
 	if (root)
 		sysfs_remove_link(&root->sysdev.kobj,
@@ -70,7 +74,7 @@
 	sysdev_remove_file(&cpu->sysdev, &attr_online);
 
 	sysdev_unregister(&cpu->sysdev);
-
+	cpu_sys_devices[logical_cpu] = NULL;
 	return;
 }
 #else /* ... !CONFIG_HOTPLUG_CPU */
@@ -102,10 +106,19 @@
 					  kobject_name(&cpu->sysdev.kobj));
 	if (!error && !cpu->no_control)
 		register_cpu_control(cpu);
+	if (!error)
+		cpu_sys_devices[num] = &cpu->sysdev;
 	return error;
 }
 
-
+struct sys_device *get_cpu_sysdev(int cpu)
+{
+	if (cpu < NR_CPUS)
+		return cpu_sys_devices[cpu];
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(get_cpu_sysdev);
 
 int __init cpu_dev_init(void)
 {
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index ef3fe51..161f3a3 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -28,6 +28,7 @@
 /**
  *	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.
  *
@@ -57,7 +58,7 @@
 
 /**
  * driver_find_device - device iterator for locating a particular device.
- * @driver: The device's driver
+ * @drv: The device's driver
  * @start: Device to begin with
  * @data: Data to pass to match function
  * @match: Callback function to check device
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
index 88ab044..cb1b98a 100644
--- a/drivers/base/firmware.c
+++ b/drivers/base/firmware.c
@@ -11,6 +11,9 @@
 #include <linux/kobject.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/device.h>
+
+#include "base.h"
 
 static decl_subsys(firmware, NULL, NULL);
 
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4acb2c5..98f6c02 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -62,14 +62,16 @@
 }
 
 /**
- * firmware_timeout_store:
- * Description:
+ * firmware_timeout_store - set number of seconds to wait for firmware
+ * @class: device class pointer
+ * @buf: buffer to scan for timeout value
+ * @count: number of bytes in @buf
+ *
  *	Sets the number of seconds to wait for the firmware.  Once
- *	this expires an error will be return to the driver and no
+ *	this expires an error will be returned to the driver and no
  *	firmware will be provided.
  *
- *	Note: zero means 'wait for ever'
- *
+ *	Note: zero means 'wait forever'.
  **/
 static ssize_t
 firmware_timeout_store(struct class *class, const char *buf, size_t count)
@@ -123,12 +125,15 @@
 }
 
 /**
- * firmware_loading_store: - loading control file
- * Description:
+ * firmware_loading_store - set value in the 'loading' control file
+ * @class_dev: class_device pointer
+ * @buf: buffer to scan for loading control value
+ * @count: number of bytes in @buf
+ *
  *	The relevant values are:
  *
  *	 1: Start a load, discarding any previous partial load.
- *	 0: Conclude the load and handle the data to the driver code.
+ *	 0: Conclude the load and hand the data to the driver code.
  *	-1: Conclude the load with an error and discard any written data.
  **/
 static ssize_t
@@ -201,6 +206,7 @@
 	up(&fw_lock);
 	return ret_count;
 }
+
 static int
 fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
@@ -227,11 +233,13 @@
 }
 
 /**
- * firmware_data_write:
+ * firmware_data_write - write method for firmware
+ * @kobj: kobject for the class_device
+ * @buffer: buffer being written
+ * @offset: buffer offset for write in total data store area
+ * @count: buffer size
  *
- * Description:
- *
- *	Data written to the 'data' attribute will be later handled to
+ *	Data written to the 'data' attribute will be later handed to
  *	the driver as a firmware image.
  **/
 static ssize_t
@@ -264,6 +272,7 @@
 	up(&fw_lock);
 	return retval;
 }
+
 static struct bin_attribute firmware_attr_data_tmpl = {
 	.attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
 	.size = 0,
@@ -448,13 +457,16 @@
 
 /**
  * request_firmware: - request firmware to hotplug and wait for it
- * Description:
- *      @firmware will be used to return a firmware image by the name
+ * @firmware_p: pointer to firmware image
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ *
+ *      @firmware_p will be used to return a firmware image by the name
  *      of @name for device @device.
  *
  *      Should be called from user context where sleeping is allowed.
  *
- *      @name will be use as $FIRMWARE in the hotplug environment and
+ *      @name will be used as $FIRMWARE in the hotplug environment and
  *      should be distinctive enough not to be confused with any other
  *      firmware image for this or any other device.
  **/
@@ -468,6 +480,7 @@
 
 /**
  * release_firmware: - release the resource associated with a firmware image
+ * @fw: firmware resource to release
  **/
 void
 release_firmware(const struct firmware *fw)
@@ -480,8 +493,10 @@
 
 /**
  * register_firmware: - provide a firmware image for later usage
+ * @name: name of firmware image file
+ * @data: buffer pointer for the firmware image
+ * @size: size of the data buffer area
  *
- * Description:
  *	Make sure that @data will be available by requesting firmware @name.
  *
  *	Note: This will not be possible until some kind of persistence
@@ -526,21 +541,19 @@
 }
 
 /**
- * request_firmware_nowait:
+ * request_firmware_nowait: asynchronous version of request_firmware
+ * @module: module requesting the firmware
+ * @hotplug: invokes hotplug event to copy the firmware image if this flag
+ *	is non-zero else the firmware copy must be done manually.
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ * @context: will be passed over to @cont, and
+ *	@fw may be %NULL if firmware request fails.
+ * @cont: function will be called asynchronously when the firmware
+ *	request is over.
  *
- * Description:
  *	Asynchronous variant of request_firmware() for contexts where
  *	it is not possible to sleep.
- *
- *      @hotplug invokes hotplug event to copy the firmware image if this flag
- *      is non-zero else the firmware copy must be done manually.
- *
- *	@cont will be called asynchronously when the firmware request is over.
- *
- *	@context will be passed over to @cont.
- *
- *	@fw may be %NULL if firmware request fails.
- *
  **/
 int
 request_firmware_nowait(
diff --git a/drivers/base/init.c b/drivers/base/init.c
index a76ae5a..c648914 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -9,15 +9,10 @@
 
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/memory.h>
 
-extern int devices_init(void);
-extern int buses_init(void);
-extern int classes_init(void);
-extern int firmware_init(void);
-extern int platform_bus_init(void);
-extern int system_bus_init(void);
-extern int cpu_dev_init(void);
-extern int attribute_container_init(void);
+#include "base.h"
+
 /**
  *	driver_init - initialize driver model.
  *
@@ -39,5 +34,6 @@
 	platform_bus_init();
 	system_bus_init();
 	cpu_dev_init();
+	memory_dev_init();
 	attribute_container_init();
 }
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
new file mode 100644
index 0000000..b7ddd65
--- /dev/null
+++ b/drivers/base/memory.c
@@ -0,0 +1,452 @@
+/*
+ * drivers/base/memory.c - basic Memory class support
+ *
+ * Written by Matt Tolentino <matthew.e.tolentino@intel.com>
+ *            Dave Hansen <haveblue@us.ibm.com>
+ *
+ * This file provides the necessary infrastructure to represent
+ * a SPARSEMEM-memory-model system's physical memory in /sysfs.
+ * All arch-independent code that assumes MEMORY_HOTPLUG requires
+ * SPARSEMEM should be contained here, or in mm/memory_hotplug.c.
+ */
+
+#include <linux/sysdev.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>	/* capable() */
+#include <linux/topology.h>
+#include <linux/device.h>
+#include <linux/memory.h>
+#include <linux/kobject.h>
+#include <linux/memory_hotplug.h>
+#include <linux/mm.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+
+#define MEMORY_CLASS_NAME	"memory"
+
+static struct sysdev_class memory_sysdev_class = {
+	set_kset_name(MEMORY_CLASS_NAME),
+};
+EXPORT_SYMBOL(memory_sysdev_class);
+
+static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
+{
+	return MEMORY_CLASS_NAME;
+}
+
+static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+			int num_envp, char *buffer, int buffer_size)
+{
+	int retval = 0;
+
+	return retval;
+}
+
+static struct kset_hotplug_ops memory_hotplug_ops = {
+	.name		= memory_hotplug_name,
+	.hotplug	= memory_hotplug,
+};
+
+static struct notifier_block *memory_chain;
+
+static int register_memory_notifier(struct notifier_block *nb)
+{
+        return notifier_chain_register(&memory_chain, nb);
+}
+
+static void unregister_memory_notifier(struct notifier_block *nb)
+{
+        notifier_chain_unregister(&memory_chain, nb);
+}
+
+/*
+ * register_memory - Setup a sysfs device for a memory block
+ */
+static int
+register_memory(struct memory_block *memory, struct mem_section *section,
+		struct node *root)
+{
+	int error;
+
+	memory->sysdev.cls = &memory_sysdev_class;
+	memory->sysdev.id = __section_nr(section);
+
+	error = sysdev_register(&memory->sysdev);
+
+	if (root && !error)
+		error = sysfs_create_link(&root->sysdev.kobj,
+					  &memory->sysdev.kobj,
+					  kobject_name(&memory->sysdev.kobj));
+
+	return error;
+}
+
+static void
+unregister_memory(struct memory_block *memory, struct mem_section *section,
+		struct node *root)
+{
+	BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
+	BUG_ON(memory->sysdev.id != __section_nr(section));
+
+	sysdev_unregister(&memory->sysdev);
+	if (root)
+		sysfs_remove_link(&root->sysdev.kobj,
+				  kobject_name(&memory->sysdev.kobj));
+}
+
+/*
+ * use this as the physical section index that this memsection
+ * uses.
+ */
+
+static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	return sprintf(buf, "%08lx\n", mem->phys_index);
+}
+
+/*
+ * online, offline, going offline, etc.
+ */
+static ssize_t show_mem_state(struct sys_device *dev, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	ssize_t len = 0;
+
+	/*
+	 * We can probably put these states in a nice little array
+	 * so that they're not open-coded
+	 */
+	switch (mem->state) {
+		case MEM_ONLINE:
+			len = sprintf(buf, "online\n");
+			break;
+		case MEM_OFFLINE:
+			len = sprintf(buf, "offline\n");
+			break;
+		case MEM_GOING_OFFLINE:
+			len = sprintf(buf, "going-offline\n");
+			break;
+		default:
+			len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
+					mem->state);
+			WARN_ON(1);
+			break;
+	}
+
+	return len;
+}
+
+static inline int memory_notify(unsigned long val, void *v)
+{
+	return notifier_call_chain(&memory_chain, val, v);
+}
+
+/*
+ * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
+ * OK to have direct references to sparsemem variables in here.
+ */
+static int
+memory_block_action(struct memory_block *mem, unsigned long action)
+{
+	int i;
+	unsigned long psection;
+	unsigned long start_pfn, start_paddr;
+	struct page *first_page;
+	int ret;
+	int old_state = mem->state;
+
+	psection = mem->phys_index;
+	first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
+
+	/*
+	 * The probe routines leave the pages reserved, just
+	 * as the bootmem code does.  Make sure they're still
+	 * that way.
+	 */
+	if (action == MEM_ONLINE) {
+		for (i = 0; i < PAGES_PER_SECTION; i++) {
+			if (PageReserved(first_page+i))
+				continue;
+
+			printk(KERN_WARNING "section number %ld page number %d "
+				"not reserved, was it already online? \n",
+				psection, i);
+			return -EBUSY;
+		}
+	}
+
+	switch (action) {
+		case MEM_ONLINE:
+			start_pfn = page_to_pfn(first_page);
+			ret = online_pages(start_pfn, PAGES_PER_SECTION);
+			break;
+		case MEM_OFFLINE:
+			mem->state = MEM_GOING_OFFLINE;
+			memory_notify(MEM_GOING_OFFLINE, NULL);
+			start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
+			ret = remove_memory(start_paddr,
+					    PAGES_PER_SECTION << PAGE_SHIFT);
+			if (ret) {
+				mem->state = old_state;
+				break;
+			}
+			memory_notify(MEM_MAPPING_INVALID, NULL);
+			break;
+		default:
+			printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
+					__FUNCTION__, mem, action, action);
+			WARN_ON(1);
+			ret = -EINVAL;
+	}
+	/*
+	 * For now, only notify on successful memory operations
+	 */
+	if (!ret)
+		memory_notify(action, NULL);
+
+	return ret;
+}
+
+static int memory_block_change_state(struct memory_block *mem,
+		unsigned long to_state, unsigned long from_state_req)
+{
+	int ret = 0;
+	down(&mem->state_sem);
+
+	if (mem->state != from_state_req) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = memory_block_action(mem, to_state);
+	if (!ret)
+		mem->state = to_state;
+
+out:
+	up(&mem->state_sem);
+	return ret;
+}
+
+static ssize_t
+store_mem_state(struct sys_device *dev, const char *buf, size_t count)
+{
+	struct memory_block *mem;
+	unsigned int phys_section_nr;
+	int ret = -EINVAL;
+
+	mem = container_of(dev, struct memory_block, sysdev);
+	phys_section_nr = mem->phys_index;
+
+	if (!valid_section_nr(phys_section_nr))
+		goto out;
+
+	if (!strncmp(buf, "online", min((int)count, 6)))
+		ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+	else if(!strncmp(buf, "offline", min((int)count, 7)))
+		ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
+out:
+	if (ret)
+		return ret;
+	return count;
+}
+
+/*
+ * phys_device is a bad name for this.  What I really want
+ * is a way to differentiate between memory ranges that
+ * are part of physical devices that constitute
+ * a complete removable unit or fru.
+ * i.e. do these ranges belong to the same physical device,
+ * s.t. if I offline all of these sections I can then
+ * remove the physical device?
+ */
+static ssize_t show_phys_device(struct sys_device *dev, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	return sprintf(buf, "%d\n", mem->phys_device);
+}
+
+static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
+static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
+static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
+
+#define mem_create_simple_file(mem, attr_name)	\
+	sysdev_create_file(&mem->sysdev, &attr_##attr_name)
+#define mem_remove_simple_file(mem, attr_name)	\
+	sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
+
+/*
+ * Block size attribute stuff
+ */
+static ssize_t
+print_block_size(struct class *class, char *buf)
+{
+	return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
+}
+
+static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
+
+static int block_size_init(void)
+{
+	sysfs_create_file(&memory_sysdev_class.kset.kobj,
+		&class_attr_block_size_bytes.attr);
+	return 0;
+}
+
+/*
+ * Some architectures will have custom drivers to do this, and
+ * will not need to do it from userspace.  The fake hot-add code
+ * as well as ppc64 will do all of their discovery in userspace
+ * and will require this interface.
+ */
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+static ssize_t
+memory_probe_store(struct class *class, const char __user *buf, size_t count)
+{
+	u64 phys_addr;
+	int ret;
+
+	phys_addr = simple_strtoull(buf, NULL, 0);
+
+	ret = add_memory(phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
+
+	if (ret)
+		count = ret;
+
+	return count;
+}
+static CLASS_ATTR(probe, 0700, NULL, memory_probe_store);
+
+static int memory_probe_init(void)
+{
+	sysfs_create_file(&memory_sysdev_class.kset.kobj,
+		&class_attr_probe.attr);
+	return 0;
+}
+#else
+#define memory_probe_init(...)	do {} while (0)
+#endif
+
+/*
+ * Note that phys_device is optional.  It is here to allow for
+ * differentiation between which *physical* devices each
+ * section belongs to...
+ */
+
+static int add_memory_block(unsigned long node_id, struct mem_section *section,
+		     unsigned long state, int phys_device)
+{
+	struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	int ret = 0;
+
+	if (!mem)
+		return -ENOMEM;
+
+	mem->phys_index = __section_nr(section);
+	mem->state = state;
+	init_MUTEX(&mem->state_sem);
+	mem->phys_device = phys_device;
+
+	ret = register_memory(mem, section, NULL);
+	if (!ret)
+		ret = mem_create_simple_file(mem, phys_index);
+	if (!ret)
+		ret = mem_create_simple_file(mem, state);
+	if (!ret)
+		ret = mem_create_simple_file(mem, phys_device);
+
+	return ret;
+}
+
+/*
+ * For now, we have a linear search to go find the appropriate
+ * memory_block corresponding to a particular phys_index. If
+ * this gets to be a real problem, we can always use a radix
+ * tree or something here.
+ *
+ * This could be made generic for all sysdev classes.
+ */
+static struct memory_block *find_memory_block(struct mem_section *section)
+{
+	struct kobject *kobj;
+	struct sys_device *sysdev;
+	struct memory_block *mem;
+	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+
+	/*
+	 * This only works because we know that section == sysdev->id
+	 * slightly redundant with sysdev_register()
+	 */
+	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+
+	kobj = kset_find_obj(&memory_sysdev_class.kset, name);
+	if (!kobj)
+		return NULL;
+
+	sysdev = container_of(kobj, struct sys_device, kobj);
+	mem = container_of(sysdev, struct memory_block, sysdev);
+
+	return mem;
+}
+
+int remove_memory_block(unsigned long node_id, struct mem_section *section,
+		int phys_device)
+{
+	struct memory_block *mem;
+
+	mem = find_memory_block(section);
+	mem_remove_simple_file(mem, phys_index);
+	mem_remove_simple_file(mem, state);
+	mem_remove_simple_file(mem, phys_device);
+	unregister_memory(mem, section, NULL);
+
+	return 0;
+}
+
+/*
+ * need an interface for the VM to add new memory regions,
+ * but without onlining it.
+ */
+int register_new_memory(struct mem_section *section)
+{
+	return add_memory_block(0, section, MEM_OFFLINE, 0);
+}
+
+int unregister_memory_section(struct mem_section *section)
+{
+	if (!valid_section(section))
+		return -EINVAL;
+
+	return remove_memory_block(0, section, 0);
+}
+
+/*
+ * Initialize the sysfs support for memory devices...
+ */
+int __init memory_dev_init(void)
+{
+	unsigned int i;
+	int ret;
+
+	memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
+	ret = sysdev_class_register(&memory_sysdev_class);
+
+	/*
+	 * Create entries for memory sections that were found
+	 * during boot and have been initialized
+	 */
+	for (i = 0; i < NR_MEM_SECTIONS; i++) {
+		if (!valid_section_nr(i))
+			continue;
+		add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
+	}
+
+	memory_probe_init();
+	block_size_init();
+
+	return ret;
+}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 361e204..08d9cc9 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -16,6 +16,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/bootmem.h>
 #include <linux/err.h>
+#include <linux/slab.h>
+
+#include "base.h"
 
 struct device platform_bus = {
 	.bus_id		= "platform",
@@ -279,13 +282,9 @@
 {
 	int ret = 0;
 
-	if (dev->driver && dev->driver->suspend) {
-		ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
-		if (ret == 0)
-			ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
-		if (ret == 0)
-			ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
-	}
+	if (dev->driver && dev->driver->suspend)
+		ret = dev->driver->suspend(dev, state);
+
 	return ret;
 }
 
@@ -293,13 +292,9 @@
 {
 	int ret = 0;
 
-	if (dev->driver && dev->driver->resume) {
-		ret = dev->driver->resume(dev, RESUME_POWER_ON);
-		if (ret == 0)
-			ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
-		if (ret == 0)
-			ret = dev->driver->resume(dev, RESUME_ENABLE);
-	}
+	if (dev->driver && dev->driver->resume)
+		ret = dev->driver->resume(dev);
+
 	return ret;
 }
 
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 15e6a8f..0d2e101 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -30,23 +30,6 @@
 DECLARE_MUTEX(dpm_sem);
 DECLARE_MUTEX(dpm_list_sem);
 
-/*
- * PM Reference Counting.
- */
-
-static inline void device_pm_hold(struct device * dev)
-{
-	if (dev)
-		atomic_inc(&dev->power.pm_users);
-}
-
-static inline void device_pm_release(struct device * dev)
-{
-	if (dev)
-		atomic_dec(&dev->power.pm_users);
-}
-
-
 /**
  *	device_pm_set_parent - Specify power dependency.
  *	@dev:		Device who needs power.
@@ -62,10 +45,8 @@
 
 void device_pm_set_parent(struct device * dev, struct device * parent)
 {
-	struct device * old_parent = dev->power.pm_parent;
-	device_pm_release(old_parent);
-	dev->power.pm_parent = parent;
-	device_pm_hold(parent);
+	put_device(dev->power.pm_parent);
+	dev->power.pm_parent = get_device(parent);
 }
 EXPORT_SYMBOL_GPL(device_pm_set_parent);
 
@@ -75,7 +56,6 @@
 
 	pr_debug("PM: Adding info for %s:%s\n",
 		 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
-	atomic_set(&dev->power.pm_users, 0);
 	down(&dpm_list_sem);
 	list_add_tail(&dev->power.entry, &dpm_active);
 	device_pm_set_parent(dev, dev->parent);
@@ -91,7 +71,7 @@
 		 dev->bus ? dev->bus->name : "No Bus", dev->kobj.name);
 	down(&dpm_list_sem);
 	dpm_sysfs_remove(dev);
-	device_pm_release(dev->power.pm_parent);
+	put_device(dev->power.pm_parent);
 	list_del_init(&dev->power.entry);
 	up(&dpm_list_sem);
 }
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 2e700d7..fb3d35a 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -67,9 +67,6 @@
  * runtime.c
  */
 
-extern int dpm_runtime_suspend(struct device *, pm_message_t);
-extern void dpm_runtime_resume(struct device *);
-
 #else /* CONFIG_PM */
 
 
@@ -82,14 +79,4 @@
 
 }
 
-static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
-{
-	return 0;
-}
-
-static inline void dpm_runtime_resume(struct device * dev)
-{
-
-}
-
 #endif
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e8f0519..adbc314 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -36,6 +36,7 @@
 	runtime_resume(dev);
 	up(&dpm_sem);
 }
+EXPORT_SYMBOL(dpm_runtime_resume);
 
 
 /**
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 8d04fb4..89c5787 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -48,8 +48,81 @@
 static DEVICE_ATTR(state, 0644, state_show, state_store);
 
 
+/*
+ *	wakeup - Report/change current wakeup option for device
+ *
+ *	Some devices support "wakeup" events, which are hardware signals
+ *	used to activate devices from suspended or low power states.  Such
+ *	devices have one of three values for the sysfs power/wakeup file:
+ *
+ *	 + "enabled\n" to issue the events;
+ *	 + "disabled\n" not to do so; or
+ *	 + "\n" for temporary or permanent inability to issue wakeup.
+ *
+ *	(For example, unconfigured USB devices can't issue wakeups.)
+ *
+ *	Familiar examples of devices that can issue wakeup events include
+ *	keyboards and mice (both PS2 and USB styles), power buttons, modems,
+ *	"Wake-On-LAN" Ethernet links, GPIO lines, and more.  Some events
+ *	will wake the entire system from a suspend state; others may just
+ *	wake up the device (if the system as a whole is already active).
+ *	Some wakeup events use normal IRQ lines; other use special out
+ *	of band signaling.
+ *
+ *	It is the responsibility of device drivers to enable (or disable)
+ *	wakeup signaling as part of changing device power states, respecting
+ *	the policy choices provided through the driver model.
+ *
+ *	Devices may not be able to generate wakeup events from all power
+ *	states.  Also, the events may be ignored in some configurations;
+ *	for example, they might need help from other devices that aren't
+ *	active, or which may have wakeup disabled.  Some drivers rely on
+ *	wakeup events internally (unless they are disabled), keeping
+ *	their hardware in low power modes whenever they're unused.  This
+ *	saves runtime power, without requiring system-wide sleep states.
+ */
+
+static const char enabled[] = "enabled";
+static const char disabled[] = "disabled";
+
+static ssize_t
+wake_show(struct device * dev, struct device_attribute *attr, char * buf)
+{
+	return sprintf(buf, "%s\n", device_can_wakeup(dev)
+		? (device_may_wakeup(dev) ? enabled : disabled)
+		: "");
+}
+
+static ssize_t
+wake_store(struct device * dev, struct device_attribute *attr,
+	const char * buf, size_t n)
+{
+	char *cp;
+	int len = n;
+
+	if (!device_can_wakeup(dev))
+		return -EINVAL;
+
+	cp = memchr(buf, '\n', n);
+	if (cp)
+		len = cp - buf;
+	if (len == sizeof enabled - 1
+			&& strncmp(buf, enabled, sizeof enabled - 1) == 0)
+		device_set_wakeup_enable(dev, 1);
+	else if (len == sizeof disabled - 1
+			&& strncmp(buf, disabled, sizeof disabled - 1) == 0)
+		device_set_wakeup_enable(dev, 0);
+	else
+		return -EINVAL;
+	return n;
+}
+
+static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
+
+
 static struct attribute * power_attrs[] = {
 	&dev_attr_state.attr,
+	&dev_attr_wakeup.attr,
 	NULL,
 };
 static struct attribute_group pm_attr_group = {
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 3431eb6..66ed8f2 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pm.h>
+#include <asm/semaphore.h>
 
 extern struct subsystem devices_subsys;
 
diff --git a/drivers/block/Kconfig.iosched b/drivers/block/Kconfig.iosched
index 6070a48..5b90d2f 100644
--- a/drivers/block/Kconfig.iosched
+++ b/drivers/block/Kconfig.iosched
@@ -38,4 +38,32 @@
 	  among all processes in the system. It should provide a fair
 	  working environment, suitable for desktop systems.
 
+choice
+	prompt "Default I/O scheduler"
+	default DEFAULT_AS
+	help
+	  Select the I/O scheduler which will be used by default for all
+	  block devices.
+
+	config DEFAULT_AS
+		bool "Anticipatory" if IOSCHED_AS
+
+	config DEFAULT_DEADLINE
+		bool "Deadline" if IOSCHED_DEADLINE
+
+	config DEFAULT_CFQ
+		bool "CFQ" if IOSCHED_CFQ
+
+	config DEFAULT_NOOP
+		bool "No-op"
+
+endchoice
+
+config DEFAULT_IOSCHED
+	string
+	default "anticipatory" if DEFAULT_AS
+	default "deadline" if DEFAULT_DEADLINE
+	default "cfq" if DEFAULT_CFQ
+	default "noop" if DEFAULT_NOOP
+
 endmenu
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 0e9e586..881c48d 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "12"
+#define VERSION "14"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 45a2430..41ae0ed 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -224,7 +224,7 @@
 		return PTR_ERR(aoe_class);
 	}
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-		class_device_create(aoe_class,
+		class_device_create(aoe_class, NULL,
 					MKDEV(AOE_MAJOR, chardevs[i].minor),
 					NULL, chardevs[i].name);
 
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index b5be4b7..5c9c7c1 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -8,6 +8,7 @@
 #include <linux/blkdev.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <asm/unaligned.h>
 #include "aoe.h"
 
 #define TIMERTICK (HZ / 10)
@@ -311,16 +312,16 @@
 	u16 n;
 
 	/* word 83: command set supported */
-	n = le16_to_cpup((__le16 *) &id[83<<1]);
+	n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
 
 	/* word 86: command set/feature enabled */
-	n |= le16_to_cpup((__le16 *) &id[86<<1]);
+	n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
 
 	if (n & (1<<10)) {	/* bit 10: LBA 48 */
 		d->flags |= DEVFL_EXT;
 
 		/* word 100: number lba48 sectors */
-		ssize = le64_to_cpup((__le64 *) &id[100<<1]);
+		ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
 
 		/* set as in ide-disk.c:init_idedisk_capacity */
 		d->geo.cylinders = ssize;
@@ -331,12 +332,12 @@
 		d->flags &= ~DEVFL_EXT;
 
 		/* number lba28 sectors */
-		ssize = le32_to_cpup((__le32 *) &id[60<<1]);
+		ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
 
 		/* NOTE: obsolete in ATA 6 */
-		d->geo.cylinders = le16_to_cpup((__le16 *) &id[54<<1]);
-		d->geo.heads = le16_to_cpup((__le16 *) &id[55<<1]);
-		d->geo.sectors = le16_to_cpup((__le16 *) &id[56<<1]);
+		d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
+		d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
+		d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
 	}
 	d->ssize = ssize;
 	d->geo.start = 0;
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index 95c0a36..c6744ff 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -98,7 +98,6 @@
 
 	struct as_rq *next_arq[2];	/* next in sort order */
 	sector_t last_sector[2];	/* last REQ_SYNC & REQ_ASYNC sectors */
-	struct list_head *dispatch;	/* driver dispatch queue */
 	struct list_head *hash;		/* request hash */
 
 	unsigned long exit_prob;	/* probability a task will exit while
@@ -239,6 +238,25 @@
 	return ioc;
 }
 
+static void as_put_io_context(struct as_rq *arq)
+{
+	struct as_io_context *aic;
+
+	if (unlikely(!arq->io_context))
+		return;
+
+	aic = arq->io_context->aic;
+
+	if (arq->is_sync == REQ_SYNC && aic) {
+		spin_lock(&aic->lock);
+		set_bit(AS_TASK_IORUNNING, &aic->state);
+		aic->last_end_request = jiffies;
+		spin_unlock(&aic->lock);
+	}
+
+	put_io_context(arq->io_context);
+}
+
 /*
  * the back merge hash support functions
  */
@@ -261,14 +279,6 @@
 		__as_del_arq_hash(arq);
 }
 
-static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq)
-{
-	as_del_arq_hash(arq);
-
-	if (q->last_merge == arq->request)
-		q->last_merge = NULL;
-}
-
 static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
 {
 	struct request *rq = arq->request;
@@ -312,7 +322,7 @@
 		BUG_ON(!arq->on_hash);
 
 		if (!rq_mergeable(__rq)) {
-			as_remove_merge_hints(ad->q, arq);
+			as_del_arq_hash(arq);
 			continue;
 		}
 
@@ -950,23 +960,12 @@
 
 	WARN_ON(!list_empty(&rq->queuelist));
 
-	if (arq->state == AS_RQ_PRESCHED) {
-		WARN_ON(arq->io_context);
-		goto out;
-	}
-
-	if (arq->state == AS_RQ_MERGED)
-		goto out_ioc;
-
 	if (arq->state != AS_RQ_REMOVED) {
 		printk("arq->state %d\n", arq->state);
 		WARN_ON(1);
 		goto out;
 	}
 
-	if (!blk_fs_request(rq))
-		goto out;
-
 	if (ad->changed_batch && ad->nr_dispatched == 1) {
 		kblockd_schedule_work(&ad->antic_work);
 		ad->changed_batch = 0;
@@ -1001,21 +1000,7 @@
 		}
 	}
 
-out_ioc:
-	if (!arq->io_context)
-		goto out;
-
-	if (arq->is_sync == REQ_SYNC) {
-		struct as_io_context *aic = arq->io_context->aic;
-		if (aic) {
-			spin_lock(&aic->lock);
-			set_bit(AS_TASK_IORUNNING, &aic->state);
-			aic->last_end_request = jiffies;
-			spin_unlock(&aic->lock);
-		}
-	}
-
-	put_io_context(arq->io_context);
+	as_put_io_context(arq);
 out:
 	arq->state = AS_RQ_POSTSCHED;
 }
@@ -1047,73 +1032,11 @@
 		ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
 
 	list_del_init(&arq->fifo);
-	as_remove_merge_hints(q, arq);
+	as_del_arq_hash(arq);
 	as_del_arq_rb(ad, arq);
 }
 
 /*
- * as_remove_dispatched_request is called to remove a request which has gone
- * to the dispatch list.
- */
-static void as_remove_dispatched_request(request_queue_t *q, struct request *rq)
-{
-	struct as_rq *arq = RQ_DATA(rq);
-	struct as_io_context *aic;
-
-	if (!arq) {
-		WARN_ON(1);
-		return;
-	}
-
-	WARN_ON(arq->state != AS_RQ_DISPATCHED);
-	WARN_ON(ON_RB(&arq->rb_node));
-	if (arq->io_context && arq->io_context->aic) {
-		aic = arq->io_context->aic;
-		if (aic) {
-			WARN_ON(!atomic_read(&aic->nr_dispatched));
-			atomic_dec(&aic->nr_dispatched);
-		}
-	}
-}
-
-/*
- * as_remove_request is called when a driver has finished with a request.
- * This should be only called for dispatched requests, but for some reason
- * a POWER4 box running hwscan it does not.
- */
-static void as_remove_request(request_queue_t *q, struct request *rq)
-{
-	struct as_rq *arq = RQ_DATA(rq);
-
-	if (unlikely(arq->state == AS_RQ_NEW))
-		goto out;
-
-	if (ON_RB(&arq->rb_node)) {
-		if (arq->state != AS_RQ_QUEUED) {
-			printk("arq->state %d\n", arq->state);
-			WARN_ON(1);
-			goto out;
-		}
-		/*
-		 * We'll lose the aliased request(s) here. I don't think this
-		 * will ever happen, but if it does, hopefully someone will
-		 * report it.
-		 */
-		WARN_ON(!list_empty(&rq->queuelist));
-		as_remove_queued_request(q, rq);
-	} else {
-		if (arq->state != AS_RQ_DISPATCHED) {
-			printk("arq->state %d\n", arq->state);
-			WARN_ON(1);
-			goto out;
-		}
-		as_remove_dispatched_request(q, rq);
-	}
-out:
-	arq->state = AS_RQ_REMOVED;
-}
-
-/*
  * as_fifo_expired returns 0 if there are no expired reads on the fifo,
  * 1 otherwise.  It is ratelimited so that we only perform the check once per
  * `fifo_expire' interval.  Otherwise a large number of expired requests
@@ -1165,7 +1088,6 @@
 static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
 {
 	struct request *rq = arq->request;
-	struct list_head *insert;
 	const int data_dir = arq->is_sync;
 
 	BUG_ON(!ON_RB(&arq->rb_node));
@@ -1198,13 +1120,13 @@
 	/*
 	 * take it off the sort and fifo list, add to dispatch queue
 	 */
-	insert = ad->dispatch->prev;
-
 	while (!list_empty(&rq->queuelist)) {
 		struct request *__rq = list_entry_rq(rq->queuelist.next);
 		struct as_rq *__arq = RQ_DATA(__rq);
 
-		list_move_tail(&__rq->queuelist, ad->dispatch);
+		list_del(&__rq->queuelist);
+
+		elv_dispatch_add_tail(ad->q, __rq);
 
 		if (__arq->io_context && __arq->io_context->aic)
 			atomic_inc(&__arq->io_context->aic->nr_dispatched);
@@ -1218,7 +1140,8 @@
 	as_remove_queued_request(ad->q, rq);
 	WARN_ON(arq->state != AS_RQ_QUEUED);
 
-	list_add(&rq->queuelist, insert);
+	elv_dispatch_sort(ad->q, rq);
+
 	arq->state = AS_RQ_DISPATCHED;
 	if (arq->io_context && arq->io_context->aic)
 		atomic_inc(&arq->io_context->aic->nr_dispatched);
@@ -1230,12 +1153,42 @@
  * read/write expire, batch expire, etc, and moves it to the dispatch
  * queue. Returns 1 if a request was found, 0 otherwise.
  */
-static int as_dispatch_request(struct as_data *ad)
+static int as_dispatch_request(request_queue_t *q, int force)
 {
+	struct as_data *ad = q->elevator->elevator_data;
 	struct as_rq *arq;
 	const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
 	const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
 
+	if (unlikely(force)) {
+		/*
+		 * Forced dispatch, accounting is useless.  Reset
+		 * accounting states and dump fifo_lists.  Note that
+		 * batch_data_dir is reset to REQ_SYNC to avoid
+		 * screwing write batch accounting as write batch
+		 * accounting occurs on W->R transition.
+		 */
+		int dispatched = 0;
+
+		ad->batch_data_dir = REQ_SYNC;
+		ad->changed_batch = 0;
+		ad->new_batch = 0;
+
+		while (ad->next_arq[REQ_SYNC]) {
+			as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+			dispatched++;
+		}
+		ad->last_check_fifo[REQ_SYNC] = jiffies;
+
+		while (ad->next_arq[REQ_ASYNC]) {
+			as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+			dispatched++;
+		}
+		ad->last_check_fifo[REQ_ASYNC] = jiffies;
+
+		return dispatched;
+	}
+
 	/* Signal that the write batch was uncontended, so we can't time it */
 	if (ad->batch_data_dir == REQ_ASYNC && !reads) {
 		if (ad->current_write_count == 0 || !writes)
@@ -1359,20 +1312,6 @@
 	return 1;
 }
 
-static struct request *as_next_request(request_queue_t *q)
-{
-	struct as_data *ad = q->elevator->elevator_data;
-	struct request *rq = NULL;
-
-	/*
-	 * if there are still requests on the dispatch queue, grab the first
-	 */
-	if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
-		rq = list_entry_rq(ad->dispatch->next);
-
-	return rq;
-}
-
 /*
  * Add arq to a list behind alias
  */
@@ -1404,17 +1343,26 @@
 	/*
 	 * Don't want to have to handle merges.
 	 */
-	as_remove_merge_hints(ad->q, arq);
+	as_del_arq_hash(arq);
+	arq->request->flags |= REQ_NOMERGE;
 }
 
 /*
  * add arq to rbtree and fifo
  */
-static void as_add_request(struct as_data *ad, struct as_rq *arq)
+static void as_add_request(request_queue_t *q, struct request *rq)
 {
+	struct as_data *ad = q->elevator->elevator_data;
+	struct as_rq *arq = RQ_DATA(rq);
 	struct as_rq *alias;
 	int data_dir;
 
+	if (arq->state != AS_RQ_PRESCHED) {
+		printk("arq->state: %d\n", arq->state);
+		WARN_ON(1);
+	}
+	arq->state = AS_RQ_NEW;
+
 	if (rq_data_dir(arq->request) == READ
 			|| current->flags&PF_SYNCWRITE)
 		arq->is_sync = 1;
@@ -1437,12 +1385,8 @@
 		arq->expires = jiffies + ad->fifo_expire[data_dir];
 		list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
 
-		if (rq_mergeable(arq->request)) {
+		if (rq_mergeable(arq->request))
 			as_add_arq_hash(ad, arq);
-
-			if (!ad->q->last_merge)
-				ad->q->last_merge = arq->request;
-		}
 		as_update_arq(ad, arq); /* keep state machine up to date */
 
 	} else {
@@ -1463,96 +1407,24 @@
 	arq->state = AS_RQ_QUEUED;
 }
 
+static void as_activate_request(request_queue_t *q, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+
+	WARN_ON(arq->state != AS_RQ_DISPATCHED);
+	arq->state = AS_RQ_REMOVED;
+	if (arq->io_context && arq->io_context->aic)
+		atomic_dec(&arq->io_context->aic->nr_dispatched);
+}
+
 static void as_deactivate_request(request_queue_t *q, struct request *rq)
 {
-	struct as_data *ad = q->elevator->elevator_data;
 	struct as_rq *arq = RQ_DATA(rq);
 
-	if (arq) {
-		if (arq->state == AS_RQ_REMOVED) {
-			arq->state = AS_RQ_DISPATCHED;
-			if (arq->io_context && arq->io_context->aic)
-				atomic_inc(&arq->io_context->aic->nr_dispatched);
-		}
-	} else
-		WARN_ON(blk_fs_request(rq)
-			&& (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
-
-	/* Stop anticipating - let this request get through */
-	as_antic_stop(ad);
-}
-
-/*
- * requeue the request. The request has not been completed, nor is it a
- * new request, so don't touch accounting.
- */
-static void as_requeue_request(request_queue_t *q, struct request *rq)
-{
-	as_deactivate_request(q, rq);
-	list_add(&rq->queuelist, &q->queue_head);
-}
-
-/*
- * Account a request that is inserted directly onto the dispatch queue.
- * arq->io_context->aic->nr_dispatched should not need to be incremented
- * because only new requests should come through here: requeues go through
- * our explicit requeue handler.
- */
-static void as_account_queued_request(struct as_data *ad, struct request *rq)
-{
-	if (blk_fs_request(rq)) {
-		struct as_rq *arq = RQ_DATA(rq);
-		arq->state = AS_RQ_DISPATCHED;
-		ad->nr_dispatched++;
-	}
-}
-
-static void
-as_insert_request(request_queue_t *q, struct request *rq, int where)
-{
-	struct as_data *ad = q->elevator->elevator_data;
-	struct as_rq *arq = RQ_DATA(rq);
-
-	if (arq) {
-		if (arq->state != AS_RQ_PRESCHED) {
-			printk("arq->state: %d\n", arq->state);
-			WARN_ON(1);
-		}
-		arq->state = AS_RQ_NEW;
-	}
-
-	/* barriers must flush the reorder queue */
-	if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
-			&& where == ELEVATOR_INSERT_SORT)) {
-		WARN_ON(1);
-		where = ELEVATOR_INSERT_BACK;
-	}
-
-	switch (where) {
-		case ELEVATOR_INSERT_BACK:
-			while (ad->next_arq[REQ_SYNC])
-				as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
-
-			while (ad->next_arq[REQ_ASYNC])
-				as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
-
-			list_add_tail(&rq->queuelist, ad->dispatch);
-			as_account_queued_request(ad, rq);
-			as_antic_stop(ad);
-			break;
-		case ELEVATOR_INSERT_FRONT:
-			list_add(&rq->queuelist, ad->dispatch);
-			as_account_queued_request(ad, rq);
-			as_antic_stop(ad);
-			break;
-		case ELEVATOR_INSERT_SORT:
-			BUG_ON(!blk_fs_request(rq));
-			as_add_request(ad, arq);
-			break;
-		default:
-			BUG();
-			return;
-	}
+	WARN_ON(arq->state != AS_RQ_REMOVED);
+	arq->state = AS_RQ_DISPATCHED;
+	if (arq->io_context && arq->io_context->aic)
+		atomic_inc(&arq->io_context->aic->nr_dispatched);
 }
 
 /*
@@ -1565,12 +1437,8 @@
 {
 	struct as_data *ad = q->elevator->elevator_data;
 
-	if (!list_empty(&ad->fifo_list[REQ_ASYNC])
-		|| !list_empty(&ad->fifo_list[REQ_SYNC])
-		|| !list_empty(ad->dispatch))
-			return 0;
-
-	return 1;
+	return list_empty(&ad->fifo_list[REQ_ASYNC])
+		&& list_empty(&ad->fifo_list[REQ_SYNC]);
 }
 
 static struct request *
@@ -1608,15 +1476,6 @@
 	int ret;
 
 	/*
-	 * try last_merge to avoid going to hash
-	 */
-	ret = elv_try_last_merge(q, bio);
-	if (ret != ELEVATOR_NO_MERGE) {
-		__rq = q->last_merge;
-		goto out_insert;
-	}
-
-	/*
 	 * see if the merge hash can satisfy a back merge
 	 */
 	__rq = as_find_arq_hash(ad, bio->bi_sector);
@@ -1644,9 +1503,6 @@
 
 	return ELEVATOR_NO_MERGE;
 out:
-	if (rq_mergeable(__rq))
-		q->last_merge = __rq;
-out_insert:
 	if (ret) {
 		if (rq_mergeable(__rq))
 			as_hot_arq_hash(ad, RQ_DATA(__rq));
@@ -1693,9 +1549,6 @@
 		 * behind the disk head. We currently don't bother adjusting.
 		 */
 	}
-
-	if (arq->on_hash)
-		q->last_merge = req;
 }
 
 static void
@@ -1763,6 +1616,7 @@
 	 * kill knowledge of next, this one is a goner
 	 */
 	as_remove_queued_request(q, next);
+	as_put_io_context(anext);
 
 	anext->state = AS_RQ_MERGED;
 }
@@ -1782,7 +1636,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	if (as_next_request(q))
+	if (!as_queue_empty(q))
 		q->request_fn(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
@@ -1797,7 +1651,9 @@
 		return;
 	}
 
-	if (arq->state != AS_RQ_POSTSCHED && arq->state != AS_RQ_PRESCHED) {
+	if (unlikely(arq->state != AS_RQ_POSTSCHED &&
+		     arq->state != AS_RQ_PRESCHED &&
+		     arq->state != AS_RQ_MERGED)) {
 		printk("arq->state %d\n", arq->state);
 		WARN_ON(1);
 	}
@@ -1807,7 +1663,7 @@
 }
 
 static int as_set_request(request_queue_t *q, struct request *rq,
-			  struct bio *bio, int gfp_mask)
+			  struct bio *bio, gfp_t gfp_mask)
 {
 	struct as_data *ad = q->elevator->elevator_data;
 	struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
@@ -1907,7 +1763,6 @@
 	INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
 	ad->sort_list[REQ_SYNC] = RB_ROOT;
 	ad->sort_list[REQ_ASYNC] = RB_ROOT;
-	ad->dispatch = &q->queue_head;
 	ad->fifo_expire[REQ_SYNC] = default_read_expire;
 	ad->fifo_expire[REQ_ASYNC] = default_write_expire;
 	ad->antic_expire = default_antic_expire;
@@ -2072,10 +1927,9 @@
 		.elevator_merge_fn = 		as_merge,
 		.elevator_merged_fn =		as_merged_request,
 		.elevator_merge_req_fn =	as_merged_requests,
-		.elevator_next_req_fn =		as_next_request,
-		.elevator_add_req_fn =		as_insert_request,
-		.elevator_remove_req_fn =	as_remove_request,
-		.elevator_requeue_req_fn = 	as_requeue_request,
+		.elevator_dispatch_fn =		as_dispatch_request,
+		.elevator_add_req_fn =		as_add_request,
+		.elevator_activate_req_fn =	as_activate_request,
 		.elevator_deactivate_req_fn = 	as_deactivate_request,
 		.elevator_queue_empty_fn =	as_queue_empty,
 		.elevator_completed_req_fn =	as_completed_request,
@@ -2119,8 +1973,8 @@
 
 static void __exit as_exit(void)
 {
-	kmem_cache_destroy(arq_pool);
 	elv_unregister(&iosched_as);
+	kmem_cache_destroy(arq_pool);
 }
 
 module_init(as_init);
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e183a3e..ec27976 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -28,13 +28,17 @@
    through the array controller.  Note in particular, neither 
    physical nor logical disks are presented through the scsi layer. */
 
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/atomic.h>
+
 #include <scsi/scsi.h> 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h> 
-#include <asm/atomic.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
 
 #include "cciss_scsi.h"
 
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index cd056e7..5281f8e 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -84,7 +84,6 @@
 	(node)->rb_left = NULL;		\
 } while (0)
 #define RB_CLEAR_ROOT(root)	((root)->rb_node = NULL)
-#define ON_RB(node)		((node)->rb_color != RB_NONE)
 #define rb_entry_crq(node)	rb_entry((node), struct cfq_rq, rb_node)
 #define rq_rb_key(rq)		(rq)->sector
 
@@ -271,10 +270,7 @@
 #undef CFQ_CFQQ_FNS
 
 enum cfq_rq_state_flags {
-	CFQ_CRQ_FLAG_in_flight = 0,
-	CFQ_CRQ_FLAG_in_driver,
-	CFQ_CRQ_FLAG_is_sync,
-	CFQ_CRQ_FLAG_requeued,
+	CFQ_CRQ_FLAG_is_sync = 0,
 };
 
 #define CFQ_CRQ_FNS(name)						\
@@ -291,14 +287,11 @@
 	return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0;	\
 }
 
-CFQ_CRQ_FNS(in_flight);
-CFQ_CRQ_FNS(in_driver);
 CFQ_CRQ_FNS(is_sync);
-CFQ_CRQ_FNS(requeued);
 #undef CFQ_CRQ_FNS
 
 static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
-static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
+static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
 static void cfq_put_cfqd(struct cfq_data *cfqd);
 
 #define process_sync(tsk)	((tsk)->flags & PF_SYNCWRITE)
@@ -311,14 +304,6 @@
 	hlist_del_init(&crq->hash);
 }
 
-static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
-{
-	cfq_del_crq_hash(crq);
-
-	if (q->last_merge == crq->request)
-		q->last_merge = NULL;
-}
-
 static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
 {
 	const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
@@ -347,18 +332,13 @@
 	return NULL;
 }
 
-static inline int cfq_pending_requests(struct cfq_data *cfqd)
-{
-	return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues;
-}
-
 /*
  * scheduler run of queue, if there are requests pending and no one in the
  * driver that will restart queueing
  */
 static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
 {
-	if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd))
+	if (!cfqd->rq_in_driver && cfqd->busy_queues)
 		kblockd_schedule_work(&cfqd->unplug_work);
 }
 
@@ -366,7 +346,7 @@
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 
-	return !cfq_pending_requests(cfqd);
+	return !cfqd->busy_queues;
 }
 
 /*
@@ -386,11 +366,6 @@
 	if (crq2 == NULL)
 		return crq1;
 
-	if (cfq_crq_requeued(crq1) && !cfq_crq_requeued(crq2))
-		return crq1;
-	else if (cfq_crq_requeued(crq2) && !cfq_crq_requeued(crq1))
-		return crq2;
-
 	if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
 		return crq1;
 	else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
@@ -461,10 +436,7 @@
 	struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
 	struct rb_node *rbnext, *rbprev;
 
-	rbnext = NULL;
-	if (ON_RB(&last->rb_node))
-		rbnext = rb_next(&last->rb_node);
-	if (!rbnext) {
+	if (!(rbnext = rb_next(&last->rb_node))) {
 		rbnext = rb_first(&cfqq->sort_list);
 		if (rbnext == &last->rb_node)
 			rbnext = NULL;
@@ -545,13 +517,13 @@
  * the pending list according to last request service
  */
 static inline void
-cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue)
+cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
 	BUG_ON(cfq_cfqq_on_rr(cfqq));
 	cfq_mark_cfqq_on_rr(cfqq);
 	cfqd->busy_queues++;
 
-	cfq_resort_rr_list(cfqq, requeue);
+	cfq_resort_rr_list(cfqq, 0);
 }
 
 static inline void
@@ -571,22 +543,19 @@
 static inline void cfq_del_crq_rb(struct cfq_rq *crq)
 {
 	struct cfq_queue *cfqq = crq->cfq_queue;
+	struct cfq_data *cfqd = cfqq->cfqd;
+	const int sync = cfq_crq_is_sync(crq);
 
-	if (ON_RB(&crq->rb_node)) {
-		struct cfq_data *cfqd = cfqq->cfqd;
-		const int sync = cfq_crq_is_sync(crq);
+	BUG_ON(!cfqq->queued[sync]);
+	cfqq->queued[sync]--;
 
-		BUG_ON(!cfqq->queued[sync]);
-		cfqq->queued[sync]--;
+	cfq_update_next_crq(crq);
 
-		cfq_update_next_crq(crq);
+	rb_erase(&crq->rb_node, &cfqq->sort_list);
+	RB_CLEAR_COLOR(&crq->rb_node);
 
-		rb_erase(&crq->rb_node, &cfqq->sort_list);
-		RB_CLEAR_COLOR(&crq->rb_node);
-
-		if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
-			cfq_del_cfqq_rr(cfqd, cfqq);
-	}
+	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
+		cfq_del_cfqq_rr(cfqd, cfqq);
 }
 
 static struct cfq_rq *
@@ -627,12 +596,12 @@
 	 * if that happens, put the alias on the dispatch list
 	 */
 	while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
-		cfq_dispatch_sort(cfqd->queue, __alias);
+		cfq_dispatch_insert(cfqd->queue, __alias);
 
 	rb_insert_color(&crq->rb_node, &cfqq->sort_list);
 
 	if (!cfq_cfqq_on_rr(cfqq))
-		cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq));
+		cfq_add_cfqq_rr(cfqd, cfqq);
 
 	/*
 	 * check if this request is a better next-serve candidate
@@ -643,10 +612,8 @@
 static inline void
 cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
 {
-	if (ON_RB(&crq->rb_node)) {
-		rb_erase(&crq->rb_node, &cfqq->sort_list);
-		cfqq->queued[cfq_crq_is_sync(crq)]--;
-	}
+	rb_erase(&crq->rb_node, &cfqq->sort_list);
+	cfqq->queued[cfq_crq_is_sync(crq)]--;
 
 	cfq_add_crq_rb(crq);
 }
@@ -676,49 +643,28 @@
 	return NULL;
 }
 
+static void cfq_activate_request(request_queue_t *q, struct request *rq)
+{
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+
+	cfqd->rq_in_driver++;
+}
+
 static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
-	struct cfq_rq *crq = RQ_DATA(rq);
 
-	if (crq) {
-		struct cfq_queue *cfqq = crq->cfq_queue;
-
-		if (cfq_crq_in_driver(crq)) {
-			cfq_clear_crq_in_driver(crq);
-			WARN_ON(!cfqd->rq_in_driver);
-			cfqd->rq_in_driver--;
-		}
-		if (cfq_crq_in_flight(crq)) {
-			const int sync = cfq_crq_is_sync(crq);
-
-			cfq_clear_crq_in_flight(crq);
-			WARN_ON(!cfqq->on_dispatch[sync]);
-			cfqq->on_dispatch[sync]--;
-		}
-		cfq_mark_crq_requeued(crq);
-	}
+	WARN_ON(!cfqd->rq_in_driver);
+	cfqd->rq_in_driver--;
 }
 
-/*
- * make sure the service time gets corrected on reissue of this request
- */
-static void cfq_requeue_request(request_queue_t *q, struct request *rq)
-{
-	cfq_deactivate_request(q, rq);
-	list_add(&rq->queuelist, &q->queue_head);
-}
-
-static void cfq_remove_request(request_queue_t *q, struct request *rq)
+static void cfq_remove_request(struct request *rq)
 {
 	struct cfq_rq *crq = RQ_DATA(rq);
 
-	if (crq) {
-		list_del_init(&rq->queuelist);
-		cfq_del_crq_rb(crq);
-		cfq_remove_merge_hints(q, crq);
-
-	}
+	list_del_init(&rq->queuelist);
+	cfq_del_crq_rb(crq);
+	cfq_del_crq_hash(crq);
 }
 
 static int
@@ -728,12 +674,6 @@
 	struct request *__rq;
 	int ret;
 
-	ret = elv_try_last_merge(q, bio);
-	if (ret != ELEVATOR_NO_MERGE) {
-		__rq = q->last_merge;
-		goto out_insert;
-	}
-
 	__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
 	if (__rq && elv_rq_merge_ok(__rq, bio)) {
 		ret = ELEVATOR_BACK_MERGE;
@@ -748,8 +688,6 @@
 
 	return ELEVATOR_NO_MERGE;
 out:
-	q->last_merge = __rq;
-out_insert:
 	*req = __rq;
 	return ret;
 }
@@ -762,14 +700,12 @@
 	cfq_del_crq_hash(crq);
 	cfq_add_crq_hash(cfqd, crq);
 
-	if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) {
+	if (rq_rb_key(req) != crq->rb_key) {
 		struct cfq_queue *cfqq = crq->cfq_queue;
 
 		cfq_update_next_crq(crq);
 		cfq_reposition_crq_rb(cfqq, crq);
 	}
-
-	q->last_merge = req;
 }
 
 static void
@@ -785,7 +721,7 @@
 	    time_before(next->start_time, rq->start_time))
 		list_move(&rq->queuelist, &next->queuelist);
 
-	cfq_remove_request(q, next);
+	cfq_remove_request(next);
 }
 
 static inline void
@@ -992,53 +928,15 @@
 	return 1;
 }
 
-/*
- * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues,
- * this function sector sorts the selected request to minimize seeks. we start
- * at cfqd->last_sector, not 0.
- */
-static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq)
+static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_queue *cfqq = crq->cfq_queue;
-	struct list_head *head = &q->queue_head, *entry = head;
-	struct request *__rq;
-	sector_t last;
-
-	list_del(&crq->request->queuelist);
-
-	last = cfqd->last_sector;
-	list_for_each_entry_reverse(__rq, head, queuelist) {
-		struct cfq_rq *__crq = RQ_DATA(__rq);
-
-		if (blk_barrier_rq(__rq))
-			break;
-		if (!blk_fs_request(__rq))
-			break;
-		if (cfq_crq_requeued(__crq))
-			break;
-
-		if (__rq->sector <= crq->request->sector)
-			break;
-		if (__rq->sector > last && crq->request->sector < last) {
-			last = crq->request->sector + crq->request->nr_sectors;
-			break;
-		}
-		entry = &__rq->queuelist;
-	}
-
-	cfqd->last_sector = last;
 
 	cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
-
-	cfq_del_crq_rb(crq);
-	cfq_remove_merge_hints(q, crq);
-
-	cfq_mark_crq_in_flight(crq);
-	cfq_clear_crq_requeued(crq);
-
+	cfq_remove_request(crq->request);
 	cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
-	list_add_tail(&crq->request->queuelist, entry);
+	elv_dispatch_sort(q, crq->request);
 }
 
 /*
@@ -1159,7 +1057,7 @@
 		/*
 		 * finally, insert request into driver dispatch list
 		 */
-		cfq_dispatch_sort(cfqd->queue, crq);
+		cfq_dispatch_insert(cfqd->queue, crq);
 
 		cfqd->dispatch_slice++;
 		dispatched++;
@@ -1194,7 +1092,7 @@
 }
 
 static int
-cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
+cfq_dispatch_requests(request_queue_t *q, int force)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_queue *cfqq;
@@ -1204,12 +1102,25 @@
 
 	cfqq = cfq_select_queue(cfqd, force);
 	if (cfqq) {
+		int max_dispatch;
+
+		/*
+		 * if idle window is disabled, allow queue buildup
+		 */
+		if (!cfq_cfqq_idle_window(cfqq) &&
+		    cfqd->rq_in_driver >= cfqd->cfq_max_depth)
+			return 0;
+
 		cfq_clear_cfqq_must_dispatch(cfqq);
 		cfq_clear_cfqq_wait_request(cfqq);
 		del_timer(&cfqd->idle_slice_timer);
 
-		if (cfq_class_idle(cfqq))
-			max_dispatch = 1;
+		if (!force) {
+			max_dispatch = cfqd->cfq_quantum;
+			if (cfq_class_idle(cfqq))
+				max_dispatch = 1;
+		} else
+			max_dispatch = INT_MAX;
 
 		return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
 	}
@@ -1217,93 +1128,6 @@
 	return 0;
 }
 
-static inline void cfq_account_dispatch(struct cfq_rq *crq)
-{
-	struct cfq_queue *cfqq = crq->cfq_queue;
-	struct cfq_data *cfqd = cfqq->cfqd;
-
-	if (unlikely(!blk_fs_request(crq->request)))
-		return;
-
-	/*
-	 * accounted bit is necessary since some drivers will call
-	 * elv_next_request() many times for the same request (eg ide)
-	 */
-	if (cfq_crq_in_driver(crq))
-		return;
-
-	cfq_mark_crq_in_driver(crq);
-	cfqd->rq_in_driver++;
-}
-
-static inline void
-cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
-{
-	struct cfq_data *cfqd = cfqq->cfqd;
-	unsigned long now;
-
-	if (!cfq_crq_in_driver(crq))
-		return;
-
-	now = jiffies;
-
-	WARN_ON(!cfqd->rq_in_driver);
-	cfqd->rq_in_driver--;
-
-	if (!cfq_class_idle(cfqq))
-		cfqd->last_end_request = now;
-
-	if (!cfq_cfqq_dispatched(cfqq)) {
-		if (cfq_cfqq_on_rr(cfqq)) {
-			cfqq->service_last = now;
-			cfq_resort_rr_list(cfqq, 0);
-		}
-		if (cfq_cfqq_expired(cfqq)) {
-			__cfq_slice_expired(cfqd, cfqq, 0);
-			cfq_schedule_dispatch(cfqd);
-		}
-	}
-
-	if (cfq_crq_is_sync(crq))
-		crq->io_context->last_end_request = now;
-}
-
-static struct request *cfq_next_request(request_queue_t *q)
-{
-	struct cfq_data *cfqd = q->elevator->elevator_data;
-	struct request *rq;
-
-	if (!list_empty(&q->queue_head)) {
-		struct cfq_rq *crq;
-dispatch:
-		rq = list_entry_rq(q->queue_head.next);
-
-		crq = RQ_DATA(rq);
-		if (crq) {
-			struct cfq_queue *cfqq = crq->cfq_queue;
-
-			/*
-			 * if idle window is disabled, allow queue buildup
-			 */
-			if (!cfq_crq_in_driver(crq) &&
-			    !cfq_cfqq_idle_window(cfqq) &&
-			    !blk_barrier_rq(rq) &&
-			    cfqd->rq_in_driver >= cfqd->cfq_max_depth)
-				return NULL;
-
-			cfq_remove_merge_hints(q, crq);
-			cfq_account_dispatch(crq);
-		}
-
-		return rq;
-	}
-
-	if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0))
-		goto dispatch;
-
-	return NULL;
-}
-
 /*
  * task holds one reference to the queue, dropped when task exits. each crq
  * in-flight on this queue also holds a reference, dropped when crq is freed.
@@ -1422,7 +1246,7 @@
 }
 
 static struct cfq_io_context *
-cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
+cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
 {
 	struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
 
@@ -1517,7 +1341,7 @@
 
 static struct cfq_queue *
 cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
-	      int gfp_mask)
+	      gfp_t gfp_mask)
 {
 	const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
 	struct cfq_queue *cfqq, *new_cfqq = NULL;
@@ -1578,7 +1402,7 @@
  * cfqq, so we don't need to worry about it disappearing
  */
 static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
 {
 	struct io_context *ioc = NULL;
 	struct cfq_io_context *cic;
@@ -1816,8 +1640,9 @@
 	}
 }
 
-static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
+static void cfq_insert_request(request_queue_t *q, struct request *rq)
 {
+	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_rq *crq = RQ_DATA(rq);
 	struct cfq_queue *cfqq = crq->cfq_queue;
 
@@ -1827,66 +1652,43 @@
 
 	list_add_tail(&rq->queuelist, &cfqq->fifo);
 
-	if (rq_mergeable(rq)) {
+	if (rq_mergeable(rq))
 		cfq_add_crq_hash(cfqd, crq);
 
-		if (!cfqd->queue->last_merge)
-			cfqd->queue->last_merge = rq;
-	}
-
 	cfq_crq_enqueued(cfqd, cfqq, crq);
 }
 
-static void
-cfq_insert_request(request_queue_t *q, struct request *rq, int where)
-{
-	struct cfq_data *cfqd = q->elevator->elevator_data;
-
-	switch (where) {
-		case ELEVATOR_INSERT_BACK:
-			while (cfq_dispatch_requests(q, INT_MAX, 1))
-				;
-			list_add_tail(&rq->queuelist, &q->queue_head);
-			/*
-			 * If we were idling with pending requests on
-			 * inactive cfqqs, force dispatching will
-			 * remove the idle timer and the queue won't
-			 * be kicked by __make_request() afterward.
-			 * Kick it here.
-			 */
-			cfq_schedule_dispatch(cfqd);
-			break;
-		case ELEVATOR_INSERT_FRONT:
-			list_add(&rq->queuelist, &q->queue_head);
-			break;
-		case ELEVATOR_INSERT_SORT:
-			BUG_ON(!blk_fs_request(rq));
-			cfq_enqueue(cfqd, rq);
-			break;
-		default:
-			printk("%s: bad insert point %d\n", __FUNCTION__,where);
-			return;
-	}
-}
-
 static void cfq_completed_request(request_queue_t *q, struct request *rq)
 {
 	struct cfq_rq *crq = RQ_DATA(rq);
-	struct cfq_queue *cfqq;
+	struct cfq_queue *cfqq = crq->cfq_queue;
+	struct cfq_data *cfqd = cfqq->cfqd;
+	const int sync = cfq_crq_is_sync(crq);
+	unsigned long now;
 
-	if (unlikely(!blk_fs_request(rq)))
-		return;
+	now = jiffies;
 
-	cfqq = crq->cfq_queue;
+	WARN_ON(!cfqd->rq_in_driver);
+	WARN_ON(!cfqq->on_dispatch[sync]);
+	cfqd->rq_in_driver--;
+	cfqq->on_dispatch[sync]--;
 
-	if (cfq_crq_in_flight(crq)) {
-		const int sync = cfq_crq_is_sync(crq);
+	if (!cfq_class_idle(cfqq))
+		cfqd->last_end_request = now;
 
-		WARN_ON(!cfqq->on_dispatch[sync]);
-		cfqq->on_dispatch[sync]--;
+	if (!cfq_cfqq_dispatched(cfqq)) {
+		if (cfq_cfqq_on_rr(cfqq)) {
+			cfqq->service_last = now;
+			cfq_resort_rr_list(cfqq, 0);
+		}
+		if (cfq_cfqq_expired(cfqq)) {
+			__cfq_slice_expired(cfqd, cfqq, 0);
+			cfq_schedule_dispatch(cfqd);
+		}
 	}
 
-	cfq_account_completion(cfqq, crq);
+	if (cfq_crq_is_sync(crq))
+		crq->io_context->last_end_request = now;
 }
 
 static struct request *
@@ -2075,7 +1877,7 @@
  */
 static int
 cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-		int gfp_mask)
+		gfp_t gfp_mask)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct task_struct *tsk = current;
@@ -2118,9 +1920,6 @@
 		INIT_HLIST_NODE(&crq->hash);
 		crq->cfq_queue = cfqq;
 		crq->io_context = cic;
-		cfq_clear_crq_in_flight(crq);
-		cfq_clear_crq_in_driver(crq);
-		cfq_clear_crq_requeued(crq);
 
 		if (rw == READ || process_sync(tsk))
 			cfq_mark_crq_is_sync(crq);
@@ -2201,7 +2000,7 @@
 		 * only expire and reinvoke request handler, if there are
 		 * other queues with pending requests
 		 */
-		if (!cfq_pending_requests(cfqd)) {
+		if (!cfqd->busy_queues) {
 			cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
 			add_timer(&cfqd->idle_slice_timer);
 			goto out_cont;
@@ -2576,10 +2375,9 @@
 		.elevator_merge_fn = 		cfq_merge,
 		.elevator_merged_fn =		cfq_merged_request,
 		.elevator_merge_req_fn =	cfq_merged_requests,
-		.elevator_next_req_fn =		cfq_next_request,
+		.elevator_dispatch_fn =		cfq_dispatch_requests,
 		.elevator_add_req_fn =		cfq_insert_request,
-		.elevator_remove_req_fn =	cfq_remove_request,
-		.elevator_requeue_req_fn =	cfq_requeue_request,
+		.elevator_activate_req_fn =	cfq_activate_request,
 		.elevator_deactivate_req_fn =	cfq_deactivate_request,
 		.elevator_queue_empty_fn =	cfq_queue_empty,
 		.elevator_completed_req_fn =	cfq_completed_request,
@@ -2620,28 +2418,8 @@
 
 static void __exit cfq_exit(void)
 {
-	struct task_struct *g, *p;
-	unsigned long flags;
-
-	read_lock_irqsave(&tasklist_lock, flags);
-
-	/*
-	 * iterate each process in the system, removing our io_context
-	 */
-	do_each_thread(g, p) {
-		struct io_context *ioc = p->io_context;
-
-		if (ioc && ioc->cic) {
-			ioc->cic->exit(ioc->cic);
-			cfq_free_io_context(ioc->cic);
-			ioc->cic = NULL;
-		}
-	} while_each_thread(g, p);
-
-	read_unlock_irqrestore(&tasklist_lock, flags);
-
-	cfq_slab_kill();
 	elv_unregister(&iosched_cfq);
+	cfq_slab_kill();
 }
 
 module_init(cfq_init);
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index 52a3ae5..7929471 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -50,7 +50,6 @@
 	 * next in sort order. read, write or both are NULL
 	 */
 	struct deadline_rq *next_drq[2];
-	struct list_head *dispatch;	/* driver dispatch queue */
 	struct list_head *hash;		/* request hash */
 	unsigned int batching;		/* number of sequential requests made */
 	sector_t last_sector;		/* head position */
@@ -113,15 +112,6 @@
 		__deadline_del_drq_hash(drq);
 }
 
-static void
-deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq)
-{
-	deadline_del_drq_hash(drq);
-
-	if (q->last_merge == drq->request)
-		q->last_merge = NULL;
-}
-
 static inline void
 deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
 {
@@ -239,10 +229,9 @@
 			dd->next_drq[data_dir] = rb_entry_drq(rbnext);
 	}
 
-	if (ON_RB(&drq->rb_node)) {
-		rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
-		RB_CLEAR(&drq->rb_node);
-	}
+	BUG_ON(!ON_RB(&drq->rb_node));
+	rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
+	RB_CLEAR(&drq->rb_node);
 }
 
 static struct request *
@@ -286,7 +275,7 @@
 /*
  * add drq to rbtree and fifo
  */
-static inline void
+static void
 deadline_add_request(struct request_queue *q, struct request *rq)
 {
 	struct deadline_data *dd = q->elevator->elevator_data;
@@ -301,12 +290,8 @@
 	drq->expires = jiffies + dd->fifo_expire[data_dir];
 	list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
 
-	if (rq_mergeable(rq)) {
+	if (rq_mergeable(rq))
 		deadline_add_drq_hash(dd, drq);
-
-		if (!q->last_merge)
-			q->last_merge = rq;
-	}
 }
 
 /*
@@ -315,14 +300,11 @@
 static void deadline_remove_request(request_queue_t *q, struct request *rq)
 {
 	struct deadline_rq *drq = RQ_DATA(rq);
+	struct deadline_data *dd = q->elevator->elevator_data;
 
-	if (drq) {
-		struct deadline_data *dd = q->elevator->elevator_data;
-
-		list_del_init(&drq->fifo);
-		deadline_remove_merge_hints(q, drq);
-		deadline_del_drq_rb(dd, drq);
-	}
+	list_del_init(&drq->fifo);
+	deadline_del_drq_rb(dd, drq);
+	deadline_del_drq_hash(drq);
 }
 
 static int
@@ -333,15 +315,6 @@
 	int ret;
 
 	/*
-	 * try last_merge to avoid going to hash
-	 */
-	ret = elv_try_last_merge(q, bio);
-	if (ret != ELEVATOR_NO_MERGE) {
-		__rq = q->last_merge;
-		goto out_insert;
-	}
-
-	/*
 	 * see if the merge hash can satisfy a back merge
 	 */
 	__rq = deadline_find_drq_hash(dd, bio->bi_sector);
@@ -373,8 +346,6 @@
 
 	return ELEVATOR_NO_MERGE;
 out:
-	q->last_merge = __rq;
-out_insert:
 	if (ret)
 		deadline_hot_drq_hash(dd, RQ_DATA(__rq));
 	*req = __rq;
@@ -399,8 +370,6 @@
 		deadline_del_drq_rb(dd, drq);
 		deadline_add_drq_rb(dd, drq);
 	}
-
-	q->last_merge = req;
 }
 
 static void
@@ -452,7 +421,7 @@
 	request_queue_t *q = drq->request->q;
 
 	deadline_remove_request(q, drq->request);
-	list_add_tail(&drq->request->queuelist, dd->dispatch);
+	elv_dispatch_add_tail(q, drq->request);
 }
 
 /*
@@ -502,8 +471,9 @@
  * deadline_dispatch_requests selects the best request according to
  * read/write expire, fifo_batch, etc
  */
-static int deadline_dispatch_requests(struct deadline_data *dd)
+static int deadline_dispatch_requests(request_queue_t *q, int force)
 {
+	struct deadline_data *dd = q->elevator->elevator_data;
 	const int reads = !list_empty(&dd->fifo_list[READ]);
 	const int writes = !list_empty(&dd->fifo_list[WRITE]);
 	struct deadline_rq *drq;
@@ -597,65 +567,12 @@
 	return 1;
 }
 
-static struct request *deadline_next_request(request_queue_t *q)
-{
-	struct deadline_data *dd = q->elevator->elevator_data;
-	struct request *rq;
-
-	/*
-	 * if there are still requests on the dispatch queue, grab the first one
-	 */
-	if (!list_empty(dd->dispatch)) {
-dispatch:
-		rq = list_entry_rq(dd->dispatch->next);
-		return rq;
-	}
-
-	if (deadline_dispatch_requests(dd))
-		goto dispatch;
-
-	return NULL;
-}
-
-static void
-deadline_insert_request(request_queue_t *q, struct request *rq, int where)
-{
-	struct deadline_data *dd = q->elevator->elevator_data;
-
-	/* barriers must flush the reorder queue */
-	if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)
-			&& where == ELEVATOR_INSERT_SORT))
-		where = ELEVATOR_INSERT_BACK;
-
-	switch (where) {
-		case ELEVATOR_INSERT_BACK:
-			while (deadline_dispatch_requests(dd))
-				;
-			list_add_tail(&rq->queuelist, dd->dispatch);
-			break;
-		case ELEVATOR_INSERT_FRONT:
-			list_add(&rq->queuelist, dd->dispatch);
-			break;
-		case ELEVATOR_INSERT_SORT:
-			BUG_ON(!blk_fs_request(rq));
-			deadline_add_request(q, rq);
-			break;
-		default:
-			printk("%s: bad insert point %d\n", __FUNCTION__,where);
-			return;
-	}
-}
-
 static int deadline_queue_empty(request_queue_t *q)
 {
 	struct deadline_data *dd = q->elevator->elevator_data;
 
-	if (!list_empty(&dd->fifo_list[WRITE])
-	    || !list_empty(&dd->fifo_list[READ])
-	    || !list_empty(dd->dispatch))
-		return 0;
-
-	return 1;
+	return list_empty(&dd->fifo_list[WRITE])
+		&& list_empty(&dd->fifo_list[READ]);
 }
 
 static struct request *
@@ -733,7 +650,6 @@
 	INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
 	dd->sort_list[READ] = RB_ROOT;
 	dd->sort_list[WRITE] = RB_ROOT;
-	dd->dispatch = &q->queue_head;
 	dd->fifo_expire[READ] = read_expire;
 	dd->fifo_expire[WRITE] = write_expire;
 	dd->writes_starved = writes_starved;
@@ -748,15 +664,13 @@
 	struct deadline_data *dd = q->elevator->elevator_data;
 	struct deadline_rq *drq = RQ_DATA(rq);
 
-	if (drq) {
-		mempool_free(drq, dd->drq_pool);
-		rq->elevator_private = NULL;
-	}
+	mempool_free(drq, dd->drq_pool);
+	rq->elevator_private = NULL;
 }
 
 static int
 deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-		     int gfp_mask)
+		     gfp_t gfp_mask)
 {
 	struct deadline_data *dd = q->elevator->elevator_data;
 	struct deadline_rq *drq;
@@ -917,9 +831,8 @@
 		.elevator_merge_fn = 		deadline_merge,
 		.elevator_merged_fn =		deadline_merged_request,
 		.elevator_merge_req_fn =	deadline_merged_requests,
-		.elevator_next_req_fn =		deadline_next_request,
-		.elevator_add_req_fn =		deadline_insert_request,
-		.elevator_remove_req_fn =	deadline_remove_request,
+		.elevator_dispatch_fn =		deadline_dispatch_requests,
+		.elevator_add_req_fn =		deadline_add_request,
 		.elevator_queue_empty_fn =	deadline_queue_empty,
 		.elevator_former_req_fn =	deadline_former_request,
 		.elevator_latter_req_fn =	deadline_latter_request,
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 98f0126..36f1057 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/compiler.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 
@@ -83,21 +84,11 @@
 }
 EXPORT_SYMBOL(elv_try_merge);
 
-inline int elv_try_last_merge(request_queue_t *q, struct bio *bio)
-{
-	if (q->last_merge)
-		return elv_try_merge(q->last_merge, bio);
-
-	return ELEVATOR_NO_MERGE;
-}
-EXPORT_SYMBOL(elv_try_last_merge);
-
 static struct elevator_type *elevator_find(const char *name)
 {
 	struct elevator_type *e = NULL;
 	struct list_head *entry;
 
-	spin_lock_irq(&elv_list_lock);
 	list_for_each(entry, &elv_list) {
 		struct elevator_type *__e;
 
@@ -108,7 +99,6 @@
 			break;
 		}
 	}
-	spin_unlock_irq(&elv_list_lock);
 
 	return e;
 }
@@ -120,12 +110,15 @@
 
 static struct elevator_type *elevator_get(const char *name)
 {
-	struct elevator_type *e = elevator_find(name);
+	struct elevator_type *e;
 
-	if (!e)
-		return NULL;
-	if (!try_module_get(e->elevator_owner))
-		return NULL;
+	spin_lock_irq(&elv_list_lock);
+
+	e = elevator_find(name);
+	if (e && !try_module_get(e->elevator_owner))
+		e = NULL;
+
+	spin_unlock_irq(&elv_list_lock);
 
 	return e;
 }
@@ -139,8 +132,6 @@
 	eq->ops = &e->ops;
 	eq->elevator_type = e;
 
-	INIT_LIST_HEAD(&q->queue_head);
-	q->last_merge = NULL;
 	q->elevator = eq;
 
 	if (eq->ops->elevator_init_fn)
@@ -153,23 +144,20 @@
 
 static void elevator_setup_default(void)
 {
-	/*
-	 * check if default is set and exists
-	 */
-	if (chosen_elevator[0] && elevator_find(chosen_elevator))
-		return;
+	struct elevator_type *e;
 
-#if defined(CONFIG_IOSCHED_AS)
-	strcpy(chosen_elevator, "anticipatory");
-#elif defined(CONFIG_IOSCHED_DEADLINE)
-	strcpy(chosen_elevator, "deadline");
-#elif defined(CONFIG_IOSCHED_CFQ)
-	strcpy(chosen_elevator, "cfq");
-#elif defined(CONFIG_IOSCHED_NOOP)
-	strcpy(chosen_elevator, "noop");
-#else
-#error "You must build at least 1 IO scheduler into the kernel"
-#endif
+	/*
+	 * If default has not been set, use the compiled-in selection.
+	 */
+	if (!chosen_elevator[0])
+		strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
+
+ 	/*
+ 	 * If the given scheduler is not available, fall back to no-op.
+ 	 */
+ 	if (!(e = elevator_find(chosen_elevator)))
+ 		strcpy(chosen_elevator, "noop");
+	elevator_put(e);
 }
 
 static int __init elevator_setup(char *str)
@@ -186,6 +174,11 @@
 	struct elevator_queue *eq;
 	int ret = 0;
 
+	INIT_LIST_HEAD(&q->queue_head);
+	q->last_merge = NULL;
+	q->end_sector = 0;
+	q->boundary_rq = NULL;
+
 	elevator_setup_default();
 
 	if (!name)
@@ -220,9 +213,52 @@
 	kfree(e);
 }
 
+/*
+ * Insert rq into dispatch queue of q.  Queue lock must be held on
+ * entry.  If sort != 0, rq is sort-inserted; otherwise, rq will be
+ * appended to the dispatch queue.  To be used by specific elevators.
+ */
+void elv_dispatch_sort(request_queue_t *q, struct request *rq)
+{
+	sector_t boundary;
+	struct list_head *entry;
+
+	if (q->last_merge == rq)
+		q->last_merge = NULL;
+
+	boundary = q->end_sector;
+
+	list_for_each_prev(entry, &q->queue_head) {
+		struct request *pos = list_entry_rq(entry);
+
+		if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
+			break;
+		if (rq->sector >= boundary) {
+			if (pos->sector < boundary)
+				continue;
+		} else {
+			if (pos->sector >= boundary)
+				break;
+		}
+		if (rq->sector >= pos->sector)
+			break;
+	}
+
+	list_add(&rq->queuelist, entry);
+}
+
 int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
 {
 	elevator_t *e = q->elevator;
+	int ret;
+
+	if (q->last_merge) {
+		ret = elv_try_merge(q->last_merge, bio);
+		if (ret != ELEVATOR_NO_MERGE) {
+			*req = q->last_merge;
+			return ret;
+		}
+	}
 
 	if (e->ops->elevator_merge_fn)
 		return e->ops->elevator_merge_fn(q, req, bio);
@@ -236,6 +272,8 @@
 
 	if (e->ops->elevator_merged_fn)
 		e->ops->elevator_merged_fn(q, rq);
+
+	q->last_merge = rq;
 }
 
 void elv_merge_requests(request_queue_t *q, struct request *rq,
@@ -243,20 +281,13 @@
 {
 	elevator_t *e = q->elevator;
 
-	if (q->last_merge == next)
-		q->last_merge = NULL;
-
 	if (e->ops->elevator_merge_req_fn)
 		e->ops->elevator_merge_req_fn(q, rq, next);
+
+	q->last_merge = rq;
 }
 
-/*
- * For careful internal use by the block layer. Essentially the same as
- * a requeue in that it tells the io scheduler that this request is not
- * active in the driver or hardware anymore, but we don't want the request
- * added back to the scheduler. Function is not exported.
- */
-void elv_deactivate_request(request_queue_t *q, struct request *rq)
+void elv_requeue_request(request_queue_t *q, struct request *rq)
 {
 	elevator_t *e = q->elevator;
 
@@ -264,19 +295,14 @@
 	 * it already went through dequeue, we need to decrement the
 	 * in_flight count again
 	 */
-	if (blk_account_rq(rq))
+	if (blk_account_rq(rq)) {
 		q->in_flight--;
+		if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn)
+			e->ops->elevator_deactivate_req_fn(q, rq);
+	}
 
 	rq->flags &= ~REQ_STARTED;
 
-	if (e->ops->elevator_deactivate_req_fn)
-		e->ops->elevator_deactivate_req_fn(q, rq);
-}
-
-void elv_requeue_request(request_queue_t *q, struct request *rq)
-{
-	elv_deactivate_request(q, rq);
-
 	/*
 	 * if this is the flush, requeue the original instead and drop the flush
 	 */
@@ -285,31 +311,27 @@
 		rq = rq->end_io_data;
 	}
 
-	/*
-	 * the request is prepped and may have some resources allocated.
-	 * allowing unprepped requests to pass this one may cause resource
-	 * deadlock.  turn on softbarrier.
-	 */
-	rq->flags |= REQ_SOFTBARRIER;
-
-	/*
-	 * if iosched has an explicit requeue hook, then use that. otherwise
-	 * just put the request at the front of the queue
-	 */
-	if (q->elevator->ops->elevator_requeue_req_fn)
-		q->elevator->ops->elevator_requeue_req_fn(q, rq);
-	else
-		__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+	__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
 }
 
 void __elv_add_request(request_queue_t *q, struct request *rq, int where,
 		       int plug)
 {
-	/*
-	 * barriers implicitly indicate back insertion
-	 */
-	if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) &&
-	    where == ELEVATOR_INSERT_SORT)
+	if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
+		/*
+		 * barriers implicitly indicate back insertion
+		 */
+		if (where == ELEVATOR_INSERT_SORT)
+			where = ELEVATOR_INSERT_BACK;
+
+		/*
+		 * this request is scheduling boundary, update end_sector
+		 */
+		if (blk_fs_request(rq)) {
+			q->end_sector = rq_end_sector(rq);
+			q->boundary_rq = rq;
+		}
+	} else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
 		where = ELEVATOR_INSERT_BACK;
 
 	if (plug)
@@ -317,23 +339,54 @@
 
 	rq->q = q;
 
-	if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
-		q->elevator->ops->elevator_add_req_fn(q, rq, where);
+	switch (where) {
+	case ELEVATOR_INSERT_FRONT:
+		rq->flags |= REQ_SOFTBARRIER;
 
-		if (blk_queue_plugged(q)) {
-			int nrq = q->rq.count[READ] + q->rq.count[WRITE]
-				  - q->in_flight;
+		list_add(&rq->queuelist, &q->queue_head);
+		break;
 
-			if (nrq >= q->unplug_thresh)
-				__generic_unplug_device(q);
-		}
-	} else
+	case ELEVATOR_INSERT_BACK:
+		rq->flags |= REQ_SOFTBARRIER;
+
+		while (q->elevator->ops->elevator_dispatch_fn(q, 1))
+			;
+		list_add_tail(&rq->queuelist, &q->queue_head);
 		/*
-		 * if drain is set, store the request "locally". when the drain
-		 * is finished, the requests will be handed ordered to the io
-		 * scheduler
+		 * We kick the queue here for the following reasons.
+		 * - The elevator might have returned NULL previously
+		 *   to delay requests and returned them now.  As the
+		 *   queue wasn't empty before this request, ll_rw_blk
+		 *   won't run the queue on return, resulting in hang.
+		 * - Usually, back inserted requests won't be merged
+		 *   with anything.  There's no point in delaying queue
+		 *   processing.
 		 */
-		list_add_tail(&rq->queuelist, &q->drain_list);
+		blk_remove_plug(q);
+		q->request_fn(q);
+		break;
+
+	case ELEVATOR_INSERT_SORT:
+		BUG_ON(!blk_fs_request(rq));
+		rq->flags |= REQ_SORTED;
+		q->elevator->ops->elevator_add_req_fn(q, rq);
+		if (q->last_merge == NULL && rq_mergeable(rq))
+			q->last_merge = rq;
+		break;
+
+	default:
+		printk(KERN_ERR "%s: bad insertion point %d\n",
+		       __FUNCTION__, where);
+		BUG();
+	}
+
+	if (blk_queue_plugged(q)) {
+		int nrq = q->rq.count[READ] + q->rq.count[WRITE]
+			- q->in_flight;
+
+		if (nrq >= q->unplug_thresh)
+			__generic_unplug_device(q);
+	}
 }
 
 void elv_add_request(request_queue_t *q, struct request *rq, int where,
@@ -348,13 +401,19 @@
 
 static inline struct request *__elv_next_request(request_queue_t *q)
 {
-	struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
+	struct request *rq;
+
+	if (unlikely(list_empty(&q->queue_head) &&
+		     !q->elevator->ops->elevator_dispatch_fn(q, 0)))
+		return NULL;
+
+	rq = list_entry_rq(q->queue_head.next);
 
 	/*
 	 * if this is a barrier write and the device has to issue a
 	 * flush sequence to support it, check how far we are
 	 */
-	if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
+	if (blk_fs_request(rq) && blk_barrier_rq(rq)) {
 		BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
 
 		if (q->ordered == QUEUE_ORDERED_FLUSH &&
@@ -371,15 +430,30 @@
 	int ret;
 
 	while ((rq = __elv_next_request(q)) != NULL) {
-		/*
-		 * just mark as started even if we don't start it, a request
-		 * that has been delayed should not be passed by new incoming
-		 * requests
-		 */
-		rq->flags |= REQ_STARTED;
+		if (!(rq->flags & REQ_STARTED)) {
+			elevator_t *e = q->elevator;
 
-		if (rq == q->last_merge)
-			q->last_merge = NULL;
+			/*
+			 * This is the first time the device driver
+			 * sees this request (possibly after
+			 * requeueing).  Notify IO scheduler.
+			 */
+			if (blk_sorted_rq(rq) &&
+			    e->ops->elevator_activate_req_fn)
+				e->ops->elevator_activate_req_fn(q, rq);
+
+			/*
+			 * just mark as started even if we don't start
+			 * it, a request that has been delayed should
+			 * not be passed by new incoming requests
+			 */
+			rq->flags |= REQ_STARTED;
+		}
+
+		if (!q->boundary_rq || q->boundary_rq == rq) {
+			q->end_sector = rq_end_sector(rq);
+			q->boundary_rq = NULL;
+		}
 
 		if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
 			break;
@@ -391,9 +465,9 @@
 			/*
 			 * the request may have been (partially) prepped.
 			 * we need to keep this request in the front to
-			 * avoid resource deadlock.  turn on softbarrier.
+			 * avoid resource deadlock.  REQ_STARTED will
+			 * prevent other fs requests from passing this one.
 			 */
-			rq->flags |= REQ_SOFTBARRIER;
 			rq = NULL;
 			break;
 		} else if (ret == BLKPREP_KILL) {
@@ -416,42 +490,32 @@
 	return rq;
 }
 
-void elv_remove_request(request_queue_t *q, struct request *rq)
+void elv_dequeue_request(request_queue_t *q, struct request *rq)
 {
-	elevator_t *e = q->elevator;
+	BUG_ON(list_empty(&rq->queuelist));
+
+	list_del_init(&rq->queuelist);
 
 	/*
 	 * the time frame between a request being removed from the lists
 	 * and to it is freed is accounted as io that is in progress at
-	 * the driver side. note that we only account requests that the
-	 * driver has seen (REQ_STARTED set), to avoid false accounting
-	 * for request-request merges
+	 * the driver side.
 	 */
 	if (blk_account_rq(rq))
 		q->in_flight++;
-
-	/*
-	 * the main clearing point for q->last_merge is on retrieval of
-	 * request by driver (it calls elv_next_request()), but it _can_
-	 * also happen here if a request is added to the queue but later
-	 * deleted without ever being given to driver (merged with another
-	 * request).
-	 */
-	if (rq == q->last_merge)
-		q->last_merge = NULL;
-
-	if (e->ops->elevator_remove_req_fn)
-		e->ops->elevator_remove_req_fn(q, rq);
 }
 
 int elv_queue_empty(request_queue_t *q)
 {
 	elevator_t *e = q->elevator;
 
+	if (!list_empty(&q->queue_head))
+		return 0;
+
 	if (e->ops->elevator_queue_empty_fn)
 		return e->ops->elevator_queue_empty_fn(q);
 
-	return list_empty(&q->queue_head);
+	return 1;
 }
 
 struct request *elv_latter_request(request_queue_t *q, struct request *rq)
@@ -487,7 +551,7 @@
 }
 
 int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
-		    int gfp_mask)
+		    gfp_t gfp_mask)
 {
 	elevator_t *e = q->elevator;
 
@@ -523,11 +587,11 @@
 	/*
 	 * request is released from the driver, io must be done
 	 */
-	if (blk_account_rq(rq))
+	if (blk_account_rq(rq)) {
 		q->in_flight--;
-
-	if (e->ops->elevator_completed_req_fn)
-		e->ops->elevator_completed_req_fn(q, rq);
+		if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
+			e->ops->elevator_completed_req_fn(q, rq);
+	}
 }
 
 int elv_register_queue(struct request_queue *q)
@@ -555,10 +619,9 @@
 
 int elv_register(struct elevator_type *e)
 {
+	spin_lock_irq(&elv_list_lock);
 	if (elevator_find(e->elevator_name))
 		BUG();
-
-	spin_lock_irq(&elv_list_lock);
 	list_add_tail(&e->list, &elv_list);
 	spin_unlock_irq(&elv_list_lock);
 
@@ -572,6 +635,27 @@
 
 void elv_unregister(struct elevator_type *e)
 {
+	struct task_struct *g, *p;
+
+	/*
+	 * Iterate every thread in the process to remove the io contexts.
+	 */
+	read_lock(&tasklist_lock);
+	do_each_thread(g, p) {
+		struct io_context *ioc = p->io_context;
+		if (ioc && ioc->cic) {
+			ioc->cic->exit(ioc->cic);
+			ioc->cic->dtor(ioc->cic);
+			ioc->cic = NULL;
+		}
+		if (ioc && ioc->aic) {
+			ioc->aic->exit(ioc->aic);
+			ioc->aic->dtor(ioc->aic);
+			ioc->aic = NULL;
+		}
+	} while_each_thread(g, p);
+	read_unlock(&tasklist_lock);
+
 	spin_lock_irq(&elv_list_lock);
 	list_del_init(&e->list);
 	spin_unlock_irq(&elv_list_lock);
@@ -582,25 +666,36 @@
  * switch to new_e io scheduler. be careful not to introduce deadlocks -
  * we don't free the old io scheduler, before we have allocated what we
  * need for the new one. this way we have a chance of going back to the old
- * one, if the new one fails init for some reason. we also do an intermediate
- * switch to noop to ensure safety with stack-allocated requests, since they
- * don't originate from the block layer allocator. noop is safe here, because
- * it never needs to touch the elevator itself for completion events. DRAIN
- * flags will make sure we don't touch it for additions either.
+ * one, if the new one fails init for some reason.
  */
 static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
 {
-	elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
-	struct elevator_type *noop_elevator = NULL;
-	elevator_t *old_elevator;
+	elevator_t *old_elevator, *e;
 
+	/*
+	 * Allocate new elevator
+	 */
+	e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
 	if (!e)
 		goto error;
 
 	/*
-	 * first step, drain requests from the block freelist
+	 * Turn on BYPASS and drain all requests w/ elevator private data
 	 */
-	blk_wait_queue_drained(q, 0);
+	spin_lock_irq(q->queue_lock);
+
+	set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+
+	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
+		;
+
+	while (q->rq.elvpriv) {
+		spin_unlock_irq(q->queue_lock);
+		msleep(10);
+		spin_lock_irq(q->queue_lock);
+	}
+
+	spin_unlock_irq(q->queue_lock);
 
 	/*
 	 * unregister old elevator data
@@ -609,18 +704,6 @@
 	old_elevator = q->elevator;
 
 	/*
- 	 * next step, switch to noop since it uses no private rq structures
-	 * and doesn't allocate any memory for anything. then wait for any
-	 * non-fs requests in-flight
- 	 */
-	noop_elevator = elevator_get("noop");
-	spin_lock_irq(q->queue_lock);
-	elevator_attach(q, noop_elevator, e);
-	spin_unlock_irq(q->queue_lock);
-
-	blk_wait_queue_drained(q, 1);
-
-	/*
 	 * attach and start new elevator
 	 */
 	if (elevator_attach(q, new_e, e))
@@ -630,11 +713,10 @@
 		goto fail_register;
 
 	/*
-	 * finally exit old elevator and start queue again
+	 * finally exit old elevator and turn off BYPASS.
 	 */
 	elevator_exit(old_elevator);
-	blk_finish_queue_drain(q);
-	elevator_put(noop_elevator);
+	clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
 	return;
 
 fail_register:
@@ -643,13 +725,13 @@
 	 * one again (along with re-adding the sysfs dir)
 	 */
 	elevator_exit(e);
+	e = NULL;
 fail:
 	q->elevator = old_elevator;
 	elv_register_queue(q);
-	blk_finish_queue_drain(q);
+	clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+	kfree(e);
 error:
-	if (noop_elevator)
-		elevator_put(noop_elevator);
 	elevator_put(new_e);
 	printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
 }
@@ -671,8 +753,10 @@
 		return -EINVAL;
 	}
 
-	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name))
+	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) {
+		elevator_put(e);
 		return count;
+	}
 
 	elevator_switch(q, e);
 	return count;
@@ -701,11 +785,12 @@
 	return len;
 }
 
+EXPORT_SYMBOL(elv_dispatch_sort);
 EXPORT_SYMBOL(elv_add_request);
 EXPORT_SYMBOL(__elv_add_request);
 EXPORT_SYMBOL(elv_requeue_request);
 EXPORT_SYMBOL(elv_next_request);
-EXPORT_SYMBOL(elv_remove_request);
+EXPORT_SYMBOL(elv_dequeue_request);
 EXPORT_SYMBOL(elv_queue_empty);
 EXPORT_SYMBOL(elv_completed_request);
 EXPORT_SYMBOL(elevator_exit);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index d42840c..486ce1f 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -337,10 +337,30 @@
 	return ret;
 }
 
+static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr,
+			       const char *page, size_t count)
+{
+	struct gendisk *disk = to_disk(kobj);
+	struct disk_attribute *disk_attr =
+		container_of(attr,struct disk_attribute,attr);
+	ssize_t ret = 0;
+
+	if (disk_attr->store)
+		ret = disk_attr->store(disk, page, count);
+	return ret;
+}
+
 static struct sysfs_ops disk_sysfs_ops = {
 	.show	= &disk_attr_show,
+	.store	= &disk_attr_store,
 };
 
+static ssize_t disk_uevent_store(struct gendisk * disk,
+				 const char *buf, size_t count)
+{
+	kobject_hotplug(&disk->kobj, KOBJ_ADD);
+	return count;
+}
 static ssize_t disk_dev_read(struct gendisk * disk, char *page)
 {
 	dev_t base = MKDEV(disk->major, disk->first_minor); 
@@ -382,6 +402,10 @@
 		jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
 		jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
 }
+static struct disk_attribute disk_attr_uevent = {
+	.attr = {.name = "uevent", .mode = S_IWUSR },
+	.store	= disk_uevent_store
+};
 static struct disk_attribute disk_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
 	.show	= disk_dev_read
@@ -404,6 +428,7 @@
 };
 
 static struct attribute * default_attrs[] = {
+	&disk_attr_uevent.attr,
 	&disk_attr_dev.attr,
 	&disk_attr_range.attr,
 	&disk_attr_removable.attr,
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index baedac5..0af7351 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -263,8 +263,6 @@
 	blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
 
 	blk_queue_activity_fn(q, NULL, NULL);
-
-	INIT_LIST_HEAD(&q->drain_list);
 }
 
 EXPORT_SYMBOL(blk_queue_make_request);
@@ -353,6 +351,8 @@
 	struct request *rq = flush_rq->end_io_data;
 	request_queue_t *q = rq->q;
 
+	elv_completed_request(q, flush_rq);
+
 	rq->flags |= REQ_BAR_PREFLUSH;
 
 	if (!flush_rq->errors)
@@ -369,6 +369,8 @@
 	struct request *rq = flush_rq->end_io_data;
 	request_queue_t *q = rq->q;
 
+	elv_completed_request(q, flush_rq);
+
 	rq->flags |= REQ_BAR_POSTFLUSH;
 
 	q->end_flush_fn(q, flush_rq);
@@ -408,8 +410,6 @@
 	if (!list_empty(&rq->queuelist))
 		blkdev_dequeue_request(rq);
 
-	elv_deactivate_request(q, rq);
-
 	flush_rq->end_io_data = rq;
 	flush_rq->end_io = blk_pre_flush_end_io;
 
@@ -1040,6 +1040,7 @@
 static char *rq_flags[] = {
 	"REQ_RW",
 	"REQ_FAILFAST",
+	"REQ_SORTED",
 	"REQ_SOFTBARRIER",
 	"REQ_HARDBARRIER",
 	"REQ_CMD",
@@ -1047,6 +1048,7 @@
 	"REQ_STARTED",
 	"REQ_DONTPREP",
 	"REQ_QUEUED",
+	"REQ_ELVPRIV",
 	"REQ_PC",
 	"REQ_BLOCK_PC",
 	"REQ_SENSE",
@@ -1637,9 +1639,9 @@
 
 	rl->count[READ] = rl->count[WRITE] = 0;
 	rl->starved[READ] = rl->starved[WRITE] = 0;
+	rl->elvpriv = 0;
 	init_waitqueue_head(&rl->wait[READ]);
 	init_waitqueue_head(&rl->wait[WRITE]);
-	init_waitqueue_head(&rl->drain);
 
 	rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
 				mempool_free_slab, request_cachep, q->node);
@@ -1652,13 +1654,13 @@
 
 static int __make_request(request_queue_t *, struct bio *);
 
-request_queue_t *blk_alloc_queue(int gfp_mask)
+request_queue_t *blk_alloc_queue(gfp_t gfp_mask)
 {
 	return blk_alloc_queue_node(gfp_mask, -1);
 }
 EXPORT_SYMBOL(blk_alloc_queue);
 
-request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
+request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 {
 	request_queue_t *q;
 
@@ -1782,12 +1784,14 @@
 
 static inline void blk_free_request(request_queue_t *q, struct request *rq)
 {
-	elv_put_request(q, rq);
+	if (rq->flags & REQ_ELVPRIV)
+		elv_put_request(q, rq);
 	mempool_free(rq, q->rq.rq_pool);
 }
 
 static inline struct request *
-blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
+blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
+		  int priv, gfp_t gfp_mask)
 {
 	struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -1800,11 +1804,15 @@
 	 */
 	rq->flags = rw;
 
-	if (!elv_set_request(q, rq, bio, gfp_mask))
-		return rq;
+	if (priv) {
+		if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) {
+			mempool_free(rq, q->rq.rq_pool);
+			return NULL;
+		}
+		rq->flags |= REQ_ELVPRIV;
+	}
 
-	mempool_free(rq, q->rq.rq_pool);
-	return NULL;
+	return rq;
 }
 
 /*
@@ -1860,22 +1868,18 @@
  * A request has just been released.  Account for it, update the full and
  * congestion status, wake up any waiters.   Called under q->queue_lock.
  */
-static void freed_request(request_queue_t *q, int rw)
+static void freed_request(request_queue_t *q, int rw, int priv)
 {
 	struct request_list *rl = &q->rq;
 
 	rl->count[rw]--;
+	if (priv)
+		rl->elvpriv--;
 
 	__freed_request(q, rw);
 
 	if (unlikely(rl->starved[rw ^ 1]))
 		__freed_request(q, rw ^ 1);
-
-	if (!rl->count[READ] && !rl->count[WRITE]) {
-		smp_mb();
-		if (unlikely(waitqueue_active(&rl->drain)))
-			wake_up(&rl->drain);
-	}
 }
 
 #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
@@ -1885,14 +1889,12 @@
  * Returns !NULL on success, with queue_lock *not held*.
  */
 static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
-				   int gfp_mask)
+				   gfp_t gfp_mask)
 {
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
 	struct io_context *ioc = current_io_context(GFP_ATOMIC);
-
-	if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
-		goto out;
+	int priv;
 
 	if (rl->count[rw]+1 >= q->nr_requests) {
 		/*
@@ -1937,9 +1939,14 @@
 	rl->starved[rw] = 0;
 	if (rl->count[rw] >= queue_congestion_on_threshold(q))
 		set_queue_congested(q, rw);
+
+	priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+	if (priv)
+		rl->elvpriv++;
+
 	spin_unlock_irq(q->queue_lock);
 
-	rq = blk_alloc_request(q, rw, bio, gfp_mask);
+	rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
 	if (!rq) {
 		/*
 		 * Allocation failed presumably due to memory. Undo anything
@@ -1949,7 +1956,7 @@
 		 * wait queue, but this is pretty rare.
 		 */
 		spin_lock_irq(q->queue_lock);
-		freed_request(q, rw);
+		freed_request(q, rw, priv);
 
 		/*
 		 * in the very unlikely event that allocation failed and no
@@ -2019,7 +2026,7 @@
 	return rq;
 }
 
-struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
+struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
 {
 	struct request *rq;
 
@@ -2251,7 +2258,7 @@
  * @gfp_mask:	memory allocation flags
  */
 int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
-		    unsigned int len, unsigned int gfp_mask)
+		    unsigned int len, gfp_t gfp_mask)
 {
 	struct bio *bio;
 
@@ -2433,13 +2440,15 @@
 {
 	unsigned long now = jiffies;
 
-	__disk_stat_add(disk, time_in_queue,
-			disk->in_flight * (now - disk->stamp));
-	disk->stamp = now;
+	if (now == disk->stamp)
+		return;
 
-	if (disk->in_flight)
-		__disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
-	disk->stamp_idle = now;
+	if (disk->in_flight) {
+		__disk_stat_add(disk, time_in_queue,
+				disk->in_flight * (now - disk->stamp));
+		__disk_stat_add(disk, io_ticks, (now - disk->stamp));
+	}
+	disk->stamp = now;
 }
 
 /*
@@ -2454,6 +2463,8 @@
 	if (unlikely(--req->ref_count))
 		return;
 
+	elv_completed_request(q, req);
+
 	req->rq_status = RQ_INACTIVE;
 	req->rl = NULL;
 
@@ -2463,26 +2474,25 @@
 	 */
 	if (rl) {
 		int rw = rq_data_dir(req);
-
-		elv_completed_request(q, req);
+		int priv = req->flags & REQ_ELVPRIV;
 
 		BUG_ON(!list_empty(&req->queuelist));
 
 		blk_free_request(q, req);
-		freed_request(q, rw);
+		freed_request(q, rw, priv);
 	}
 }
 
 void blk_put_request(struct request *req)
 {
-	/*
-	 * if req->rl isn't set, this request didnt originate from the
-	 * block layer, so it's safe to just disregard it
-	 */
-	if (req->rl) {
-		unsigned long flags;
-		request_queue_t *q = req->q;
+	unsigned long flags;
+	request_queue_t *q = req->q;
 
+	/*
+	 * Gee, IDE calls in w/ NULL q.  Fix IDE and remove the
+	 * following if (q) test.
+	 */
+	if (q) {
 		spin_lock_irqsave(q->queue_lock, flags);
 		__blk_put_request(q, req);
 		spin_unlock_irqrestore(q->queue_lock, flags);
@@ -2797,97 +2807,6 @@
 	}
 }
 
-void blk_finish_queue_drain(request_queue_t *q)
-{
-	struct request_list *rl = &q->rq;
-	struct request *rq;
-	int requeued = 0;
-
-	spin_lock_irq(q->queue_lock);
-	clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
-
-	while (!list_empty(&q->drain_list)) {
-		rq = list_entry_rq(q->drain_list.next);
-
-		list_del_init(&rq->queuelist);
-		elv_requeue_request(q, rq);
-		requeued++;
-	}
-
-	if (requeued)
-		q->request_fn(q);
-
-	spin_unlock_irq(q->queue_lock);
-
-	wake_up(&rl->wait[0]);
-	wake_up(&rl->wait[1]);
-	wake_up(&rl->drain);
-}
-
-static int wait_drain(request_queue_t *q, struct request_list *rl, int dispatch)
-{
-	int wait = rl->count[READ] + rl->count[WRITE];
-
-	if (dispatch)
-		wait += !list_empty(&q->queue_head);
-
-	return wait;
-}
-
-/*
- * We rely on the fact that only requests allocated through blk_alloc_request()
- * have io scheduler private data structures associated with them. Any other
- * type of request (allocated on stack or through kmalloc()) should not go
- * to the io scheduler core, but be attached to the queue head instead.
- */
-void blk_wait_queue_drained(request_queue_t *q, int wait_dispatch)
-{
-	struct request_list *rl = &q->rq;
-	DEFINE_WAIT(wait);
-
-	spin_lock_irq(q->queue_lock);
-	set_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
-
-	while (wait_drain(q, rl, wait_dispatch)) {
-		prepare_to_wait(&rl->drain, &wait, TASK_UNINTERRUPTIBLE);
-
-		if (wait_drain(q, rl, wait_dispatch)) {
-			__generic_unplug_device(q);
-			spin_unlock_irq(q->queue_lock);
-			io_schedule();
-			spin_lock_irq(q->queue_lock);
-		}
-
-		finish_wait(&rl->drain, &wait);
-	}
-
-	spin_unlock_irq(q->queue_lock);
-}
-
-/*
- * block waiting for the io scheduler being started again.
- */
-static inline void block_wait_queue_running(request_queue_t *q)
-{
-	DEFINE_WAIT(wait);
-
-	while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
-		struct request_list *rl = &q->rq;
-
-		prepare_to_wait_exclusive(&rl->drain, &wait,
-				TASK_UNINTERRUPTIBLE);
-
-		/*
-		 * re-check the condition. avoids using prepare_to_wait()
-		 * in the fast path (queue is running)
-		 */
-		if (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))
-			io_schedule();
-
-		finish_wait(&rl->drain, &wait);
-	}
-}
-
 static void handle_bad_sector(struct bio *bio)
 {
 	char b[BDEVNAME_SIZE];
@@ -2983,8 +2902,6 @@
 		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
 			goto end_io;
 
-		block_wait_queue_running(q);
-
 		/*
 		 * If this device has partitions, remap block n
 		 * of partition p to block n+start(p) of the disk.
@@ -3393,7 +3310,7 @@
  * 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.
  */
-struct io_context *current_io_context(int gfp_flags)
+struct io_context *current_io_context(gfp_t gfp_flags)
 {
 	struct task_struct *tsk = current;
 	struct io_context *ret;
@@ -3424,7 +3341,7 @@
  *
  * This is always called in the context of the task which submitted the I/O.
  */
-struct io_context *get_io_context(int gfp_flags)
+struct io_context *get_io_context(gfp_t gfp_flags)
 {
 	struct io_context *ret;
 	ret = current_io_context(gfp_flags);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b35e088..96c664a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -881,7 +881,7 @@
 static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 {
 	struct file *filp = lo->lo_backing_file;
-	int gfp = lo->old_gfp_mask;
+	gfp_t gfp = lo->old_gfp_mask;
 
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c
index b1730b6..f56b8ed 100644
--- a/drivers/block/noop-iosched.c
+++ b/drivers/block/noop-iosched.c
@@ -7,57 +7,19 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-/*
- * See if we can find a request that this buffer can be coalesced with.
- */
-static int elevator_noop_merge(request_queue_t *q, struct request **req,
-			       struct bio *bio)
+static void elevator_noop_add_request(request_queue_t *q, struct request *rq)
 {
-	int ret;
-
-	ret = elv_try_last_merge(q, bio);
-	if (ret != ELEVATOR_NO_MERGE)
-		*req = q->last_merge;
-
-	return ret;
+	elv_dispatch_add_tail(q, rq);
 }
 
-static void elevator_noop_merge_requests(request_queue_t *q, struct request *req,
-					 struct request *next)
+static int elevator_noop_dispatch(request_queue_t *q, int force)
 {
-	list_del_init(&next->queuelist);
-}
-
-static void elevator_noop_add_request(request_queue_t *q, struct request *rq,
-				      int where)
-{
-	if (where == ELEVATOR_INSERT_FRONT)
-		list_add(&rq->queuelist, &q->queue_head);
-	else
-		list_add_tail(&rq->queuelist, &q->queue_head);
-
-	/*
-	 * new merges must not precede this barrier
-	 */
-	if (rq->flags & REQ_HARDBARRIER)
-		q->last_merge = NULL;
-	else if (!q->last_merge)
-		q->last_merge = rq;
-}
-
-static struct request *elevator_noop_next_request(request_queue_t *q)
-{
-	if (!list_empty(&q->queue_head))
-		return list_entry_rq(q->queue_head.next);
-
-	return NULL;
+	return 0;
 }
 
 static struct elevator_type elevator_noop = {
 	.ops = {
-		.elevator_merge_fn		= elevator_noop_merge,
-		.elevator_merge_req_fn		= elevator_noop_merge_requests,
-		.elevator_next_req_fn		= elevator_noop_next_request,
+		.elevator_dispatch_fn		= elevator_noop_dispatch,
 		.elevator_add_req_fn		= elevator_noop_add_request,
 	},
 	.elevator_name = "noop",
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 1fef136..ce94aa1 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -29,6 +29,7 @@
 #include <linux/string.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/sched.h>	/* TASK_* */
 
 #ifdef CONFIG_PARPORT_MODULE
 #define CONFIG_PARPORT
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 94af920..e9746af2 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -807,10 +807,6 @@
 		return 1;
 	spin_lock_irqsave(&pf_spin_lock, saved_flags);
 	pf_end_request(1);
-	if (pf_req) {
-		pf_count = pf_req->current_nr_sectors;
-		pf_buf = pf_req->buffer;
-	}
 	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
 	return 1;
 }
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index b398239..6f5df0f 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -162,6 +162,8 @@
 #include <linux/mtio.h>
 #include <linux/pg.h>
 #include <linux/device.h>
+#include <linux/sched.h>	/* current, TASK_* */
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 
@@ -674,7 +676,7 @@
 	for (unit = 0; unit < PG_UNITS; unit++) {
 		struct pg *dev = &devices[unit];
 		if (dev->present) {
-			class_device_create(pg_class, MKDEV(major, unit),
+			class_device_create(pg_class, NULL, MKDEV(major, unit),
 					NULL, "pg%u", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit),
 				      S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index d8d3523..715ae5d 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -146,6 +146,7 @@
 #include <linux/slab.h>
 #include <linux/mtio.h>
 #include <linux/device.h>
+#include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
 
 #include <asm/uaccess.h>
 
@@ -971,7 +972,7 @@
 	devfs_mk_dir("pt");
 	for (unit = 0; unit < PT_UNITS; unit++)
 		if (pt[unit].present) {
-			class_device_create(pt_class, MKDEV(major, unit),
+			class_device_create(pt_class, NULL, MKDEV(major, unit),
 					NULL, "pt%d", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit),
 				      S_IFCHR | S_IRUSR | S_IWUSR,
@@ -980,7 +981,7 @@
 				class_device_destroy(pt_class, MKDEV(major, unit));
 				goto out_class;
 			}
-			class_device_create(pt_class, MKDEV(major, unit + 128),
+			class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
 					NULL, "pt%dn", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit + 128),
 				      S_IFCHR | S_IRUSR | S_IWUSR,
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 145c1fb..68c60a5 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -348,7 +348,7 @@
 		struct block_device *bdev = inode->i_bdev;
 		struct address_space *mapping;
 		unsigned bsize;
-		int gfp_mask;
+		gfp_t gfp_mask;
 
 		inode = igrab(bdev->bd_inode);
 		rd_bdev[unit] = bdev;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index d57007b9..1ded3b4 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -1,7 +1,7 @@
 /*
  *  sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware
  *
- *  Copyright 2004 Red Hat, Inc.
+ *  Copyright 2004-2005 Red Hat, Inc.
  *
  *  Author/maintainer:  Jeff Garzik <jgarzik@pobox.com>
  *
@@ -31,10 +31,6 @@
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
 
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Promise SATA SX8 block driver");
-
 #if 0
 #define CARM_DEBUG
 #define CARM_VERBOSE_DEBUG
@@ -45,9 +41,35 @@
 #undef CARM_NDEBUG
 
 #define DRV_NAME "sx8"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "1.0"
 #define PFX DRV_NAME ": "
 
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Promise SATA SX8 block driver");
+MODULE_VERSION(DRV_VERSION);
+
+/*
+ * SX8 hardware has a single message queue for all ATA ports.
+ * When this driver was written, the hardware (firmware?) would
+ * corrupt data eventually, if more than one request was outstanding.
+ * As one can imagine, having 8 ports bottlenecking on a single
+ * command hurts performance.
+ *
+ * Based on user reports, later versions of the hardware (firmware?)
+ * seem to be able to survive with more than one command queued.
+ *
+ * Therefore, we default to the safe option -- 1 command -- but
+ * allow the user to increase this.
+ *
+ * SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ),
+ * but problems seem to occur when you exceed ~30, even on newer hardware.
+ */
+static int max_queue = 1;
+module_param(max_queue, int, 0444);
+MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)");
+
+
 #define NEXT_RESP(idx)	((idx + 1) % RMSG_Q_LEN)
 
 /* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
@@ -90,12 +112,10 @@
 
 	/* command message queue limits */
 	CARM_MAX_REQ		= 64,	       /* max command msgs per host */
-	CARM_MAX_Q		= 1,		   /* one command at a time */
 	CARM_MSG_LOW_WATER	= (CARM_MAX_REQ / 4),	     /* refill mark */
 
 	/* S/G limits, host-wide and per-request */
 	CARM_MAX_REQ_SG		= 32,	     /* max s/g entries per request */
-	CARM_SG_BOUNDARY	= 0xffffUL,	    /* s/g segment boundary */
 	CARM_MAX_HOST_SG	= 600,		/* max s/g entries per host */
 	CARM_SG_LOW_WATER	= (CARM_MAX_HOST_SG / 4),   /* re-fill mark */
 
@@ -181,6 +201,10 @@
 	FL_DYN_MAJOR		= (1 << 17),
 };
 
+enum {
+	CARM_SG_BOUNDARY	= 0xffffUL,	    /* s/g segment boundary */
+};
+
 enum scatter_gather_types {
 	SGT_32BIT		= 0,
 	SGT_64BIT		= 1,
@@ -218,7 +242,6 @@
 
 struct carm_port {
 	unsigned int			port_no;
-	unsigned int			n_queued;
 	struct gendisk			*disk;
 	struct carm_host		*host;
 
@@ -448,7 +471,7 @@
 	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
 		if (msg_size <= msg_sizes[i])
 			return i;
-	
+
 	return -ENOENT;
 }
 
@@ -509,7 +532,7 @@
 	if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
 		return NULL;
 
-	for (i = 0; i < CARM_MAX_Q; i++)
+	for (i = 0; i < max_queue; i++)
 		if ((host->msg_alloc & (1ULL << i)) == 0) {
 			struct carm_request *crq = &host->req[i];
 			crq->port = NULL;
@@ -521,14 +544,14 @@
 			assert(host->n_msgs <= CARM_MAX_REQ);
 			return crq;
 		}
-	
+
 	DPRINTK("no request available, returning NULL\n");
 	return NULL;
 }
 
 static int carm_put_request(struct carm_host *host, struct carm_request *crq)
 {
-	assert(crq->tag < CARM_MAX_Q);
+	assert(crq->tag < max_queue);
 
 	if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
 		return -EINVAL; /* tried to clear a tag that was not active */
@@ -791,7 +814,7 @@
 			int is_ok)
 {
 	carm_end_request_queued(host, crq, is_ok);
-	if (CARM_MAX_Q == 1)
+	if (max_queue == 1)
 		carm_round_robin(host);
 	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
 		 (host->hw_sg_used <= CARM_SG_LOW_WATER)) {
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index ed4d500..bfb23d5 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1512,7 +1512,7 @@
 	scmd->nsg = 1;
 	sg = &scmd->sgv[0];
 	sg->page = virt_to_page(sc->top_sense);
-	sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1);
+	sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1);
 	sg->length = UB_SENSE_SIZE;
 	scmd->len = UB_SENSE_SIZE;
 	scmd->lun = cmd->lun;
@@ -1891,7 +1891,7 @@
 	cmd->nsg = 1;
 	sg = &cmd->sgv[0];
 	sg->page = virt_to_page(p);
-	sg->offset = (unsigned int)p & (PAGE_SIZE-1);
+	sg->offset = (unsigned long)p & (PAGE_SIZE-1);
 	sg->length = 8;
 	cmd->len = 8;
 	cmd->lun = lun;
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 543f93e..b9fbe6e 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -55,14 +55,6 @@
 
 	  Say Y here to compile support for HCI BCSP protocol.
 
-config BT_HCIUART_BCSP_TXCRC
-	bool "Transmit CRC with every BCSP packet"
-	depends on BT_HCIUART_BCSP
-	help
-	  If you say Y here, a 16-bit CRC checksum will be transmitted along with
-	  every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip.
-	  This increases reliability, but slightly reduces efficiency.
-
 config BT_HCIBCM203X
 	tristate "HCI BCM203x USB driver"
 	depends on USB
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 4fa8523..0db0400 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -550,6 +550,9 @@
 	if (ignore)
 		return -ENODEV;
 
+	if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
+		return -ENODEV;
+
 	data = kmalloc(sizeof(*data), GFP_KERNEL);
 	if (!data) {
 		BT_ERR("Can't allocate data structure");
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 0ee324e..0a47614 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -1,35 +1,27 @@
-/* 
-   BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
-   Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
-
-   Based on
-       hci_h4.c  by Maxim Krasnyansky <maxk@qualcomm.com>
-       ABCSP     by Carl Orsborn <cjo@csr.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
 /*
- * $Id: hci_bcsp.c,v 1.2 2002/09/26 05:05:14 maxk Exp $
+ *
+ *  Bluetooth HCI UART driver
+ *
+ *  Copyright (C) 2002-2003  Fabrizio Gennari <fabrizio.gennari@philips.com>
+ *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
  */
 
-#define VERSION "0.2"
-
 #include <linux/config.h>
 #include <linux/module.h>
 
@@ -52,16 +44,56 @@
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
+
 #include "hci_uart.h"
-#include "hci_bcsp.h"
 
 #ifndef CONFIG_BT_HCIUART_DEBUG
 #undef  BT_DBG
 #define BT_DBG( A... )
 #endif
 
+#define VERSION "0.3"
+
+static int txcrc = 1;
 static int hciextn = 1;
 
+#define BCSP_TXWINSIZE	4
+
+#define BCSP_ACK_PKT	0x05
+#define BCSP_LE_PKT	0x06
+
+struct bcsp_struct {
+	struct sk_buff_head unack;	/* Unack'ed packets queue */
+	struct sk_buff_head rel;	/* Reliable packets queue */
+	struct sk_buff_head unrel;	/* Unreliable packets queue */
+
+	unsigned long rx_count;
+	struct	sk_buff *rx_skb;
+	u8	rxseq_txack;		/* rxseq == txack. */
+	u8	rxack;			/* Last packet sent by us that the peer ack'ed */
+	struct	timer_list tbcsp;
+
+	enum {
+		BCSP_W4_PKT_DELIMITER,
+		BCSP_W4_PKT_START,
+		BCSP_W4_BCSP_HDR,
+		BCSP_W4_DATA,
+		BCSP_W4_CRC
+	} rx_state;
+
+	enum {
+		BCSP_ESCSTATE_NOESC,
+		BCSP_ESCSTATE_ESC
+	} rx_esc_state;
+
+	u8	use_crc;
+	u16	message_crc;
+	u8	txack_req;		/* Do we need to send ack's to the peer? */
+
+	/* Reliable packet sequence number - used to assign seq to each rel pkt. */
+	u8	msgq_txseq;
+};
+
 /* ---- BCSP CRC calculation ---- */
 
 /* Table for calculating CRC for polynomial 0x1021, LSB processed first,
@@ -111,6 +143,7 @@
 		rev |= (crc & 1);
 		crc = crc >> 1;
 	}
+
 	return (rev);
 }
 
@@ -119,6 +152,7 @@
 static void bcsp_slip_msgdelim(struct sk_buff *skb)
 {
 	const char pkt_delim = 0xc0;
+
 	memcpy(skb_put(skb, 1), &pkt_delim, 1);
 }
 
@@ -173,11 +207,8 @@
 {
 	struct sk_buff *nskb;
 	u8 hdr[4], chan;
-	int rel, i;
-
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
 	u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
-#endif
+	int rel, i;
 
 	switch (pkt_type) {
 	case HCI_ACLDATA_PKT:
@@ -240,9 +271,9 @@
 		BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
 		bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
 	}
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
-	hdr[0] |= 0x40;
-#endif
+
+	if (bcsp->use_crc)
+		hdr[0] |= 0x40;
 
 	hdr[1] = ((len << 4) & 0xff) | chan;
 	hdr[2] = len >> 4;
@@ -251,25 +282,25 @@
 	/* Put BCSP header */
 	for (i = 0; i < 4; i++) {
 		bcsp_slip_one_byte(nskb, hdr[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
-		bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
-#endif
+
+		if (bcsp->use_crc)
+			bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
 	}
 
 	/* Put payload */
 	for (i = 0; i < len; i++) {
 		bcsp_slip_one_byte(nskb, data[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
-		bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
-#endif
+
+		if (bcsp->use_crc)
+			bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
 	}
 
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
 	/* Put CRC */
-	bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
-	bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
-	bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
-#endif
+	if (bcsp->use_crc) {
+		bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
+		bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
+		bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
+	}
 
 	bcsp_slip_msgdelim(nskb);
 	return nskb;
@@ -317,7 +348,6 @@
 
 	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
 
-
 	/* We could not send a reliable packet, either because there are
 	   none or because there are too many unack'ed pkts. Did we receive
 	   any packets we have not acknowledged yet ? */
@@ -363,7 +393,7 @@
 		BT_ERR("Peer acked invalid packet");
 
 	BT_DBG("Removing %u pkts out of %u, up to seqno %u",
-	       pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
+		pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
 
 	for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed
 			&& skb != (struct sk_buff *) &bcsp->unack; i++) {
@@ -374,8 +404,10 @@
 		kfree_skb(skb);
 		skb = nskb;
 	}
+
 	if (bcsp->unack.qlen == 0)
 		del_timer(&bcsp->tbcsp);
+
 	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
 
 	if (i != pkts_to_be_removed)
@@ -530,6 +562,7 @@
 
 		hci_recv_frame(bcsp->rx_skb);
 	}
+
 	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
 	bcsp->rx_skb = NULL;
 }
@@ -598,8 +631,8 @@
 
 				BT_ERR ("Checksum failed: computed %04x received %04x",
 					bcsp_crc_reverse(bcsp->message_crc),
-				     	(bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
-				     	bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
+					(bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
+					bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
 
 				kfree_skb(bcsp->rx_skb);
 				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
@@ -633,7 +666,7 @@
 				bcsp->rx_count = 4;
 				bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
 				BCSP_CRC_INIT(bcsp->message_crc);
-				
+
 				/* Do not increment ptr or decrement count
 				 * Allocate packet. Max len of a BCSP pkt= 
 				 * 0xFFF (payload) +4 (header) +2 (crc) */
@@ -698,6 +731,9 @@
 
 	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
 
+	if (txcrc)
+		bcsp->use_crc = 1;
+
 	return 0;
 }
 
@@ -718,18 +754,19 @@
 }
 
 static struct hci_uart_proto bcsp = {
-	.id      = HCI_UART_BCSP,
-	.open    = bcsp_open,
-	.close   = bcsp_close,
-	.enqueue = bcsp_enqueue,
-	.dequeue = bcsp_dequeue,
-	.recv    = bcsp_recv,
-	.flush   = bcsp_flush
+	.id		= HCI_UART_BCSP,
+	.open		= bcsp_open,
+	.close		= bcsp_close,
+	.enqueue	= bcsp_enqueue,
+	.dequeue	= bcsp_dequeue,
+	.recv		= bcsp_recv,
+	.flush		= bcsp_flush
 };
 
 int bcsp_init(void)
 {
 	int err = hci_uart_register_proto(&bcsp);
+
 	if (!err)
 		BT_INFO("HCI BCSP protocol initialized");
 	else
@@ -743,5 +780,8 @@
 	return hci_uart_unregister_proto(&bcsp);
 }
 
+module_param(txcrc, bool, 0644);
+MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
+
 module_param(hciextn, bool, 0644);
 MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
diff --git a/drivers/bluetooth/hci_bcsp.h b/drivers/bluetooth/hci_bcsp.h
deleted file mode 100644
index a2b3bb9..0000000
--- a/drivers/bluetooth/hci_bcsp.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 
-   BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
-   Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
-
-   Based on
-       hci_h4.c  by Maxim Krasnyansky <maxk@qualcomm.com>
-       ABCSP     by Carl Orsborn <cjo@csr.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
-/* 
- * $Id: hci_bcsp.h,v 1.2 2002/09/26 05:05:14 maxk Exp $
- */
-
-#ifndef __HCI_BCSP_H__
-#define __HCI_BCSP_H__
-
-#define BCSP_TXWINSIZE  4
-
-#define BCSP_ACK_PKT    0x05
-#define BCSP_LE_PKT     0x06
-
-struct bcsp_struct {
-	struct sk_buff_head unack;	/* Unack'ed packets queue */
-	struct sk_buff_head rel;	/* Reliable packets queue */
-	struct sk_buff_head unrel;	/* Unreliable packets queue */
-
-	unsigned long rx_count;
-	struct  sk_buff *rx_skb;
-	u8      rxseq_txack;		/* rxseq == txack. */
-	u8      rxack;			/* Last packet sent by us that the peer ack'ed */
-	struct  timer_list tbcsp;
-	
-	enum {
-		BCSP_W4_PKT_DELIMITER,
-		BCSP_W4_PKT_START,
-		BCSP_W4_BCSP_HDR,
-		BCSP_W4_DATA,
-		BCSP_W4_CRC
-	} rx_state;
-
-	enum {
-		BCSP_ESCSTATE_NOESC,
-		BCSP_ESCSTATE_ESC
-	} rx_esc_state;
-
-	u16     message_crc;
-	u8      txack_req;		/* Do we need to send ack's to the peer? */
-
-	/* Reliable packet sequence number - used to assign seq to each rel pkt. */
-	u8      msgq_txseq;
-};
-
-#endif	/* __HCI_BCSP_H__ */
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index cf8a22d..12e369a 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -1,33 +1,27 @@
-/* 
-   BlueZ - Bluetooth protocol stack for Linux
-   Copyright (C) 2000-2001 Qualcomm Incorporated
-
-   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
 /*
- * Bluetooth HCI UART(H4) protocol.
  *
- * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $    
+ *  Bluetooth HCI UART driver
+ *
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
  */
-#define VERSION "1.2"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -51,24 +45,41 @@
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
+
 #include "hci_uart.h"
-#include "hci_h4.h"
 
 #ifndef CONFIG_BT_HCIUART_DEBUG
 #undef  BT_DBG
 #define BT_DBG( A... )
 #endif
 
+#define VERSION "1.2"
+
+struct h4_struct {
+	unsigned long rx_state;
+	unsigned long rx_count;
+	struct sk_buff *rx_skb;
+	struct sk_buff_head txq;
+};
+
+/* H4 receiver States */
+#define H4_W4_PACKET_TYPE	0
+#define H4_W4_EVENT_HDR		1
+#define H4_W4_ACL_HDR		2
+#define H4_W4_SCO_HDR		3
+#define H4_W4_DATA		4
+
 /* Initialize protocol */
 static int h4_open(struct hci_uart *hu)
 {
 	struct h4_struct *h4;
-	
+
 	BT_DBG("hu %p", hu);
-	
+
 	h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
 	if (!h4)
 		return -ENOMEM;
+
 	memset(h4, 0, sizeof(*h4));
 
 	skb_queue_head_init(&h4->txq);
@@ -83,7 +94,9 @@
 	struct h4_struct *h4 = hu->priv;
 
 	BT_DBG("hu %p", hu);
+
 	skb_queue_purge(&h4->txq);
+
 	return 0;
 }
 
@@ -91,16 +104,19 @@
 static int h4_close(struct hci_uart *hu)
 {
 	struct h4_struct *h4 = hu->priv;
+
 	hu->priv = NULL;
 
 	BT_DBG("hu %p", hu);
 
 	skb_queue_purge(&h4->txq);
+
 	if (h4->rx_skb)
 		kfree_skb(h4->rx_skb);
 
 	hu->priv = NULL;
 	kfree(h4);
+
 	return 0;
 }
 
@@ -114,6 +130,7 @@
 	/* Prepend skb with frame type */
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
 	skb_queue_tail(&h4->txq, skb);
+
 	return 0;
 }
 
@@ -122,6 +139,7 @@
 	register int room = skb_tailroom(h4->rx_skb);
 
 	BT_DBG("len %d room %d", len, room);
+
 	if (!len) {
 		hci_recv_frame(h4->rx_skb);
 	} else if (len > room) {
@@ -136,6 +154,7 @@
 	h4->rx_state = H4_W4_PACKET_TYPE;
 	h4->rx_skb   = NULL;
 	h4->rx_count = 0;
+
 	return 0;
 }
 
@@ -228,6 +247,7 @@
 			ptr++; count--;
 			continue;
 		};
+
 		ptr++; count--;
 
 		/* Allocate packet */
@@ -238,9 +258,11 @@
 			h4->rx_count = 0;
 			return 0;
 		}
+
 		h4->rx_skb->dev = (void *) hu->hdev;
 		bt_cb(h4->rx_skb)->pkt_type = type;
 	}
+
 	return count;
 }
 
@@ -251,23 +273,24 @@
 }
 
 static struct hci_uart_proto h4p = {
-	.id      = HCI_UART_H4,
-	.open    = h4_open,
-	.close   = h4_close,
-	.recv    = h4_recv,
-	.enqueue = h4_enqueue,
-	.dequeue = h4_dequeue,
-	.flush   = h4_flush,
+	.id		= HCI_UART_H4,
+	.open		= h4_open,
+	.close		= h4_close,
+	.recv		= h4_recv,
+	.enqueue	= h4_enqueue,
+	.dequeue	= h4_dequeue,
+	.flush		= h4_flush,
 };
-	      
+
 int h4_init(void)
 {
 	int err = hci_uart_register_proto(&h4p);
+
 	if (!err)
 		BT_INFO("HCI H4 protocol initialized");
 	else
 		BT_ERR("HCI H4 protocol registration failed");
-	
+
 	return err;
 }
 
diff --git a/drivers/bluetooth/hci_h4.h b/drivers/bluetooth/hci_h4.h
deleted file mode 100644
index b95ff54..0000000
--- a/drivers/bluetooth/hci_h4.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 
-   BlueZ - Bluetooth protocol stack for Linux
-   Copyright (C) 2000-2001 Qualcomm Incorporated
-
-   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * $Id: hci_h4.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
- */
-
-#ifdef __KERNEL__
-struct h4_struct {
-	unsigned long rx_state;
-	unsigned long rx_count;
-	struct sk_buff *rx_skb;
-	struct sk_buff_head txq;
-};
-
-/* H4 receiver States */
-#define H4_W4_PACKET_TYPE 0
-#define H4_W4_EVENT_HDR	  1
-#define H4_W4_ACL_HDR     2
-#define H4_W4_SCO_HDR     3
-#define H4_W4_DATA        4
-
-#endif /* __KERNEL__ */
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index aed80cc..4a775f6 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -1,33 +1,27 @@
-/* 
-   BlueZ - Bluetooth protocol stack for Linux
-   Copyright (C) 2000-2001 Qualcomm Incorporated
-
-   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
 /*
- * Bluetooth HCI UART driver.
  *
- * $Id: hci_ldisc.c,v 1.5 2002/10/02 18:37:20 maxk Exp $    
+ *  Bluetooth HCI UART driver
+ *
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
  */
-#define VERSION "2.1"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -59,6 +53,8 @@
 #define BT_DBG( A... )
 #endif
 
+#define VERSION "2.2"
+
 static int reset = 0;
 
 static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
@@ -72,6 +68,7 @@
 		return -EEXIST;
 
 	hup[p->id] = p;
+
 	return 0;
 }
 
@@ -84,6 +81,7 @@
 		return -EINVAL;
 
 	hup[p->id] = NULL;
+
 	return 0;
 }
 
@@ -91,13 +89,14 @@
 {
 	if (id >= HCI_UART_MAX_PROTO)
 		return NULL;
+
 	return hup[id];
 }
 
 static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
 {
 	struct hci_dev *hdev = hu->hdev;
-	
+
 	/* Update HCI stat counters */
 	switch (pkt_type) {
 	case HCI_COMMAND_PKT:
@@ -117,10 +116,12 @@
 static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
 {
 	struct sk_buff *skb = hu->tx_skb;
+
 	if (!skb)
 		skb = hu->proto->dequeue(hu);
 	else
 		hu->tx_skb = NULL;
+
 	return skb;
 }
 
@@ -129,7 +130,7 @@
 	struct tty_struct *tty = hu->tty;
 	struct hci_dev *hdev = hu->hdev;
 	struct sk_buff *skb;
-	
+
 	if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
 		set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
 		return 0;
@@ -142,7 +143,7 @@
 
 	while ((skb = hci_uart_dequeue(hu))) {
 		int len;
-	
+
 		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 		len = tty->driver->write(tty, skb->data, skb->len);
 		hdev->stat.byte_tx += len;
@@ -152,11 +153,11 @@
 			hu->tx_skb = skb;
 			break;
 		}
-	
+
 		hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
 		kfree_skb(skb);
-	} 
-	
+	}
+
 	if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
 		goto restart;
 
@@ -173,6 +174,7 @@
 	/* Nothing to do for UART driver */
 
 	set_bit(HCI_RUNNING, &hdev->flags);
+
 	return 0;
 }
 
@@ -234,6 +236,7 @@
 	hu->proto->enqueue(hu, skb);
 
 	hci_uart_tx_wakeup(hu);
+
 	return 0;
 }
 
@@ -241,7 +244,8 @@
 {
 	struct hci_uart *hu;
 
-	if (!hdev) return;
+	if (!hdev)
+		return;
 
 	BT_DBG("%s", hdev->name);
 
@@ -272,6 +276,7 @@
 		BT_ERR("Can't allocate controll structure");
 		return -ENFILE;
 	}
+
 	memset(hu, 0, sizeof(struct hci_uart));
 
 	tty->disc_data = hu;
@@ -280,8 +285,10 @@
 	spin_lock_init(&hu->rx_lock);
 
 	/* Flush any pending characters in the driver and line discipline. */
+
 	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
 	   open path is before the ldisc is referencable */
+
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 
@@ -372,13 +379,13 @@
 static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
 {
 	struct hci_uart *hu = (void *)tty->disc_data;
-	
+
 	if (!hu || tty != hu->tty)
 		return;
 
 	if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
 		return;
-	
+
 	spin_lock(&hu->rx_lock);
 	hu->proto->recv(hu, (void *) data, count);
 	hu->hdev->stat.byte_rx += count;
@@ -429,8 +436,8 @@
 static int hci_uart_set_proto(struct hci_uart *hu, int id)
 {
 	struct hci_uart_proto *p;
-	int err;	
-	
+	int err;
+
 	p = hci_uart_get_proto(id);
 	if (!p)
 		return -EPROTONOSUPPORT;
@@ -446,6 +453,7 @@
 		p->close(hu);
 		return err;
 	}
+
 	return 0;
 }
 
@@ -463,7 +471,7 @@
  * Return Value:    Command dependent
  */
 static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
-                            unsigned int cmd, unsigned long arg)
+					unsigned int cmd, unsigned long arg)
 {
 	struct hci_uart *hu = (void *)tty->disc_data;
 	int err = 0;
@@ -483,14 +491,14 @@
 				return err;
 			}
 			tty->low_latency = 1;
-		} else	
+		} else
 			return -EBUSY;
 
 	case HCIUARTGETPROTO:
 		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
 			return hu->proto->id;
 		return -EUNATCH;
-		
+
 	default:
 		err = n_tty_ioctl(tty, file, cmd, arg);
 		break;
@@ -502,27 +510,23 @@
 /*
  * We don't provide read/write/poll interface for user space.
  */
-static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr)
-{
-	return 0;
-}
-static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count)
-{
-	return 0;
-}
-static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait)
+static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
+					unsigned char __user *buf, size_t nr)
 {
 	return 0;
 }
 
-#ifdef CONFIG_BT_HCIUART_H4
-int h4_init(void);
-int h4_deinit(void);
-#endif
-#ifdef CONFIG_BT_HCIUART_BCSP
-int bcsp_init(void);
-int bcsp_deinit(void);
-#endif
+static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file,
+					const unsigned char *data, size_t count)
+{
+	return 0;
+}
+
+static unsigned int hci_uart_tty_poll(struct tty_struct *tty,
+					struct file *filp, poll_table *wait)
+{
+	return 0;
+}
 
 static int __init hci_uart_init(void)
 {
@@ -534,18 +538,18 @@
 	/* Register the tty discipline */
 
 	memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
-	hci_uart_ldisc.magic       = TTY_LDISC_MAGIC;
-	hci_uart_ldisc.name        = "n_hci";
-	hci_uart_ldisc.open        = hci_uart_tty_open;
-	hci_uart_ldisc.close       = hci_uart_tty_close;
-	hci_uart_ldisc.read        = hci_uart_tty_read;
-	hci_uart_ldisc.write       = hci_uart_tty_write;
-	hci_uart_ldisc.ioctl       = hci_uart_tty_ioctl;
-	hci_uart_ldisc.poll        = hci_uart_tty_poll;
-	hci_uart_ldisc.receive_room= hci_uart_tty_room;
-	hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
-	hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup;
-	hci_uart_ldisc.owner       = THIS_MODULE;
+	hci_uart_ldisc.magic		= TTY_LDISC_MAGIC;
+	hci_uart_ldisc.name		= "n_hci";
+	hci_uart_ldisc.open		= hci_uart_tty_open;
+	hci_uart_ldisc.close		= hci_uart_tty_close;
+	hci_uart_ldisc.read		= hci_uart_tty_read;
+	hci_uart_ldisc.write		= hci_uart_tty_write;
+	hci_uart_ldisc.ioctl		= hci_uart_tty_ioctl;
+	hci_uart_ldisc.poll		= hci_uart_tty_poll;
+	hci_uart_ldisc.receive_room	= hci_uart_tty_room;
+	hci_uart_ldisc.receive_buf	= hci_uart_tty_receive;
+	hci_uart_ldisc.write_wakeup	= hci_uart_tty_wakeup;
+	hci_uart_ldisc.owner		= THIS_MODULE;
 
 	if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
 		BT_ERR("HCI line discipline registration failed. (%d)", err);
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 0a57d727..b250e67 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -1,32 +1,29 @@
-/* 
-   BlueZ - Bluetooth protocol stack for Linux
-   Copyright (C) 2000-2001 Qualcomm Incorporated
-
-   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
 /*
- * $Id: hci_uart.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
+ *
+ *  Bluetooth HCI UART driver
+ *
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
  */
 
-#ifndef N_HCI 
+#ifndef N_HCI
 #define N_HCI	15
 #endif
 
@@ -42,7 +39,6 @@
 #define HCI_UART_3WIRE	2
 #define HCI_UART_H4DS	3
 
-#ifdef __KERNEL__
 struct hci_uart;
 
 struct hci_uart_proto {
@@ -56,27 +52,35 @@
 };
 
 struct hci_uart {
-	struct tty_struct  *tty;
-	struct hci_dev     *hdev;
-	unsigned long      flags;
+	struct tty_struct	*tty;
+	struct hci_dev		*hdev;
+	unsigned long		flags;
 
-	struct hci_uart_proto *proto;
-	void               *priv;
-	
-	struct sk_buff     *tx_skb;
-	unsigned long      tx_state;
-	spinlock_t         rx_lock;
+	struct hci_uart_proto	*proto;
+	void			*priv;
+
+	struct sk_buff		*tx_skb;
+	unsigned long		tx_state;
+	spinlock_t		rx_lock;
 };
 
 /* HCI_UART flag bits */
-#define HCI_UART_PROTO_SET		0
+#define HCI_UART_PROTO_SET	0
 
 /* TX states  */
-#define HCI_UART_SENDING		1
-#define HCI_UART_TX_WAKEUP		2
+#define HCI_UART_SENDING	1
+#define HCI_UART_TX_WAKEUP	2
 
 int hci_uart_register_proto(struct hci_uart_proto *p);
 int hci_uart_unregister_proto(struct hci_uart_proto *p);
 int hci_uart_tx_wakeup(struct hci_uart *hu);
 
-#endif /* __KERNEL__ */
+#ifdef CONFIG_BT_HCIUART_H4
+int h4_init(void);
+int h4_deinit(void);
+#endif
+
+#ifdef CONFIG_BT_HCIUART_BCSP
+int bcsp_init(void);
+int bcsp_deinit(void);
+#endif
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index c29365d..fdf4370 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -661,7 +661,7 @@
 
 config NVRAM
 	tristate "/dev/nvram support"
-	depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM
+	depends on ATARI || X86 || ARM || GENERIC_NVRAM
 	---help---
 	  If you say Y here and create a character special file /dev/nvram
 	  with major number 10 and minor number 144 using mknod ("man mknod"),
@@ -985,7 +985,7 @@
 
 config HANGCHECK_TIMER
 	tristate "Hangcheck timer"
-	depends on X86_64 || X86 || IA64 || PPC64 || ARCH_S390
+	depends on X86 || IA64 || PPC64 || ARCH_S390
 	help
 	  The hangcheck-timer module detects when the system has gone
 	  out to lunch past a certain margin.  It can reboot the system
@@ -1001,5 +1001,17 @@
 
 source "drivers/char/tpm/Kconfig"
 
+config TELCLOCK
+	tristate "Telecom clock driver for MPBL0010 ATCA SBC"
+	depends on EXPERIMENTAL
+	default n
+	help
+	  The telecom clock device is specific to the MPBL0010 ATCA computer and
+	  allows direct userspace access to the configuration of the telecom clock
+	  configuration settings.  This device is used for hardware synchronization
+	  across the ATCA backplane fabric.  Upon loading, the driver exports a
+	  sysfs directory, /sys/devices/platform/telco_clock, with a number of
+	  files for controlling the behavior of this hardware.
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 08f6928..4aeae68 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -82,6 +82,7 @@
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
 obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
 obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
+obj-$(CONFIG_TELCLOCK) += tlclk.o
 
 obj-$(CONFIG_WATCHDOG)	+= watchdog/
 obj-$(CONFIG_MWAVE) += mwave/
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 7f8c1b5..486ed8a 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -27,7 +27,7 @@
 
 config AGP_ALI
 	tristate "ALI chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	---help---
 	  This option gives you AGP support for the GLX component of
 	  XFree86 4.x on the following ALi chipsets.  The supported chipsets
@@ -45,7 +45,7 @@
 
 config AGP_ATI
 	tristate "ATI chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	---help---
       This option gives you AGP support for the GLX component of
       XFree86 4.x on the ATI RadeonIGP family of chipsets.
@@ -55,7 +55,7 @@
 
 config AGP_AMD
 	tristate "AMD Irongate, 761, and 762 chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	help
 	  This option gives you AGP support for the GLX component of
 	  XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
@@ -91,7 +91,7 @@
 
 config AGP_NVIDIA
 	tristate "NVIDIA nForce/nForce2 chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	help
 	  This option gives you AGP support for the GLX component of
 	  XFree86 4.x on the following NVIDIA chipsets.  The supported chipsets
@@ -99,7 +99,7 @@
 
 config AGP_SIS
 	tristate "SiS chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	help
 	  This option gives you AGP support for the GLX component of
 	  XFree86 4.x on Silicon Integrated Systems [SiS] chipsets.
@@ -111,14 +111,14 @@
 
 config AGP_SWORKS
 	tristate "Serverworks LE/HE chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	help
 	  Say Y here to support the Serverworks AGP card.  See 
 	  <http://www.serverworks.com/> for product descriptions and images.
 
 config AGP_VIA
 	tristate "VIA chipset support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	help
 	  This option gives you AGP support for the GLX component of
 	  XFree86 4.x on VIA MVP3/Apollo Pro chipsets.
@@ -154,7 +154,7 @@
 
 config AGP_EFFICEON
 	tristate "Transmeta Efficeon support"
-	depends on AGP && X86 && !X86_64
+	depends on AGP && X86_32
 	help
 	  This option gives you AGP support for the Transmeta Efficeon
 	  series processors with integrated northbridges.
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 9c9c9c2..b02fc22 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/agp_backend.h>
+#include <asm/page.h>		/* PAGE_SIZE */
 #include "agp.h"
 
 #define ALI_AGPCTRL	0xb8
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 0a7624a..0e6c3a3 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -13,6 +13,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/agp_backend.h>
+#include <asm/page.h>		/* PAGE_SIZE */
 #include "agp.h"
 
 /* Will need to be increased if AMD64 ever goes >8-way. */
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index e572ced..0b6e726 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -6,6 +6,8 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/agp_backend.h>
 #include <asm/agp.h>
 #include "agp.h"
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 9494329..a2d9e5e 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -10,6 +10,8 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/agp_backend.h>
 
 #include "agp.h"
diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c
index c9ac731..4008324 100644
--- a/drivers/char/agp/isoch.c
+++ b/drivers/char/agp/isoch.c
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/agp_backend.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 
 #include "agp.h"
 
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index d3aa159..7957fc9 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/agp_backend.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioca_provider.h>
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index a9fb12c..71ea59a 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -5,6 +5,8 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/agp_backend.h>
 #include "agp.h"
 
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index cf4c364..c7f818c 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -281,7 +281,7 @@
  * make sure "cyc" appears in all kernel messages; all soft interrupts
  * handled by same routine; recognize out-of-band reception; comment
  * out some diagnostic messages; leave RTS/CTS flow control to hardware;
- * fix race condition in -Z buffer management; only -Y needs to explictly
+ * fix race condition in -Z buffer management; only -Y needs to explicitly
  * flush chars; tidy up some startup messages;
  *
  * Revision 1.36.4.18  1996/07/25 18:57:31  bentson
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 475cc5e..6d34497 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -15,6 +15,8 @@
 #include <linux/device.h>
 #include <linux/kdev_t.h>
 #include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 
 #include "drm_core.h"
 #include "drmP.h"
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 26271e3..8693835 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -515,7 +515,7 @@
 		err = PTR_ERR(dsp56k_class);
 		goto out_chrdev;
 	}
-	class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+	class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
 
 	err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
 		      S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 407708a..b7a0e4d 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -3113,6 +3113,7 @@
 int __init init_PCI (void)
 {	/* Begin init_PCI */
 	memset (&epca_driver, 0, sizeof (epca_driver));
+	epca_driver.owner = THIS_MODULE;
 	epca_driver.name = "epca";
 	epca_driver.id_table = epca_pci_tbl;
 	epca_driver.probe = epca_init_one;
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index 5745b74..821357c 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -331,27 +331,27 @@
 
 	zft_class = class_create(THIS_MODULE, "zft");
 	for (i = 0; i < 4; i++) {
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"qft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"zqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nzqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"rawqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nrawqft%i", i);
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index a54bc93..66e53dd 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,7 +117,7 @@
 __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #endif /* not MODULE */
 
-#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
+#if defined(CONFIG_X86)
 # define HAVE_MONOTONIC
 # define TIMER_FREQ 1000000000ULL
 #elif defined(CONFIG_ARCH_S390)
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index c055bb6..3808d95 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -49,7 +49,9 @@
 #define	HPET_USER_FREQ	(64)
 #define	HPET_DRIFT	(500)
 
-static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
+#define HPET_RANGE_SIZE		1024	/* from HPET spec */
+
+static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
 
 /* A lock for concurrent access by app and isr hpet activity. */
 static DEFINE_SPINLOCK(hpet_lock);
@@ -78,7 +80,7 @@
 	struct hpet __iomem *hp_hpet;
 	unsigned long hp_hpet_phys;
 	struct time_interpolator *hp_interpolator;
-	unsigned long hp_period;
+	unsigned long long hp_tick_freq;
 	unsigned long hp_delta;
 	unsigned int hp_ntimer;
 	unsigned int hp_which;
@@ -90,6 +92,7 @@
 #define	HPET_OPEN		0x0001
 #define	HPET_IE			0x0002	/* interrupt enabled */
 #define	HPET_PERIODIC		0x0004
+#define	HPET_SHARED_IRQ		0x0008
 
 #if BITS_PER_LONG == 64
 #define	write_counter(V, MC)	writeq(V, MC)
@@ -120,6 +123,11 @@
 	unsigned long isr;
 
 	devp = data;
+	isr = 1 << (devp - devp->hd_hpets->hp_dev);
+
+	if ((devp->hd_flags & HPET_SHARED_IRQ) &&
+	    !(isr & readl(&devp->hd_hpet->hpet_isr)))
+		return IRQ_NONE;
 
 	spin_lock(&hpet_lock);
 	devp->hd_irqdata++;
@@ -137,8 +145,8 @@
 			      &devp->hd_timer->hpet_compare);
 	}
 
-	isr = (1 << (devp - devp->hd_hpets->hp_dev));
-	writeq(isr, &devp->hd_hpet->hpet_isr);
+	if (devp->hd_flags & HPET_SHARED_IRQ)
+		writel(isr, &devp->hd_hpet->hpet_isr);
 	spin_unlock(&hpet_lock);
 
 	spin_lock(&hpet_task_lock);
@@ -276,7 +284,8 @@
 
 	if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
 					PAGE_SIZE, vma->vm_page_prot)) {
-		printk(KERN_ERR "remap_pfn_range failed in hpet.c\n");
+		printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
+			__FUNCTION__);
 		return -EAGAIN;
 	}
 
@@ -364,7 +373,9 @@
 	hpet = devp->hd_hpet;
 	hpetp = devp->hd_hpets;
 
-	v = readq(&timer->hpet_config);
+	if (!devp->hd_ireqfreq)
+		return -EIO;
+
 	spin_lock_irq(&hpet_lock);
 
 	if (devp->hd_flags & HPET_IE) {
@@ -373,16 +384,21 @@
 	}
 
 	devp->hd_flags |= HPET_IE;
+
+	if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK)
+		devp->hd_flags |= HPET_SHARED_IRQ;
 	spin_unlock_irq(&hpet_lock);
 
-	t = readq(&timer->hpet_config);
 	irq = devp->hd_hdwirq;
 
 	if (irq) {
-		sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
+		unsigned long irq_flags;
 
-		if (request_irq
-		    (irq, hpet_interrupt, SA_INTERRUPT, devp->hd_name, (void *)devp)) {
+		sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
+		irq_flags = devp->hd_flags & HPET_SHARED_IRQ
+						? SA_SHIRQ : SA_INTERRUPT;
+		if (request_irq(irq, hpet_interrupt, irq_flags,
+				devp->hd_name, (void *)devp)) {
 			printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
 			irq = 0;
 		}
@@ -416,20 +432,24 @@
 		write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
 	}
 
-	isr = (1 << (devp - hpets->hp_dev));
-	writeq(isr, &hpet->hpet_isr);
+	if (devp->hd_flags & HPET_SHARED_IRQ) {
+		isr = 1 << (devp - devp->hd_hpets->hp_dev);
+		writel(isr, &hpet->hpet_isr);
+	}
 	writeq(g, &timer->hpet_config);
 	local_irq_restore(flags);
 
 	return 0;
 }
 
-static inline unsigned long hpet_time_div(unsigned long dis)
+/* converts Hz to number of timer ticks */
+static inline unsigned long hpet_time_div(struct hpets *hpets,
+					  unsigned long dis)
 {
-	unsigned long long m = 1000000000000000ULL;
+	unsigned long long m;
 
+	m = hpets->hp_tick_freq + (dis >> 1);
 	do_div(m, dis);
-
 	return (unsigned long)m;
 }
 
@@ -477,14 +497,21 @@
 		{
 			struct hpet_info info;
 
-			info.hi_ireqfreq = hpet_time_div(hpetp->hp_period *
-							 devp->hd_ireqfreq);
+			if (devp->hd_ireqfreq)
+				info.hi_ireqfreq =
+					hpet_time_div(hpetp, devp->hd_ireqfreq);
+			else
+				info.hi_ireqfreq = 0;
 			info.hi_flags =
 			    readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
-			info.hi_hpet = devp->hd_hpets->hp_which;
-			info.hi_timer = devp - devp->hd_hpets->hp_dev;
-			if (copy_to_user((void __user *)arg, &info, sizeof(info)))
-				err = -EFAULT;
+			info.hi_hpet = hpetp->hp_which;
+			info.hi_timer = devp - hpetp->hp_dev;
+			if (kernel)
+				memcpy((void *)arg, &info, sizeof(info));
+			else
+				if (copy_to_user((void __user *)arg, &info,
+						 sizeof(info)))
+					err = -EFAULT;
 			break;
 		}
 	case HPET_EPI:
@@ -516,12 +543,12 @@
 			break;
 		}
 
-		if (arg & (arg - 1)) {
+		if (!arg) {
 			err = -EINVAL;
 			break;
 		}
 
-		devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg);
+		devp->hd_ireqfreq = hpet_time_div(hpetp, arg);
 	}
 
 	return err;
@@ -539,6 +566,17 @@
 	.mmap = hpet_mmap,
 };
 
+static int hpet_is_known(struct hpet_data *hdp)
+{
+	struct hpets *hpetp;
+
+	for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+		if (hpetp->hp_hpet_phys == hdp->hd_phys_address)
+			return 1;
+
+	return 0;
+}
+
 EXPORT_SYMBOL(hpet_alloc);
 EXPORT_SYMBOL(hpet_register);
 EXPORT_SYMBOL(hpet_unregister);
@@ -563,6 +601,8 @@
 		return -EINVAL;
 	}
 
+	tp->ht_opaque = NULL;
+
 	spin_lock_irq(&hpet_task_lock);
 	spin_lock(&hpet_lock);
 
@@ -702,15 +742,14 @@
 #ifdef	CONFIG_TIME_INTERPOLATION
 	struct time_interpolator *ti;
 
-	ti = kmalloc(sizeof(*ti), GFP_KERNEL);
+	ti = kzalloc(sizeof(*ti), GFP_KERNEL);
 	if (!ti)
 		return;
 
-	memset(ti, 0, sizeof(*ti));
 	ti->source = TIME_SOURCE_MMIO64;
 	ti->shift = 10;
 	ti->addr = &hpetp->hp_hpet->hpet_mc;
-	ti->frequency = hpet_time_div(hpets->hp_period);
+	ti->frequency = hpetp->hp_tick_freq;
 	ti->drift = HPET_DRIFT;
 	ti->mask = -1;
 
@@ -743,11 +782,11 @@
 	if (!timer)
 		return 0;
 
-	hpet = hpets->hp_hpet;
+	hpet = hpetp->hp_hpet;
 	t = read_counter(&timer->hpet_compare);
 
 	i = 0;
-	count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE);
+	count = hpet_time_div(hpetp, TICK_CALIBRATE);
 
 	local_irq_save(flags);
 
@@ -771,28 +810,29 @@
 	struct hpets *hpetp;
 	size_t siz;
 	struct hpet __iomem *hpet;
-	static struct hpets *last = (struct hpets *)0;
-	unsigned long ns;
+	static struct hpets *last = NULL;
+	unsigned long period;
+	unsigned long long temp;
 
 	/*
 	 * hpet_alloc can be called by platform dependent code.
-	 * if platform dependent code has allocated the hpet
-	 * ACPI also reports hpet, then we catch it here.
+	 * If platform dependent code has allocated the hpet that
+	 * ACPI has also reported, then we catch it here.
 	 */
-	for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-		if (hpetp->hp_hpet == hdp->hd_address)
-			return 0;
+	if (hpet_is_known(hdp)) {
+		printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
+			__FUNCTION__);
+		return 0;
+	}
 
 	siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
 				      sizeof(struct hpet_dev));
 
-	hpetp = kmalloc(siz, GFP_KERNEL);
+	hpetp = kzalloc(siz, GFP_KERNEL);
 
 	if (!hpetp)
 		return -ENOMEM;
 
-	memset(hpetp, 0, siz);
-
 	hpetp->hp_which = hpet_nhpet++;
 	hpetp->hp_hpet = hdp->hd_address;
 	hpetp->hp_hpet_phys = hdp->hd_phys_address;
@@ -822,21 +862,23 @@
 
 	last = hpetp;
 
-	hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
-	    HPET_COUNTER_CLK_PERIOD_SHIFT;
+	period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
+		HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */
+	temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */
+	temp += period >> 1; /* round */
+	do_div(temp, period);
+	hpetp->hp_tick_freq = temp; /* ticks per second */
 
-	printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
-		hpetp->hp_which, hdp->hd_phys_address,
+	printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s",
+		hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address,
 		hpetp->hp_ntimer > 1 ? "s" : "");
 	for (i = 0; i < hpetp->hp_ntimer; i++)
 		printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
 	printk("\n");
 
-	ns = hpetp->hp_period;	/* femptoseconds, 10^-15 */
-	ns /= 1000000;		/* convert to nanoseconds, 10^-9 */
-	printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
-		hpetp->hp_which, ns, hpetp->hp_ntimer,
-		cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
+	printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
+	       hpetp->hp_which, hpetp->hp_ntimer,
+	       cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq);
 
 	mcfg = readq(&hpet->hpet_config);
 	if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
@@ -845,13 +887,10 @@
 		writeq(mcfg, &hpet->hpet_config);
 	}
 
-	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
-	     i++, hpet_ntimer++, devp++) {
-		unsigned long v;
+	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) {
 		struct hpet_timer __iomem *timer;
 
 		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
-		v = readq(&timer->hpet_config);
 
 		devp->hd_hpets = hpetp;
 		devp->hd_hpet = hpet;
@@ -880,7 +919,6 @@
 	struct hpet_data *hdp;
 	acpi_status status;
 	struct acpi_resource_address64 addr;
-	struct hpets *hpetp;
 
 	hdp = data;
 
@@ -893,9 +931,29 @@
 		hdp->hd_phys_address = addr.min_address_range;
 		hdp->hd_address = ioremap(addr.min_address_range, size);
 
-		for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-			if (hpetp->hp_hpet == hdp->hd_address)
-				return -EBUSY;
+		if (hpet_is_known(hdp)) {
+			printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+				__FUNCTION__, hdp->hd_phys_address);
+			iounmap(hdp->hd_address);
+			return -EBUSY;
+		}
+	} else if (res->id == ACPI_RSTYPE_FIXED_MEM32) {
+		struct acpi_resource_fixed_mem32 *fixmem32;
+
+		fixmem32 = &res->data.fixed_memory32;
+		if (!fixmem32)
+			return -EINVAL;
+
+		hdp->hd_phys_address = fixmem32->range_base_address;
+		hdp->hd_address = ioremap(fixmem32->range_base_address,
+						HPET_RANGE_SIZE);
+
+		if (hpet_is_known(hdp)) {
+			printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+				__FUNCTION__, hdp->hd_phys_address);
+			iounmap(hdp->hd_address);
+			return -EBUSY;
+		}
 	} else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
 		struct acpi_resource_ext_irq *irqp;
 		int i;
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 9e4e26a..d815d19 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -721,8 +721,9 @@
 			}
 
 			if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-				class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i), NULL, "ipl%d", i);
+				class_device_create(ip2_class, NULL,
+						MKDEV(IP2_IPL_MAJOR, 4 * i),
+						NULL, "ipl%d", i);
 				err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
 						"ip2/ipl%d", i);
@@ -732,8 +733,9 @@
 					goto out_class;
 				}
 
-				class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i + 1), NULL, "stat%d", i);
+				class_device_create(ip2_class, NULL,
+						MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+						NULL, "stat%d", i);
 				err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
 						"ip2/stat%d", i);
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index a09ff10..7c0684d 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -798,7 +798,7 @@
 	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
 		      "ipmidev/%d", if_num);
 
-	class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
+	class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
 }
 
 static void ipmi_smi_gone(int if_num)
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 9c19e54..e3ddbdb 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -5246,7 +5246,8 @@
 		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 			       S_IFCHR | S_IRUSR | S_IWUSR,
 			       "staliomem/%d", i);
-		class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
+		class_device_create(istallion_class, NULL,
+				MKDEV(STL_SIOMEMMAJOR, i),
 				NULL, "staliomem%d", i);
 	}
 
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
index b771611..29963d8 100644
--- a/drivers/char/lcd.c
+++ b/drivers/char/lcd.c
@@ -575,8 +575,8 @@
 
 static int lcd_waiters = 0;
 
-static long lcd_read(struct inode *inode, struct file *file, char *buf,
-		     unsigned long count)
+static ssize_t lcd_read(struct file *file, char *buf,
+		     size_t count, loff_t *ofs)
 {
 	long buttons_now;
 
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
index 878a952..a8d4ae7 100644
--- a/drivers/char/lcd.h
+++ b/drivers/char/lcd.h
@@ -22,7 +22,7 @@
 #define MAX_IDLE_TIME 120
 
 struct lcd_display {
-        unsigned long buttons;
+        unsigned buttons;
         int size1;
         int size2;
         unsigned char line1[LCD_CHARS_PER_LINE];
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 2afb903..e572605 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -805,7 +805,7 @@
 	if (reset)
 		lp_reset(nr);
 
-	class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+	class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
 				"lp%d", nr);
 	devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
 			"printers/%d", nr);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 9df928d..91dd669 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -918,7 +918,8 @@
 
 	mem_class = class_create(THIS_MODULE, "mem");
 	for (i = 0; i < ARRAY_SIZE(devlist); i++) {
-		class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
+		class_device_create(mem_class, NULL,
+					MKDEV(MEM_MAJOR, devlist[i].minor),
 					NULL, devlist[i].name);
 		devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
 				S_IFCHR | devlist[i].mode, devlist[i].name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 0c83751..3e4c041 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -234,7 +234,7 @@
 	}
 	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	misc->class = class_device_create(misc_class, dev, misc->dev,
+	misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
 					  "%s", misc->name);
 	if (IS_ERR(misc->class)) {
 		err = PTR_ERR(misc->class);
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 1200618..78c89a3 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -441,7 +441,7 @@
 mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i;
-	mmtimer_t *base = timers + cpuid_to_cnodeid(smp_processor_id()) *
+	mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) *
 						NUM_COMPARATORS;
 	unsigned long expires = 0;
 	int result = IRQ_NONE;
@@ -608,7 +608,7 @@
 	 */
 	preempt_disable();
 
-	nodeid =  cpuid_to_cnodeid(smp_processor_id());
+	nodeid =  cpu_to_node(smp_processor_id());
 	base = timers + nodeid * NUM_COMPARATORS;
 retry:
 	/* Don't use an allocated timer, or a deleted one that's pending */
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index 613aed9..d1fe05e 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -53,6 +53,8 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/sched.h>	/* cond_resched() */
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index c9bdf54..c556f4d 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -62,7 +62,7 @@
 
 static inline unsigned char *alloc_buf(void)
 {
-	unsigned int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+	gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 
 	if (PAGE_SIZE != N_TTY_BUF_SIZE)
 		return kmalloc(N_TTY_BUF_SIZE, prio);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 1af733d..9e24bbd 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -32,9 +32,11 @@
  * 		added changelog
  * 	1.2	Erik Gilling: Cobalt Networks support
  * 		Tim Hockin: general cleanup, Cobalt support
+ * 	1.3	Jon Ringle: Comdial MP1000 support
+ *
  */
 
-#define NVRAM_VERSION	"1.2"
+#define NVRAM_VERSION	"1.3"
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -45,6 +47,7 @@
 #define PC		1
 #define ATARI		2
 #define COBALT		3
+#define MP1000		4
 
 /* select machine configuration */
 #if defined(CONFIG_ATARI)
@@ -54,6 +57,9 @@
 #  if defined(CONFIG_COBALT)
 #    include <linux/cobalt-nvram.h>
 #    define MACH COBALT
+#  elif defined(CONFIG_MACH_MP1000)
+#    undef MACH
+#    define MACH MP1000
 #  else
 #    define MACH PC
 #  endif
@@ -112,6 +118,23 @@
 
 #endif
 
+#if MACH == MP1000
+
+/* RTC in a MP1000 */
+#define CHECK_DRIVER_INIT()	1
+
+#define MP1000_CKS_RANGE_START	0
+#define MP1000_CKS_RANGE_END	111
+#define MP1000_CKS_LOC		112
+
+#define NVRAM_BYTES		(128-NVRAM_FIRST_BYTE)
+
+#define mach_check_checksum	mp1000_check_checksum
+#define mach_set_checksum	mp1000_set_checksum
+#define mach_proc_infos		mp1000_proc_infos
+
+#endif
+
 /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
  * rtc_lock held. Due to the index-port/data-port design of the RTC, we
  * don't want two different things trying to get to it at once. (e.g. the
@@ -915,6 +938,91 @@
 
 #endif /* MACH == ATARI */
 
+#if MACH == MP1000
+
+static int
+mp1000_check_checksum(void)
+{
+	int i;
+	unsigned short sum = 0;
+	unsigned short expect;
+
+	for (i = MP1000_CKS_RANGE_START; i <= MP1000_CKS_RANGE_END; ++i)
+		sum += __nvram_read_byte(i);
+
+        expect = __nvram_read_byte(MP1000_CKS_LOC+1)<<8 |
+	    __nvram_read_byte(MP1000_CKS_LOC);
+	return ((sum & 0xffff) == expect);
+}
+
+static void
+mp1000_set_checksum(void)
+{
+	int i;
+	unsigned short sum = 0;
+
+	for (i = MP1000_CKS_RANGE_START; i <= MP1000_CKS_RANGE_END; ++i)
+		sum += __nvram_read_byte(i);
+	__nvram_write_byte(sum >> 8, MP1000_CKS_LOC + 1);
+	__nvram_write_byte(sum & 0xff, MP1000_CKS_LOC);
+}
+
+#ifdef CONFIG_PROC_FS
+
+#define         SERVER_N_LEN         32
+#define         PATH_N_LEN           32
+#define         FILE_N_LEN           32
+#define         NVRAM_MAGIC_SIG      0xdead
+
+typedef struct NvRamImage
+{
+	unsigned short int    magic;
+	unsigned short int    mode;
+	char                  fname[FILE_N_LEN];
+	char                  path[PATH_N_LEN];
+	char                  server[SERVER_N_LEN];
+	char                  pad[12];
+} NvRam;
+
+static int
+mp1000_proc_infos(unsigned char *nvram, char *buffer, int *len,
+    off_t *begin, off_t offset, int size)
+{
+	int checksum;
+        NvRam* nv = (NvRam*)nvram;
+
+	spin_lock_irq(&rtc_lock);
+	checksum = __nvram_check_checksum();
+	spin_unlock_irq(&rtc_lock);
+
+	PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
+
+        switch( nv->mode )
+        {
+           case 0 :
+                    PRINT_PROC( "\tMode 0, tftp prompt\n" );
+                    break;
+           case 1 :
+                    PRINT_PROC( "\tMode 1, booting from disk\n" );
+                    break;
+           case 2 :
+                    PRINT_PROC( "\tMode 2, Alternate boot from disk /boot/%s\n", nv->fname );
+                    break;
+           case 3 :
+                    PRINT_PROC( "\tMode 3, Booting from net:\n" );
+                    PRINT_PROC( "\t\t%s:%s%s\n",nv->server, nv->path, nv->fname );
+                    break;
+           default:
+                    PRINT_PROC( "\tInconsistant nvram?\n" );
+                    break;
+        }
+
+	return 1;
+}
+#endif
+
+#endif /* MACH == MP1000 */
+
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(__nvram_read_byte);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 0e22880..306ee0f 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -752,7 +752,7 @@
 
 static void pp_attach(struct parport *port)
 {
-	class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
+	class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
 			NULL, "parport%d", port->number);
 }
 
diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c
index 40a3cf6..601d09b 100644
--- a/drivers/char/qtronix.c
+++ b/drivers/char/qtronix.c
@@ -591,6 +591,11 @@
 		return retval;
 
 	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+	if (!queue) {
+		misc_deregister(&psaux_mouse);
+		return -ENOMEM;
+	}
+		
 	memset(queue, 0, sizeof(*queue));
 	queue->head = queue->tail = 0;
 	init_waitqueue_head(&queue->proc_list);
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index f13e5de..30e4cbe 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -128,7 +128,7 @@
 static void bind_device(struct raw_config_request *rq)
 {
 	class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-	class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+	class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
 				      NULL, "raw%d", rq->raw_minor);
 }
 
@@ -307,7 +307,7 @@
 		unregister_chrdev_region(dev, MAX_RAW_MINORS);
 		goto error;
 	}
-	class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+	class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
 	devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
 		      S_IFCHR | S_IRUGO | S_IWUGO,
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 5b1d368..928b850 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -256,7 +256,6 @@
 static int sReadAiopID(ByteIO_t io);
 static int sReadAiopNumChan(WordIO_t io);
 
-#ifdef MODULE
 MODULE_AUTHOR("Theodore Ts'o");
 MODULE_DESCRIPTION("Comtrol RocketPort driver");
 module_param(board1, ulong, 0);
@@ -288,17 +287,14 @@
 module_param_array(pc104_4, ulong, NULL, 0);
 MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
 
-int rp_init(void);
+static int rp_init(void);
 static void rp_cleanup_module(void);
 
 module_init(rp_init);
 module_exit(rp_cleanup_module);
 
-#endif
 
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
 
 /*************************************************************************/
 /*                     Module code starts here                           */
@@ -2378,7 +2374,7 @@
 /*
  * The module "startup" routine; it's run when the module is loaded.
  */
-int __init rp_init(void)
+static int __init rp_init(void)
 {
 	int retval, pci_boards_found, isa_boards_found, i;
 
@@ -2502,7 +2498,6 @@
 	return 0;
 }
 
-#ifdef MODULE
 
 static void rp_cleanup_module(void)
 {
@@ -2530,7 +2525,6 @@
 	if (controller)
 		release_region(controller, 4);
 }
-#endif
 
 /***************************************************************************
 Function: sInitController
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index e1a90d9..887b8b2 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -519,30 +519,28 @@
 
 static int ticnt_save;
 
-static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410_rtc_suspend(struct device *dev, pm_message_t state)
 {
 	struct rtc_time tm;
 	struct timespec time;
 
 	time.tv_nsec = 0;
 
-	if (level == SUSPEND_POWER_DOWN) {
-		/* save TICNT for anyone using periodic interrupts */
+	/* save TICNT for anyone using periodic interrupts */
 
-		ticnt_save = readb(S3C2410_TICNT);
+	ticnt_save = readb(S3C2410_TICNT);
 
-		/* calculate time delta for suspend */
+	/* calculate time delta for suspend */
 
-		s3c2410_rtc_gettime(&tm);
-		rtc_tm_to_time(&tm, &time.tv_sec);
-		save_time_delta(&s3c2410_rtc_delta, &time);
-		s3c2410_rtc_enable(dev, 0);
-	}
+	s3c2410_rtc_gettime(&tm);
+	rtc_tm_to_time(&tm, &time.tv_sec);
+	save_time_delta(&s3c2410_rtc_delta, &time);
+	s3c2410_rtc_enable(dev, 0);
 
 	return 0;
 }
 
-static int s3c2410_rtc_resume(struct device *dev, u32 level)
+static int s3c2410_rtc_resume(struct device *dev)
 {
 	struct rtc_time tm;
 	struct timespec time;
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 6b4e9d1..dda30e4 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -790,7 +790,7 @@
 
 	}	
 
-	printk("Total: %d A2232 boards initialized.\n.", nr_a2232); /* Some status report if no card was found */
+	printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */
 
 	a2232_init_portstructs();
 
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 261a41b..0e7d216 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -377,7 +377,7 @@
 	dev_t first_dev, dev;
 	nasid_t event_nasid = ia64_sn_get_console_nasid();
 
-	if (alloc_chrdev_region(&first_dev, 0, numionodes,
+	if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
 				SYSCTL_BASENAME) < 0) {
 		printk("%s: failed to register SN system controller device\n",
 		       __FUNCTION__);
@@ -385,7 +385,7 @@
 	}
 	snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
 
-	for (cnode = 0; cnode < numionodes; cnode++) {
+	for (cnode = 0; cnode < num_cnodes; cnode++) {
 			geoid = cnodeid_get_geoid(cnode);
 			devnamep = devname;
 			format_module_id(devnamep, geo_module(geoid),
@@ -437,7 +437,7 @@
 				continue;
 			}
 
-			class_device_create(snsc_class, dev, NULL,
+			class_device_create(snsc_class, NULL, dev, NULL,
 						"%s", devname);
 
 			ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 36ae9ad..f86c155 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -424,10 +424,6 @@
 
 #define SONYPI_BUF_SIZE	128
 
-/* The name of the devices for the input device drivers */
-#define SONYPI_JOG_INPUTNAME	"Sony Vaio Jogdial"
-#define SONYPI_KEY_INPUTNAME	"Sony Vaio Keys"
-
 /* Correspondance table between sonypi events and input layer events */
 static struct {
 	int sonypiev;
@@ -490,8 +486,8 @@
 	struct fasync_struct *fifo_async;
 	int open_count;
 	int model;
-	struct input_dev input_jog_dev;
-	struct input_dev input_key_dev;
+	struct input_dev *input_jog_dev;
+	struct input_dev *input_key_dev;
 	struct work_struct input_work;
 	struct kfifo *input_fifo;
 	spinlock_t input_fifo_lock;
@@ -779,8 +775,8 @@
 
 static void sonypi_report_input_event(u8 event)
 {
-	struct input_dev *jog_dev = &sonypi_device.input_jog_dev;
-	struct input_dev *key_dev = &sonypi_device.input_key_dev;
+	struct input_dev *jog_dev = sonypi_device.input_jog_dev;
+	struct input_dev *key_dev = sonypi_device.input_key_dev;
 	struct sonypi_keypress kp = { NULL };
 	int i;
 
@@ -1171,19 +1167,17 @@
 #ifdef CONFIG_PM
 static int old_camera_power;
 
-static int sonypi_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sonypi_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_DISABLE) {
-		old_camera_power = sonypi_device.camera_power;
-		sonypi_disable();
-	}
+	old_camera_power = sonypi_device.camera_power;
+	sonypi_disable();
+
 	return 0;
 }
 
-static int sonypi_resume(struct device *dev, u32 level)
+static int sonypi_resume(struct device *dev)
 {
-	if (level == RESUME_ENABLE)
-		sonypi_enable(old_camera_power);
+	sonypi_enable(old_camera_power);
 	return 0;
 }
 #endif
@@ -1203,6 +1197,47 @@
 	.shutdown	= sonypi_shutdown,
 };
 
+static int __devinit sonypi_create_input_devices(void)
+{
+	struct input_dev *jog_dev;
+	struct input_dev *key_dev;
+	int i;
+
+	sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
+	if (!jog_dev)
+		return -ENOMEM;
+
+	jog_dev->name = "Sony Vaio Jogdial";
+	jog_dev->id.bustype = BUS_ISA;
+	jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+	jog_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	jog_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
+	jog_dev->relbit[0] = BIT(REL_WHEEL);
+
+	sonypi_device.input_key_dev = key_dev = input_allocate_device();
+	if (!key_dev) {
+		input_free_device(jog_dev);
+		sonypi_device.input_jog_dev = NULL;
+		return -ENOMEM;
+	}
+
+	key_dev->name = "Sony Vaio Keys";
+	key_dev->id.bustype = BUS_ISA;
+	key_dev->id.vendor = PCI_VENDOR_ID_SONY;
+
+	/* Initialize the Input Drivers: special keys */
+	key_dev->evbit[0] = BIT(EV_KEY);
+	for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
+		if (sonypi_inputkeys[i].inputev)
+			set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
+
+	input_register_device(jog_dev);
+	input_register_device(key_dev);
+
+	return 0;
+}
+
 static int __devinit sonypi_probe(void)
 {
 	int i, ret;
@@ -1298,34 +1333,10 @@
 	}
 
 	if (useinput) {
-		/* Initialize the Input Drivers: jogdial */
-		int i;
-		sonypi_device.input_jog_dev.evbit[0] =
-			BIT(EV_KEY) | BIT(EV_REL);
-		sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] =
-			BIT(BTN_MIDDLE);
-		sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL);
-		sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME;
-		sonypi_device.input_jog_dev.id.bustype = BUS_ISA;
-		sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
 
-		input_register_device(&sonypi_device.input_jog_dev);
-		printk(KERN_INFO "%s input method installed.\n",
-		       sonypi_device.input_jog_dev.name);
-
-		/* Initialize the Input Drivers: special keys */
-		sonypi_device.input_key_dev.evbit[0] = BIT(EV_KEY);
-		for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
-			if (sonypi_inputkeys[i].inputev)
-				set_bit(sonypi_inputkeys[i].inputev,
-					sonypi_device.input_key_dev.keybit);
-		sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME;
-		sonypi_device.input_key_dev.id.bustype = BUS_ISA;
-		sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY;
-
-		input_register_device(&sonypi_device.input_key_dev);
-		printk(KERN_INFO "%s input method installed.\n",
-		       sonypi_device.input_key_dev.name);
+		ret = sonypi_create_input_devices();
+		if (ret)
+			goto out_inputdevices;
 
 		spin_lock_init(&sonypi_device.input_fifo_lock);
 		sonypi_device.input_fifo =
@@ -1375,8 +1386,9 @@
 out_platformdev:
 	kfifo_free(sonypi_device.input_fifo);
 out_infifo:
-	input_unregister_device(&sonypi_device.input_key_dev);
-	input_unregister_device(&sonypi_device.input_jog_dev);
+	input_unregister_device(sonypi_device.input_key_dev);
+	input_unregister_device(sonypi_device.input_jog_dev);
+out_inputdevices:
 	free_irq(sonypi_device.irq, sonypi_irq);
 out_reqirq:
 	release_region(sonypi_device.ioport1, sonypi_device.region_size);
@@ -1402,8 +1414,8 @@
 	platform_device_unregister(sonypi_device.pdev);
 
 	if (useinput) {
-		input_unregister_device(&sonypi_device.input_key_dev);
-		input_unregister_device(&sonypi_device.input_jog_dev);
+		input_unregister_device(sonypi_device.input_key_dev);
+		input_unregister_device(sonypi_device.input_jog_dev);
 		kfifo_free(sonypi_device.input_fifo);
 	}
 
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 50e0b61..352547e 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -38,19 +38,19 @@
  *
  * Revision 1.0:  April 1st 1997.
  *                Initial release for alpha testing.
- * Revision 1.1:  April 14th 1997. 
- *                Incorporated Richard Hudsons suggestions, 
+ * Revision 1.1:  April 14th 1997.
+ *                Incorporated Richard Hudsons suggestions,
  *                removed some debugging printk's.
  * Revision 1.2:  April 15th 1997.
  *                Ported to 2.1.x kernels.
- * Revision 1.3:  April 17th 1997 
- *                Backported to 2.0. (Compatibility macros). 
+ * Revision 1.3:  April 17th 1997
+ *                Backported to 2.0. (Compatibility macros).
  * Revision 1.4:  April 18th 1997
- *                Fixed DTR/RTS bug that caused the card to indicate 
- *                "don't send data" to a modem after the password prompt.  
+ *                Fixed DTR/RTS bug that caused the card to indicate
+ *                "don't send data" to a modem after the password prompt.
  *                Fixed bug for premature (fake) interrupts.
  * Revision 1.5:  April 19th 1997
- *                fixed a minor typo in the header file, cleanup a little. 
+ *                fixed a minor typo in the header file, cleanup a little.
  *                performance warnings are now MAXed at once per minute.
  * Revision 1.6:  May 23 1997
  *                Changed the specialix=... format to include interrupt.
@@ -60,10 +60,10 @@
  *                port to linux-2.1.43 kernel.
  * Revision 1.9:  Oct 9  1998
  *                Added stuff for the IO8+/PCI version.
- * Revision 1.10: Oct 22  1999 / Jan 21 2000. 
- *                Added stuff for setserial. 
+ * Revision 1.10: Oct 22  1999 / Jan 21 2000.
+ *                Added stuff for setserial.
  *                Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
- * 
+ *
  */
 
 #define VERSION "1.11"
@@ -154,7 +154,7 @@
 
 
 
-/* 
+/*
  * The following defines are mostly for testing purposes. But if you need
  * some nice reporting in your syslog, you can define them also.
  */
@@ -188,7 +188,7 @@
 
 static unsigned long baud_table[] =  {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 0, 
+	9600, 19200, 38400, 57600, 115200, 0,
 };
 
 static struct specialix_board sx_board[SX_NBOARD] =  {
@@ -216,7 +216,7 @@
 		KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
 	static const char *badinfo =
 		KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
- 
+
 	if (!port) {
 		printk(badinfo, name, routine);
 		return 1;
@@ -231,9 +231,9 @@
 
 
 /*
- * 
+ *
  *  Service functions for specialix IO8+ driver.
- * 
+ *
  */
 
 /* Get board number from pointer */
@@ -246,7 +246,7 @@
 /* Get port number from pointer */
 static inline int port_No (struct specialix_port const * port)
 {
-	return SX_PORT(port - sx_port); 
+	return SX_PORT(port - sx_port);
 }
 
 
@@ -309,7 +309,7 @@
 			return;
 		udelay (1);
 	}
-	
+
 	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
 }
 
@@ -329,7 +329,7 @@
 			return;
 		udelay (1);
 	}
-	
+
 	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
 }
 
@@ -338,34 +338,28 @@
  *  specialix IO8+ IO range functions.
  */
 
-static inline int sx_check_io_range(struct specialix_board * bp)
+static inline int sx_request_io_range(struct specialix_board * bp)
 {
-	return check_region (bp->base, SX_IO_SPACE);
-}
-
-
-static inline void sx_request_io_range(struct specialix_board * bp)
-{
-	request_region(bp->base, 
-	               bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE,
-	               "specialix IO8+" );
+	return request_region(bp->base,
+		bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
+		"specialix IO8+") == NULL;
 }
 
 
 static inline void sx_release_io_range(struct specialix_board * bp)
 {
-	release_region(bp->base, 
+	release_region(bp->base,
 	               bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
 }
 
-	
+
 /* Must be called with enabled interrupts */
-/* Ugly. Very ugly. Don't use this for anything else than initialization 
+/* Ugly. Very ugly. Don't use this for anything else than initialization
    code */
 static inline void sx_long_delay(unsigned long delay)
 {
 	unsigned long i;
-	
+
 	for (i = jiffies + delay; time_after(i, jiffies); ) ;
 }
 
@@ -378,7 +372,7 @@
 	int i;
 	unsigned long flags;
 
-	if (bp->flags & SX_BOARD_IS_PCI) 
+	if (bp->flags & SX_BOARD_IS_PCI)
 		return 1;
 	switch (bp->irq) {
 	/* In the same order as in the docs... */
@@ -420,7 +414,7 @@
 	sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT);      /* Prio for receiver intr    */
 	/* Set RegAckEn */
 	sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
-	
+
 	/* Setting up prescaler. We need 4 ticks per 1 ms */
 	scaler =  SX_OSCFREQ/SPECIALIX_TPS;
 
@@ -448,7 +442,7 @@
 	spin_lock_irqsave(&bp->lock, flags);
 	for (i=0, t=0;i<8;i++) {
 		sx_out_off (bp, CD186x_CAR, i);
-		if (sx_in_off (bp, reg) & bit) 
+		if (sx_in_off (bp, reg) & bit)
 			t |= 1 << i;
 	}
 	spin_unlock_irqrestore(&bp->lock, flags);
@@ -472,7 +466,7 @@
 	spin_unlock_irqrestore(&bp->lock, flags);
 	if (irq) {
 		printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
-		sx_interrupt (((struct specialix_board *)data)->irq, 
+		sx_interrupt (((struct specialix_board *)data)->irq,
 		              (void*)data, NULL);
 	}
 	missed_irq_timer.expires = jiffies + sx_poll;
@@ -495,7 +489,7 @@
 
 	func_enter();
 
-	if (sx_check_io_range(bp)) {
+	if (sx_request_io_range(bp)) {
 		func_exit();
 		return 1;
 	}
@@ -509,15 +503,16 @@
 	short_pause ();
 	val2 = sx_in_off(bp, CD186x_PPRL);
 
-	
+
 	if ((val1 != 0x5a) || (val2 != 0xa5)) {
 		printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
 		       board_No(bp), bp->base);
+		sx_release_io_range(bp);
 		func_exit();
 		return 1;
 	}
 
-	/* Check the DSR lines that Specialix uses as board 
+	/* Check the DSR lines that Specialix uses as board
 	   identification */
 	val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
 	val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
@@ -532,6 +527,7 @@
 	if (val1 != val2) {
 		printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
 		       board_No(bp), val2, bp->base, val1);
+		sx_release_io_range(bp);
 		func_exit();
 		return 1;
 	}
@@ -546,7 +542,7 @@
 		sx_wait_CCR(bp);
 		sx_out(bp, CD186x_CCR, CCR_TXEN);        /* Enable transmitter     */
 		sx_out(bp, CD186x_IER, IER_TXRDY);       /* Enable tx empty intr   */
-		sx_long_delay(HZ/20);	       		
+		sx_long_delay(HZ/20);
 		irqs = probe_irq_off(irqs);
 
 		dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
@@ -561,14 +557,15 @@
 		}
 
 		dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
-		        val1, val2, val3); 
-	
+		        val1, val2, val3);
+
 	}
-	
+
 #if 0
 	if (irqs <= 0) {
 		printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
 		       board_No(bp), bp->base);
+		sx_release_io_range(bp);
 		func_exit();
 		return 1;
 	}
@@ -579,19 +576,20 @@
 #endif
 	/* Reset CD186x again  */
 	if (!sx_init_CD186x(bp)) {
+		sx_release_io_range(bp);
 		func_exit();
-		return -EIO;
+		return 1;
 	}
 
 	sx_request_io_range(bp);
 	bp->flags |= SX_BOARD_PRESENT;
-	
+
 	/* Chip           revcode   pkgtype
 	                  GFRCR     SRCR bit 7
 	   CD180 rev B    0x81      0
 	   CD180 rev C    0x82      0
 	   CD1864 rev A   0x82      1
-	   CD1865 rev A   0x83      1  -- Do not use!!! Does not work. 
+	   CD1865 rev A   0x83      1  -- Do not use!!! Does not work.
 	   CD1865 rev B   0x84      1
 	 -- Thanks to Gwen Wang, Cirrus Logic.
 	 */
@@ -623,8 +621,8 @@
 	return 0;
 }
 
-/* 
- * 
+/*
+ *
  *  Interrupt processing routines.
  * */
 
@@ -657,7 +655,7 @@
 			return port;
 		}
 	}
-	printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n", 
+	printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
 	       board_No(bp), what, channel);
 	return NULL;
 }
@@ -681,7 +679,7 @@
 	tty = port->tty;
 	dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n",
 		 port,  tty->flip.count, TTY_FLIPBUF_SIZE);
-	
+
 	status = sx_in(bp, CD186x_RCSR);
 
 	dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
@@ -707,30 +705,30 @@
 		return;
 	}
 	if (status & RCSR_TOUT) {
-		printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", 
+		printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
 		       board_No(bp), port_No(port));
 		func_exit();
 		return;
-		
+
 	} else if (status & RCSR_BREAK) {
 		dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
 		       board_No(bp), port_No(port));
 		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
 		if (port->flags & ASYNC_SAK)
 			do_SAK(tty);
-		
-	} else if (status & RCSR_PE) 
+
+	} else if (status & RCSR_PE)
 		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
-	
-	else if (status & RCSR_FE) 
+
+	else if (status & RCSR_FE)
 		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
-	
+
 	else if (status & RCSR_OE)
 		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-	
+
 	else
 		*tty->flip.flag_buf_ptr++ = 0;
-	
+
 	*tty->flip.char_buf_ptr++ = ch;
 	tty->flip.count++;
 	schedule_delayed_work(&tty->flip.work, 1);
@@ -746,18 +744,18 @@
 	unsigned char count;
 
 	func_enter();
-	
+
 	if (!(port = sx_get_port(bp, "Receive"))) {
 		dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
 		func_exit();
 		return;
 	}
 	tty = port->tty;
-	
+
 	count = sx_in(bp, CD186x_RDCR);
 	dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
 	port->hits[count > 8 ? 9 : count]++;
-	
+
 	while (count--) {
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 			printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n",
@@ -787,7 +785,7 @@
 	}
 	dprintk (SX_DEBUG_TX, "port: %p\n", port);
 	tty = port->tty;
-	
+
 	if (port->IER & IER_TXEMPTY) {
 		/* FIFO drained */
 		sx_out(bp, CD186x_CAR, port_No(port));
@@ -796,7 +794,7 @@
 		func_exit();
 		return;
 	}
-	
+
 	if ((port->xmit_cnt <= 0 && !port->break_length)
 	    || tty->stopped || tty->hw_stopped) {
 		sx_out(bp, CD186x_CAR, port_No(port));
@@ -805,7 +803,7 @@
 		func_exit();
 		return;
 	}
-	
+
 	if (port->break_length) {
 		if (port->break_length > 0) {
 			if (port->COR2 & COR2_ETC) {
@@ -831,7 +829,7 @@
 		func_exit();
 		return;
 	}
-	
+
 	count = CD186x_NFIFO;
 	do {
 		sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
@@ -839,7 +837,7 @@
 		if (--port->xmit_cnt <= 0)
 			break;
 	} while (--count > 0);
-	
+
 	if (port->xmit_cnt <= 0) {
 		sx_out(bp, CD186x_CAR, port_No(port));
 		port->IER &= ~IER_TXRDY;
@@ -862,9 +860,9 @@
 	dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
 	if (!(port = sx_get_port(bp, "Modem")))
 		return;
-	
+
 	tty = port->tty;
-	
+
 	mcr = sx_in(bp, CD186x_MCR);
 	printk ("mcr = %02x.\n", mcr);
 
@@ -879,7 +877,7 @@
 			schedule_work(&port->tqueue_hangup);
 		}
 	}
-	
+
 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
 	if (mcr & MCR_CTSCHG) {
 		if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
@@ -906,7 +904,7 @@
 		sx_out(bp, CD186x_IER, port->IER);
 	}
 #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
-	
+
 	/* Clear change bits */
 	sx_out(bp, CD186x_MCR, 0);
 }
@@ -940,7 +938,7 @@
 	while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
 	                                   (SRSR_RREQint |
 		                            SRSR_TREQint |
-	                                    SRSR_MREQint)))) {	
+	                                    SRSR_MREQint)))) {
 		if (status & SRSR_RREQint) {
 			ack = sx_in(bp, CD186x_RRAR);
 
@@ -951,7 +949,7 @@
 			else
 				printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
 				       board_No(bp), status, ack);
-		
+
 		} else if (status & SRSR_TREQint) {
 			ack = sx_in(bp, CD186x_TRAR);
 
@@ -963,13 +961,13 @@
 		} else if (status & SRSR_MREQint) {
 			ack = sx_in(bp, CD186x_MRAR);
 
-			if (ack == (SX_ID | GIVR_IT_MODEM)) 
+			if (ack == (SX_ID | GIVR_IT_MODEM))
 				sx_check_modem(bp);
 			else
 				printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
 				       board_No(bp), status, ack);
-		
-		} 
+
+		}
 
 		sx_out(bp, CD186x_EOIR, 0);   /* Mark end of interrupt */
 	}
@@ -1026,7 +1024,7 @@
 {
 	int error;
 
-	if (bp->flags & SX_BOARD_ACTIVE) 
+	if (bp->flags & SX_BOARD_ACTIVE)
 		return 0;
 
 	if (bp->flags & SX_BOARD_IS_PCI)
@@ -1034,7 +1032,7 @@
 	else
 		error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
 
-	if (error) 
+	if (error)
 		return error;
 
 	turn_ints_on (bp);
@@ -1055,7 +1053,7 @@
 	}
 
 	bp->flags &= ~SX_BOARD_ACTIVE;
-	
+
 	dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
 		 bp->irq, board_No (bp));
 	free_irq(bp->irq, bp);
@@ -1068,7 +1066,7 @@
 
 
 /*
- * Setting up port characteristics. 
+ * Setting up port characteristics.
  * Must be called with disabled interrupts
  */
 static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
@@ -1103,10 +1101,10 @@
 	spin_unlock_irqrestore(&bp->lock, flags);
 	dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
 	baud = C_BAUD(tty);
-	
+
 	if (baud & CBAUDEX) {
 		baud &= ~CBAUDEX;
-		if (baud < 1 || baud > 2) 
+		if (baud < 1 || baud > 2)
 			port->tty->termios->c_cflag &= ~CBAUDEX;
 		else
 			baud += 15;
@@ -1117,8 +1115,8 @@
 		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 			baud += 2;
 	}
-	
-	
+
+
 	if (!baud_table[baud]) {
 		/* Drop DTR & exit */
 		dprintk (SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
@@ -1127,7 +1125,7 @@
 			spin_lock_irqsave(&bp->lock, flags);
 			sx_out(bp, CD186x_MSVR, port->MSVR );
 			spin_unlock_irqrestore(&bp->lock, flags);
-		} 
+		}
 		else
 			dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
 		return;
@@ -1137,9 +1135,9 @@
 			port ->MSVR |= MSVR_DTR;
 		}
 	}
-	
+
 	/*
-	 * Now we must calculate some speed depended things 
+	 * Now we must calculate some speed depended things
 	 */
 
 	/* Set baud rate for port */
@@ -1152,7 +1150,7 @@
 		tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
 		         CD186x_TPC/2) / CD186x_TPC);
 
-	if ((tmp < 0x10) && time_before(again, jiffies)) { 
+	if ((tmp < 0x10) && time_before(again, jiffies)) {
 		again = jiffies + HZ * 60;
 		/* Page 48 of version 2.0 of the CL-CD1865 databook */
 		if (tmp >= 12) {
@@ -1164,27 +1162,27 @@
 			printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
 			        "Warning: overstressing Cirrus chip. "
 			        "This might not work.\n"
-			        "Read specialix.txt for more info.\n", 
+			        "Read specialix.txt for more info.\n",
 			        port_No (port), tmp);
 		}
 	}
 	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff); 
-	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff); 
-	sx_out(bp, CD186x_RBPRL, tmp & 0xff); 
+	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
+	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
+	sx_out(bp, CD186x_RBPRL, tmp & 0xff);
 	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
 	spin_unlock_irqrestore(&bp->lock, flags);
 	if (port->custom_divisor) {
 		baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
 		baud = ( baud + 5 ) / 10;
-	} else 
+	} else
 		baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
 
 	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;		
+	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
 	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
 					      SERIAL_XMIT_SIZE - 1 : tmp);
-	
+
 	/* Receiver timeout will be transmission time for 1.5 chars */
 	tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
 	tmp = (tmp > 0xff) ? 0xff : tmp;
@@ -1205,29 +1203,29 @@
 		cor1 |= COR1_8BITS;
 		break;
 	}
-	
-	if (C_CSTOPB(tty)) 
+
+	if (C_CSTOPB(tty))
 		cor1 |= COR1_2SB;
-	
+
 	cor1 |= COR1_IGNORE;
 	if (C_PARENB(tty)) {
 		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty)) 
+		if (C_PARODD(tty))
 			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty)) 
+		if (I_INPCK(tty))
 			cor1 &= ~COR1_IGNORE;
 	}
 	/* Set marking of some errors */
 	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty)) 
+	if (I_INPCK(tty))
 		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty)) 
+	if (I_BRKINT(tty) || I_PARMRK(tty))
 		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty)) 
+	if (I_IGNPAR(tty))
 		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
 	if (I_IGNBRK(tty)) {
 		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty)) 
+		if (I_IGNPAR(tty))
 			/* Real raw mode. Ignore all */
 			port->mark_mask &= ~RCSR_OE;
 	}
@@ -1241,7 +1239,7 @@
 		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
 		spin_unlock_irqrestore(&bp->lock, flags);
 #else
-		port->COR2 |= COR2_CTSAE; 
+		port->COR2 |= COR2_CTSAE;
 #endif
 	}
 	/* Enable Software Flow Control. FIXME: I'm not sure about this */
@@ -1264,11 +1262,11 @@
 		mcor1 |= MCOR1_CDZD;
 		mcor2 |= MCOR2_CDOD;
 	}
-	
-	if (C_CREAD(tty)) 
+
+	if (C_CREAD(tty))
 		/* Enable receiver */
 		port->IER |= IER_RXD;
-	
+
 	/* Set input FIFO size (1-8 bytes) */
 	cor3 |= sx_rxfifo;
 	/* Setting up CD186x channel registers */
@@ -1311,11 +1309,11 @@
 		func_exit();
 		return 0;
 	}
-	
+
 	if (!port->xmit_buf) {
 		/* We may sleep in get_zeroed_page() */
 		unsigned long tmp;
-		
+
 		if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
 			func_exit();
 			return -ENOMEM;
@@ -1328,10 +1326,10 @@
 		}
 		port->xmit_buf = (unsigned char *) tmp;
 	}
-		
+
 	spin_lock_irqsave(&port->lock, flags);
 
-	if (port->tty) 
+	if (port->tty)
 		clear_bit(TTY_IO_ERROR, &port->tty->flags);
 
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
@@ -1340,7 +1338,7 @@
 
 	spin_unlock_irqrestore(&port->lock, flags);
 
-		
+
 	func_exit();
 	return 0;
 }
@@ -1352,14 +1350,14 @@
 	struct tty_struct *tty;
 	int i;
 	unsigned long flags;
-	
+
 	func_enter();
 
 	if (!(port->flags & ASYNC_INITIALIZED)) {
 		func_exit();
 		return;
 	}
-	
+
 	if (sx_debug & SX_DEBUG_FIFO) {
 		dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
 			board_No(bp), port_No(port), port->overrun);
@@ -1394,13 +1392,13 @@
 	if (tty)
 		set_bit(TTY_IO_ERROR, &tty->flags);
 	port->flags &= ~ASYNC_INITIALIZED;
-	
-	if (!bp->count) 
+
+	if (!bp->count)
 		sx_shutdown_board(bp);
 	func_exit();
 }
 
-	
+
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
                            struct specialix_port *port)
 {
@@ -1427,7 +1425,7 @@
 			return -ERESTARTSYS;
 		}
 	}
-	
+
 	/*
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
@@ -1477,7 +1475,7 @@
 			if (port->flags & ASYNC_HUP_NOTIFY)
 				retval = -EAGAIN;
 			else
-				retval = -ERESTARTSYS;	
+				retval = -ERESTARTSYS;
 			break;
 		}
 		if (!(port->flags & ASYNC_CLOSING) &&
@@ -1506,7 +1504,7 @@
 	port->flags |= ASYNC_NORMAL_ACTIVE;
 	func_exit();
 	return 0;
-}	
+}
 
 
 static int sx_open(struct tty_struct * tty, struct file * filp)
@@ -1526,7 +1524,7 @@
 		func_exit();
 		return -ENODEV;
 	}
-	
+
 	bp = &sx_board[board];
 	port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
 	port->overrun = 0;
@@ -1557,7 +1555,7 @@
 		func_enter();
 		return error;
 	}
-	
+
 	if ((error = block_til_ready(tty, filp, port))) {
 		func_enter();
 		return error;
@@ -1574,7 +1572,7 @@
 	struct specialix_board *bp;
 	unsigned long flags;
 	unsigned long timeout;
-	
+
 	func_enter();
 	if (!port || sx_paranoia_check(port, tty->name, "close")) {
 		func_exit();
@@ -1587,7 +1585,7 @@
 		func_exit();
 		return;
 	}
-	
+
 	bp = port_Board(port);
 	if ((tty->count == 1) && (port->count != 1)) {
 		printk(KERN_ERR "sx%d: sx_close: bad port count;"
@@ -1607,7 +1605,7 @@
 	}
 	port->flags |= ASYNC_CLOSING;
 	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * Now we wait for the transmit buffer to clear; and we notify
 	 * the line discipline to only process XON/XOFF characters.
 	 */
 	tty->closing = 1;
@@ -1681,7 +1679,7 @@
 }
 
 
-static int sx_write(struct tty_struct * tty, 
+static int sx_write(struct tty_struct * tty,
                     const unsigned char *buf, int count)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
@@ -1694,7 +1692,7 @@
 		func_exit();
 		return 0;
 	}
-	
+
 	bp = port_Board(port);
 
 	if (!tty || !port->xmit_buf || !tmp_buf) {
@@ -1824,7 +1822,7 @@
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 
 	func_enter();
-	
+
 	if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
 		func_exit();
 		return 0;
@@ -1881,13 +1879,13 @@
 		port_No(port), status, sx_in (bp, CD186x_CAR));
 	dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
 	if (SX_CRTSCTS(port->tty)) {
-		result  = /*   (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ 
+		result  = /*   (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
 		          |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
 		          |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
 		          |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
 		          |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
 	} else {
-		result  = /*   (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ 
+		result  = /*   (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
 		          |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
 		          |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
 		          |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
@@ -1955,7 +1953,7 @@
 {
 	struct specialix_board *bp = port_Board(port);
 	unsigned long flags;
-	
+
 	func_enter();
 
 	spin_lock_irqsave (&port->lock, flags);
@@ -1996,8 +1994,8 @@
 		func_enter();
 		return -EFAULT;
 	}
-	
-#if 0	
+
+#if 0
 	if ((tmp.irq != bp->irq) ||
 	    (tmp.port != bp->base) ||
 	    (tmp.type != PORT_CIRRUS) ||
@@ -2008,12 +2006,12 @@
 		func_exit();
 		return -EINVAL;
 	}
-#endif	
+#endif
 
 	change_speed = ((port->flags & ASYNC_SPD_MASK) !=
 			(tmp.flags & ASYNC_SPD_MASK));
 	change_speed |= (tmp.custom_divisor != port->custom_divisor);
-	
+
 	if (!capable(CAP_SYS_ADMIN)) {
 		if ((tmp.close_delay != port->close_delay) ||
 		    (tmp.closing_wait != port->closing_wait) ||
@@ -2045,7 +2043,7 @@
 {
 	struct serial_struct tmp;
 	struct specialix_board *bp = port_Board(port);
-	
+
 	func_enter();
 
 	/*
@@ -2074,7 +2072,7 @@
 }
 
 
-static int sx_ioctl(struct tty_struct * tty, struct file * filp, 
+static int sx_ioctl(struct tty_struct * tty, struct file * filp,
                     unsigned int cmd, unsigned long arg)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
@@ -2087,7 +2085,7 @@
 		func_exit();
 		return -ENODEV;
 	}
-	
+
 	switch (cmd) {
 	 case TCSBRK:	/* SVID version: non-zero arg --> no break */
 		retval = tty_check_change(tty);
@@ -2129,7 +2127,7 @@
 	 case TIOCGSERIAL:
 		 func_exit();
 		return sx_get_serial_info(port, argp);
-	 case TIOCSSERIAL:	
+	 case TIOCSSERIAL:
 		 func_exit();
 		return sx_set_serial_info(port, argp);
 	 default:
@@ -2153,16 +2151,16 @@
 		func_exit();
 		return;
 	}
-	
+
 	bp = port_Board(port);
-	
+
 	/* Use DTR instead of RTS ! */
-	if (SX_CRTSCTS (tty)) 
+	if (SX_CRTSCTS (tty))
 		port->MSVR &= ~MSVR_DTR;
 	else {
 		/* Auch!!! I think the system shouldn't call this then. */
 		/* Or maybe we're supposed (allowed?) to do our side of hw
-		   handshake anyway, even when hardware handshake is off. 
+		   handshake anyway, even when hardware handshake is off.
 		   When you see this in your logs, please report.... */
 		printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
 	                 port_No (port));
@@ -2193,14 +2191,14 @@
 	unsigned long flags;
 
 	func_enter();
-				
+
 	if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
 		func_exit();
 		return;
 	}
-	
+
 	bp = port_Board(port);
-	
+
 	spin_lock_irqsave(&port->lock, flags);
 	/* XXXX Use DTR INSTEAD???? */
 	if (SX_CRTSCTS(tty)) {
@@ -2234,14 +2232,14 @@
 	unsigned long flags;
 
 	func_enter();
-	
+
 	if (sx_paranoia_check(port, tty->name, "sx_stop")) {
 		func_exit();
 		return;
 	}
 
 	bp = port_Board(port);
-	
+
 	spin_lock_irqsave(&port->lock, flags);
 	port->IER &= ~IER_TXRDY;
 	spin_lock_irqsave(&bp->lock, flags);
@@ -2261,14 +2259,14 @@
 	unsigned long flags;
 
 	func_enter();
-				
+
 	if (sx_paranoia_check(port, tty->name, "sx_start")) {
 		func_exit();
 		return;
 	}
-	
+
 	bp = port_Board(port);
-	
+
 	spin_lock_irqsave(&port->lock, flags);
 	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
@@ -2290,13 +2288,13 @@
  *
  * 	serial interrupt routine -> (workqueue) ->
  * 	do_sx_hangup() -> tty->hangup() -> sx_hangup()
- * 
+ *
  */
 static void do_sx_hangup(void *private_)
 {
 	struct specialix_port	*port = (struct specialix_port *) private_;
 	struct tty_struct	*tty;
-	
+
 	func_enter();
 
 	tty = port->tty;
@@ -2319,9 +2317,9 @@
 		func_exit();
 		return;
 	}
-	
+
 	bp = port_Board(port);
-	
+
 	sx_shutdown_port(bp, port);
 	spin_lock_irqsave(&port->lock, flags);
 	port->event = 0;
@@ -2346,10 +2344,10 @@
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	unsigned long flags;
 	struct specialix_board  * bp;
-				
+
 	if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
 		return;
-	
+
 	if (tty->termios->c_cflag == old_termios->c_cflag &&
 	    tty->termios->c_iflag == old_termios->c_iflag)
 		return;
@@ -2420,7 +2418,7 @@
 		func_exit();
 		return 1;
 	}
-	
+
 	if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
 		printk(KERN_ERR "sx: Couldn't get free page.\n");
 		put_tty_driver(specialix_driver);
@@ -2457,7 +2455,7 @@
 		init_waitqueue_head(&sx_port[i].close_wait);
 		spin_lock_init(&sx_port[i].lock);
 	}
-	
+
 	func_exit();
 	return 0;
 }
@@ -2472,8 +2470,8 @@
 	func_exit();
 }
 
-/* 
- * This routine must be called by kernel at boot time 
+/*
+ * This routine must be called by kernel at boot time
  */
 static int __init specialix_init(void)
 {
@@ -2489,7 +2487,7 @@
 #else
 	printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
 #endif
-	
+
 	for (i = 0; i < SX_NBOARD; i++)
 		sx_board[i].lock = SPIN_LOCK_UNLOCKED;
 
@@ -2498,7 +2496,7 @@
 		return -EIO;
 	}
 
-	for (i = 0; i < SX_NBOARD; i++) 
+	for (i = 0; i < SX_NBOARD; i++)
 		if (sx_board[i].base && !sx_probe(&sx_board[i]))
 			found++;
 
@@ -2512,8 +2510,8 @@
 				i++;
 				continue;
 			}
-			pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
-			                        PCI_DEVICE_ID_SPECIALIX_IO8, 
+			pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+			                        PCI_DEVICE_ID_SPECIALIX_IO8,
 			                        pdev);
 			if (!pdev) break;
 
@@ -2557,10 +2555,10 @@
 /*
  * You can setup up to 4 boards.
  * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
- * You should specify the IRQs too in that case "irq=....,...". 
- * 
+ * You should specify the IRQs too in that case "irq=....,...".
+ *
  * More than 4 boards in one computer is not possible, as the card can
- * only use 4 different interrupts. 
+ * only use 4 different interrupts.
  *
  */
 static int __init specialix_init_module(void)
@@ -2583,16 +2581,16 @@
 
 	return specialix_init();
 }
-	
+
 static void __exit specialix_exit_module(void)
 {
 	int i;
-	
+
 	func_enter();
 
 	sx_release_drivers();
 	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].flags & SX_BOARD_PRESENT) 
+		if (sx_board[i].flags & SX_BOARD_PRESENT)
 			sx_release_io_range(&sx_board[i]);
 #ifdef SPECIALIX_TIMER
 	del_timer (&missed_irq_timer);
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 951545a..1c68641 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -3095,7 +3095,9 @@
 		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 				S_IFCHR|S_IRUSR|S_IWUSR,
 				"staliomem/%d", i);
-		class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+		class_device_create(stallion_class, NULL,
+				    MKDEV(STL_SIOMEMMAJOR, i), NULL,
+				    "staliomem%d", i);
 	}
 
 	stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index ea2d54b..0133dc0 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -912,6 +912,7 @@
 MODULE_LICENSE("GPL");
 
 static struct pci_driver synclink_pci_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "synclink",
 	.id_table	= synclink_pci_tbl,
 	.probe		= synclink_init_one,
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 6fb165c..f185724 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -500,6 +500,7 @@
 MODULE_LICENSE("GPL");
 
 static struct pci_driver synclinkmp_pci_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "synclinkmp",
 	.id_table	= synclinkmp_pci_tbl,
 	.probe		= synclinkmp_init_one,
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index ec78d2f..41a94bc 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -436,7 +436,7 @@
 		goto out;
 	}
 
-	class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
+	class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
 			TIPAR_MINOR + nr), NULL, "par%d", nr);
 	/* Use devfs, tree: /dev/ticables/par/[0..2] */
 	err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
new file mode 100644
index 0000000..18cdd43
--- /dev/null
+++ b/drivers/char/tlclk.c
@@ -0,0 +1,896 @@
+/*
+ * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010
+ *
+ * Copyright (C) 2005 Kontron Canada
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * Send feedback to <sebastien.bouchard@ca.kontron.com> and the current
+ * Maintainer  <mark.gross@intel.com>
+ *
+ * Description : This is the TELECOM CLOCK module driver for the ATCA
+ * MPCBL0010 ATCA computer.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>	/* printk() */
+#include <linux/fs.h>		/* everything... */
+#include <linux/errno.h>	/* error codes */
+#include <linux/delay.h>	/* udelay */
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <asm/io.h>		/* inb/outb */
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>");
+MODULE_LICENSE("GPL");
+
+/*Hardware Reset of the PLL */
+#define RESET_ON	0x00
+#define RESET_OFF	0x01
+
+/* MODE SELECT */
+#define NORMAL_MODE 	0x00
+#define HOLDOVER_MODE	0x10
+#define FREERUN_MODE	0x20
+
+/* FILTER SELECT */
+#define FILTER_6HZ	0x04
+#define FILTER_12HZ	0x00
+
+/* SELECT REFERENCE FREQUENCY */
+#define REF_CLK1_8kHz		0x00
+#define REF_CLK2_19_44MHz	0x02
+
+/* Select primary or secondary redundant clock */
+#define PRIMARY_CLOCK	0x00
+#define SECONDARY_CLOCK	0x01
+
+/* CLOCK TRANSMISSION DEFINE */
+#define CLK_8kHz	0xff
+#define CLK_16_384MHz	0xfb
+
+#define CLK_1_544MHz	0x00
+#define CLK_2_048MHz	0x01
+#define CLK_4_096MHz	0x02
+#define CLK_6_312MHz	0x03
+#define CLK_8_192MHz	0x04
+#define CLK_19_440MHz	0x06
+
+#define CLK_8_592MHz	0x08
+#define CLK_11_184MHz	0x09
+#define CLK_34_368MHz	0x0b
+#define CLK_44_736MHz	0x0a
+
+/* RECEIVED REFERENCE */
+#define AMC_B1 0
+#define AMC_B2 1
+
+/* HARDWARE SWITCHING DEFINE */
+#define HW_ENABLE	0x80
+#define HW_DISABLE	0x00
+
+/* HARDWARE SWITCHING MODE DEFINE */
+#define PLL_HOLDOVER	0x40
+#define LOST_CLOCK	0x00
+
+/* ALARMS DEFINE */
+#define UNLOCK_MASK	0x10
+#define HOLDOVER_MASK	0x20
+#define SEC_LOST_MASK	0x40
+#define PRI_LOST_MASK	0x80
+
+/* INTERRUPT CAUSE DEFINE */
+
+#define PRI_LOS_01_MASK		0x01
+#define PRI_LOS_10_MASK		0x02
+
+#define SEC_LOS_01_MASK		0x04
+#define SEC_LOS_10_MASK		0x08
+
+#define HOLDOVER_01_MASK	0x10
+#define HOLDOVER_10_MASK	0x20
+
+#define UNLOCK_01_MASK		0x40
+#define UNLOCK_10_MASK		0x80
+
+struct tlclk_alarms {
+	__u32 lost_clocks;
+	__u32 lost_primary_clock;
+	__u32 lost_secondary_clock;
+	__u32 primary_clock_back;
+	__u32 secondary_clock_back;
+	__u32 switchover_primary;
+	__u32 switchover_secondary;
+	__u32 pll_holdover;
+	__u32 pll_end_holdover;
+	__u32 pll_lost_sync;
+	__u32 pll_sync;
+};
+/* Telecom clock I/O register definition */
+#define TLCLK_BASE 0xa08
+#define TLCLK_REG0 TLCLK_BASE
+#define TLCLK_REG1 (TLCLK_BASE+1)
+#define TLCLK_REG2 (TLCLK_BASE+2)
+#define TLCLK_REG3 (TLCLK_BASE+3)
+#define TLCLK_REG4 (TLCLK_BASE+4)
+#define TLCLK_REG5 (TLCLK_BASE+5)
+#define TLCLK_REG6 (TLCLK_BASE+6)
+#define TLCLK_REG7 (TLCLK_BASE+7)
+
+#define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port)
+
+/* 0 = Dynamic allocation of the major device number */
+#define TLCLK_MAJOR 0
+
+/* sysfs interface definition:
+Upon loading the driver will create a sysfs directory under
+/sys/devices/platform/telco_clock.
+
+This directory exports the following interfaces.  There operation is
+documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
+alarms				:
+current_ref			:
+enable_clk3a_output		:
+enable_clk3b_output		:
+enable_clka0_output		:
+enable_clka1_output		:
+enable_clkb0_output		:
+enable_clkb1_output		:
+filter_select			:
+hardware_switching		:
+hardware_switching_mode		:
+interrupt_switch		:
+mode_select			:
+refalign			:
+reset				:
+select_amcb1_transmit_clock	:
+select_amcb2_transmit_clock	:
+select_redundant_clock		:
+select_ref_frequency		:
+test_mode			:
+
+All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
+has the same effect as echo 0x99 > refalign.
+*/
+
+static unsigned int telclk_interrupt;
+
+static int int_events;		/* Event that generate a interrupt */
+static int got_event;		/* if events processing have been done */
+
+static void switchover_timeout(unsigned long data);
+static struct timer_list switchover_timer =
+	TIMER_INITIALIZER(switchover_timeout , 0, 0);
+
+static struct tlclk_alarms *alarm_events;
+
+static DEFINE_SPINLOCK(event_lock);
+
+static int tlclk_major = TLCLK_MAJOR;
+
+static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+static int tlclk_open(struct inode *inode, struct file *filp)
+{
+	int result;
+
+	/* Make sure there is no interrupt pending while
+	 * initialising interrupt handler */
+	inb(TLCLK_REG6);
+
+	/* This device is wired through the FPGA IO space of the ATCA blade
+	 * we can't share this IRQ */
+	result = request_irq(telclk_interrupt, &tlclk_interrupt,
+			     SA_INTERRUPT, "telco_clock", tlclk_interrupt);
+	if (result == -EBUSY) {
+		printk(KERN_ERR "telco_clock: Interrupt can't be reserved!\n");
+		return -EBUSY;
+	}
+	inb(TLCLK_REG6);	/* Clear interrupt events */
+
+	return 0;
+}
+
+static int tlclk_release(struct inode *inode, struct file *filp)
+{
+	free_irq(telclk_interrupt, tlclk_interrupt);
+
+	return 0;
+}
+
+ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
+		loff_t *f_pos)
+{
+	if (count < sizeof(struct tlclk_alarms))
+		return -EIO;
+
+	wait_event_interruptible(wq, got_event);
+	if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms)))
+		return -EFAULT;
+
+	memset(alarm_events, 0, sizeof(struct tlclk_alarms));
+	got_event = 0;
+
+	return  sizeof(struct tlclk_alarms);
+}
+
+ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
+	    loff_t *f_pos)
+{
+	return 0;
+}
+
+static struct file_operations tlclk_fops = {
+	.read = tlclk_read,
+	.write = tlclk_write,
+	.open = tlclk_open,
+	.release = tlclk_release,
+
+};
+
+static struct miscdevice tlclk_miscdev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "telco_clock",
+	.fops = &tlclk_fops,
+};
+
+static ssize_t show_current_ref(struct device *d,
+		struct device_attribute *attr, char *buf)
+{
+	unsigned long ret_val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&event_lock, flags);
+	ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return sprintf(buf, "0x%lX\n", ret_val);
+}
+
+static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
+
+
+static ssize_t show_interrupt_switch(struct device *d,
+		struct device_attribute *attr, char *buf)
+{
+	unsigned long ret_val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&event_lock, flags);
+	ret_val = inb(TLCLK_REG6);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return sprintf(buf, "0x%lX\n", ret_val);
+}
+
+static DEVICE_ATTR(interrupt_switch, S_IRUGO,
+		show_interrupt_switch, NULL);
+
+static ssize_t show_alarms(struct device *d,
+		struct device_attribute *attr,  char *buf)
+{
+	unsigned long ret_val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&event_lock, flags);
+	ret_val = (inb(TLCLK_REG2) & 0xf0);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return sprintf(buf, "0x%lX\n", ret_val);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static ssize_t store_enable_clk3b_output(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL,
+		store_enable_clk3b_output);
+
+static ssize_t store_enable_clk3a_output(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL,
+		store_enable_clk3a_output);
+
+static ssize_t store_enable_clkb1_output(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL,
+		store_enable_clkb1_output);
+
+
+static ssize_t store_enable_clka1_output(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL,
+		store_enable_clka1_output);
+
+static ssize_t store_enable_clkb0_output(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL,
+		store_enable_clkb0_output);
+
+static ssize_t store_enable_clka0_output(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
+		store_enable_clka0_output);
+
+static ssize_t store_test_mode(struct device *d,
+		struct device_attribute *attr,  const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG4, 0xfd, 2);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode);
+
+static ssize_t store_select_amcb2_transmit_clock(struct device *d,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long flags;
+	unsigned long tmp;
+	unsigned char val;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+		if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
+			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
+			SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
+		} else if (val >= CLK_8_592MHz) {
+			SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
+			switch (val) {
+			case CLK_8_592MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+				break;
+			case CLK_11_184MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
+				break;
+			case CLK_34_368MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
+				break;
+			case CLK_44_736MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+				break;
+			}
+		} else
+			SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
+
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL,
+	store_select_amcb2_transmit_clock);
+
+static ssize_t store_select_amcb1_transmit_clock(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+		if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
+			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
+			SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
+		} else if (val >= CLK_8_592MHz) {
+			SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
+			switch (val) {
+			case CLK_8_592MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+				break;
+			case CLK_11_184MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
+				break;
+			case CLK_34_368MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
+				break;
+			case CLK_44_736MHz:
+				SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+				break;
+			}
+		} else
+			SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL,
+		store_select_amcb1_transmit_clock);
+
+static ssize_t store_select_redundant_clock(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL,
+		store_select_redundant_clock);
+
+static ssize_t store_select_ref_frequency(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL,
+		store_select_ref_frequency);
+
+static ssize_t store_filter_select(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select);
+
+static ssize_t store_hardware_switching_mode(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL,
+		store_hardware_switching_mode);
+
+static ssize_t store_hardware_switching(struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL,
+		store_hardware_switching);
+
+static ssize_t store_refalign (struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
+	udelay(2);
+	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
+	udelay(2);
+	SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign);
+
+static ssize_t store_mode_select (struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select);
+
+static ssize_t store_reset (struct device *d,
+		 struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long tmp;
+	unsigned char val;
+	unsigned long flags;
+
+	sscanf(buf, "%lX", &tmp);
+	dev_dbg(d, "tmp = 0x%lX\n", tmp);
+
+	val = (unsigned char)tmp;
+	spin_lock_irqsave(&event_lock, flags);
+	SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
+
+static struct attribute *tlclk_sysfs_entries[] = {
+	&dev_attr_current_ref.attr,
+	&dev_attr_interrupt_switch.attr,
+	&dev_attr_alarms.attr,
+	&dev_attr_enable_clk3a_output.attr,
+	&dev_attr_enable_clk3b_output.attr,
+	&dev_attr_enable_clkb1_output.attr,
+	&dev_attr_enable_clka1_output.attr,
+	&dev_attr_enable_clkb0_output.attr,
+	&dev_attr_enable_clka0_output.attr,
+	&dev_attr_test_mode.attr,
+	&dev_attr_select_amcb1_transmit_clock.attr,
+	&dev_attr_select_amcb2_transmit_clock.attr,
+	&dev_attr_select_redundant_clock.attr,
+	&dev_attr_select_ref_frequency.attr,
+	&dev_attr_filter_select.attr,
+	&dev_attr_hardware_switching_mode.attr,
+	&dev_attr_hardware_switching.attr,
+	&dev_attr_refalign.attr,
+	&dev_attr_mode_select.attr,
+	&dev_attr_reset.attr,
+	NULL
+};
+
+static struct attribute_group tlclk_attribute_group = {
+	.name = NULL,		/* put in device directory */
+	.attrs = tlclk_sysfs_entries,
+};
+
+static struct platform_device *tlclk_device;
+
+static int __init tlclk_init(void)
+{
+	int ret;
+
+	ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
+	if (ret < 0) {
+		printk(KERN_ERR "telco_clock: can't get major! %d\n", tlclk_major);
+		return ret;
+	}
+	alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
+	if (!alarm_events)
+		goto out1;
+
+	/* Read telecom clock IRQ number (Set by BIOS) */
+	if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
+		printk(KERN_ERR "tlclk: request_region failed! 0x%X\n",
+			TLCLK_BASE);
+		ret = -EBUSY;
+		goto out2;
+	}
+	telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
+
+	if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
+		printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw\n",
+			telclk_interrupt);
+		ret = -ENXIO;
+		goto out3;
+	}
+
+	init_timer(&switchover_timer);
+
+	ret = misc_register(&tlclk_miscdev);
+	if (ret < 0) {
+		printk(KERN_ERR " misc_register retruns %d\n", ret);
+		ret = -EBUSY;
+		goto out3;
+	}
+
+	tlclk_device = platform_device_register_simple("telco_clock",
+				-1, NULL, 0);
+	if (!tlclk_device) {
+		printk(KERN_ERR " platform_device_register retruns 0x%X\n",
+			(unsigned int) tlclk_device);
+		ret = -EBUSY;
+		goto out4;
+	}
+
+	ret = sysfs_create_group(&tlclk_device->dev.kobj,
+			&tlclk_attribute_group);
+	if (ret) {
+		printk(KERN_ERR "failed to create sysfs device attributes\n");
+		sysfs_remove_group(&tlclk_device->dev.kobj,
+			&tlclk_attribute_group);
+		goto out5;
+	}
+
+	return 0;
+out5:
+	platform_device_unregister(tlclk_device);
+out4:
+	misc_deregister(&tlclk_miscdev);
+out3:
+	release_region(TLCLK_BASE, 8);
+out2:
+	kfree(alarm_events);
+out1:
+	unregister_chrdev(tlclk_major, "telco_clock");
+	return ret;
+}
+
+static void __exit tlclk_cleanup(void)
+{
+	sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group);
+	platform_device_unregister(tlclk_device);
+	misc_deregister(&tlclk_miscdev);
+	unregister_chrdev(tlclk_major, "telco_clock");
+
+	release_region(TLCLK_BASE, 8);
+	del_timer_sync(&switchover_timer);
+	kfree(alarm_events);
+
+}
+
+static void switchover_timeout(unsigned long data)
+{
+	if ((data & 1)) {
+		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+			alarm_events->switchover_primary++;
+	} else {
+		if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08))
+			alarm_events->switchover_secondary++;
+	}
+
+	/* Alarm processing is done, wake up read task */
+	del_timer(&switchover_timer);
+	got_event = 1;
+	wake_up(&wq);
+}
+
+static irqreturn_t tlclk_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&event_lock, flags);
+	/* Read and clear interrupt events */
+	int_events = inb(TLCLK_REG6);
+
+	/* Primary_Los changed from 0 to 1 ? */
+	if (int_events & PRI_LOS_01_MASK) {
+		if (inb(TLCLK_REG2) & SEC_LOST_MASK)
+			alarm_events->lost_clocks++;
+		else
+			alarm_events->lost_primary_clock++;
+	}
+
+	/* Primary_Los changed from 1 to 0 ? */
+	if (int_events & PRI_LOS_10_MASK) {
+		alarm_events->primary_clock_back++;
+		SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
+	}
+	/* Secondary_Los changed from 0 to 1 ? */
+	if (int_events & SEC_LOS_01_MASK) {
+		if (inb(TLCLK_REG2) & PRI_LOST_MASK)
+			alarm_events->lost_clocks++;
+		else
+			alarm_events->lost_secondary_clock++;
+	}
+	/* Secondary_Los changed from 1 to 0 ? */
+	if (int_events & SEC_LOS_10_MASK) {
+		alarm_events->secondary_clock_back++;
+		SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
+	}
+	if (int_events & HOLDOVER_10_MASK)
+		alarm_events->pll_end_holdover++;
+
+	if (int_events & UNLOCK_01_MASK)
+		alarm_events->pll_lost_sync++;
+
+	if (int_events & UNLOCK_10_MASK)
+		alarm_events->pll_sync++;
+
+	/* Holdover changed from 0 to 1 ? */
+	if (int_events & HOLDOVER_01_MASK) {
+		alarm_events->pll_holdover++;
+
+		/* TIMEOUT in ~10ms */
+		switchover_timer.expires = jiffies + msecs_to_jiffies(10);
+		switchover_timer.data = inb(TLCLK_REG1);
+		add_timer(&switchover_timer);
+	} else {
+		got_event = 1;
+		wake_up(&wq);
+	}
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+module_init(tlclk_init);
+module_exit(tlclk_cleanup);
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 049d128..303f158 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -64,7 +64,7 @@
 	if (count == 0)
 		return -ENODATA;
 	if (count > bufsiz) {
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"invalid count value %x %zx \n", count, bufsiz);
 		return -E2BIG;
 	}
@@ -72,21 +72,21 @@
 	down(&chip->tpm_mutex);
 
 	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"tpm_transmit: tpm_send: error %zd\n", rc);
 		goto out;
 	}
 
 	stop = jiffies + 2 * 60 * HZ;
 	do {
-		u8 status = inb(chip->vendor->base + 1);
+		u8 status = chip->vendor->status(chip);
 		if ((status & chip->vendor->req_complete_mask) ==
 		    chip->vendor->req_complete_val) {
 			goto out_recv;
 		}
 
 		if ((status == chip->vendor->req_canceled)) {
-			dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+			dev_err(chip->dev, "Operation Canceled\n");
 			rc = -ECANCELED;
 			goto out;
 		}
@@ -97,14 +97,14 @@
 
 
 	chip->vendor->cancel(chip);
-	dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+	dev_err(chip->dev, "Operation Timed out\n");
 	rc = -ETIME;
 	goto out;
 
 out_recv:
 	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
 	if (rc < 0)
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"tpm_transmit: tpm_recv: error %zd\n", rc);
 out:
 	up(&chip->tpm_mutex);
@@ -139,15 +139,14 @@
 	__be32 index;
 	char *str = buf;
 
-	struct tpm_chip *chip =
-	    pci_get_drvdata(to_pci_dev(dev));
+	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if (chip == NULL)
 		return -ENODEV;
 
 	memcpy(data, cap_pcr, sizeof(cap_pcr));
 	if ((len = tpm_transmit(chip, data, sizeof(data)))
 	    < CAP_PCR_RESULT_SIZE) {
-		dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+		dev_dbg(chip->dev, "A TPM error (%d) occurred "
 				"attempting to determine the number of PCRS\n",
 			be32_to_cpu(*((__be32 *) (data + 6))));
 		return 0;
@@ -161,9 +160,10 @@
 		memcpy(data + 10, &index, 4);
 		if ((len = tpm_transmit(chip, data, sizeof(data)))
 		    < READ_PCR_RESULT_SIZE){
-			dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
+			dev_dbg(chip->dev, "A TPM error (%d) occurred"
 				" attempting to read PCR %d of %d\n",
-				be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
+				be32_to_cpu(*((__be32 *) (data + 6))),
+				i, num_pcrs);
 			goto out;
 		}
 		str += sprintf(str, "PCR-%02d: ", i);
@@ -191,21 +191,19 @@
 	int i, rc;
 	char *str = buf;
 
-	struct tpm_chip *chip =
-	    pci_get_drvdata(to_pci_dev(dev));
+	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if (chip == NULL)
 		return -ENODEV;
 
-	data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+	data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	memcpy(data, readpubek, sizeof(readpubek));
-	memset(data + sizeof(readpubek), 0, 20);	/* zero nonce */
 
 	if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
 	    READ_PUBEK_RESULT_SIZE) {
-		dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+		dev_dbg(chip->dev, "A TPM error (%d) occurred "
 				"attempting to read the PUBEK\n",
 			    be32_to_cpu(*((__be32 *) (data + 6))));
 		rc = 0;
@@ -245,7 +243,6 @@
 	kfree(data);
 	return rc;
 }
-
 EXPORT_SYMBOL_GPL(tpm_show_pubek);
 
 #define CAP_VER_RESULT_SIZE 18
@@ -274,8 +271,7 @@
 	ssize_t len;
 	char *str = buf;
 
-	struct tpm_chip *chip =
-	    pci_get_drvdata(to_pci_dev(dev));
+	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if (chip == NULL)
 		return -ENODEV;
 
@@ -315,7 +311,6 @@
 }
 EXPORT_SYMBOL_GPL(tpm_store_cancel);
 
-
 /*
  * Device file system interface to the TPM
  */
@@ -339,21 +334,20 @@
 	}
 
 	if (chip->num_opens) {
-		dev_dbg(&chip->pci_dev->dev,
-			"Another process owns this TPM\n");
+		dev_dbg(chip->dev, "Another process owns this TPM\n");
 		rc = -EBUSY;
 		goto err_out;
 	}
 
 	chip->num_opens++;
-	pci_dev_get(chip->pci_dev);
+	get_device(chip->dev);
 
 	spin_unlock(&driver_lock);
 
 	chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
 	if (chip->data_buffer == NULL) {
 		chip->num_opens--;
-		pci_dev_put(chip->pci_dev);
+		put_device(chip->dev);
 		return -ENOMEM;
 	}
 
@@ -366,7 +360,6 @@
 	spin_unlock(&driver_lock);
 	return rc;
 }
-
 EXPORT_SYMBOL_GPL(tpm_open);
 
 int tpm_release(struct inode *inode, struct file *file)
@@ -378,15 +371,14 @@
 	chip->num_opens--;
 	del_singleshot_timer_sync(&chip->user_read_timer);
 	atomic_set(&chip->data_pending, 0);
-	pci_dev_put(chip->pci_dev);
+	put_device(chip->dev);
 	kfree(chip->data_buffer);
 	spin_unlock(&driver_lock);
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(tpm_release);
 
-ssize_t tpm_write(struct file * file, const char __user * buf,
+ssize_t tpm_write(struct file *file, const char __user *buf,
 		  size_t size, loff_t * off)
 {
 	struct tpm_chip *chip = file->private_data;
@@ -422,7 +414,7 @@
 
 EXPORT_SYMBOL_GPL(tpm_write);
 
-ssize_t tpm_read(struct file * file, char __user * buf,
+ssize_t tpm_read(struct file * file, char __user *buf,
 		 size_t size, loff_t * off)
 {
 	struct tpm_chip *chip = file->private_data;
@@ -444,15 +436,14 @@
 
 	return ret_size;
 }
-
 EXPORT_SYMBOL_GPL(tpm_read);
 
-void __devexit tpm_remove(struct pci_dev *pci_dev)
+void tpm_remove_hardware(struct device *dev)
 {
-	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+	struct tpm_chip *chip = dev_get_drvdata(dev);
 
 	if (chip == NULL) {
-		dev_err(&pci_dev->dev, "No device data found\n");
+		dev_err(dev, "No device data found\n");
 		return;
 	}
 
@@ -462,22 +453,20 @@
 
 	spin_unlock(&driver_lock);
 
-	pci_set_drvdata(pci_dev, NULL);
+	dev_set_drvdata(dev, NULL);
 	misc_deregister(&chip->vendor->miscdev);
 	kfree(chip->vendor->miscdev.name);
 
-	sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
+	sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
 
-	pci_disable_device(pci_dev);
-
-	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
+		!(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
 
 	kfree(chip);
 
-	pci_dev_put(pci_dev);
+	put_device(dev);
 }
-
-EXPORT_SYMBOL_GPL(tpm_remove);
+EXPORT_SYMBOL_GPL(tpm_remove_hardware);
 
 static u8 savestate[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
@@ -489,32 +478,30 @@
  * We are about to suspend. Save the TPM state
  * so that it can be restored.
  */
-int tpm_pm_suspend(struct pci_dev *pci_dev, pm_message_t pm_state)
+int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
 {
-	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if (chip == NULL)
 		return -ENODEV;
 
 	tpm_transmit(chip, savestate, sizeof(savestate));
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(tpm_pm_suspend);
 
 /*
  * Resume from a power safe. The BIOS already restored
  * the TPM state.
  */
-int tpm_pm_resume(struct pci_dev *pci_dev)
+int tpm_pm_resume(struct device *dev)
 {
-	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+	struct tpm_chip *chip = dev_get_drvdata(dev);
 
 	if (chip == NULL)
 		return -ENODEV;
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
 /*
@@ -524,8 +511,7 @@
  * upon errant exit from this function specific probe function should call
  * pci_disable_device
  */
-int tpm_register_hardware(struct pci_dev *pci_dev,
-			  struct tpm_vendor_specific *entry)
+int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
 {
 #define DEVNAME_SIZE 7
 
@@ -534,12 +520,10 @@
 	int i, j;
 
 	/* Driver specific per-device data */
-	chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
-	memset(chip, 0, sizeof(struct tpm_chip));
-
 	init_MUTEX(&chip->buffer_mutex);
 	init_MUTEX(&chip->tpm_mutex);
 	INIT_LIST_HEAD(&chip->list);
@@ -563,8 +547,7 @@
 
 dev_num_search_complete:
 	if (chip->dev_num < 0) {
-		dev_err(&pci_dev->dev,
-			"No available tpm device numbers\n");
+		dev_err(dev, "No available tpm device numbers\n");
 		kfree(chip);
 		return -ENODEV;
 	} else if (chip->dev_num == 0)
@@ -576,15 +559,15 @@
 	scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
 	chip->vendor->miscdev.name = devname;
 
-	chip->vendor->miscdev.dev = &(pci_dev->dev);
-	chip->pci_dev = pci_dev_get(pci_dev);
+	chip->vendor->miscdev.dev = dev;
+	chip->dev = get_device(dev);
 
 	if (misc_register(&chip->vendor->miscdev)) {
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"unable to misc_register %s, minor %d\n",
 			chip->vendor->miscdev.name,
 			chip->vendor->miscdev.minor);
-		pci_dev_put(pci_dev);
+		put_device(dev);
 		kfree(chip);
 		dev_mask[i] &= !(1 << j);
 		return -ENODEV;
@@ -592,17 +575,16 @@
 
 	spin_lock(&driver_lock);
 
-	pci_set_drvdata(pci_dev, chip);
+	dev_set_drvdata(dev, chip);
 
 	list_add(&chip->list, &tpm_chip_list);
 
 	spin_unlock(&driver_lock);
 
-	sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
+	sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(tpm_register_hardware);
 
 MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 373b41f..024814b 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -55,12 +55,13 @@
 	int (*recv) (struct tpm_chip *, u8 *, size_t);
 	int (*send) (struct tpm_chip *, u8 *, size_t);
 	void (*cancel) (struct tpm_chip *);
+	u8 (*status) (struct tpm_chip *);
 	struct miscdevice miscdev;
 	struct attribute_group *attr_group;
 };
 
 struct tpm_chip {
-	struct pci_dev *pci_dev;	/* PCI device stuff */
+	struct device *dev;	/* Device stuff */
 
 	int dev_num;		/* /dev/tpm# */
 	int num_opens;		/* only one allowed */
@@ -91,13 +92,13 @@
 	outb(value & 0xFF, base+1);
 }
 
-extern int tpm_register_hardware(struct pci_dev *,
+extern int tpm_register_hardware(struct device *,
 				 struct tpm_vendor_specific *);
 extern int tpm_open(struct inode *, struct file *);
 extern int tpm_release(struct inode *, struct file *);
 extern ssize_t tpm_write(struct file *, const char __user *, size_t,
 			 loff_t *);
 extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
-extern void __devexit tpm_remove(struct pci_dev *);
-extern int tpm_pm_suspend(struct pci_dev *, pm_message_t);
-extern int tpm_pm_resume(struct pci_dev *);
+extern void tpm_remove_hardware(struct device *);
+extern int tpm_pm_suspend(struct device *, pm_message_t);
+extern int tpm_pm_resume(struct device *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index c0d6491..8cb42e8 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -40,7 +40,7 @@
 	ATML_STATUS_READY = 0x08
 };
 
-static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 {
 	u8 status, *hdr = buf;
 	u32 size;
@@ -54,7 +54,7 @@
 	for (i = 0; i < 6; i++) {
 		status = inb(chip->vendor->base + 1);
 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
-			dev_err(&chip->pci_dev->dev,
+			dev_err(chip->dev,
 				"error reading header\n");
 			return -EIO;
 		}
@@ -66,12 +66,12 @@
 	size = be32_to_cpu(*native_size);
 
 	if (count < size) {
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"Recv size(%d) less than available space\n", size);
 		for (; i < size; i++) {	/* clear the waiting data anyway */
 			status = inb(chip->vendor->base + 1);
 			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
-				dev_err(&chip->pci_dev->dev,
+				dev_err(chip->dev,
 					"error reading data\n");
 				return -EIO;
 			}
@@ -83,7 +83,7 @@
 	for (; i < size; i++) {
 		status = inb(chip->vendor->base + 1);
 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
-			dev_err(&chip->pci_dev->dev,
+			dev_err(chip->dev,
 				"error reading data\n");
 			return -EIO;
 		}
@@ -93,20 +93,20 @@
 	/* make sure data available is gone */
 	status = inb(chip->vendor->base + 1);
 	if (status & ATML_STATUS_DATA_AVAIL) {
-		dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+		dev_err(chip->dev, "data available is stuck\n");
 		return -EIO;
 	}
 
 	return size;
 }
 
-static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
 	int i;
 
-	dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+	dev_dbg(chip->dev, "tpm_atml_send:\n");
 	for (i = 0; i < count; i++) {
-		dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+		dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
 		outb(buf[i], chip->vendor->base);
 	}
 
@@ -118,6 +118,11 @@
 	outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
 }
 
+static u8 tpm_atml_status(struct tpm_chip *chip)
+{
+	return inb(chip->vendor->base + 1);
+}
+
 static struct file_operations atmel_ops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
@@ -137,7 +142,7 @@
 	&dev_attr_pcrs.attr,
 	&dev_attr_caps.attr,
 	&dev_attr_cancel.attr,
-	0,
+	NULL,
 };
 
 static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
@@ -146,6 +151,7 @@
 	.recv = tpm_atml_recv,
 	.send = tpm_atml_send,
 	.cancel = tpm_atml_cancel,
+	.status = tpm_atml_status,
 	.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
 	.req_complete_val = ATML_STATUS_DATA_AVAIL,
 	.req_canceled = ATML_STATUS_READY,
@@ -153,86 +159,94 @@
 	.miscdev = { .fops = &atmel_ops, },
 };
 
-static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
-				   const struct pci_device_id *pci_id)
+static struct platform_device *pdev;
+
+static void __devexit tpm_atml_remove(struct device *dev)
 {
-	u8 version[4];
-	int rc = 0;
-	int lo, hi;
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-
-	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
-	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
-
-	tpm_atmel.base = (hi<<8)|lo;
-	dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
-
-	/* verify that it is an Atmel part */
-	if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
-	    || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
-		rc = -ENODEV;
-		goto out_err;
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip) {
+		release_region(chip->vendor->base, 2);
+		tpm_remove_hardware(chip->dev);
 	}
-
-	/* query chip for its version number */
-	if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
-		version[1] = tpm_read_index(TPM_ADDR, 0x01);
-		version[2] = tpm_read_index(TPM_ADDR, 0x02);
-		version[3] = tpm_read_index(TPM_ADDR, 0x03);
-	} else {
-		dev_info(&pci_dev->dev, "version query failed\n");
-		rc = -ENODEV;
-		goto out_err;
-	}
-
-	if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
-		goto out_err;
-
-	dev_info(&pci_dev->dev,
-		 "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
-		 version[2], version[3]);
-
-	return 0;
-out_err:
-	pci_disable_device(pci_dev);
-	return rc;
 }
 
-static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
-	{PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
-
-static struct pci_driver atmel_pci_driver = {
+static struct device_driver atml_drv = {
 	.name = "tpm_atmel",
-	.id_table = tpm_pci_tbl,
-	.probe = tpm_atml_init,
-	.remove = __devexit_p(tpm_remove),
+	.bus = &platform_bus_type,
+	.owner = THIS_MODULE,
 	.suspend = tpm_pm_suspend,
 	.resume = tpm_pm_resume,
 };
 
 static int __init init_atmel(void)
 {
-	return pci_register_driver(&atmel_pci_driver);
+	int rc = 0;
+	int lo, hi;
+
+	driver_register(&atml_drv);
+
+	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+
+	tpm_atmel.base = (hi<<8)|lo;
+
+	/* verify that it is an Atmel part */
+	if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
+	    || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
+		return -ENODEV;
+	}
+
+	/* verify chip version number is 1.1 */
+	if (	(tpm_read_index(TPM_ADDR, 0x00) != 0x01) ||
+		(tpm_read_index(TPM_ADDR, 0x01) != 0x01 ))
+		return -ENODEV;
+
+	pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+	if ( !pdev )
+		return -ENOMEM;
+
+	pdev->name = "tpm_atmel0";
+	pdev->id = -1;
+	pdev->num_resources = 0;
+	pdev->dev.release = tpm_atml_remove;
+	pdev->dev.driver = &atml_drv;
+
+	if ((rc = platform_device_register(pdev)) < 0) {
+		kfree(pdev);
+		pdev = NULL;
+		return rc;
+	}
+
+	if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) {
+		platform_device_unregister(pdev);
+		kfree(pdev);
+		pdev = NULL;
+		return -EBUSY;
+	}
+
+	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) {
+		release_region(tpm_atmel.base, 2);
+		platform_device_unregister(pdev);
+		kfree(pdev);
+		pdev = NULL;
+		return rc;
+	}
+
+	dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n",
+			tpm_atmel.base);
+	return 0;
 }
 
 static void __exit cleanup_atmel(void)
 {
-	pci_unregister_driver(&atmel_pci_driver);
+	if (pdev) {
+		tpm_atml_remove(&pdev->dev);
+		platform_device_unregister(pdev);
+		kfree(pdev);
+		pdev = NULL;
+	}
+
+	driver_unregister(&atml_drv);
 }
 
 module_init(init_atmel);
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 939e51e..8198dbb 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -5,6 +5,7 @@
  * Specifications at www.trustedcomputinggroup.org
  *
  * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
+ * Sirrix AG - security technologies, http://www.sirrix.com and
  * Applied Data Security Group, Ruhr-University Bochum, Germany
  * Project-Homepage: http://www.prosec.rub.de/tpm
  *
@@ -29,9 +30,10 @@
 #define	TPM_INFINEON_DEV_VEN_VALUE	0x15D1
 
 /* These values will be filled after PnP-call */
-static int TPM_INF_DATA = 0;
-static int TPM_INF_ADDR = 0;
-static int pnp_registered = 0;
+static int TPM_INF_DATA;
+static int TPM_INF_ADDR;
+static int TPM_INF_BASE;
+static int TPM_INF_PORT_LEN;
 
 /* TPM header definitions */
 enum infineon_tpm_header {
@@ -143,11 +145,9 @@
 	}
 	if (i == TPM_MAX_TRIES) {	/* timeout occurs */
 		if (wait_for_bit == STAT_XFE)
-			dev_err(&chip->pci_dev->dev,
-				"Timeout in wait(STAT_XFE)\n");
+			dev_err(chip->dev, "Timeout in wait(STAT_XFE)\n");
 		if (wait_for_bit == STAT_RDA)
-			dev_err(&chip->pci_dev->dev,
-				"Timeout in wait(STAT_RDA)\n");
+			dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n");
 		return -EIO;
 	}
 	return 0;
@@ -170,7 +170,7 @@
 static void tpm_wtx(struct tpm_chip *chip)
 {
 	number_of_wtx++;
-	dev_info(&chip->pci_dev->dev, "Granting WTX (%02d / %02d)\n",
+	dev_info(chip->dev, "Granting WTX (%02d / %02d)\n",
 		 number_of_wtx, TPM_MAX_WTX_PACKAGES);
 	wait_and_send(chip, TPM_VL_VER);
 	wait_and_send(chip, TPM_CTRL_WTX);
@@ -181,7 +181,7 @@
 
 static void tpm_wtx_abort(struct tpm_chip *chip)
 {
-	dev_info(&chip->pci_dev->dev, "Aborting WTX\n");
+	dev_info(chip->dev, "Aborting WTX\n");
 	wait_and_send(chip, TPM_VL_VER);
 	wait_and_send(chip, TPM_CTRL_WTX_ABORT);
 	wait_and_send(chip, 0x00);
@@ -206,7 +206,7 @@
 	}
 
 	if (buf[0] != TPM_VL_VER) {
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"Wrong transport protocol implementation!\n");
 		return -EIO;
 	}
@@ -221,8 +221,7 @@
 		}
 
 		if ((size == 0x6D00) && (buf[1] == 0x80)) {
-			dev_err(&chip->pci_dev->dev,
-				"Error handling on vendor layer!\n");
+			dev_err(chip->dev, "Error handling on vendor layer!\n");
 			return -EIO;
 		}
 
@@ -234,7 +233,7 @@
 	}
 
 	if (buf[1] == TPM_CTRL_WTX) {
-		dev_info(&chip->pci_dev->dev, "WTX-package received\n");
+		dev_info(chip->dev, "WTX-package received\n");
 		if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
 			tpm_wtx(chip);
 			goto recv_begin;
@@ -245,14 +244,14 @@
 	}
 
 	if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
-		dev_info(&chip->pci_dev->dev, "WTX-abort acknowledged\n");
+		dev_info(chip->dev, "WTX-abort acknowledged\n");
 		return size;
 	}
 
 	if (buf[1] == TPM_CTRL_ERROR) {
-		dev_err(&chip->pci_dev->dev, "ERROR-package received:\n");
+		dev_err(chip->dev, "ERROR-package received:\n");
 		if (buf[4] == TPM_INF_NAK)
-			dev_err(&chip->pci_dev->dev,
+			dev_err(chip->dev,
 				"-> Negative acknowledgement"
 				" - retransmit command!\n");
 		return -EIO;
@@ -271,7 +270,7 @@
 
 	ret = empty_fifo(chip, 1);
 	if (ret) {
-		dev_err(&chip->pci_dev->dev, "Timeout while clearing FIFO\n");
+		dev_err(chip->dev, "Timeout while clearing FIFO\n");
 		return -EIO;
 	}
 
@@ -316,6 +315,11 @@
 	 */
 }
 
+static u8 tpm_inf_status(struct tpm_chip *chip)
+{
+	return inb(chip->vendor->base + STAT);
+}
+
 static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
 static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
 static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
@@ -344,6 +348,7 @@
 	.recv = tpm_inf_recv,
 	.send = tpm_inf_send,
 	.cancel = tpm_inf_cancel,
+	.status = tpm_inf_status,
 	.req_complete_mask = 0,
 	.req_complete_val = 0,
 	.attr_group = &inf_attr_grp,
@@ -356,30 +361,11 @@
 	{"IFX0102", 0},
 	{"", 0}
 };
+
 MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
 
 static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
-					const struct pnp_device_id *dev_id)
-{
-	if (pnp_port_valid(dev, 0)) {
-		TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff);
-		TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff);
-		tpm_inf.base = pnp_port_start(dev, 1);
-		dev_info(&dev->dev, "Found %s with ID %s\n",
-		dev->name, dev_id->id);
-		return 0;
-	}
-	return -ENODEV;
-}
-
-static struct pnp_driver tpm_inf_pnp = {
-	.name = "tpm_inf_pnp",
-	.id_table = tpm_pnp_tbl,
-	.probe = tpm_inf_pnp_probe,
-};
-
-static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
-				   const struct pci_device_id *pci_id)
+				       const struct pnp_device_id *dev_id)
 {
 	int rc = 0;
 	u8 iol, ioh;
@@ -388,30 +374,28 @@
 	int productid[2];
 	char chipname[20];
 
-	rc = pci_enable_device(pci_dev);
-	if (rc)
-		return rc;
-
-	dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
-
-	/* read IO-ports from PnP */
-	rc = pnp_register_driver(&tpm_inf_pnp);
-	if (rc < 0) {
-		dev_err(&pci_dev->dev,
-			"Error %x from pnp_register_driver!\n",rc);
-		goto error2;
-	}
-	if (!rc) {
-		dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
-		goto error;
+	/* read IO-ports through PnP */
+	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+	    !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
+		TPM_INF_ADDR = pnp_port_start(dev, 0);
+		TPM_INF_DATA = (TPM_INF_ADDR + 1);
+		TPM_INF_BASE = pnp_port_start(dev, 1);
+		TPM_INF_PORT_LEN = pnp_port_len(dev, 1);
+		if (!TPM_INF_PORT_LEN)
+			return -EINVAL;
+		dev_info(&dev->dev, "Found %s with ID %s\n",
+			 dev->name, dev_id->id);
+		if (!((TPM_INF_BASE >> 8) & 0xff))
+			return -EINVAL;
+		/* publish my base address and request region */
+		tpm_inf.base = TPM_INF_BASE;
+		if (request_region
+		    (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+			release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+			return -EINVAL;
+		}
 	} else {
-		pnp_registered = 1;
-	}
-
-	/* Make sure, we have received valid config ports */
-	if (!TPM_INF_ADDR) {
-		dev_err(&pci_dev->dev, "No valid IO-ports received!\n");
-		goto error;
+		return -EINVAL;
 	}
 
 	/* query chip for its vendor, its version number a.s.o. */
@@ -443,10 +427,6 @@
 
 	if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
 
-		if (tpm_inf.base == 0) {
-			dev_err(&pci_dev->dev, "No IO-ports found!\n");
-			goto error;
-		}
 		/* configure TPM with IO-ports */
 		outb(IOLIMH, TPM_INF_ADDR);
 		outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
@@ -460,10 +440,11 @@
 		iol = inb(TPM_INF_DATA);
 
 		if ((ioh << 8 | iol) != tpm_inf.base) {
-			dev_err(&pci_dev->dev,
+			dev_err(&dev->dev,
 				"Could not set IO-ports to %04x\n",
 				tpm_inf.base);
-			goto error;
+			release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+			return -EIO;
 		}
 
 		/* activate register */
@@ -475,7 +456,7 @@
 		outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
 
 		/* Finally, we're done, print some infos */
-		dev_info(&pci_dev->dev, "TPM found: "
+		dev_info(&dev->dev, "TPM found: "
 			 "config base 0x%x, "
 			 "io base 0x%x, "
 			 "chip version %02x%02x, "
@@ -483,59 +464,53 @@
 			 "product id %02x%02x"
 			 "%s\n",
 			 TPM_INF_ADDR,
-			 tpm_inf.base,
+			 TPM_INF_BASE,
 			 version[0], version[1],
 			 vendorid[0], vendorid[1],
 			 productid[0], productid[1], chipname);
 
-		rc = tpm_register_hardware(pci_dev, &tpm_inf);
-		if (rc < 0)
-			goto error;
+		rc = tpm_register_hardware(&dev->dev, &tpm_inf);
+		if (rc < 0) {
+			release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+			return -ENODEV;
+		}
 		return 0;
 	} else {
-		dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
-error:
-		pnp_unregister_driver(&tpm_inf_pnp);
-error2:
-		pci_disable_device(pci_dev);
-		pnp_registered = 0;
+		dev_info(&dev->dev, "No Infineon TPM found!\n");
 		return -ENODEV;
 	}
 }
 
-static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)},
-	{0,}
-};
+static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
+{
+	struct tpm_chip *chip = pnp_get_drvdata(dev);
 
-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+	if (chip) {
+		release_region(chip->vendor->base, TPM_INF_PORT_LEN);
+		tpm_remove_hardware(chip->dev);
+	}
+}
 
-static struct pci_driver inf_pci_driver = {
-	.name = "tpm_inf",
-	.id_table = tpm_pci_tbl,
-	.probe = tpm_inf_probe,
-	.remove = __devexit_p(tpm_remove),
-	.suspend = tpm_pm_suspend,
-	.resume = tpm_pm_resume,
+static struct pnp_driver tpm_inf_pnp = {
+	.name = "tpm_inf_pnp",
+	.driver = {
+		.owner = THIS_MODULE,
+		.suspend = tpm_pm_suspend,
+		.resume = tpm_pm_resume,
+	},
+	.id_table = tpm_pnp_tbl,
+	.probe = tpm_inf_pnp_probe,
+	.remove = tpm_inf_pnp_remove,
 };
 
 static int __init init_inf(void)
 {
-	return pci_register_driver(&inf_pci_driver);
+	return pnp_register_driver(&tpm_inf_pnp);
 }
 
 static void __exit cleanup_inf(void)
 {
-	if (pnp_registered)
-		pnp_unregister_driver(&tpm_inf_pnp);
-	pci_unregister_driver(&inf_pci_driver);
+	pnp_unregister_driver(&tpm_inf_pnp);
 }
 
 module_init(init_inf);
@@ -543,5 +518,5 @@
 
 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.5");
+MODULE_VERSION("1.6");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index b412734..253871b 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -111,7 +111,7 @@
 	}
 	while (time_before(jiffies, stop));
 
-	dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+	dev_info(chip->dev, "wait for ready failed\n");
 	return -EBUSY;
 }
 
@@ -127,12 +127,12 @@
 		return -EIO;
 
 	if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
-		dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+		dev_err(chip->dev, "F0 timeout\n");
 		return -EIO;
 	}
 	if ((data =
 	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
-		dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+		dev_err(chip->dev, "not in normal mode (0x%x)\n",
 			data);
 		return -EIO;
 	}
@@ -141,7 +141,7 @@
 	for (p = buffer; p < &buffer[count]; p++) {
 		if (wait_for_stat
 		    (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
-			dev_err(&chip->pci_dev->dev,
+			dev_err(chip->dev,
 				"OBF timeout (while reading data)\n");
 			return -EIO;
 		}
@@ -152,11 +152,11 @@
 
 	if ((data & NSC_STATUS_F0) == 0 &&
 	(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
-		dev_err(&chip->pci_dev->dev, "F0 not set\n");
+		dev_err(chip->dev, "F0 not set\n");
 		return -EIO;
 	}
 	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
-		dev_err(&chip->pci_dev->dev,
+		dev_err(chip->dev,
 			"expected end of command(0x%x)\n", data);
 		return -EIO;
 	}
@@ -187,19 +187,19 @@
 		return -EIO;
 
 	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
-		dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+		dev_err(chip->dev, "IBF timeout\n");
 		return -EIO;
 	}
 
 	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
 	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
-		dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+		dev_err(chip->dev, "IBR timeout\n");
 		return -EIO;
 	}
 
 	for (i = 0; i < count; i++) {
 		if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
-			dev_err(&chip->pci_dev->dev,
+			dev_err(chip->dev,
 				"IBF timeout (while writing data)\n");
 			return -EIO;
 		}
@@ -207,7 +207,7 @@
 	}
 
 	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
-		dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+		dev_err(chip->dev, "IBF timeout\n");
 		return -EIO;
 	}
 	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
@@ -220,6 +220,11 @@
 	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
 }
 
+static u8 tpm_nsc_status(struct tpm_chip *chip)
+{
+	return inb(chip->vendor->base + NSC_STATUS);
+}
+
 static struct file_operations nsc_ops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
@@ -239,7 +244,7 @@
 	&dev_attr_pcrs.attr,
 	&dev_attr_caps.attr,
 	&dev_attr_cancel.attr,
-	0,
+	NULL,
 };
 
 static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
@@ -248,6 +253,7 @@
 	.recv = tpm_nsc_recv,
 	.send = tpm_nsc_send,
 	.cancel = tpm_nsc_cancel,
+	.status = tpm_nsc_status,
 	.req_complete_mask = NSC_STATUS_OBF,
 	.req_complete_val = NSC_STATUS_OBF,
 	.req_canceled = NSC_STATUS_RDY,
@@ -255,16 +261,32 @@
 	.miscdev = { .fops = &nsc_ops, },
 };
 
-static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
-				  const struct pci_device_id *pci_id)
+static struct platform_device *pdev = NULL;
+
+static void __devexit tpm_nsc_remove(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if ( chip ) {
+		release_region(chip->vendor->base, 2);
+		tpm_remove_hardware(chip->dev);
+	}
+}
+
+static struct device_driver nsc_drv = {
+	.name = "tpm_nsc",
+	.bus = &platform_bus_type,
+	.owner = THIS_MODULE,
+	.suspend = tpm_pm_suspend,
+	.resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
 {
 	int rc = 0;
 	int lo, hi;
 	int nscAddrBase = TPM_ADDR;
 
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
+	driver_register(&nsc_drv);
 
 	/* select PM channel 1 */
 	tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
@@ -273,37 +295,71 @@
 	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
 		nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
 			(tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
-		if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
-			rc = -ENODEV;
-			goto out_err;
-		}
+		if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6)
+			return -ENODEV;
 	}
 
 	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
 	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
 	tpm_nsc.base = (hi<<8) | lo;
 
-	dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
-	dev_dbg(&pci_dev->dev,
+	/* enable the DPM module */
+	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
+
+	pdev = kmalloc(sizeof(struct platform_device), GFP_KERNEL);
+	if ( !pdev )
+		return -ENOMEM;
+
+	memset(pdev, 0, sizeof(struct platform_device));
+
+	pdev->name = "tpm_nscl0";
+	pdev->id = -1;
+	pdev->num_resources = 0;
+	pdev->dev.release = tpm_nsc_remove;
+	pdev->dev.driver = &nsc_drv;
+
+	if ((rc=platform_device_register(pdev)) < 0) {
+		kfree(pdev);
+		pdev = NULL;
+		return rc;
+	}
+
+	if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+		platform_device_unregister(pdev);
+		kfree(pdev);
+		pdev = NULL;
+		return -EBUSY;
+	}
+
+	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) {
+		release_region(tpm_nsc.base, 2);
+		platform_device_unregister(pdev);
+		kfree(pdev);
+		pdev = NULL;
+		return rc;
+	}
+
+	dev_dbg(&pdev->dev, "NSC TPM detected\n");
+	dev_dbg(&pdev->dev,
 		"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
 		tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
 		tpm_read_index(nscAddrBase,0x27));
-	dev_dbg(&pci_dev->dev,
+	dev_dbg(&pdev->dev,
 		"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
 		tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
 		tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
-	dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+	dev_dbg(&pdev->dev, "NSC IO Base0 0x%x\n",
 		(tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
-	dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+	dev_dbg(&pdev->dev, "NSC IO Base1 0x%x\n",
 		(tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
-	dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+	dev_dbg(&pdev->dev, "NSC Interrupt number and wakeup 0x%x\n",
 		tpm_read_index(nscAddrBase,0x70));
-	dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+	dev_dbg(&pdev->dev, "NSC IRQ type select 0x%x\n",
 		tpm_read_index(nscAddrBase,0x71));
-	dev_dbg(&pci_dev->dev,
+	dev_dbg(&pdev->dev,
 		"NSC DMA channel select0 0x%x, select1 0x%x\n",
 		tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
-	dev_dbg(&pci_dev->dev,
+	dev_dbg(&pdev->dev,
 		"NSC Config "
 		"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
 		tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
@@ -312,55 +368,23 @@
 		tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
 		tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
 
-	dev_info(&pci_dev->dev,
+	dev_info(&pdev->dev,
 		 "NSC TPM revision %d\n",
 		 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
 
-	/* enable the DPM module */
-	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
-
-	if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
-		goto out_err;
-
 	return 0;
-
-out_err:
-	pci_disable_device(pci_dev);
-	return rc;
-}
-
-static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
-
-static struct pci_driver nsc_pci_driver = {
-	.name = "tpm_nsc",
-	.id_table = tpm_pci_tbl,
-	.probe = tpm_nsc_init,
-	.remove = __devexit_p(tpm_remove),
-	.suspend = tpm_pm_suspend,
-	.resume = tpm_pm_resume,
-};
-
-static int __init init_nsc(void)
-{
-	return pci_register_driver(&nsc_pci_driver);
 }
 
 static void __exit cleanup_nsc(void)
 {
-	pci_unregister_driver(&nsc_pci_driver);
+	if (pdev) {
+		tpm_nsc_remove(&pdev->dev);
+		platform_device_unregister(pdev);
+		kfree(pdev);
+		pdev = NULL;
+	}
+
+	driver_unregister(&nsc_drv);
 }
 
 module_init(init_nsc);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index e5953f3..c586bfa 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -809,7 +809,7 @@
 	check_tty_count(tty, "do_tty_hangup");
 	file_list_lock();
 	/* This breaks for file handles being sent over AF_UNIX sockets ? */
-	list_for_each_entry(filp, &tty->tty_files, f_list) {
+	list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
 		if (filp->f_op->write == redirected_tty_write)
 			cons_filp = filp;
 		if (filp->f_op->write != tty_write)
@@ -2728,7 +2728,7 @@
 		pty_line_name(driver, index, name);
 	else
 		tty_line_name(driver, index, name);
-	class_device_create(tty_class, dev, device, name);
+	class_device_create(tty_class, NULL, dev, device, "%s", name);
 }
 
 /**
@@ -2983,14 +2983,14 @@
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
 		panic("Couldn't register /dev/tty driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
-	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
 
 	cdev_init(&console_cdev, &console_fops);
 	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
 		panic("Couldn't register /dev/console driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
-	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
 
 #ifdef CONFIG_UNIX98_PTYS
 	cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2998,7 +2998,7 @@
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
-	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 #endif
 
 #ifdef CONFIG_VT
@@ -3007,7 +3007,7 @@
 	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
 	devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
-	class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+	class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
 
 	vty_init();
 #endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 79c2928..f66c7ad 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -484,8 +484,10 @@
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
 			S_IFCHR|S_IRUSR|S_IWUSR,
 			"vcc/a%u", tty->index + 1);
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+			NULL, "vcs%u", tty->index + 1);
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+			NULL, "vcsa%u", tty->index + 1);
 }
 void vcs_remove_devfs(struct tty_struct *tty)
 {
@@ -503,7 +505,7 @@
 
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
 	return 0;
 }
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index d92a056..51abd3d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -956,9 +956,9 @@
 	state[i].cur_part = 0;
 	for (j = 0; j < MAX_PARTITIONS; ++j)
 		state[i].part_stat_rwi[j] = VIOT_IDLE;
-	class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+	class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
 			"iseries!vt%d", i);
-	class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+	class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
 			NULL, "iseries!nvt%d", i);
 	devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
 			"iseries/vt%d", i);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 1d44f69..003dda1 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -192,6 +192,9 @@
 	int i, j, k;
 	int ret;
 
+	if (!capable(CAP_SYS_TTY_CONFIG))
+		return -EPERM;
+
 	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
 	if (!kbs) {
 		ret = -ENOMEM;
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index 2865dac..e75045f 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
+#include <linux/jiffies.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index 7fc2188..d8dede5 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -45,6 +45,8 @@
 #include <linux/fs.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 427ad51..37c9e13 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -66,7 +66,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/reboot.h>
-
+#include <linux/sched.h>	/* TASK_INTERRUPTIBLE, set_current_state() and friends */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 0b8e493..5308e5c 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -753,6 +753,7 @@
 MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl);
 
 static struct pci_driver pcipcwd_driver = {
+	.owner		= THIS_MODULE,
 	.name		= WATCHDOG_NAME,
 	.id_table	= pcipcwd_pci_tbl,
 	.probe		= pcipcwd_card_init,
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 3625b26..b732020 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -464,32 +464,28 @@
 static unsigned long wtcon_save;
 static unsigned long wtdat_save;
 
-static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		/* Save watchdog state, and turn it off. */
-		wtcon_save = readl(wdt_base + S3C2410_WTCON);
-		wtdat_save = readl(wdt_base + S3C2410_WTDAT);
+	/* Save watchdog state, and turn it off. */
+	wtcon_save = readl(wdt_base + S3C2410_WTCON);
+	wtdat_save = readl(wdt_base + S3C2410_WTDAT);
 
-		/* Note that WTCNT doesn't need to be saved. */
-		s3c2410wdt_stop();
-	}
+	/* Note that WTCNT doesn't need to be saved. */
+	s3c2410wdt_stop();
 
 	return 0;
 }
 
-static int s3c2410wdt_resume(struct device *dev, u32 level)
+static int s3c2410wdt_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		/* Restore watchdog state. */
+	/* Restore watchdog state. */
 
-		writel(wtdat_save, wdt_base + S3C2410_WTDAT);
-		writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
-		writel(wtcon_save, wdt_base + S3C2410_WTCON);
+	writel(wtdat_save, wdt_base + S3C2410_WTDAT);
+	writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
+	writel(wtcon_save, wdt_base + S3C2410_WTCON);
 
-		printk(KERN_INFO PFX "watchdog %sabled\n",
-		       (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
-	}
+	printk(KERN_INFO PFX "watchdog %sabled\n",
+	       (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
 
 	return 0;
 }
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
index 72501be..4ee9974 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/char/watchdog/sc520_wdt.c
@@ -63,6 +63,7 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
index 20e5eb8..a91edaf 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/char/watchdog/softdog.c
@@ -47,6 +47,8 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
+
 #include <asm/uaccess.h>
 
 #define PFX "SoftDog: "
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index 4b33119..dc9370f 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -711,6 +711,7 @@
 
 
 static struct pci_driver wdtpci_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "wdt_pci",
 	.id_table	= wdtpci_pci_tbl,
 	.probe		= wdtpci_init_one,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 109d62c..6c6121b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -4,6 +4,9 @@
  *  Copyright (C) 2001 Russell King
  *            (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
  *
+ *  Oct 2005 - Ashok Raj <ashok.raj@intel.com>
+ *         		Added handling for CPU hotplug
+ *
  * 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.
@@ -36,13 +39,6 @@
 static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
 
-/* we keep a copy of all ->add'ed CPU's struct sys_device here;
- * as it is only accessed in ->add and ->remove, no lock or reference
- * count is necessary.
- */
-static struct sys_device	*cpu_sys_devices[NR_CPUS];
-
-
 /* internal prototypes */
 static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
 static void handle_update(void *data);
@@ -574,6 +570,9 @@
 	unsigned long flags;
 	unsigned int j;
 
+	if (cpu_is_offline(cpu))
+		return 0;
+
 	cpufreq_debug_disable_ratelimit();
 	dprintk("adding CPU %u\n", cpu);
 
@@ -582,7 +581,6 @@
 	 * CPU because it is in the same boat. */
 	policy = cpufreq_cpu_get(cpu);
 	if (unlikely(policy)) {
-		cpu_sys_devices[cpu] = sys_dev;
 		dprintk("CPU already managed, adding link\n");
 		sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq");
 		cpufreq_debug_enable_ratelimit();
@@ -657,7 +655,6 @@
 	}
 
 	module_put(cpufreq_driver->owner);
-	cpu_sys_devices[cpu] = sys_dev;
 	dprintk("initialization complete\n");
 	cpufreq_debug_enable_ratelimit();
 	
@@ -682,7 +679,7 @@
 
 nomem_out:
 	module_put(cpufreq_driver->owner);
- module_out:
+module_out:
 	cpufreq_debug_enable_ratelimit();
 	return ret;
 }
@@ -698,6 +695,7 @@
 	unsigned int cpu = sys_dev->id;
 	unsigned long flags;
 	struct cpufreq_policy *data;
+	struct sys_device *cpu_sys_dev;
 #ifdef CONFIG_SMP
 	unsigned int j;
 #endif
@@ -710,7 +708,6 @@
 
 	if (!data) {
 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-		cpu_sys_devices[cpu] = NULL;
 		cpufreq_debug_enable_ratelimit();
 		return -EINVAL;
 	}
@@ -725,14 +722,12 @@
 		dprintk("removing link\n");
 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 		sysfs_remove_link(&sys_dev->kobj, "cpufreq");
-		cpu_sys_devices[cpu] = NULL;
 		cpufreq_cpu_put(data);
 		cpufreq_debug_enable_ratelimit();
 		return 0;
 	}
 #endif
 
-	cpu_sys_devices[cpu] = NULL;
 
 	if (!kobject_get(&data->kobj)) {
 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -761,7 +756,8 @@
 			if (j == cpu)
 				continue;
 			dprintk("removing link for cpu %u\n", j);
-			sysfs_remove_link(&cpu_sys_devices[j]->kobj, "cpufreq");
+			cpu_sys_dev = get_cpu_sysdev(j);
+			sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
 			cpufreq_cpu_put(data);
 		}
 	}
@@ -772,7 +768,6 @@
 	down(&data->lock);
 	if (cpufreq_driver->target)
 		__cpufreq_governor(data, CPUFREQ_GOV_STOP);
-	cpufreq_driver->target = NULL;
 	up(&data->lock);
 
 	kobject_unregister(&data->kobj);
@@ -1119,17 +1114,30 @@
 			    unsigned int relation)
 {
 	int retval = -EINVAL;
-	lock_cpu_hotplug();
+
+	/*
+	 * Converted the lock_cpu_hotplug to preempt_disable()
+	 * and preempt_enable(). This is a bit kludgy and relies on how cpu
+	 * hotplug works. All we need is a guarantee that cpu hotplug won't make
+	 * progress on any cpu. Once we do preempt_disable(), this would ensure
+	 * that hotplug threads don't get onto this cpu, thereby delaying
+	 * the cpu remove process.
+	 *
+	 * We removed the lock_cpu_hotplug since we need to call this function
+	 * via cpu hotplug callbacks, which result in locking the cpu hotplug
+	 * thread itself. Agree this is not very clean, cpufreq community
+	 * could improve this if required. - Ashok Raj <ashok.raj@intel.com>
+	 */
+	preempt_disable();
 	dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
 		target_freq, relation);
 	if (cpu_online(policy->cpu) && cpufreq_driver->target)
 		retval = cpufreq_driver->target(policy, target_freq, relation);
-	unlock_cpu_hotplug();
+	preempt_enable();
 	return retval;
 }
 EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
 
-
 int cpufreq_driver_target(struct cpufreq_policy *policy,
 			  unsigned int target_freq,
 			  unsigned int relation)
@@ -1416,6 +1424,45 @@
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
+static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+	struct cpufreq_policy *policy;
+	struct sys_device *sys_dev;
+
+	sys_dev = get_cpu_sysdev(cpu);
+
+	if (sys_dev) {
+		switch (action) {
+		case CPU_ONLINE:
+			cpufreq_add_dev(sys_dev);
+			break;
+		case CPU_DOWN_PREPARE:
+			/*
+			 * We attempt to put this cpu in lowest frequency
+			 * possible before going down. This will permit
+			 * hardware-managed P-State to switch other related
+			 * threads to min or higher speeds if possible.
+			 */
+			policy = cpufreq_cpu_data[cpu];
+			if (policy) {
+				cpufreq_driver_target(policy, policy->min,
+						CPUFREQ_RELATION_H);
+			}
+			break;
+		case CPU_DEAD:
+			cpufreq_remove_dev(sys_dev);
+			break;
+		}
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_cpu_notifier =
+{
+    .notifier_call = cpufreq_cpu_callback,
+};
 
 /*********************************************************************
  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
@@ -1476,6 +1523,7 @@
 	}
 
 	if (!ret) {
+		register_cpu_notifier(&cpufreq_cpu_notifier);
 		dprintk("driver %s up and running\n", driver_data->name);
 		cpufreq_debug_enable_ratelimit();
 	}
@@ -1507,6 +1555,7 @@
 	dprintk("unregistering driver %s\n", driver->name);
 
 	sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
+	unregister_cpu_notifier(&cpufreq_cpu_notifier);
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 741b6b1..3597f25 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -19,6 +19,7 @@
 #include <linux/percpu.h>
 #include <linux/kobject.h>
 #include <linux/spinlock.h>
+#include <linux/notifier.h>
 #include <asm/cputime.h>
 
 static spinlock_t cpufreq_stats_lock;
@@ -298,6 +299,27 @@
 	return 0;
 }
 
+static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+		cpufreq_update_policy(cpu);
+		break;
+	case CPU_DEAD:
+		cpufreq_stats_free_table(cpu);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_stat_cpu_notifier =
+{
+	.notifier_call = cpufreq_stat_cpu_callback,
+};
+
 static struct notifier_block notifier_policy_block = {
 	.notifier_call = cpufreq_stat_notifier_policy
 };
@@ -311,6 +333,7 @@
 {
 	int ret;
 	unsigned int cpu;
+
 	spin_lock_init(&cpufreq_stats_lock);
 	if ((ret = cpufreq_register_notifier(&notifier_policy_block,
 				CPUFREQ_POLICY_NOTIFIER)))
@@ -323,20 +346,31 @@
 		return ret;
 	}
 
-	for_each_cpu(cpu)
-		cpufreq_update_policy(cpu);
+	register_cpu_notifier(&cpufreq_stat_cpu_notifier);
+	lock_cpu_hotplug();
+	for_each_online_cpu(cpu) {
+		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE,
+			(void *)(long)cpu);
+	}
+	unlock_cpu_hotplug();
 	return 0;
 }
 static void
 __exit cpufreq_stats_exit(void)
 {
 	unsigned int cpu;
+
 	cpufreq_unregister_notifier(&notifier_policy_block,
 			CPUFREQ_POLICY_NOTIFIER);
 	cpufreq_unregister_notifier(&notifier_trans_block,
 			CPUFREQ_TRANSITION_NOTIFIER);
-	for_each_cpu(cpu)
-		cpufreq_stats_free_table(cpu);
+	unregister_cpu_notifier(&cpufreq_stat_cpu_notifier);
+	lock_cpu_hotplug();
+	for_each_online_cpu(cpu) {
+		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD,
+			(void *)(long)cpu);
+	}
+	unlock_cpu_hotplug();
 }
 
 MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 094835c..4263935 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -2,7 +2,7 @@
 
 config CRYPTO_DEV_PADLOCK
 	tristate "Support for VIA PadLock ACE"
-	depends on CRYPTO && X86 && !X86_64
+	depends on CRYPTO && X86_32
 	help
 	  Some VIA processors come with an integrated crypto engine
 	  (so called VIA PadLock ACE, Advanced Cryptography Engine)
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 327b58e..b6815c6 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -70,8 +70,7 @@
 
 config DCDBAS
 	tristate "Dell Systems Management Base Driver"
-	depends on X86 || X86_64
-	default m
+	depends on X86
 	help
 	  The Dell Systems Management Base Driver provides a sysfs interface
 	  for systems management software to perform System Management
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index e928cdb..8102876 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -121,7 +121,7 @@
 static struct adm1021_data *adm1021_update_device(struct device *dev);
 
 /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
-static int read_only = 0;
+static int read_only;
 
 
 /* This is the driver that will be inserted */
@@ -204,11 +204,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access adm1021_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto error0;
 	}
-	memset(data, 0, sizeof(struct adm1021_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 526b7ff..3ec1242 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -331,11 +331,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct adm1025_data));
 
 	/* The common I2C client data is placed right before the
 	   ADM1025-specific data. */
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 6251581..e0f5654 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -315,7 +315,7 @@
 	.detach_client  = adm1026_detach_client,
 };
 
-int adm1026_attach_adapter(struct i2c_adapter *adapter)
+static int adm1026_attach_adapter(struct i2c_adapter *adapter)
 {
 	if (!(adapter->class & I2C_CLASS_HWMON)) {
 		return 0;
@@ -323,7 +323,7 @@
 	return i2c_probe(adapter, &addr_data, adm1026_detect);
 }
 
-int adm1026_detach_client(struct i2c_client *client)
+static int adm1026_detach_client(struct i2c_client *client)
 {
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->class_dev);
@@ -332,7 +332,7 @@
 	return 0;
 }
 
-int adm1026_read_value(struct i2c_client *client, u8 reg)
+static int adm1026_read_value(struct i2c_client *client, u8 reg)
 {
 	int res;
 
@@ -346,7 +346,7 @@
 	return res;
 }
 
-int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
+static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
 {
 	int res;
 
@@ -360,7 +360,7 @@
 	return res;
 }
 
-void adm1026_init_client(struct i2c_client *client)
+static void adm1026_init_client(struct i2c_client *client)
 {
 	int value, i;
 	struct adm1026_data *data = i2c_get_clientdata(client);
@@ -460,7 +460,7 @@
 	}
 }
 
-void adm1026_print_gpio(struct i2c_client *client)
+static void adm1026_print_gpio(struct i2c_client *client)
 {
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int  i;
@@ -492,7 +492,7 @@
 	}
 }
 
-void adm1026_fixup_gpio(struct i2c_client *client)
+static void adm1026_fixup_gpio(struct i2c_client *client)
 {
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int  i;
@@ -1452,8 +1452,8 @@
 static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
 
-int adm1026_detect(struct i2c_adapter *adapter, int address,
-		int kind)
+static int adm1026_detect(struct i2c_adapter *adapter, int address,
+			  int kind)
 {
 	int company, verstep;
 	struct i2c_client *new_client;
@@ -1470,13 +1470,11 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access adm1026_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
 
-	memset(data, 0, sizeof(struct adm1026_data));
-
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 58338ed..7c545d5 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -740,11 +740,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct adm1031_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index bc7faef..11dc95f 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -45,6 +45,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
@@ -69,8 +70,7 @@
 #define ADM9240_REG_INT(nr)		(0x41 + (nr))
 #define ADM9240_REG_INT_MASK(nr)	(0x43 + (nr))
 #define ADM9240_REG_TEMP		0x27
-#define ADM9240_REG_TEMP_HIGH		0x39
-#define ADM9240_REG_TEMP_HYST		0x3a
+#define ADM9240_REG_TEMP_MAX(nr)	(0x39 + (nr)) /* 0, 1 = high, hyst */
 #define ADM9240_REG_ANALOG_OUT		0x19
 #define ADM9240_REG_CHASSIS_CLEAR	0x46
 #define ADM9240_REG_VID_FAN_DIV		0x47
@@ -162,177 +162,155 @@
 	u8 fan_min[2];		/* rw	fan1_min */
 	u8 fan_div[2];		/* rw	fan1_div, read-only accessor */
 	s16 temp;		/* ro	temp1_input, 9-bit sign-extended */
-	s8 temp_high;		/* rw	temp1_max */
-	s8 temp_hyst;		/* rw	temp1_max_hyst */
+	s8 temp_max[2];		/* rw	0 -> temp_max, 1 -> temp_max_hyst */
 	u16 alarms;		/* ro	alarms */
 	u8 aout;		/* rw	aout_output */
 	u8 vid;			/* ro	vid */
 	u8 vrm;			/* --	vrm set on startup, no accessor */
 };
 
-/* i2c byte read/write interface */
-static int adm9240_read_value(struct i2c_client *client, u8 reg)
-{
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
 /*** sysfs accessors ***/
 
 /* temperature */
-#define show_temp(value, scale)					\
-static ssize_t show_##value(struct device *dev,			\
-			    struct device_attribute *attr,	\
-			    char *buf)				\
-{								\
-	struct adm9240_data *data = adm9240_update_device(dev);	\
-	return sprintf(buf, "%d\n", data->value * scale);	\
-}
-show_temp(temp_high, 1000);
-show_temp(temp_hyst, 1000);
-show_temp(temp, 500); /* 0.5'C per bit */
-
-#define set_temp(value, reg)					\
-static ssize_t set_##value(struct device *dev, 			\
-			   struct device_attribute *attr,	\
-			   const char *buf, size_t count)	\
-{								\
-	struct i2c_client *client = to_i2c_client(dev);		\
-	struct adm9240_data *data = adm9240_update_device(dev);	\
-	long temp = simple_strtoul(buf, NULL, 10);		\
-								\
-	down(&data->update_lock);				\
-	data->value = TEMP_TO_REG(temp);			\
-	adm9240_write_value(client, reg, data->value);		\
-	up(&data->update_lock);					\
-	return count;						\
+static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
+		char *buf)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
 }
 
-set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
-set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
+static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
+		char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000);
+}
 
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
-		show_temp_high, set_temp_high);
-static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
-		show_temp_hyst, set_temp_hyst);
+static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_max[attr->index] = TEMP_TO_REG(val);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index),
+			data->temp_max[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+
 static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+		show_max, set_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+		show_max, set_max, 1);
 
 /* voltage */
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+		char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adm9240_data *data = adm9240_update_device(dev);
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index],
+				attr->index));
 }
 
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev,
+		struct device_attribute *devattr, char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adm9240_data *data = adm9240_update_device(dev);
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index],
+				attr->index));
 }
 
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev,
+		struct device_attribute *devattr, char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adm9240_data *data = adm9240_update_device(dev);
-	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index],
+				attr->index));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_in_min(struct device *dev,
+		struct device_attribute *devattr,
+		const char *buf, size_t count)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	down(&data->update_lock);
-	data->in_min[nr] = IN_TO_REG(val, nr);
-	adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
+	data->in_min[attr->index] = IN_TO_REG(val, attr->index);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index),
+			data->in_min[attr->index]);
 	up(&data->update_lock);
 	return count;
 }
 
-static ssize_t set_in_max(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_in_max(struct device *dev,
+		struct device_attribute *devattr,
+		const char *buf, size_t count)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	down(&data->update_lock);
-	data->in_max[nr] = IN_TO_REG(val, nr);
-	adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
+	data->in_max[attr->index] = IN_TO_REG(val, attr->index);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index),
+			data->in_max[attr->index]);
 	up(&data->update_lock);
 	return count;
 }
 
-#define show_in_offset(offset)						\
-static ssize_t show_in##offset(struct device *dev,			\
-			       struct device_attribute *attr,		\
-			       char *buf)				\
-{									\
-	return show_in(dev, buf, offset);				\
-}									\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);	\
-static ssize_t show_in##offset##_min(struct device *dev,		\
-				     struct device_attribute *attr,	\
-				     char *buf)				\
-{									\
-	return show_in_min(dev, buf, offset);				\
-}									\
-static ssize_t show_in##offset##_max(struct device *dev,		\
-				     struct device_attribute *attr,	\
-				     char *buf)				\
-{									\
-	return show_in_max(dev, buf, offset);				\
-}									\
-static ssize_t								\
-set_in##offset##_min(struct device *dev,				\
-		     struct device_attribute *attr, const char *buf,	\
-		     size_t count)					\
-{									\
-	return set_in_min(dev, buf, count, offset);			\
-}									\
-static ssize_t								\
-set_in##offset##_max(struct device *dev,				\
-		     struct device_attribute *attr, const char *buf,	\
-		     size_t count)					\
-{									\
-	return set_in_max(dev, buf, count, offset);			\
-}									\
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,			\
-		show_in##offset##_min, set_in##offset##_min);		\
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,			\
-		show_in##offset##_max, set_in##offset##_max);
+#define vin(nr)							\
+static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, 		\
+		show_in, NULL, nr);				\
+static SENSOR_DEVICE_ATTR(in##nr##_min, S_IRUGO | S_IWUSR,	\
+		show_in_min, set_in_min, nr);			\
+static SENSOR_DEVICE_ATTR(in##nr##_max, S_IRUGO | S_IWUSR,	\
+		show_in_max, set_in_max, nr);
 
-show_in_offset(0);
-show_in_offset(1);
-show_in_offset(2);
-show_in_offset(3);
-show_in_offset(4);
-show_in_offset(5);
+vin(0);
+vin(1);
+vin(2);
+vin(3);
+vin(4);
+vin(5);
 
 /* fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev,
+		struct device_attribute *devattr, char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adm9240_data *data = adm9240_update_device(dev);
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
-				1 << data->fan_div[nr]));
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
+				1 << data->fan_div[attr->index]));
 }
 
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev,
+		struct device_attribute *devattr, char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adm9240_data *data = adm9240_update_device(dev);
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
-				1 << data->fan_div[nr]));
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index],
+				1 << data->fan_div[attr->index]));
 }
 
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev,
+		struct device_attribute *devattr, char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adm9240_data *data = adm9240_update_device(dev);
-	return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
+	return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
 }
 
 /* write new fan div, callers must hold data->update_lock */
@@ -341,16 +319,16 @@
 {
 	u8 reg, old, shift = (nr + 2) * 2;
 
-	reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+	reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
 	old = (reg >> shift) & 3;
 	reg &= ~(3 << shift);
 	reg |= (fan_div << shift);
-	adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
 	dev_dbg(&client->dev, "fan%d clock divider changed from %u "
 			"to %u\n", nr + 1, 1 << old, 1 << fan_div);
 }
 
-/* 
+/*
  * set fan speed low limit:
  *
  * - value is zero: disable fan speed low limit alarm
@@ -361,12 +339,15 @@
  * - otherwise: select fan clock divider to suit fan speed low limit,
  *   measurement code may adjust registers to ensure fan speed reading
  */
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev,
+		struct device_attribute *devattr,
+		const char *buf, size_t count)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int nr = attr->index;
 	u8 new_div;
 
 	down(&data->update_lock);
@@ -406,50 +387,27 @@
 		data->fan_div[nr] = new_div;
 		adm9240_write_fan_div(client, nr, new_div);
 	}
-	adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
+	i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr),
 			data->fan_min[nr]);
 
 	up(&data->update_lock);
 	return count;
 }
 
-#define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev,			\
-				  struct device_attribute *attr,	\
-				  char *buf)				\
-{									\
-return show_fan(dev, buf, offset - 1);					\
-}									\
-static ssize_t show_fan_##offset##_div (struct device *dev,		\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-return show_fan_div(dev, buf, offset - 1);				\
-}									\
-static ssize_t show_fan_##offset##_min (struct device *dev,		\
-					struct device_attribute *attr,	\
-					char *buf)			\
-{									\
-return show_fan_min(dev, buf, offset - 1);				\
-}									\
-static ssize_t set_fan_##offset##_min (struct device *dev, 		\
-				       struct device_attribute *attr,	\
-				       const char *buf, size_t count)	\
-{									\
-return set_fan_min(dev, buf, count, offset - 1);			\
-}									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, 			\
-		show_fan_##offset, NULL);				\
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, 				\
-		show_fan_##offset##_div, NULL);				\
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_min, set_fan_##offset##_min);
+#define fan(nr)							\
+static SENSOR_DEVICE_ATTR(fan##nr##_input, S_IRUGO,		\
+		show_fan, NULL, nr - 1);			\
+static SENSOR_DEVICE_ATTR(fan##nr##_div, S_IRUGO,		\
+		show_fan_div, NULL, nr - 1);			\
+static SENSOR_DEVICE_ATTR(fan##nr##_min, S_IRUGO | S_IWUSR,	\
+		show_fan_min, set_fan_min, nr - 1);
 
-show_fan_offset(1);
-show_fan_offset(2);
+fan(1);
+fan(2);
 
 /* alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct adm9240_data *data = adm9240_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
@@ -457,7 +415,8 @@
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /* vid */
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct adm9240_data *data = adm9240_update_device(dev);
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
@@ -465,13 +424,16 @@
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 /* analog output */
-static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_aout(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct adm9240_data *data = adm9240_update_device(dev);
 	return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
 }
 
-static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_aout(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
@@ -479,20 +441,23 @@
 
 	down(&data->update_lock);
 	data->aout = AOUT_TO_REG(val);
-	adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
+	i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout);
 	up(&data->update_lock);
 	return count;
 }
 static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
 
 /* chassis_clear */
-static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t chassis_clear(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	unsigned long val = simple_strtol(buf, NULL, 10);
 
 	if (val == 1) {
-		adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+		i2c_smbus_write_byte_data(client,
+				ADM9240_REG_CHASSIS_CLEAR, 0x80);
 		dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
 	}
 	return count;
@@ -513,11 +478,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct adm9240_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -533,7 +497,7 @@
 	if (kind < 0) {
 
 		/* verify chip: reg address should match i2c address */
-		if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
+		if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
 				!= address) {
 			dev_err(&adapter->dev, "detect fail: address match, "
 					"0x%02x\n", address);
@@ -541,8 +505,8 @@
 		}
 
 		/* check known chip manufacturer */
-		man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
-
+		man_id = i2c_smbus_read_byte_data(new_client,
+				ADM9240_REG_MAN_ID);
 		if (man_id == 0x23) {
 			kind = adm9240;
 		} else if (man_id == 0xda) {
@@ -556,7 +520,8 @@
 		}
 
 		/* successful detect, print chip info */
-		die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
+		die_rev = i2c_smbus_read_byte_data(new_client,
+				ADM9240_REG_DIE_REV);
 		dev_info(&adapter->dev, "found %s revision %u\n",
 				man_id == 0x23 ? "ADM9240" :
 				man_id == 0xda ? "DS1780" : "LM81", die_rev);
@@ -588,33 +553,59 @@
 		goto exit_detach;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
-	device_create_file(&new_client->dev, &dev_attr_in5_input);
-	device_create_file(&new_client->dev, &dev_attr_in5_min);
-	device_create_file(&new_client->dev, &dev_attr_in5_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in0_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in0_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in0_max.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in1_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in1_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in1_max.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in2_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in2_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in2_max.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in3_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in3_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in3_max.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in4_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in4_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in4_max.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in5_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in5_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_in5_max.dev_attr);
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_temp1_max.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_temp1_max_hyst.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_fan1_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_fan1_div.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_fan1_min.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_fan2_input.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_fan2_div.dev_attr);
+	device_create_file(&new_client->dev,
+			&sensor_dev_attr_fan2_min.dev_attr);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 	device_create_file(&new_client->dev, &dev_attr_aout_output);
 	device_create_file(&new_client->dev, &dev_attr_chassis_clear);
@@ -654,8 +645,8 @@
 static void adm9240_init_client(struct i2c_client *client)
 {
 	struct adm9240_data *data = i2c_get_clientdata(client);
-	u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
-	u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
+	u8 conf = i2c_smbus_read_byte_data(client, ADM9240_REG_CONFIG);
+	u8 mode = i2c_smbus_read_byte_data(client, ADM9240_REG_TEMP_CONF) & 3;
 
 	data->vrm = vid_which_vrm(); /* need this to report vid as mV */
 
@@ -672,18 +663,22 @@
 
 		for (i = 0; i < 6; i++)
 		{
-			adm9240_write_value(client,
+			i2c_smbus_write_byte_data(client,
 					ADM9240_REG_IN_MIN(i), 0);
-			adm9240_write_value(client,
+			i2c_smbus_write_byte_data(client,
 					ADM9240_REG_IN_MAX(i), 255);
 		}
-		adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
-		adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
-		adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
-		adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
+		i2c_smbus_write_byte_data(client,
+				ADM9240_REG_FAN_MIN(0), 255);
+		i2c_smbus_write_byte_data(client,
+				ADM9240_REG_FAN_MIN(1), 255);
+		i2c_smbus_write_byte_data(client,
+				ADM9240_REG_TEMP_MAX(0), 127);
+		i2c_smbus_write_byte_data(client,
+				ADM9240_REG_TEMP_MAX(1), 127);
 
 		/* start measurement cycle */
-		adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
+		i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
 
 		dev_info(&client->dev, "cold start: config was 0x%02x "
 				"mode %u\n", conf, mode);
@@ -704,25 +699,25 @@
 
 		for (i = 0; i < 6; i++) /* read voltages */
 		{
-			data->in[i] = adm9240_read_value(client,
+			data->in[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_IN(i));
 		}
-		data->alarms = adm9240_read_value(client,
+		data->alarms = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_INT(0)) |
-					adm9240_read_value(client,
+					i2c_smbus_read_byte_data(client,
 					ADM9240_REG_INT(1)) << 8;
 
 		/* read temperature: assume temperature changes less than
 		 * 0.5'C per two measurement cycles thus ignore possible
 		 * but unlikely aliasing error on lsb reading. --Grant */
-		data->temp = ((adm9240_read_value(client,
+		data->temp = ((i2c_smbus_read_byte_data(client,
 					ADM9240_REG_TEMP) << 8) |
-					adm9240_read_value(client,
+					i2c_smbus_read_byte_data(client,
 					ADM9240_REG_TEMP_CONF)) / 128;
 
 		for (i = 0; i < 2; i++) /* read fans */
 		{
-			data->fan[i] = adm9240_read_value(client,
+			data->fan[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_FAN(i));
 
 			/* adjust fan clock divider on overflow */
@@ -747,30 +742,30 @@
 
 		for (i = 0; i < 6; i++)
 		{
-			data->in_min[i] = adm9240_read_value(client,
+			data->in_min[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_IN_MIN(i));
-			data->in_max[i] = adm9240_read_value(client,
+			data->in_max[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_IN_MAX(i));
 		}
 		for (i = 0; i < 2; i++)
 		{
-			data->fan_min[i] = adm9240_read_value(client,
+			data->fan_min[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_FAN_MIN(i));
 		}
-		data->temp_high = adm9240_read_value(client,
-				ADM9240_REG_TEMP_HIGH);
-		data->temp_hyst = adm9240_read_value(client,
-				ADM9240_REG_TEMP_HYST);
+		data->temp_max[0] = i2c_smbus_read_byte_data(client,
+				ADM9240_REG_TEMP_MAX(0));
+		data->temp_max[1] = i2c_smbus_read_byte_data(client,
+				ADM9240_REG_TEMP_MAX(1));
 
 		/* read fan divs and 5-bit VID */
-		i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+		i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
 		data->fan_div[0] = (i >> 4) & 3;
 		data->fan_div[1] = (i >> 6) & 3;
 		data->vid = i & 0x0f;
-		data->vid |= (adm9240_read_value(client,
+		data->vid |= (i2c_smbus_read_byte_data(client,
 					ADM9240_REG_VID4) & 1) << 4;
 		/* read analog out */
-		data->aout = adm9240_read_value(client,
+		data->aout = i2c_smbus_read_byte_data(client,
 				ADM9240_REG_ANALOG_OUT);
 
 		data->last_updated_config = jiffies;
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 8e34855..52c4697 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -629,19 +629,17 @@
 	int i, id, err;
 	struct asb100_data *data = i2c_get_clientdata(new_client);
 
-	data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!(data->lm75[0])) {
 		err = -ENOMEM;
 		goto ERROR_SC_0;
 	}
-	memset(data->lm75[0], 0x00, sizeof(struct i2c_client));
 
-	data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!(data->lm75[1])) {
 		err = -ENOMEM;
 		goto ERROR_SC_1;
 	}
-	memset(data->lm75[1], 0x00, sizeof(struct i2c_client));
 
 	id = i2c_adapter_id(adapter);
 
@@ -724,12 +722,11 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access asb100_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
-		pr_debug("asb100.o: detect failed, kmalloc failed!\n");
+	if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
+		pr_debug("asb100.o: detect failed, kzalloc failed!\n");
 		err = -ENOMEM;
 		goto ERROR0;
 	}
-	memset(data, 0, sizeof(struct asb100_data));
 
 	new_client = &data->client;
 	init_MUTEX(&data->lock);
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index deb4d34..53324f5 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -253,6 +253,8 @@
 
 static int atxp1_attach_adapter(struct i2c_adapter *adapter)
 {
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
 	return i2c_probe(adapter, &addr_data, &atxp1_detect);
 };
 
@@ -266,12 +268,11 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
 
-	memset(data, 0, sizeof(struct atxp1_data));
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index b0199e0..34f71b7 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -180,12 +180,14 @@
 
 static int ds1621_attach_adapter(struct i2c_adapter *adapter)
 {
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
 	return i2c_probe(adapter, &addr_data, ds1621_detect);
 }
 
 /* This function is called by i2c_probe */
-int ds1621_detect(struct i2c_adapter *adapter, int address,
-                  int kind)
+static int ds1621_detect(struct i2c_adapter *adapter, int address,
+			 int kind)
 {
 	int conf, temp;
 	struct i2c_client *new_client;
@@ -200,11 +202,10 @@
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access ds1621_{read,write}_value. */
-	if (!(data = kmalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct ds1621_data));
 	
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index eef6061..a02e1c3 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -303,11 +303,10 @@
 	/* OK. For now, we presume we have a valid client. We now create the
 	 * client structure, even though we cannot fill it completely yet.
 	 * But it allows us to access i2c_smbus_read_byte_data. */
-	if (!(data = kmalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
   	}
-	memset(data, 0, sizeof(struct fscher_data));
 
 	/* The common I2C client data is placed right before the
 	 * Hermes-specific data. */
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 5fc77a5..64e4edc 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -438,7 +438,7 @@
 	return i2c_probe(adapter, &addr_data, fscpos_detect);
 }
 
-int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
+static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
 	struct fscpos_data *data;
@@ -453,11 +453,10 @@
 	 * But it allows us to access fscpos_{read,write}_value.
 	 */
 
-	if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct fscpos_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 256b932..2f178db 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -365,11 +365,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access gl518_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct gl518_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 12fd757..c39ba12 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -536,11 +536,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access gl520_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct gl520_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 7f01076..0015da5 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -296,11 +296,9 @@
 	return 0;
 }
 
-static int hdaps_resume(struct device *dev, u32 level)
+static int hdaps_resume(struct device *dev)
 {
-	if (level == RESUME_ENABLE)
-		return hdaps_device_init();
-	return 0;
+	return hdaps_device_init();
 }
 
 static struct device_driver hdaps_driver = {
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 9b41c9b..6f48579 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -45,7 +45,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	id = id & MAX_ID_MASK;
-	cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
+	cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev,
 					HWMON_ID_FORMAT, id);
 
 	if (IS_ERR(cdev))
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 53cc2b6..6c41e25 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -2,7 +2,7 @@
     it87.c - Part of lm_sensors, Linux kernel modules for hardware
              monitoring.
 
-    Supports: IT8705F  Super I/O chip w/LPC interface & SMBus
+    Supports: IT8705F  Super I/O chip w/LPC interface
               IT8712F  Super I/O chip w/LPC interface & SMBus
               Sis950   A clone of the IT8705F
 
@@ -47,7 +47,7 @@
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
 					0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned short isa_address = 0x290;
+static unsigned short isa_address;
 
 /* Insmod parameters */
 I2C_CLIENT_INSMOD_2(it87, it8712);
@@ -706,7 +706,7 @@
 }
 
 /* SuperIO detection - will change isa_address if a chip is found */
-static int __init it87_find(int *address)
+static int __init it87_find(unsigned short *address)
 {
 	int err = -ENODEV;
 
@@ -738,7 +738,7 @@
 }
 
 /* This function is called by i2c_probe */
-int it87_detect(struct i2c_adapter *adapter, int address, int kind)
+static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
 	struct i2c_client *new_client;
@@ -757,42 +757,14 @@
 		if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
 			goto ERROR0;
 
-	/* Probe whether there is anything available on this address. Already
-	   done for SMBus and Super-I/O clients */
-	if (kind < 0) {
-		if (is_isa && !chip_type) {
-#define REALLY_SLOW_IO
-			/* We need the timeouts for at least some IT87-like chips. But only
-			   if we read 'undefined' registers. */
-			i = inb_p(address + 1);
-			if (inb_p(address + 2) != i
-			 || inb_p(address + 3) != i
-			 || inb_p(address + 7) != i) {
-		 		err = -ENODEV;
-				goto ERROR1;
-			}
-#undef REALLY_SLOW_IO
-
-			/* Let's just hope nothing breaks here */
-			i = inb_p(address + 5) & 0x7f;
-			outb_p(~i & 0x7f, address + 5);
-			if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
-				outb_p(i, address + 5);
-				err = -ENODEV;
-				goto ERROR1;
-			}
-		}
-	}
-
-	/* OK. For now, we presume we have a valid client. We now create the
+	/* For now, we presume we have a valid client. We create the
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access it87_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
-	memset(data, 0, sizeof(struct it87_data));
 
 	new_client = &data->client;
 	if (is_isa)
@@ -1182,20 +1154,18 @@
 
 static int __init sm_it87_init(void)
 {
-	int addr, res;
-
-	if (!it87_find(&addr)) {
-		isa_address = addr;
-	}
+	int res;
 
 	res = i2c_add_driver(&it87_driver);
 	if (res)
 		return res;
 
-	res = i2c_isa_add_driver(&it87_isa_driver);
-	if (res) {
-		i2c_del_driver(&it87_driver);
-		return res;
+	if (!it87_find(&isa_address)) {
+		res = i2c_isa_add_driver(&it87_isa_driver);
+		if (res) {
+			i2c_del_driver(&it87_driver);
+			return res;
+		}
 	}
 
 	return 0;
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index be5c709..954ec24 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -375,11 +375,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm63_data));
 
 	/* The common I2C client data is placed right before the
 	   LM63-specific data. */
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 9a3ebdf..d70f4c8 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -127,11 +127,10 @@
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm75_{read,write}_value. */
-	if (!(data = kmalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm75_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 866eab9..9380fda 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -226,11 +226,10 @@
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm77_{read,write}_value. */
-	if (!(data = kmalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm77_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index f6730dc..bde0cda 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -480,7 +480,7 @@
 }
 
 /* This function is called by i2c_probe */
-int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
+static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i, err;
 	struct i2c_client *new_client;
@@ -540,11 +540,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm78_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
-	memset(data, 0, sizeof(struct lm78_data));
 
 	new_client = &data->client;
 	if (is_isa)
@@ -726,7 +725,6 @@
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-/* Called when we have found a new LM78. It should set limits, etc. */
 static void lm78_init_client(struct i2c_client *client)
 {
 	u8 config = lm78_read_value(client, LM78_REG_CONFIG);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 83af8b3..c359fde 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -393,7 +393,7 @@
 	return i2c_probe(adapter, &addr_data, lm80_detect);
 }
 
-int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
+static int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i, cur;
 	struct i2c_client *new_client;
@@ -407,11 +407,10 @@
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm80_{read,write}_value. */
-	if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm80_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index d74b2c2..9a70611 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -230,11 +230,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm83_data));
 
 	/* The common I2C client data is placed right after the
 	 * LM83-specific data. */
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index ab214df..d1070ed 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1007,14 +1007,14 @@
 temp_auto(2);
 temp_auto(3);
 
-int lm85_attach_adapter(struct i2c_adapter *adapter)
+static int lm85_attach_adapter(struct i2c_adapter *adapter)
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
 	return i2c_probe(adapter, &addr_data, lm85_detect);
 }
 
-int lm85_detect(struct i2c_adapter *adapter, int address,
+static int lm85_detect(struct i2c_adapter *adapter, int address,
 		int kind)
 {
 	int company, verstep ;
@@ -1033,11 +1033,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm85_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR0;
 	}
-	memset(data, 0, sizeof(struct lm85_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -1236,7 +1235,7 @@
 	return err;
 }
 
-int lm85_detach_client(struct i2c_client *client)
+static int lm85_detach_client(struct i2c_client *client)
 {
 	struct lm85_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->class_dev);
@@ -1246,7 +1245,7 @@
 }
 
 
-int lm85_read_value(struct i2c_client *client, u8 reg)
+static int lm85_read_value(struct i2c_client *client, u8 reg)
 {
 	int res;
 
@@ -1276,7 +1275,7 @@
 	return res ;
 }
 
-int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+static int lm85_write_value(struct i2c_client *client, u8 reg, int value)
 {
 	int res ;
 
@@ -1305,7 +1304,7 @@
 	return res ;
 }
 
-void lm85_init_client(struct i2c_client *client)
+static void lm85_init_client(struct i2c_client *client)
 {
 	int value;
 	struct lm85_data *data = i2c_get_clientdata(client);
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index dca996d..eeec1817 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -554,11 +554,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm87_data));
 
 	/* The common I2C client data is placed right before the
 	   LM87-specific data. */
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 14de05f..83cf2e1 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -31,7 +31,7 @@
  * Devices. That chip is similar to the LM90, with a few differences
  * that are not handled by this driver. Complete datasheet can be
  * obtained from Analog's website at:
- *   http://products.analog.com/products/info.asp?product=ADM1032
+ *   http://www.analog.com/en/prod/0,2877,ADM1032,00.html
  * Among others, it has a higher accuracy than the LM90, much like the
  * LM86 does.
  *
@@ -49,7 +49,7 @@
  * register values are decoded differently) it is ignored by this
  * driver. Complete datasheet can be obtained from Analog's website
  * at:
- *   http://products.analog.com/products/info.asp?product=ADT7461
+ *   http://www.analog.com/en/prod/0,2877,ADT7461,00.html
  *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
@@ -83,10 +83,10 @@
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
  * MAX6659.
- * LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
- * LM89-1, and LM99-1 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
+ * have address 0x4c.
+ * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
- * ADT7461 always has address 0x4c.
  */
 
 static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
@@ -345,10 +345,74 @@
 static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+/* pec used for ADM1032 only */
+static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC));
+}
+
+static ssize_t set_pec(struct device *dev, struct device_attribute *dummy,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	long val = simple_strtol(buf, NULL, 10);
+
+	switch (val) {
+	case 0:
+		client->flags &= ~I2C_CLIENT_PEC;
+		break;
+	case 1:
+		client->flags |= I2C_CLIENT_PEC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
+
 /*
  * Real code
  */
 
+/* The ADM1032 supports PEC but not on write byte transactions, so we need
+   to explicitely ask for a transaction without PEC. */
+static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
+{
+	return i2c_smbus_xfer(client->adapter, client->addr,
+			      client->flags & ~I2C_CLIENT_PEC,
+			      I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+}
+
+/* It is assumed that client->update_lock is held (unless we are in
+   detection or initialization steps). This matters when PEC is enabled,
+   because we don't want the address pointer to change between the write
+   byte and the read byte transactions. */
+static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value)
+{
+	int err;
+
+ 	if (client->flags & I2C_CLIENT_PEC) {
+ 		err = adm1032_write_byte(client, reg);
+ 		if (err >= 0)
+ 			err = i2c_smbus_read_byte(client);
+ 	} else
+ 		err = i2c_smbus_read_byte_data(client, reg);
+
+	if (err < 0) {
+		dev_warn(&client->dev, "Register %#02x read failed (%d)\n",
+			 reg, err);
+		return err;
+	}
+	*value = err;
+
+	return 0;
+}
+
 static int lm90_attach_adapter(struct i2c_adapter *adapter)
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
@@ -370,11 +434,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm90_data));
 
 	/* The common I2C client data is placed right before the
 	   LM90-specific data. */
@@ -403,20 +466,22 @@
 	if (kind < 0) { /* detection and identification */
 		u8 man_id, chip_id, reg_config1, reg_convrate;
 
-		man_id = i2c_smbus_read_byte_data(new_client,
-			 LM90_REG_R_MAN_ID);
-		chip_id = i2c_smbus_read_byte_data(new_client,
-			  LM90_REG_R_CHIP_ID);
-		reg_config1 = i2c_smbus_read_byte_data(new_client,
-			      LM90_REG_R_CONFIG1);
-		reg_convrate = i2c_smbus_read_byte_data(new_client,
-			       LM90_REG_R_CONVRATE);
+		if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID,
+				  &man_id) < 0
+		 || lm90_read_reg(new_client, LM90_REG_R_CHIP_ID,
+		 		  &chip_id) < 0
+		 || lm90_read_reg(new_client, LM90_REG_R_CONFIG1,
+		 		  &reg_config1) < 0
+		 || lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
+		 		  &reg_convrate) < 0)
+			goto exit_free;
 		
 		if (man_id == 0x01) { /* National Semiconductor */
 			u8 reg_config2;
 
-			reg_config2 = i2c_smbus_read_byte_data(new_client,
-				      LM90_REG_R_CONFIG2);
+			if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
+					  &reg_config2) < 0)
+				goto exit_free;
 
 			if ((reg_config1 & 0x2A) == 0x00
 			 && (reg_config2 & 0xF8) == 0x00
@@ -435,14 +500,12 @@
 			}
 		} else
 		if (man_id == 0x41) { /* Analog Devices */
-			if (address == 0x4C
-			 && (chip_id & 0xF0) == 0x40 /* ADM1032 */
+			if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
 			 && (reg_config1 & 0x3F) == 0x00
 			 && reg_convrate <= 0x0A) {
 				kind = adm1032;
 			} else
-			if (address == 0x4c
-			 && chip_id == 0x51 /* ADT7461 */
+			if (chip_id == 0x51 /* ADT7461 */
 			 && (reg_config1 & 0x1F) == 0x00 /* check compat mode */
 			 && reg_convrate <= 0x0A) {
 				kind = adt7461;
@@ -477,6 +540,10 @@
 		name = "lm90";
 	} else if (kind == adm1032) {
 		name = "adm1032";
+		/* The ADM1032 supports PEC, but only if combined
+		   transactions are not used. */
+		if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+			new_client->flags |= I2C_CLIENT_PEC;
 	} else if (kind == lm99) {
 		name = "lm99";
 	} else if (kind == lm86) {
@@ -529,6 +596,9 @@
 			   &sensor_dev_attr_temp2_crit_hyst.dev_attr);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
+	if (new_client->flags & I2C_CLIENT_PEC)
+		device_create_file(&new_client->dev, &dev_attr_pec);
+
 	return 0;
 
 exit_detach:
@@ -548,7 +618,10 @@
 	 */
 	i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
 				  5); /* 2 Hz */
-	config = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
+	if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) {
+		dev_warn(&client->dev, "Initialization failed!\n");
+		return;
+	}
 	if (config & 0x40)
 		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
 					  config & 0xBF); /* run */
@@ -576,21 +649,15 @@
 	down(&data->update_lock);
 
 	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
-		u8 oldh, newh;
+		u8 oldh, newh, l;
 
 		dev_dbg(&client->dev, "Updating lm90 data.\n");
-		data->temp8[0] = i2c_smbus_read_byte_data(client,
-				 LM90_REG_R_LOCAL_TEMP);
-		data->temp8[1] = i2c_smbus_read_byte_data(client,
-				 LM90_REG_R_LOCAL_LOW);
-		data->temp8[2] = i2c_smbus_read_byte_data(client,
-				 LM90_REG_R_LOCAL_HIGH);
-		data->temp8[3] = i2c_smbus_read_byte_data(client,
-				 LM90_REG_R_LOCAL_CRIT);
-		data->temp8[4] = i2c_smbus_read_byte_data(client,
-				 LM90_REG_R_REMOTE_CRIT);
-		data->temp_hyst = i2c_smbus_read_byte_data(client,
-				  LM90_REG_R_TCRIT_HYST);
+		lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, &data->temp8[0]);
+		lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[1]);
+		lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[2]);
+		lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[3]);
+		lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[4]);
+		lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
 
 		/*
 		 * There is a trick here. We have to read two registers to
@@ -606,36 +673,20 @@
 		 * then we have a valid reading. Else we have to read the low
 		 * byte again, and now we believe we have a correct reading.
 		 */
-		oldh = i2c_smbus_read_byte_data(client,
-		       LM90_REG_R_REMOTE_TEMPH);
-		data->temp11[0] = i2c_smbus_read_byte_data(client,
-				  LM90_REG_R_REMOTE_TEMPL);
-		newh = i2c_smbus_read_byte_data(client,
-		       LM90_REG_R_REMOTE_TEMPH);
-		if (newh != oldh) {
-			data->temp11[0] = i2c_smbus_read_byte_data(client,
-					  LM90_REG_R_REMOTE_TEMPL);
-#ifdef DEBUG
-			oldh = i2c_smbus_read_byte_data(client,
-			       LM90_REG_R_REMOTE_TEMPH);
-			/* oldh is actually newer */
-			if (newh != oldh)
-				dev_warn(&client->dev, "Remote temperature may be "
-					 "wrong.\n");
-#endif
-		}
-		data->temp11[0] |= (newh << 8);
+		if (lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &oldh) == 0
+		 && lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0
+		 && lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPH, &newh) == 0
+		 && (newh == oldh
+		  || lm90_read_reg(client, LM90_REG_R_REMOTE_TEMPL, &l) == 0))
+			data->temp11[0] = (newh << 8) | l;
 
-		data->temp11[1] = (i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_REMOTE_LOWH) << 8) +
-				   i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_REMOTE_LOWL);
-		data->temp11[2] = (i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_REMOTE_HIGHH) << 8) +
-				   i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_REMOTE_HIGHL);
-		data->alarms = i2c_smbus_read_byte_data(client,
-			       LM90_REG_R_STATUS);
+		if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &newh) == 0
+		 && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, &l) == 0)
+			data->temp11[1] = (newh << 8) | l;
+		if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &newh) == 0
+		 && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, &l) == 0)
+			data->temp11[2] = (newh << 8) | l;
+		lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 647b7c7..7a4b370 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -300,11 +300,10 @@
 					    | I2C_FUNC_SMBUS_WORD_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct lm92_data));
 
 	/* Fill in enough client fields so that we can read from the chip,
 	   which is required for identication */
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 16bf71f..6a82ffa 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -197,11 +197,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct max1619_data));
 
 	/* The common I2C client data is placed right before the
 	   MAX1619-specific data. */
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index cf2a357..17f745a 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -754,9 +754,8 @@
 	const char *name = "pc87360";
 	int use_thermistors = 0;
 
-	if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
+	if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(data, 0x00, sizeof(struct pc87360_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 21aa9a4..9c6cade 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -518,11 +518,10 @@
 			goto exit_release;
 	}
 
-	if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
-	memset(data, 0, sizeof(struct sis5595_data));
 
 	new_client = &data->client;
 	new_client->addr = address;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 7fe7157..2a3e21b 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -244,11 +244,10 @@
 		return -EBUSY;
 	}
 
-	if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto error_release;
 	}
-	memset(data, 0x00, sizeof(struct smsc47b397_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -299,7 +298,7 @@
 	superio_enter();
 	id = superio_inb(SUPERIO_REG_DEVID);
 
-	if (id != 0x6f) {
+	if ((id != 0x6f) && (id != 0x81)) {
 		superio_exit();
 		return -ENODEV;
 	}
@@ -310,8 +309,9 @@
 	*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
 		 |  superio_inb(SUPERIO_REG_BASE_LSB);
 
-	printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC "
-		"(base address 0x%04x, revision %u)\n", *addr, rev);
+	printk(KERN_INFO "smsc47b397: found SMSC %s "
+		"(base address 0x%04x, revision %u)\n",
+		id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
 
 	superio_exit();
 	return 0;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index c9cc683..5905c1a 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -3,7 +3,7 @@
                  for hardware monitoring
 
     Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
-    LPC47M15x and LPC47M192 Super-I/O chips.
+    LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
 
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
@@ -356,6 +356,8 @@
 	 * 0x5F) and LPC47B27x (device id 0x51) have fan control.
 	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
 	 * can do much more besides (device id 0x60).
+	 * The LPC47M997 is undocumented, but seems to be compatible with
+	 * the LPC47M192, and has the same device id.
 	 */
 	if (val == 0x51)
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
@@ -364,7 +366,8 @@
 	else if (val == 0x5F)
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
 	else if (val == 0x60)
-		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
+		printk(KERN_INFO "smsc47m1: Found SMSC "
+		       "LPC47M15x/LPC47M192/LPC47M997\n");
 	else {
 		superio_exit();
 		return -ENODEV;
@@ -396,11 +399,10 @@
 		return -EBUSY;
 	}
 
-	if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto error_release;
 	}
-	memset(data, 0x00, sizeof(struct smsc47m1_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 05ddc88..6f696f8 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -44,7 +44,7 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static unsigned short force_addr = 0;
+static unsigned short force_addr;
 module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
@@ -198,7 +198,7 @@
  but the function is very linear in the useful range (0-80 deg C), so
  we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
  is the temp at via register values 0-255: */
-static const long tempLUT[] =
+static const s16 tempLUT[] =
 { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
 	-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
 	-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
@@ -270,7 +270,7 @@
 }
 
 /* for 8-bit temperature hyst and over registers */
-#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
+#define TEMP_FROM_REG(val)	((long)tempLUT[val] * 100)
 
 /* for 10-bit temperature readings */
 static inline long TEMP_FROM_REG10(u16 val)
@@ -589,10 +589,8 @@
 	u16 val;
 
 	/* 8231 requires multiple of 256, we enforce that on 686 as well */
-	if (force_addr)
-		address = force_addr & 0xFF00;
-
 	if (force_addr) {
+		address = force_addr & 0xFF00;
 		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
 			 address);
 		if (PCIBIOS_SUCCESSFUL !=
@@ -603,11 +601,17 @@
 	    pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
 		return -ENODEV;
 	if (!(val & 0x0001)) {
-		dev_warn(&adapter->dev, "enabling sensors\n");
-		if (PCIBIOS_SUCCESSFUL !=
-		    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
-					  val | 0x0001))
+		if (force_addr) {
+			dev_info(&adapter->dev, "enabling sensors\n");
+			if (PCIBIOS_SUCCESSFUL !=
+			    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
+						  val | 0x0001))
+				return -ENODEV;
+		} else {
+			dev_warn(&adapter->dev, "sensors disabled - enable "
+				 "with force_addr=0x%x\n", address);
 			return -ENODEV;
+		}
 	}
 
 	/* Reserve the ISA region */
@@ -617,11 +621,10 @@
 		return -ENODEV;
 	}
 
-	if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
-	memset(data, 0, sizeof(struct via686a_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -708,7 +711,6 @@
 	return 0;
 }
 
-/* Called when we have found a new VIA686A. Set limits, etc. */
 static void via686a_init_client(struct i2c_client *client)
 {
 	u8 reg;
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index b60efe8..eee22a5 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -105,7 +105,9 @@
  * ISA constants
  */
 
-#define REGION_LENGTH		8
+#define REGION_ALIGNMENT	~7
+#define REGION_OFFSET		5
+#define REGION_LENGTH		2
 #define ADDR_REG_OFFSET		5
 #define DATA_REG_OFFSET		6
 
@@ -673,16 +675,16 @@
 	struct w83627ehf_data *data;
 	int i, err = 0;
 
-	if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+	if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
+	                    w83627ehf_driver.name)) {
 		err = -EBUSY;
 		goto exit;
 	}
 
-	if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
-	memset(data, 0, sizeof(struct w83627ehf_data));
 
 	client = &data->client;
 	i2c_set_clientdata(client, data);
@@ -762,7 +764,7 @@
 exit_free:
 	kfree(data);
 exit_release:
-	release_region(address, REGION_LENGTH);
+	release_region(address + REGION_OFFSET, REGION_LENGTH);
 exit:
 	return err;
 }
@@ -776,7 +778,7 @@
 
 	if ((err = i2c_detach_client(client)))
 		return err;
-	release_region(client->addr, REGION_LENGTH);
+	release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
 	kfree(data);
 
 	return 0;
@@ -807,7 +809,7 @@
 	superio_select(W83627EHF_LD_HWM);
 	val = (superio_inb(SIO_REG_ADDR) << 8)
 	    | superio_inb(SIO_REG_ADDR + 1);
-	*addr = val & ~(REGION_LENGTH - 1);
+	*addr = val & REGION_ALIGNMENT;
 	if (*addr == 0) {
 		superio_exit();
 		return -ENODEV;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 3479dc5..70ef926 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -142,10 +142,14 @@
 #define WINB_BASE_REG 0x60
 /* Constants specified below */
 
-/* Length of ISA address segment */
-#define WINB_EXTENT 8
+/* Alignment of the base address */
+#define WINB_ALIGNMENT		~7
 
-/* Where are the ISA address/data registers relative to the base address */
+/* Offset & size of I/O region we are interested in */
+#define WINB_REGION_OFFSET	5
+#define WINB_REGION_SIZE	2
+
+/* Where are the sensors address/data registers relative to the base address */
 #define W83781D_ADDR_REG_OFFSET 5
 #define W83781D_DATA_REG_OFFSET 6
 
@@ -197,7 +201,6 @@
 
 #define W83627HF_REG_PWM1 0x5A
 #define W83627HF_REG_PWM2 0x5B
-#define W83627HF_REG_PWMCLK12 0x5C
 
 #define W83627THF_REG_PWM1		0x01	/* 697HF and 637HF too */
 #define W83627THF_REG_PWM2		0x03	/* 697HF and 637HF too */
@@ -981,7 +984,7 @@
 	superio_select(W83627HF_LD_HWM);
 	val = (superio_inb(WINB_BASE_REG) << 8) |
 	       superio_inb(WINB_BASE_REG + 1);
-	*addr = val & ~(WINB_EXTENT - 1);
+	*addr = val & WINB_ALIGNMENT;
 	if (*addr == 0 && force_addr == 0) {
 		superio_exit();
 		return -ENODEV;
@@ -1000,9 +1003,10 @@
 	const char *client_name = "";
 
 	if(force_addr)
-		address = force_addr & ~(WINB_EXTENT - 1);
+		address = force_addr & WINB_ALIGNMENT;
 
-	if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
+	if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
+	                    w83627hf_driver.name)) {
 		err = -EBUSY;
 		goto ERROR0;
 	}
@@ -1041,11 +1045,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access w83627hf_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
-	memset(data, 0, sizeof(struct w83627hf_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -1148,7 +1151,7 @@
       ERROR2:
 	kfree(data);
       ERROR1:
-	release_region(address, WINB_EXTENT);
+	release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
       ERROR0:
 	return err;
 }
@@ -1163,7 +1166,7 @@
 	if ((err = i2c_detach_client(client)))
 		return err;
 
-	release_region(client->addr, WINB_EXTENT);
+	release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
 	kfree(data);
 
 	return 0;
@@ -1275,7 +1278,6 @@
 	return 0;
 }
 
-/* Called when we have found a new W83781D. It should set limits, etc. */
 static void w83627hf_init_client(struct i2c_client *client)
 {
 	struct w83627hf_data *data = i2c_get_clientdata(client);
@@ -1369,12 +1371,6 @@
 			}
 		}
 
-		if (type == w83627hf) {
-			/* enable PWM2 control (can't hurt since PWM reg
-		           should have been reset to 0xff) */
-			w83627hf_write_value(client, W83627HF_REG_PWMCLK12,
-					    0x19);
-		}
 		/* enable comparator mode for temp2 and temp3 so
 	           alarm indication will work correctly */
 		i = w83627hf_read_value(client, W83781D_REG_IRQ);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 4c43337..9265f32 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -889,12 +889,11 @@
 	const char *client_name = "";
 	struct w83781d_data *data = i2c_get_clientdata(new_client);
 
-	data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!(data->lm75[0])) {
 		err = -ENOMEM;
 		goto ERROR_SC_0;
 	}
-	memset(data->lm75[0], 0x00, sizeof (struct i2c_client));
 
 	id = i2c_adapter_id(adapter);
 
@@ -919,13 +918,11 @@
 	}
 
 	if (kind != w83783s) {
-
-		data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+		data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 		if (!(data->lm75[1])) {
 			err = -ENOMEM;
 			goto ERROR_SC_1;
 		}
-		memset(data->lm75[1], 0x0, sizeof(struct i2c_client));
 
 		if (force_subclients[0] == id &&
 		    force_subclients[1] == address) {
@@ -1064,11 +1061,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access w83781d_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
-	memset(data, 0, sizeof(struct w83781d_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -1451,7 +1447,6 @@
 	return 0;
 }
 
-/* Called when we have found a new W83781D. It should set limits, etc. */
 static void
 w83781d_init_client(struct i2c_client *client)
 {
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index ba0c280..4be59db 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1086,11 +1086,10 @@
 	int err;
 	struct i2c_client *sub_client;
 
-	(*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	(*sub_cli) = sub_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!(sub_client)) {
 		return -ENOMEM;
 	}
-	memset(sub_client, 0x00, sizeof(struct i2c_client));
 	sub_client->addr = 0x48 + addr;
 	i2c_set_clientdata(sub_client, NULL);
 	sub_client->adapter = adapter;
@@ -1184,11 +1183,10 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access w83792d_{read,write}_value. */
 
-	if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR0;
 	}
-	memset(data, 0, sizeof(struct w83792d_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
@@ -1429,7 +1427,6 @@
 	return 0;
 }
 
-/* Called when we have found a new W83792D. It should set limits, etc. */
 static void
 w83792d_init_client(struct i2c_client *client)
 {
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 133e34a..f495b63 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -37,6 +37,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 
 /* How many retries on register read error */
@@ -73,7 +74,7 @@
  * The W83L785TS-S uses signed 8-bit values.
  */
 
-#define TEMP_FROM_REG(val)	((val & 0x80 ? val-0x100 : val) * 1000)
+#define TEMP_FROM_REG(val)	((val) * 1000)
 
 /*
  * Functions declaration
@@ -111,27 +112,24 @@
 	unsigned long last_updated; /* in jiffies */
 
 	/* registers values */
-	u8 temp, temp_over;
+	s8 temp[2]; /* 0: input
+		       1: critical limit */
 };
 
 /*
  * Sysfs stuff
  */
 
-static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+	char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct w83l785ts_data *data = w83l785ts_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
 }
 
-static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct w83l785ts_data *data = w83l785ts_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
-}
-
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
-static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_over, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
 
 /*
  * Real code
@@ -158,12 +156,10 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct w83l785ts_data));
-
 
 	/* The common I2C client data is placed right before the
 	 * W83L785TS-specific data. */
@@ -228,7 +224,7 @@
 	init_MUTEX(&data->update_lock);
 
 	/* Default values in case the first read fails (unlikely). */
-	data->temp_over = data->temp = 0;
+	data->temp[1] = data->temp[0] = 0;
 
 	/* Tell the I2C layer a new client has arrived. */
 	if ((err = i2c_attach_client(new_client))) 
@@ -246,8 +242,10 @@
 		goto exit_detach;
 	}
 
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
+	device_create_file(&new_client->dev,
+			   &sensor_dev_attr_temp1_input.dev_attr);
+	device_create_file(&new_client->dev,
+			   &sensor_dev_attr_temp1_max.dev_attr);
 
 	return 0;
 
@@ -305,10 +303,10 @@
 
 	if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
 		dev_dbg(&client->dev, "Updating w83l785ts data.\n");
-		data->temp = w83l785ts_read_value(client,
-			     W83L785TS_REG_TEMP, data->temp);
-		data->temp_over = w83l785ts_read_value(client,
-				  W83L785TS_REG_TEMP_OVER, data->temp_over);
+		data->temp[0] = w83l785ts_read_value(client,
+				W83L785TS_REG_TEMP, data->temp[0]);
+		data->temp[1] = w83l785ts_read_value(client,
+				W83L785TS_REG_TEMP_OVER, data->temp[1]);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index beb10ed..82946ac 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -34,7 +34,7 @@
 #define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
 #define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
 
-static int i2c_debug=0;
+static int i2c_debug;
 
 #define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
 #define pca_inw(adap, reg) adap->read_byte(adap, reg)
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 8ed5ad1..938848a 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -42,7 +42,7 @@
 
 /* module parameters:
  */
-static int bit_scan=0;	/* have a look at what's hanging 'round		*/
+static int bit_scan;	/* have a look at what's hanging 'round		*/
 
 
 static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, 
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 3badfec..4010fe9 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -135,11 +135,12 @@
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  810/815 family of mainboard I2C interfaces.  Specifically, the 
-	  following versions of the chipset is supported:
+	  following versions of the chipset are supported:
 	    i810AA
 	    i810AB
 	    i810E
 	    i815
+	    i845G
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-i810.
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index f021acd..ba90f51 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -134,7 +134,7 @@
 					/*  -> Read  = 1		*/
 #define	ALI1535_SMBIO_EN	0x04	/* SMB I/O Space enable		*/
 
-
+static struct pci_driver ali1535_driver;
 static unsigned short ali1535_smba;
 static DECLARE_MUTEX(i2c_ali1535_sem);
 
@@ -162,7 +162,8 @@
 		goto exit;
 	}
 
-	if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb")) {
+	if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
+			    ali1535_driver.name)) {
 		dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
 			ali1535_smba);
 		goto exit;
@@ -480,7 +481,6 @@
 	.owner		= THIS_MODULE,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 static struct pci_device_id ali1535_ids[] = {
@@ -513,6 +513,7 @@
 }
 
 static struct pci_driver ali1535_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "ali1535_smbus",
 	.id_table	= ali1535_ids,
 	.probe		= ali1535_probe,
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 8694750..f1a62d8 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -60,6 +60,7 @@
 
 #define HST_CNTL2_SIZEMASK	0x38
 
+static struct pci_driver ali1563_pci_driver;
 static unsigned short ali1563_smba;
 
 static int ali1563_transaction(struct i2c_adapter * a, int size)
@@ -350,7 +351,8 @@
 		dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
 		goto Err;
 	}
-	if (!request_region(ali1563_smba,ALI1563_SMB_IOSIZE,"i2c-ali1563")) {
+	if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
+			    ali1563_pci_driver.name)) {
 		dev_warn(&dev->dev,"Could not allocate I/O space");
 		goto Err;
 	}
@@ -406,7 +408,8 @@
 MODULE_DEVICE_TABLE (pci, ali1563_id_table);
 
 static struct pci_driver ali1563_pci_driver = {
- 	.name		= "ali1563_i2c",
+	.owner		= THIS_MODULE,
+ 	.name		= "ali1563_smbus",
 	.id_table	= ali1563_id_table,
  	.probe		= ali1563_probe,
 	.remove		= __devexit_p(ali1563_remove),
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index b3f50bf..400b08e 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -125,12 +125,13 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static u16 force_addr = 0;
+static u16 force_addr;
 module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the i2c controller");
 
-static unsigned short ali15x3_smba = 0;
+static struct pci_driver ali15x3_driver;
+static unsigned short ali15x3_smba;
 
 static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
 {
@@ -166,7 +167,8 @@
 	if(force_addr)
 		ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
 
-	if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) {
+	if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
+			    ali15x3_driver.name)) {
 		dev_err(&ALI15X3_dev->dev,
 			"ALI15X3_smb region 0x%x already in use!\n",
 			ali15x3_smba);
@@ -470,7 +472,6 @@
 	.owner		= THIS_MODULE,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 static struct pci_device_id ali15x3_ids[] = {
@@ -503,6 +504,7 @@
 }
 
 static struct pci_driver ali15x3_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "ali15x3_smbus",
 	.id_table	= ali15x3_ids,
 	.probe		= ali15x3_probe,
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 4e553e8..f51ab65 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -169,12 +169,12 @@
 	init_MUTEX(&amd756_lock);
 
 	/* Define the 5 virtual adapters and algorithms structures */
-	if (!(s4882_adapter = kmalloc(5 * sizeof(struct i2c_adapter),
+	if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
 				      GFP_KERNEL))) {
 		error = -ENOMEM;
 		goto ERROR1;
 	}
-	if (!(s4882_algo = kmalloc(5 * sizeof(struct i2c_algorithm),
+	if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm),
 				   GFP_KERNEL))) {
 		error = -ENOMEM;
 		goto ERROR2;
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 6ad0603..de035d1 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -85,8 +85,8 @@
 #define AMD756_PROCESS_CALL	0x04
 #define AMD756_BLOCK_DATA	0x05
 
-
-static unsigned short amd756_ioport = 0;
+static struct pci_driver amd756_driver;
+static unsigned short amd756_ioport;
 
 /* 
   SMBUS event = I/O 28-29 bit 11
@@ -303,7 +303,6 @@
 	.owner		= THIS_MODULE,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
@@ -365,7 +364,7 @@
 		amd756_ioport += SMB_ADDR_OFFSET;
 	}
 
-	if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
+	if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
 		dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
 			amd756_ioport);
 		return -ENODEV;
@@ -402,6 +401,7 @@
 }
 
 static struct pci_driver amd756_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "amd756_smbus",
 	.id_table	= amd756_ids,
 	.probe		= amd756_probe,
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 45ea24b..f3b79a6 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -30,6 +30,8 @@
 	int size;
 };
 
+static struct pci_driver amd8111_driver;
+
 /*
  * AMD PCI control registers definitions.
  */
@@ -242,7 +244,6 @@
 			break;
 
 		case I2C_SMBUS_BLOCK_PROC_CALL:
-			protocol |= pec;
 			len = min_t(u8, data->block[0], 31);
 			amd_ec_write(smbus, AMD_SMB_CMD, command);
 			amd_ec_write(smbus, AMD_SMB_BCNT, len);
@@ -252,13 +253,6 @@
 			read_write = I2C_SMBUS_READ;
 			break;
 
-		case I2C_SMBUS_WORD_DATA_PEC:
-		case I2C_SMBUS_BLOCK_DATA_PEC:
-		case I2C_SMBUS_PROC_CALL_PEC:
-		case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
-			dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
-			return -1;
-
 		default:
 			dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
 			return -1;
@@ -343,16 +337,15 @@
 	if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
 		return -ENODEV;
 
-	smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL);
+	smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
 	if (!smbus)
 		return -ENOMEM;
-	memset(smbus, 0, sizeof(struct amd_smbus));
 
 	smbus->dev = dev;
 	smbus->base = pci_resource_start(dev, 0);
 	smbus->size = pci_resource_len(dev, 0);
 
-	if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0"))
+	if (!request_region(smbus->base, smbus->size, amd8111_driver.name))
 		goto out_kfree;
 
 	smbus->adapter.owner = THIS_MODULE;
@@ -391,6 +384,7 @@
 }
 
 static struct pci_driver amd8111_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "amd8111_smbus2",
 	.id_table	= amd8111_ids,
 	.probe		= amd8111_probe,
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 6930b66..59f8308 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -22,7 +22,7 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of 
+/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
    for Alpha Processor Inc. UP-2000(+) boards */
 
 #include <linux/kernel.h>
@@ -46,12 +46,14 @@
 #define DEFAULT_BASE 0x330
 
 static int base;
+static u8 __iomem *base_iomem;
+
 static int irq;
 static int clock  = 0x1c;
 static int own    = 0x55;
 static int mmapped;
 
-/* vdovikin: removed static struct i2c_pcf_isa gpi; code - 
+/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
   this module in real supports only one device, due to missing arguments
   in some functions, called from the algo-pcf module. Sometimes it's
   need to be rewriten - but for now just remove this for simpler reading */
@@ -60,40 +62,33 @@
 static int pcf_pending;
 static spinlock_t lock;
 
+static struct i2c_adapter pcf_isa_ops;
+
 /* ----- local functions ----------------------------------------------	*/
 
 static void pcf_isa_setbyte(void *data, int ctl, int val)
 {
-	int address = ctl ? (base + 1) : base;
+	u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
 
 	/* enable irq if any specified for serial operation */
 	if (ctl && irq && (val & I2C_PCF_ESO)) {
 		val |= I2C_PCF_ENI;
 	}
 
-	pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255);
-
-	switch (mmapped) {
-	case 0: /* regular I/O */
-		outb(val, address);
-		break;
-	case 2: /* double mapped I/O needed for UP2000 board,
-                   I don't know why this... */
-		writeb(val, (void *)address);
-		/* fall */
-	case 1: /* memory mapped I/O */
-		writeb(val, (void *)address);
-		break;
-	}
+	pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val);
+	iowrite8(val, address);
+#ifdef __alpha__
+	/* API UP2000 needs some hardware fudging to make the write stick */
+	iowrite8(val, address);
+#endif
 }
 
 static int pcf_isa_getbyte(void *data, int ctl)
 {
-	int address = ctl ? (base + 1) : base;
-	int val = mmapped ? readb((void *)address) : inb(address);
+	u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
+	int val = ioread8(address);
 
-	pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val);
-
+	pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
 	return (val);
 }
 
@@ -149,16 +144,40 @@
 {
 	spin_lock_init(&lock);
 	if (!mmapped) {
-		if (!request_region(base, 2, "i2c (isa bus adapter)")) {
-			printk(KERN_ERR
-			       "i2c-elektor: requested I/O region (0x%X:2) "
-			       "is in use.\n", base);
+		if (!request_region(base, 2, pcf_isa_ops.name)) {
+			printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
+			       "in use\n", pcf_isa_ops.name, base);
+			return -ENODEV;
+		}
+		base_iomem = ioport_map(base, 2);
+		if (!base_iomem) {
+			printk(KERN_ERR "%s: remap of I/O region %#x failed\n",
+			       pcf_isa_ops.name, base);
+			release_region(base, 2);
+			return -ENODEV;
+		}
+	} else {
+		if (!request_mem_region(base, 2, pcf_isa_ops.name)) {
+			printk(KERN_ERR "%s: requested memory region (%#x:2) "
+			       "is in use\n", pcf_isa_ops.name, base);
+			return -ENODEV;
+		}
+		base_iomem = ioremap(base, 2);
+		if (base_iomem == NULL) {
+			printk(KERN_ERR "%s: remap of memory region %#x "
+			       "failed\n", pcf_isa_ops.name, base);
+			release_mem_region(base, 2);
 			return -ENODEV;
 		}
 	}
+	pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base,
+		 base_iomem);
+
 	if (irq > 0) {
-		if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", NULL) < 0) {
-			printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq);
+		if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name,
+				NULL) < 0) {
+			printk(KERN_ERR "%s: Request irq%d failed\n",
+			       pcf_isa_ops.name, irq);
 			irq = 0;
 		} else
 			enable_irq(irq);
@@ -186,47 +205,49 @@
 	.class		= I2C_CLASS_HWMON,
 	.id		= I2C_HW_P_ELEK,
 	.algo_data	= &pcf_isa_data,
-	.name		= "PCF8584 ISA adapter",
+	.name		= "i2c-elektor",
 };
 
-static int __init i2c_pcfisa_init(void) 
+static int __init i2c_pcfisa_init(void)
 {
 #ifdef __alpha__
-	/* check to see we have memory mapped PCF8584 connected to the 
+	/* check to see we have memory mapped PCF8584 connected to the
 	Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
 	if (base == 0) {
 		struct pci_dev *cy693_dev;
-		
-		cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ, 
+
+		cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
 					   PCI_DEVICE_ID_CONTAQ_82C693, NULL);
 		if (cy693_dev) {
-			char config;
+			unsigned char config;
 			/* yeap, we've found cypress, let's check config */
 			if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
-				
-				pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config);
+
+				pr_debug("%s: found cy82c693, config "
+					 "register 0x47 = 0x%02x\n",
+					 pcf_isa_ops.name, config);
 
 				/* UP2000 board has this register set to 0xe1,
-                                   but the most significant bit as seems can be 
+				   but the most significant bit as seems can be
 				   reset during the proper initialisation
-                                   sequence if guys from API decides to do that
-                                   (so, we can even enable Tsunami Pchip
-                                   window for the upper 1 Gb) */
+				   sequence if guys from API decides to do that
+				   (so, we can even enable Tsunami Pchip
+				   window for the upper 1 Gb) */
 
 				/* so just check for ROMCS at 0xe0000,
-                                   ROMCS enabled for writes
+				   ROMCS enabled for writes
 				   and external XD Bus buffer in use. */
 				if ((config & 0x7f) == 0x61) {
 					/* seems to be UP2000 like board */
 					base = 0xe0000;
-                                        /* I don't know why we need to
-                                           write twice */
-					mmapped = 2;
-                                        /* UP2000 drives ISA with
+					mmapped = 1;
+					/* UP2000 drives ISA with
 					   8.25 MHz (PCI/4) clock
 					   (this can be read from cypress) */
 					clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
-					printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n");
+					pr_info("%s: found API UP2000 like "
+						"board, will probe PCF8584 "
+						"later\n", pcf_isa_ops.name);
 				}
 			}
 			pci_dev_put(cy693_dev);
@@ -236,12 +257,11 @@
 
 	/* sanity checks for mmapped I/O */
 	if (mmapped && base < 0xc8000) {
-		printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
+		printk(KERN_ERR "%s: incorrect base address (%#x) specified "
+		       "for mmapped I/O\n", pcf_isa_ops.name, base);
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n");
-
 	if (base == 0) {
 		base = DEFAULT_BASE;
 	}
@@ -251,8 +271,8 @@
 		return -ENODEV;
 	if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
 		goto fail;
-	
-	printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base);
+
+	dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
 
 	return 0;
 
@@ -262,8 +282,13 @@
 		free_irq(irq, NULL);
 	}
 
-	if (!mmapped)
-		release_region(base , 2);
+	if (!mmapped) {
+		ioport_unmap(base_iomem);
+		release_region(base, 2);
+	} else {
+		iounmap(base_iomem);
+		release_mem_region(base, 2);
+	}
 	return -ENODEV;
 }
 
@@ -276,8 +301,13 @@
 		free_irq(irq, NULL);
 	}
 
-	if (!mmapped)
-		release_region(base , 2);
+	if (!mmapped) {
+		ioport_unmap(base_iomem);
+		release_region(base, 2);
+	} else {
+		iounmap(base_iomem);
+		release_mem_region(base, 2);
+	}
 }
 
 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index e0cb3b0..1b5354e 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -155,6 +155,7 @@
 
 
 static struct pci_driver hydra_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "hydra_smbus",
 	.id_table	= hydra_ids,
 	.probe		= hydra_probe,
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 709beab..4f63195 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -52,10 +52,6 @@
 #include <linux/i2c.h>
 #include <asm/io.h>
 
-#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
-#define HAVE_PEC
-#endif
-
 /* I801 SMBus address offsets */
 #define SMBHSTSTS	(0 + i801_smba)
 #define SMBHSTCNT	(2 + i801_smba)
@@ -106,10 +102,11 @@
 		 "EXTREMELY DANGEROUS!");
 
 static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data,
-				  char read_write, int command);
+static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+				  int command, int hwpec);
 
 static unsigned short i801_smba;
+static struct pci_driver i801_driver;
 static struct pci_dev *I801_dev;
 static int isich4;
 
@@ -143,7 +140,7 @@
 		}
 	}
 
-	if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
+	if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) {
 		dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
 			i801_smba);
 		error_return = -EBUSY;
@@ -252,7 +249,7 @@
 
 /* All-inclusive block transaction function */
 static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
-				  int command)
+				  int command, int hwpec)
 {
 	int i, len;
 	int smbcmd;
@@ -391,8 +388,7 @@
 			goto END;
 	}
 
-#ifdef HAVE_PEC
-	if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+	if (hwpec) {
 		/* wait for INTR bit as advised by Intel */
 		timeout = 0;
 		do {
@@ -406,7 +402,6 @@
 		}
 		outb_p(temp, SMBHSTSTS); 
 	}
-#endif
 	result = 0;
 END:
 	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
@@ -421,14 +416,13 @@
 		       unsigned short flags, char read_write, u8 command,
 		       int size, union i2c_smbus_data * data)
 {
-	int hwpec = 0;
+	int hwpec;
 	int block = 0;
 	int ret, xact = 0;
 
-#ifdef HAVE_PEC
-	if(isich4)
-		hwpec = (flags & I2C_CLIENT_PEC) != 0;
-#endif
+	hwpec = isich4 && (flags & I2C_CLIENT_PEC)
+		&& size != I2C_SMBUS_QUICK
+		&& size != I2C_SMBUS_I2C_BLOCK_DATA;
 
 	switch (size) {
 	case I2C_SMBUS_QUICK:
@@ -463,11 +457,6 @@
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
 	case I2C_SMBUS_I2C_BLOCK_DATA:
-#ifdef HAVE_PEC
-	case I2C_SMBUS_BLOCK_DATA_PEC:
-		if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
-			size = I2C_SMBUS_BLOCK_DATA_PEC;
-#endif
 		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
 		       SMBHSTADD);
 		outb_p(command, SMBHSTCMD);
@@ -479,27 +468,18 @@
 		return -1;
 	}
 
-#ifdef HAVE_PEC
-	if(isich4 && hwpec) {
-		if(size != I2C_SMBUS_QUICK &&
-		   size != I2C_SMBUS_I2C_BLOCK_DATA)
-			outb_p(1, SMBAUXCTL);	/* enable HW PEC */
-	}
-#endif
+	if (hwpec)
+		outb_p(1, SMBAUXCTL);	/* enable hardware PEC */
+
 	if(block)
-		ret = i801_block_transaction(data, read_write, size);
+		ret = i801_block_transaction(data, read_write, size, hwpec);
 	else {
 		outb_p(xact | ENABLE_INT9, SMBHSTCNT);
 		ret = i801_transaction();
 	}
 
-#ifdef HAVE_PEC
-	if(isich4 && hwpec) {
-		if(size != I2C_SMBUS_QUICK &&
-		   size != I2C_SMBUS_I2C_BLOCK_DATA)
-			outb_p(0, SMBAUXCTL);
-	}
-#endif
+	if (hwpec)
+		outb_p(0, SMBAUXCTL);	/* disable hardware PEC */
 
 	if(block)
 		return ret;
@@ -526,12 +506,7 @@
 	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
-#ifdef HAVE_PEC
-	     | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
-	                 I2C_FUNC_SMBUS_HWPEC_CALC
-	               : 0)
-#endif
-	    ;
+	     | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
 }
 
 static struct i2c_algorithm smbus_algorithm = {
@@ -543,7 +518,6 @@
 	.owner		= THIS_MODULE,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 static struct pci_device_id i801_ids[] = {
@@ -586,6 +560,7 @@
 }
 
 static struct pci_driver i801_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "i801_smbus",
 	.id_table	= i801_ids,
 	.probe		= i801_probe,
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index 0ff7016..52bc305 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -32,6 +32,7 @@
    i810AB		7123           
    i810E		7125           
    i815			1132           
+   i845G		2562
 */
 
 #include <linux/kernel.h>
@@ -232,6 +233,7 @@
 }
 
 static struct pci_driver i810_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "i810_smbus",
 	.id_table	= i810_ids,
 	.probe		= i810_probe,
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index a3ed959..1a58725 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -672,13 +672,12 @@
 		printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
 			ocp->def->index);
 
-	if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){
+	if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
 		printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
 			ocp->def->index);
 		return -ENOMEM;
 	}
 
-	memset(dev, 0, sizeof(*dev));
 	dev->idx = ocp->def->index;
 	ocp_set_drvdata(ocp, dev);
 	
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 7bd9102..9888fae 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -43,7 +43,7 @@
 #include "i2c-iop3xx.h"
 
 /* global unit counter */
-static int i2c_id = 0;
+static int i2c_id;
 
 static inline unsigned char 
 iic_cook_addr(struct i2c_msg *msg) 
@@ -440,19 +440,17 @@
 	struct i2c_adapter *new_adapter;
 	struct i2c_algo_iop3xx_data *adapter_data;
 
-	new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
 	if (!new_adapter) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	memset((void*)new_adapter, 0, sizeof(*new_adapter));
 
-	adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
+	adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
 	if (!adapter_data) {
 		ret = -ENOMEM;
 		goto free_adapter;
 	}
-	memset((void*)adapter_data, 0, sizeof(*adapter_data));
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -525,6 +523,7 @@
 
 
 static struct device_driver iop3xx_i2c_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "IOP3xx-I2C",
 	.bus		= &platform_bus_type,
 	.probe		= iop3xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index bdc6806..4fdc024 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -92,6 +92,7 @@
 
 	/* Add the driver to the list of i2c drivers in the driver core */
 	driver->driver.name = driver->name;
+	driver->driver.owner = driver->owner;
 	driver->driver.bus = &i2c_bus_type;
 	driver->driver.probe = i2c_isa_device_probe;
 	driver->driver.remove = i2c_isa_device_remove;
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 1956af3..42016ee 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -36,6 +36,8 @@
 #include <asm/hardware.h>	/* Pick up IXP2000-specific bits */
 #include <asm/arch/gpio.h>
 
+static struct device_driver ixp2000_i2c_driver;
+
 static inline int ixp2000_scl_pin(void *data)
 {
 	return ((struct ixp2000_i2c_pins*)data)->scl_pin;
@@ -104,11 +106,10 @@
 	struct platform_device *plat_dev = to_platform_device(dev);
 	struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
 	struct ixp2000_i2c_data *drv_data = 
-		kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
+		kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
 
 	if (!drv_data)
 		return -ENOMEM;
-	memzero(drv_data, sizeof(*drv_data));
 	drv_data->gpio_pins = gpio;
 
 	drv_data->algo_data.data = gpio;
@@ -121,6 +122,8 @@
 	drv_data->algo_data.timeout = 100;
 
 	drv_data->adapter.id = I2C_HW_B_IXP2000,
+	strlcpy(drv_data->adapter.name, ixp2000_i2c_driver.name,
+		I2C_NAME_SIZE);
 	drv_data->adapter.algo_data = &drv_data->algo_data,
 
 	drv_data->adapter.dev.parent = &plat_dev->dev;
@@ -142,6 +145,7 @@
 }
 
 static struct device_driver ixp2000_i2c_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "IXP2000-I2C",
 	.bus		= &platform_bus_type,
 	.probe		= ixp2000_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index f6f5ca3..69303ab 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -35,6 +35,8 @@
 
 #include <asm/hardware.h>	/* Pick up IXP4xx-specific bits */
 
+static struct device_driver ixp4xx_i2c_driver;
+
 static inline int ixp4xx_scl_pin(void *data)
 {
 	return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
@@ -105,12 +107,11 @@
 	struct platform_device *plat_dev = to_platform_device(dev);
 	struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
 	struct ixp4xx_i2c_data *drv_data = 
-		kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
+		kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
 
 	if(!drv_data)
 		return -ENOMEM;
 
-	memzero(drv_data, sizeof(struct ixp4xx_i2c_data));
 	drv_data->gpio_pins = gpio;
 
 	/*
@@ -129,6 +130,8 @@
 	drv_data->algo_data.timeout = 100;
 
 	drv_data->adapter.id = I2C_HW_B_IXP4XX;
+	strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.name,
+		I2C_NAME_SIZE);
 	drv_data->adapter.algo_data = &drv_data->algo_data;
 
 	drv_data->adapter.dev.parent = &plat_dev->dev;
@@ -151,6 +154,7 @@
 }
 
 static struct device_driver ixp4xx_i2c_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "IXP4XX-I2C",
 	.bus		= &platform_bus_type,
 	.probe		= ixp4xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index eff5896..d61f748 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -535,13 +535,12 @@
 
 	tsize = sizeof(struct keywest_iface) +
 		(sizeof(struct keywest_chan) + 4) * nchan;
-	iface = (struct keywest_iface *) kmalloc(tsize, GFP_KERNEL);
+	iface = kzalloc(tsize, GFP_KERNEL);
 	if (iface == NULL) {
 		printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n");
 		pmac_low_i2c_unlock(np);
 		return -ENOMEM;
 	}
-	memset(iface, 0, tsize);
 	spin_lock_init(&iface->lock);
 	init_completion(&iface->complete);
 	iface->node = of_node_get(np);
@@ -716,6 +715,7 @@
 
 static struct macio_driver i2c_keywest_macio_driver = 
 {
+	.owner		= THIS_MODULE,
 	.name 		= "i2c-keywest",
 	.match_table	= i2c_keywest_match,
 	.probe		= create_iface_macio,
@@ -724,6 +724,7 @@
 
 static struct of_platform_driver i2c_keywest_of_platform_driver = 
 {
+	.owner		= THIS_MODULE,
 	.name 		= "i2c-keywest",
 	.match_table	= i2c_keywest_match,
 	.probe		= create_iface_of_platform,
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f065583..8491633 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -296,10 +296,9 @@
 
 	pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
 
-	if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+	if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
 		return -ENOMEM;
 	}
-	memset(i2c, 0, sizeof(*i2c));
 
 	i2c->irq = platform_get_irq(pdev, 0);
 	i2c->flags = pdata->device_flags;
@@ -361,6 +360,7 @@
 
 /* Structure for a device driver */
 static struct device_driver fsl_i2c_driver = {
+	.owner = THIS_MODULE,
 	.name = "fsl-i2c",
 	.bus = &platform_bus_type,
 	.probe = fsl_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 99abca4..d0d2a6f 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -500,13 +500,10 @@
 	if ((pd->id != 0) || !pdata)
 		return -ENODEV;
 
-	drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
-
+	drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
 	if (!drv_data)
 		return -ENOMEM;
 
-	memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data));
-
 	if (mv64xxx_i2c_map_regs(pd, drv_data)) {
 		rc = -ENODEV;
 		goto exit_kfree;
@@ -570,6 +567,7 @@
 }
 
 static struct device_driver mv64xxx_i2c_driver = {
+	.owner	= THIS_MODULE,
 	.name	= MV64XXX_I2C_CTLR_NAME,
 	.bus	= &platform_bus_type,
 	.probe	= mv64xxx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index fe9c0f4..fd26036 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -97,6 +97,7 @@
 #define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA		0x4a
 #define NVIDIA_SMB_PRTCL_PEC			0x80
 
+static struct pci_driver nforce2_driver;
 
 static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
 		       unsigned short flags, char read_write,
@@ -113,7 +114,6 @@
 	.owner          = THIS_MODULE,
 	.class          = I2C_CLASS_HWMON,
 	.algo           = &smbus_algorithm,
-	.name   	= "unset",
 };
 
 /* Return -1 on error. See smbus.h for more information */
@@ -188,13 +188,6 @@
 			dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
 			return -1;
 
-		case I2C_SMBUS_WORD_DATA_PEC:
-		case I2C_SMBUS_BLOCK_DATA_PEC:
-		case I2C_SMBUS_PROC_CALL_PEC:
-		case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
-			dev_err(&adap->dev, "Unexpected software PEC transaction %d\n.", size);
-			return -1;
-
 		default:
 			dev_err(&adap->dev, "Unsupported transaction %d\n", size);
 			return -1;
@@ -285,7 +278,7 @@
 	smbus->base = iobase & 0xfffc;
 	smbus->size = 8;
 
-	if (!request_region(smbus->base, smbus->size, "nForce2 SMBus")) {
+	if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
 		dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
 			smbus->base, smbus->base+smbus->size-1, name);
 		return -1;
@@ -313,10 +306,8 @@
 	int res1, res2;
 
 	/* we support 2 SMBus adapters */
-	if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus),
-				       	GFP_KERNEL)))
+	if (!(smbuses = kzalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL)))
 		return -ENOMEM;
-	memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
 	pci_set_drvdata(dev, smbuses);
 
 	/* SMBus adapter 1 */
@@ -356,6 +347,7 @@
 }
 
 static struct pci_driver nforce2_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "nForce2_smbus",
 	.id_table	= nforce2_ids,
 	.probe		= nforce2_probe,
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 71a2502..2854d85 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -155,12 +155,11 @@
 {
 	struct i2c_par *adapter;
 	
-	adapter = kmalloc(sizeof(struct i2c_par), GFP_KERNEL);
+	adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);
 	if (adapter == NULL) {
-		printk(KERN_ERR "i2c-parport: Failed to kmalloc\n");
+		printk(KERN_ERR "i2c-parport: Failed to kzalloc\n");
 		return;
 	}
-	memset(adapter, 0x00, sizeof(struct i2c_par));
 
 	pr_debug("i2c-parport: attaching to %s\n", port->name);
 	adapter->pdev = parport_register_device(port, "i2c-parport",
@@ -232,7 +231,7 @@
 	}
 }
 
-static struct parport_driver i2c_driver = {
+static struct parport_driver i2c_parport_driver = {
 	.name	= "i2c-parport",
 	.attach	= i2c_parport_attach,
 	.detach	= i2c_parport_detach,
@@ -250,12 +249,12 @@
 		type = 0;
 	}
 	
-	return parport_register_driver(&i2c_driver);
+	return parport_register_driver(&i2c_parport_driver);
 }
 
 static void __exit i2c_parport_exit(void)
 {
-	parport_unregister_driver(&i2c_driver);
+	parport_unregister_driver(&i2c_parport_driver);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 6d48a4d..7d63eec 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -90,13 +90,13 @@
 
 /* If force is set to anything different from 0, we forcibly enable the
    PIIX4. DANGEROUS! */
-static int force = 0;
+static int force;
 module_param (force, int, 0);
 MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the PIIX4 at the given address. VERY DANGEROUS! */
-static int force_addr = 0;
+static int force_addr;
 module_param (force_addr, int, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Forcibly enable the PIIX4 at the given address. "
@@ -104,14 +104,15 @@
 
 /* If fix_hstcfg is set to anything different from 0, we reset one of the
    registers to be a valid value. */
-static int fix_hstcfg = 0;
+static int fix_hstcfg;
 module_param (fix_hstcfg, int, 0);
 MODULE_PARM_DESC(fix_hstcfg,
 		"Fix config register. Needed on some boards (Force CPCI735).");
 
 static int piix4_transaction(void);
 
-static unsigned short piix4_smba = 0;
+static unsigned short piix4_smba;
+static struct pci_driver piix4_driver;
 static struct i2c_adapter piix4_adapter;
 
 static struct dmi_system_id __devinitdata piix4_dmi_table[] = {
@@ -157,7 +158,7 @@
 		}
 	}
 
-	if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) {
+	if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
 		dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n",
 			piix4_smba);
 		return -ENODEV;
@@ -407,7 +408,6 @@
 	.owner		= THIS_MODULE,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 static struct pci_device_id piix4_ids[] = {
@@ -462,6 +462,7 @@
 }
 
 static struct pci_driver piix4_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "piix4_smbus",
 	.id_table	= piix4_ids,
 	.probe		= piix4_probe,
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
index 8a9f564..bfefe7f 100644
--- a/drivers/i2c/busses/i2c-pmac-smu.c
+++ b/drivers/i2c/busses/i2c-pmac-smu.c
@@ -211,12 +211,11 @@
 	}
 	busid = *reg;
 
-	iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL);
+	iface = kzalloc(sizeof(struct smu_iface), GFP_KERNEL);
 	if (iface == NULL) {
 		printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
 		return -ENOMEM;
 	}
-	memset(iface, 0, sizeof(struct smu_iface));
 	init_completion(&iface->complete);
 	iface->busid = busid;
 
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 83fd16d..42cb1d8 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -83,11 +83,6 @@
 /*
  * i2c configuration
  */
-#ifndef I2C_HW_B_S3VIA
-#define I2C_HW_B_S3VIA	0x18	/* S3VIA ProSavage adapter		*/
-#endif
-
-/* delays */
 #define CYCLE_DELAY	10
 #define TIMEOUT		(HZ / 2)
 
@@ -241,14 +236,12 @@
 	struct s_i2c_chip *chip;
 	struct s_i2c_bus  *bus;
 
-        pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); 
+	pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
 	chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
 	if (chip == NULL) {
 		return -ENOMEM;
 	}
 
-	memset(chip, 0, sizeof(struct s_i2c_chip));
-
 	base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
 	len  = dev->resource[0].end - base + 1;
 	chip->mmio = ioremap_nocache(base, len);
@@ -308,6 +301,7 @@
 MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
 
 static struct pci_driver prosavage_driver = {
+	.owner		=	THIS_MODULE,
 	.name		=	"prosavage_smbus",
 	.id_table	=	prosavage_pci_tbl,
 	.probe		=	prosavage_probe,
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 73a092f..6ced28e 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -879,14 +879,12 @@
 }
 
 #ifdef CONFIG_PM
-static int s3c24xx_i2c_resume(struct device *dev, u32 level)
+static int s3c24xx_i2c_resume(struct device *dev)
 {
 	struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
-	
-	if (i2c != NULL && level == RESUME_ENABLE) {
-		dev_dbg(dev, "resume: level %d\n", level);
+
+	if (i2c != NULL)
 		s3c24xx_i2c_init(i2c);
-	}
 
 	return 0;
 }
@@ -898,6 +896,7 @@
 /* device driver for platform bus bits */
 
 static struct device_driver s3c2410_i2c_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "s3c2410-i2c",
 	.bus		= &platform_bus_type,
 	.probe		= s3c24xx_i2c_probe,
@@ -906,6 +905,7 @@
 };
 
 static struct device_driver s3c2440_i2c_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "s3c2440-i2c",
 	.bus		= &platform_bus_type,
 	.probe		= s3c24xx_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 0c85182..aebe87b 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -179,6 +179,7 @@
 }
 
 static struct pci_driver savage4_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "savage4_smbus",
 	.id_table	= savage4_ids,
 	.probe		= savage4_probe,
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 080318d..3ad27c3 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -123,11 +123,12 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static u16 force_addr = 0;
+static u16 force_addr;
 module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
 
-static unsigned short sis5595_base = 0;
+static struct pci_driver sis5595_driver;
+static unsigned short sis5595_base;
 
 static u8 sis5595_read(u8 reg)
 {
@@ -172,7 +173,8 @@
 
 	/* NB: We grab just the two SMBus registers here, but this may still
 	 * interfere with ACPI :-(  */
-	if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) {
+	if (!request_region(sis5595_base + SMB_INDEX, 2,
+			    sis5595_driver.name)) {
 		dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
 			sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
 		return -ENODEV;
@@ -364,7 +366,6 @@
 static struct i2c_adapter sis5595_adapter = {
 	.owner		= THIS_MODULE,
 	.class          = I2C_CLASS_HWMON,
-	.name		= "unset",
 	.algo		= &smbus_algorithm,
 };
 
@@ -397,6 +398,7 @@
 }
 
 static struct pci_driver sis5595_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "sis5595_smbus",
 	.id_table	= sis5595_ids,
 	.probe		= sis5595_probe,
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 86f0f44..7f49e5f 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -92,6 +92,8 @@
 #define SIS630_PCALL		0x04
 #define SIS630_BLOCK_DATA	0x05
 
+static struct pci_driver sis630_driver;
+
 /* insmod parameters */
 static int high_clock;
 static int force;
@@ -101,7 +103,7 @@
 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
 
 /* acpi base address */
-static unsigned short acpi_base = 0;
+static unsigned short acpi_base;
 
 /* supported chips */
 static int supported[] = {
@@ -432,7 +434,8 @@
 	dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
 
 	/* Everything is happy, let's grab the memory and set things up. */
-	if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) {
+	if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
+			    sis630_driver.name)) {
 		dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
 			"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
 		goto exit;
@@ -455,7 +458,6 @@
 static struct i2c_adapter sis630_adapter = {
 	.owner		= THIS_MODULE,
 	.class		= I2C_CLASS_HWMON,
-	.name		= "unset",
 	.algo		= &smbus_algorithm,
 };
 
@@ -494,6 +496,7 @@
 
 
 static struct pci_driver sis630_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "sis630_smbus",
 	.id_table	= sis630_ids,
 	.probe		= sis630_probe,
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index ead2ff3..6a134c0 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -82,8 +82,9 @@
 #define SIS96x_PROC_CALL  0x04
 #define SIS96x_BLOCK_DATA 0x05
 
+static struct pci_driver sis96x_driver;
 static struct i2c_adapter sis96x_adapter;
-static u16 sis96x_smbus_base = 0;
+static u16 sis96x_smbus_base;
 
 static inline u8 sis96x_read(u8 reg)
 {
@@ -257,7 +258,6 @@
 	.owner		= THIS_MODULE,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 static struct pci_device_id sis96x_ids[] = {
@@ -294,7 +294,8 @@
 			sis96x_smbus_base);
 
 	/* Everything is happy, let's grab the memory and set things up. */
-	if (!request_region(sis96x_smbus_base, SMB_IOSIZE, "sis96x-smbus")) {
+	if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
+			    sis96x_driver.name)) {
 		dev_err(&dev->dev, "SMBus registers 0x%04x-0x%04x "
 			"already in use!\n", sis96x_smbus_base,
 			sis96x_smbus_base + SMB_IOSIZE - 1);
@@ -328,6 +329,7 @@
 }
 
 static struct pci_driver sis96x_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "sis96x_smbus",
 	.id_table	= sis96x_ids,
 	.probe		= sis96x_probe,
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 040b8ab..544a38e 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -43,9 +43,9 @@
 
 /* io-region reservation */
 #define IOSPACE		0x06
-#define IOTEXT		"via-i2c"
 
-static u16 pm_io_base = 0;
+static struct pci_driver vt586b_driver;
+static u16 pm_io_base;
 
 /*
    It does not appear from the datasheet that the GPIO pins are
@@ -130,7 +130,7 @@
 	pci_read_config_word(dev, base, &pm_io_base);
 	pm_io_base &= (0xff << 8);
 
-	if (!request_region(I2C_DIR, IOSPACE, IOTEXT)) {
+	if (!request_region(I2C_DIR, IOSPACE, vt586b_driver.name)) {
 		dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE);
 		return -ENODEV;
 	}
@@ -159,6 +159,7 @@
 
 
 static struct pci_driver vt586b_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "vt586b_smbus",
 	.id_table	= vt586b_ids,
 	.probe		= vt586b_probe,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 99d209e..c9366b5 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -1,9 +1,10 @@
 /*
     i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
               monitoring
-    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>, 
+    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
     Mark D. Studebaker <mdsxyz123@yahoo.com>
+    Copyright (C) 2005  Jean Delvare <khali@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,15 +22,19 @@
 */
 
 /*
-   Supports Via devices:
-	82C596A/B (0x3050)
-	82C596B (0x3051)
-	82C686A/B
-	8231
-	8233
-	8233A (0x3147 and 0x3177)
-	8235
-	8237
+   Supports the following VIA south bridges:
+
+   Chip name          PCI ID  REV     I2C block
+   VT82C596A          0x3050             no
+   VT82C596B          0x3051             no
+   VT82C686A          0x3057  0x30       no
+   VT82C686B          0x3057  0x40       yes
+   VT8231             0x8235             no?
+   VT8233             0x3074             yes
+   VT8233A            0x3147             yes?
+   VT8235             0x3177             yes
+   VT8237R            0x3227             yes
+
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
@@ -38,7 +43,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -46,48 +50,37 @@
 
 static struct pci_dev *vt596_pdev;
 
-#define SMBBA1	   	 0x90
-#define SMBBA2     	 0x80
-#define SMBBA3     	 0xD0
+#define SMBBA1		0x90
+#define SMBBA2		0x80
+#define SMBBA3		0xD0
 
 /* SMBus address offsets */
 static unsigned short vt596_smba;
 #define SMBHSTSTS	(vt596_smba + 0)
-#define SMBHSLVSTS	(vt596_smba + 1)
 #define SMBHSTCNT	(vt596_smba + 2)
 #define SMBHSTCMD	(vt596_smba + 3)
 #define SMBHSTADD	(vt596_smba + 4)
 #define SMBHSTDAT0	(vt596_smba + 5)
 #define SMBHSTDAT1	(vt596_smba + 6)
 #define SMBBLKDAT	(vt596_smba + 7)
-#define SMBSLVCNT	(vt596_smba + 8)
-#define SMBSHDWCMD	(vt596_smba + 9)
-#define SMBSLVEVT	(vt596_smba + 0xA)
-#define SMBSLVDAT	(vt596_smba + 0xC)
 
 /* PCI Address Constants */
 
 /* SMBus data in configuration space can be found in two places,
-   We try to select the better one*/
+   We try to select the better one */
 
-static unsigned short smb_cf_hstcfg = 0xD2;
-
-#define SMBHSTCFG   (smb_cf_hstcfg)
-#define SMBSLVC     (smb_cf_hstcfg + 1)
-#define SMBSHDW1    (smb_cf_hstcfg + 2)
-#define SMBSHDW2    (smb_cf_hstcfg + 3)
-#define SMBREV      (smb_cf_hstcfg + 4)
+static unsigned short SMBHSTCFG = 0xD2;
 
 /* Other settings */
 #define MAX_TIMEOUT	500
-#define ENABLE_INT9	0
 
 /* VT82C596 constants */
-#define VT596_QUICK      0x00
-#define VT596_BYTE       0x04
-#define VT596_BYTE_DATA  0x08
-#define VT596_WORD_DATA  0x0C
-#define VT596_BLOCK_DATA 0x14
+#define VT596_QUICK		0x00
+#define VT596_BYTE		0x04
+#define VT596_BYTE_DATA		0x08
+#define VT596_WORD_DATA		0x0C
+#define VT596_BLOCK_DATA	0x14
+#define VT596_I2C_BLOCK_DATA	0x34
 
 
 /* If force is set to anything different from 0, we forcibly enable the
@@ -105,40 +98,65 @@
 		 "EXTREMELY DANGEROUS!");
 
 
+static struct pci_driver vt596_driver;
 static struct i2c_adapter vt596_adapter;
 
-/* Another internally used function */
-static int vt596_transaction(void)
+#define FEATURE_I2CBLOCK	(1<<0)
+static unsigned int vt596_features;
+
+#ifdef DEBUG
+static void vt596_dump_regs(const char *msg, u8 size)
+{
+	dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
+		"DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		inb_p(SMBHSTDAT1));
+
+	if (size == VT596_BLOCK_DATA
+	 || size == VT596_I2C_BLOCK_DATA) {
+		int i;
+
+		dev_dbg(&vt596_adapter.dev, "BLK=");
+		for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
+			printk("%02x,", inb_p(SMBBLKDAT));
+		printk("\n");
+		dev_dbg(&vt596_adapter.dev, "    ");
+		for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
+			printk("%02x,", inb_p(SMBBLKDAT));
+		printk("%02x\n", inb_p(SMBBLKDAT));
+	}
+}
+#else
+static inline void vt596_dump_regs(const char *msg, u8 size) { }
+#endif
+
+/* Return -1 on error, 0 on success */
+static int vt596_transaction(u8 size)
 {
 	int temp;
 	int result = 0;
 	int timeout = 0;
 
-	dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
-		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), 
-		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), 
-		inb_p(SMBHSTDAT1));
+	vt596_dump_regs("Transaction (pre)", size);
 
 	/* Make sure the SMBus host is ready to start transmitting */
 	if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
 		dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
-				"Resetting...\n", temp);
-		
+			"Resetting... ", temp);
+
 		outb_p(temp, SMBHSTSTS);
 		if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
-			dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
-			
+			printk("Failed! (0x%02x)\n", temp);
 			return -1;
 		} else {
-			dev_dbg(&vt596_adapter.dev, "Successfull!\n");
+			printk("Successful!\n");
 		}
 	}
 
-	/* start the transaction by setting bit 6 */
-	outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
+	/* Start the transaction by setting bit 6 */
+	outb_p(0x40 | (size & 0x3C), SMBHSTCNT);
 
-	/* We will always wait for a fraction of a second! 
-	   I don't know if VIA needs this, Intel did  */
+	/* We will always wait for a fraction of a second */
 	do {
 		msleep(1);
 		temp = inb_p(SMBHSTSTS);
@@ -147,77 +165,61 @@
 	/* If the SMBus is still busy, we give up */
 	if (timeout >= MAX_TIMEOUT) {
 		result = -1;
-		dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n");
+		dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
 	}
 
 	if (temp & 0x10) {
 		result = -1;
-		dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n");
+		dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
+			inb_p(SMBHSTCNT) & 0x3C);
 	}
 
 	if (temp & 0x08) {
 		result = -1;
-		dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be "
-			"locked until next hard\nreset. (sorry!)\n");
-		/* Clock stops and slave is stuck in mid-transmission */
+		dev_err(&vt596_adapter.dev, "SMBus collision!\n");
 	}
 
 	if (temp & 0x04) {
 		result = -1;
-		dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
+		/* Quick commands are used to probe for chips, so
+		   errors are expected, and we don't want to frighten the
+		   user. */
+		if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
+			dev_err(&vt596_adapter.dev, "Transaction error!\n");
 	}
 
-	if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+	/* Resetting status register */
+	if (temp & 0x1F)
 		outb_p(temp, SMBHSTSTS);
-		if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
-			dev_warn(&vt596_adapter.dev, "Failed reset at end "
-				 "of transaction (%02x)\n", temp);
-		}
-	}
 
-	dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
-		"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
-		inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), 
-		inb_p(SMBHSTDAT1));
-	
+	vt596_dump_regs("Transaction (post)", size);
+
 	return result;
 }
 
-/* Return -1 on error. */
+/* Return -1 on error, 0 on success */
 static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
-		unsigned short flags,  char read_write, u8 command,
-		int size,  union i2c_smbus_data *data)
+		unsigned short flags, char read_write, u8 command,
+		int size, union i2c_smbus_data *data)
 {
-	int i, len;
+	int i;
 
 	switch (size) {
-	case I2C_SMBUS_PROC_CALL:
-		dev_info(&vt596_adapter.dev,
-			 "I2C_SMBUS_PROC_CALL not supported!\n");
-		return -1;
 	case I2C_SMBUS_QUICK:
-		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-		       SMBHSTADD);
 		size = VT596_QUICK;
 		break;
 	case I2C_SMBUS_BYTE:
-		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-		       SMBHSTADD);
 		if (read_write == I2C_SMBUS_WRITE)
 			outb_p(command, SMBHSTCMD);
 		size = VT596_BYTE;
 		break;
 	case I2C_SMBUS_BYTE_DATA:
-		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-		       SMBHSTADD);
 		outb_p(command, SMBHSTCMD);
 		if (read_write == I2C_SMBUS_WRITE)
 			outb_p(data->byte, SMBHSTDAT0);
 		size = VT596_BYTE_DATA;
 		break;
 	case I2C_SMBUS_WORD_DATA:
-		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-		       SMBHSTADD);
 		outb_p(command, SMBHSTCMD);
 		if (read_write == I2C_SMBUS_WRITE) {
 			outb_p(data->word & 0xff, SMBHSTDAT0);
@@ -225,28 +227,33 @@
 		}
 		size = VT596_WORD_DATA;
 		break;
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+		if (!(vt596_features & FEATURE_I2CBLOCK))
+			goto exit_unsupported;
+		if (read_write == I2C_SMBUS_READ)
+			outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
+		/* Fall through */
 	case I2C_SMBUS_BLOCK_DATA:
-		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-		       SMBHSTADD);
 		outb_p(command, SMBHSTCMD);
 		if (read_write == I2C_SMBUS_WRITE) {
-			len = data->block[0];
-			if (len < 0)
-				len = 0;
+			u8 len = data->block[0];
 			if (len > I2C_SMBUS_BLOCK_MAX)
 				len = I2C_SMBUS_BLOCK_MAX;
 			outb_p(len, SMBHSTDAT0);
-			i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+			inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
 			for (i = 1; i <= len; i++)
 				outb_p(data->block[i], SMBBLKDAT);
 		}
-		size = VT596_BLOCK_DATA;
+		size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ?
+		       VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA;
 		break;
+	default:
+		goto exit_unsupported;
 	}
 
-	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
+	outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
 
-	if (vt596_transaction()) /* Error in transaction */
+	if (vt596_transaction(size)) /* Error in transaction */
 		return -1;
 
 	if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
@@ -254,35 +261,39 @@
 
 	switch (size) {
 	case VT596_BYTE:
-		/* Where is the result put? I assume here it is in
-		 * SMBHSTDAT0 but it might just as well be in the
-		 * SMBHSTCMD. No clue in the docs 
-		 */
-		data->byte = inb_p(SMBHSTDAT0);
-		break;
 	case VT596_BYTE_DATA:
 		data->byte = inb_p(SMBHSTDAT0);
 		break;
 	case VT596_WORD_DATA:
 		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
 		break;
+	case VT596_I2C_BLOCK_DATA:
 	case VT596_BLOCK_DATA:
 		data->block[0] = inb_p(SMBHSTDAT0);
 		if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
 			data->block[0] = I2C_SMBUS_BLOCK_MAX;
-		i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+		inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
 		for (i = 1; i <= data->block[0]; i++)
 			data->block[i] = inb_p(SMBBLKDAT);
 		break;
 	}
 	return 0;
+
+exit_unsupported:
+	dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
+		 size);
+	return -1;
 }
 
 static u32 vt596_func(struct i2c_adapter *adapter)
 {
-	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
 	    I2C_FUNC_SMBUS_BLOCK_DATA;
+
+	if (vt596_features & FEATURE_I2CBLOCK)
+		func |= I2C_FUNC_SMBUS_I2C_BLOCK;
+	return func;
 }
 
 static struct i2c_algorithm smbus_algorithm = {
@@ -294,7 +305,6 @@
 	.owner		= THIS_MODULE,
 	.class		= I2C_CLASS_HWMON,
 	.algo		= &smbus_algorithm,
-	.name		= "unset",
 };
 
 static int __devinit vt596_probe(struct pci_dev *pdev,
@@ -302,7 +312,7 @@
 {
 	unsigned char temp;
 	int error = -ENODEV;
-	
+
 	/* Determine the address of the SMBus areas */
 	if (force_addr) {
 		vt596_smba = force_addr & 0xfff0;
@@ -311,12 +321,12 @@
 	}
 
 	if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
-	    !(vt596_smba & 0x1)) {
+	    !(vt596_smba & 0x0001)) {
 		/* try 2nd address and config reg. for 596 */
 		if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
 		    !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
-		    (vt596_smba & 0x1)) {
-			smb_cf_hstcfg = 0x84;
+		    (vt596_smba & 0x0001)) {
+			SMBHSTCFG = 0x84;
 		} else {
 			/* no matches at all */
 			dev_err(&pdev->dev, "Cannot configure "
@@ -333,10 +343,10 @@
 		return -ENODEV;
 	}
 
- found:
-	if (!request_region(vt596_smba, 8, "viapro-smbus")) {
+found:
+	if (!request_region(vt596_smba, 8, vt596_driver.name)) {
 		dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
-		        vt596_smba);
+			vt596_smba);
 		return -ENODEV;
 	}
 
@@ -348,16 +358,16 @@
 		pci_write_config_word(pdev, id->driver_data, vt596_smba);
 		pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
 		dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
-		     "address 0x%04x!\n", vt596_smba);
-	} else if ((temp & 1) == 0) {
+			 "address 0x%04x!\n", vt596_smba);
+	} else if (!(temp & 0x01)) {
 		if (force) {
-			/* NOTE: This assumes I/O space and other allocations 
-			 * WERE done by the Bios!  Don't complain if your 
-			 * hardware does weird things after enabling this. 
-			 * :') Check for Bios updates before resorting to 
+			/* NOTE: This assumes I/O space and other allocations
+			 * WERE done by the Bios!  Don't complain if your
+			 * hardware does weird things after enabling this.
+			 * :') Check for Bios updates before resorting to
 			 * this.
 			 */
-			pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
+			pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
 			dev_info(&pdev->dev, "Enabling SMBus device\n");
 		} else {
 			dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
@@ -367,22 +377,28 @@
 		}
 	}
 
-	if ((temp & 0x0E) == 8)
-		dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n");
-	else if ((temp & 0x0E) == 0)
-		dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n");
-	else
-		dev_dbg(&pdev->dev, "Illegal Interrupt configuration "
-			"(or code out of date)!\n");
-
-	pci_read_config_byte(pdev, SMBREV, &temp);
-	dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
 	dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
 
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_VIA_8237:
+	case PCI_DEVICE_ID_VIA_8235:
+	case PCI_DEVICE_ID_VIA_8233A:
+	case PCI_DEVICE_ID_VIA_8233_0:
+		vt596_features |= FEATURE_I2CBLOCK;
+		break;
+	case PCI_DEVICE_ID_VIA_82C686_4:
+		/* The VT82C686B (rev 0x40) does support I2C block
+		   transactions, but the VT82C686A (rev 0x30) doesn't */
+		if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
+		 && temp >= 0x40)
+			vt596_features |= FEATURE_I2CBLOCK;
+		break;
+	}
+
 	vt596_adapter.dev.parent = &pdev->dev;
 	snprintf(vt596_adapter.name, I2C_NAME_SIZE,
-			"SMBus Via Pro adapter at %04x", vt596_smba);
-	
+		 "SMBus Via Pro adapter at %04x", vt596_smba);
+
 	vt596_pdev = pci_dev_get(pdev);
 	if (i2c_add_adapter(&vt596_adapter)) {
 		pci_dev_put(vt596_pdev);
@@ -395,7 +411,7 @@
 	 */
 	return -ENODEV;
 
- release_region:
+release_region:
 	release_region(vt596_smba, 8);
 	return error;
 }
@@ -420,9 +436,10 @@
 	{ 0, }
 };
 
-MODULE_DEVICE_TABLE (pci, vt596_ids);
+MODULE_DEVICE_TABLE(pci, vt596_ids);
 
 static struct pci_driver vt596_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "vt596_smbus",
 	.id_table	= vt596_ids,
 	.probe		= vt596_probe,
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index b675773..650c3eb 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -225,6 +225,7 @@
 }
 
 static struct pci_driver voodoo3_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "voodoo3_smbus",
 	.id_table	= voodoo3_ids,
 	.probe		= voodoo3_probe,
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index a1d580e..d3478e0 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -442,14 +442,13 @@
 	int rc = 0;
 	char description[64];
 
-	iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
 	if (!iface) {
 		printk(KERN_ERR NAME ": can't allocate memory\n");
 		rc = -ENOMEM;
 		goto errout;
 	}
 
-	memset(iface, 0, sizeof(*iface));
 	adapter = &iface->adapter;
 	i2c_set_adapdata(adapter, iface);
 	snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 6bd44a4..f9fae28 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -126,4 +126,13 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called max6875.
 
+config RTC_X1205_I2C
+	tristate "Xicor X1205 RTC chip"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Xicor X1205 RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called x1205.
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index a876dd4..46178b5 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -13,6 +13,7 @@
 obj-$(CONFIG_SENSORS_RTC8564)	+= rtc8564.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
+obj-$(CONFIG_RTC_X1205_I2C)	+= x1205.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 9d3175c..01b0370 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -243,11 +243,10 @@
 				     I2C_FUNC_I2C))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct ds1337_data));
 	INIT_LIST_HEAD(&data->list);
 
 	/* The common I2C client data is placed right before the
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 0936327..da488b7 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -167,7 +167,8 @@
 
 static ulong new_time;
 
-DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
+static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
+				(ulong) & new_time);
 
 int ds1374_set_rtc_time(ulong nowtime)
 {
@@ -193,13 +194,11 @@
 	struct i2c_client *client;
 	int rc;
 
-	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!client)
 		return -ENOMEM;
 
-	memset(client, 0, sizeof(struct i2c_client));
 	strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
-	client->flags = I2C_DF_NOTIFY;
 	client->addr = addr;
 	client->adapter = adap;
 	client->driver = &ds1374_driver;
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index d58403a..4baf573 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -88,8 +88,8 @@
 		dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
 
 		if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
-			for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_I2C_BLOCK_MAX)
-				if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_I2C_BLOCK_MAX)
+			for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
+				if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
 					goto exit;
 		} else {
 			if (i2c_smbus_write_byte(client, slice << 5)) {
@@ -155,7 +155,7 @@
 }
 
 /* This function is called by i2c_probe */
-int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
 	struct eeprom_data *data;
@@ -171,11 +171,10 @@
 					    | I2C_FUNC_SMBUS_BYTE))
 		goto exit;
 
-	if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct eeprom_data));
 
 	new_client = &data->client;
 	memset(data->data, 0xff, EEPROM_SIZE);
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 8ee56d4..eaa4742 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -888,6 +888,7 @@
 }
 
 struct device_driver omap_otg_driver = {
+	.owner		= THIS_MODULE,
 	.name		= "omap_otg",
 	.bus		= &platform_bus_type,
 	.probe		= otg_probe,
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 3f14528..3df309a 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -174,13 +174,11 @@
 	struct i2c_client *client;
 	int rc;
 
-	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!client)
 		return -ENOMEM;
 
-	memset(client, 0, sizeof(struct i2c_client));
 	strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
-	client->flags = I2C_DF_NOTIFY;
 	client->addr = addr;
 	client->adapter = adap;
 	client->driver = &m41t00_driver;
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 9e1aeb6..b376a00 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -179,16 +179,14 @@
 	if (address & 1)
 		return 0;
 
-	if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL)))
+	if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
 		return -ENOMEM;
-	memset(data, 0, sizeof(struct max6875_data));
 
 	/* A fake client is created on the odd address */
-	if (!(fake_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+	if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit_kfree1;
 	}
-	memset(fake_client, 0, sizeof(struct i2c_client));
 
 	/* Init real i2c_client */
 	real_client = &data->client;
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 225577f..59a9303 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -122,11 +122,10 @@
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet. */
-	if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct pca9539_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index 6525743..c323c2d 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -115,7 +115,7 @@
 }
 
 /* This function is called by i2c_probe */
-int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
 	struct pcf8574_data *data;
@@ -127,11 +127,10 @@
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet. */
-	if (!(data = kmalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct pcf8574_data));
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 80f1df9..ce420a6 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -166,7 +166,7 @@
 }
 
 /* This function is called by i2c_probe */
-int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
 	struct pcf8591_data *data;
@@ -178,11 +178,10 @@
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet. */
-	if (!(data = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
+	if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(data, 0, sizeof(struct pcf8591_data));
 	
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 0b5385c..916cdc1 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -148,17 +148,16 @@
 		{addr, I2C_M_RD, 2, data}
 	};
 
-	d = kmalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
+	d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
 	if (!d) {
 		ret = -ENOMEM;
 		goto done;
 	}
-	memset(d, 0, sizeof(struct rtc8564_data));
 	new_client = &d->client;
 
 	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
 	i2c_set_clientdata(new_client, d);
-	new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
+	new_client->flags = I2C_CLIENT_ALLOW_USE;
 	new_client->addr = addr;
 	new_client->adapter = adap;
 	new_client->driver = &rtc8564_driver;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 280e963..280dd7a 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -500,11 +500,10 @@
 		return 0;
 	}
 
-	tps = kmalloc(sizeof *tps, GFP_KERNEL);
+	tps = kzalloc(sizeof *tps, GFP_KERNEL);
 	if (!tps)
 		return 0;
 
-	memset(tps, 0, sizeof *tps);
 	init_MUTEX(&tps->lock);
 	INIT_WORK(&tps->work, tps65010_work, tps);
 	tps->irq = -1;
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
new file mode 100644
index 0000000..7da366c
--- /dev/null
+++ b/drivers/i2c/chips/x1205.c
@@ -0,0 +1,698 @@
+/*
+ *  x1205.c - An i2c driver for the Xicor X1205 RTC
+ *  Copyright 2004 Karen Spearel
+ *  Copyright 2005 Alessandro Zummo
+ *
+ *  please send all reports to:
+ *	kas11 at tampabay dot rr dot com
+ *      a dot zummo at towertech dot it
+ *
+ *  based on the other drivers in this same directory.
+ *
+ *  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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/list.h>
+
+#include <linux/x1205.h>
+
+#define DRV_VERSION "0.9.9"
+
+/* Addresses to scan: none. This chip is located at
+ * 0x6f and uses a two bytes register addressing.
+ * Two bytes need to be written to read a single register,
+ * while most other chips just require one and take the second
+ * one as the data to be written. To prevent corrupting
+ * unknown chips, the user must explicitely set the probe parameter.
+ */
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+I2C_CLIENT_MODULE_PARM(hctosys,
+	"Set the system time from the hardware clock upon initialization");
+
+/* offsets into CCR area */
+
+#define CCR_SEC			0
+#define CCR_MIN			1
+#define CCR_HOUR		2
+#define CCR_MDAY		3
+#define CCR_MONTH		4
+#define CCR_YEAR		5
+#define CCR_WDAY		6
+#define CCR_Y2K			7
+
+#define X1205_REG_SR		0x3F	/* status register */
+#define X1205_REG_Y2K		0x37
+#define X1205_REG_DW		0x36
+#define X1205_REG_YR		0x35
+#define X1205_REG_MO		0x34
+#define X1205_REG_DT		0x33
+#define X1205_REG_HR		0x32
+#define X1205_REG_MN		0x31
+#define X1205_REG_SC		0x30
+#define X1205_REG_DTR		0x13
+#define X1205_REG_ATR		0x12
+#define X1205_REG_INT		0x11
+#define X1205_REG_0		0x10
+#define X1205_REG_Y2K1		0x0F
+#define X1205_REG_DWA1		0x0E
+#define X1205_REG_YRA1		0x0D
+#define X1205_REG_MOA1		0x0C
+#define X1205_REG_DTA1		0x0B
+#define X1205_REG_HRA1		0x0A
+#define X1205_REG_MNA1		0x09
+#define X1205_REG_SCA1		0x08
+#define X1205_REG_Y2K0		0x07
+#define X1205_REG_DWA0		0x06
+#define X1205_REG_YRA0		0x05
+#define X1205_REG_MOA0		0x04
+#define X1205_REG_DTA0		0x03
+#define X1205_REG_HRA0		0x02
+#define X1205_REG_MNA0		0x01
+#define X1205_REG_SCA0		0x00
+
+#define X1205_CCR_BASE		0x30	/* Base address of CCR */
+#define X1205_ALM0_BASE		0x00	/* Base address of ALARM0 */
+
+#define X1205_SR_RTCF		0x01	/* Clock failure */
+#define X1205_SR_WEL		0x02	/* Write Enable Latch */
+#define X1205_SR_RWEL		0x04	/* Register Write Enable */
+
+#define X1205_DTR_DTR0		0x01
+#define X1205_DTR_DTR1		0x02
+#define X1205_DTR_DTR2		0x04
+
+#define X1205_HR_MIL		0x80	/* Set in ccr.hour for 24 hr mode */
+
+/* Prototypes */
+static int x1205_attach(struct i2c_adapter *adapter);
+static int x1205_detach(struct i2c_client *client);
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
+static int x1205_command(struct i2c_client *client, unsigned int cmd,
+	void *arg);
+
+static struct i2c_driver x1205_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "x1205",
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter = &x1205_attach,
+	.detach_client	= &x1205_detach,
+};
+
+struct x1205_data {
+	struct i2c_client client;
+	struct list_head list;
+	unsigned int epoch;
+};
+
+static const unsigned char days_in_mo[] =
+	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static LIST_HEAD(x1205_clients);
+
+/* Workaround until the I2C subsytem will allow to send
+ * commands to a specific client. This function will send the command
+ * to the first client.
+ */
+int x1205_do_command(unsigned int cmd, void *arg)
+{
+	struct list_head *walk;
+	struct list_head *tmp;
+	struct x1205_data *data;
+
+	list_for_each_safe(walk, tmp, &x1205_clients) {
+		data = list_entry(walk, struct x1205_data, list);
+		return x1205_command(&data->client, cmd, arg);
+	}
+
+	return -ENODEV;
+}
+
+#define is_leap(year) \
+	((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+/* make sure the rtc_time values are in bounds */
+static int x1205_validate_tm(struct rtc_time *tm)
+{
+	int year = tm->tm_year + 1900;
+
+	if ((tm->tm_year < 70) || (tm->tm_year > 255))
+		return -EINVAL;
+
+	if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
+		return -EINVAL;
+
+	if (tm->tm_mday > days_in_mo[tm->tm_mon]
+		+ ((tm->tm_mon == 1) && is_leap(year)))
+		return -EINVAL;
+
+	if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * In the routines that deal directly with the x1205 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
+				u8 reg_base)
+{
+	unsigned char dt_addr[2] = { 0, reg_base };
+	static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+	unsigned char buf[8], sr;
+
+	struct i2c_msg msgs[] = {
+		{ client->addr, 0, 2, sr_addr },	/* setup read ptr */
+		{ client->addr, I2C_M_RD, 1, &sr }, 	/* read status */
+		{ client->addr, 0, 2, dt_addr },	/* setup read ptr */
+		{ client->addr, I2C_M_RD, 8, buf },	/* read date */
+	};
+
+	struct x1205_data *data = i2c_get_clientdata(client);
+
+	/* read status register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	/* check for battery failure */
+	if (sr & X1205_SR_RTCF) {
+		dev_warn(&client->dev,
+			"Clock had a power failure, you must set the date.\n");
+		return -EINVAL;
+	}
+
+	/* read date registers */
+	if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
+		"mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
+		__FUNCTION__,
+		buf[0], buf[1], buf[2], buf[3],
+		buf[4], buf[5], buf[6], buf[7]);
+
+	tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
+	tm->tm_min = BCD2BIN(buf[CCR_MIN]);
+	tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+	tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
+	tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
+	data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
+	tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
+	tm->tm_wday = buf[CCR_WDAY];
+
+	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+		"mday=%d, mon=%d, year=%d, wday=%d\n",
+		__FUNCTION__,
+		tm->tm_sec, tm->tm_min, tm->tm_hour,
+		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+	return 0;
+}
+
+static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+				int datetoo, u8 reg_base)
+{
+	int i, err, xfer;
+
+	unsigned char buf[8];
+
+	static const unsigned char wel[3] = { 0, X1205_REG_SR,
+						X1205_SR_WEL };
+
+	static const unsigned char rwel[3] = { 0, X1205_REG_SR,
+						X1205_SR_WEL | X1205_SR_RWEL };
+
+	static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
+
+	struct x1205_data *data = i2c_get_clientdata(client);
+
+	/* check if all values in the tm struct are correct */
+	if ((err = x1205_validate_tm(tm)) < 0)
+		return err;
+
+	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+		"mday=%d, mon=%d, year=%d, wday=%d\n",
+		__FUNCTION__,
+		tm->tm_sec, tm->tm_min, tm->tm_hour,
+		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+	buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
+	buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+
+	/* set hour and 24hr bit */
+	buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+
+	/* should we also set the date? */
+	if (datetoo) {
+		buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+
+		/* month, 0 - 11 */
+		buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+
+		/* year, since 1900 */
+		buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
+		buf[CCR_WDAY] = tm->tm_wday & 0x07;
+		buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
+	}
+
+	/* this sequence is required to unlock the chip */
+	xfer = i2c_master_send(client, wel, 3);
+	if (xfer != 3) {
+		dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
+		return -EIO;
+	}
+
+	xfer = i2c_master_send(client, rwel, 3);
+	if (xfer != 3) {
+		dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
+		return -EIO;
+	}
+
+	/* write register's data */
+	for (i = 0; i < (datetoo ? 8 : 3); i++) {
+		unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
+
+		xfer = i2c_master_send(client, rdata, 3);
+		if (xfer != 3) {
+			dev_err(&client->dev,
+				"%s: xfer=%d addr=%02x, data=%02x\n",
+				__FUNCTION__,
+				 xfer, rdata[1], rdata[2]);
+			return -EIO;
+		}
+	};
+
+	/* disable further writes */
+	xfer = i2c_master_send(client, diswe, 3);
+	if (xfer != 3) {
+		dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int x1205_get_dtrim(struct i2c_client *client, int *trim)
+{
+	unsigned char dtr;
+	static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
+
+	struct i2c_msg msgs[] = {
+		{ client->addr, 0, 2, dtr_addr },	/* setup read ptr */
+		{ client->addr, I2C_M_RD, 1, &dtr }, 	/* read dtr */
+	};
+
+	/* read dtr register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
+
+	*trim = 0;
+
+	if (dtr & X1205_DTR_DTR0)
+		*trim += 20;
+
+	if (dtr & X1205_DTR_DTR1)
+		*trim += 10;
+
+	if (dtr & X1205_DTR_DTR2)
+		*trim = -*trim;
+
+	return 0;
+}
+
+static int x1205_get_atrim(struct i2c_client *client, int *trim)
+{
+	s8 atr;
+	static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
+
+	struct i2c_msg msgs[] = {
+		{ client->addr, 0, 2, atr_addr },	/* setup read ptr */
+		{ client->addr, I2C_M_RD, 1, &atr }, 	/* read atr */
+	};
+
+	/* read atr register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
+
+	/* atr is a two's complement value on 6 bits,
+	 * perform sign extension. The formula is
+	 * Catr = (atr * 0.25pF) + 11.00pF.
+	 */
+	if (atr & 0x20)
+		atr |= 0xC0;
+
+	dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
+
+	*trim = (atr * 250) + 11000;
+
+	dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
+
+	return 0;
+}
+
+static int x1205_hctosys(struct i2c_client *client)
+{
+	int err;
+
+	struct rtc_time tm;
+	struct timespec tv;
+
+	err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
+
+	if (err) {
+		dev_err(&client->dev,
+			"Unable to set the system clock\n");
+		return err;
+	}
+
+	/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
+	 * whether it stores the most close value or the value with partial
+	 * seconds truncated. However, it is important that we use it to store
+	 * the truncated value. This is because otherwise it is necessary,
+	 * in an rtc sync function, to read both xtime.tv_sec and
+	 * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
+	 * of >32bits is not possible. So storing the most close value would
+	 * slow down the sync API. So here we have the truncated value and
+	 * the best guess is to add 0.5s.
+	 */
+
+	tv.tv_nsec = NSEC_PER_SEC >> 1;
+
+	/* WARNING: this is not the C library 'mktime' call, it is a built in
+	 * inline function from include/linux/time.h.  It expects (requires)
+	 * the month to be in the range 1-12
+	 */
+
+	tv.tv_sec  = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
+				tm.tm_mday, tm.tm_hour,
+				tm.tm_min, tm.tm_sec);
+
+	do_settimeofday(&tv);
+
+	dev_info(&client->dev,
+		"setting the system clock to %d-%d-%d %d:%d:%d\n",
+		tm.tm_year + 1900, tm.tm_mon + 1,
+		tm.tm_mday, tm.tm_hour, tm.tm_min,
+		tm.tm_sec);
+
+	return 0;
+}
+
+struct x1205_limit
+{
+	unsigned char reg;
+	unsigned char mask;
+	unsigned char min;
+	unsigned char max;
+};
+
+static int x1205_validate_client(struct i2c_client *client)
+{
+	int i, xfer;
+
+	/* Probe array. We will read the register at the specified
+	 * address and check if the given bits are zero.
+	 */
+	static const unsigned char probe_zero_pattern[] = {
+		/* register, mask */
+		X1205_REG_SR,	0x18,
+		X1205_REG_DTR,	0xF8,
+		X1205_REG_ATR,	0xC0,
+		X1205_REG_INT,	0x18,
+		X1205_REG_0,	0xFF,
+	};
+
+	static const struct x1205_limit probe_limits_pattern[] = {
+		/* register, mask, min, max */
+		{ X1205_REG_Y2K,	0xFF,	19,	20	},
+		{ X1205_REG_DW,		0xFF,	0,	6	},
+		{ X1205_REG_YR,		0xFF,	0,	99	},
+		{ X1205_REG_MO,		0xFF,	0,	12	},
+		{ X1205_REG_DT,		0xFF,	0,	31	},
+		{ X1205_REG_HR,		0x7F,	0,	23	},
+		{ X1205_REG_MN,		0xFF,	0,	59	},
+		{ X1205_REG_SC,		0xFF,	0,	59	},
+		{ X1205_REG_Y2K1,	0xFF,	19,	20	},
+		{ X1205_REG_Y2K0,	0xFF,	19,	20	},
+	};
+
+	/* check that registers have bits a 0 where expected */
+	for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
+		unsigned char buf;
+
+		unsigned char addr[2] = { 0, probe_zero_pattern[i] };
+
+		struct i2c_msg msgs[2] = {
+			{ client->addr, 0, 2, addr },
+			{ client->addr, I2C_M_RD, 1, &buf },
+		};
+
+		xfer = i2c_transfer(client->adapter, msgs, 2);
+		if (xfer != 2) {
+			dev_err(&client->adapter->dev,
+				"%s: could not read register %x\n",
+				__FUNCTION__, addr[1]);
+
+			return -EIO;
+		}
+
+		if ((buf & probe_zero_pattern[i+1]) != 0) {
+			dev_err(&client->adapter->dev,
+				"%s: register=%02x, zero pattern=%d, value=%x\n",
+				__FUNCTION__, addr[1], i, buf);
+
+			return -ENODEV;
+		}
+	}
+
+	/* check limits (only registers with bcd values) */
+	for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
+		unsigned char reg, value;
+
+		unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
+
+		struct i2c_msg msgs[2] = {
+			{ client->addr, 0, 2, addr },
+			{ client->addr, I2C_M_RD, 1, &reg },
+		};
+
+		xfer = i2c_transfer(client->adapter, msgs, 2);
+
+		if (xfer != 2) {
+			dev_err(&client->adapter->dev,
+				"%s: could not read register %x\n",
+				__FUNCTION__, addr[1]);
+
+			return -EIO;
+		}
+
+		value = BCD2BIN(reg & probe_limits_pattern[i].mask);
+
+		if (value > probe_limits_pattern[i].max ||
+			value < probe_limits_pattern[i].min) {
+			dev_dbg(&client->adapter->dev,
+				"%s: register=%x, lim pattern=%d, value=%d\n",
+				__FUNCTION__, addr[1], i, value);
+
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static int x1205_attach(struct i2c_adapter *adapter)
+{
+	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+	return i2c_probe(adapter, &addr_data, x1205_probe);
+}
+
+int x1205_direct_attach(int adapter_id,
+	struct i2c_client_address_data *address_data)
+{
+	int err;
+	struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
+
+	if (adapter) {
+		err = i2c_probe(adapter,
+			address_data, x1205_probe);
+
+		i2c_put_adapter(adapter);
+
+		return err;
+	}
+
+	return -ENODEV;
+}
+
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct x1205_data *data;
+
+	int err = 0;
+
+	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+		err = -ENODEV;
+		goto exit;
+	}
+
+	if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	/* Initialize our structures */
+	data->epoch = 2000;
+
+	client = &data->client;
+	client->addr = address;
+	client->driver = &x1205_driver;
+	client->adapter	= adapter;
+
+	strlcpy(client->name, "x1205", I2C_NAME_SIZE);
+
+	i2c_set_clientdata(client, data);
+
+	/* Verify the chip is really an X1205 */
+	if (kind < 0) {
+		if (x1205_validate_client(client) < 0) {
+			err = -ENODEV;
+			goto exit_kfree;
+		}
+	}
+
+	/* Inform the i2c layer */
+	if ((err = i2c_attach_client(client)))
+		goto exit_kfree;
+
+	list_add(&data->list, &x1205_clients);
+
+	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+	/* If requested, set the system time */
+	if (hctosys)
+		x1205_hctosys(client);
+
+	return 0;
+
+exit_kfree:
+	kfree(data);
+
+exit:
+	return err;
+}
+
+static int x1205_detach(struct i2c_client *client)
+{
+	int err;
+	struct x1205_data *data = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	list_del(&data->list);
+
+	kfree(data);
+
+	return 0;
+}
+
+static int x1205_command(struct i2c_client *client, unsigned int cmd,
+	void *param)
+{
+	if (param == NULL)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_TIME))
+		return -EACCES;
+
+	dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+
+	switch (cmd) {
+	case X1205_CMD_GETDATETIME:
+		return x1205_get_datetime(client, param, X1205_CCR_BASE);
+
+	case X1205_CMD_SETTIME:
+		return x1205_set_datetime(client, param, 0,
+				X1205_CCR_BASE);
+
+	case X1205_CMD_SETDATETIME:
+		return x1205_set_datetime(client, param, 1,
+				X1205_CCR_BASE);
+
+	case X1205_CMD_GETALARM:
+		return x1205_get_datetime(client, param, X1205_ALM0_BASE);
+
+	case X1205_CMD_SETALARM:
+		return x1205_set_datetime(client, param, 1,
+				X1205_ALM0_BASE);
+
+	case X1205_CMD_GETDTRIM:
+		return x1205_get_dtrim(client, param);
+
+	case X1205_CMD_GETATRIM:
+		return x1205_get_atrim(client, param);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int __init x1205_init(void)
+{
+	return i2c_add_driver(&x1205_driver);
+}
+
+static void __exit x1205_exit(void)
+{
+	i2c_del_driver(&x1205_driver);
+}
+
+MODULE_AUTHOR(
+	"Karen Spearel <kas11@tampabay.rr.com>, "
+	"Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Xicor X1205 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+EXPORT_SYMBOL_GPL(x1205_do_command);
+EXPORT_SYMBOL_GPL(x1205_direct_attach);
+
+module_init(x1205_init);
+module_exit(x1205_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index dda472e..02e335a 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -19,7 +19,8 @@
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
-   SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */
+   SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
+   Jean Delvare <khali@linux-fr.org> */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -48,7 +49,7 @@
 	int rc = 0;
 
 	if (dev->driver && dev->driver->suspend)
-		rc = dev->driver->suspend(dev,state,0);
+		rc = dev->driver->suspend(dev, state);
 	return rc;
 }
 
@@ -57,7 +58,7 @@
 	int rc = 0;
 	
 	if (dev->driver && dev->driver->resume)
-		rc = dev->driver->resume(dev,0);
+		rc = dev->driver->resume(dev);
 	return rc;
 }
 
@@ -85,6 +86,7 @@
 }
 
 struct device_driver i2c_adapter_driver = {
+	.owner = THIS_MODULE,
 	.name =	"i2c_adapter",
 	.bus = &i2c_bus_type,
 	.probe = i2c_device_probe,
@@ -98,6 +100,7 @@
 }
 
 struct class i2c_adapter_class = {
+	.owner =	THIS_MODULE,
 	.name =		"i2c-adapter",
 	.release =	&i2c_adapter_class_dev_release,
 };
@@ -291,6 +294,7 @@
 	down(&core_lists);
 
 	/* add the driver to the list of i2c drivers in the driver core */
+	driver->driver.owner = driver->owner;
 	driver->driver.name = driver->name;
 	driver->driver.bus = &i2c_bus_type;
 	driver->driver.probe = i2c_device_probe;
@@ -706,10 +710,6 @@
 	int i, err;
 	int adap_id = i2c_adapter_id(adapter);
 
-	/* Forget it if we can't probe using SMBUS_QUICK */
-	if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
-		return -1;
-
 	/* Force entries are done first, and are not affected by ignore
 	   entries */
 	if (address_data->forces) {
@@ -736,6 +736,17 @@
 		}
 	}
 
+	/* Stop here if we can't use SMBUS_QUICK */
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
+		if (address_data->probe[0] == I2C_CLIENT_END
+		 && address_data->normal_i2c[0] == I2C_CLIENT_END)
+		 	return 0;
+
+		dev_warn(&adapter->dev, "SMBus Quick command not supported, "
+			 "can't probe for chips\n");
+		return -1;
+	}
+
 	/* Probe entries are done second, and are not affected by ignore
 	   entries either */
 	for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
@@ -820,101 +831,44 @@
 	return (u8)(data >> 8);
 }
 
-/* CRC over count bytes in the first array plus the bytes in the rest
-   array if it is non-null. rest[0] is the (length of rest) - 1
-   and is included. */
-static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
 {
 	int i;
 
 	for(i = 0; i < count; i++)
-		crc = crc8((crc ^ first[i]) << 8);
-	if(rest != NULL)
-		for(i = 0; i <= rest[0]; i++)
-			crc = crc8((crc ^ rest[i]) << 8);
+		crc = crc8((crc ^ p[i]) << 8);
 	return crc;
 }
 
-static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+/* Assume a 7-bit address, which is reasonable for SMBus */
+static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
 {
-	return i2c_smbus_partial_pec(0, count, first, rest);
+	/* The address will be sent first */
+	u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
+	pec = i2c_smbus_pec(pec, &addr, 1);
+
+	/* The data buffer follows */
+	return i2c_smbus_pec(pec, msg->buf, msg->len);
 }
 
-/* Returns new "size" (transaction type)
-   Note that we convert byte to byte_data and byte_data to word_data
-   rather than invent new xxx_PEC transactions. */
-static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
-			     union i2c_smbus_data *data)
+/* Used for write only transactions */
+static inline void i2c_smbus_add_pec(struct i2c_msg *msg)
 {
-	u8 buf[3];
-
-	buf[0] = addr << 1;
-	buf[1] = command;
-	switch(size) {
-		case I2C_SMBUS_BYTE:
-			data->byte = i2c_smbus_pec(2, buf, NULL);
-			size = I2C_SMBUS_BYTE_DATA;
-			break;
-		case I2C_SMBUS_BYTE_DATA:
-			buf[2] = data->byte;
-			data->word = buf[2] ||
-			            (i2c_smbus_pec(3, buf, NULL) << 8);
-			size = I2C_SMBUS_WORD_DATA;
-			break;
-		case I2C_SMBUS_WORD_DATA:
-			/* unsupported */
-			break;
-		case I2C_SMBUS_BLOCK_DATA:
-			data->block[data->block[0] + 1] =
-			             i2c_smbus_pec(2, buf, data->block);
-			size = I2C_SMBUS_BLOCK_DATA_PEC;
-			break;
-	}
-	return size;	
+	msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);
+	msg->len++;
 }
 
-static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
-			       union i2c_smbus_data *data)
+/* Return <0 on CRC error
+   If there was a write before this read (most cases) we need to take the
+   partial CRC from the write part into account.
+   Note that this function does modify the message (we need to decrease the
+   message length to hide the CRC byte from the caller). */
+static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
 {
-	u8 buf[3], rpec, cpec;
+	u8 rpec = msg->buf[--msg->len];
+	cpec = i2c_smbus_msg_pec(cpec, msg);
 
-	buf[1] = command;
-	switch(size) {
-		case I2C_SMBUS_BYTE_DATA:
-			buf[0] = (addr << 1) | 1;
-			cpec = i2c_smbus_pec(2, buf, NULL);
-			rpec = data->byte;
-			break;
-		case I2C_SMBUS_WORD_DATA:
-			buf[0] = (addr << 1) | 1;
-			buf[2] = data->word & 0xff;
-			cpec = i2c_smbus_pec(3, buf, NULL);
-			rpec = data->word >> 8;
-			break;
-		case I2C_SMBUS_WORD_DATA_PEC:
-			/* unsupported */
-			cpec = rpec = 0;
-			break;
-		case I2C_SMBUS_PROC_CALL_PEC:
-			/* unsupported */
-			cpec = rpec = 0;
-			break;
-		case I2C_SMBUS_BLOCK_DATA_PEC:
-			buf[0] = (addr << 1);
-			buf[2] = (addr << 1) | 1;
-			cpec = i2c_smbus_pec(3, buf, data->block);
-			rpec = data->block[data->block[0] + 1];
-			break;
-		case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
-			buf[0] = (addr << 1) | 1;
-			rpec = i2c_smbus_partial_pec(partial, 1,
-			                             buf, data->block);
-			cpec = data->block[data->block[0] + 1];
-			break;
-		default:
-			cpec = rpec = 0;
-			break;
-	}
 	if (rpec != cpec) {
 		pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
 			rpec, cpec);
@@ -941,9 +895,8 @@
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 {
-	union i2c_smbus_data data;	/* only for PEC */
 	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-	                      I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
+	                      I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
 }
 
 s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
@@ -1026,13 +979,14 @@
 	  need to use only one message; when reading, we need two. We initialize
 	  most things with sane defaults, to keep the code below somewhat
 	  simpler. */
-	unsigned char msgbuf0[34];
-	unsigned char msgbuf1[34];
+	unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
+	unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
 	int num = read_write == I2C_SMBUS_READ?2:1;
 	struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, 
 	                          { addr, flags | I2C_M_RD, 0, msgbuf1 }
 	                        };
 	int i;
+	u8 partial_pec = 0;
 
 	msgbuf0[0] = command;
 	switch(size) {
@@ -1075,7 +1029,6 @@
 		msgbuf0[2] = (data->word >> 8) & 0xff;
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
-	case I2C_SMBUS_BLOCK_DATA_PEC:
 		if (read_write == I2C_SMBUS_READ) {
 			dev_err(&adapter->dev, "Block read not supported "
 			       "under I2C emulation!\n");
@@ -1088,23 +1041,20 @@
 				       data->block[0]);
 				return -1;
 			}
-			if(size == I2C_SMBUS_BLOCK_DATA_PEC)
-				(msg[0].len)++;
-			for (i = 1; i <= msg[0].len; i++)
+			for (i = 1; i < msg[0].len; i++)
 				msgbuf0[i] = data->block[i-1];
 		}
 		break;
 	case I2C_SMBUS_BLOCK_PROC_CALL:
-	case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
 		dev_dbg(&adapter->dev, "Block process call not supported "
 		       "under I2C emulation!\n");
 		return -1;
 	case I2C_SMBUS_I2C_BLOCK_DATA:
 		if (read_write == I2C_SMBUS_READ) {
-			msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
+			msg[1].len = I2C_SMBUS_BLOCK_MAX;
 		} else {
 			msg[0].len = data->block[0] + 1;
-			if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
+			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
 				dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
 				       "invalid block write size (%d)\n",
 				       data->block[0]);
@@ -1120,9 +1070,30 @@
 		return -1;
 	}
 
+	i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
+				      && size != I2C_SMBUS_I2C_BLOCK_DATA);
+	if (i) {
+		/* Compute PEC if first message is a write */
+		if (!(msg[0].flags & I2C_M_RD)) {
+		 	if (num == 1) /* Write only */
+				i2c_smbus_add_pec(&msg[0]);
+			else /* Write followed by read */
+				partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
+		}
+		/* Ask for PEC if last message is a read */
+		if (msg[num-1].flags & I2C_M_RD)
+		 	msg[num-1].len++;
+	}
+
 	if (i2c_transfer(adapter, msg, num) < 0)
 		return -1;
 
+	/* Check PEC if last message is a read */
+	if (i && (msg[num-1].flags & I2C_M_RD)) {
+		if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
+			return -1;
+	}
+
 	if (read_write == I2C_SMBUS_READ)
 		switch(size) {
 			case I2C_SMBUS_BYTE:
@@ -1137,8 +1108,8 @@
 				break;
 			case I2C_SMBUS_I2C_BLOCK_DATA:
 				/* fixed at 32 for now */
-				data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
-				for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
+				data->block[0] = I2C_SMBUS_BLOCK_MAX;
+				for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
 					data->block[i+1] = msgbuf1[i];
 				break;
 		}
@@ -1151,28 +1122,8 @@
                    union i2c_smbus_data * data)
 {
 	s32 res;
-	int swpec = 0;
-	u8 partial = 0;
 
 	flags &= I2C_M_TEN | I2C_CLIENT_PEC;
-	if((flags & I2C_CLIENT_PEC) &&
-	   !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
-		swpec = 1;
-		if(read_write == I2C_SMBUS_READ &&
-		   size == I2C_SMBUS_BLOCK_DATA)
-			size = I2C_SMBUS_BLOCK_DATA_PEC;
-		else if(size == I2C_SMBUS_PROC_CALL)
-			size = I2C_SMBUS_PROC_CALL_PEC;
-		else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {
-			i2c_smbus_add_pec(addr, command,
-		                          I2C_SMBUS_BLOCK_DATA, data);
-			partial = data->block[data->block[0] + 1];
-			size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
-		} else if(read_write == I2C_SMBUS_WRITE &&
-		          size != I2C_SMBUS_QUICK &&
-		          size != I2C_SMBUS_I2C_BLOCK_DATA)
-			size = i2c_smbus_add_pec(addr, command, size, data);
-	}
 
 	if (adapter->algo->smbus_xfer) {
 		down(&adapter->bus_lock);
@@ -1183,13 +1134,6 @@
 		res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
 	                                      command,size,data);
 
-	if(res >= 0 && swpec &&
-	   size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
-	   (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||
-	    size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
-		if(i2c_smbus_check_pec(addr, command, size, partial, data))
-			return -1;
-	}
 	return res;
 }
 
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index aa7a4fa..ea14c8f 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -26,15 +26,11 @@
 
 /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
 
-/* The devfs code is contributed by Philipp Matthias Hahn 
-   <pmhahn@titan.lahn.de> */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
@@ -80,10 +76,9 @@
 {
 	struct i2c_dev *i2c_dev;
 
-	i2c_dev = kmalloc(sizeof(*i2c_dev), GFP_KERNEL);
+	i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
 	if (!i2c_dev)
 		return ERR_PTR(-ENOMEM);
-	memset(i2c_dev, 0x00, sizeof(*i2c_dev));
 
 	spin_lock(&i2c_dev_array_lock);
 	if (i2c_dev_array[adap->nr]) {
@@ -177,8 +172,8 @@
 	int i,datasize,res;
 	unsigned long funcs;
 
-	dev_dbg(&client->adapter->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
-		iminor(inode),cmd, arg);
+	dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
+		cmd, arg);
 
 	switch ( cmd ) {
 	case I2C_SLAVE:
@@ -432,8 +427,6 @@
 	if (IS_ERR(i2c_dev))
 		return PTR_ERR(i2c_dev);
 
-	devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
-			S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
 	pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
 		 adap->name, i2c_dev->minor);
 
@@ -466,7 +459,6 @@
 		return -ENODEV;
 
 	init_completion(&i2c_dev->released);
-	devfs_remove("i2c/%d", i2c_dev->minor);
 	return_i2c_dev(i2c_dev);
 	class_device_unregister(&i2c_dev->class_dev);
 	wait_for_completion(&i2c_dev->released);
@@ -522,8 +514,6 @@
 	if (res)
 		goto out_unreg_class;
 
-	devfs_mk_dir("i2c");
-
 	return 0;
 
 out_unreg_class:
@@ -539,7 +529,6 @@
 {
 	i2c_del_driver(&i2cdev_driver);
 	class_unregister(&i2c_dev_class);
-	devfs_remove("i2c");
 	unregister_chrdev(I2C_MAJOR,"i2c");
 }
 
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 1cadd2c..a737886 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -778,6 +778,35 @@
 	  This option enables the use of the sleep LED as a hard drive
 	  activity LED.
 
+config BLK_DEV_IDE_AU1XXX
+       bool "IDE for AMD Alchemy Au1200"
+       depends on SOC_AU1200
+choice
+       prompt "IDE Mode for AMD Alchemy Au1200"
+       default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+       depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+
+config BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+       bool "PIO+DbDMA IDE for AMD Alchemy Au1200"
+
+config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+       bool "MDMA2+DbDMA IDE for AMD Alchemy Au1200"
+       depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
+endchoice
+
+config BLK_DEV_IDE_AU1XXX_BURSTABLE_ON
+        bool "Enable burstable Mode on DbDMA"
+        default false
+        depends BLK_DEV_IDE_AU1XXX
+        help
+          This option enable the burstable Flag on DbDMA controller
+          (cf. "AMD Alchemy 'Au1200' Processor Data Book - PRELIMINARY").
+
+config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+       int "Maximum transfer size (KB) per request (up to 128)"
+       default "128"
+       depends BLK_DEV_IDE_AU1XXX
+
 config IDE_ARM
 	def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
 
@@ -1013,7 +1042,7 @@
 endif
 
 config BLK_DEV_IDEDMA
-	def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS
+	def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 
 config IDEDMA_IVB
 	bool "IGNORE word93 Validation BITS"
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 74af7e0..8b9d855 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2211,13 +2211,12 @@
 
 	if (toc == NULL) {
 		/* Try to allocate space. */
-		toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
-						    GFP_KERNEL);
-		info->toc = toc;
+		toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
 		if (toc == NULL) {
 			printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
 			return -ENOMEM;
 		}
+		info->toc = toc;
 	}
 
 	/* Check to see if the existing data is still valid.
@@ -2240,7 +2239,8 @@
 	/* First read just the header, so we know how long the TOC is. */
 	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
 				    sizeof(struct atapi_toc_header), sense);
-	if (stat) return stat;
+	if (stat)
+		return stat;
 
 #if ! STANDARD_ATAPI
 	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
@@ -2324,7 +2324,8 @@
 		/* Read the multisession information. */
 		stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
 					   sizeof(ms_tmp), sense);
-		if (stat) return stat;
+		if (stat)
+			return stat;
 
 		toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
 	} else {
@@ -2460,7 +2461,7 @@
 			    struct packet_command *cgc)
 {
 	struct request req;
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 
 	if (cgc->timeout <= 0)
 		cgc->timeout = ATAPI_WAIT_PC;
@@ -2537,7 +2538,7 @@
 			   unsigned int cmd, void *arg)
 			   
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	struct cdrom_info *info = drive->driver_data;
 	int stat;
 
@@ -2548,7 +2549,7 @@
 	 */
 	case CDROMPLAYTRKIND: {
 		unsigned long lba_start, lba_end;
-		struct cdrom_ti *ti = (struct cdrom_ti *)arg;
+		struct cdrom_ti *ti = arg;
 		struct atapi_toc_entry *first_toc, *last_toc;
 
 		stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
@@ -2571,12 +2572,13 @@
 	}
 
 	case CDROMREADTOCHDR: {
-		struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
+		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;
+		if (stat)
+			return stat;
 
 		toc = info->toc;
 		tochdr->cdth_trk0 = toc->hdr.first_track;
@@ -2586,11 +2588,12 @@
 	}
 
 	case CDROMREADTOCENTRY: {
-		struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
+		struct cdrom_tocentry *tocentry = arg;
 		struct atapi_toc_entry *toce;
 
 		stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
-		if (stat) return stat;
+		if (stat)
+			return stat;
 
 		tocentry->cdte_ctrl = toce->control;
 		tocentry->cdte_adr  = toce->adr;
@@ -2613,7 +2616,7 @@
 static
 int ide_cdrom_reset (struct cdrom_device_info *cdi)
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	struct request_sense sense;
 	struct request req;
 	int ret;
@@ -2636,12 +2639,13 @@
 static
 int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	struct request_sense sense;
 
 	if (position) {
 		int stat = cdrom_lockdoor(drive, 0, &sense);
-		if (stat) return stat;
+		if (stat)
+			return stat;
 	}
 
 	return cdrom_eject(drive, !position, &sense);
@@ -2650,7 +2654,7 @@
 static
 int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	return cdrom_lockdoor(drive, lock, NULL);
 }
 
@@ -2700,7 +2704,7 @@
 static
 int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	struct request_sense sense;
 	struct atapi_capabilities_page cap;
 	int stat;
@@ -2723,7 +2727,7 @@
 static
 int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	struct media_event_desc med;
 	struct request_sense sense;
 	int stat;
@@ -2769,7 +2773,7 @@
 				struct cdrom_multisession *ms_info)
 {
 	struct atapi_toc *toc;
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	struct cdrom_info *info = drive->driver_data;
 	struct request_sense sense;
 	int ret;
@@ -2791,7 +2795,7 @@
 {
 	int stat;
 	char mcnbuf[24];
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 
 /* get MCN */
 	if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
@@ -2815,7 +2819,7 @@
 int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
 				       int slot_nr)
 {
-	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	ide_drive_t *drive = cdi->handle;
 	int retval;
 	
 	if (slot_nr == CDSL_CURRENT) {
@@ -2886,7 +2890,7 @@
 	devinfo->mask = 0;
 	devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
 	devinfo->capacity = nslots;
-	devinfo->handle = (void *) drive;
+	devinfo->handle = drive;
 	strcpy(devinfo->name, drive->name);
 	
 	/* set capability mask to match the probe. */
@@ -2942,7 +2946,7 @@
 	 * registered with the Uniform layer yet, it can't do this.
 	 * Same goes for cdi->ops.
 	 */
-	cdi->handle = (ide_drive_t *) drive;
+	cdi->handle = drive;
 	cdi->ops = &ide_cdrom_dops;
 
 	if (ide_cdrom_get_capabilities(drive, &cap))
@@ -3254,6 +3258,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PROC_FS
 static
 sector_t ide_cdrom_capacity (ide_drive_t *drive)
 {
@@ -3264,6 +3269,7 @@
 
 	return capacity * sectors_per_frame;
 }
+#endif
 
 static int ide_cd_remove(struct device *dev)
 {
@@ -3309,7 +3315,7 @@
 static int proc_idecd_read_capacity
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_drive_t*drive = (ide_drive_t *)data;
+	ide_drive_t *drive = data;
 	int len;
 
 	len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
@@ -3449,7 +3455,7 @@
 		printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
 		goto failed;
 	}
-	info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
+	info = kmalloc(sizeof(struct cdrom_info), GFP_KERNEL);
 	if (info == NULL) {
 		printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
 		goto failed;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 4063d2c..84665e2 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -64,6 +64,7 @@
 		case ide_cy82c693:	name = "cy82c693";	break;
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
+		case ide_au1xxx:	name = "au1xxx";	break;
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ee38e6b..47f2b83 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1013,6 +1013,8 @@
 
 static DECLARE_MUTEX(idetape_ref_sem);
 
+static struct class *idetape_sysfs_class;
+
 #define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
 
 #define ide_tape_g(disk) \
@@ -4704,6 +4706,10 @@
 
 	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));
 	devfs_remove("%s/mt", drive->devfs_name);
 	devfs_remove("%s/mtn", drive->devfs_name);
 	devfs_unregister_tape(g->number);
@@ -4878,6 +4884,11 @@
 
 	idetape_setup(drive, tape, minor);
 
+	class_device_create(idetape_sysfs_class, NULL,
+			MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name);
+	class_device_create(idetape_sysfs_class, NULL,
+			MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
+
 	devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
 			S_IFCHR | S_IRUGO | S_IWUGO,
 			"%s/mt", drive->devfs_name);
@@ -4903,6 +4914,7 @@
 static void __exit idetape_exit (void)
 {
 	driver_unregister(&idetape_driver.gen_driver);
+	class_destroy(idetape_sysfs_class);
 	unregister_chrdev(IDETAPE_MAJOR, "ht");
 }
 
@@ -4911,11 +4923,33 @@
  */
 static int idetape_init (void)
 {
+	int error = 1;
+	idetape_sysfs_class = class_create(THIS_MODULE, "ide_tape");
+	if (IS_ERR(idetape_sysfs_class)) {
+		idetape_sysfs_class = NULL;
+		printk(KERN_ERR "Unable to create sysfs class for ide tapes\n");
+		error = -EBUSY;
+		goto out;
+	}
+
 	if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
 		printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
-		return -EBUSY;
+		error = -EBUSY;
+		goto out_free_class;
 	}
-	return driver_register(&idetape_driver.gen_driver);
+
+	error = driver_register(&idetape_driver.gen_driver);
+	if (error)
+		goto out_free_driver;
+
+	return 0;
+
+out_free_driver:
+	driver_unregister(&idetape_driver.gen_driver);
+out_free_class:
+	class_destroy(idetape_sysfs_class);
+out:
+	return error;
 }
 
 module_init(idetape_init);
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
new file mode 100644
index 0000000..2b6327c
--- /dev/null
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -0,0 +1,1250 @@
+/*
+ * 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
+ *
+ * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.
+ *
+ * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
+ *       Interface and Linux Device Driver" Application Note.
+ */
+#undef REALLY_SLOW_IO           /* most systems can safely undef this */
+
+#include <linux/config.h>       /* for CONFIG_BLK_DEV_IDEPCI */
+#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/hdreg.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/sysdev.h>
+
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1xxx.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#if CONFIG_PM
+#include <asm/mach-au1x00/au1xxx_pm.h>
+#endif
+
+#include <asm/mach-au1x00/au1xxx_ide.h>
+
+#define DRV_NAME	"au1200-ide"
+#define DRV_VERSION	"1.0"
+#define DRV_AUTHOR	"AMD PCS / Pete Popov <ppopov@embeddedalley.com>"
+#define DRV_DESC	"Au1200 IDE"
+
+static _auide_hwif auide_hwif;
+static spinlock_t ide_tune_drive_spin_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t ide_tune_chipset_spin_lock = SPIN_LOCK_UNLOCKED;
+static int dbdma_init_done = 0;
+
+/*
+ * local I/O functions
+ */
+u8 auide_inb(unsigned long port)
+{
+        return (au_readb(port));
+}
+
+u16 auide_inw(unsigned long port)
+{
+        return (au_readw(port));
+}
+
+u32 auide_inl(unsigned long port)
+{
+        return (au_readl(port));
+}
+
+void auide_insw(unsigned long port, void *addr, u32 count)
+{
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+
+        _auide_hwif *ahwif = &auide_hwif;
+        chan_tab_t *ctp;
+        au1x_ddma_desc_t *dp;
+
+        if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1,
+				DDMA_FLAGS_NOIE)) {
+                printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
+                return;
+        }
+        ctp = *((chan_tab_t **)ahwif->rx_chan);
+        dp = ctp->cur_ptr;
+        while (dp->dscr_cmd0 & DSCR_CMD0_V)
+                ;
+        ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
+#else
+        while (count--)
+        {
+                *(u16 *)addr = au_readw(port);
+                addr +=2 ;
+        }
+#endif
+}
+
+void auide_insl(unsigned long port, void *addr, u32 count)
+{
+        while (count--)
+        {
+                *(u32 *)addr = au_readl(port);
+                /* NOTE: For IDE interfaces over PCMCIA,
+                 * 32-bit access does not work
+                 */
+                addr += 4;
+        }
+}
+
+void auide_outb(u8 addr, unsigned long port)
+{
+        return (au_writeb(addr, port));
+}
+
+void auide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port)
+{
+        return (au_writeb(addr, port));
+}
+
+void auide_outw(u16 addr, unsigned long port)
+{
+        return (au_writew(addr, port));
+}
+
+void auide_outl(u32 addr, unsigned long port)
+{
+        return (au_writel(addr, port));
+}
+
+void auide_outsw(unsigned long port, void *addr, u32 count)
+{
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+        _auide_hwif *ahwif = &auide_hwif;
+        chan_tab_t *ctp;
+        au1x_ddma_desc_t *dp;
+
+        if(!put_source_flags(ahwif->tx_chan, (void*)addr,
+                                          count << 1, DDMA_FLAGS_NOIE)) {
+                printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__);
+                return;
+        }
+        ctp = *((chan_tab_t **)ahwif->tx_chan);
+        dp = ctp->cur_ptr;
+        while (dp->dscr_cmd0 & DSCR_CMD0_V)
+                ;
+        ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
+#else
+        while (count--)
+        {
+                au_writew(*(u16 *)addr, port);
+                addr += 2;
+        }
+#endif
+}
+
+void auide_outsl(unsigned long port, void *addr, u32 count)
+{
+        while (count--)
+        {
+                au_writel(*(u32 *)addr, port);
+                /* NOTE: For IDE interfaces over PCMCIA,
+                 * 32-bit access does not work
+                 */
+                addr += 4;
+        }
+}
+
+static void auide_tune_drive(ide_drive_t *drive, byte pio)
+{
+        int mem_sttime;
+        int mem_stcfg;
+        unsigned long flags;
+        u8 speed;
+
+        /* get the best pio mode for the drive */
+        pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+
+        printk("%s: setting Au1XXX IDE to PIO mode%d\n",
+                drive->name, pio);
+
+        spin_lock_irqsave(&ide_tune_drive_spin_lock, flags);
+
+        mem_sttime = 0;
+        mem_stcfg  = au_readl(MEM_STCFG2);
+
+        /* set pio mode! */
+        switch(pio) {
+                case 0:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_PIO0_TWCS
+                                     | SBC_IDE_PIO0_TCSH
+                                     | SBC_IDE_PIO0_TCSOFF
+                                     | SBC_IDE_PIO0_TWP
+                                     | SBC_IDE_PIO0_TCSW
+                                     | SBC_IDE_PIO0_TPM
+                                     | SBC_IDE_PIO0_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg |= TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS;
+
+                        au_writel(mem_sttime,MEM_STTIME2);
+                        au_writel(mem_stcfg,MEM_STCFG2);
+                        break;
+
+                case 1:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_PIO1_TWCS
+                                     | SBC_IDE_PIO1_TCSH
+                                     | SBC_IDE_PIO1_TCSOFF
+                                     | SBC_IDE_PIO1_TWP
+                                     | SBC_IDE_PIO1_TCSW
+                                     | SBC_IDE_PIO1_TPM
+                                     | SBC_IDE_PIO1_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg |= TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS;
+                        break;
+
+                case 2:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_PIO2_TWCS
+                                     | SBC_IDE_PIO2_TCSH
+                                     | SBC_IDE_PIO2_TCSOFF
+                                     | SBC_IDE_PIO2_TWP
+                                     | SBC_IDE_PIO2_TCSW
+                                     | SBC_IDE_PIO2_TPM
+                                     | SBC_IDE_PIO2_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg &= ~TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS;
+                        break;
+
+                case 3:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_PIO3_TWCS
+                                     | SBC_IDE_PIO3_TCSH
+                                     | SBC_IDE_PIO3_TCSOFF
+                                     | SBC_IDE_PIO3_TWP
+                                     | SBC_IDE_PIO3_TCSW
+                                     | SBC_IDE_PIO3_TPM
+                                     | SBC_IDE_PIO3_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg |= TS_MASK;
+                        mem_stcfg &= ~TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS;
+
+                        break;
+
+                case 4:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_PIO4_TWCS
+                                     | SBC_IDE_PIO4_TCSH
+                                     | SBC_IDE_PIO4_TCSOFF
+                                     | SBC_IDE_PIO4_TWP
+                                     | SBC_IDE_PIO4_TCSW
+                                     | SBC_IDE_PIO4_TPM
+                                     | SBC_IDE_PIO4_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg &= ~TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS;
+                        break;
+        }
+
+        au_writel(mem_sttime,MEM_STTIME2);
+        au_writel(mem_stcfg,MEM_STCFG2);
+
+        spin_unlock_irqrestore(&ide_tune_drive_spin_lock, flags);
+
+        speed = pio + XFER_PIO_0;
+        ide_config_drive_speed(drive, speed);
+}
+
+static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
+{
+        u8 mode = 0;
+        int mem_sttime;
+        int mem_stcfg;
+        unsigned long flags;
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+        struct hd_driveid *id = drive->id;
+
+        /*
+         * Now see what the current drive is capable of,
+         * selecting UDMA only if the mate said it was ok.
+         */
+        if (id && (id->capability & 1) && drive->autodma &&
+            !__ide_dma_bad_drive(drive)) {
+                if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
+                        if      (id->dma_mword & 4)
+                                mode = XFER_MW_DMA_2;
+                        else if (id->dma_mword & 2)
+                                mode = XFER_MW_DMA_1;
+                        else if (id->dma_mword & 1)
+                                mode = XFER_MW_DMA_0;
+                }
+        }
+#endif
+
+        spin_lock_irqsave(&ide_tune_chipset_spin_lock, flags);
+
+        mem_sttime = 0;
+        mem_stcfg  = au_readl(MEM_STCFG2);
+
+        switch(speed) {
+                case XFER_PIO_4:
+                case XFER_PIO_3:
+                case XFER_PIO_2:
+                case XFER_PIO_1:
+                case XFER_PIO_0:
+                        auide_tune_drive(drive, (speed - XFER_PIO_0));
+                        break;
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+                case XFER_MW_DMA_2:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_MDMA2_TWCS
+                                     | SBC_IDE_MDMA2_TCSH
+                                     | SBC_IDE_MDMA2_TCSOFF
+                                     | SBC_IDE_MDMA2_TWP
+                                     | SBC_IDE_MDMA2_TCSW
+                                     | SBC_IDE_MDMA2_TPM
+                                     | SBC_IDE_MDMA2_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg &= ~TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
+
+                        mode = XFER_MW_DMA_2;
+                        break;
+                case XFER_MW_DMA_1:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_MDMA1_TWCS
+                                     | SBC_IDE_MDMA1_TCSH
+                                     | SBC_IDE_MDMA1_TCSOFF
+                                     | SBC_IDE_MDMA1_TWP
+                                     | SBC_IDE_MDMA1_TCSW
+                                     | SBC_IDE_MDMA1_TPM
+                                     | SBC_IDE_MDMA1_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg &= ~TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
+
+                        mode = XFER_MW_DMA_1;
+                        break;
+                case XFER_MW_DMA_0:
+                        /* set timing parameters for RCS2# */
+                        mem_sttime =   SBC_IDE_MDMA0_TWCS
+                                     | SBC_IDE_MDMA0_TCSH
+                                     | SBC_IDE_MDMA0_TCSOFF
+                                     | SBC_IDE_MDMA0_TWP
+                                     | SBC_IDE_MDMA0_TCSW
+                                     | SBC_IDE_MDMA0_TPM
+                                     | SBC_IDE_MDMA0_TA;
+                        /* set configuration for RCS2# */
+                        mem_stcfg |= TS_MASK;
+                        mem_stcfg &= ~TCSOE_MASK;
+                        mem_stcfg &= ~TOECS_MASK;
+                        mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
+
+                        mode = XFER_MW_DMA_0;
+                        break;
+#endif
+                default:
+                        return 1;
+        }
+
+        /*
+         * Tell the drive to switch to the new mode; abort on failure.
+         */
+        if (!mode || ide_config_drive_speed(drive, mode))
+        {
+                return 1;       /* failure */
+        }
+
+
+        au_writel(mem_sttime,MEM_STTIME2);
+        au_writel(mem_stcfg,MEM_STCFG2);
+
+        spin_unlock_irqrestore(&ide_tune_chipset_spin_lock, flags);
+
+        return 0;
+}
+
+/*
+ * Multi-Word DMA + DbDMA functions
+ */
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+
+static int in_drive_list(struct hd_driveid *id,
+                         const struct drive_list_entry *drive_table)
+{
+        for ( ; drive_table->id_model ; drive_table++){
+                if ((!strcmp(drive_table->id_model, id->model)) &&
+                        ((strstr(drive_table->id_firmware, id->fw_rev)) ||
+                        (!strcmp(drive_table->id_firmware, "ALL")))
+                )
+                        return 1;
+        }
+        return 0;
+}
+
+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;
+        ide_hwif_t *hwif = HWIF(drive);
+
+        struct request *rq = HWGROUP(drive)->rq;
+
+        _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+        struct scatterlist *sg;
+
+        iswrite = (rq_data_dir(rq) == WRITE);
+        /* Save for interrupt context */
+        ahwif->drive = drive;
+
+        /* Build sglist */
+        hwif->sg_nents = i = auide_build_sglist(drive, rq);
+
+        if (!i)
+                return 0;
+
+        /* fill the descriptors */
+        sg = hwif->sg_table;
+        while (i && sg_dma_len(sg)) {
+                u32 cur_addr;
+                u32 cur_len;
+
+                cur_addr = sg_dma_address(sg);
+                cur_len = sg_dma_len(sg);
+
+                while (cur_len) {
+                        u32 flags = DDMA_FLAGS_NOIE;
+                        unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
+
+                        if (++count >= PRD_ENTRIES) {
+                                printk(KERN_WARNING "%s: DMA table too small\n",
+                                drive->name);
+                                goto use_pio_instead;
+                        }
+
+                        /* Lets enable intr for the last descriptor only */
+                        if (1==i)
+                                flags = DDMA_FLAGS_IE;
+                        else
+                                flags = DDMA_FLAGS_NOIE;
+
+                        if (iswrite) {
+				if(!put_source_flags(ahwif->tx_chan,
+						(void*)(page_address(sg->page)
+							+ sg->offset),
+						tc, flags)) {
+					printk(KERN_ERR "%s failed %d\n",
+							__FUNCTION__, __LINE__);
+				}
+                        } else
+			{
+				if(!put_dest_flags(ahwif->rx_chan,
+						(void*)(page_address(sg->page)
+							+ sg->offset),
+						tc, flags)) {
+					printk(KERN_ERR "%s failed %d\n",
+							__FUNCTION__, __LINE__);
+				}
+                        }
+
+                        cur_addr += tc;
+                        cur_len -= tc;
+                }
+                sg++;
+                i--;
+        }
+
+        if (count)
+                return 1;
+
+use_pio_instead:
+        dma_unmap_sg(ahwif->dev,
+                     hwif->sg_table,
+                     hwif->sg_nents,
+                     hwif->sg_dma_direction);
+
+        return 0; /* revert to PIO for this request */
+}
+
+static int auide_dma_end(ide_drive_t *drive)
+{
+        ide_hwif_t *hwif = HWIF(drive);
+        _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+
+        if (hwif->sg_nents) {
+                dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents,
+                             hwif->sg_dma_direction);
+                hwif->sg_nents = 0;
+        }
+
+        return 0;
+}
+
+static void auide_dma_start(ide_drive_t *drive )
+{
+//      printk("%s\n", __FUNCTION__);
+}
+
+ide_startstop_t auide_dma_intr(ide_drive_t *drive)
+{
+        //printk("%s\n", __FUNCTION__);
+
+        u8 stat = 0, dma_stat = 0;
+
+        dma_stat = HWIF(drive)->ide_dma_end(drive);
+        stat = HWIF(drive)->INB(IDE_STATUS_REG);        /* get drive status */
+        if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+                if (!dma_stat) {
+                        struct request *rq = HWGROUP(drive)->rq;
+
+                        ide_end_request(drive, 1, rq->nr_sectors);
+                        return ide_stopped;
+                }
+                printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
+                                 drive->name, dma_stat);
+        }
+        return ide_error(drive, "dma_intr", stat);
+}
+
+static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+        //printk("%s\n", __FUNCTION__);
+
+        /* issue cmd to drive */
+        ide_execute_command(drive, command, &auide_dma_intr,
+                            (2*WAIT_CMD), NULL);
+}
+
+static int auide_dma_setup(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+
+        if (drive->media != ide_disk)
+                return 1;
+
+        if (!auide_build_dmatable(drive))
+                        /* try PIO instead of DMA */
+                        return 1;
+
+        drive->waiting_for_dma = 1;
+
+        return 0;
+}
+
+static int auide_dma_check(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+        if( !dbdma_init_done ){
+                auide_hwif.white_list = in_drive_list(drive->id,
+                                                      dma_white_list);
+                auide_hwif.black_list = in_drive_list(drive->id,
+                                                      dma_black_list);
+                auide_hwif.drive = drive;
+                auide_ddma_init(&auide_hwif);
+                dbdma_init_done = 1;
+        }
+#endif
+
+        /* Is the drive in our DMA black list? */
+        if ( auide_hwif.black_list ) {
+                drive->using_dma = 0;
+                printk("%s found in dma_blacklist[]! Disabling DMA.\n",
+                drive->id->model);
+        }
+        else
+                drive->using_dma = 1;
+
+        return HWIF(drive)->ide_dma_host_on(drive);
+}
+
+static int auide_dma_test_irq(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+
+        if (!drive->waiting_for_dma)
+                printk(KERN_WARNING "%s: ide_dma_test_irq \
+                                     called while not waiting\n", drive->name);
+
+        /* If dbdma didn't execute the STOP command yet, the
+         * active bit is still set
+	 */
+        drive->waiting_for_dma++;
+        if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
+                printk(KERN_WARNING "%s: timeout waiting for ddma to \
+                                     complete\n", drive->name);
+                return 1;
+        }
+        udelay(10);
+        return 0;
+}
+
+static int auide_dma_host_on(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+        return 0;
+}
+
+static int auide_dma_on(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+        drive->using_dma = 1;
+        return auide_dma_host_on(drive);
+}
+
+
+static int auide_dma_host_off(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+        return 0;
+}
+
+static int auide_dma_off_quietly(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+        drive->using_dma = 0;
+        return auide_dma_host_off(drive);
+}
+
+static int auide_dma_lostirq(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+
+        printk(KERN_ERR "%s: IRQ lost\n", drive->name);
+        return 0;
+}
+
+static void auide_ddma_tx_callback(int irq, void *param, struct pt_regs *regs)
+{
+//      printk("%s\n", __FUNCTION__);
+
+        _auide_hwif *ahwif = (_auide_hwif*)param;
+        ahwif->drive->waiting_for_dma = 0;
+        return;
+}
+
+static void auide_ddma_rx_callback(int irq, void *param, struct pt_regs *regs)
+{
+//      printk("%s\n", __FUNCTION__);
+
+        _auide_hwif *ahwif = (_auide_hwif*)param;
+        ahwif->drive->waiting_for_dma = 0;
+        return;
+}
+
+static int auide_dma_timeout(ide_drive_t *drive)
+{
+//      printk("%s\n", __FUNCTION__);
+
+        printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
+
+        if (HWIF(drive)->ide_dma_test_irq(drive))
+                return 0;
+
+        return HWIF(drive)->ide_dma_end(drive);
+}
+#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+
+
+static int auide_ddma_init( _auide_hwif *auide )
+{
+//      printk("%s\n", __FUNCTION__);
+
+        dbdev_tab_t source_dev_tab;
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+        dbdev_tab_t target_dev_tab;
+        ide_hwif_t *hwif = auide->hwif;
+        char warning_output [2][80];
+        int i;
+#endif
+
+        /* Add our custom device to DDMA device table */
+        /* Create our new device entries in the table */
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+        source_dev_tab.dev_id = AU1XXX_ATA_DDMA_REQ;
+
+        if( auide->white_list || auide->black_list ){
+                source_dev_tab.dev_tsize       = 8;
+                source_dev_tab.dev_devwidth    = 32;
+                source_dev_tab.dev_physaddr    = (u32)AU1XXX_ATA_PHYS_ADDR;
+                source_dev_tab.dev_intlevel    = 0;
+                source_dev_tab.dev_intpolarity = 0;
+
+                /* init device table for target - static bus controller - */
+                target_dev_tab.dev_id          = DSCR_CMD0_ALWAYS;
+                target_dev_tab.dev_tsize       = 8;
+                target_dev_tab.dev_devwidth    = 32;
+                target_dev_tab.dev_physaddr    = (u32)AU1XXX_ATA_PHYS_ADDR;
+                target_dev_tab.dev_intlevel    = 0;
+                target_dev_tab.dev_intpolarity = 0;
+                target_dev_tab.dev_flags       = DEV_FLAGS_ANYUSE;
+        }
+        else{
+                source_dev_tab.dev_tsize       = 1;
+                source_dev_tab.dev_devwidth    = 16;
+                source_dev_tab.dev_physaddr    = (u32)AU1XXX_ATA_PHYS_ADDR;
+                source_dev_tab.dev_intlevel    = 0;
+                source_dev_tab.dev_intpolarity = 0;
+
+                /* init device table for target - static bus controller - */
+                target_dev_tab.dev_id          = DSCR_CMD0_ALWAYS;
+                target_dev_tab.dev_tsize       = 1;
+                target_dev_tab.dev_devwidth    = 16;
+                target_dev_tab.dev_physaddr    = (u32)AU1XXX_ATA_PHYS_ADDR;
+                target_dev_tab.dev_intlevel    = 0;
+                target_dev_tab.dev_intpolarity = 0;
+                target_dev_tab.dev_flags       = DEV_FLAGS_ANYUSE;
+
+                sprintf(&warning_output[0][0],
+                        "%s is not on ide driver white list.",
+                        auide_hwif.drive->id->model);
+                for ( i=strlen(&warning_output[0][0]) ; i<76; i++ ){
+                        sprintf(&warning_output[0][i]," ");
+                }
+
+                sprintf(&warning_output[1][0],
+                "To add %s please read 'Documentation/mips/AU1xxx_IDE.README'.",
+                        auide_hwif.drive->id->model);
+                for ( i=strlen(&warning_output[1][0]) ; i<76; i++ ){
+                        sprintf(&warning_output[1][i]," ");
+                }
+
+                printk("\n****************************************");
+                printk("****************************************\n");
+                printk("* %s *\n",&warning_output[0][0]);
+                printk("* Switch to safe MWDMA Mode!            ");
+                printk("                                       *\n");
+                printk("* %s *\n",&warning_output[1][0]);
+                printk("****************************************");
+                printk("****************************************\n\n");
+        }
+#else
+        source_dev_tab.dev_id = DSCR_CMD0_ALWAYS;
+        source_dev_tab.dev_tsize       = 8;
+        source_dev_tab.dev_devwidth    = 32;
+        source_dev_tab.dev_physaddr    = (u32)AU1XXX_ATA_PHYS_ADDR;
+        source_dev_tab.dev_intlevel    = 0;
+        source_dev_tab.dev_intpolarity = 0;
+#endif
+
+#if CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON
+        /* set flags for tx channel */
+        source_dev_tab.dev_flags =  DEV_FLAGS_OUT
+                                  | DEV_FLAGS_SYNC
+                                  | DEV_FLAGS_BURSTABLE;
+        auide->tx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+        /* set flags for rx channel */
+        source_dev_tab.dev_flags =  DEV_FLAGS_IN
+                                  | DEV_FLAGS_SYNC
+                                  | DEV_FLAGS_BURSTABLE;
+        auide->rx_dev_id = au1xxx_ddma_add_device( &source_dev_tab );
+#else
+        /* set flags for tx channel */
+        source_dev_tab.dev_flags = DEV_FLAGS_OUT | DEV_FLAGS_SYNC;
+        auide->tx_dev_id         = au1xxx_ddma_add_device( &source_dev_tab );
+        /* set flags for rx channel */
+        source_dev_tab.dev_flags = DEV_FLAGS_IN | DEV_FLAGS_SYNC;
+        auide->rx_dev_id         = au1xxx_ddma_add_device( &source_dev_tab );
+#endif
+
+#if  defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+
+        auide->target_dev_id           = au1xxx_ddma_add_device(&target_dev_tab);
+
+        /* Get a channel for TX */
+        auide->tx_chan = au1xxx_dbdma_chan_alloc(auide->target_dev_id,
+                                                 auide->tx_dev_id,
+                                                 auide_ddma_tx_callback,
+                                                 (void*)auide);
+        /* Get a channel for RX */
+        auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
+                                                 auide->target_dev_id,
+                                                 auide_ddma_rx_callback,
+                                                 (void*)auide);
+#else   /* CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA */
+        /*
+         * Note: if call back is not enabled, update ctp->cur_ptr manually
+         */
+        auide->tx_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
+                                                 auide->tx_dev_id,
+                                                 NULL,
+                                                 (void*)auide);
+        auide->rx_chan = au1xxx_dbdma_chan_alloc(auide->rx_dev_id,
+                                                 DSCR_CMD0_ALWAYS,
+                                                 NULL,
+                                                 (void*)auide);
+#endif
+        auide->tx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->tx_chan,
+                                                             NUM_DESCRIPTORS);
+        auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
+                                                             NUM_DESCRIPTORS);
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+        hwif->dmatable_cpu = dma_alloc_coherent(auide->dev,
+                                                PRD_ENTRIES * PRD_BYTES,        /* 1 Page */
+                                                &hwif->dmatable_dma, GFP_KERNEL);
+
+        auide->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
+                                GFP_KERNEL|GFP_DMA);
+        if (auide->sg_table == NULL) {
+                return -ENOMEM;
+        }
+#endif
+        au1xxx_dbdma_start( auide->tx_chan );
+        au1xxx_dbdma_start( auide->rx_chan );
+        return 0;
+}
+
+static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
+{
+        int i;
+#define ide_ioreg_t unsigned long
+        ide_ioreg_t *ata_regs = hw->io_ports;
+
+	/* fixme */
+        for (i = 0; i < IDE_CONTROL_OFFSET; i++) {
+                *ata_regs++ = (ide_ioreg_t) ahwif->regbase
+                            + (ide_ioreg_t)(i << AU1XXX_ATA_REG_OFFSET);
+        }
+
+        /* set the Alternative Status register */
+        *ata_regs = (ide_ioreg_t) ahwif->regbase
+                  + (ide_ioreg_t)(14 << AU1XXX_ATA_REG_OFFSET);
+}
+
+static int au_ide_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+        _auide_hwif *ahwif = &auide_hwif;
+        ide_hwif_t *hwif;
+	struct resource *res;
+	int ret = 0;
+
+#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
+        char *mode = "MWDMA2";
+#elif defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
+        char *mode = "PIO+DDMA(offload)";
+#endif
+
+        memset(&auide_hwif, 0, sizeof(_auide_hwif));
+        auide_hwif.dev                  = 0;
+
+	ahwif->dev = dev;
+	ahwif->irq = platform_get_irq(pdev, 0);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (res == NULL) {
+		pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id);
+		ret = -ENODEV;
+		goto out;
+	}
+
+        if (!request_mem_region (res->start, res->end-res->start, pdev->name)) {
+		pr_debug("%s: request_mem_region failed\n", DRV_NAME);
+                ret =  -EBUSY;
+		goto out;
+        }
+
+	ahwif->regbase = (u32)ioremap(res->start, res->end-res->start);
+	if (ahwif->regbase == 0) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+        hwif                            = &ide_hwifs[pdev->id];
+	hw_regs_t *hw 			= &hwif->hw;
+        hwif->irq = hw->irq             = ahwif->irq;
+        hwif->chipset                   = ide_au1xxx;
+
+        auide_setup_ports(hw, ahwif);
+	memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+        hwif->rqsize = CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ;
+        hwif->rqsize                    = ((hwif->rqsize > AU1XXX_ATA_RQSIZE)
+                                        || (hwif->rqsize < 32)) ? AU1XXX_ATA_RQSIZE : hwif->rqsize;
+#else /* if kernel config is not set */
+        hwif->rqsize                    = AU1XXX_ATA_RQSIZE;
+#endif
+
+        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                = 0x07;
+#else
+        hwif->mwdma_mask                = 0x0;
+        hwif->swdma_mask                = 0x0;
+#endif
+        //hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+        hwif->noprobe = 0;
+        hwif->drives[0].unmask          = 1;
+        hwif->drives[1].unmask          = 1;
+
+        /* hold should be on in all cases */
+        hwif->hold                      = 1;
+        hwif->mmio                      = 2;
+
+        /* set up local I/O function entry points */
+        hwif->INB                       = auide_inb;
+        hwif->INW                       = auide_inw;
+        hwif->INL                       = auide_inl;
+        hwif->INSW                      = auide_insw;
+        hwif->INSL                      = auide_insl;
+        hwif->OUTB                      = auide_outb;
+        hwif->OUTBSYNC                  = auide_outbsync;
+        hwif->OUTW                      = auide_outw;
+        hwif->OUTL                      = auide_outl;
+        hwif->OUTSW                     = auide_outsw;
+        hwif->OUTSL                     = auide_outsl;
+
+        hwif->tuneproc                  = &auide_tune_drive;
+        hwif->speedproc                 = &auide_tune_chipset;
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+        hwif->ide_dma_off_quietly       = &auide_dma_off_quietly;
+        hwif->ide_dma_timeout           = &auide_dma_timeout;
+
+        hwif->ide_dma_check             = &auide_dma_check;
+        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->ide_dma_host_off          = &auide_dma_host_off;
+        hwif->ide_dma_host_on           = &auide_dma_host_on;
+        hwif->ide_dma_lostirq           = &auide_dma_lostirq;
+        hwif->ide_dma_on                = &auide_dma_on;
+
+        hwif->autodma                   = 1;
+        hwif->drives[0].autodma         = hwif->autodma;
+        hwif->drives[1].autodma         = hwif->autodma;
+        hwif->atapi_dma                 = 1;
+        hwif->drives[0].using_dma       = 1;
+        hwif->drives[1].using_dma       = 1;
+#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+        hwif->autodma                   = 0;
+        hwif->channel                   = 0;
+        hwif->hold                      = 1;
+        hwif->select_data               = 0;    /* no chipset-specific code */
+        hwif->config_data               = 0;    /* no chipset-specific code */
+
+        hwif->drives[0].autodma         = 0;
+        hwif->drives[0].drive_data      = 0;    /* no drive data */
+        hwif->drives[0].using_dma       = 0;
+        hwif->drives[0].waiting_for_dma = 0;
+        hwif->drives[0].autotune        = 1;    /* 1=autotune, 2=noautotune, 0=default */
+        /* secondary hdd not supported */
+        hwif->drives[1].autodma         = 0;
+
+        hwif->drives[1].drive_data      = 0;
+        hwif->drives[1].using_dma       = 0;
+        hwif->drives[1].waiting_for_dma = 0;
+        hwif->drives[1].autotune        = 2;   /* 1=autotune, 2=noautotune, 0=default */
+#endif
+        hwif->drives[0].io_32bit        = 0;   /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
+        hwif->drives[1].io_32bit        = 0;   /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
+
+        /*Register Driver with PM Framework*/
+#ifdef CONFIG_PM
+        auide_hwif.pm.lock    = SPIN_LOCK_UNLOCKED;
+        auide_hwif.pm.stopped = 0;
+
+        auide_hwif.pm.dev = new_au1xxx_power_device( "ide",
+                                                &au1200ide_pm_callback,
+                                                NULL);
+        if ( auide_hwif.pm.dev == NULL )
+                printk(KERN_INFO "Unable to create a power management \
+                                device entry for the au1200-IDE.\n");
+        else
+                printk(KERN_INFO "Power management device entry for the \
+                                au1200-IDE loaded.\n");
+#endif
+
+        auide_hwif.hwif                 = hwif;
+        hwif->hwif_data                 = &auide_hwif;
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+        auide_ddma_init(&auide_hwif);
+        dbdma_init_done = 1;
+#endif
+
+	probe_hwif_init(hwif);
+	dev_set_drvdata(dev, hwif);
+
+        printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
+
+out:
+        return ret;
+}
+
+static int au_ide_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res;
+	ide_hwif_t *hwif = dev_get_drvdata(dev);
+        _auide_hwif *ahwif = &auide_hwif;
+
+	ide_unregister(hwif - ide_hwifs);
+
+	iounmap((void *)ahwif->regbase);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start);
+
+	return 0;
+}
+
+static struct device_driver au1200_ide_driver = {
+	.name		= "au1200-ide",
+	.bus		= &platform_bus_type,
+	.probe 		= au_ide_probe,
+	.remove		= au_ide_remove,
+};
+
+static int __init au_ide_init(void)
+{
+	return driver_register(&au1200_ide_driver);
+}
+
+static void __init au_ide_exit(void)
+{
+	driver_unregister(&au1200_ide_driver);
+}
+
+#ifdef CONFIG_PM
+int au1200ide_pm_callback( au1xxx_power_dev_t *dev,\
+                        au1xxx_request_t request, void *data) {
+
+        unsigned int d, err = 0;
+        unsigned long flags;
+
+        spin_lock_irqsave(auide_hwif.pm.lock, flags);
+
+        switch (request){
+                case AU1XXX_PM_SLEEP:
+                        err = au1xxxide_pm_sleep(dev);
+                        break;
+                case AU1XXX_PM_WAKEUP:
+                        d = *((unsigned int*)data);
+                        if ( d > 0 && d <= 99) {
+                                err = au1xxxide_pm_standby(dev);
+                        }
+                        else {
+                                err = au1xxxide_pm_resume(dev);
+                        }
+                        break;
+                case AU1XXX_PM_GETSTATUS:
+                        err = au1xxxide_pm_getstatus(dev);
+                        break;
+                case AU1XXX_PM_ACCESS:
+                        err = au1xxxide_pm_access(dev);
+                        break;
+                case AU1XXX_PM_IDLE:
+                        err = au1xxxide_pm_idle(dev);
+                        break;
+                case AU1XXX_PM_CLEANUP:
+                        err = au1xxxide_pm_cleanup(dev);
+                        break;
+                default:
+                        err = -1;
+                        break;
+        }
+
+        spin_unlock_irqrestore(auide_hwif.pm.lock, flags);
+
+        return err;
+}
+
+static int au1xxxide_pm_standby( au1xxx_power_dev_t *dev ) {
+        return 0;
+}
+
+static int au1xxxide_pm_sleep( au1xxx_power_dev_t *dev ) {
+
+        int retval;
+        ide_hwif_t *hwif = auide_hwif.hwif;
+        struct request rq;
+        struct request_pm_state rqpm;
+        ide_task_t args;
+
+        if(auide_hwif.pm.stopped)
+                return -1;
+
+        /*
+         * wait until hard disc is ready
+         */
+        if ( wait_for_ready(&hwif->drives[0], 35000) ) {
+                printk("Wait for drive sleep timeout!\n");
+                retval = -1;
+        }
+
+        /*
+         * sequenz to tell the high level ide driver that pm is resuming
+         */
+        memset(&rq, 0, sizeof(rq));
+        memset(&rqpm, 0, sizeof(rqpm));
+        memset(&args, 0, sizeof(args));
+        rq.flags = REQ_PM_SUSPEND;
+        rq.special = &args;
+        rq.pm = &rqpm;
+        rqpm.pm_step = ide_pm_state_start_suspend;
+        rqpm.pm_state = PMSG_SUSPEND;
+
+        retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_wait);
+
+        if (wait_for_ready (&hwif->drives[0], 35000)) {
+                printk("Wait for drive sleep timeout!\n");
+                retval = -1;
+        }
+
+        /*
+         * stop dbdma channels
+         */
+        au1xxx_dbdma_reset(auide_hwif.tx_chan);
+        au1xxx_dbdma_reset(auide_hwif.rx_chan);
+
+        auide_hwif.pm.stopped = 1;
+
+        return retval;
+}
+
+static int au1xxxide_pm_resume( au1xxx_power_dev_t *dev ) {
+
+        int retval;
+        ide_hwif_t *hwif = auide_hwif.hwif;
+        struct request rq;
+        struct request_pm_state rqpm;
+        ide_task_t args;
+
+        if(!auide_hwif.pm.stopped)
+                return -1;
+
+        /*
+         * start dbdma channels
+         */
+        au1xxx_dbdma_start(auide_hwif.tx_chan);
+        au1xxx_dbdma_start(auide_hwif.rx_chan);
+
+        /*
+         * wait until hard disc is ready
+         */
+        if (wait_for_ready ( &hwif->drives[0], 35000)) {
+                printk("Wait for drive wake up timeout!\n");
+                retval = -1;
+        }
+
+        /*
+         * sequenz to tell the high level ide driver that pm is resuming
+         */
+        memset(&rq, 0, sizeof(rq));
+        memset(&rqpm, 0, sizeof(rqpm));
+        memset(&args, 0, sizeof(args));
+        rq.flags = REQ_PM_RESUME;
+        rq.special = &args;
+        rq.pm = &rqpm;
+        rqpm.pm_step = ide_pm_state_start_resume;
+        rqpm.pm_state = PMSG_ON;
+
+        retval = ide_do_drive_cmd(&hwif->drives[0], &rq, ide_head_wait);
+
+        /*
+        * wait for hard disc
+        */
+        if ( wait_for_ready(&hwif->drives[0], 35000) ) {
+                printk("Wait for drive wake up timeout!\n");
+                retval = -1;
+        }
+
+        auide_hwif.pm.stopped = 0;
+
+        return retval;
+}
+
+static int au1xxxide_pm_getstatus( au1xxx_power_dev_t *dev ) {
+        return dev->cur_state;
+}
+
+static int au1xxxide_pm_access( au1xxx_power_dev_t *dev ) {
+        if (dev->cur_state != AWAKE_STATE)
+                return 0;
+        else
+                return -1;
+}
+
+static int au1xxxide_pm_idle( au1xxx_power_dev_t *dev ) {
+        return 0;
+}
+
+static int au1xxxide_pm_cleanup( au1xxx_power_dev_t *dev ) {
+        return 0;
+}
+#endif /* CONFIG_PM */
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AU1200 IDE driver");
+
+module_init(au_ide_init);
+module_exit(au_ide_exit);
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index e34730c..cbbbe14 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2361,7 +2361,7 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	class_device_create(hpsb_protocol_class, MKDEV(
+	class_device_create(hpsb_protocol_class, NULL, MKDEV(
 		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
 		NULL, "dv1394-%d", id);
 	devfs_mk_dir("ieee1394/dv/host%d", id);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 4802bbb..c9e92d8 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -1630,7 +1630,7 @@
 /* Transmit a packet (called by kernel) */
 static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
 {
-	int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+	gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 	struct eth1394hdr *eth;
 	struct eth1394_priv *priv = netdev_priv(dev);
 	int proto;
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 347ece6..7fff5a1 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1292,7 +1292,7 @@
 
 		if (ud->device.driver &&
 		    (!ud->device.driver->suspend ||
-		      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0)))
+		      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
 			device_release_driver(&ud->device);
 	}
 	up_write(&ne->device.bus->subsys.rwsem);
@@ -1315,7 +1315,7 @@
 			continue;
 
 		if (ud->device.driver && ud->device.driver->resume)
-			ud->device.driver->resume(&ud->device, 0);
+			ud->device.driver->resume(&ud->device);
 	}
 	up_read(&ne->device.bus->subsys.rwsem);
 
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 0470f77..24411e6 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2912,7 +2912,7 @@
 
 	hpsb_register_highlevel(&raw1394_highlevel);
 
-	if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV(
+	if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
 		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_RAW1394 * 16), 
 		NULL, RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 11be9c9..23911da 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1370,7 +1370,7 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	class_device_create(hpsb_protocol_class, MKDEV(
+	class_device_create(hpsb_protocol_class, NULL, MKDEV(
 		IEEE1394_MAJOR,	minor), 
 		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 5ac86f5..0c3c695 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -37,58 +37,41 @@
  * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
  */
 
-#include <linux/dma-mapping.h>
-
-#include <asm/bug.h>
-
-#include <rdma/ib_smi.h>
-
-#include "smi.h"
-#include "agent_priv.h"
-#include "mad_priv.h"
 #include "agent.h"
+#include "smi.h"
 
-spinlock_t ib_agent_port_list_lock;
+#define SPFX "ib_agent: "
+
+struct ib_agent_port_private {
+	struct list_head port_list;
+	struct ib_mad_agent *agent[2];
+};
+
+static DEFINE_SPINLOCK(ib_agent_port_list_lock);
 static LIST_HEAD(ib_agent_port_list);
 
-/*
- * Caller must hold ib_agent_port_list_lock
- */
-static inline struct ib_agent_port_private *
-__ib_get_agent_port(struct ib_device *device, int port_num,
-		    struct ib_mad_agent *mad_agent)
+static struct ib_agent_port_private *
+__ib_get_agent_port(struct ib_device *device, int port_num)
 {
 	struct ib_agent_port_private *entry;
 
-	BUG_ON(!(!!device ^ !!mad_agent));  /* Exactly one MUST be (!NULL) */
-
-	if (device) {
-		list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-			if (entry->smp_agent->device == device &&
-			    entry->port_num == port_num)
-				return entry;
-		}
-	} else {
-		list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-			if ((entry->smp_agent == mad_agent) ||
-			    (entry->perf_mgmt_agent == mad_agent))
-				return entry;
-		}
+	list_for_each_entry(entry, &ib_agent_port_list, port_list) {
+		if (entry->agent[0]->device == device &&
+		    entry->agent[0]->port_num == port_num)
+			return entry;
 	}
 	return NULL;
 }
 
-static inline struct ib_agent_port_private *
-ib_get_agent_port(struct ib_device *device, int port_num,
-		  struct ib_mad_agent *mad_agent)
+static struct ib_agent_port_private *
+ib_get_agent_port(struct ib_device *device, int port_num)
 {
 	struct ib_agent_port_private *entry;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ib_agent_port_list_lock, flags);
-	entry = __ib_get_agent_port(device, port_num, mad_agent);
+	entry = __ib_get_agent_port(device, port_num);
 	spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
-
 	return entry;
 }
 
@@ -100,192 +83,76 @@
 
 	if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
 		return 1;
-	port_priv = ib_get_agent_port(device, port_num, NULL);
+
+	port_priv = ib_get_agent_port(device, port_num);
 	if (!port_priv) {
 		printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d "
-		       "not open\n",
-		       device->name, port_num);
+		       "not open\n", device->name, port_num);
 		return 1;
 	}
 
-	return smi_check_local_smp(port_priv->smp_agent, smp);
+	return smi_check_local_smp(port_priv->agent[0], smp);
 }
 
-static int agent_mad_send(struct ib_mad_agent *mad_agent,
-			  struct ib_agent_port_private *port_priv,
-			  struct ib_mad_private *mad_priv,
-			  struct ib_grh *grh,
-			  struct ib_wc *wc)
-{
-	struct ib_agent_send_wr *agent_send_wr;
-	struct ib_sge gather_list;
-	struct ib_send_wr send_wr;
-	struct ib_send_wr *bad_send_wr;
-	struct ib_ah_attr ah_attr;
-	unsigned long flags;
-	int ret = 1;
-
-	agent_send_wr = kmalloc(sizeof(*agent_send_wr), GFP_KERNEL);
-	if (!agent_send_wr)
-		goto out;
-	agent_send_wr->mad = mad_priv;
-
-	gather_list.addr = dma_map_single(mad_agent->device->dma_device,
-					  &mad_priv->mad,
-					  sizeof(mad_priv->mad),
-					  DMA_TO_DEVICE);
-	gather_list.length = sizeof(mad_priv->mad);
-	gather_list.lkey = mad_agent->mr->lkey;
-
-	send_wr.next = NULL;
-	send_wr.opcode = IB_WR_SEND;
-	send_wr.sg_list = &gather_list;
-	send_wr.num_sge = 1;
-	send_wr.wr.ud.remote_qpn = wc->src_qp; /* DQPN */
-	send_wr.wr.ud.timeout_ms = 0;
-	send_wr.send_flags = IB_SEND_SIGNALED | IB_SEND_SOLICITED;
-
-	ah_attr.dlid = wc->slid;
-	ah_attr.port_num = mad_agent->port_num;
-	ah_attr.src_path_bits = wc->dlid_path_bits;
-	ah_attr.sl = wc->sl;
-	ah_attr.static_rate = 0;
-	ah_attr.ah_flags = 0; /* No GRH */
-	if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
-		if (wc->wc_flags & IB_WC_GRH) {
-			ah_attr.ah_flags = IB_AH_GRH;
-			/* Should sgid be looked up ? */
-			ah_attr.grh.sgid_index = 0;
-			ah_attr.grh.hop_limit = grh->hop_limit;
-			ah_attr.grh.flow_label = be32_to_cpu(
-				grh->version_tclass_flow)  & 0xfffff;
-			ah_attr.grh.traffic_class = (be32_to_cpu(
-				grh->version_tclass_flow) >> 20) & 0xff;
-			memcpy(ah_attr.grh.dgid.raw,
-			       grh->sgid.raw,
-			       sizeof(ah_attr.grh.dgid));
-		}
-	}
-
-	agent_send_wr->ah = ib_create_ah(mad_agent->qp->pd, &ah_attr);
-	if (IS_ERR(agent_send_wr->ah)) {
-		printk(KERN_ERR SPFX "No memory for address handle\n");
-		kfree(agent_send_wr);
-		goto out;
-	}
-
-	send_wr.wr.ud.ah = agent_send_wr->ah;
-	if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {
-		send_wr.wr.ud.pkey_index = wc->pkey_index;
-		send_wr.wr.ud.remote_qkey = IB_QP1_QKEY;
-	} else { 	/* for SMPs */
-		send_wr.wr.ud.pkey_index = 0;
-		send_wr.wr.ud.remote_qkey = 0;
-	}
-	send_wr.wr.ud.mad_hdr = &mad_priv->mad.mad.mad_hdr;
-	send_wr.wr_id = (unsigned long)agent_send_wr;
-
-	pci_unmap_addr_set(agent_send_wr, mapping, gather_list.addr);
-
-	/* Send */
-	spin_lock_irqsave(&port_priv->send_list_lock, flags);
-	if (ib_post_send_mad(mad_agent, &send_wr, &bad_send_wr)) {
-		spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-		dma_unmap_single(mad_agent->device->dma_device,
-				 pci_unmap_addr(agent_send_wr, mapping),
-				 sizeof(mad_priv->mad),
-				 DMA_TO_DEVICE);
-		ib_destroy_ah(agent_send_wr->ah);
-		kfree(agent_send_wr);
-	} else {
-		list_add_tail(&agent_send_wr->send_list,
-			      &port_priv->send_posted_list);
-		spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-		ret = 0;
-	}
-
-out:
-	return ret;
-}
-
-int agent_send(struct ib_mad_private *mad,
-	       struct ib_grh *grh,
-	       struct ib_wc *wc,
-	       struct ib_device *device,
-	       int port_num)
+int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
+			struct ib_wc *wc, struct ib_device *device,
+			int port_num, int qpn)
 {
 	struct ib_agent_port_private *port_priv;
-	struct ib_mad_agent *mad_agent;
+	struct ib_mad_agent *agent;
+	struct ib_mad_send_buf *send_buf;
+	struct ib_ah *ah;
+	int ret;
 
-	port_priv = ib_get_agent_port(device, port_num, NULL);
+	port_priv = ib_get_agent_port(device, port_num);
 	if (!port_priv) {
-		printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n",
-		       device->name, port_num);
-		return 1;
+		printk(KERN_ERR SPFX "Unable to find port agent\n");
+		return -ENODEV;
 	}
 
-	/* Get mad agent based on mgmt_class in MAD */
-	switch (mad->mad.mad.mad_hdr.mgmt_class) {
-		case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-		case IB_MGMT_CLASS_SUBN_LID_ROUTED:
-			mad_agent = port_priv->smp_agent;
-			break;
-		case IB_MGMT_CLASS_PERF_MGMT:
-			mad_agent = port_priv->perf_mgmt_agent;
-			break;
-		default:
-			return 1;
+	agent = port_priv->agent[qpn];
+	ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
+	if (IS_ERR(ah)) {
+		ret = PTR_ERR(ah);
+		printk(KERN_ERR SPFX "ib_create_ah_from_wc error:%d\n", ret);
+		return ret;
 	}
 
-	return agent_mad_send(mad_agent, port_priv, mad, grh, wc);
+	send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,
+				      IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
+				      GFP_KERNEL);
+	if (IS_ERR(send_buf)) {
+		ret = PTR_ERR(send_buf);
+		printk(KERN_ERR SPFX "ib_create_send_mad error:%d\n", ret);
+		goto err1;
+	}
+
+	memcpy(send_buf->mad, mad, sizeof *mad);
+	send_buf->ah = ah;
+	if ((ret = ib_post_send_mad(send_buf, NULL))) {
+		printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
+		goto err2;
+	}
+	return 0;
+err2:
+	ib_free_send_mad(send_buf);
+err1:
+	ib_destroy_ah(ah);
+	return ret;
 }
 
 static void agent_send_handler(struct ib_mad_agent *mad_agent,
 			       struct ib_mad_send_wc *mad_send_wc)
 {
-	struct ib_agent_port_private	*port_priv;
-	struct ib_agent_send_wr		*agent_send_wr;
-	unsigned long			flags;
-
-	/* Find matching MAD agent */
-	port_priv = ib_get_agent_port(NULL, 0, mad_agent);
-	if (!port_priv) {
-		printk(KERN_ERR SPFX "agent_send_handler: no matching MAD "
-		       "agent %p\n", mad_agent);
-		return;
-	}
-
-	agent_send_wr = (struct ib_agent_send_wr *)(unsigned long)mad_send_wc->wr_id;
-	spin_lock_irqsave(&port_priv->send_list_lock, flags);
-	/* Remove completed send from posted send MAD list */
-	list_del(&agent_send_wr->send_list);
-	spin_unlock_irqrestore(&port_priv->send_list_lock, flags);
-
-	dma_unmap_single(mad_agent->device->dma_device,
-			 pci_unmap_addr(agent_send_wr, mapping),
-			 sizeof(agent_send_wr->mad->mad),
-			 DMA_TO_DEVICE);
-
-	ib_destroy_ah(agent_send_wr->ah);
-
-	/* Release allocated memory */
-	kmem_cache_free(ib_mad_cache, agent_send_wr->mad);
-	kfree(agent_send_wr);
+	ib_destroy_ah(mad_send_wc->send_buf->ah);
+	ib_free_send_mad(mad_send_wc->send_buf);
 }
 
 int ib_agent_port_open(struct ib_device *device, int port_num)
 {
-	int ret;
 	struct ib_agent_port_private *port_priv;
 	unsigned long flags;
-
-	/* First, check if port already open for SMI */
-	port_priv = ib_get_agent_port(device, port_num, NULL);
-	if (port_priv) {
-		printk(KERN_DEBUG SPFX "%s port %d already open\n",
-		       device->name, port_num);
-		return 0;
-	}
+	int ret;
 
 	/* Create new device info */
 	port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL);
@@ -294,32 +161,25 @@
 		ret = -ENOMEM;
 		goto error1;
 	}
-
 	memset(port_priv, 0, sizeof *port_priv);
-	port_priv->port_num = port_num;
-	spin_lock_init(&port_priv->send_list_lock);
-	INIT_LIST_HEAD(&port_priv->send_posted_list);
 
-	/* Obtain send only MAD agent for SM class (SMI QP) */
-	port_priv->smp_agent = ib_register_mad_agent(device, port_num,
-						     IB_QPT_SMI,
-						     NULL, 0,
+	/* Obtain send only MAD agent for SMI QP */
+	port_priv->agent[0] = ib_register_mad_agent(device, port_num,
+						    IB_QPT_SMI, NULL, 0,
 						    &agent_send_handler,
-						     NULL, NULL);
-
-	if (IS_ERR(port_priv->smp_agent)) {
-		ret = PTR_ERR(port_priv->smp_agent);
+						    NULL, NULL);
+	if (IS_ERR(port_priv->agent[0])) {
+		ret = PTR_ERR(port_priv->agent[0]);
 		goto error2;
 	}
 
-	/* Obtain send only MAD agent for PerfMgmt class (GSI QP) */
-	port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
-							   IB_QPT_GSI,
-							   NULL, 0,
-							  &agent_send_handler,
-							   NULL, NULL);
-	if (IS_ERR(port_priv->perf_mgmt_agent)) {
-		ret = PTR_ERR(port_priv->perf_mgmt_agent);
+	/* Obtain send only MAD agent for GSI QP */
+	port_priv->agent[1] = ib_register_mad_agent(device, port_num,
+						    IB_QPT_GSI, NULL, 0,
+						    &agent_send_handler,
+						    NULL, NULL);
+	if (IS_ERR(port_priv->agent[1])) {
+		ret = PTR_ERR(port_priv->agent[1]);
 		goto error3;
 	}
 
@@ -330,7 +190,7 @@
 	return 0;
 
 error3:
-	ib_unregister_mad_agent(port_priv->smp_agent);
+	ib_unregister_mad_agent(port_priv->agent[0]);
 error2:
 	kfree(port_priv);
 error1:
@@ -343,7 +203,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&ib_agent_port_list_lock, flags);
-	port_priv = __ib_get_agent_port(device, port_num, NULL);
+	port_priv = __ib_get_agent_port(device, port_num);
 	if (port_priv == NULL) {
 		spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 		printk(KERN_ERR SPFX "Port %d not found\n", port_num);
@@ -352,9 +212,8 @@
 	list_del(&port_priv->port_list);
 	spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 
-	ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
-	ib_unregister_mad_agent(port_priv->smp_agent);
+	ib_unregister_mad_agent(port_priv->agent[1]);
+	ib_unregister_mad_agent(port_priv->agent[0]);
 	kfree(port_priv);
-
 	return 0;
 }
diff --git a/drivers/infiniband/core/agent.h b/drivers/infiniband/core/agent.h
index d942684..86d72fa 100644
--- a/drivers/infiniband/core/agent.h
+++ b/drivers/infiniband/core/agent.h
@@ -39,17 +39,15 @@
 #ifndef __AGENT_H_
 #define __AGENT_H_
 
-extern spinlock_t ib_agent_port_list_lock;
+#include <linux/err.h>
+#include <rdma/ib_mad.h>
 
-extern int ib_agent_port_open(struct ib_device *device,
-			      int port_num);
+extern int ib_agent_port_open(struct ib_device *device, int port_num);
 
 extern int ib_agent_port_close(struct ib_device *device, int port_num);
 
-extern int agent_send(struct ib_mad_private *mad,
-		      struct ib_grh *grh,
-		      struct ib_wc *wc,
-		      struct ib_device *device,
-		      int port_num);
+extern int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
+			       struct ib_wc *wc, struct ib_device *device,
+			       int port_num, int qpn);
 
 #endif	/* __AGENT_H_ */
diff --git a/drivers/infiniband/core/agent_priv.h b/drivers/infiniband/core/agent_priv.h
deleted file mode 100644
index 2ec6d7f..0000000
--- a/drivers/infiniband/core/agent_priv.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Mellanox Technologies Ltd.  All rights reserved.
- * Copyright (c) 2004, 2005 Infinicon Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Topspin Corporation.  All rights reserved.
- * Copyright (c) 2004, 2005 Voltaire Corporation.  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.
- *
- * $Id: agent_priv.h 1640 2005-01-24 22:39:02Z halr $
- */
-
-#ifndef __IB_AGENT_PRIV_H__
-#define __IB_AGENT_PRIV_H__
-
-#include <linux/pci.h>
-
-#define SPFX "ib_agent: "
-
-struct ib_agent_send_wr {
-	struct list_head send_list;
-	struct ib_ah *ah;
-	struct ib_mad_private *mad;
-	DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
-struct ib_agent_port_private {
-	struct list_head port_list;
-	struct list_head send_posted_list;
-	spinlock_t send_list_lock;
-	int port_num;
-	struct ib_mad_agent *smp_agent;	      /* SM class */
-	struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
-};
-
-#endif	/* __IB_AGENT_PRIV_H__ */
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index f014e63..c57a387 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/sched.h>	/* INIT_WORK, schedule_work(), flush_scheduled_work() */
 
 #include <rdma/ib_cache.h>
 
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 54db6d4..580c3a2 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -135,6 +135,7 @@
 	__be64 tid;
 	__be32 local_qpn;
 	__be32 remote_qpn;
+	enum ib_qp_type qp_type;
 	__be32 sq_psn;
 	__be32 rq_psn;
 	int timeout_ms;
@@ -175,8 +176,7 @@
 
 	m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, 
 			       cm_id_priv->av.pkey_index,
-			       ah, 0, sizeof(struct ib_mad_hdr),
-			       sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
+			       0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
 			       GFP_ATOMIC);
 	if (IS_ERR(m)) {
 		ib_destroy_ah(ah);
@@ -184,7 +184,8 @@
 	}
 
 	/* Timeout set by caller if response is expected. */
-	m->send_wr.wr.ud.retries = cm_id_priv->max_cm_retries;
+	m->ah = ah;
+	m->retries = cm_id_priv->max_cm_retries;
 
 	atomic_inc(&cm_id_priv->refcount);
 	m->context[0] = cm_id_priv;
@@ -205,20 +206,20 @@
 		return PTR_ERR(ah);
 
 	m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
-			       ah, 0, sizeof(struct ib_mad_hdr),
-			       sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
+			       0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
 			       GFP_ATOMIC);
 	if (IS_ERR(m)) {
 		ib_destroy_ah(ah);
 		return PTR_ERR(m);
 	}
+	m->ah = ah;
 	*msg = m;
 	return 0;
 }
 
 static void cm_free_msg(struct ib_mad_send_buf *msg)
 {
-	ib_destroy_ah(msg->send_wr.wr.ud.ah);
+	ib_destroy_ah(msg->ah);
 	if (msg->context[0])
 		cm_deref_id(msg->context[0]);
 	ib_free_send_mad(msg);
@@ -366,9 +367,15 @@
 		cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
 					  service_node);
 		if ((cur_cm_id_priv->id.service_mask & service_id) ==
-		    (service_mask & cur_cm_id_priv->id.service_id))
-			return cm_id_priv;
-		if (service_id < cur_cm_id_priv->id.service_id)
+		    (service_mask & cur_cm_id_priv->id.service_id) &&
+		    (cm_id_priv->id.device == cur_cm_id_priv->id.device))
+			return cur_cm_id_priv;
+
+		if (cm_id_priv->id.device < cur_cm_id_priv->id.device)
+			link = &(*link)->rb_left;
+		else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)
+			link = &(*link)->rb_right;
+		else if (service_id < cur_cm_id_priv->id.service_id)
 			link = &(*link)->rb_left;
 		else
 			link = &(*link)->rb_right;
@@ -378,7 +385,8 @@
 	return NULL;
 }
 
-static struct cm_id_private * cm_find_listen(__be64 service_id)
+static struct cm_id_private * cm_find_listen(struct ib_device *device,
+					     __be64 service_id)
 {
 	struct rb_node *node = cm.listen_service_table.rb_node;
 	struct cm_id_private *cm_id_priv;
@@ -386,9 +394,15 @@
 	while (node) {
 		cm_id_priv = rb_entry(node, struct cm_id_private, service_node);
 		if ((cm_id_priv->id.service_mask & service_id) ==
-		    (cm_id_priv->id.service_mask & cm_id_priv->id.service_id))
+		     cm_id_priv->id.service_id &&
+		    (cm_id_priv->id.device == device))
 			return cm_id_priv;
-		if (service_id < cm_id_priv->id.service_id)
+
+		if (device < cm_id_priv->id.device)
+			node = node->rb_left;
+		else if (device > cm_id_priv->id.device)
+			node = node->rb_right;
+		else if (service_id < cm_id_priv->id.service_id)
 			node = node->rb_left;
 		else
 			node = node->rb_right;
@@ -523,7 +537,8 @@
 	ib_send_cm_sidr_rep(&cm_id_priv->id, &param);
 }
 
-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
+				 ib_cm_handler cm_handler,
 				 void *context)
 {
 	struct cm_id_private *cm_id_priv;
@@ -535,6 +550,7 @@
 
 	memset(cm_id_priv, 0, sizeof *cm_id_priv);
 	cm_id_priv->id.state = IB_CM_IDLE;
+	cm_id_priv->id.device = device;
 	cm_id_priv->id.cm_handler = cm_handler;
 	cm_id_priv->id.context = context;
 	cm_id_priv->id.remote_cm_qpn = 1;
@@ -662,8 +678,7 @@
 		break;
 	case IB_CM_SIDR_REQ_SENT:
 		cm_id->state = IB_CM_IDLE;
-		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-			      (unsigned long) cm_id_priv->msg);
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		break;
 	case IB_CM_SIDR_REQ_RCVD:
@@ -674,8 +689,7 @@
 	case IB_CM_MRA_REQ_RCVD:
 	case IB_CM_REP_SENT:
 	case IB_CM_MRA_REP_RCVD:
-		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-			      (unsigned long) cm_id_priv->msg);
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		/* Fall through */
 	case IB_CM_REQ_RCVD:
 	case IB_CM_MRA_REQ_SENT:
@@ -692,8 +706,7 @@
 		ib_send_cm_dreq(cm_id, NULL, 0);
 		goto retest;
 	case IB_CM_DREQ_SENT:
-		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-			      (unsigned long) cm_id_priv->msg);
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		cm_enter_timewait(cm_id_priv);
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		break;
@@ -867,7 +880,6 @@
 		   struct ib_cm_req_param *param)
 {
 	struct cm_id_private *cm_id_priv;
-	struct ib_send_wr *bad_send_wr;
 	struct cm_req_msg *req_msg;
 	unsigned long flags;
 	int ret;
@@ -911,6 +923,7 @@
 	cm_id_priv->responder_resources = param->responder_resources;
 	cm_id_priv->retry_count = param->retry_count;
 	cm_id_priv->path_mtu = param->primary_path->mtu;
+	cm_id_priv->qp_type = param->qp_type;
 
 	ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
 	if (ret)
@@ -919,7 +932,7 @@
 	req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;
 	cm_format_req(req_msg, cm_id_priv, param);
 	cm_id_priv->tid = req_msg->hdr.tid;
-	cm_id_priv->msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+	cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;
 	cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;
 
 	cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
@@ -928,8 +941,7 @@
 				cm_req_get_primary_local_ack_timeout(req_msg);
 
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				&cm_id_priv->msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(cm_id_priv->msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		goto error2;
@@ -952,7 +964,6 @@
 			void *ari, u8 ari_length)
 {
 	struct ib_mad_send_buf *msg = NULL;
-	struct ib_send_wr *bad_send_wr;
 	struct cm_rej_msg *rej_msg, *rcv_msg;
 	int ret;
 
@@ -975,7 +986,7 @@
 		memcpy(rej_msg->ari, ari, ari_length);
 	}
 
-	ret = ib_post_send_mad(port->mad_agent, &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		cm_free_msg(msg);
 
@@ -1047,7 +1058,6 @@
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 	param = &work->cm_event.param.req_rcvd;
 	param->listen_id = listen_id;
-	param->device = cm_id_priv->av.port->mad_agent->device;
 	param->port = cm_id_priv->av.port->port_num;
 	param->primary_path = &work->path[0];
 	if (req_msg->alt_local_lid)
@@ -1156,7 +1166,6 @@
 			       struct cm_id_private *cm_id_priv)
 {
 	struct ib_mad_send_buf *msg = NULL;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -1185,8 +1194,7 @@
 	}
 	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
-			       &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		goto free;
 	return;
@@ -1226,7 +1234,8 @@
 	}
 
 	/* Find matching listen request. */
-	listen_cm_id_priv = cm_find_listen(req_msg->service_id);
+	listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,
+					   req_msg->service_id);
 	if (!listen_cm_id_priv) {
 		spin_unlock_irqrestore(&cm.lock, flags);
 		cm_issue_rej(work->port, work->mad_recv_wc,
@@ -1254,7 +1263,7 @@
 
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
-	cm_id = ib_create_cm_id(NULL, NULL);
+	cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
 	if (IS_ERR(cm_id))
 		return PTR_ERR(cm_id);
 
@@ -1305,6 +1314,7 @@
 				cm_req_get_primary_local_ack_timeout(req_msg);
 	cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
 	cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
+	cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
 
 	cm_format_req_event(work, cm_id_priv, &listen_cm_id_priv->id);
 	cm_process_work(cm_id_priv, work);
@@ -1349,7 +1359,6 @@
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
 	struct cm_rep_msg *rep_msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -1371,11 +1380,10 @@
 
 	rep_msg = (struct cm_rep_msg *) msg->mad;
 	cm_format_rep(rep_msg, cm_id_priv, param);
-	msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+	msg->timeout_ms = cm_id_priv->timeout_ms;
 	msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		cm_free_msg(msg);
@@ -1413,7 +1421,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	void *data;
 	int ret;
@@ -1440,8 +1447,7 @@
 	cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
 		      private_data, private_data_len);
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		cm_free_msg(msg);
@@ -1486,7 +1492,6 @@
 	struct cm_id_private *cm_id_priv;
 	struct cm_rep_msg *rep_msg;
 	struct ib_mad_send_buf *msg = NULL;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -1514,8 +1519,7 @@
 		goto unlock;
 	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
-			       &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		goto free;
 	goto deref;
@@ -1583,8 +1587,7 @@
 
 	/* todo: handle peer_to_peer */
 
-	ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-		      (unsigned long) cm_id_priv->msg);
+	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1618,8 +1621,7 @@
 		goto out;
 	}
 
-	ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-		      (unsigned long) cm_id_priv->msg);
+	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1658,8 +1660,7 @@
 	}
 	cm_id_priv->id.state = IB_CM_ESTABLISHED;
 
-	ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-		      (unsigned long) cm_id_priv->msg);
+	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1696,7 +1697,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -1718,11 +1718,10 @@
 
 	cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
 		       private_data, private_data_len);
-	msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+	msg->timeout_ms = cm_id_priv->timeout_ms;
 	msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		cm_enter_timewait(cm_id_priv);
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@@ -1756,7 +1755,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	void *data;
 	int ret;
@@ -1786,8 +1784,7 @@
 	cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
 		       private_data, private_data_len);
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,
-			       &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		cm_free_msg(msg);
@@ -1804,7 +1801,6 @@
 	struct cm_id_private *cm_id_priv;
 	struct cm_dreq_msg *dreq_msg;
 	struct ib_mad_send_buf *msg = NULL;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -1823,8 +1819,7 @@
 	switch (cm_id_priv->id.state) {
 	case IB_CM_REP_SENT:
 	case IB_CM_DREQ_SENT:
-		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-			      (unsigned long) cm_id_priv->msg);
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		break;
 	case IB_CM_ESTABLISHED:
 	case IB_CM_MRA_REP_RCVD:
@@ -1838,8 +1833,7 @@
 			       cm_id_priv->private_data_len);
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-		if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				     &msg->send_wr, &bad_send_wr))
+		if (ib_post_send_mad(msg, NULL))
 			cm_free_msg(msg);
 		goto deref;
 	default:
@@ -1886,8 +1880,7 @@
 	}
 	cm_enter_timewait(cm_id_priv);
 
-	ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-		      (unsigned long) cm_id_priv->msg);
+	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
 	if (!ret)
 		list_add_tail(&work->list, &cm_id_priv->work_list);
@@ -1912,7 +1905,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -1956,8 +1948,7 @@
 	if (ret)
 		goto out;
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		cm_free_msg(msg);
 
@@ -2033,8 +2024,7 @@
 	case IB_CM_MRA_REQ_RCVD:
 	case IB_CM_REP_SENT:
 	case IB_CM_MRA_REP_RCVD:
-		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-			      (unsigned long) cm_id_priv->msg);
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		/* fall through */
 	case IB_CM_REQ_RCVD:
 	case IB_CM_MRA_REQ_SENT:
@@ -2044,8 +2034,7 @@
 			cm_reset_to_idle(cm_id_priv);
 		break;
 	case IB_CM_DREQ_SENT:
-		ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-			      (unsigned long) cm_id_priv->msg);
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		/* fall through */
 	case IB_CM_REP_RCVD:
 	case IB_CM_MRA_REP_SENT:
@@ -2080,7 +2069,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	void *data;
 	unsigned long flags;
 	int ret;
@@ -2104,8 +2092,7 @@
 		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
 			      CM_MSG_RESPONSE_REQ, service_timeout,
 			      private_data, private_data_len);
-		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				       &msg->send_wr, &bad_send_wr);
+		ret = ib_post_send_mad(msg, NULL);
 		if (ret)
 			goto error2;
 		cm_id->state = IB_CM_MRA_REQ_SENT;
@@ -2118,8 +2105,7 @@
 		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
 			      CM_MSG_RESPONSE_REP, service_timeout,
 			      private_data, private_data_len);
-		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				       &msg->send_wr, &bad_send_wr);
+		ret = ib_post_send_mad(msg, NULL);
 		if (ret)
 			goto error2;
 		cm_id->state = IB_CM_MRA_REP_SENT;
@@ -2132,8 +2118,7 @@
 		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
 			      CM_MSG_RESPONSE_OTHER, service_timeout,
 			      private_data, private_data_len);
-		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				       &msg->send_wr, &bad_send_wr);
+		ret = ib_post_send_mad(msg, NULL);
 		if (ret)
 			goto error2;
 		cm_id->lap_state = IB_CM_MRA_LAP_SENT;
@@ -2195,14 +2180,14 @@
 	case IB_CM_REQ_SENT:
 		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
 		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
-				  (unsigned long) cm_id_priv->msg, timeout))
+				  cm_id_priv->msg, timeout))
 			goto out;
 		cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;
 		break;
 	case IB_CM_REP_SENT:
 		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||
 		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
-				  (unsigned long) cm_id_priv->msg, timeout))
+				  cm_id_priv->msg, timeout))
 			goto out;
 		cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;
 		break;
@@ -2210,7 +2195,7 @@
 		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,
-				  (unsigned long) cm_id_priv->msg, timeout))
+				  cm_id_priv->msg, timeout))
 			goto out;
 		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
 		break;
@@ -2273,7 +2258,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -2294,11 +2278,10 @@
 
 	cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv,
 		      alternate_path, private_data, private_data_len);
-	msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+	msg->timeout_ms = cm_id_priv->timeout_ms;
 	msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED;
 
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		cm_free_msg(msg);
@@ -2342,7 +2325,6 @@
 	struct cm_lap_msg *lap_msg;
 	struct ib_cm_lap_event_param *param;
 	struct ib_mad_send_buf *msg = NULL;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -2376,8 +2358,7 @@
 			      cm_id_priv->private_data_len);
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
-		if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				     &msg->send_wr, &bad_send_wr))
+		if (ib_post_send_mad(msg, NULL))
 			cm_free_msg(msg);
 		goto deref;
 	default:
@@ -2433,7 +2414,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -2456,8 +2436,7 @@
 
 	cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status,
 		      info, info_length, private_data, private_data_len);
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		cm_free_msg(msg);
@@ -2496,8 +2475,7 @@
 		goto out;
 	}
 	cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
-	ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-		      (unsigned long) cm_id_priv->msg);
+	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 	cm_id_priv->msg = NULL;
 
 	ret = atomic_inc_and_test(&cm_id_priv->work_count);
@@ -2572,7 +2550,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -2595,13 +2572,12 @@
 
 	cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv,
 			   param);
-	msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;
+	msg->timeout_ms = cm_id_priv->timeout_ms;
 	msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT;
 
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
 	if (cm_id->state == IB_CM_IDLE)
-		ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-				       &msg->send_wr, &bad_send_wr);
+		ret = ib_post_send_mad(msg, NULL);
 	else
 		ret = -EINVAL;
 
@@ -2629,7 +2605,6 @@
 	param = &work->cm_event.param.sidr_req_rcvd;
 	param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
 	param->listen_id = listen_id;
-	param->device = work->port->mad_agent->device;
 	param->port = work->port->port_num;
 	work->cm_event.private_data = &sidr_req_msg->private_data;
 }
@@ -2642,7 +2617,7 @@
 	struct ib_wc *wc;
 	unsigned long flags;
 
-	cm_id = ib_create_cm_id(NULL, NULL);
+	cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
 	if (IS_ERR(cm_id))
 		return PTR_ERR(cm_id);
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -2666,7 +2641,8 @@
 		spin_unlock_irqrestore(&cm.lock, flags);
 		goto out; /* Duplicate message. */
 	}
-	cur_cm_id_priv = cm_find_listen(sidr_req_msg->service_id);
+	cur_cm_id_priv = cm_find_listen(cm_id->device,
+					sidr_req_msg->service_id);
 	if (!cur_cm_id_priv) {
 		rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
 		spin_unlock_irqrestore(&cm.lock, flags);
@@ -2715,7 +2691,6 @@
 {
 	struct cm_id_private *cm_id_priv;
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
 	unsigned long flags;
 	int ret;
 
@@ -2737,8 +2712,7 @@
 
 	cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,
 			   param);
-	ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,
-			       &msg->send_wr, &bad_send_wr);
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		cm_free_msg(msg);
@@ -2791,8 +2765,7 @@
 		goto out;
 	}
 	cm_id_priv->id.state = IB_CM_IDLE;
-	ib_cancel_mad(cm_id_priv->av.port->mad_agent,
-		      (unsigned long) cm_id_priv->msg);
+	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
 	cm_format_sidr_rep_event(work);
@@ -2860,9 +2833,7 @@
 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;
-
-	msg = (struct ib_mad_send_buf *)(unsigned long)mad_send_wc->wr_id;
+	struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
 
 	switch (mad_send_wc->status) {
 	case IB_WC_SUCCESS:
@@ -3064,10 +3035,10 @@
 	case IB_CM_ESTABLISHED:
 		*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |
 				IB_QP_PKEY_INDEX | IB_QP_PORT;
-		qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+		qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
+					   IB_ACCESS_REMOTE_WRITE;
 		if (cm_id_priv->responder_resources)
-			qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_WRITE |
-						    IB_ACCESS_REMOTE_READ;
+			qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ;
 		qp_attr->pkey_index = cm_id_priv->av.pkey_index;
 		qp_attr->port_num = cm_id_priv->av.port->port_num;
 		ret = 0;
@@ -3097,14 +3068,18 @@
 	case IB_CM_MRA_REP_RCVD:
 	case IB_CM_ESTABLISHED:
 		*qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |
-				IB_QP_DEST_QPN | IB_QP_RQ_PSN |
-				IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER;
+				IB_QP_DEST_QPN | IB_QP_RQ_PSN;
 		qp_attr->ah_attr = cm_id_priv->av.ah_attr;
 		qp_attr->path_mtu = cm_id_priv->path_mtu;
 		qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
 		qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
-		qp_attr->max_dest_rd_atomic = cm_id_priv->responder_resources;
-		qp_attr->min_rnr_timer = 0;
+		if (cm_id_priv->qp_type == IB_QPT_RC) {
+			*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
+					 IB_QP_MIN_RNR_TIMER;
+			qp_attr->max_dest_rd_atomic =
+					cm_id_priv->responder_resources;
+			qp_attr->min_rnr_timer = 0;
+		}
 		if (cm_id_priv->alt_av.ah_attr.dlid) {
 			*qp_attr_mask |= IB_QP_ALT_PATH;
 			qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
@@ -3133,14 +3108,17 @@
 	case IB_CM_REP_SENT:
 	case IB_CM_MRA_REP_RCVD:
 	case IB_CM_ESTABLISHED:
-		*qp_attr_mask = IB_QP_STATE | IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
-				IB_QP_RNR_RETRY | IB_QP_SQ_PSN |
-				IB_QP_MAX_QP_RD_ATOMIC;
-		qp_attr->timeout = cm_id_priv->local_ack_timeout;
-		qp_attr->retry_cnt = cm_id_priv->retry_count;
-		qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+		*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
 		qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
-		qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+		if (cm_id_priv->qp_type == IB_QPT_RC) {
+			*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
+					 IB_QP_RNR_RETRY |
+					 IB_QP_MAX_QP_RD_ATOMIC;
+			qp_attr->timeout = cm_id_priv->local_ack_timeout;
+			qp_attr->retry_cnt = cm_id_priv->retry_count;
+			qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
+			qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+		}
 		if (cm_id_priv->alt_av.ah_attr.dlid) {
 			*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
 			qp_attr->path_mig_state = IB_MIG_REARM;
@@ -3323,6 +3301,7 @@
 	flush_workqueue(cm.wq);
 	destroy_workqueue(cm.wq);
 	ib_unregister_client(&cm_client);
+	idr_destroy(&cm.local_id_table);
 }
 
 module_init(ib_cm_init);
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 813ab70..4d3aee9 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -186,6 +186,7 @@
 		req_msg->offset40 = cpu_to_be32((be32_to_cpu(
 						  req_msg->offset40) &
 						   0xFFFFFFF9) | 0x2);
+		break;
 	default:
 		req_msg->offset40 = cpu_to_be32(be32_to_cpu(
 						 req_msg->offset40) &
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index d3cf84e..5a6e449 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -514,6 +514,12 @@
 		  u8 port_num,
 		  struct ib_port_attr *port_attr)
 {
+	if (device->node_type == IB_NODE_SWITCH) {
+		if (port_num)
+			return -EINVAL;
+	} else if (port_num < 1 || port_num > device->phys_port_cnt)
+		return -EINVAL;
+
 	return device->query_port(device, port_num, port_attr);
 }
 EXPORT_SYMBOL(ib_query_port);
@@ -583,6 +589,12 @@
 		   u8 port_num, int port_modify_mask,
 		   struct ib_port_modify *port_modify)
 {
+	if (device->node_type == IB_NODE_SWITCH) {
+		if (port_num)
+			return -EINVAL;
+	} else if (port_num < 1 || port_num > device->phys_port_cnt)
+		return -EINVAL;
+
 	return device->modify_port(device, port_num, port_modify_mask,
 				   port_modify);
 }
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index a14ca87..88f9f8c 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -579,7 +579,7 @@
 }
 
 static void snoop_send(struct ib_mad_qp_info *qp_info,
-		       struct ib_send_wr *send_wr,
+		       struct ib_mad_send_buf *send_buf,
 		       struct ib_mad_send_wc *mad_send_wc,
 		       int mad_snoop_flags)
 {
@@ -597,7 +597,7 @@
 		atomic_inc(&mad_snoop_priv->refcount);
 		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 		mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,
-						    send_wr, mad_send_wc);
+						    send_buf, mad_send_wc);
 		if (atomic_dec_and_test(&mad_snoop_priv->refcount))
 			wake_up(&mad_snoop_priv->wait);
 		spin_lock_irqsave(&qp_info->snoop_lock, flags);
@@ -654,10 +654,10 @@
  * Return < 0 if error
  */
 static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
-				  struct ib_smp *smp,
-				  struct ib_send_wr *send_wr)
+				  struct ib_mad_send_wr_private *mad_send_wr)
 {
 	int ret;
+	struct ib_smp *smp = mad_send_wr->send_buf.mad;
 	unsigned long flags;
 	struct ib_mad_local_private *local;
 	struct ib_mad_private *mad_priv;
@@ -666,6 +666,7 @@
 	struct ib_device *device = mad_agent_priv->agent.device;
 	u8 port_num = mad_agent_priv->agent.port_num;
 	struct ib_wc mad_wc;
+	struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
 
 	if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {
 		ret = -EINVAL;
@@ -745,13 +746,7 @@
 		goto out;
 	}
 
-	local->send_wr = *send_wr;
-	local->send_wr.sg_list = local->sg_list;
-	memcpy(local->sg_list, send_wr->sg_list,
-	       sizeof *send_wr->sg_list * send_wr->num_sge);
-	local->send_wr.next = NULL;
-	local->tid = send_wr->wr.ud.mad_hdr->tid;
-	local->wr_id = send_wr->wr_id;
+	local->mad_send_wr = mad_send_wr;
 	/* Reference MAD agent until send side of local completion handled */
 	atomic_inc(&mad_agent_priv->refcount);
 	/* Queue local completion to local list */
@@ -781,17 +776,17 @@
 
 struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
 					    u32 remote_qpn, u16 pkey_index,
-					    struct ib_ah *ah, int rmpp_active,
+					    int rmpp_active,
 					    int hdr_len, int data_len,
 					    gfp_t gfp_mask)
 {
 	struct ib_mad_agent_private *mad_agent_priv;
-	struct ib_mad_send_buf *send_buf;
+	struct ib_mad_send_wr_private *mad_send_wr;
 	int buf_size;
 	void *buf;
 
-	mad_agent_priv = container_of(mad_agent,
-				      struct ib_mad_agent_private, agent);
+	mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
+				      agent);
 	buf_size = get_buf_length(hdr_len, data_len);
 
 	if ((!mad_agent->rmpp_version &&
@@ -799,45 +794,40 @@
 	    (!rmpp_active && buf_size > sizeof(struct ib_mad)))
 		return ERR_PTR(-EINVAL);
 
-	buf = kmalloc(sizeof *send_buf + buf_size, gfp_mask);
+	buf = kmalloc(sizeof *mad_send_wr + buf_size, gfp_mask);
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
-	memset(buf, 0, sizeof *send_buf + buf_size);
+	memset(buf, 0, sizeof *mad_send_wr + buf_size);
 
-	send_buf = buf + buf_size;
-	send_buf->mad = buf;
+	mad_send_wr = buf + buf_size;
+	mad_send_wr->send_buf.mad = buf;
 
-	send_buf->sge.addr = dma_map_single(mad_agent->device->dma_device,
-					    buf, buf_size, DMA_TO_DEVICE);
-	pci_unmap_addr_set(send_buf, mapping, send_buf->sge.addr);
-	send_buf->sge.length = buf_size;
-	send_buf->sge.lkey = mad_agent->mr->lkey;
+	mad_send_wr->mad_agent_priv = mad_agent_priv;
+	mad_send_wr->sg_list[0].length = buf_size;
+	mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey;
 
-	send_buf->send_wr.wr_id = (unsigned long) send_buf;
-	send_buf->send_wr.sg_list = &send_buf->sge;
-	send_buf->send_wr.num_sge = 1;
-	send_buf->send_wr.opcode = IB_WR_SEND;
-	send_buf->send_wr.send_flags = IB_SEND_SIGNALED;
-	send_buf->send_wr.wr.ud.ah = ah;
-	send_buf->send_wr.wr.ud.mad_hdr = &send_buf->mad->mad_hdr;
-	send_buf->send_wr.wr.ud.remote_qpn = remote_qpn;
-	send_buf->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
-	send_buf->send_wr.wr.ud.pkey_index = pkey_index;
+	mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;
+	mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
+	mad_send_wr->send_wr.num_sge = 1;
+	mad_send_wr->send_wr.opcode = IB_WR_SEND;
+	mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;
+	mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;
+	mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
+	mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;
 
 	if (rmpp_active) {
-		struct ib_rmpp_mad *rmpp_mad;
-		rmpp_mad = (struct ib_rmpp_mad *)send_buf->mad;
+		struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad;
 		rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len -
-			offsetof(struct ib_rmpp_mad, data) + data_len);
+						   IB_MGMT_RMPP_HDR + data_len);
 		rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version;
 		rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;
 		ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr,
 				  IB_MGMT_RMPP_FLAG_ACTIVE);
 	}
 
-	send_buf->mad_agent = mad_agent;
+	mad_send_wr->send_buf.mad_agent = mad_agent;
 	atomic_inc(&mad_agent_priv->refcount);
-	return send_buf;
+	return &mad_send_wr->send_buf;
 }
 EXPORT_SYMBOL(ib_create_send_mad);
 
@@ -847,10 +837,6 @@
 
 	mad_agent_priv = container_of(send_buf->mad_agent,
 				      struct ib_mad_agent_private, agent);
-
-	dma_unmap_single(send_buf->mad_agent->device->dma_device,
-			 pci_unmap_addr(send_buf, mapping),
-			 send_buf->sge.length, DMA_TO_DEVICE);
 	kfree(send_buf->mad);
 
 	if (atomic_dec_and_test(&mad_agent_priv->refcount))
@@ -861,8 +847,10 @@
 int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
 {
 	struct ib_mad_qp_info *qp_info;
-	struct ib_send_wr *bad_send_wr;
 	struct list_head *list;
+	struct ib_send_wr *bad_send_wr;
+	struct ib_mad_agent *mad_agent;
+	struct ib_sge *sge;
 	unsigned long flags;
 	int ret;
 
@@ -871,10 +859,17 @@
 	mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;
 	mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;
 
+	mad_agent = mad_send_wr->send_buf.mad_agent;
+	sge = mad_send_wr->sg_list;
+	sge->addr = dma_map_single(mad_agent->device->dma_device,
+				   mad_send_wr->send_buf.mad, sge->length,
+				   DMA_TO_DEVICE);
+	pci_unmap_addr_set(mad_send_wr, mapping, sge->addr);
+
 	spin_lock_irqsave(&qp_info->send_queue.lock, flags);
 	if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
-		ret = ib_post_send(mad_send_wr->mad_agent_priv->agent.qp,
-				   &mad_send_wr->send_wr, &bad_send_wr);
+		ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
+				   &bad_send_wr);
 		list = &qp_info->send_queue.list;
 	} else {
 		ret = 0;
@@ -886,6 +881,11 @@
 		list_add_tail(&mad_send_wr->mad_list.list, list);
 	}
 	spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);
+	if (ret)
+		dma_unmap_single(mad_agent->device->dma_device,
+				 pci_unmap_addr(mad_send_wr, mapping),
+				 sge->length, DMA_TO_DEVICE);
+
 	return ret;
 }
 
@@ -893,45 +893,28 @@
  * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
  *  with the registered client
  */
-int ib_post_send_mad(struct ib_mad_agent *mad_agent,
-		     struct ib_send_wr *send_wr,
-		     struct ib_send_wr **bad_send_wr)
+int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
+		     struct ib_mad_send_buf **bad_send_buf)
 {
-	int ret = -EINVAL;
 	struct ib_mad_agent_private *mad_agent_priv;
-
-	/* Validate supplied parameters */
-	if (!bad_send_wr)
-		goto error1;
-
-	if (!mad_agent || !send_wr)
-		goto error2;
-
-	if (!mad_agent->send_handler)
-		goto error2;
-
-	mad_agent_priv = container_of(mad_agent,
-				      struct ib_mad_agent_private,
-				      agent);
+	struct ib_mad_send_buf *next_send_buf;
+	struct ib_mad_send_wr_private *mad_send_wr;
+	unsigned long flags;
+	int ret = -EINVAL;
 
 	/* Walk list of send WRs and post each on send list */
-	while (send_wr) {
-		unsigned long			flags;
-		struct ib_send_wr		*next_send_wr;
-		struct ib_mad_send_wr_private	*mad_send_wr;
-		struct ib_smp			*smp;
+	for (; send_buf; send_buf = next_send_buf) {
 
-		/* Validate more parameters */
-		if (send_wr->num_sge > IB_MAD_SEND_REQ_MAX_SG)
-			goto error2;
+		mad_send_wr = container_of(send_buf,
+					   struct ib_mad_send_wr_private,
+					   send_buf);
+		mad_agent_priv = mad_send_wr->mad_agent_priv;
 
-		if (send_wr->wr.ud.timeout_ms && !mad_agent->recv_handler)
-			goto error2;
-
-		if (!send_wr->wr.ud.mad_hdr) {
-			printk(KERN_ERR PFX "MAD header must be supplied "
-			       "in WR %p\n", send_wr);
-			goto error2;
+		if (!send_buf->mad_agent->send_handler ||
+		    (send_buf->timeout_ms &&
+		     !send_buf->mad_agent->recv_handler)) {
+			ret = -EINVAL;
+			goto error;
 		}
 
 		/*
@@ -939,40 +922,24 @@
 		 * current one completes, and the user modifies the work
 		 * request associated with the completion
 		 */
-		next_send_wr = (struct ib_send_wr *)send_wr->next;
+		next_send_buf = send_buf->next;
+		mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;
 
-		smp = (struct ib_smp *)send_wr->wr.ud.mad_hdr;
-		if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
-			ret = handle_outgoing_dr_smp(mad_agent_priv, smp,
-						     send_wr);
+		if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==
+		    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+			ret = handle_outgoing_dr_smp(mad_agent_priv,
+						     mad_send_wr);
 			if (ret < 0)		/* error */
-				goto error2;
+				goto error;
 			else if (ret == 1)	/* locally consumed */
-				goto next;
+				continue;
 		}
 
-		/* Allocate MAD send WR tracking structure */
-		mad_send_wr = kmalloc(sizeof *mad_send_wr, GFP_ATOMIC);
-		if (!mad_send_wr) {
-			printk(KERN_ERR PFX "No memory for "
-			       "ib_mad_send_wr_private\n");
-			ret = -ENOMEM;
-			goto error2;
-		}
-		memset(mad_send_wr, 0, sizeof *mad_send_wr);
-
-		mad_send_wr->send_wr = *send_wr;
-		mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;
-		memcpy(mad_send_wr->sg_list, send_wr->sg_list,
-		       sizeof *send_wr->sg_list * send_wr->num_sge);
-		mad_send_wr->wr_id = send_wr->wr_id;
-		mad_send_wr->tid = send_wr->wr.ud.mad_hdr->tid;
-		mad_send_wr->mad_agent_priv = mad_agent_priv;
+		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_wr->wr.
-							ud.timeout_ms);
-		mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
-		/* One reference for each work request to QP + response */
+		mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
+		mad_send_wr->retries = send_buf->retries;
+		/* Reference for work request to QP + response */
 		mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
 		mad_send_wr->status = IB_WC_SUCCESS;
 
@@ -995,16 +962,13 @@
 			list_del(&mad_send_wr->agent_list);
 			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 			atomic_dec(&mad_agent_priv->refcount);
-			goto error2;
+			goto error;
 		}
-next:
-		send_wr = next_send_wr;
 	}
 	return 0;
-
-error2:
-	*bad_send_wr = send_wr;
-error1:
+error:
+	if (bad_send_buf)
+		*bad_send_buf = send_buf;
 	return ret;
 }
 EXPORT_SYMBOL(ib_post_send_mad);
@@ -1447,8 +1411,7 @@
 		 * of MAD.
 		 */
 		hi_tid = be64_to_cpu(mad->mad_hdr.tid) >> 32;
-		list_for_each_entry(entry, &port_priv->agent_list,
-				    agent_list) {
+		list_for_each_entry(entry, &port_priv->agent_list, agent_list) {
 			if (entry->agent.hi_tid == hi_tid) {
 				mad_agent = entry;
 				break;
@@ -1571,8 +1534,7 @@
 	 */
 	list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
 			    agent_list) {
-		if (is_data_mad(mad_agent_priv,
-				mad_send_wr->send_wr.wr.ud.mad_hdr) &&
+		if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
 		    mad_send_wr->tid == tid && mad_send_wr->timeout) {
 			/* Verify request has not been canceled */
 			return (mad_send_wr->status == IB_WC_SUCCESS) ?
@@ -1628,14 +1590,14 @@
 		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 
 		/* Defined behavior is to complete response before request */
-		mad_recv_wc->wc->wr_id = mad_send_wr->wr_id;
+		mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
 		mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
 						   mad_recv_wc);
 		atomic_dec(&mad_agent_priv->refcount);
 
 		mad_send_wc.status = IB_WC_SUCCESS;
 		mad_send_wc.vendor_err = 0;
-		mad_send_wc.wr_id = mad_send_wr->wr_id;
+		mad_send_wc.send_buf = &mad_send_wr->send_buf;
 		ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
 	} else {
 		mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
@@ -1728,11 +1690,11 @@
 			if (ret & IB_MAD_RESULT_CONSUMED)
 				goto out;
 			if (ret & IB_MAD_RESULT_REPLY) {
-				/* Send response */
-				if (!agent_send(response, &recv->grh, wc,
-						port_priv->device,
-						port_priv->port_num))
-					response = NULL;
+				agent_send_response(&response->mad.mad,
+						    &recv->grh, wc,
+						    port_priv->device,
+						    port_priv->port_num,
+						    qp_info->qp->qp_num);
 				goto out;
 			}
 		}
@@ -1866,15 +1828,15 @@
 
 	if (mad_send_wr->status != IB_WC_SUCCESS )
 		mad_send_wc->status = mad_send_wr->status;
-	if (ret != IB_RMPP_RESULT_INTERNAL)
+	if (ret == IB_RMPP_RESULT_INTERNAL)
+		ib_rmpp_send_handler(mad_send_wc);
+	else
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   mad_send_wc);
 
 	/* Release reference on agent taken when sending */
 	if (atomic_dec_and_test(&mad_agent_priv->refcount))
 		wake_up(&mad_agent_priv->wait);
-
-	kfree(mad_send_wr);
 	return;
 done:
 	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
@@ -1888,6 +1850,7 @@
 	struct ib_mad_qp_info		*qp_info;
 	struct ib_mad_queue		*send_queue;
 	struct ib_send_wr		*bad_send_wr;
+	struct ib_mad_send_wc		mad_send_wc;
 	unsigned long flags;
 	int ret;
 
@@ -1898,6 +1861,9 @@
 	qp_info = send_queue->qp_info;
 
 retry:
+	dma_unmap_single(mad_send_wr->send_buf.mad_agent->device->dma_device,
+			 pci_unmap_addr(mad_send_wr, mapping),
+			 mad_send_wr->sg_list[0].length, DMA_TO_DEVICE);
 	queued_send_wr = NULL;
 	spin_lock_irqsave(&send_queue->lock, flags);
 	list_del(&mad_list->list);
@@ -1914,17 +1880,17 @@
 	}
 	spin_unlock_irqrestore(&send_queue->lock, flags);
 
-	/* Restore client wr_id in WC and complete send */
-	wc->wr_id = mad_send_wr->wr_id;
+	mad_send_wc.send_buf = &mad_send_wr->send_buf;
+	mad_send_wc.status = wc->status;
+	mad_send_wc.vendor_err = wc->vendor_err;
 	if (atomic_read(&qp_info->snoop_count))
-		snoop_send(qp_info, &mad_send_wr->send_wr,
-			   (struct ib_mad_send_wc *)wc,
+		snoop_send(qp_info, &mad_send_wr->send_buf, &mad_send_wc,
 			   IB_MAD_SNOOP_SEND_COMPLETIONS);
-	ib_mad_complete_send_wr(mad_send_wr, (struct ib_mad_send_wc *)wc);
+	ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
 
 	if (queued_send_wr) {
 		ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
-				&bad_send_wr);
+				   &bad_send_wr);
 		if (ret) {
 			printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret);
 			mad_send_wr = queued_send_wr;
@@ -2066,38 +2032,37 @@
 
 	list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
 				 &cancel_list, agent_list) {
-		mad_send_wc.wr_id = mad_send_wr->wr_id;
+		mad_send_wc.send_buf = &mad_send_wr->send_buf;
+		list_del(&mad_send_wr->agent_list);
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
-
-		list_del(&mad_send_wr->agent_list);
-		kfree(mad_send_wr);
 		atomic_dec(&mad_agent_priv->refcount);
 	}
 }
 
 static struct ib_mad_send_wr_private*
-find_send_by_wr_id(struct ib_mad_agent_private *mad_agent_priv, u64 wr_id)
+find_send_wr(struct ib_mad_agent_private *mad_agent_priv,
+	     struct ib_mad_send_buf *send_buf)
 {
 	struct ib_mad_send_wr_private *mad_send_wr;
 
 	list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
 			    agent_list) {
-		if (mad_send_wr->wr_id == wr_id)
+		if (&mad_send_wr->send_buf == send_buf)
 			return mad_send_wr;
 	}
 
 	list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
 			    agent_list) {
-		if (is_data_mad(mad_agent_priv,
-				mad_send_wr->send_wr.wr.ud.mad_hdr) &&
-		    mad_send_wr->wr_id == wr_id)
+		if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
+		    &mad_send_wr->send_buf == send_buf)
 			return mad_send_wr;
 	}
 	return NULL;
 }
 
-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms)
+int ib_modify_mad(struct ib_mad_agent *mad_agent,
+		  struct ib_mad_send_buf *send_buf, u32 timeout_ms)
 {
 	struct ib_mad_agent_private *mad_agent_priv;
 	struct ib_mad_send_wr_private *mad_send_wr;
@@ -2107,7 +2072,7 @@
 	mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
 				      agent);
 	spin_lock_irqsave(&mad_agent_priv->lock, flags);
-	mad_send_wr = find_send_by_wr_id(mad_agent_priv, wr_id);
+	mad_send_wr = find_send_wr(mad_agent_priv, send_buf);
 	if (!mad_send_wr || mad_send_wr->status != IB_WC_SUCCESS) {
 		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 		return -EINVAL;
@@ -2119,7 +2084,7 @@
 		mad_send_wr->refcount -= (mad_send_wr->timeout > 0);
 	}
 
-	mad_send_wr->send_wr.wr.ud.timeout_ms = timeout_ms;
+	mad_send_wr->send_buf.timeout_ms = timeout_ms;
 	if (active)
 		mad_send_wr->timeout = msecs_to_jiffies(timeout_ms);
 	else
@@ -2130,9 +2095,10 @@
 }
 EXPORT_SYMBOL(ib_modify_mad);
 
-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id)
+void ib_cancel_mad(struct ib_mad_agent *mad_agent,
+		   struct ib_mad_send_buf *send_buf)
 {
-	ib_modify_mad(mad_agent, wr_id, 0);
+	ib_modify_mad(mad_agent, send_buf, 0);
 }
 EXPORT_SYMBOL(ib_cancel_mad);
 
@@ -2166,10 +2132,9 @@
 			 * Defined behavior is to complete response
 			 * before request
 			 */
-			build_smp_wc(local->wr_id,
+			build_smp_wc((unsigned long) local->mad_send_wr,
 				     be16_to_cpu(IB_LID_PERMISSIVE),
-				     0 /* pkey index */,
-				     recv_mad_agent->agent.port_num, &wc);
+				     0, recv_mad_agent->agent.port_num, &wc);
 
 			local->mad_priv->header.recv_wc.wc = &wc;
 			local->mad_priv->header.recv_wc.mad_len =
@@ -2196,11 +2161,11 @@
 		/* Complete send */
 		mad_send_wc.status = IB_WC_SUCCESS;
 		mad_send_wc.vendor_err = 0;
-		mad_send_wc.wr_id = local->wr_id;
+		mad_send_wc.send_buf = &local->mad_send_wr->send_buf;
 		if (atomic_read(&mad_agent_priv->qp_info->snoop_count))
-			snoop_send(mad_agent_priv->qp_info, &local->send_wr,
-				  &mad_send_wc,
-				   IB_MAD_SNOOP_SEND_COMPLETIONS);
+			snoop_send(mad_agent_priv->qp_info,
+				   &local->mad_send_wr->send_buf,
+				   &mad_send_wc, IB_MAD_SNOOP_SEND_COMPLETIONS);
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
 
@@ -2221,8 +2186,7 @@
 	if (!mad_send_wr->retries--)
 		return -ETIMEDOUT;
 
-	mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_wr.
-						wr.ud.timeout_ms);
+	mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
 
 	if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
 		ret = ib_retry_rmpp(mad_send_wr);
@@ -2285,11 +2249,10 @@
 			mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR;
 		else
 			mad_send_wc.status = mad_send_wr->status;
-		mad_send_wc.wr_id = mad_send_wr->wr_id;
+		mad_send_wc.send_buf = &mad_send_wr->send_buf;
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
 
-		kfree(mad_send_wr);
 		atomic_dec(&mad_agent_priv->refcount);
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
 	}
@@ -2683,40 +2646,47 @@
 
 static void ib_mad_init_device(struct ib_device *device)
 {
-	int num_ports, cur_port, i;
+	int start, end, i;
 
 	if (device->node_type == IB_NODE_SWITCH) {
-		num_ports = 1;
-		cur_port = 0;
+		start = 0;
+		end   = 0;
 	} else {
-		num_ports = device->phys_port_cnt;
-		cur_port = 1;
+		start = 1;
+		end   = device->phys_port_cnt;
 	}
-	for (i = 0; i < num_ports; i++, cur_port++) {
-		if (ib_mad_port_open(device, cur_port)) {
+
+	for (i = start; i <= end; i++) {
+		if (ib_mad_port_open(device, i)) {
 			printk(KERN_ERR PFX "Couldn't open %s port %d\n",
-			       device->name, cur_port);
-			goto error_device_open;
+			       device->name, i);
+			goto error;
 		}
-		if (ib_agent_port_open(device, cur_port)) {
+		if (ib_agent_port_open(device, i)) {
 			printk(KERN_ERR PFX "Couldn't open %s port %d "
 			       "for agents\n",
-			       device->name, cur_port);
-			goto error_device_open;
+			       device->name, i);
+			goto error_agent;
 		}
 	}
 	return;
 
-error_device_open:
-	while (i > 0) {
-		cur_port--;
-		if (ib_agent_port_close(device, cur_port))
+error_agent:
+	if (ib_mad_port_close(device, i))
+		printk(KERN_ERR PFX "Couldn't close %s port %d\n",
+		       device->name, i);
+
+error:
+	i--;
+
+	while (i >= start) {
+		if (ib_agent_port_close(device, i))
 			printk(KERN_ERR PFX "Couldn't close %s port %d "
 			       "for agents\n",
-			       device->name, cur_port);
-		if (ib_mad_port_close(device, cur_port))
+			       device->name, i);
+		if (ib_mad_port_close(device, i))
 			printk(KERN_ERR PFX "Couldn't close %s port %d\n",
-			       device->name, cur_port);
+			       device->name, i);
 		i--;
 	}
 }
@@ -2754,7 +2724,6 @@
 	int ret;
 
 	spin_lock_init(&ib_mad_port_list_lock);
-	spin_lock_init(&ib_agent_port_list_lock);
 
 	ib_mad_cache = kmem_cache_create("ib_mad",
 					 sizeof(struct ib_mad_private),
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index f1ba794..570f786 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -118,9 +118,10 @@
 	struct ib_mad_list_head mad_list;
 	struct list_head agent_list;
 	struct ib_mad_agent_private *mad_agent_priv;
+	struct ib_mad_send_buf send_buf;
+	DECLARE_PCI_UNMAP_ADDR(mapping)
 	struct ib_send_wr send_wr;
 	struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
-	u64 wr_id;			/* client WR ID */
 	__be64 tid;
 	unsigned long timeout;
 	int retries;
@@ -141,10 +142,7 @@
 	struct list_head completion_list;
 	struct ib_mad_private *mad_priv;
 	struct ib_mad_agent_private *recv_mad_agent;
-	struct ib_send_wr send_wr;
-	struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
-	u64 wr_id;			/* client WR ID */
-	__be64 tid;
+	struct ib_mad_send_wr_private *mad_send_wr;
 };
 
 struct ib_mad_mgmt_method_table {
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index e23836d..3249e1d 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -103,12 +103,12 @@
 static int data_offset(u8 mgmt_class)
 {
 	if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
-		return offsetof(struct ib_sa_mad, data);
+		return IB_MGMT_SA_HDR;
 	else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
 		 (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
-		return offsetof(struct ib_vendor_mad, data);
+		return IB_MGMT_VENDOR_HDR;
 	else
-		return offsetof(struct ib_rmpp_mad, data);
+		return IB_MGMT_RMPP_HDR;
 }
 
 static void format_ack(struct ib_rmpp_mad *ack,
@@ -135,55 +135,52 @@
 		     struct ib_mad_recv_wc *recv_wc)
 {
 	struct ib_mad_send_buf *msg;
-	struct ib_send_wr *bad_send_wr;
-	int hdr_len, ret;
+	int ret;
 
-	hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
 	msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
-				 recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
-				 hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
-				 GFP_KERNEL);
+				 recv_wc->wc->pkey_index, 1, IB_MGMT_RMPP_HDR,
+				 IB_MGMT_RMPP_DATA, GFP_KERNEL);
 	if (!msg)
 		return;
 
-	format_ack((struct ib_rmpp_mad *) msg->mad,
-		   (struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
-	ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
-			       &bad_send_wr);
+	format_ack(msg->mad, (struct ib_rmpp_mad *) recv_wc->recv_buf.mad,
+		   rmpp_recv);
+	msg->ah = rmpp_recv->ah;
+	ret = ib_post_send_mad(msg, NULL);
 	if (ret)
 		ib_free_send_mad(msg);
 }
 
-static int alloc_response_msg(struct ib_mad_agent *agent,
-			      struct ib_mad_recv_wc *recv_wc,
-			      struct ib_mad_send_buf **msg)
+static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent,
+						  struct ib_mad_recv_wc *recv_wc)
 {
-	struct ib_mad_send_buf *m;
+	struct ib_mad_send_buf *msg;
 	struct ib_ah *ah;
-	int hdr_len;
 
 	ah = ib_create_ah_from_wc(agent->qp->pd, recv_wc->wc,
 				  recv_wc->recv_buf.grh, agent->port_num);
 	if (IS_ERR(ah))
-		return PTR_ERR(ah);
+		return (void *) ah;
 
-	hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
-	m = ib_create_send_mad(agent, recv_wc->wc->src_qp,
-			       recv_wc->wc->pkey_index, ah, 1, hdr_len,
-			       sizeof(struct ib_rmpp_mad) - hdr_len,
-			       GFP_KERNEL);
-	if (IS_ERR(m)) {
+	msg = ib_create_send_mad(agent, recv_wc->wc->src_qp,
+				 recv_wc->wc->pkey_index, 1,
+				 IB_MGMT_RMPP_HDR, IB_MGMT_RMPP_DATA,
+				 GFP_KERNEL);
+	if (IS_ERR(msg))
 		ib_destroy_ah(ah);
-		return PTR_ERR(m);
-	}
-	*msg = m;
-	return 0;
+	else
+		msg->ah = ah;
+
+	return msg;
 }
 
-static void free_msg(struct ib_mad_send_buf *msg)
+void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc)
 {
-	ib_destroy_ah(msg->send_wr.wr.ud.ah);
-	ib_free_send_mad(msg);
+	struct ib_rmpp_mad *rmpp_mad = mad_send_wc->send_buf->mad;
+
+	if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_ACK)
+		ib_destroy_ah(mad_send_wc->send_buf->ah);
+	ib_free_send_mad(mad_send_wc->send_buf);
 }
 
 static void nack_recv(struct ib_mad_agent_private *agent,
@@ -191,14 +188,13 @@
 {
 	struct ib_mad_send_buf *msg;
 	struct ib_rmpp_mad *rmpp_mad;
-	struct ib_send_wr *bad_send_wr;
 	int ret;
 
-	ret = alloc_response_msg(&agent->agent, recv_wc, &msg);
-	if (ret)
+	msg = alloc_response_msg(&agent->agent, recv_wc);
+	if (IS_ERR(msg))
 		return;
 
-	rmpp_mad = (struct ib_rmpp_mad *) msg->mad;
+	rmpp_mad = msg->mad;
 	memcpy(rmpp_mad, recv_wc->recv_buf.mad,
 	       data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class));
 
@@ -210,9 +206,11 @@
 	rmpp_mad->rmpp_hdr.seg_num = 0;
 	rmpp_mad->rmpp_hdr.paylen_newwin = 0;
 
-	ret = ib_post_send_mad(&agent->agent, &msg->send_wr, &bad_send_wr);
-	if (ret)
-		free_msg(msg);
+	ret = ib_post_send_mad(msg, NULL);
+	if (ret) {
+		ib_destroy_ah(msg->ah);
+		ib_free_send_mad(msg);
+	}
 }
 
 static void recv_timeout_handler(void *data)
@@ -585,7 +583,7 @@
 	int timeout;
 	u32 paylen;
 
-	rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+	rmpp_mad = mad_send_wr->send_buf.mad;
 	ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
 	rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num);
 
@@ -612,7 +610,7 @@
 	}
 
 	/* 2 seconds for an ACK until we can find the packet lifetime */
-	timeout = mad_send_wr->send_wr.wr.ud.timeout_ms;
+	timeout = mad_send_wr->send_buf.timeout_ms;
 	if (!timeout || timeout > 2000)
 		mad_send_wr->timeout = msecs_to_jiffies(2000);
 	mad_send_wr->seg_num++;
@@ -640,7 +638,7 @@
 
 	wc.status = IB_WC_REM_ABORT_ERR;
 	wc.vendor_err = rmpp_status;
-	wc.wr_id = mad_send_wr->wr_id;
+	wc.send_buf = &mad_send_wr->send_buf;
 	ib_mad_complete_send_wr(mad_send_wr, &wc);
 	return;
 out:
@@ -694,12 +692,12 @@
 
 	if (seg_num > mad_send_wr->last_ack) {
 		mad_send_wr->last_ack = seg_num;
-		mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
+		mad_send_wr->retries = mad_send_wr->send_buf.retries;
 	}
 	mad_send_wr->newwin = newwin;
 	if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
 		/* If no response is expected, the ACK completes the send */
-		if (!mad_send_wr->send_wr.wr.ud.timeout_ms) {
+		if (!mad_send_wr->send_buf.timeout_ms) {
 			struct ib_mad_send_wc wc;
 
 			ib_mark_mad_done(mad_send_wr);
@@ -707,13 +705,13 @@
 
 			wc.status = IB_WC_SUCCESS;
 			wc.vendor_err = 0;
-			wc.wr_id = mad_send_wr->wr_id;
+			wc.send_buf = &mad_send_wr->send_buf;
 			ib_mad_complete_send_wr(mad_send_wr, &wc);
 			return;
 		}
 		if (mad_send_wr->refcount == 1)
-			ib_reset_mad_timeout(mad_send_wr, mad_send_wr->
-					     send_wr.wr.ud.timeout_ms);
+			ib_reset_mad_timeout(mad_send_wr,
+					     mad_send_wr->send_buf.timeout_ms);
 	} else if (mad_send_wr->refcount == 1 &&
 		   mad_send_wr->seg_num < mad_send_wr->newwin &&
 		   mad_send_wr->seg_num <= mad_send_wr->total_seg) {
@@ -842,7 +840,7 @@
 	struct ib_rmpp_mad *rmpp_mad;
 	int i, total_len, ret;
 
-	rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+	rmpp_mad = mad_send_wr->send_buf.mad;
 	if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
 	      IB_MGMT_RMPP_FLAG_ACTIVE))
 		return IB_RMPP_RESULT_UNHANDLED;
@@ -863,7 +861,7 @@
 
         mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) /
 			(sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset);
-	mad_send_wr->pad = total_len - offsetof(struct ib_rmpp_mad, data) -
+	mad_send_wr->pad = total_len - IB_MGMT_RMPP_HDR -
 			   be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
 
 	/* We need to wait for the final ACK even if there isn't a response */
@@ -878,23 +876,15 @@
 			    struct ib_mad_send_wc *mad_send_wc)
 {
 	struct ib_rmpp_mad *rmpp_mad;
-	struct ib_mad_send_buf *msg;
 	int ret;
 
-	rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+	rmpp_mad = mad_send_wr->send_buf.mad;
 	if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
 	      IB_MGMT_RMPP_FLAG_ACTIVE))
 		return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
 
-	if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
-		msg = (struct ib_mad_send_buf *) (unsigned long)
-		      mad_send_wc->wr_id;
-		if (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_ACK)
-			ib_free_send_mad(msg);
-		else
-			free_msg(msg);
+	if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
 		return IB_RMPP_RESULT_INTERNAL;	 /* ACK, STOP, or ABORT */
-	}
 
 	if (mad_send_wc->status != IB_WC_SUCCESS ||
 	    mad_send_wr->status != IB_WC_SUCCESS)
@@ -905,7 +895,7 @@
 
 	if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
 		mad_send_wr->timeout =
-			msecs_to_jiffies(mad_send_wr->send_wr.wr.ud.timeout_ms);
+			msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
 		return IB_RMPP_RESULT_PROCESSED; /* Send done */
 	}
 
@@ -926,7 +916,7 @@
 	struct ib_rmpp_mad *rmpp_mad;
 	int ret;
 
-	rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
+	rmpp_mad = mad_send_wr->send_buf.mad;
 	if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
 	      IB_MGMT_RMPP_FLAG_ACTIVE))
 		return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
diff --git a/drivers/infiniband/core/mad_rmpp.h b/drivers/infiniband/core/mad_rmpp.h
index c4924df..f0616fd 100644
--- a/drivers/infiniband/core/mad_rmpp.h
+++ b/drivers/infiniband/core/mad_rmpp.h
@@ -51,6 +51,8 @@
 int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
 			    struct ib_mad_send_wc *mad_send_wc);
 
+void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc);
+
 void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent);
 
 int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr);
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 2626182..acda7d6 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -43,6 +43,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kref.h>
 #include <linux/idr.h>
+#include <linux/workqueue.h>
 
 #include <rdma/ib_pack.h>
 #include <rdma/ib_sa.h>
@@ -73,11 +74,10 @@
 struct ib_sa_query {
 	void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);
 	void (*release)(struct ib_sa_query *);
-	struct ib_sa_port  *port;
-	struct ib_sa_mad   *mad;
-	struct ib_sa_sm_ah *sm_ah;
-	DECLARE_PCI_UNMAP_ADDR(mapping)
-	int                 id;
+	struct ib_sa_port      *port;
+	struct ib_mad_send_buf *mad_buf;
+	struct ib_sa_sm_ah     *sm_ah;
+	int			id;
 };
 
 struct ib_sa_service_query {
@@ -426,6 +426,7 @@
 {
 	unsigned long flags;
 	struct ib_mad_agent *agent;
+	struct ib_mad_send_buf *mad_buf;
 
 	spin_lock_irqsave(&idr_lock, flags);
 	if (idr_find(&query_idr, id) != query) {
@@ -433,9 +434,10 @@
 		return;
 	}
 	agent = query->port->agent;
+	mad_buf = query->mad_buf;
 	spin_unlock_irqrestore(&idr_lock, flags);
 
-	ib_cancel_mad(agent, id);
+	ib_cancel_mad(agent, mad_buf);
 }
 EXPORT_SYMBOL(ib_sa_cancel_query);
 
@@ -457,71 +459,46 @@
 
 static int send_mad(struct ib_sa_query *query, int timeout_ms)
 {
-	struct ib_sa_port *port = query->port;
 	unsigned long flags;
-	int ret;
-	struct ib_sge      gather_list;
-	struct ib_send_wr *bad_wr, wr = {
-		.opcode      = IB_WR_SEND,
-		.sg_list     = &gather_list,
-		.num_sge     = 1,
-		.send_flags  = IB_SEND_SIGNALED,
-		.wr	     = {
-			 .ud = {
-				 .mad_hdr     = &query->mad->mad_hdr,
-				 .remote_qpn  = 1,
-				 .remote_qkey = IB_QP1_QKEY,
-				 .timeout_ms  = timeout_ms,
-			 }
-		 }
-	};
+	int ret, id;
 
 retry:
 	if (!idr_pre_get(&query_idr, GFP_ATOMIC))
 		return -ENOMEM;
 	spin_lock_irqsave(&idr_lock, flags);
-	ret = idr_get_new(&query_idr, query, &query->id);
+	ret = idr_get_new(&query_idr, query, &id);
 	spin_unlock_irqrestore(&idr_lock, flags);
 	if (ret == -EAGAIN)
 		goto retry;
 	if (ret)
 		return ret;
 
-	wr.wr_id = query->id;
+	query->mad_buf->timeout_ms  = timeout_ms;
+	query->mad_buf->context[0] = query;
+	query->id = id;
 
-	spin_lock_irqsave(&port->ah_lock, flags);
-	kref_get(&port->sm_ah->ref);
-	query->sm_ah = port->sm_ah;
-	wr.wr.ud.ah  = port->sm_ah->ah;
-	spin_unlock_irqrestore(&port->ah_lock, flags);
+	spin_lock_irqsave(&query->port->ah_lock, flags);
+	kref_get(&query->port->sm_ah->ref);
+	query->sm_ah = query->port->sm_ah;
+	spin_unlock_irqrestore(&query->port->ah_lock, flags);
 
-	gather_list.addr   = dma_map_single(port->agent->device->dma_device,
-					    query->mad,
-					    sizeof (struct ib_sa_mad),
-					    DMA_TO_DEVICE);
-	gather_list.length = sizeof (struct ib_sa_mad);
-	gather_list.lkey   = port->agent->mr->lkey;
-	pci_unmap_addr_set(query, mapping, gather_list.addr);
+	query->mad_buf->ah = query->sm_ah->ah;
 
-	ret = ib_post_send_mad(port->agent, &wr, &bad_wr);
+	ret = ib_post_send_mad(query->mad_buf, NULL);
 	if (ret) {
-		dma_unmap_single(port->agent->device->dma_device,
-				 pci_unmap_addr(query, mapping),
-				 sizeof (struct ib_sa_mad),
-				 DMA_TO_DEVICE);
-		kref_put(&query->sm_ah->ref, free_sm_ah);
 		spin_lock_irqsave(&idr_lock, flags);
-		idr_remove(&query_idr, query->id);
+		idr_remove(&query_idr, id);
 		spin_unlock_irqrestore(&idr_lock, flags);
+
+		kref_put(&query->sm_ah->ref, free_sm_ah);
 	}
 
 	/*
 	 * It's not safe to dereference query any more, because the
 	 * send may already have completed and freed the query in
-	 * another context.  So use wr.wr_id, which has a copy of the
-	 * query's id.
+	 * another context.
 	 */
-	return ret ? ret : wr.wr_id;
+	return ret ? ret : id;
 }
 
 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
@@ -543,7 +520,6 @@
 
 static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
 {
-	kfree(sa_query->mad);
 	kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));
 }
 
@@ -583,44 +559,59 @@
 {
 	struct ib_sa_path_query *query;
 	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
-	struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
-	struct ib_mad_agent *agent  = port->agent;
+	struct ib_sa_port   *port;
+	struct ib_mad_agent *agent;
+	struct ib_sa_mad *mad;
 	int ret;
 
+	if (!sa_dev)
+		return -ENODEV;
+
+	port  = &sa_dev->port[port_num - sa_dev->start_port];
+	agent = port->agent;
+
 	query = kmalloc(sizeof *query, gfp_mask);
 	if (!query)
 		return -ENOMEM;
-	query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
-	if (!query->sa_query.mad) {
-		kfree(query);
-		return -ENOMEM;
+
+	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+						     0, IB_MGMT_SA_HDR,
+						     IB_MGMT_SA_DATA, gfp_mask);
+	if (!query->sa_query.mad_buf) {
+		ret = -ENOMEM;
+		goto err1;
 	}
 
 	query->callback = callback;
 	query->context  = context;
 
-	init_mad(query->sa_query.mad, agent);
+	mad = query->sa_query.mad_buf->mad;
+	init_mad(mad, agent);
 
-	query->sa_query.callback              = callback ? ib_sa_path_rec_callback : NULL;
-	query->sa_query.release               = ib_sa_path_rec_release;
-	query->sa_query.port                  = port;
-	query->sa_query.mad->mad_hdr.method   = IB_MGMT_METHOD_GET;
-	query->sa_query.mad->mad_hdr.attr_id  = cpu_to_be16(IB_SA_ATTR_PATH_REC);
-	query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+	query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
+	query->sa_query.release  = ib_sa_path_rec_release;
+	query->sa_query.port     = port;
+	mad->mad_hdr.method	 = IB_MGMT_METHOD_GET;
+	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_PATH_REC);
+	mad->sa_hdr.comp_mask	 = comp_mask;
 
-	ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),
-		rec, query->sa_query.mad->data);
+	ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);
 
 	*sa_query = &query->sa_query;
 
 	ret = send_mad(&query->sa_query, timeout_ms);
-	if (ret < 0) {
-		*sa_query = NULL;
-		kfree(query->sa_query.mad);
-		kfree(query);
-	}
+	if (ret < 0)
+		goto err2;
 
 	return ret;
+
+err2:
+	*sa_query = NULL;
+	ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+	kfree(query);
+	return ret;
 }
 EXPORT_SYMBOL(ib_sa_path_rec_get);
 
@@ -643,7 +634,6 @@
 
 static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
 {
-	kfree(sa_query->mad);
 	kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
 }
 
@@ -685,10 +675,17 @@
 {
 	struct ib_sa_service_query *query;
 	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
-	struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
-	struct ib_mad_agent *agent  = port->agent;
+	struct ib_sa_port   *port;
+	struct ib_mad_agent *agent;
+	struct ib_sa_mad *mad;
 	int ret;
 
+	if (!sa_dev)
+		return -ENODEV;
+
+	port  = &sa_dev->port[port_num - sa_dev->start_port];
+	agent = port->agent;
+
 	if (method != IB_MGMT_METHOD_GET &&
 	    method != IB_MGMT_METHOD_SET &&
 	    method != IB_SA_METHOD_DELETE)
@@ -697,38 +694,46 @@
 	query = kmalloc(sizeof *query, gfp_mask);
 	if (!query)
 		return -ENOMEM;
-	query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
-	if (!query->sa_query.mad) {
-		kfree(query);
-		return -ENOMEM;
+
+	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+						     0, IB_MGMT_SA_HDR,
+						     IB_MGMT_SA_DATA, gfp_mask);
+	if (!query->sa_query.mad_buf) {
+		ret = -ENOMEM;
+		goto err1;
 	}
 
 	query->callback = callback;
 	query->context  = context;
 
-	init_mad(query->sa_query.mad, agent);
+	mad = query->sa_query.mad_buf->mad;
+	init_mad(mad, agent);
 
-	query->sa_query.callback              = callback ? ib_sa_service_rec_callback : NULL;
-	query->sa_query.release               = ib_sa_service_rec_release;
-	query->sa_query.port                  = port;
-	query->sa_query.mad->mad_hdr.method   = method;
-	query->sa_query.mad->mad_hdr.attr_id  =
-				cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
-	query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+	query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
+	query->sa_query.release  = ib_sa_service_rec_release;
+	query->sa_query.port     = port;
+	mad->mad_hdr.method	 = method;
+	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
+	mad->sa_hdr.comp_mask	 = comp_mask;
 
 	ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
-		rec, query->sa_query.mad->data);
+		rec, mad->data);
 
 	*sa_query = &query->sa_query;
 
 	ret = send_mad(&query->sa_query, timeout_ms);
-	if (ret < 0) {
-		*sa_query = NULL;
-		kfree(query->sa_query.mad);
-		kfree(query);
-	}
+	if (ret < 0)
+		goto err2;
 
 	return ret;
+
+err2:
+	*sa_query = NULL;
+	ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+	kfree(query);
+	return ret;
 }
 EXPORT_SYMBOL(ib_sa_service_rec_query);
 
@@ -751,7 +756,6 @@
 
 static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query)
 {
-	kfree(sa_query->mad);
 	kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));
 }
 
@@ -768,60 +772,69 @@
 {
 	struct ib_sa_mcmember_query *query;
 	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
-	struct ib_sa_port   *port   = &sa_dev->port[port_num - sa_dev->start_port];
-	struct ib_mad_agent *agent  = port->agent;
+	struct ib_sa_port   *port;
+	struct ib_mad_agent *agent;
+	struct ib_sa_mad *mad;
 	int ret;
 
+	if (!sa_dev)
+		return -ENODEV;
+
+	port  = &sa_dev->port[port_num - sa_dev->start_port];
+	agent = port->agent;
+
 	query = kmalloc(sizeof *query, gfp_mask);
 	if (!query)
 		return -ENOMEM;
-	query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
-	if (!query->sa_query.mad) {
-		kfree(query);
-		return -ENOMEM;
+
+	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
+						     0, IB_MGMT_SA_HDR,
+						     IB_MGMT_SA_DATA, gfp_mask);
+	if (!query->sa_query.mad_buf) {
+		ret = -ENOMEM;
+		goto err1;
 	}
 
 	query->callback = callback;
 	query->context  = context;
 
-	init_mad(query->sa_query.mad, agent);
+	mad = query->sa_query.mad_buf->mad;
+	init_mad(mad, agent);
 
-	query->sa_query.callback              = callback ? ib_sa_mcmember_rec_callback : NULL;
-	query->sa_query.release               = ib_sa_mcmember_rec_release;
-	query->sa_query.port                  = port;
-	query->sa_query.mad->mad_hdr.method   = method;
-	query->sa_query.mad->mad_hdr.attr_id  = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
-	query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
+	query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
+	query->sa_query.release  = ib_sa_mcmember_rec_release;
+	query->sa_query.port     = port;
+	mad->mad_hdr.method	 = method;
+	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
+	mad->sa_hdr.comp_mask	 = comp_mask;
 
 	ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),
-		rec, query->sa_query.mad->data);
+		rec, mad->data);
 
 	*sa_query = &query->sa_query;
 
 	ret = send_mad(&query->sa_query, timeout_ms);
-	if (ret < 0) {
-		*sa_query = NULL;
-		kfree(query->sa_query.mad);
-		kfree(query);
-	}
+	if (ret < 0)
+		goto err2;
 
 	return ret;
+
+err2:
+	*sa_query = NULL;
+	ib_free_send_mad(query->sa_query.mad_buf);
+
+err1:
+	kfree(query);
+	return ret;
 }
 EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
 
 static void send_handler(struct ib_mad_agent *agent,
 			 struct ib_mad_send_wc *mad_send_wc)
 {
-	struct ib_sa_query *query;
+	struct ib_sa_query *query = mad_send_wc->send_buf->context[0];
 	unsigned long flags;
 
-	spin_lock_irqsave(&idr_lock, flags);
-	query = idr_find(&query_idr, mad_send_wc->wr_id);
-	spin_unlock_irqrestore(&idr_lock, flags);
-
-	if (!query)
-		return;
-
 	if (query->callback)
 		switch (mad_send_wc->status) {
 		case IB_WC_SUCCESS:
@@ -838,30 +851,25 @@
 			break;
 		}
 
-	dma_unmap_single(agent->device->dma_device,
-			 pci_unmap_addr(query, mapping),
-			 sizeof (struct ib_sa_mad),
-			 DMA_TO_DEVICE);
-	kref_put(&query->sm_ah->ref, free_sm_ah);
-
-	query->release(query);
-
 	spin_lock_irqsave(&idr_lock, flags);
-	idr_remove(&query_idr, mad_send_wc->wr_id);
+	idr_remove(&query_idr, query->id);
 	spin_unlock_irqrestore(&idr_lock, flags);
+
+        ib_free_send_mad(mad_send_wc->send_buf);
+	kref_put(&query->sm_ah->ref, free_sm_ah);
+	query->release(query);
 }
 
 static void recv_handler(struct ib_mad_agent *mad_agent,
 			 struct ib_mad_recv_wc *mad_recv_wc)
 {
 	struct ib_sa_query *query;
-	unsigned long flags;
+	struct ib_mad_send_buf *mad_buf;
 
-	spin_lock_irqsave(&idr_lock, flags);
-	query = idr_find(&query_idr, mad_recv_wc->wc->wr_id);
-	spin_unlock_irqrestore(&idr_lock, flags);
+	mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;
+	query = mad_buf->context[0];
 
-	if (query && query->callback) {
+	if (query->callback) {
 		if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
 			query->callback(query,
 					mad_recv_wc->recv_buf.mad->mad_hdr.status ?
@@ -975,6 +983,7 @@
 static void __exit ib_sa_cleanup(void)
 {
 	ib_unregister_client(&sa_client);
+	idr_destroy(&query_idr);
 }
 
 module_init(ib_sa_init);
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
index db25503..2b3c401 100644
--- a/drivers/infiniband/core/smi.h
+++ b/drivers/infiniband/core/smi.h
@@ -39,6 +39,8 @@
 #ifndef __SMI_H_
 #define __SMI_H_
 
+#include <rdma/ib_smi.h>
+
 int smi_handle_dr_smp_recv(struct ib_smp *smp,
 			   u8 node_type,
 			   int port_num,
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 211ba32..7ce7a6c 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -65,6 +65,11 @@
 	int			index;
 };
 
+static inline int ibdev_is_alive(const struct ib_device *dev) 
+{
+	return dev->reg_state == IB_DEV_REGISTERED;
+}
+
 static ssize_t port_attr_show(struct kobject *kobj,
 			      struct attribute *attr, char *buf)
 {
@@ -74,6 +79,8 @@
 
 	if (!port_attr->show)
 		return -EIO;
+	if (!ibdev_is_alive(p->ibdev))
+		return -ENODEV;
 
 	return port_attr->show(p, port_attr, buf);
 }
@@ -581,6 +588,9 @@
 {
 	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
 
+	if (!ibdev_is_alive(dev))
+		return -ENODEV;
+
 	switch (dev->node_type) {
 	case IB_NODE_CA:     return sprintf(buf, "%d: CA\n", dev->node_type);
 	case IB_NODE_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);
@@ -595,6 +605,9 @@
 	struct ib_device_attr attr;
 	ssize_t ret;
 
+	if (!ibdev_is_alive(dev))
+		return -ENODEV;
+
 	ret = ib_query_device(dev, &attr);
 	if (ret)
 		return ret;
@@ -612,6 +625,9 @@
 	struct ib_device_attr attr;
 	ssize_t ret;
 
+	if (!ibdev_is_alive(dev))
+		return -ENODEV;
+
 	ret = ib_query_device(dev, &attr);
 	if (ret)
 		return ret;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index d0f0b0a..2847756 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -41,37 +41,81 @@
 #include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/cdev.h>
+#include <linux/idr.h>
 
 #include <asm/uaccess.h>
 
-#include "ucm.h"
+#include <rdma/ib_cm.h>
+#include <rdma/ib_user_cm.h>
 
 MODULE_AUTHOR("Libor Michalek");
 MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access");
 MODULE_LICENSE("Dual BSD/GPL");
 
-static int ucm_debug_level;
+struct ib_ucm_device {
+	int			devnum;
+	struct cdev		dev;
+	struct class_device	class_dev;
+	struct ib_device	*ib_dev;
+};
 
-module_param_named(debug_level, ucm_debug_level, int, 0644);
-MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+struct ib_ucm_file {
+	struct semaphore mutex;
+	struct file *filp;
+	struct ib_ucm_device *device;
+
+	struct list_head  ctxs;
+	struct list_head  events;
+	wait_queue_head_t poll_wait;
+};
+
+struct ib_ucm_context {
+	int                 id;
+	wait_queue_head_t   wait;
+	atomic_t            ref;
+	int		    events_reported;
+
+	struct ib_ucm_file *file;
+	struct ib_cm_id    *cm_id;
+	__u64		   uid;
+
+	struct list_head    events;    /* list of pending events. */
+	struct list_head    file_list; /* member in file ctx list */
+};
+
+struct ib_ucm_event {
+	struct ib_ucm_context *ctx;
+	struct list_head file_list; /* member in file event list */
+	struct list_head ctx_list;  /* member in ctx event list */
+
+	struct ib_cm_id *cm_id;
+	struct ib_ucm_event_resp resp;
+	void *data;
+	void *info;
+	int data_len;
+	int info_len;
+};
 
 enum {
 	IB_UCM_MAJOR = 231,
-	IB_UCM_MINOR = 255
+	IB_UCM_BASE_MINOR = 224,
+	IB_UCM_MAX_DEVICES = 32
 };
 
-#define IB_UCM_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_MINOR)
+#define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
 
-#define PFX "UCM: "
+static void ib_ucm_add_one(struct ib_device *device);
+static void ib_ucm_remove_one(struct ib_device *device);
 
-#define ucm_dbg(format, arg...)			\
-	do {					\
-		if (ucm_debug_level > 0)	\
-			printk(KERN_DEBUG PFX format, ## arg); \
-	} while (0)
+static struct ib_client ucm_client = {
+	.name   = "ucm",
+	.add    = ib_ucm_add_one,
+	.remove = ib_ucm_remove_one
+};
 
-static struct semaphore ctx_id_mutex;
-static struct idr       ctx_id_table;
+static DECLARE_MUTEX(ctx_id_mutex);
+static DEFINE_IDR(ctx_id_table);
+static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES);
 
 static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
 {
@@ -152,17 +196,13 @@
 		goto error;
 
 	list_add_tail(&ctx->file_list, &file->ctxs);
-	ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
 	return ctx;
 
 error:
 	kfree(ctx);
 	return NULL;
 }
-/*
- * Event portion of the API, handle CM events
- * and allow event polling.
- */
+
 static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
 				  struct ib_sa_path_rec	 *kpath)
 {
@@ -209,6 +249,7 @@
 	ureq->retry_count                = kreq->retry_count;
 	ureq->rnr_retry_count            = kreq->rnr_retry_count;
 	ureq->srq                        = kreq->srq;
+	ureq->port			 = kreq->port;
 
 	ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path);
 	ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path);
@@ -295,6 +336,8 @@
 	case IB_CM_SIDR_REQ_RECEIVED:
 		uvt->resp.u.sidr_req_resp.pkey = 
 					evt->param.sidr_req_rcvd.pkey;
+		uvt->resp.u.sidr_req_resp.port = 
+					evt->param.sidr_req_rcvd.port;
 		uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
 		break;
 	case IB_CM_SIDR_REP_RECEIVED:
@@ -387,9 +430,7 @@
 
 	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 		return -EFAULT;
-	/*
-	 * wait
-	 */
+
 	down(&file->mutex);
 	while (list_empty(&file->events)) {
 
@@ -471,7 +512,6 @@
 	return result;
 }
 
-
 static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
 				const char __user *inbuf,
 				int in_len, int out_len)
@@ -494,29 +534,27 @@
 		return -ENOMEM;
 
 	ctx->uid = cmd.uid;
-	ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
+	ctx->cm_id = ib_create_cm_id(file->device->ib_dev,
+				     ib_ucm_event_handler, ctx);
 	if (IS_ERR(ctx->cm_id)) {
 		result = PTR_ERR(ctx->cm_id);
-		goto err;
+		goto err1;
 	}
 
 	resp.id = ctx->id;
 	if (copy_to_user((void __user *)(unsigned long)cmd.response,
 			 &resp, sizeof(resp))) {
 		result = -EFAULT;
-		goto err;
+		goto err2;
 	}
-
 	return 0;
 
-err:
+err2:
+	ib_destroy_cm_id(ctx->cm_id);
+err1:
 	down(&ctx_id_mutex);
 	idr_remove(&ctx_id_table, ctx->id);
 	up(&ctx_id_mutex);
-
-	if (!IS_ERR(ctx->cm_id))
-		ib_destroy_cm_id(ctx->cm_id);
-
 	kfree(ctx);
 	return result;
 }
@@ -1184,9 +1222,6 @@
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	ucm_dbg("Write. cmd <%d> in <%d> out <%d> len <%Zu>\n",
-		hdr.cmd, hdr.in, hdr.out, len);
-
 	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
 		return -EINVAL;
 
@@ -1231,8 +1266,7 @@
 
 	filp->private_data = file;
 	file->filp = filp;
-
-	ucm_dbg("Created struct\n");
+	file->device = container_of(inode->i_cdev, struct ib_ucm_device, dev);
 
 	return 0;
 }
@@ -1263,7 +1297,17 @@
 	return 0;
 }
 
-static struct file_operations ib_ucm_fops = {
+static void ib_ucm_release_class_dev(struct class_device *class_dev)
+{
+	struct ib_ucm_device *dev;
+
+	dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+	cdev_del(&dev->dev);
+	clear_bit(dev->devnum, dev_map);
+	kfree(dev);
+}
+
+static struct file_operations ucm_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ib_ucm_open,
 	.release = ib_ucm_close,
@@ -1271,55 +1315,142 @@
 	.poll    = ib_ucm_poll,
 };
 
+static struct class ucm_class = {
+	.name    = "infiniband_cm",
+	.release = ib_ucm_release_class_dev
+};
 
-static struct class *ib_ucm_class;
-static struct cdev	  ib_ucm_cdev;
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+	struct ib_ucm_device *dev;
+	
+	dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+	return print_dev_t(buf, dev->dev.dev);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
+
+static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
+{
+	struct ib_ucm_device *dev;
+	
+	dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+	return sprintf(buf, "%s\n", dev->ib_dev->name);
+}
+static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+static void ib_ucm_add_one(struct ib_device *device)
+{
+	struct ib_ucm_device *ucm_dev;
+
+	if (!device->alloc_ucontext)
+		return;
+
+	ucm_dev = kmalloc(sizeof *ucm_dev, GFP_KERNEL);
+	if (!ucm_dev)
+		return;
+
+	memset(ucm_dev, 0, sizeof *ucm_dev);
+	ucm_dev->ib_dev = device;
+
+	ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
+	if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES)
+		goto err;
+
+	set_bit(ucm_dev->devnum, dev_map);
+
+	cdev_init(&ucm_dev->dev, &ucm_fops);
+	ucm_dev->dev.owner = THIS_MODULE;
+	kobject_set_name(&ucm_dev->dev.kobj, "ucm%d", ucm_dev->devnum);
+	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.dev = device->dma_device;
+	snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
+		 ucm_dev->devnum);
+	if (class_device_register(&ucm_dev->class_dev))
+		goto err_cdev;
+
+	if (class_device_create_file(&ucm_dev->class_dev,
+				     &class_device_attr_dev))
+		goto err_class;
+	if (class_device_create_file(&ucm_dev->class_dev,
+				     &class_device_attr_ibdev))
+		goto err_class;
+
+	ib_set_client_data(device, &ucm_client, ucm_dev);
+	return;
+
+err_class:
+	class_device_unregister(&ucm_dev->class_dev);
+err_cdev:
+	cdev_del(&ucm_dev->dev);
+	clear_bit(ucm_dev->devnum, dev_map);
+err:
+	kfree(ucm_dev);
+	return;
+}
+
+static void ib_ucm_remove_one(struct ib_device *device)
+{
+	struct ib_ucm_device *ucm_dev = ib_get_client_data(device, &ucm_client);
+
+	if (!ucm_dev)
+		return;
+
+	class_device_unregister(&ucm_dev->class_dev);
+}
+
+static ssize_t show_abi_version(struct class *class, char *buf)
+{
+	return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION);
+}
+static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 
 static int __init ib_ucm_init(void)
 {
-	int result;
+	int ret;
 
-	result = register_chrdev_region(IB_UCM_DEV, 1, "infiniband_cm");
-	if (result) {
-		ucm_dbg("Error <%d> registering dev\n", result);
-		goto err_chr;
+	ret = register_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES,
+				     "infiniband_cm");
+	if (ret) {
+		printk(KERN_ERR "ucm: couldn't register device number\n");
+		goto err;
 	}
 
-	cdev_init(&ib_ucm_cdev, &ib_ucm_fops);
-
-	result = cdev_add(&ib_ucm_cdev, IB_UCM_DEV, 1);
-	if (result) {
- 		ucm_dbg("Error <%d> adding cdev\n", result);
-		goto err_cdev;
+	ret = class_register(&ucm_class);
+	if (ret) {
+		printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
+		goto err_chrdev;
 	}
 
-	ib_ucm_class = class_create(THIS_MODULE, "infiniband_cm");
-	if (IS_ERR(ib_ucm_class)) {
-		result = PTR_ERR(ib_ucm_class);
- 		ucm_dbg("Error <%d> creating class\n", result);
+	ret = class_create_file(&ucm_class, &class_attr_abi_version);
+	if (ret) {
+		printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
 		goto err_class;
 	}
 
-	class_device_create(ib_ucm_class, IB_UCM_DEV, NULL, "ucm");
-
-	idr_init(&ctx_id_table);
-	init_MUTEX(&ctx_id_mutex);
-
+	ret = ib_register_client(&ucm_client);
+	if (ret) {
+		printk(KERN_ERR "ucm: couldn't register client\n");
+		goto err_class;
+	}
 	return 0;
+
 err_class:
-	cdev_del(&ib_ucm_cdev);
-err_cdev:
-	unregister_chrdev_region(IB_UCM_DEV, 1);
-err_chr:
-	return result;
+	class_unregister(&ucm_class);
+err_chrdev:
+	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+err:
+	return ret;
 }
 
 static void __exit ib_ucm_cleanup(void)
 {
-	class_device_destroy(ib_ucm_class, IB_UCM_DEV);
-	class_destroy(ib_ucm_class);
-	cdev_del(&ib_ucm_cdev);
-	unregister_chrdev_region(IB_UCM_DEV, 1);
+	ib_unregister_client(&ucm_client);
+	class_unregister(&ucm_class);
+	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+	idr_destroy(&ctx_id_table);
 }
 
 module_init(ib_ucm_init);
diff --git a/drivers/infiniband/core/ucm.h b/drivers/infiniband/core/ucm.h
deleted file mode 100644
index f46f37b..0000000
--- a/drivers/infiniband/core/ucm.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Intel Corporation.  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.
- *
- * $Id: ucm.h 2208 2005-04-22 23:24:31Z libor $
- */
-
-#ifndef UCM_H
-#define UCM_H
-
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-#include <linux/idr.h>
-
-#include <rdma/ib_cm.h>
-#include <rdma/ib_user_cm.h>
-
-struct ib_ucm_file {
-	struct semaphore mutex;
-	struct file *filp;
-
-	struct list_head  ctxs;   /* list of active connections */
-	struct list_head  events; /* list of pending events */
-	wait_queue_head_t poll_wait;
-};
-
-struct ib_ucm_context {
-	int                 id;
-	wait_queue_head_t   wait;
-	atomic_t            ref;
-	int		    events_reported;
-
-	struct ib_ucm_file *file;
-	struct ib_cm_id    *cm_id;
-	__u64		   uid;
-
-	struct list_head    events;    /* list of pending events. */
-	struct list_head    file_list; /* member in file ctx list */
-};
-
-struct ib_ucm_event {
-	struct ib_ucm_context *ctx;
-	struct list_head file_list; /* member in file event list */
-	struct list_head ctx_list;  /* member in ctx event list */
-
-	struct ib_cm_id *cm_id;
-	struct ib_ucm_event_resp resp;
-	void *data;
-	void *info;
-	int data_len;
-	int info_len;
-};
-
-#endif /* UCM_H */
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index a64d6b4..97128e2 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -64,18 +64,39 @@
 	IB_UMAD_MINOR_BASE = 0
 };
 
-struct ib_umad_port {
-	int                    devnum;
-	struct cdev            dev;
-	struct class_device    class_dev;
+/*
+ * Our lifetime rules for these structs are the following: each time a
+ * device special file is opened, we look up the corresponding struct
+ * ib_umad_port by minor in the umad_port[] table while holding the
+ * port_lock.  If this lookup succeeds, we take a reference on the
+ * ib_umad_port's struct ib_umad_device while still holding the
+ * port_lock; if the lookup fails, we fail the open().  We drop these
+ * references in the corresponding close().
+ *
+ * In addition to references coming from open character devices, there
+ * is one more reference to each ib_umad_device representing the
+ * module's reference taken when allocating the ib_umad_device in
+ * ib_umad_add_one().
+ *
+ * When destroying an ib_umad_device, we clear all of its
+ * ib_umad_ports from umad_port[] while holding port_lock before
+ * dropping the module's reference to the ib_umad_device.  This is
+ * always safe because any open() calls will either succeed and obtain
+ * a reference before we clear the umad_port[] entries, or fail after
+ * we clear the umad_port[] entries.
+ */
 
-	int                    sm_devnum;
-	struct cdev            sm_dev;
-	struct class_device    sm_class_dev;
+struct ib_umad_port {
+	struct cdev           *dev;
+	struct class_device   *class_dev;
+
+	struct cdev           *sm_dev;
+	struct class_device   *sm_class_dev;
 	struct semaphore       sm_sem;
 
 	struct ib_device      *ib_dev;
 	struct ib_umad_device *umad_dev;
+	int                    dev_num;
 	u8                     port_num;
 };
 
@@ -96,21 +117,31 @@
 };
 
 struct ib_umad_packet {
-	struct ib_ah      *ah;
 	struct ib_mad_send_buf *msg;
 	struct list_head   list;
 	int		   length;
-	DECLARE_PCI_UNMAP_ADDR(mapping)
 	struct ib_user_mad mad;
 };
 
+static struct class *umad_class;
+
 static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
-static spinlock_t map_lock;
+
+static DEFINE_SPINLOCK(port_lock);
+static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
 static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);
 
 static void ib_umad_add_one(struct ib_device *device);
 static void ib_umad_remove_one(struct ib_device *device);
 
+static void ib_umad_release_dev(struct kref *ref)
+{
+	struct ib_umad_device *dev =
+		container_of(ref, struct ib_umad_device, ref);
+
+	kfree(dev);
+}
+
 static int queue_packet(struct ib_umad_file *file,
 			struct ib_mad_agent *agent,
 			struct ib_umad_packet *packet)
@@ -139,22 +170,19 @@
 			 struct ib_mad_send_wc *send_wc)
 {
 	struct ib_umad_file *file = agent->context;
-	struct ib_umad_packet *timeout, *packet =
-		(void *) (unsigned long) send_wc->wr_id;
+	struct ib_umad_packet *timeout;
+	struct ib_umad_packet *packet = send_wc->send_buf->context[0];
 
-	ib_destroy_ah(packet->msg->send_wr.wr.ud.ah);
+	ib_destroy_ah(packet->msg->ah);
 	ib_free_send_mad(packet->msg);
 
 	if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
-		timeout = kmalloc(sizeof *timeout + sizeof (struct ib_mad_hdr),
-				  GFP_KERNEL);
+		timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL);
 		if (!timeout)
 			goto out;
 
-		memset(timeout, 0, sizeof *timeout + sizeof (struct ib_mad_hdr));
-
-		timeout->length = sizeof (struct ib_mad_hdr);
-		timeout->mad.hdr.id = packet->mad.hdr.id;
+		timeout->length 	= IB_MGMT_MAD_HDR;
+		timeout->mad.hdr.id 	= packet->mad.hdr.id;
 		timeout->mad.hdr.status = ETIMEDOUT;
 		memcpy(timeout->mad.data, packet->mad.data,
 		       sizeof (struct ib_mad_hdr));
@@ -177,11 +205,10 @@
 		goto out;
 
 	length = mad_recv_wc->mad_len;
-	packet = kmalloc(sizeof *packet + length, GFP_KERNEL);
+	packet = kzalloc(sizeof *packet + length, GFP_KERNEL);
 	if (!packet)
 		goto out;
 
-	memset(packet, 0, sizeof *packet + length);
 	packet->length = length;
 
 	ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data);
@@ -247,7 +274,7 @@
 		else
 			ret = -ENOSPC;
 	} else if (copy_to_user(buf, &packet->mad,
-			      packet->length + sizeof (struct ib_user_mad)))
+				packet->length + sizeof (struct ib_user_mad)))
 		ret = -EFAULT;
 	else
 		ret = packet->length + sizeof (struct ib_user_mad);
@@ -268,26 +295,23 @@
 	struct ib_umad_packet *packet;
 	struct ib_mad_agent *agent;
 	struct ib_ah_attr ah_attr;
-	struct ib_send_wr *bad_wr;
+	struct ib_ah *ah;
 	struct ib_rmpp_mad *rmpp_mad;
 	u8 method;
 	__be64 *tid;
-	int ret, length, hdr_len, data_len, rmpp_hdr_size;
+	int ret, length, hdr_len, copy_offset;
 	int rmpp_active = 0;
 
 	if (count < sizeof (struct ib_user_mad))
 		return -EINVAL;
 
 	length = count - sizeof (struct ib_user_mad);
-	packet = kmalloc(sizeof *packet + sizeof(struct ib_mad_hdr) +
-			 sizeof(struct ib_rmpp_hdr), GFP_KERNEL);
+	packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL);
 	if (!packet)
 		return -ENOMEM;
 
 	if (copy_from_user(&packet->mad, buf,
-			    sizeof (struct ib_user_mad) +
-			    sizeof(struct ib_mad_hdr) +
-			    sizeof(struct ib_rmpp_hdr))) {
+			    sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)) {
 		ret = -EFAULT;
 		goto err;
 	}
@@ -298,8 +322,6 @@
 		goto err;
 	}
 
-	packet->length = length;
-
 	down_read(&file->agent_mutex);
 
 	agent = file->agent[packet->mad.hdr.id];
@@ -321,9 +343,9 @@
 		ah_attr.grh.traffic_class  = packet->mad.hdr.traffic_class;
 	}
 
-	packet->ah = ib_create_ah(agent->qp->pd, &ah_attr);
-	if (IS_ERR(packet->ah)) {
-		ret = PTR_ERR(packet->ah);
+	ah = ib_create_ah(agent->qp->pd, &ah_attr);
+	if (IS_ERR(ah)) {
+		ret = PTR_ERR(ah);
 		goto err_up;
 	}
 
@@ -337,64 +359,44 @@
 
 		/* Validate that the management class can support RMPP */
 		if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
-			hdr_len = offsetof(struct ib_sa_mad, data);
-			data_len = length - hdr_len;
+			hdr_len = IB_MGMT_SA_HDR;
 		} else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
 			    (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {
-				hdr_len = offsetof(struct ib_vendor_mad, data);
-				data_len = length - hdr_len;
+				hdr_len = IB_MGMT_VENDOR_HDR;
 		} else {
 			ret = -EINVAL;
 			goto err_ah;
 		}
 		rmpp_active = 1;
+		copy_offset = IB_MGMT_RMPP_HDR;
 	} else {
-		if (length > sizeof(struct ib_mad)) {
-			ret = -EINVAL;
-			goto err_ah;
-		}
-		hdr_len = offsetof(struct ib_mad, data);
-		data_len = length - hdr_len;
+		hdr_len = IB_MGMT_MAD_HDR;
+		copy_offset = IB_MGMT_MAD_HDR;
 	}
 
 	packet->msg = ib_create_send_mad(agent,
 					 be32_to_cpu(packet->mad.hdr.qpn),
-					 0, packet->ah, rmpp_active,
-					 hdr_len, data_len,
+					 0, rmpp_active,
+					 hdr_len, length - hdr_len,
 					 GFP_KERNEL);
 	if (IS_ERR(packet->msg)) {
 		ret = PTR_ERR(packet->msg);
 		goto err_ah;
 	}
 
-	packet->msg->send_wr.wr.ud.timeout_ms  = packet->mad.hdr.timeout_ms;
-	packet->msg->send_wr.wr.ud.retries = packet->mad.hdr.retries;
+	packet->msg->ah 	= ah;
+	packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;
+	packet->msg->retries 	= packet->mad.hdr.retries;
+	packet->msg->context[0] = packet;
 
-	/* Override send WR WRID initialized in ib_create_send_mad */
-	packet->msg->send_wr.wr_id = (unsigned long) packet;
-
-	if (!rmpp_active) {
-		/* Copy message from user into send buffer */
-		if (copy_from_user(packet->msg->mad,
-				   buf + sizeof(struct ib_user_mad), length)) {
-			ret = -EFAULT;
-			goto err_msg;
-		}
-	} else {
-		rmpp_hdr_size = sizeof(struct ib_mad_hdr) +
-				sizeof(struct ib_rmpp_hdr);
-
-		/* Only copy MAD headers (RMPP header in place) */
-		memcpy(packet->msg->mad, packet->mad.data,
-		       sizeof(struct ib_mad_hdr));
-
-		/* Now, copy rest of message from user into send buffer */
-		if (copy_from_user(((struct ib_rmpp_mad *) packet->msg->mad)->data,
-				   buf + sizeof (struct ib_user_mad) + rmpp_hdr_size,
-				   length - rmpp_hdr_size)) {
-			ret = -EFAULT;
-			goto err_msg;
-		}
+	/* Copy MAD headers (RMPP header in place) */
+	memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR);
+	/* Now, copy rest of message from user into send buffer */
+	if (copy_from_user(packet->msg->mad + copy_offset,
+			   buf + sizeof (struct ib_user_mad) + copy_offset,
+			   length - copy_offset)) {
+		ret = -EFAULT;
+		goto err_msg;
 	}
 
 	/*
@@ -403,29 +405,29 @@
 	 * transaction ID matches the agent being used to send the
 	 * MAD.
 	 */
-	method = packet->msg->mad->mad_hdr.method;
+	method = ((struct ib_mad_hdr *) packet->msg->mad)->method;
 
 	if (!(method & IB_MGMT_METHOD_RESP)       &&
 	    method != IB_MGMT_METHOD_TRAP_REPRESS &&
 	    method != IB_MGMT_METHOD_SEND) {
-		tid = &packet->msg->mad->mad_hdr.tid;
+		tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;
 		*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
 				   (be64_to_cpup(tid) & 0xffffffff));
 	}
 
-	ret = ib_post_send_mad(agent, &packet->msg->send_wr, &bad_wr);
+	ret = ib_post_send_mad(packet->msg, NULL);
 	if (ret)
 		goto err_msg;
 
 	up_read(&file->agent_mutex);
 
-	return sizeof (struct ib_user_mad_hdr) + packet->length;
+	return count;
 
 err_msg:
 	ib_free_send_mad(packet->msg);
 
 err_ah:
-	ib_destroy_ah(packet->ah);
+	ib_destroy_ah(ah);
 
 err_up:
 	up_read(&file->agent_mutex);
@@ -565,15 +567,23 @@
 
 static int ib_umad_open(struct inode *inode, struct file *filp)
 {
-	struct ib_umad_port *port =
-		container_of(inode->i_cdev, struct ib_umad_port, dev);
+	struct ib_umad_port *port;
 	struct ib_umad_file *file;
 
-	file = kmalloc(sizeof *file, GFP_KERNEL);
-	if (!file)
-		return -ENOMEM;
+	spin_lock(&port_lock);
+	port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
+	if (port)
+		kref_get(&port->umad_dev->ref);
+	spin_unlock(&port_lock);
 
-	memset(file, 0, sizeof *file);
+	if (!port)
+		return -ENXIO;
+
+	file = kzalloc(sizeof *file, GFP_KERNEL);
+	if (!file) {
+		kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+		return -ENOMEM;
+	}
 
 	spin_lock_init(&file->recv_lock);
 	init_rwsem(&file->agent_mutex);
@@ -589,6 +599,7 @@
 static int ib_umad_close(struct inode *inode, struct file *filp)
 {
 	struct ib_umad_file *file = filp->private_data;
+	struct ib_umad_device *dev = file->port->umad_dev;
 	struct ib_umad_packet *packet, *tmp;
 	int i;
 
@@ -603,6 +614,8 @@
 
 	kfree(file);
 
+	kref_put(&dev->ref, ib_umad_release_dev);
+
 	return 0;
 }
 
@@ -619,30 +632,46 @@
 
 static int ib_umad_sm_open(struct inode *inode, struct file *filp)
 {
-	struct ib_umad_port *port =
-		container_of(inode->i_cdev, struct ib_umad_port, sm_dev);
+	struct ib_umad_port *port;
 	struct ib_port_modify props = {
 		.set_port_cap_mask = IB_PORT_SM
 	};
 	int ret;
 
+	spin_lock(&port_lock);
+	port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];
+	if (port)
+		kref_get(&port->umad_dev->ref);
+	spin_unlock(&port_lock);
+
+	if (!port)
+		return -ENXIO;
+
 	if (filp->f_flags & O_NONBLOCK) {
-		if (down_trylock(&port->sm_sem))
-			return -EAGAIN;
+		if (down_trylock(&port->sm_sem)) {
+			ret = -EAGAIN;
+			goto fail;
+		}
 	} else {
-		if (down_interruptible(&port->sm_sem))
-			return -ERESTARTSYS;
+		if (down_interruptible(&port->sm_sem)) {
+			ret = -ERESTARTSYS;
+			goto fail;
+		}
 	}
 
 	ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
 	if (ret) {
 		up(&port->sm_sem);
-		return ret;
+		goto fail;
 	}
 
 	filp->private_data = port;
 
 	return 0;
+
+fail:
+	kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+	return ret;
 }
 
 static int ib_umad_sm_close(struct inode *inode, struct file *filp)
@@ -656,6 +685,8 @@
 	ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
 	up(&port->sm_sem);
 
+	kref_put(&port->umad_dev->ref, ib_umad_release_dev);
+
 	return ret;
 }
 
@@ -671,21 +702,13 @@
 	.remove = ib_umad_remove_one
 };
 
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-	struct ib_umad_port *port = class_get_devdata(class_dev);
-
-	if (class_dev == &port->class_dev)
-		return print_dev_t(buf, port->dev.dev);
-	else
-		return print_dev_t(buf, port->sm_dev.dev);
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
 static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
 	struct ib_umad_port *port = class_get_devdata(class_dev);
 
+	if (!port)
+		return -ENODEV;
+
 	return sprintf(buf, "%s\n", port->ib_dev->name);
 }
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
@@ -694,38 +717,13 @@
 {
 	struct ib_umad_port *port = class_get_devdata(class_dev);
 
+	if (!port)
+		return -ENODEV;
+
 	return sprintf(buf, "%d\n", port->port_num);
 }
 static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
 
-static void ib_umad_release_dev(struct kref *ref)
-{
-	struct ib_umad_device *dev =
-		container_of(ref, struct ib_umad_device, ref);
-
-	kfree(dev);
-}
-
-static void ib_umad_release_port(struct class_device *class_dev)
-{
-	struct ib_umad_port *port = class_get_devdata(class_dev);
-
-	if (class_dev == &port->class_dev) {
-		cdev_del(&port->dev);
-		clear_bit(port->devnum, dev_map);
-	} else {
-		cdev_del(&port->sm_dev);
-		clear_bit(port->sm_devnum, dev_map);
-	}
-
-	kref_put(&port->umad_dev->ref, ib_umad_release_dev);
-}
-
-static struct class umad_class = {
-	.name    = "infiniband_mad",
-	.release = ib_umad_release_port
-};
-
 static ssize_t show_abi_version(struct class *class, char *buf)
 {
 	return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION);
@@ -735,91 +733,102 @@
 static int ib_umad_init_port(struct ib_device *device, int port_num,
 			     struct ib_umad_port *port)
 {
-	spin_lock(&map_lock);
-	port->devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
-	if (port->devnum >= IB_UMAD_MAX_PORTS) {
-		spin_unlock(&map_lock);
+	spin_lock(&port_lock);
+	port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
+	if (port->dev_num >= IB_UMAD_MAX_PORTS) {
+		spin_unlock(&port_lock);
 		return -1;
 	}
-	port->sm_devnum = find_next_zero_bit(dev_map, IB_UMAD_MAX_PORTS * 2, IB_UMAD_MAX_PORTS);
-	if (port->sm_devnum >= IB_UMAD_MAX_PORTS * 2) {
-		spin_unlock(&map_lock);
-		return -1;
-	}
-	set_bit(port->devnum, dev_map);
-	set_bit(port->sm_devnum, dev_map);
-	spin_unlock(&map_lock);
+	set_bit(port->dev_num, dev_map);
+	spin_unlock(&port_lock);
 
 	port->ib_dev   = device;
 	port->port_num = port_num;
 	init_MUTEX(&port->sm_sem);
 
-	cdev_init(&port->dev, &umad_fops);
-	port->dev.owner = THIS_MODULE;
-	kobject_set_name(&port->dev.kobj, "umad%d", port->devnum);
-	if (cdev_add(&port->dev, base_dev + port->devnum, 1))
+	port->dev = cdev_alloc();
+	if (!port->dev)
 		return -1;
-
-	port->class_dev.class = &umad_class;
-	port->class_dev.dev   = device->dma_device;
-
-	snprintf(port->class_dev.class_id, BUS_ID_SIZE, "umad%d", port->devnum);
-
-	if (class_device_register(&port->class_dev))
+	port->dev->owner = THIS_MODULE;
+	port->dev->ops   = &umad_fops;
+	kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);
+	if (cdev_add(port->dev, base_dev + port->dev_num, 1))
 		goto err_cdev;
 
-	class_set_devdata(&port->class_dev, port);
-	kref_get(&port->umad_dev->ref);
+	port->class_dev = class_device_create(umad_class, NULL, port->dev->dev,
+					      device->dma_device,
+					      "umad%d", port->dev_num);
+	if (IS_ERR(port->class_dev))
+		goto err_cdev;
 
-	if (class_device_create_file(&port->class_dev, &class_device_attr_dev))
+	if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))
 		goto err_class;
-	if (class_device_create_file(&port->class_dev, &class_device_attr_ibdev))
-		goto err_class;
-	if (class_device_create_file(&port->class_dev, &class_device_attr_port))
+	if (class_device_create_file(port->class_dev, &class_device_attr_port))
 		goto err_class;
 
-	cdev_init(&port->sm_dev, &umad_sm_fops);
-	port->sm_dev.owner = THIS_MODULE;
-	kobject_set_name(&port->dev.kobj, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
-	if (cdev_add(&port->sm_dev, base_dev + port->sm_devnum, 1))
-		return -1;
-
-	port->sm_class_dev.class = &umad_class;
-	port->sm_class_dev.dev   = device->dma_device;
-
-	snprintf(port->sm_class_dev.class_id, BUS_ID_SIZE, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);
-
-	if (class_device_register(&port->sm_class_dev))
+	port->sm_dev = cdev_alloc();
+	if (!port->sm_dev)
+		goto err_class;
+	port->sm_dev->owner = THIS_MODULE;
+	port->sm_dev->ops   = &umad_sm_fops;
+	kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num);
+	if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
 		goto err_sm_cdev;
 
-	class_set_devdata(&port->sm_class_dev, port);
-	kref_get(&port->umad_dev->ref);
+	port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev,
+						 device->dma_device,
+						 "issm%d", port->dev_num);
+	if (IS_ERR(port->sm_class_dev))
+		goto err_sm_cdev;
 
-	if (class_device_create_file(&port->sm_class_dev, &class_device_attr_dev))
+	class_set_devdata(port->class_dev,    port);
+	class_set_devdata(port->sm_class_dev, port);
+
+	if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))
 		goto err_sm_class;
-	if (class_device_create_file(&port->sm_class_dev, &class_device_attr_ibdev))
+	if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
 		goto err_sm_class;
-	if (class_device_create_file(&port->sm_class_dev, &class_device_attr_port))
-		goto err_sm_class;
+
+	spin_lock(&port_lock);
+	umad_port[port->dev_num] = port;
+	spin_unlock(&port_lock);
 
 	return 0;
 
 err_sm_class:
-	class_device_unregister(&port->sm_class_dev);
+	class_device_destroy(umad_class, port->sm_dev->dev);
 
 err_sm_cdev:
-	cdev_del(&port->sm_dev);
+	cdev_del(port->sm_dev);
 
 err_class:
-	class_device_unregister(&port->class_dev);
+	class_device_destroy(umad_class, port->dev->dev);
 
 err_cdev:
-	cdev_del(&port->dev);
-	clear_bit(port->devnum, dev_map);
+	cdev_del(port->dev);
+	clear_bit(port->dev_num, dev_map);
 
 	return -1;
 }
 
+static void ib_umad_kill_port(struct ib_umad_port *port)
+{
+	class_set_devdata(port->class_dev,    NULL);
+	class_set_devdata(port->sm_class_dev, NULL);
+
+	class_device_destroy(umad_class, port->dev->dev);
+	class_device_destroy(umad_class, port->sm_dev->dev);
+
+	cdev_del(port->dev);
+	cdev_del(port->sm_dev);
+
+	spin_lock(&port_lock);
+	umad_port[port->dev_num] = NULL;
+	spin_unlock(&port_lock);
+
+	clear_bit(port->dev_num, dev_map);
+}
+
 static void ib_umad_add_one(struct ib_device *device)
 {
 	struct ib_umad_device *umad_dev;
@@ -832,15 +841,12 @@
 		e = device->phys_port_cnt;
 	}
 
-	umad_dev = kmalloc(sizeof *umad_dev +
+	umad_dev = kzalloc(sizeof *umad_dev +
 			   (e - s + 1) * sizeof (struct ib_umad_port),
 			   GFP_KERNEL);
 	if (!umad_dev)
 		return;
 
-	memset(umad_dev, 0, sizeof *umad_dev +
-	       (e - s + 1) * sizeof (struct ib_umad_port));
-
 	kref_init(&umad_dev->ref);
 
 	umad_dev->start_port = s;
@@ -858,10 +864,8 @@
 	return;
 
 err:
-	while (--i >= s) {
-		class_device_unregister(&umad_dev->port[i - s].class_dev);
-		class_device_unregister(&umad_dev->port[i - s].sm_class_dev);
-	}
+	while (--i >= s)
+		ib_umad_kill_port(&umad_dev->port[i]);
 
 	kref_put(&umad_dev->ref, ib_umad_release_dev);
 }
@@ -874,10 +878,8 @@
 	if (!umad_dev)
 		return;
 
-	for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) {
-		class_device_unregister(&umad_dev->port[i].class_dev);
-		class_device_unregister(&umad_dev->port[i].sm_class_dev);
-	}
+	for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i)
+		ib_umad_kill_port(&umad_dev->port[i]);
 
 	kref_put(&umad_dev->ref, ib_umad_release_dev);
 }
@@ -886,8 +888,6 @@
 {
 	int ret;
 
-	spin_lock_init(&map_lock);
-
 	ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,
 				     "infiniband_mad");
 	if (ret) {
@@ -895,13 +895,14 @@
 		goto out;
 	}
 
-	ret = class_register(&umad_class);
-	if (ret) {
+	umad_class = class_create(THIS_MODULE, "infiniband_mad");
+	if (IS_ERR(umad_class)) {
+		ret = PTR_ERR(umad_class);
 		printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");
 		goto out_chrdev;
 	}
 
-	ret = class_create_file(&umad_class, &class_attr_abi_version);
+	ret = class_create_file(umad_class, &class_attr_abi_version);
 	if (ret) {
 		printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
 		goto out_class;
@@ -916,7 +917,7 @@
 	return 0;
 
 out_class:
-	class_unregister(&umad_class);
+	class_destroy(umad_class);
 
 out_chrdev:
 	unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
@@ -928,7 +929,7 @@
 static void __exit ib_umad_cleanup(void)
 {
 	ib_unregister_client(&umad_client);
-	class_unregister(&umad_class);
+	class_destroy(umad_class);
 	unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
 }
 
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index cc12434..031cdf3 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -3,6 +3,7 @@
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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
@@ -38,29 +39,47 @@
 #ifndef UVERBS_H
 #define UVERBS_H
 
-/* Include device.h and fs.h until cdev.h is self-sufficient */
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
 #include <linux/kref.h>
 #include <linux/idr.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
 
+/*
+ * Our lifetime rules for these structs are the following:
+ *
+ * struct ib_uverbs_device: One reference is held by the module and
+ * released in ib_uverbs_remove_one().  Another reference is taken by
+ * ib_uverbs_open() each time the character special file is opened,
+ * and released in ib_uverbs_release_file() when the file is released.
+ *
+ * struct ib_uverbs_file: One reference is held by the VFS and
+ * released when the file is closed.  Another reference is taken when
+ * an asynchronous event queue file is created and released when the
+ * event file is closed.
+ *
+ * struct ib_uverbs_event_file: One reference is held by the VFS and
+ * released when the file is closed.  For asynchronous event files,
+ * another reference is held by the corresponding main context file
+ * and released when that file is closed.  For completion event files,
+ * a reference is taken when a CQ is created that uses the file, and
+ * released when the CQ is destroyed.
+ */
+
 struct ib_uverbs_device {
+	struct kref				ref;
 	int					devnum;
-	struct cdev				dev;
-	struct class_device			class_dev;
+	struct cdev			       *dev;
+	struct class_device		       *class_dev;
 	struct ib_device		       *ib_dev;
-	int					num_comp;
+	int					num_comp_vectors;
 };
 
 struct ib_uverbs_event_file {
 	struct kref				ref;
+	struct file			       *file;
 	struct ib_uverbs_file		       *uverbs_file;
 	spinlock_t				lock;
-	int					fd;
 	int					is_async;
 	wait_queue_head_t			poll_wait;
 	struct fasync_struct		       *async_queue;
@@ -73,8 +92,7 @@
 	struct ib_uverbs_device		       *device;
 	struct ib_ucontext		       *ucontext;
 	struct ib_event_handler			event_handler;
-	struct ib_uverbs_event_file	        async_file;
-	struct ib_uverbs_event_file	        comp_file[1];
+	struct ib_uverbs_event_file	       *async_file;
 };
 
 struct ib_uverbs_event {
@@ -110,10 +128,23 @@
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
 
+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+					int is_async, int *fd);
+void ib_uverbs_release_event_file(struct kref *ref);
+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd);
+
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+			   struct ib_uverbs_event_file *ev_file,
+			   struct ib_ucq_object *uobj);
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+			      struct ib_uevent_object *uobj);
+
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_event_handler(struct ib_event_handler *handler,
+			     struct ib_event *event);
 
 int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
 		void *addr, size_t size, int write);
@@ -125,21 +156,26 @@
 				 const char __user *buf, int in_len,	\
 				 int out_len)
 
-IB_UVERBS_DECLARE_CMD(query_params);
 IB_UVERBS_DECLARE_CMD(get_context);
 IB_UVERBS_DECLARE_CMD(query_device);
 IB_UVERBS_DECLARE_CMD(query_port);
-IB_UVERBS_DECLARE_CMD(query_gid);
-IB_UVERBS_DECLARE_CMD(query_pkey);
 IB_UVERBS_DECLARE_CMD(alloc_pd);
 IB_UVERBS_DECLARE_CMD(dealloc_pd);
 IB_UVERBS_DECLARE_CMD(reg_mr);
 IB_UVERBS_DECLARE_CMD(dereg_mr);
+IB_UVERBS_DECLARE_CMD(create_comp_channel);
 IB_UVERBS_DECLARE_CMD(create_cq);
+IB_UVERBS_DECLARE_CMD(poll_cq);
+IB_UVERBS_DECLARE_CMD(req_notify_cq);
 IB_UVERBS_DECLARE_CMD(destroy_cq);
 IB_UVERBS_DECLARE_CMD(create_qp);
 IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
+IB_UVERBS_DECLARE_CMD(post_send);
+IB_UVERBS_DECLARE_CMD(post_recv);
+IB_UVERBS_DECLARE_CMD(post_srq_recv);
+IB_UVERBS_DECLARE_CMD(create_ah);
+IB_UVERBS_DECLARE_CMD(destroy_ah);
 IB_UVERBS_DECLARE_CMD(attach_mcast);
 IB_UVERBS_DECLARE_CMD(detach_mcast);
 IB_UVERBS_DECLARE_CMD(create_srq);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 5624451..8c89abc 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 PathScale, 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
@@ -33,6 +34,9 @@
  * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
  */
 
+#include <linux/file.h>
+#include <linux/fs.h>
+
 #include <asm/uaccess.h>
 
 #include "uverbs.h"
@@ -45,29 +49,6 @@
 		(udata)->outlen = (olen);				\
 	} while (0)
 
-ssize_t ib_uverbs_query_params(struct ib_uverbs_file *file,
-			       const char __user *buf,
-			       int in_len, int out_len)
-{
-	struct ib_uverbs_query_params      cmd;
-	struct ib_uverbs_query_params_resp resp;
-
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	memset(&resp, 0, sizeof resp);
-
-	resp.num_cq_events = file->device->num_comp;
-
-	if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp))
-	    return -EFAULT;
-
-	return in_len;
-}
-
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 			      const char __user *buf,
 			      int in_len, int out_len)
@@ -77,7 +58,7 @@
 	struct ib_udata                   udata;
 	struct ib_device                 *ibdev = file->device->ib_dev;
 	struct ib_ucontext		 *ucontext;
-	int i;
+	struct file			 *filp;
 	int ret;
 
 	if (out_len < sizeof resp)
@@ -110,26 +91,42 @@
 	INIT_LIST_HEAD(&ucontext->srq_list);
 	INIT_LIST_HEAD(&ucontext->ah_list);
 
-	resp.async_fd = file->async_file.fd;
-	for (i = 0; i < file->device->num_comp; ++i)
-		if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
-				 i * sizeof (__u32),
-				 &file->comp_file[i].fd, sizeof (__u32))) {
-			ret = -EFAULT;
-			goto err_free;
-		}
+	resp.num_comp_vectors = file->device->num_comp_vectors;
+
+	filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
+	if (IS_ERR(filp)) {
+		ret = PTR_ERR(filp);
+		goto err_free;
+	}
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_free;
+		goto err_file;
 	}
 
+	file->async_file = filp->private_data;
+
+	INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev,
+			      ib_uverbs_event_handler);
+	ret = ib_register_event_handler(&file->event_handler);
+	if (ret)
+		goto err_file;
+
+	kref_get(&file->async_file->ref);
+	kref_get(&file->ref);
 	file->ucontext = ucontext;
+
+	fd_install(resp.async_fd, filp);
+
 	up(&file->mutex);
 
 	return in_len;
 
+err_file:
+	put_unused_fd(resp.async_fd);
+	fput(filp);
+
 err_free:
 	ibdev->dealloc_ucontext(ucontext);
 
@@ -255,62 +252,6 @@
 	return in_len;
 }
 
-ssize_t ib_uverbs_query_gid(struct ib_uverbs_file *file,
-			    const char __user *buf,
-			    int in_len, int out_len)
-{
-	struct ib_uverbs_query_gid      cmd;
-	struct ib_uverbs_query_gid_resp resp;
-	int                             ret;
-
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	memset(&resp, 0, sizeof resp);
-
-	ret = ib_query_gid(file->device->ib_dev, cmd.port_num, cmd.index,
-			   (union ib_gid *) resp.gid);
-	if (ret)
-		return ret;
-
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
-			 &resp, sizeof resp))
-		return -EFAULT;
-
-	return in_len;
-}
-
-ssize_t ib_uverbs_query_pkey(struct ib_uverbs_file *file,
-			     const char __user *buf,
-			     int in_len, int out_len)
-{
-	struct ib_uverbs_query_pkey      cmd;
-	struct ib_uverbs_query_pkey_resp resp;
-	int                              ret;
-
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	memset(&resp, 0, sizeof resp);
-
-	ret = ib_query_pkey(file->device->ib_dev, cmd.port_num, cmd.index,
-			    &resp.pkey);
-	if (ret)
-		return ret;
-
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
-			 &resp, sizeof resp))
-		return -EFAULT;
-
-	return in_len;
-}
-
 ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
 			   const char __user *buf,
 			   int in_len, int out_len)
@@ -349,24 +290,20 @@
 	pd->uobject = uobj;
 	atomic_set(&pd->usecnt, 0);
 
+	down(&ib_uverbs_idr_mutex);
+
 retry:
 	if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
 		ret = -ENOMEM;
-		goto err_pd;
+		goto err_up;
 	}
 
-	down(&ib_uverbs_idr_mutex);
 	ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
-	up(&ib_uverbs_idr_mutex);
 
 	if (ret == -EAGAIN)
 		goto retry;
 	if (ret)
-		goto err_pd;
-
-	down(&file->mutex);
-	list_add_tail(&uobj->list, &file->ucontext->pd_list);
-	up(&file->mutex);
+		goto err_up;
 
 	memset(&resp, 0, sizeof resp);
 	resp.pd_handle = uobj->id;
@@ -374,21 +311,22 @@
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_list;
+		goto err_idr;
 	}
 
+	down(&file->mutex);
+	list_add_tail(&uobj->list, &file->ucontext->pd_list);
+	up(&file->mutex);
+
+	up(&ib_uverbs_idr_mutex);
+
 	return in_len;
 
-err_list:
- 	down(&file->mutex);
-	list_del(&uobj->list);
-	up(&file->mutex);
-
-	down(&ib_uverbs_idr_mutex);
+err_idr:
 	idr_remove(&ib_uverbs_pd_idr, uobj->id);
-	up(&ib_uverbs_idr_mutex);
 
-err_pd:
+err_up:
+	up(&ib_uverbs_idr_mutex);
 	ib_dealloc_pd(pd);
 
 err:
@@ -459,6 +397,14 @@
 	if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
 		return -EINVAL;
 
+	/*
+	 * Local write permission is required if remote write or
+	 * remote atomic permission is also requested.
+	 */
+	if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&
+	    !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))
+		return -EINVAL;
+
 	obj = kmalloc(sizeof *obj, GFP_KERNEL);
 	if (!obj)
 		return -ENOMEM;
@@ -524,24 +470,22 @@
 
 	resp.mr_handle = obj->uobject.id;
 
-	down(&file->mutex);
-	list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
-	up(&file->mutex);
-
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_list;
+		goto err_idr;
 	}
 
+	down(&file->mutex);
+	list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
+	up(&file->mutex);
+
 	up(&ib_uverbs_idr_mutex);
 
 	return in_len;
 
-err_list:
-	down(&file->mutex);
-	list_del(&obj->uobject.list);
-	up(&file->mutex);
+err_idr:
+	idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);
 
 err_unreg:
 	ib_dereg_mr(mr);
@@ -595,6 +539,35 @@
 	return ret ? ret : in_len;
 }
 
+ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
+				      const char __user *buf, int in_len,
+				      int out_len)
+{
+	struct ib_uverbs_create_comp_channel	   cmd;
+	struct ib_uverbs_create_comp_channel_resp  resp;
+	struct file				  *filp;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
+	if (IS_ERR(filp))
+		return PTR_ERR(filp);
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		put_unused_fd(resp.fd);
+		fput(filp);
+		return -EFAULT;
+	}
+
+	fd_install(resp.fd, filp);
+	return in_len;
+}
+
 ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
 			    const char __user *buf, int in_len,
 			    int out_len)
@@ -603,6 +576,7 @@
 	struct ib_uverbs_create_cq_resp resp;
 	struct ib_udata                 udata;
 	struct ib_ucq_object           *uobj;
+	struct ib_uverbs_event_file    *ev_file = NULL;
 	struct ib_cq                   *cq;
 	int                             ret;
 
@@ -616,9 +590,12 @@
 		   (unsigned long) cmd.response + sizeof resp,
 		   in_len - sizeof cmd, out_len - sizeof resp);
 
-	if (cmd.event_handler >= file->device->num_comp)
+	if (cmd.comp_vector >= file->device->num_comp_vectors)
 		return -EINVAL;
 
+	if (cmd.comp_channel >= 0)
+		ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
+
 	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
 	if (!uobj)
 		return -ENOMEM;
@@ -641,27 +618,23 @@
 	cq->uobject       = &uobj->uobject;
 	cq->comp_handler  = ib_uverbs_comp_handler;
 	cq->event_handler = ib_uverbs_cq_event_handler;
-	cq->cq_context    = file;
+	cq->cq_context    = ev_file;
 	atomic_set(&cq->usecnt, 0);
 
+	down(&ib_uverbs_idr_mutex);
+
 retry:
 	if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
 		ret = -ENOMEM;
-		goto err_cq;
+		goto err_up;
 	}
 
-	down(&ib_uverbs_idr_mutex);
 	ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
-	up(&ib_uverbs_idr_mutex);
 
 	if (ret == -EAGAIN)
 		goto retry;
 	if (ret)
-		goto err_cq;
-
-	down(&file->mutex);
-	list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
-	up(&file->mutex);
+		goto err_up;
 
 	memset(&resp, 0, sizeof resp);
 	resp.cq_handle = uobj->uobject.id;
@@ -670,21 +643,22 @@
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_list;
+		goto err_idr;
 	}
 
+	down(&file->mutex);
+	list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
+	up(&file->mutex);
+
+	up(&ib_uverbs_idr_mutex);
+
 	return in_len;
 
-err_list:
- 	down(&file->mutex);
-	list_del(&uobj->uobject.list);
-	up(&file->mutex);
-
-	down(&ib_uverbs_idr_mutex);
+err_idr:
 	idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
-	up(&ib_uverbs_idr_mutex);
 
-err_cq:
+err_up:
+	up(&ib_uverbs_idr_mutex);
 	ib_destroy_cq(cq);
 
 err:
@@ -692,6 +666,93 @@
 	return ret;
 }
 
+ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
+			  const char __user *buf, int in_len,
+			  int out_len)
+{
+	struct ib_uverbs_poll_cq       cmd;
+	struct ib_uverbs_poll_cq_resp *resp;
+	struct ib_cq                  *cq;
+	struct ib_wc                  *wc;
+	int                            ret = 0;
+	int                            i;
+	int                            rsize;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
+	if (!wc)
+		return -ENOMEM;
+
+	rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
+	resp = kmalloc(rsize, GFP_KERNEL);
+	if (!resp) {
+		ret = -ENOMEM;
+		goto out_wc;
+	}
+
+	down(&ib_uverbs_idr_mutex);
+	cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+	if (!cq || cq->uobject->context != file->ucontext) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	resp->count = ib_poll_cq(cq, cmd.ne, wc);
+
+	for (i = 0; i < resp->count; i++) {
+		resp->wc[i].wr_id 	   = wc[i].wr_id;
+		resp->wc[i].status 	   = wc[i].status;
+		resp->wc[i].opcode 	   = wc[i].opcode;
+		resp->wc[i].vendor_err 	   = wc[i].vendor_err;
+		resp->wc[i].byte_len 	   = wc[i].byte_len;
+		resp->wc[i].imm_data 	   = wc[i].imm_data;
+		resp->wc[i].qp_num 	   = wc[i].qp_num;
+		resp->wc[i].src_qp 	   = wc[i].src_qp;
+		resp->wc[i].wc_flags 	   = wc[i].wc_flags;
+		resp->wc[i].pkey_index 	   = wc[i].pkey_index;
+		resp->wc[i].slid 	   = wc[i].slid;
+		resp->wc[i].sl 		   = wc[i].sl;
+		resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
+		resp->wc[i].port_num 	   = wc[i].port_num;
+	}
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+		ret = -EFAULT;
+
+out:
+	up(&ib_uverbs_idr_mutex);
+	kfree(resp);
+
+out_wc:
+	kfree(wc);
+	return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
+				const char __user *buf, int in_len,
+				int out_len)
+{
+	struct ib_uverbs_req_notify_cq cmd;
+	struct ib_cq                  *cq;
+	int                            ret = -EINVAL;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	down(&ib_uverbs_idr_mutex);
+	cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+	if (cq && cq->uobject->context == file->ucontext) {
+		ib_req_notify_cq(cq, cmd.solicited_only ?
+					IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
+		ret = in_len;
+	}
+	up(&ib_uverbs_idr_mutex);
+
+	return ret;
+}
+
 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
 			     const char __user *buf, int in_len,
 			     int out_len)
@@ -700,7 +761,7 @@
 	struct ib_uverbs_destroy_cq_resp resp;
 	struct ib_cq               	*cq;
 	struct ib_ucq_object        	*uobj;
-	struct ib_uverbs_event		*evt, *tmp;
+	struct ib_uverbs_event_file	*ev_file;
 	u64				 user_handle;
 	int                        	 ret = -EINVAL;
 
@@ -716,7 +777,8 @@
 		goto out;
 
 	user_handle = cq->uobject->user_handle;
-	uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
+	uobj        = container_of(cq->uobject, struct ib_ucq_object, uobject);
+	ev_file     = cq->cq_context;
 
 	ret = ib_destroy_cq(cq);
 	if (ret)
@@ -728,19 +790,7 @@
 	list_del(&uobj->uobject.list);
 	up(&file->mutex);
 
-	spin_lock_irq(&file->comp_file[0].lock);
-	list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
-		list_del(&evt->list);
-		kfree(evt);
-	}
-	spin_unlock_irq(&file->comp_file[0].lock);
-
-	spin_lock_irq(&file->async_file.lock);
-	list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
-		list_del(&evt->list);
-		kfree(evt);
-	}
-	spin_unlock_irq(&file->async_file.lock);
+	ib_uverbs_release_ucq(file, ev_file, uobj);
 
 	resp.comp_events_reported  = uobj->comp_events_reported;
 	resp.async_events_reported = uobj->async_events_reported;
@@ -859,24 +909,22 @@
 
 	resp.qp_handle = uobj->uobject.id;
 
-	down(&file->mutex);
-	list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
-	up(&file->mutex);
-
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_list;
+		goto err_idr;
 	}
 
+	down(&file->mutex);
+	list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
+	up(&file->mutex);
+
 	up(&ib_uverbs_idr_mutex);
 
 	return in_len;
 
-err_list:
-	down(&file->mutex);
-	list_del(&uobj->uobject.list);
-	up(&file->mutex);
+err_idr:
+	idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id);
 
 err_destroy:
 	ib_destroy_qp(qp);
@@ -979,7 +1027,6 @@
 	struct ib_uverbs_destroy_qp_resp resp;
 	struct ib_qp               	*qp;
 	struct ib_uevent_object        	*uobj;
-	struct ib_uverbs_event		*evt, *tmp;
 	int                        	 ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1005,12 +1052,7 @@
 	list_del(&uobj->uobject.list);
 	up(&file->mutex);
 
-	spin_lock_irq(&file->async_file.lock);
-	list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
-		list_del(&evt->list);
-		kfree(evt);
-	}
-	spin_unlock_irq(&file->async_file.lock);
+	ib_uverbs_release_uevent(file, uobj);
 
 	resp.events_reported = uobj->events_reported;
 
@@ -1026,6 +1068,468 @@
 	return ret ? ret : in_len;
 }
 
+ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+	struct ib_uverbs_post_send      cmd;
+	struct ib_uverbs_post_send_resp resp;
+	struct ib_uverbs_send_wr       *user_wr;
+	struct ib_send_wr              *wr = NULL, *last, *next, *bad_wr;
+	struct ib_qp                   *qp;
+	int                             i, sg_ind;
+	ssize_t                         ret = -EINVAL;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +
+	    cmd.sge_count * sizeof (struct ib_uverbs_sge))
+		return -EINVAL;
+
+	if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))
+		return -EINVAL;
+
+	user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);
+	if (!user_wr)
+		return -ENOMEM;
+
+	down(&ib_uverbs_idr_mutex);
+
+	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+	if (!qp || qp->uobject->context != file->ucontext)
+		goto out;
+
+	sg_ind = 0;
+	last = NULL;
+	for (i = 0; i < cmd.wr_count; ++i) {
+		if (copy_from_user(user_wr,
+				   buf + sizeof cmd + i * cmd.wqe_size,
+				   cmd.wqe_size)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		if (user_wr->num_sge + sg_ind > cmd.sge_count) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
+			       user_wr->num_sge * sizeof (struct ib_sge),
+			       GFP_KERNEL);
+		if (!next) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		if (!last)
+			wr = next;
+		else
+			last->next = next;
+		last = next;
+
+		next->next       = NULL;
+		next->wr_id      = user_wr->wr_id;
+		next->num_sge    = user_wr->num_sge;
+		next->opcode     = user_wr->opcode;
+		next->send_flags = user_wr->send_flags;
+		next->imm_data   = user_wr->imm_data;
+
+		if (qp->qp_type == IB_QPT_UD) {
+			next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,
+						  user_wr->wr.ud.ah);
+			if (!next->wr.ud.ah) {
+				ret = -EINVAL;
+				goto out;
+			}
+			next->wr.ud.remote_qpn  = user_wr->wr.ud.remote_qpn;
+			next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
+		} else {
+			switch (next->opcode) {
+			case IB_WR_RDMA_WRITE:
+			case IB_WR_RDMA_WRITE_WITH_IMM:
+			case IB_WR_RDMA_READ:
+				next->wr.rdma.remote_addr =
+					user_wr->wr.rdma.remote_addr;
+				next->wr.rdma.rkey        =
+					user_wr->wr.rdma.rkey;
+				break;
+			case IB_WR_ATOMIC_CMP_AND_SWP:
+			case IB_WR_ATOMIC_FETCH_AND_ADD:
+				next->wr.atomic.remote_addr =
+					user_wr->wr.atomic.remote_addr;
+				next->wr.atomic.compare_add =
+					user_wr->wr.atomic.compare_add;
+				next->wr.atomic.swap = user_wr->wr.atomic.swap;
+				next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (next->num_sge) {
+			next->sg_list = (void *) next +
+				ALIGN(sizeof *next, sizeof (struct ib_sge));
+			if (copy_from_user(next->sg_list,
+					   buf + sizeof cmd +
+					   cmd.wr_count * cmd.wqe_size +
+					   sg_ind * sizeof (struct ib_sge),
+					   next->num_sge * sizeof (struct ib_sge))) {
+				ret = -EFAULT;
+				goto out;
+			}
+			sg_ind += next->num_sge;
+		} else
+			next->sg_list = NULL;
+	}
+
+	resp.bad_wr = 0;
+	ret = qp->device->post_send(qp, wr, &bad_wr);
+	if (ret)
+		for (next = wr; next; next = next->next) {
+			++resp.bad_wr;
+			if (next == bad_wr)
+				break;
+		}
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp))
+		ret = -EFAULT;
+
+out:
+	up(&ib_uverbs_idr_mutex);
+
+	while (wr) {
+		next = wr->next;
+		kfree(wr);
+		wr = next;
+	}
+
+	kfree(user_wr);
+
+	return ret ? ret : in_len;
+}
+
+static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,
+						    int in_len,
+						    u32 wr_count,
+						    u32 sge_count,
+						    u32 wqe_size)
+{
+	struct ib_uverbs_recv_wr *user_wr;
+	struct ib_recv_wr        *wr = NULL, *last, *next;
+	int                       sg_ind;
+	int                       i;
+	int                       ret;
+
+	if (in_len < wqe_size * wr_count +
+	    sge_count * sizeof (struct ib_uverbs_sge))
+		return ERR_PTR(-EINVAL);
+
+	if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
+		return ERR_PTR(-EINVAL);
+
+	user_wr = kmalloc(wqe_size, GFP_KERNEL);
+	if (!user_wr)
+		return ERR_PTR(-ENOMEM);
+
+	sg_ind = 0;
+	last = NULL;
+	for (i = 0; i < wr_count; ++i) {
+		if (copy_from_user(user_wr, buf + i * wqe_size,
+				   wqe_size)) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		if (user_wr->num_sge + sg_ind > sge_count) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
+			       user_wr->num_sge * sizeof (struct ib_sge),
+			       GFP_KERNEL);
+		if (!next) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		if (!last)
+			wr = next;
+		else
+			last->next = next;
+		last = next;
+
+		next->next       = NULL;
+		next->wr_id      = user_wr->wr_id;
+		next->num_sge    = user_wr->num_sge;
+
+		if (next->num_sge) {
+			next->sg_list = (void *) next +
+				ALIGN(sizeof *next, sizeof (struct ib_sge));
+			if (copy_from_user(next->sg_list,
+					   buf + wr_count * wqe_size +
+					   sg_ind * sizeof (struct ib_sge),
+					   next->num_sge * sizeof (struct ib_sge))) {
+				ret = -EFAULT;
+				goto err;
+			}
+			sg_ind += next->num_sge;
+		} else
+			next->sg_list = NULL;
+	}
+
+	kfree(user_wr);
+	return wr;
+
+err:
+	kfree(user_wr);
+
+	while (wr) {
+		next = wr->next;
+		kfree(wr);
+		wr = next;
+	}
+
+	return ERR_PTR(ret);
+}
+
+ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+	struct ib_uverbs_post_recv      cmd;
+	struct ib_uverbs_post_recv_resp resp;
+	struct ib_recv_wr              *wr, *next, *bad_wr;
+	struct ib_qp                   *qp;
+	ssize_t                         ret = -EINVAL;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
+				       in_len - sizeof cmd, cmd.wr_count,
+				       cmd.sge_count, cmd.wqe_size);
+	if (IS_ERR(wr))
+		return PTR_ERR(wr);
+
+	down(&ib_uverbs_idr_mutex);
+
+	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+	if (!qp || qp->uobject->context != file->ucontext)
+		goto out;
+
+	resp.bad_wr = 0;
+	ret = qp->device->post_recv(qp, wr, &bad_wr);
+	if (ret)
+		for (next = wr; next; next = next->next) {
+			++resp.bad_wr;
+			if (next == bad_wr)
+				break;
+		}
+
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp))
+		ret = -EFAULT;
+
+out:
+	up(&ib_uverbs_idr_mutex);
+
+	while (wr) {
+		next = wr->next;
+		kfree(wr);
+		wr = next;
+	}
+
+	return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+	struct ib_uverbs_post_srq_recv      cmd;
+	struct ib_uverbs_post_srq_recv_resp resp;
+	struct ib_recv_wr                  *wr, *next, *bad_wr;
+	struct ib_srq                      *srq;
+	ssize_t                             ret = -EINVAL;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
+				       in_len - sizeof cmd, cmd.wr_count,
+				       cmd.sge_count, cmd.wqe_size);
+	if (IS_ERR(wr))
+		return PTR_ERR(wr);
+
+	down(&ib_uverbs_idr_mutex);
+
+	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+	if (!srq || srq->uobject->context != file->ucontext)
+		goto out;
+
+	resp.bad_wr = 0;
+	ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
+	if (ret)
+		for (next = wr; next; next = next->next) {
+			++resp.bad_wr;
+			if (next == bad_wr)
+				break;
+		}
+
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp))
+		ret = -EFAULT;
+
+out:
+	up(&ib_uverbs_idr_mutex);
+
+	while (wr) {
+		next = wr->next;
+		kfree(wr);
+		wr = next;
+	}
+
+	return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
+			    const char __user *buf, int in_len,
+			    int out_len)
+{
+	struct ib_uverbs_create_ah	 cmd;
+	struct ib_uverbs_create_ah_resp	 resp;
+	struct ib_uobject		*uobj;
+	struct ib_pd			*pd;
+	struct ib_ah			*ah;
+	struct ib_ah_attr		attr;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+	if (!uobj)
+		return -ENOMEM;
+
+	down(&ib_uverbs_idr_mutex);
+
+	pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+	if (!pd || pd->uobject->context != file->ucontext) {
+		ret = -EINVAL;
+		goto err_up;
+	}
+
+	uobj->user_handle = cmd.user_handle;
+	uobj->context     = file->ucontext;
+
+	attr.dlid 	       = cmd.attr.dlid;
+	attr.sl 	       = cmd.attr.sl;
+	attr.src_path_bits     = cmd.attr.src_path_bits;
+	attr.static_rate       = cmd.attr.static_rate;
+	attr.port_num 	       = cmd.attr.port_num;
+	attr.grh.flow_label    = cmd.attr.grh.flow_label;
+	attr.grh.sgid_index    = cmd.attr.grh.sgid_index;
+	attr.grh.hop_limit     = cmd.attr.grh.hop_limit;
+	attr.grh.traffic_class = cmd.attr.grh.traffic_class;
+	memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
+
+	ah = ib_create_ah(pd, &attr);
+	if (IS_ERR(ah)) {
+		ret = PTR_ERR(ah);
+		goto err_up;
+	}
+
+	ah->uobject = uobj;
+
+retry:
+	if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto err_destroy;
+	}
+
+	ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);
+
+	if (ret == -EAGAIN)
+		goto retry;
+	if (ret)
+		goto err_destroy;
+
+	resp.ah_handle = uobj->id;
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_idr;
+	}
+
+	down(&file->mutex);
+	list_add_tail(&uobj->list, &file->ucontext->ah_list);
+	up(&file->mutex);
+
+	up(&ib_uverbs_idr_mutex);
+
+	return in_len;
+
+err_idr:
+	idr_remove(&ib_uverbs_ah_idr, uobj->id);
+
+err_destroy:
+	ib_destroy_ah(ah);
+
+err_up:
+	up(&ib_uverbs_idr_mutex);
+
+	kfree(uobj);
+	return ret;
+}
+
+ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_destroy_ah cmd;
+	struct ib_ah		   *ah;
+	struct ib_uobject	   *uobj;
+	int			    ret = -EINVAL;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	down(&ib_uverbs_idr_mutex);
+
+	ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
+	if (!ah || ah->uobject->context != file->ucontext)
+		goto out;
+
+	uobj = ah->uobject;
+
+	ret = ib_destroy_ah(ah);
+	if (ret)
+		goto out;
+
+	idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
+
+	down(&file->mutex);
+	list_del(&uobj->list);
+	up(&file->mutex);
+
+	kfree(uobj);
+
+out:
+	up(&ib_uverbs_idr_mutex);
+
+	return ret ? ret : in_len;
+}
+
 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
 			       const char __user *buf, int in_len,
 			       int out_len)
@@ -1148,24 +1652,22 @@
 
 	resp.srq_handle = uobj->uobject.id;
 
-	down(&file->mutex);
-	list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
-	up(&file->mutex);
-
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_list;
+		goto err_idr;
 	}
 
+	down(&file->mutex);
+	list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+	up(&file->mutex);
+
 	up(&ib_uverbs_idr_mutex);
 
 	return in_len;
 
-err_list:
-	down(&file->mutex);
-	list_del(&uobj->uobject.list);
-	up(&file->mutex);
+err_idr:
+	idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);
 
 err_destroy:
 	ib_destroy_srq(srq);
@@ -1217,7 +1719,6 @@
 	struct ib_uverbs_destroy_srq_resp resp;
 	struct ib_srq               	 *srq;
 	struct ib_uevent_object        	 *uobj;
-	struct ib_uverbs_event		 *evt, *tmp;
 	int                         	  ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1243,12 +1744,7 @@
 	list_del(&uobj->uobject.list);
 	up(&file->mutex);
 
-	spin_lock_irq(&file->async_file.lock);
-	list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
-		list_del(&evt->list);
-		kfree(evt);
-	}
-	spin_unlock_irq(&file->async_file.lock);
+	ib_uverbs_release_uevent(file, uobj);
 
 	resp.events_reported = uobj->events_reported;
 
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 1251180..0eb38f4 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005 PathScale, 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
@@ -43,6 +44,7 @@
 #include <linux/poll.h>
 #include <linux/file.h>
 #include <linux/mount.h>
+#include <linux/cdev.h>
 
 #include <asm/uaccess.h>
 
@@ -62,6 +64,8 @@
 
 #define IB_UVERBS_BASE_DEV	MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
 
+static struct class *uverbs_class;
+
 DECLARE_MUTEX(ib_uverbs_idr_mutex);
 DEFINE_IDR(ib_uverbs_pd_idr);
 DEFINE_IDR(ib_uverbs_mr_idr);
@@ -72,31 +76,37 @@
 DEFINE_IDR(ib_uverbs_srq_idr);
 
 static spinlock_t map_lock;
+static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
 
 static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
 				     const char __user *buf, int in_len,
 				     int out_len) = {
-	[IB_USER_VERBS_CMD_QUERY_PARAMS]  = ib_uverbs_query_params,
-	[IB_USER_VERBS_CMD_GET_CONTEXT]   = ib_uverbs_get_context,
-	[IB_USER_VERBS_CMD_QUERY_DEVICE]  = ib_uverbs_query_device,
-	[IB_USER_VERBS_CMD_QUERY_PORT]    = ib_uverbs_query_port,
-	[IB_USER_VERBS_CMD_QUERY_GID]     = ib_uverbs_query_gid,
-	[IB_USER_VERBS_CMD_QUERY_PKEY]    = ib_uverbs_query_pkey,
-	[IB_USER_VERBS_CMD_ALLOC_PD]      = ib_uverbs_alloc_pd,
-	[IB_USER_VERBS_CMD_DEALLOC_PD]    = ib_uverbs_dealloc_pd,
-	[IB_USER_VERBS_CMD_REG_MR]        = ib_uverbs_reg_mr,
-	[IB_USER_VERBS_CMD_DEREG_MR]      = ib_uverbs_dereg_mr,
-	[IB_USER_VERBS_CMD_CREATE_CQ]     = ib_uverbs_create_cq,
-	[IB_USER_VERBS_CMD_DESTROY_CQ]    = ib_uverbs_destroy_cq,
-	[IB_USER_VERBS_CMD_CREATE_QP]     = ib_uverbs_create_qp,
-	[IB_USER_VERBS_CMD_MODIFY_QP]     = ib_uverbs_modify_qp,
-	[IB_USER_VERBS_CMD_DESTROY_QP]    = ib_uverbs_destroy_qp,
-	[IB_USER_VERBS_CMD_ATTACH_MCAST]  = ib_uverbs_attach_mcast,
-	[IB_USER_VERBS_CMD_DETACH_MCAST]  = ib_uverbs_detach_mcast,
-	[IB_USER_VERBS_CMD_CREATE_SRQ]    = ib_uverbs_create_srq,
-	[IB_USER_VERBS_CMD_MODIFY_SRQ]    = ib_uverbs_modify_srq,
-	[IB_USER_VERBS_CMD_DESTROY_SRQ]   = ib_uverbs_destroy_srq,
+	[IB_USER_VERBS_CMD_GET_CONTEXT]   	= ib_uverbs_get_context,
+	[IB_USER_VERBS_CMD_QUERY_DEVICE]  	= ib_uverbs_query_device,
+	[IB_USER_VERBS_CMD_QUERY_PORT]    	= ib_uverbs_query_port,
+	[IB_USER_VERBS_CMD_ALLOC_PD]      	= ib_uverbs_alloc_pd,
+	[IB_USER_VERBS_CMD_DEALLOC_PD]    	= ib_uverbs_dealloc_pd,
+	[IB_USER_VERBS_CMD_REG_MR]        	= ib_uverbs_reg_mr,
+	[IB_USER_VERBS_CMD_DEREG_MR]      	= ib_uverbs_dereg_mr,
+	[IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
+	[IB_USER_VERBS_CMD_CREATE_CQ]     	= ib_uverbs_create_cq,
+	[IB_USER_VERBS_CMD_POLL_CQ]     	= ib_uverbs_poll_cq,
+	[IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]     	= ib_uverbs_req_notify_cq,
+	[IB_USER_VERBS_CMD_DESTROY_CQ]    	= ib_uverbs_destroy_cq,
+	[IB_USER_VERBS_CMD_CREATE_QP]     	= ib_uverbs_create_qp,
+	[IB_USER_VERBS_CMD_MODIFY_QP]     	= ib_uverbs_modify_qp,
+	[IB_USER_VERBS_CMD_DESTROY_QP]    	= ib_uverbs_destroy_qp,
+	[IB_USER_VERBS_CMD_POST_SEND]    	= ib_uverbs_post_send,
+	[IB_USER_VERBS_CMD_POST_RECV]    	= ib_uverbs_post_recv,
+	[IB_USER_VERBS_CMD_POST_SRQ_RECV]    	= ib_uverbs_post_srq_recv,
+	[IB_USER_VERBS_CMD_CREATE_AH]    	= ib_uverbs_create_ah,
+	[IB_USER_VERBS_CMD_DESTROY_AH]    	= ib_uverbs_destroy_ah,
+	[IB_USER_VERBS_CMD_ATTACH_MCAST]  	= ib_uverbs_attach_mcast,
+	[IB_USER_VERBS_CMD_DETACH_MCAST]  	= ib_uverbs_detach_mcast,
+	[IB_USER_VERBS_CMD_CREATE_SRQ]    	= ib_uverbs_create_srq,
+	[IB_USER_VERBS_CMD_MODIFY_SRQ]    	= ib_uverbs_modify_srq,
+	[IB_USER_VERBS_CMD_DESTROY_SRQ]   	= ib_uverbs_destroy_srq,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -104,7 +114,54 @@
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device);
 
-static int ib_dealloc_ucontext(struct ib_ucontext *context)
+static void ib_uverbs_release_dev(struct kref *ref)
+{
+	struct ib_uverbs_device *dev =
+		container_of(ref, struct ib_uverbs_device, ref);
+
+	kfree(dev);
+}
+
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+			  struct ib_uverbs_event_file *ev_file,
+			  struct ib_ucq_object *uobj)
+{
+	struct ib_uverbs_event *evt, *tmp;
+
+	if (ev_file) {
+		spin_lock_irq(&ev_file->lock);
+		list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
+			list_del(&evt->list);
+			kfree(evt);
+		}
+		spin_unlock_irq(&ev_file->lock);
+
+		kref_put(&ev_file->ref, ib_uverbs_release_event_file);
+	}
+
+	spin_lock_irq(&file->async_file->lock);
+	list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
+		list_del(&evt->list);
+		kfree(evt);
+	}
+	spin_unlock_irq(&file->async_file->lock);
+}
+
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+			      struct ib_uevent_object *uobj)
+{
+	struct ib_uverbs_event *evt, *tmp;
+
+	spin_lock_irq(&file->async_file->lock);
+	list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+		list_del(&evt->list);
+		kfree(evt);
+	}
+	spin_unlock_irq(&file->async_file->lock);
+}
+
+static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
+				      struct ib_ucontext *context)
 {
 	struct ib_uobject *uobj, *tmp;
 
@@ -113,30 +170,46 @@
 
 	down(&ib_uverbs_idr_mutex);
 
-	/* XXX Free AHs */
+	list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
+		struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
+		idr_remove(&ib_uverbs_ah_idr, uobj->id);
+		ib_destroy_ah(ah);
+		list_del(&uobj->list);
+		kfree(uobj);
+	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
 		struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
+		struct ib_uevent_object *uevent =
+			container_of(uobj, struct ib_uevent_object, uobject);
 		idr_remove(&ib_uverbs_qp_idr, uobj->id);
 		ib_destroy_qp(qp);
 		list_del(&uobj->list);
-		kfree(container_of(uobj, struct ib_uevent_object, uobject));
+		ib_uverbs_release_uevent(file, uevent);
+		kfree(uevent);
 	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
 		struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
+		struct ib_uverbs_event_file *ev_file = cq->cq_context;
+		struct ib_ucq_object *ucq =
+			container_of(uobj, struct ib_ucq_object, uobject);
 		idr_remove(&ib_uverbs_cq_idr, uobj->id);
 		ib_destroy_cq(cq);
 		list_del(&uobj->list);
-		kfree(container_of(uobj, struct ib_ucq_object, uobject));
+		ib_uverbs_release_ucq(file, ev_file, ucq);
+		kfree(ucq);
 	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
 		struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+		struct ib_uevent_object *uevent =
+			container_of(uobj, struct ib_uevent_object, uobject);
 		idr_remove(&ib_uverbs_srq_idr, uobj->id);
 		ib_destroy_srq(srq);
 		list_del(&uobj->list);
-		kfree(container_of(uobj, struct ib_uevent_object, uobject));
+		ib_uverbs_release_uevent(file, uevent);
+		kfree(uevent);
 	}
 
 	/* XXX Free MWs */
@@ -175,6 +248,8 @@
 		container_of(ref, struct ib_uverbs_file, ref);
 
 	module_put(file->device->ib_dev->owner);
+	kref_put(&file->device->ref, ib_uverbs_release_dev);
+
 	kfree(file);
 }
 
@@ -188,25 +263,19 @@
 
 	spin_lock_irq(&file->lock);
 
-	while (list_empty(&file->event_list) && file->fd >= 0) {
+	while (list_empty(&file->event_list)) {
 		spin_unlock_irq(&file->lock);
 
 		if (filp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
 		if (wait_event_interruptible(file->poll_wait,
-					     !list_empty(&file->event_list) ||
-					     file->fd < 0))
+					     !list_empty(&file->event_list)))
 			return -ERESTARTSYS;
 
 		spin_lock_irq(&file->lock);
 	}
 
-	if (file->fd < 0) {
-		spin_unlock_irq(&file->lock);
-		return -ENODEV;
-	}
-
 	event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
 
 	if (file->is_async)
@@ -248,26 +317,19 @@
 	poll_wait(filp, &file->poll_wait, wait);
 
 	spin_lock_irq(&file->lock);
-	if (file->fd < 0)
-		pollflags = POLLERR;
-	else if (!list_empty(&file->event_list))
+	if (!list_empty(&file->event_list))
 		pollflags = POLLIN | POLLRDNORM;
 	spin_unlock_irq(&file->lock);
 
 	return pollflags;
 }
 
-static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
+void ib_uverbs_release_event_file(struct kref *ref)
 {
-	struct ib_uverbs_event *entry, *tmp;
+	struct ib_uverbs_event_file *file =
+		container_of(ref, struct ib_uverbs_event_file, ref);
 
-	spin_lock_irq(&file->lock);
-	if (file->fd != -1) {
-		file->fd = -1;
-		list_for_each_entry_safe(entry, tmp, &file->event_list, list)
-			kfree(entry);
-	}
-	spin_unlock_irq(&file->lock);
+	kfree(file);
 }
 
 static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)
@@ -280,21 +342,30 @@
 static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
 {
 	struct ib_uverbs_event_file *file = filp->private_data;
+	struct ib_uverbs_event *entry, *tmp;
 
-	ib_uverbs_event_release(file);
+	spin_lock_irq(&file->lock);
+	file->file = NULL;
+	list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
+		if (entry->counter)
+			list_del(&entry->obj_list);
+		kfree(entry);
+	}
+	spin_unlock_irq(&file->lock);
+
 	ib_uverbs_event_fasync(-1, filp, 0);
-	kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+
+	if (file->is_async) {
+		ib_unregister_event_handler(&file->uverbs_file->event_handler);
+		kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+	}
+	kref_put(&file->ref, ib_uverbs_release_event_file);
 
 	return 0;
 }
 
 static struct file_operations uverbs_event_fops = {
-	/*
-	 * No .owner field since we artificially create event files,
-	 * so there is no increment to the module reference count in
-	 * the open path.  All event files come from a uverbs command
-	 * file, which already takes a module reference, so this is OK.
-	 */
+	.owner	 = THIS_MODULE,
 	.read 	 = ib_uverbs_event_read,
 	.poll    = ib_uverbs_event_poll,
 	.release = ib_uverbs_event_close,
@@ -303,27 +374,37 @@
 
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
 {
-	struct ib_uverbs_file  *file = cq_context;
-	struct ib_ucq_object   *uobj;
-	struct ib_uverbs_event *entry;
-	unsigned long           flags;
+	struct ib_uverbs_event_file    *file = cq_context;
+	struct ib_ucq_object	       *uobj;
+	struct ib_uverbs_event	       *entry;
+	unsigned long			flags;
+
+	if (!file)
+		return;
+
+	spin_lock_irqsave(&file->lock, flags);
+	if (!file->file) {
+		spin_unlock_irqrestore(&file->lock, flags);
+		return;
+	}
 
 	entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-	if (!entry)
+	if (!entry) {
+		spin_unlock_irqrestore(&file->lock, flags);
 		return;
+	}
 
 	uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
 
 	entry->desc.comp.cq_handle = cq->uobject->user_handle;
 	entry->counter		   = &uobj->comp_events_reported;
 
-	spin_lock_irqsave(&file->comp_file[0].lock, flags);
-	list_add_tail(&entry->list, &file->comp_file[0].event_list);
+	list_add_tail(&entry->list, &file->event_list);
 	list_add_tail(&entry->obj_list, &uobj->comp_list);
-	spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
+	spin_unlock_irqrestore(&file->lock, flags);
 
-	wake_up_interruptible(&file->comp_file[0].poll_wait);
-	kill_fasync(&file->comp_file[0].async_queue, SIGIO, POLL_IN);
+	wake_up_interruptible(&file->poll_wait);
+	kill_fasync(&file->async_queue, SIGIO, POLL_IN);
 }
 
 static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
@@ -334,32 +415,40 @@
 	struct ib_uverbs_event *entry;
 	unsigned long flags;
 
-	entry = kmalloc(sizeof *entry, GFP_ATOMIC);
-	if (!entry)
+	spin_lock_irqsave(&file->async_file->lock, flags);
+	if (!file->async_file->file) {
+		spin_unlock_irqrestore(&file->async_file->lock, flags);
 		return;
+	}
+
+	entry = kmalloc(sizeof *entry, GFP_ATOMIC);
+	if (!entry) {
+		spin_unlock_irqrestore(&file->async_file->lock, flags);
+		return;
+	}
 
 	entry->desc.async.element    = element;
 	entry->desc.async.event_type = event;
 	entry->counter               = counter;
 
-	spin_lock_irqsave(&file->async_file.lock, flags);
-	list_add_tail(&entry->list, &file->async_file.event_list);
+	list_add_tail(&entry->list, &file->async_file->event_list);
 	if (obj_list)
 		list_add_tail(&entry->obj_list, obj_list);
-	spin_unlock_irqrestore(&file->async_file.lock, flags);
+	spin_unlock_irqrestore(&file->async_file->lock, flags);
 
-	wake_up_interruptible(&file->async_file.poll_wait);
-	kill_fasync(&file->async_file.async_queue, SIGIO, POLL_IN);
+	wake_up_interruptible(&file->async_file->poll_wait);
+	kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);
 }
 
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
 {
+	struct ib_uverbs_event_file *ev_file = context_ptr;
 	struct ib_ucq_object *uobj;
 
 	uobj = container_of(event->element.cq->uobject,
 			    struct ib_ucq_object, uobject);
 
-	ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+	ib_uverbs_async_handler(ev_file->uverbs_file, uobj->uobject.user_handle,
 				event->event, &uobj->async_list,
 				&uobj->async_events_reported);
 				
@@ -389,8 +478,8 @@
 				&uobj->events_reported);
 }
 
-static void ib_uverbs_event_handler(struct ib_event_handler *handler,
-				    struct ib_event *event)
+void ib_uverbs_event_handler(struct ib_event_handler *handler,
+			     struct ib_event *event)
 {
 	struct ib_uverbs_file *file =
 		container_of(handler, struct ib_uverbs_file, event_handler);
@@ -399,38 +488,90 @@
 				NULL, NULL);
 }
 
-static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
-				struct ib_uverbs_file *uverbs_file)
+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+					int is_async, int *fd)
 {
+	struct ib_uverbs_event_file *ev_file;
 	struct file *filp;
+	int ret;
 
-	spin_lock_init(&file->lock);
-	INIT_LIST_HEAD(&file->event_list);
-	init_waitqueue_head(&file->poll_wait);
-	file->uverbs_file = uverbs_file;
-	file->async_queue = NULL;
+	ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
+	if (!ev_file)
+		return ERR_PTR(-ENOMEM);
 
-	file->fd = get_unused_fd();
-	if (file->fd < 0)
-		return file->fd;
+	kref_init(&ev_file->ref);
+	spin_lock_init(&ev_file->lock);
+	INIT_LIST_HEAD(&ev_file->event_list);
+	init_waitqueue_head(&ev_file->poll_wait);
+	ev_file->uverbs_file = uverbs_file;
+	ev_file->async_queue = NULL;
+	ev_file->is_async    = is_async;
+
+	*fd = get_unused_fd();
+	if (*fd < 0) {
+		ret = *fd;
+		goto err;
+	}
 
 	filp = get_empty_filp();
 	if (!filp) {
-		put_unused_fd(file->fd);
-		return -ENFILE;
+		ret = -ENFILE;
+		goto err_fd;
 	}
 
-	filp->f_op 	   = &uverbs_event_fops;
+	ev_file->file      = filp;
+
+	/*
+	 * fops_get() can't fail here, because we're coming from a
+	 * system call on a uverbs file, which will already have a
+	 * module reference.
+	 */
+	filp->f_op 	   = fops_get(&uverbs_event_fops);
 	filp->f_vfsmnt 	   = mntget(uverbs_event_mnt);
 	filp->f_dentry 	   = dget(uverbs_event_mnt->mnt_root);
 	filp->f_mapping    = filp->f_dentry->d_inode->i_mapping;
 	filp->f_flags      = O_RDONLY;
 	filp->f_mode       = FMODE_READ;
-	filp->private_data = file;
+	filp->private_data = ev_file;
 
-	fd_install(file->fd, filp);
+	return filp;
 
-	return 0;
+err_fd:
+	put_unused_fd(*fd);
+
+err:
+	kfree(ev_file);
+	return ERR_PTR(ret);
+}
+
+/*
+ * Look up a completion event file by FD.  If lookup is successful,
+ * takes a ref to the event file struct that it returns; if
+ * unsuccessful, returns NULL.
+ */
+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
+{
+	struct ib_uverbs_event_file *ev_file = NULL;
+	struct file *filp;
+
+	filp = fget(fd);
+	if (!filp)
+		return NULL;
+
+	if (filp->f_op != &uverbs_event_fops)
+		goto out;
+
+	ev_file = filp->private_data;
+	if (ev_file->is_async) {
+		ev_file = NULL;
+		goto out;
+	}
+
+	kref_get(&ev_file->ref);
+
+out:
+	fput(filp);
+	return ev_file;
 }
 
 static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
@@ -450,11 +591,11 @@
 
 	if (hdr.command < 0				||
 	    hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
-	    !uverbs_cmd_table[hdr.command])
+	    !uverbs_cmd_table[hdr.command]		||
+	    !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
 		return -EINVAL;
 
-	if (!file->ucontext                               &&
-	    hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS &&
+	if (!file->ucontext &&
 	    hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)
 		return -EINVAL;
 
@@ -474,84 +615,57 @@
 
 static int ib_uverbs_open(struct inode *inode, struct file *filp)
 {
-	struct ib_uverbs_device *dev =
-		container_of(inode->i_cdev, struct ib_uverbs_device, dev);
+	struct ib_uverbs_device *dev;
 	struct ib_uverbs_file *file;
-	int i = 0;
 	int ret;
 
-	if (!try_module_get(dev->ib_dev->owner))
-		return -ENODEV;
+	spin_lock(&map_lock);
+	dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];
+	if (dev)
+		kref_get(&dev->ref);
+	spin_unlock(&map_lock);
 
-	file = kmalloc(sizeof *file +
-		       (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
-		       GFP_KERNEL);
-	if (!file) {
-		ret = -ENOMEM;
+	if (!dev)
+		return -ENXIO;
+
+	if (!try_module_get(dev->ib_dev->owner)) {
+		ret = -ENODEV;
 		goto err;
 	}
 
-	file->device = dev;
+	file = kmalloc(sizeof *file, GFP_KERNEL);
+	if (!file) {
+		ret = -ENOMEM;
+		goto err_module;
+	}
+
+	file->device	 = dev;
+	file->ucontext	 = NULL;
+	file->async_file = NULL;
 	kref_init(&file->ref);
 	init_MUTEX(&file->mutex);
 
-	file->ucontext = NULL;
-
-	kref_get(&file->ref);
-	ret = ib_uverbs_event_init(&file->async_file, file);
-	if (ret)
-		goto err_kref;
-
-	file->async_file.is_async = 1;
-
-	for (i = 0; i < dev->num_comp; ++i) {
-		kref_get(&file->ref);
-		ret = ib_uverbs_event_init(&file->comp_file[i], file);
-		if (ret)
-			goto err_async;
-		file->comp_file[i].is_async = 0;
-	}
-
-
 	filp->private_data = file;
 
-	INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev,
-			      ib_uverbs_event_handler);
-	if (ib_register_event_handler(&file->event_handler))
-		goto err_async;
-
 	return 0;
 
-err_async:
-	while (i--)
-		ib_uverbs_event_release(&file->comp_file[i]);
-
-	ib_uverbs_event_release(&file->async_file);
-
-err_kref:
-	/*
-	 * One extra kref_put() because we took a reference before the
-	 * event file creation that failed and got us here.
-	 */
-	kref_put(&file->ref, ib_uverbs_release_file);
-	kref_put(&file->ref, ib_uverbs_release_file);
+err_module:
+	module_put(dev->ib_dev->owner);
 
 err:
-	module_put(dev->ib_dev->owner);
+	kref_put(&dev->ref, ib_uverbs_release_dev);
+
 	return ret;
 }
 
 static int ib_uverbs_close(struct inode *inode, struct file *filp)
 {
 	struct ib_uverbs_file *file = filp->private_data;
-	int i;
 
-	ib_unregister_event_handler(&file->event_handler);
-	ib_uverbs_event_release(&file->async_file);
-	ib_dealloc_ucontext(file->ucontext);
+	ib_uverbs_cleanup_ucontext(file, file->ucontext);
 
-	for (i = 0; i < file->device->num_comp; ++i)
-		ib_uverbs_event_release(&file->comp_file[i]);
+	if (file->async_file)
+		kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
 
 	kref_put(&file->ref, ib_uverbs_release_file);
 
@@ -581,27 +695,25 @@
 
 static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
-	struct ib_uverbs_device *dev =
-		container_of(class_dev, struct ib_uverbs_device, class_dev);
+	struct ib_uverbs_device *dev = class_get_devdata(class_dev);
+
+	if (!dev)
+		return -ENODEV;
 
 	return sprintf(buf, "%s\n", dev->ib_dev->name);
 }
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 
-static void ib_uverbs_release_class_dev(struct class_device *class_dev)
+static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
 {
-	struct ib_uverbs_device *dev =
-		container_of(class_dev, struct ib_uverbs_device, class_dev);
+	struct ib_uverbs_device *dev = class_get_devdata(class_dev);
 
-	cdev_del(&dev->dev);
-	clear_bit(dev->devnum, dev_map);
-	kfree(dev);
+	if (!dev)
+		return -ENODEV;
+
+	return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
 }
-
-static struct class uverbs_class = {
-	.name    = "infiniband_verbs",
-	.release = ib_uverbs_release_class_dev
-};
+static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
 
 static ssize_t show_abi_version(struct class *class, char *buf)
 {
@@ -622,6 +734,8 @@
 
 	memset(uverbs_dev, 0, sizeof *uverbs_dev);
 
+	kref_init(&uverbs_dev->ref);
+
 	spin_lock(&map_lock);
 	uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
 	if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
@@ -631,41 +745,49 @@
 	set_bit(uverbs_dev->devnum, dev_map);
 	spin_unlock(&map_lock);
 
-	uverbs_dev->ib_dev   = device;
-	uverbs_dev->num_comp = 1;
+	uverbs_dev->ib_dev           = device;
+	uverbs_dev->num_comp_vectors = 1;
 
-	if (device->mmap)
-		cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops);
-	else
-		cdev_init(&uverbs_dev->dev, &uverbs_fops);
-	uverbs_dev->dev.owner = THIS_MODULE;
-	kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum);
-	if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+	uverbs_dev->dev = cdev_alloc();
+	if (!uverbs_dev->dev)
 		goto err;
-
-	uverbs_dev->class_dev.class = &uverbs_class;
-	uverbs_dev->class_dev.dev   = device->dma_device;
-	uverbs_dev->class_dev.devt  = uverbs_dev->dev.dev;
-	snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum);
-	if (class_device_register(&uverbs_dev->class_dev))
+	uverbs_dev->dev->owner = THIS_MODULE;
+	uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+	kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);
+	if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
 		goto err_cdev;
 
-	if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))
+	uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,
+						    uverbs_dev->dev->dev,
+						    device->dma_device,
+						    "uverbs%d", uverbs_dev->devnum);
+	if (IS_ERR(uverbs_dev->class_dev))
+		goto err_cdev;
+
+	class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
+
+	if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))
 		goto err_class;
+	if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))
+		goto err_class;
+
+	spin_lock(&map_lock);
+	dev_table[uverbs_dev->devnum] = uverbs_dev;
+	spin_unlock(&map_lock);
 
 	ib_set_client_data(device, &uverbs_client, uverbs_dev);
 
 	return;
 
 err_class:
-	class_device_unregister(&uverbs_dev->class_dev);
+	class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
 
 err_cdev:
-	cdev_del(&uverbs_dev->dev);
+	cdev_del(uverbs_dev->dev);
 	clear_bit(uverbs_dev->devnum, dev_map);
 
 err:
-	kfree(uverbs_dev);
+	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
 	return;
 }
 
@@ -676,7 +798,16 @@
 	if (!uverbs_dev)
 		return;
 
-	class_device_unregister(&uverbs_dev->class_dev);
+	class_set_devdata(uverbs_dev->class_dev, NULL);
+	class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
+	cdev_del(uverbs_dev->dev);
+
+	spin_lock(&map_lock);
+	dev_table[uverbs_dev->devnum] = NULL;
+	spin_unlock(&map_lock);
+
+	clear_bit(uverbs_dev->devnum, dev_map);
+	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
 }
 
 static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
@@ -706,13 +837,14 @@
 		goto out;
 	}
 
-	ret = class_register(&uverbs_class);
-	if (ret) {
+	uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");
+	if (IS_ERR(uverbs_class)) {
+		ret = PTR_ERR(uverbs_class);
 		printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
 		goto out_chrdev;
 	}
 
-	ret = class_create_file(&uverbs_class, &class_attr_abi_version);
+	ret = class_create_file(uverbs_class, &class_attr_abi_version);
 	if (ret) {
 		printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
 		goto out_class;
@@ -746,7 +878,7 @@
 	unregister_filesystem(&uverbs_event_fs);
 
 out_class:
-	class_unregister(&uverbs_class);
+	class_destroy(uverbs_class);
 
 out_chrdev:
 	unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
@@ -760,8 +892,15 @@
 	ib_unregister_client(&uverbs_client);
 	mntput(uverbs_event_mnt);
 	unregister_filesystem(&uverbs_event_fs);
-	class_unregister(&uverbs_class);
+	class_destroy(uverbs_class);
 	unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+	idr_destroy(&ib_uverbs_pd_idr);
+	idr_destroy(&ib_uverbs_mr_idr);
+	idr_destroy(&ib_uverbs_mw_idr);
+	idr_destroy(&ib_uverbs_ah_idr);
+	idr_destroy(&ib_uverbs_cq_idr);
+	idr_destroy(&ib_uverbs_qp_idr);
+	idr_destroy(&ib_uverbs_srq_idr);
 }
 
 module_init(ib_uverbs_init);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 5081d90..72d3ef7 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -523,16 +523,22 @@
 
 int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 {
-	return qp->device->attach_mcast ?
-		qp->device->attach_mcast(qp, gid, lid) :
-		-ENOSYS;
+	if (!qp->device->attach_mcast)
+		return -ENOSYS;
+	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+		return -EINVAL;
+
+	return qp->device->attach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_attach_mcast);
 
 int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 {
-	return qp->device->detach_mcast ?
-		qp->device->detach_mcast(qp, gid, lid) :
-		-ENOSYS;
+	if (!qp->device->detach_mcast)
+		return -ENOSYS;
+	if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UD)
+		return -EINVAL;
+
+	return qp->device->detach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_detach_mcast);
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index c44f7ba..47ec5a7 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -7,4 +7,5 @@
 ib_mthca-y :=	mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
 		mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
 		mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
-		mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o
+		mthca_provider.o mthca_memfree.o mthca_uar.o mthca_srq.o \
+		mthca_catas.o
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 889e850..22fdc44 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -34,6 +34,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
new file mode 100644
index 0000000..7ac52af
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2005 Cisco Systems.  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.
+ *
+ * $Id$
+ */
+
+#include "mthca_dev.h"
+
+enum {
+	MTHCA_CATAS_POLL_INTERVAL	= 5 * HZ,
+
+	MTHCA_CATAS_TYPE_INTERNAL	= 0,
+	MTHCA_CATAS_TYPE_UPLINK		= 3,
+	MTHCA_CATAS_TYPE_DDR		= 4,
+	MTHCA_CATAS_TYPE_PARITY		= 5,
+};
+
+static DEFINE_SPINLOCK(catas_lock);
+
+static void handle_catas(struct mthca_dev *dev)
+{
+	struct ib_event event;
+	const char *type;
+	int i;
+
+	event.device = &dev->ib_dev;
+	event.event  = IB_EVENT_DEVICE_FATAL;
+	event.element.port_num = 0;
+
+	ib_dispatch_event(&event);
+
+	switch (swab32(readl(dev->catas_err.map)) >> 24) {
+	case MTHCA_CATAS_TYPE_INTERNAL:
+		type = "internal error";
+		break;
+	case MTHCA_CATAS_TYPE_UPLINK:
+		type = "uplink bus error";
+		break;
+	case MTHCA_CATAS_TYPE_DDR:
+		type = "DDR data error";
+		break;
+	case MTHCA_CATAS_TYPE_PARITY:
+		type = "internal parity error";
+		break;
+	default:
+		type = "unknown error";
+		break;
+	}
+
+	mthca_err(dev, "Catastrophic error detected: %s\n", type);
+	for (i = 0; i < dev->catas_err.size; ++i)
+		mthca_err(dev, "  buf[%02x]: %08x\n",
+			  i, swab32(readl(dev->catas_err.map + i)));
+}
+
+static void poll_catas(unsigned long dev_ptr)
+{
+	struct mthca_dev *dev = (struct mthca_dev *) dev_ptr;
+	unsigned long flags;
+	int i;
+
+	for (i = 0; i < dev->catas_err.size; ++i)
+		if (readl(dev->catas_err.map + i)) {
+			handle_catas(dev);
+			return;
+		}
+
+	spin_lock_irqsave(&catas_lock, flags);
+	if (dev->catas_err.stop)
+		mod_timer(&dev->catas_err.timer,
+			  jiffies + MTHCA_CATAS_POLL_INTERVAL);
+	spin_unlock_irqrestore(&catas_lock, flags);
+
+	return;
+}
+
+void mthca_start_catas_poll(struct mthca_dev *dev)
+{
+	unsigned long addr;
+
+	init_timer(&dev->catas_err.timer);
+	dev->catas_err.stop = 0;
+	dev->catas_err.map  = NULL;
+
+	addr = pci_resource_start(dev->pdev, 0) +
+		((pci_resource_len(dev->pdev, 0) - 1) &
+		 dev->catas_err.addr);
+
+	if (!request_mem_region(addr, dev->catas_err.size * 4,
+				DRV_NAME)) {
+		mthca_warn(dev, "couldn't request catastrophic error region "
+			   "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
+		return;
+	}
+
+	dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4);
+	if (!dev->catas_err.map) {
+		mthca_warn(dev, "couldn't map catastrophic error region "
+			   "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);
+		release_mem_region(addr, dev->catas_err.size * 4);
+		return;
+	}
+
+	dev->catas_err.timer.data     = (unsigned long) dev;
+	dev->catas_err.timer.function = poll_catas;
+	dev->catas_err.timer.expires  = jiffies + MTHCA_CATAS_POLL_INTERVAL;
+	add_timer(&dev->catas_err.timer);
+}
+
+void mthca_stop_catas_poll(struct mthca_dev *dev)
+{
+	spin_lock_irq(&catas_lock);
+	dev->catas_err.stop = 1;
+	spin_unlock_irq(&catas_lock);
+
+	del_timer_sync(&dev->catas_err.timer);
+
+	if (dev->catas_err.map) {
+		iounmap(dev->catas_err.map);
+		release_mem_region(pci_resource_start(dev->pdev, 0) +
+				   ((pci_resource_len(dev->pdev, 0) - 1) &
+				    dev->catas_err.addr),
+				   dev->catas_err.size * 4);
+	}
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index f6a8ac0..49f211d 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems. 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
@@ -524,7 +525,7 @@
 }
 
 struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
-					  unsigned int gfp_mask)
+					  gfp_t gfp_mask)
 {
 	struct mthca_mailbox *mailbox;
 
@@ -706,9 +707,13 @@
 
 	MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
 	dev->cmd.max_cmds = 1 << lg;
+	MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
+	MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
 
 	mthca_dbg(dev, "FW version %012llx, max commands %d\n",
 		  (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
+	mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n",
+		  (unsigned long long) dev->catas_err.addr, dev->catas_err.size);
 
 	if (mthca_is_memfree(dev)) {
 		MTHCA_GET(dev->fw.arbel.fw_pages,       outbox, QUERY_FW_SIZE_OFFSET);
@@ -933,9 +938,9 @@
 		goto out;
 
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
-	dev_lim->max_srq_sz = 1 << field;
+	dev_lim->max_srq_sz = (1 << field) - 1;
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
-	dev_lim->max_qp_sz = 1 << field;
+	dev_lim->max_qp_sz = (1 << field) - 1;
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET);
 	dev_lim->reserved_qps = 1 << (field & 0xf);
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET);
@@ -1045,6 +1050,8 @@
 		  dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);
 	mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",
 		  dev_lim->max_pds, dev_lim->reserved_mgms);
+	mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
+		  dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);
 
 	mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
 
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index 65f976a..18175be 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -248,7 +248,7 @@
 		     u8  status, u64 out_param);
 
 struct mthca_mailbox *mthca_alloc_mailbox(struct mthca_dev *dev,
-					  unsigned int gfp_mask);
+					  gfp_t gfp_mask);
 void mthca_free_mailbox(struct mthca_dev *dev, struct mthca_mailbox *mailbox);
 
 int mthca_SYS_EN(struct mthca_dev *dev, u8 *status);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 7bff5a8..7e68bd4 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -83,6 +83,8 @@
 	/* Arbel FW gives us these, but we need them for Tavor */
 	MTHCA_MPT_ENTRY_SIZE  =  0x40,
 	MTHCA_MTT_SEG_SIZE    =  0x40,
+
+	MTHCA_QP_PER_MGM      = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
 };
 
 enum {
@@ -128,12 +130,16 @@
 	int      num_uars;
 	int      max_sg;
 	int      num_qps;
+	int      max_wqes;
+	int	 max_qp_init_rdma;
 	int      reserved_qps;
 	int      num_srqs;
+	int      max_srq_wqes;
 	int      reserved_srqs;
 	int      num_eecs;
 	int      reserved_eecs;
 	int      num_cqs;
+	int      max_cqes;
 	int      reserved_cqs;
 	int      num_eqs;
 	int      reserved_eqs;
@@ -148,6 +154,7 @@
 	int      reserved_mcgs;
 	int      num_pds;
 	int      reserved_pds;
+	u32      flags;
 	u8       port_width_cap;
 };
 
@@ -251,6 +258,14 @@
 	struct mthca_icm_table *table;
 };
 
+struct mthca_catas_err {
+	u64			addr;
+	u32 __iomem	       *map;
+	unsigned long		stop;
+	u32			size;
+	struct timer_list	timer;
+};
+
 struct mthca_dev {
 	struct ib_device  ib_dev;
 	struct pci_dev   *pdev;
@@ -311,6 +326,8 @@
 	struct mthca_av_table  av_table;
 	struct mthca_mcg_table mcg_table;
 
+	struct mthca_catas_err catas_err;
+
 	struct mthca_uar       driver_uar;
 	struct mthca_db_table *db_tab;
 	struct mthca_pd        driver_pd;
@@ -398,6 +415,9 @@
 int mthca_register_device(struct mthca_dev *dev);
 void mthca_unregister_device(struct mthca_dev *dev);
 
+void mthca_start_catas_poll(struct mthca_dev *dev);
+void mthca_stop_catas_poll(struct mthca_dev *dev);
+
 int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);
 void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
 
@@ -447,6 +467,8 @@
 int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
 		    struct ib_srq_attr *attr, struct mthca_srq *srq);
 void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);
+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+		     enum ib_srq_attr_mask attr_mask);
 void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
 		     enum ib_event_type event_type);
 void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 8dfafda..e5a047a 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -83,7 +83,8 @@
 	MTHCA_EVENT_TYPE_PATH_MIG   	    = 0x01,
 	MTHCA_EVENT_TYPE_COMM_EST   	    = 0x02,
 	MTHCA_EVENT_TYPE_SQ_DRAINED 	    = 0x03,
-	MTHCA_EVENT_TYPE_SRQ_LAST_WQE       = 0x13,
+	MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE    = 0x13,
+	MTHCA_EVENT_TYPE_SRQ_LIMIT	    = 0x14,
 	MTHCA_EVENT_TYPE_CQ_ERROR   	    = 0x04,
 	MTHCA_EVENT_TYPE_WQ_CATAS_ERROR     = 0x05,
 	MTHCA_EVENT_TYPE_EEC_CATAS_ERROR    = 0x06,
@@ -110,8 +111,9 @@
 				(1ULL << MTHCA_EVENT_TYPE_LOCAL_CATAS_ERROR)  | \
 				(1ULL << MTHCA_EVENT_TYPE_PORT_CHANGE)        | \
 				(1ULL << MTHCA_EVENT_TYPE_ECC_DETECT))
-#define MTHCA_SRQ_EVENT_MASK    (1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR)    | \
-				(1ULL << MTHCA_EVENT_TYPE_SRQ_LAST_WQE)
+#define MTHCA_SRQ_EVENT_MASK   ((1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR)    | \
+				(1ULL << MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE)    | \
+				(1ULL << MTHCA_EVENT_TYPE_SRQ_LIMIT))
 #define MTHCA_CMD_EVENT_MASK    (1ULL << MTHCA_EVENT_TYPE_CMD)
 
 #define MTHCA_EQ_DB_INC_CI     (1 << 24)
@@ -142,6 +144,9 @@
 			__be32 qpn;
 		} __attribute__((packed)) qp;
 		struct {
+			__be32 srqn;
+		} __attribute__((packed)) srq;
+		struct {
 			__be32 cqn;
 			u32    reserved1;
 			u8     reserved2[3];
@@ -305,6 +310,16 @@
 				       IB_EVENT_SQ_DRAINED);
 			break;
 
+		case MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE:
+			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
+				       IB_EVENT_QP_LAST_WQE_REACHED);
+			break;
+
+		case MTHCA_EVENT_TYPE_SRQ_LIMIT:
+			mthca_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff,
+					IB_EVENT_SRQ_LIMIT_REACHED);
+			break;
+
 		case MTHCA_EVENT_TYPE_WQ_CATAS_ERROR:
 			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
 				       IB_EVENT_QP_FATAL);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 9804174..1229c60 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -34,6 +34,9 @@
  * $Id: mthca_mad.c 1349 2004-12-16 21:09:43Z roland $
  */
 
+#include <linux/string.h>
+#include <linux/slab.h>
+
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_mad.h>
 #include <rdma/ib_smi.h>
@@ -46,11 +49,6 @@
 	MTHCA_VENDOR_CLASS2 = 0xa
 };
 
-struct mthca_trap_mad {
-	struct ib_mad *mad;
-	DECLARE_PCI_UNMAP_ADDR(mapping)
-};
-
 static void update_sm_ah(struct mthca_dev *dev,
 			 u8 port_num, u16 lid, u8 sl)
 {
@@ -116,49 +114,14 @@
 			 struct ib_mad *mad)
 {
 	int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED;
-	struct mthca_trap_mad *tmad;
-	struct ib_sge      gather_list;
-	struct ib_send_wr *bad_wr, wr = {
-		.opcode      = IB_WR_SEND,
-		.sg_list     = &gather_list,
-		.num_sge     = 1,
-		.send_flags  = IB_SEND_SIGNALED,
-		.wr	     = {
-			 .ud = {
-				 .remote_qpn  = qpn,
-				 .remote_qkey = qpn ? IB_QP1_QKEY : 0,
-				 .timeout_ms  = 0
-			 }
-		 }
-	};
+	struct ib_mad_send_buf *send_buf;
 	struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn];
 	int ret;
 	unsigned long flags;
 
 	if (agent) {
-		tmad = kmalloc(sizeof *tmad, GFP_KERNEL);
-		if (!tmad)
-			return;
-
-		tmad->mad = kmalloc(sizeof *tmad->mad, GFP_KERNEL);
-		if (!tmad->mad) {
-			kfree(tmad);
-			return;
-		}
-
-		memcpy(tmad->mad, mad, sizeof *mad);
-
-		wr.wr.ud.mad_hdr = &tmad->mad->mad_hdr;
-		wr.wr_id         = (unsigned long) tmad;
-
-		gather_list.addr   = dma_map_single(agent->device->dma_device,
-						    tmad->mad,
-						    sizeof *tmad->mad,
-						    DMA_TO_DEVICE);
-		gather_list.length = sizeof *tmad->mad;
-		gather_list.lkey   = to_mpd(agent->qp->pd)->ntmr.ibmr.lkey;
-		pci_unmap_addr_set(tmad, mapping, gather_list.addr);
-
+		send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR,
+					      IB_MGMT_MAD_DATA, GFP_ATOMIC);
 		/*
 		 * We rely here on the fact that MLX QPs don't use the
 		 * address handle after the send is posted (this is
@@ -166,21 +129,15 @@
 		 * it's OK for our devices).
 		 */
 		spin_lock_irqsave(&dev->sm_lock, flags);
-		wr.wr.ud.ah      = dev->sm_ah[port_num - 1];
-		if (wr.wr.ud.ah)
-			ret = ib_post_send_mad(agent, &wr, &bad_wr);
+		memcpy(send_buf->mad, mad, sizeof *mad);
+		if ((send_buf->ah = dev->sm_ah[port_num - 1]))
+			ret = ib_post_send_mad(send_buf, NULL);
 		else
 			ret = -EINVAL;
 		spin_unlock_irqrestore(&dev->sm_lock, flags);
 
-		if (ret) {
-			dma_unmap_single(agent->device->dma_device,
-					 pci_unmap_addr(tmad, mapping),
-					 sizeof *tmad->mad,
-					 DMA_TO_DEVICE);
-			kfree(tmad->mad);
-			kfree(tmad);
-		}
+		if (ret)
+			ib_free_send_mad(send_buf);
 	}
 }
 
@@ -267,15 +224,7 @@
 static void send_handler(struct ib_mad_agent *agent,
 			 struct ib_mad_send_wc *mad_send_wc)
 {
-	struct mthca_trap_mad *tmad =
-		(void *) (unsigned long) mad_send_wc->wr_id;
-
-	dma_unmap_single(agent->device->dma_device,
-			 pci_unmap_addr(tmad, mapping),
-			 sizeof *tmad->mad,
-			 DMA_TO_DEVICE);
-	kfree(tmad->mad);
-	kfree(tmad);
+	ib_free_send_mad(mad_send_wc->send_buf);
 }
 
 int mthca_create_agents(struct mthca_dev *dev)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 23a3f56..883d1e5 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -162,9 +162,18 @@
 	mdev->limits.pkey_table_len 	= dev_lim->max_pkeys;
 	mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;
 	mdev->limits.max_sg             = dev_lim->max_sg;
+	mdev->limits.max_wqes           = dev_lim->max_qp_sz;
+	mdev->limits.max_qp_init_rdma   = dev_lim->max_requester_per_qp;
 	mdev->limits.reserved_qps       = dev_lim->reserved_qps;
+	mdev->limits.max_srq_wqes       = dev_lim->max_srq_sz;
 	mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;
 	mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;
+	/*
+	 * Subtract 1 from the limit because we need to allocate a
+	 * spare CQE so the HCA HW can tell the difference between an
+	 * empty CQ and a full CQ.
+	 */
+	mdev->limits.max_cqes           = dev_lim->max_cq_sz - 1;
 	mdev->limits.reserved_cqs       = dev_lim->reserved_cqs;
 	mdev->limits.reserved_eqs       = dev_lim->reserved_eqs;
 	mdev->limits.reserved_mtts      = dev_lim->reserved_mtts;
@@ -172,6 +181,7 @@
 	mdev->limits.reserved_uars      = dev_lim->reserved_uars;
 	mdev->limits.reserved_pds       = dev_lim->reserved_pds;
 	mdev->limits.port_width_cap     = dev_lim->max_port_width;
+	mdev->limits.flags              = dev_lim->flags;
 
 	/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
 	   May be doable since hardware supports it for SRQ.
@@ -1186,6 +1196,7 @@
 
 static struct pci_driver mthca_driver = {
 	.name		= DRV_NAME,
+	.owner		= THIS_MODULE,
 	.id_table	= mthca_pci_table,
 	.probe		= mthca_init_one,
 	.remove		= __devexit_p(mthca_remove_one)
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index a270760..2fc449d 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -33,14 +33,12 @@
  */
 
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
 
-enum {
-	MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
-};
-
 struct mthca_mgm {
 	__be32 next_gid_index;
 	u32    reserved[3];
@@ -189,7 +187,12 @@
 	}
 
 	for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
-		if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
+		if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) {
+			mthca_dbg(dev, "QP %06x already a member of MGM\n", 
+				  ibqp->qp_num);
+			err = 0;
+			goto out;
+		} else if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
 			mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31));
 			break;
 		}
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 7bd7a4b..d72fe95 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -82,7 +82,7 @@
 }
 
 struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
-				  unsigned int gfp_mask)
+				  gfp_t gfp_mask)
 {
 	struct mthca_icm *icm;
 	struct mthca_icm_chunk *chunk = NULL;
@@ -487,7 +487,8 @@
 	}
 }
 
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
+int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
+		   u32 qn, __be32 **db)
 {
 	int group;
 	int start, end, dir;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index bafa515..4fdca26 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -77,7 +77,7 @@
 struct mthca_dev;
 
 struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
-				  unsigned int gfp_mask);
+				  gfp_t gfp_mask);
 void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
 
 struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
@@ -173,7 +173,8 @@
 
 int mthca_init_db_tab(struct mthca_dev *dev);
 void mthca_cleanup_db_tab(struct mthca_dev *dev);
-int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db);
+int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
+		   u32 qn, __be32 **db);
 void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
 
 #endif /* MTHCA_MEMFREE_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 0576056..bd13386 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -35,6 +35,8 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "mthca_profile.h"
 
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 3f5319a..1b9477e 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -37,6 +37,7 @@
  */
 
 #include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
 #include <linux/mm.h>
 
 #include "mthca_dev.h"
@@ -90,15 +91,26 @@
 
 	props->max_mr_size         = ~0ull;
 	props->max_qp              = mdev->limits.num_qps - mdev->limits.reserved_qps;
-	props->max_qp_wr           = 0xffff;
+	props->max_qp_wr           = mdev->limits.max_wqes;
 	props->max_sge             = mdev->limits.max_sg;
 	props->max_cq              = mdev->limits.num_cqs - mdev->limits.reserved_cqs;
-	props->max_cqe             = 0xffff;
+	props->max_cqe             = mdev->limits.max_cqes;
 	props->max_mr              = mdev->limits.num_mpts - mdev->limits.reserved_mrws;
 	props->max_pd              = mdev->limits.num_pds - mdev->limits.reserved_pds;
 	props->max_qp_rd_atom      = 1 << mdev->qp_table.rdb_shift;
-	props->max_qp_init_rd_atom = 1 << mdev->qp_table.rdb_shift;
+	props->max_qp_init_rd_atom = mdev->limits.max_qp_init_rdma;
+	props->max_res_rd_atom     = props->max_qp_rd_atom * props->max_qp;
+	props->max_srq             = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
+	props->max_srq_wr          = mdev->limits.max_srq_wqes;
+	props->max_srq_sge         = mdev->limits.max_sg;
 	props->local_ca_ack_delay  = mdev->limits.local_ca_ack_delay;
+	props->atomic_cap          = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ? 
+					IB_ATOMIC_HCA : IB_ATOMIC_NONE;
+	props->max_pkeys           = mdev->limits.pkey_table_len;
+	props->max_mcast_grp       = mdev->limits.num_mgms + mdev->limits.num_amgms;
+	props->max_mcast_qp_attach = MTHCA_QP_PER_MGM;
+	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * 
+					   props->max_mcast_grp;
 
 	err = 0;
  out:
@@ -150,9 +162,13 @@
 	props->gid_tbl_len       = to_mdev(ibdev)->limits.gid_table_len;
 	props->max_msg_sz        = 0x80000000;
 	props->pkey_tbl_len      = to_mdev(ibdev)->limits.pkey_table_len;
+	props->bad_pkey_cntr     = be16_to_cpup((__be16 *) (out_mad->data + 46));
 	props->qkey_viol_cntr    = be16_to_cpup((__be16 *) (out_mad->data + 48));
 	props->active_width      = out_mad->data[31] & 0xf;
 	props->active_speed      = out_mad->data[35] >> 4;
+	props->max_mtu           = out_mad->data[41] & 0xf;
+	props->active_mtu        = out_mad->data[36] >> 4;
+	props->subnet_timeout    = out_mad->data[51] & 0x1f;
 
  out:
 	kfree(in_mad);
@@ -634,6 +650,9 @@
 	int nent;
 	int err;
 
+	if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes)
+		return ERR_PTR(-EINVAL);
+
 	if (context) {
 		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
 			return ERR_PTR(-EFAULT);
@@ -1058,6 +1077,26 @@
 	strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
 	dev->ib_dev.owner                = THIS_MODULE;
 
+	dev->ib_dev.uverbs_abi_ver	 = MTHCA_UVERBS_ABI_VERSION;
+	dev->ib_dev.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_QP)		|
+		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)	|
+		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST)	|
+		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
 	dev->ib_dev.node_type            = IB_NODE_CA;
 	dev->ib_dev.phys_port_cnt        = dev->limits.num_ports;
 	dev->ib_dev.dma_device           = &dev->pdev->dev;
@@ -1077,6 +1116,7 @@
 
 	if (dev->mthca_flags & MTHCA_FLAG_SRQ) {
 		dev->ib_dev.create_srq           = mthca_create_srq;
+		dev->ib_dev.modify_srq		 = mthca_modify_srq;
 		dev->ib_dev.destroy_srq          = mthca_destroy_srq;
 
 		if (mthca_is_memfree(dev))
@@ -1135,10 +1175,13 @@
 		}
 	}
 
+	mthca_start_catas_poll(dev);
+
 	return 0;
 }
 
 void mthca_unregister_device(struct mthca_dev *dev)
 {
+	mthca_stop_catas_poll(dev);
 	ib_unregister_device(&dev->ib_dev);
 }
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 5fa0066..7c9afde 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -36,6 +36,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
@@ -338,8 +340,7 @@
 				[UC]  = (IB_QP_AV                  |
 					 IB_QP_PATH_MTU            |
 					 IB_QP_DEST_QPN            |
-					 IB_QP_RQ_PSN              |
-					 IB_QP_MAX_DEST_RD_ATOMIC),
+					 IB_QP_RQ_PSN),
 				[RC]  = (IB_QP_AV                  |
 					 IB_QP_PATH_MTU            |
 					 IB_QP_DEST_QPN            |
@@ -368,8 +369,7 @@
 			.trans = MTHCA_TRANS_RTR2RTS,
 			.req_param = {
 				[UD]  = IB_QP_SQ_PSN,
-				[UC]  = (IB_QP_SQ_PSN            |
-					 IB_QP_MAX_QP_RD_ATOMIC),
+				[UC]  = IB_QP_SQ_PSN,
 				[RC]  = (IB_QP_TIMEOUT           |
 					 IB_QP_RETRY_CNT         |
 					 IB_QP_RNR_RETRY         |
@@ -446,8 +446,6 @@
 				[UD]  = (IB_QP_PKEY_INDEX            |
 					 IB_QP_QKEY),
 				[UC]  = (IB_QP_AV                    |
-					 IB_QP_MAX_QP_RD_ATOMIC      |
-					 IB_QP_MAX_DEST_RD_ATOMIC    |
 					 IB_QP_CUR_STATE             |
 					 IB_QP_ALT_PATH              |
 					 IB_QP_ACCESS_FLAGS          |
@@ -478,7 +476,7 @@
 			.opt_param = {
 				[UD]  = (IB_QP_CUR_STATE             |
 					 IB_QP_QKEY),
-				[UC]  = (IB_QP_CUR_STATE),
+				[UC]  = IB_QP_CUR_STATE,
 				[RC]  = (IB_QP_CUR_STATE             |
 					 IB_QP_MIN_RNR_TIMER),
 				[MLX] = (IB_QP_CUR_STATE             |
@@ -1112,8 +1110,10 @@
 			     struct mthca_qp *qp)
 {
 	/* Sanity check QP size before proceeding */
-	if (cap->max_send_wr  > 65536 || cap->max_recv_wr  > 65536 ||
-	    cap->max_send_sge > 64    || cap->max_recv_sge > 64)
+	if (cap->max_send_wr  > dev->limits.max_wqes ||
+	    cap->max_recv_wr  > dev->limits.max_wqes ||
+	    cap->max_send_sge > dev->limits.max_sg   ||
+	    cap->max_recv_sge > dev->limits.max_sg)
 		return -EINVAL;
 
 	if (mthca_is_memfree(dev)) {
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 4f99539..df5e494 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -37,6 +37,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 18998d4..64f70aa 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -186,7 +186,8 @@
 	int err;
 
 	/* Sanity check SRQ size before proceeding */
-	if (attr->max_wr > 16 << 20 || attr->max_sge > 64)
+	if (attr->max_wr  > dev->limits.max_srq_wqes ||
+	    attr->max_sge > dev->limits.max_sg)
 		return -EINVAL;
 
 	srq->max      = attr->max_wr;
@@ -332,6 +333,29 @@
 	mthca_free_mailbox(dev, mailbox);
 }
 
+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+		     enum ib_srq_attr_mask attr_mask)
+{	
+	struct mthca_dev *dev = to_mdev(ibsrq->device);
+	struct mthca_srq *srq = to_msrq(ibsrq);
+	int ret;
+	u8 status;
+
+	/* We don't support resizing SRQs (yet?) */
+	if (attr_mask & IB_SRQ_MAX_WR)
+		return -EINVAL;
+
+	if (attr_mask & IB_SRQ_LIMIT) {
+		ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+		if (ret)
+			return ret;
+		if (status)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
 		     enum ib_event_type event_type)
 {
@@ -354,7 +378,7 @@
 
 	event.device      = &dev->ib_dev;
 	event.event       = event_type;
-	event.element.srq  = &srq->ibsrq;
+	event.element.srq = &srq->ibsrq;
 	srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);
 
 out:
@@ -415,6 +439,14 @@
 
 		wqe       = get_wqe(srq, ind);
 		next_ind  = *wqe_to_link(wqe);
+
+		if (next_ind < 0) {
+			mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+			err = -ENOMEM;
+			*bad_wr = wr;
+			break;
+		}
+
 		prev_wqe  = srq->last;
 		srq->last = wqe;
 
@@ -506,6 +538,13 @@
 		wqe       = get_wqe(srq, ind);
 		next_ind  = *wqe_to_link(wqe);
 
+		if (next_ind < 0) {
+			mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+			err = -ENOMEM;
+			*bad_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;
diff --git a/drivers/infiniband/hw/mthca/mthca_uar.c b/drivers/infiniband/hw/mthca/mthca_uar.c
index 1c8791d..8e92198 100644
--- a/drivers/infiniband/hw/mthca/mthca_uar.c
+++ b/drivers/infiniband/hw/mthca/mthca_uar.c
@@ -32,6 +32,8 @@
  * $Id$
  */
 
+#include <asm/page.h>		/* PAGE_SHIFT */
+
 #include "mthca_dev.h"
 #include "mthca_memfree.h"
 
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h b/drivers/infiniband/hw/mthca/mthca_user.h
index 41613ec..bb015c6 100644
--- a/drivers/infiniband/hw/mthca/mthca_user.h
+++ b/drivers/infiniband/hw/mthca/mthca_user.h
@@ -38,6 +38,12 @@
 #include <linux/types.h>
 
 /*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define MTHCA_UVERBS_ABI_VERSION	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).
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 4ea1c1c..c994a91 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -100,7 +100,12 @@
 
 struct ipoib_mcast;
 
-struct ipoib_buf {
+struct ipoib_rx_buf {
+	struct sk_buff *skb;
+	dma_addr_t	mapping;
+};
+
+struct ipoib_tx_buf {
 	struct sk_buff *skb;
 	DECLARE_PCI_UNMAP_ADDR(mapping)
 };
@@ -150,14 +155,14 @@
 	unsigned int admin_mtu;
 	unsigned int mcast_mtu;
 
-	struct ipoib_buf *rx_ring;
+	struct ipoib_rx_buf *rx_ring;
 
-	spinlock_t        tx_lock;
-	struct ipoib_buf *tx_ring;
-	unsigned          tx_head;
-	unsigned          tx_tail;
-	struct ib_sge     tx_sge;
-	struct ib_send_wr tx_wr;
+	spinlock_t           tx_lock;
+	struct ipoib_tx_buf *tx_ring;
+	unsigned             tx_head;
+	unsigned             tx_tail;
+	struct ib_sge        tx_sge;
+	struct ib_send_wr    tx_wr;
 
 	struct ib_wc ibwc[IPOIB_NUM_WC];
 
@@ -277,7 +282,7 @@
 int ipoib_mcast_detach(struct net_device *dev, u16 mlid,
 		       union ib_gid *mgid);
 
-int ipoib_qp_create(struct net_device *dev);
+int ipoib_init_qp(struct net_device *dev);
 int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca);
 void ipoib_transport_dev_cleanup(struct net_device *dev);
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index f744009..192fef8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -95,65 +95,77 @@
 	}
 }
 
-static inline int ipoib_ib_receive(struct ipoib_dev_priv *priv,
-				   unsigned int wr_id,
-				   dma_addr_t addr)
-{
-	struct ib_sge list = {
-		.addr    = addr,
-		.length  = IPOIB_BUF_SIZE,
-		.lkey    = priv->mr->lkey,
-	};
-	struct ib_recv_wr param = {
-		.wr_id 	    = wr_id | IPOIB_OP_RECV,
-		.sg_list    = &list,
-		.num_sge    = 1,
-	};
-	struct ib_recv_wr *bad_wr;
-
-	return ib_post_recv(priv->qp, &param, &bad_wr);
-}
-
 static int ipoib_ib_post_receive(struct net_device *dev, int id)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
-	struct sk_buff *skb;
-	dma_addr_t addr;
+	struct ib_sge list;
+	struct ib_recv_wr param;
+	struct ib_recv_wr *bad_wr;
 	int ret;
 
-	skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
-	if (!skb) {
-		ipoib_warn(priv, "failed to allocate receive buffer\n");
+	list.addr     = priv->rx_ring[id].mapping;
+	list.length   = IPOIB_BUF_SIZE;
+	list.lkey     = priv->mr->lkey;
 
-		priv->rx_ring[id].skb = NULL;
-		return -ENOMEM;
-	}
-	skb_reserve(skb, 4);	/* 16 byte align IP header */
-	priv->rx_ring[id].skb = skb;
-	addr = dma_map_single(priv->ca->dma_device,
-			      skb->data, IPOIB_BUF_SIZE,
-			      DMA_FROM_DEVICE);
-	pci_unmap_addr_set(&priv->rx_ring[id], mapping, addr);
+	param.next    = NULL;
+	param.wr_id   = id | IPOIB_OP_RECV;
+	param.sg_list = &list;
+	param.num_sge = 1;
 
-	ret = ipoib_ib_receive(priv, id, addr);
-	if (ret) {
-		ipoib_warn(priv, "ipoib_ib_receive failed for buf %d (%d)\n",
-			   id, ret);
-		dma_unmap_single(priv->ca->dma_device, addr,
+	ret = ib_post_recv(priv->qp, &param, &bad_wr);
+	if (unlikely(ret)) {
+		ipoib_warn(priv, "receive failed for buf %d (%d)\n", id, ret);
+		dma_unmap_single(priv->ca->dma_device,
+				 priv->rx_ring[id].mapping,
 				 IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
-		dev_kfree_skb_any(skb);
+		dev_kfree_skb_any(priv->rx_ring[id].skb);
 		priv->rx_ring[id].skb = NULL;
 	}
 
 	return ret;
 }
 
+static int ipoib_alloc_rx_skb(struct net_device *dev, int id)
+{
+	struct ipoib_dev_priv *priv = netdev_priv(dev);
+	struct sk_buff *skb;
+	dma_addr_t addr;
+
+	skb = dev_alloc_skb(IPOIB_BUF_SIZE + 4);
+	if (!skb)
+		return -ENOMEM;
+
+	/*
+	 * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
+	 * header.  So we need 4 more bytes to get to 48 and align the
+	 * IP header to a multiple of 16.
+	 */
+	skb_reserve(skb, 4);
+
+	addr = dma_map_single(priv->ca->dma_device,
+			      skb->data, IPOIB_BUF_SIZE,
+			      DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(addr))) {
+		dev_kfree_skb_any(skb);
+		return -EIO;
+	}
+
+	priv->rx_ring[id].skb     = skb;
+	priv->rx_ring[id].mapping = addr;
+
+	return 0;
+}
+
 static int ipoib_ib_post_receives(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int i;
 
 	for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
+		if (ipoib_alloc_rx_skb(dev, i)) {
+			ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
+			return -ENOMEM;
+		}
 		if (ipoib_ib_post_receive(dev, i)) {
 			ipoib_warn(priv, "ipoib_ib_post_receive failed for buf %d\n", i);
 			return -EIO;
@@ -176,28 +188,36 @@
 		wr_id &= ~IPOIB_OP_RECV;
 
 		if (wr_id < IPOIB_RX_RING_SIZE) {
-			struct sk_buff *skb = priv->rx_ring[wr_id].skb;
+			struct sk_buff *skb  = priv->rx_ring[wr_id].skb;
+			dma_addr_t      addr = priv->rx_ring[wr_id].mapping;
 
-			priv->rx_ring[wr_id].skb = NULL;
-
-			dma_unmap_single(priv->ca->dma_device,
-					 pci_unmap_addr(&priv->rx_ring[wr_id],
-							mapping),
-					 IPOIB_BUF_SIZE,
-					 DMA_FROM_DEVICE);
-
-			if (wc->status != IB_WC_SUCCESS) {
+			if (unlikely(wc->status != IB_WC_SUCCESS)) {
 				if (wc->status != IB_WC_WR_FLUSH_ERR)
 					ipoib_warn(priv, "failed recv event "
 						   "(status=%d, wrid=%d vend_err %x)\n",
 						   wc->status, wr_id, wc->vendor_err);
+				dma_unmap_single(priv->ca->dma_device, addr,
+						 IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
 				dev_kfree_skb_any(skb);
+				priv->rx_ring[wr_id].skb = NULL;
 				return;
 			}
 
+			/*
+			 * If we can't allocate a new RX buffer, dump
+			 * this packet and reuse the old buffer.
+			 */
+			if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) {
+				++priv->stats.rx_dropped;
+				goto repost;
+			}
+
 			ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n",
 				       wc->byte_len, wc->slid);
 
+			dma_unmap_single(priv->ca->dma_device, addr,
+					 IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+
 			skb_put(skb, wc->byte_len);
 			skb_pull(skb, IB_GRH_BYTES);
 
@@ -220,8 +240,8 @@
 				dev_kfree_skb_any(skb);
 			}
 
-			/* repost receive */
-			if (ipoib_ib_post_receive(dev, wr_id))
+		repost:
+			if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
 				ipoib_warn(priv, "ipoib_ib_post_receive failed "
 					   "for buf %d\n", wr_id);
 		} else
@@ -229,7 +249,7 @@
 				   wr_id);
 
 	} else {
-		struct ipoib_buf *tx_req;
+		struct ipoib_tx_buf *tx_req;
 		unsigned long flags;
 
 		if (wr_id >= IPOIB_TX_RING_SIZE) {
@@ -302,7 +322,7 @@
 		struct ipoib_ah *address, u32 qpn)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
-	struct ipoib_buf *tx_req;
+	struct ipoib_tx_buf *tx_req;
 	dma_addr_t addr;
 
 	if (skb->len > dev->mtu + INFINIBAND_ALEN) {
@@ -387,9 +407,9 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int ret;
 
-	ret = ipoib_qp_create(dev);
+	ret = ipoib_init_qp(dev);
 	if (ret) {
-		ipoib_warn(priv, "ipoib_qp_create returned %d\n", ret);
+		ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);
 		return -1;
 	}
 
@@ -468,7 +488,7 @@
 	struct ib_qp_attr qp_attr;
 	int attr_mask;
 	unsigned long begin;
-	struct ipoib_buf *tx_req;
+	struct ipoib_tx_buf *tx_req;
 	int i;
 
 	/* Kill the existing QP and allocate a new one */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 6c5bf07..cd4f423 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -637,8 +637,11 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-	ipoib_warn(priv, "transmit timeout: latency %ld\n",
-		   jiffies - dev->trans_start);
+	ipoib_warn(priv, "transmit timeout: latency %d msecs\n",
+		   jiffies_to_msecs(jiffies - dev->trans_start));
+	ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n",
+		   netif_queue_stopped(dev),
+		   priv->tx_head, priv->tx_tail);
 	/* XXX reset QP, etc. */
 }
 
@@ -729,7 +732,7 @@
 
 	/* Allocate RX/TX "rings" to hold queued skbs */
 
-	priv->rx_ring =	kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf),
+	priv->rx_ring =	kmalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
 				GFP_KERNEL);
 	if (!priv->rx_ring) {
 		printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
@@ -737,9 +740,9 @@
 		goto out;
 	}
 	memset(priv->rx_ring, 0,
-	       IPOIB_RX_RING_SIZE * sizeof (struct ipoib_buf));
+	       IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf));
 
-	priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf),
+	priv->tx_ring = kmalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
 				GFP_KERNEL);
 	if (!priv->tx_ring) {
 		printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
@@ -747,7 +750,7 @@
 		goto out_rx_ring_cleanup;
 	}
 	memset(priv->tx_ring, 0,
-	       IPOIB_TX_RING_SIZE * sizeof (struct ipoib_buf));
+	       IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf));
 
 	/* priv->tx_head & tx_tail are already 0 */
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 79f59d0..b5902a7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -92,7 +92,7 @@
 	return ret;
 }
 
-int ipoib_qp_create(struct net_device *dev)
+int ipoib_init_qp(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int ret;
@@ -149,10 +149,11 @@
 	return 0;
 
 out_fail:
-	ib_destroy_qp(priv->qp);
-	priv->qp = NULL;
+	qp_attr.qp_state = IB_QPS_RESET;
+	if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
+		ipoib_warn(priv, "Failed to modify QP to RESET state\n");
 
-	return -EINVAL;
+	return ret;
 }
 
 int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 3738d17..a4696cd 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -20,7 +20,6 @@
 #include <linux/major.h>
 #include <linux/smp_lock.h>
 #include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/compat.h>
 
 struct evdev {
@@ -662,6 +661,7 @@
 static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
+	struct class_device *cdev;
 	int minor;
 
 	for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
@@ -687,11 +687,13 @@
 
 	evdev_table[minor] = evdev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
-	class_device_create(input_class,
+	cdev = class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			dev->dev, "event%d", minor);
+			dev->cdev.dev, evdev->name);
+
+	/* temporary symlink to keep userspace happy */
+	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+			  evdev->name);
 
 	return &evdev->handle;
 }
@@ -701,9 +703,9 @@
 	struct evdev *evdev = handle->private;
 	struct evdev_list *list;
 
-	class_device_destroy(input_class,
+	sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
-	devfs_remove("input/event%d", evdev->minor);
 	evdev->exist = 0;
 
 	if (evdev->open) {
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index ab09cf4..0506934 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/sched.h>	/* HZ */
 
 /*#include <asm/io.h>*/
 
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 14ae558..3b1685f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -22,12 +22,12 @@
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
+EXPORT_SYMBOL(input_allocate_device);
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
@@ -39,7 +39,7 @@
 EXPORT_SYMBOL(input_accept_process);
 EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL(input_class);
+EXPORT_SYMBOL_GPL(input_class);
 
 #define INPUT_DEVICES	256
 
@@ -316,124 +316,21 @@
 	return NULL;
 }
 
-
-/*
- * Input hotplugging interface - loading event handlers based on
- * device bitfields.
- */
-
-#ifdef CONFIG_HOTPLUG
-
-/*
- * Input hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when input devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
- * or other modules, configure the device, and more.  Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- */
-
-#define SPRINTF_BIT_A(bit, name, max) \
-	do { \
-		envp[i++] = scratch; \
-		scratch += sprintf(scratch, name); \
-		for (j = NBITS(max) - 1; j >= 0; j--) \
-			if (dev->bit[j]) break; \
-		for (; j >= 0; j--) \
-			scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
-		scratch++; \
-	} while (0)
-
-#define SPRINTF_BIT_A2(bit, name, max, ev) \
-	do { \
-		if (test_bit(ev, dev->evbit)) \
-			SPRINTF_BIT_A(bit, name, max); \
-	} while (0)
-
-static void input_call_hotplug(char *verb, struct input_dev *dev)
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, int max)
 {
-	char *argv[3], **envp, *buf, *scratch;
-	int i = 0, j, value;
+	int i;
+	int len = 0;
 
-	if (!hotplug_path[0]) {
-		printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n");
-		return;
-	}
-	if (in_interrupt()) {
-		printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
-		return;
-	}
-	if (!current->fs->root) {
-		printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
-		return;
-	}
-	if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
-		printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
-		return;
-	}
-	if (!(buf = kmalloc(1024, GFP_KERNEL))) {
-		kfree (envp);
-		printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
-		return;
-	}
+	for (i = NBITS(max) - 1; i > 0; i--)
+		if (bitmap[i])
+			break;
 
-	argv[0] = hotplug_path;
-	argv[1] = "input";
-	argv[2] = NULL;
-
-	envp[i++] = "HOME=/";
-	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
-	scratch = buf;
-
-	envp[i++] = scratch;
-	scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
-
-	envp[i++] = scratch;
-	scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
-		dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1;
-
-	if (dev->name) {
-		envp[i++] = scratch;
-		scratch += sprintf(scratch, "NAME=%s", dev->name) + 1;
-	}
-
-	if (dev->phys) {
-		envp[i++] = scratch;
-		scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1;
-	}
-
-	SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
-	SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
-	SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
-	SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
-	SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
-	SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
-	SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
-	SPRINTF_BIT_A2(ffbit,  "FF=",  FF_MAX, EV_FF);
-	SPRINTF_BIT_A2(swbit,  "SW=",  SW_MAX, EV_SW);
-
-	envp[i++] = NULL;
-
-#ifdef INPUT_DEBUG
-	printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
-		argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
-#endif
-
-	value = call_usermodehelper(argv [0], argv, envp, 0);
-
-	kfree(buf);
-	kfree(envp);
-
-#ifdef INPUT_DEBUG
-	if (value != 0)
-		printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
-#endif
+	for (; i >= 0; i--)
+		len += snprintf(buf + len, max(buf_size - len, 0),
+				"%lx%s", bitmap[i], i > 0 ? " " : "");
+	return len;
 }
 
-#endif
-
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -455,37 +352,39 @@
 	return 0;
 }
 
-#define SPRINTF_BIT_B(bit, name, max) \
-	do { \
-		len += sprintf(buf + len, "B: %s", name); \
-		for (i = NBITS(max) - 1; i >= 0; i--) \
-			if (dev->bit[i]) break; \
-		for (; i >= 0; i--) \
-			len += sprintf(buf + len, "%lx ", dev->bit[i]); \
-		len += sprintf(buf + len, "\n"); \
+#define SPRINTF_BIT(ev, bm)						\
+	do {								\
+		len += sprintf(buf + len, "B: %s=", #ev);		\
+		len += input_print_bitmap(buf + len, INT_MAX,		\
+					dev->bm##bit, ev##_MAX);	\
+		len += sprintf(buf + len, "\n");			\
 	} while (0)
 
-#define SPRINTF_BIT_B2(bit, name, max, ev) \
-	do { \
-		if (test_bit(ev, dev->evbit)) \
-			SPRINTF_BIT_B(bit, name, max); \
+#define TEST_AND_SPRINTF_BIT(ev, bm)					\
+	do {								\
+		if (test_bit(EV_##ev, dev->evbit))			\
+			SPRINTF_BIT(ev, bm);				\
 	} while (0)
 
 static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
 {
 	struct input_dev *dev;
 	struct input_handle *handle;
+	const char *path;
 
 	off_t at = 0;
-	int i, len, cnt = 0;
+	int len, cnt = 0;
 
 	list_for_each_entry(dev, &input_dev_list, node) {
 
+		path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL;
+
 		len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
 			dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
 
 		len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
 		len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+		len += sprintf(buf + len, "S: Sysfs=%s\n", path ? path : "");
 		len += sprintf(buf + len, "H: Handlers=");
 
 		list_for_each_entry(handle, &dev->h_list, d_node)
@@ -493,15 +392,15 @@
 
 		len += sprintf(buf + len, "\n");
 
-		SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
-		SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
-		SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
-		SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
-		SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
-		SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
-		SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
-		SPRINTF_BIT_B2(ffbit,  "FF=",  FF_MAX, EV_FF);
-		SPRINTF_BIT_B2(swbit,  "SW=",  SW_MAX, EV_SW);
+		SPRINTF_BIT(EV, ev);
+		TEST_AND_SPRINTF_BIT(KEY, key);
+		TEST_AND_SPRINTF_BIT(REL, rel);
+		TEST_AND_SPRINTF_BIT(ABS, abs);
+		TEST_AND_SPRINTF_BIT(MSC, msc);
+		TEST_AND_SPRINTF_BIT(LED, led);
+		TEST_AND_SPRINTF_BIT(SND, snd);
+		TEST_AND_SPRINTF_BIT(FF, ff);
+		TEST_AND_SPRINTF_BIT(SW, sw);
 
 		len += sprintf(buf + len, "\n");
 
@@ -516,6 +415,8 @@
 			if (cnt >= count)
 				break;
 		}
+
+		kfree(path);
 	}
 
 	if (&dev->node == &input_dev_list)
@@ -606,6 +507,240 @@
 static inline void input_proc_exit(void) { }
 #endif
 
+#define INPUT_DEV_STRING_ATTR_SHOW(name)					\
+static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
+{										\
+	struct input_dev *input_dev = to_input_dev(dev);			\
+	int retval;								\
+										\
+	retval = down_interruptible(&input_dev->sem);				\
+	if (retval)								\
+		return retval;							\
+										\
+	retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : "");	\
+										\
+	up(&input_dev->sem);							\
+										\
+	return retval;								\
+}										\
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+
+INPUT_DEV_STRING_ATTR_SHOW(name);
+INPUT_DEV_STRING_ATTR_SHOW(phys);
+INPUT_DEV_STRING_ATTR_SHOW(uniq);
+
+static struct attribute *input_dev_attrs[] = {
+	&class_device_attr_name.attr,
+	&class_device_attr_phys.attr,
+	&class_device_attr_uniq.attr,
+	NULL
+};
+
+static struct attribute_group input_dev_group = {
+	.attrs	= input_dev_attrs,
+};
+
+#define INPUT_DEV_ID_ATTR(name)							\
+static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)	\
+{										\
+	struct input_dev *input_dev = to_input_dev(dev);			\
+	return sprintf(buf, "%04x\n", input_dev->id.name);			\
+}										\
+static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+
+INPUT_DEV_ID_ATTR(bustype);
+INPUT_DEV_ID_ATTR(vendor);
+INPUT_DEV_ID_ATTR(product);
+INPUT_DEV_ID_ATTR(version);
+
+static struct attribute *input_dev_id_attrs[] = {
+	&class_device_attr_bustype.attr,
+	&class_device_attr_vendor.attr,
+	&class_device_attr_product.attr,
+	&class_device_attr_version.attr,
+	NULL
+};
+
+static struct attribute_group input_dev_id_attr_group = {
+	.name	= "id",
+	.attrs	= input_dev_id_attrs,
+};
+
+#define INPUT_DEV_CAP_ATTR(ev, bm)						\
+static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)	\
+{										\
+	struct input_dev *input_dev = to_input_dev(dev);			\
+	return input_print_bitmap(buf, PAGE_SIZE, input_dev->bm##bit, ev##_MAX);\
+}										\
+static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+
+INPUT_DEV_CAP_ATTR(EV, ev);
+INPUT_DEV_CAP_ATTR(KEY, key);
+INPUT_DEV_CAP_ATTR(REL, rel);
+INPUT_DEV_CAP_ATTR(ABS, abs);
+INPUT_DEV_CAP_ATTR(MSC, msc);
+INPUT_DEV_CAP_ATTR(LED, led);
+INPUT_DEV_CAP_ATTR(SND, snd);
+INPUT_DEV_CAP_ATTR(FF, ff);
+INPUT_DEV_CAP_ATTR(SW, sw);
+
+static struct attribute *input_dev_caps_attrs[] = {
+	&class_device_attr_ev.attr,
+	&class_device_attr_key.attr,
+	&class_device_attr_rel.attr,
+	&class_device_attr_abs.attr,
+	&class_device_attr_msc.attr,
+	&class_device_attr_led.attr,
+	&class_device_attr_snd.attr,
+	&class_device_attr_ff.attr,
+	&class_device_attr_sw.attr,
+	NULL
+};
+
+static struct attribute_group input_dev_caps_attr_group = {
+	.name	= "capabilities",
+	.attrs	= input_dev_caps_attrs,
+};
+
+static void input_dev_release(struct class_device *class_dev)
+{
+	struct input_dev *dev = to_input_dev(class_dev);
+
+	kfree(dev);
+	module_put(THIS_MODULE);
+}
+
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
+				    char *buffer, int buffer_size, int *cur_len,
+				    const char *name, unsigned long *bitmap, int max)
+{
+	if (*cur_index >= num_envp - 1)
+		return -ENOMEM;
+
+	envp[*cur_index] = buffer + *cur_len;
+
+	*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
+	if (*cur_len > buffer_size)
+		return -ENOMEM;
+
+	*cur_len += input_print_bitmap(buffer + *cur_len,
+					max(buffer_size - *cur_len, 0),
+					bitmap, max) + 1;
+	if (*cur_len > buffer_size)
+		return -ENOMEM;
+
+	(*cur_index)++;
+	return 0;
+}
+
+#define INPUT_ADD_HOTPLUG_VAR(fmt, val...)				\
+	do {								\
+		int err = add_hotplug_env_var(envp, num_envp, &i,	\
+					buffer, buffer_size, &len,	\
+					fmt, val);			\
+		if (err)						\
+			return err;					\
+	} while (0)
+
+#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max)				\
+	do {								\
+		int err = input_add_hotplug_bm_var(envp, num_envp, &i,	\
+					buffer, buffer_size, &len,	\
+					name, bm, max);			\
+		if (err)						\
+			return err;					\
+	} while (0)
+
+static int input_dev_hotplug(struct class_device *cdev, char **envp,
+			     int num_envp, char *buffer, int buffer_size)
+{
+	struct input_dev *dev = to_input_dev(cdev);
+	int i = 0;
+	int len = 0;
+
+	INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
+				dev->id.bustype, dev->id.vendor,
+				dev->id.product, dev->id.version);
+	if (dev->name)
+		INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);
+	if (dev->phys)
+		INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);
+	if (dev->phys)
+		INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
+
+	INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
+	if (test_bit(EV_KEY, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
+	if (test_bit(EV_REL, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
+	if (test_bit(EV_ABS, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
+	if (test_bit(EV_MSC, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
+	if (test_bit(EV_LED, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);
+	if (test_bit(EV_SND, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);
+	if (test_bit(EV_FF, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
+	if (test_bit(EV_SW, dev->evbit))
+		INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
+struct class input_class = {
+	.name			= "input",
+	.release		= input_dev_release,
+	.hotplug		= input_dev_hotplug,
+};
+
+struct input_dev *input_allocate_device(void)
+{
+	struct input_dev *dev;
+
+	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
+	if (dev) {
+		dev->dynalloc = 1;
+		dev->cdev.class = &input_class;
+		class_device_initialize(&dev->cdev);
+		INIT_LIST_HEAD(&dev->h_list);
+		INIT_LIST_HEAD(&dev->node);
+	}
+
+	return dev;
+}
+
+static void input_register_classdevice(struct input_dev *dev)
+{
+	static atomic_t input_no = ATOMIC_INIT(0);
+	const char *path;
+
+	__module_get(THIS_MODULE);
+
+	dev->dev = dev->cdev.dev;
+
+	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+
+	path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL);
+	printk(KERN_INFO "input: %s/%s as %s\n",
+		dev->name ? dev->name : "Unspecified device",
+		path ? path : "", dev->cdev.class_id);
+	kfree(path);
+
+	class_device_add(&dev->cdev);
+	sysfs_create_group(&dev->cdev.kobj, &input_dev_group);
+	sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+	sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+}
+
 void input_register_device(struct input_dev *dev)
 {
 	struct input_handle *handle;
@@ -632,15 +767,15 @@
 	INIT_LIST_HEAD(&dev->h_list);
 	list_add_tail(&dev->node, &input_dev_list);
 
+	if (dev->dynalloc)
+		input_register_classdevice(dev);
+
 	list_for_each_entry(handler, &input_handler_list, node)
 		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
 			if ((id = input_match_device(handler->id_table, dev)))
 				if ((handle = handler->connect(handler, dev, id)))
 					input_link_handle(handle);
 
-#ifdef CONFIG_HOTPLUG
-	input_call_hotplug("add", dev);
-#endif
 
 	input_wakeup_procfs_readers();
 }
@@ -660,12 +795,14 @@
 		handle->handler->disconnect(handle);
 	}
 
-#ifdef CONFIG_HOTPLUG
-	input_call_hotplug("remove", dev);
-#endif
-
 	list_del_init(&dev->node);
 
+	if (dev->dynalloc) {
+		sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+		sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+		class_device_unregister(&dev->cdev);
+	}
+
 	input_wakeup_procfs_readers();
 }
 
@@ -748,16 +885,14 @@
 	.open = input_open_file,
 };
 
-struct class *input_class;
-
 static int __init input_init(void)
 {
 	int err;
 
-	input_class = class_create(THIS_MODULE, "input");
-	if (IS_ERR(input_class)) {
-		printk(KERN_ERR "input: unable to register input class\n");
-		return PTR_ERR(input_class);
+	err = class_register(&input_class);
+	if (err) {
+		printk(KERN_ERR "input: unable to register input_dev class\n");
+		return err;
 	}
 
 	err = input_proc_init();
@@ -770,24 +905,18 @@
 		goto fail2;
 	}
 
-	err = devfs_mk_dir("input");
-	if (err)
-		goto fail3;
-
 	return 0;
 
- fail3:	unregister_chrdev(INPUT_MAJOR, "input");
  fail2:	input_proc_exit();
- fail1:	class_destroy(input_class);
+ fail1:	class_unregister(&input_class);
 	return err;
 }
 
 static void __exit input_exit(void)
 {
 	input_proc_exit();
-	devfs_remove("input");
 	unregister_chrdev(INPUT_MAJOR, "input");
-	class_destroy(input_class);
+	class_unregister(&input_class);
 }
 
 subsys_initcall(input_init);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index e0938d1..20e2972 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Joystick device interfaces");
@@ -449,6 +448,7 @@
 static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct joydev *joydev;
+	struct class_device *cdev;
 	int i, j, t, minor;
 
 	for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
@@ -514,11 +514,13 @@
 
 	joydev_table[minor] = joydev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
-	class_device_create(input_class,
+	cdev = class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			dev->dev, "js%d", minor);
+			dev->cdev.dev, joydev->name);
+
+	/* temporary symlink to keep userspace happy */
+	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+			  joydev->name);
 
 	return &joydev->handle;
 }
@@ -528,8 +530,8 @@
 	struct joydev *joydev = handle->private;
 	struct joydev_list *list;
 
-	class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
-	devfs_remove("input/js%d", joydev->minor);
+	sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index bf654301..4571ea3 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -34,6 +34,7 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"FP-Gaming Assasin 3D joystick driver"
 
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index cf35ae6..704bf70 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -34,6 +34,7 @@
 #include <linux/input.h>
 #include <linux/gameport.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Logitech ADI joystick family driver"
 
@@ -54,7 +55,7 @@
 #define ADI_MIN_LENGTH		8
 #define ADI_MIN_LEN_LENGTH	10
 #define ADI_MIN_ID_LENGTH	66
-#define ADI_MAX_NAME_LENGTH	48
+#define ADI_MAX_NAME_LENGTH	64
 #define ADI_MAX_CNAME_LENGTH	16
 #define ADI_MAX_PHYS_LENGTH	64
 
@@ -106,7 +107,7 @@
  */
 
 struct adi {
-	struct input_dev dev;
+	struct input_dev *dev;
 	int length;
 	int ret;
 	int idx;
@@ -215,7 +216,7 @@
 
 static int adi_decode(struct adi *adi)
 {
-	struct input_dev *dev = &adi->dev;
+	struct input_dev *dev = adi->dev;
 	char *abs = adi->abs;
 	short *key = adi->key;
 	int i, t;
@@ -318,7 +319,8 @@
 
 	for (i = 0; seq[i]; i++) {
 		gameport_trigger(gameport);
-		if (seq[i] > 0) msleep(seq[i]);
+		if (seq[i] > 0)
+			msleep(seq[i]);
 		if (seq[i] < 0) {
 			mdelay(-seq[i]);
 			udelay(-seq[i]*14);	/* It looks like mdelay() is off by approx 1.4% */
@@ -397,42 +399,46 @@
 	}
 }
 
-static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
+static int adi_init_input(struct adi *adi, struct adi_port *port, int half)
 {
-	int i, t;
+	struct input_dev *input_dev;
 	char buf[ADI_MAX_NAME_LENGTH];
+	int i, t;
 
-	if (!adi->length) return;
-
-	init_input_dev(&adi->dev);
+	adi->dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
 	t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
 
 	snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
-	snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
+	snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s [%s]", buf, adi->cname);
 	snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
 
 	adi->abs = adi_abs[t];
 	adi->key = adi_key[t];
 
-	adi->dev.open = adi_open;
-	adi->dev.close = adi_close;
+	input_dev->name = adi->name;
+	input_dev->phys = adi->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
+	input_dev->id.product = adi->id;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &port->gameport->dev;
+	input_dev->private = port;
 
-	adi->dev.name = adi->name;
-	adi->dev.phys = adi->phys;
-	adi->dev.id.bustype = BUS_GAMEPORT;
-	adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
-	adi->dev.id.product = adi->id;
-	adi->dev.id.version = 0x0100;
+	input_dev->open = adi_open;
+	input_dev->close = adi_close;
 
-	adi->dev.private = port;
-	adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
-		set_bit(adi->abs[i], adi->dev.absbit);
+		set_bit(adi->abs[i], input_dev->absbit);
 
 	for (i = 0; i < adi->buttons; i++)
-		set_bit(adi->key[i], adi->dev.keybit);
+		set_bit(adi->key[i], input_dev->keybit);
+
+	return 0;
 }
 
 static void adi_init_center(struct adi *adi)
@@ -445,17 +451,17 @@
 	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
 
 		t = adi->abs[i];
-		x = adi->dev.abs[t];
+		x = adi->dev->abs[t];
 
 		if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
 			x = i < adi->axes10 ? 512 : 128;
 
 		if (i < adi->axes10)
-			input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
+			input_set_abs_params(adi->dev, t, 64, x * 2 - 64, 2, 16);
 		else if (i < adi->axes10 + adi->axes8)
-			input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
+			input_set_abs_params(adi->dev, t, 48, x * 2 - 48, 1, 16);
 		else
-			input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
+			input_set_abs_params(adi->dev, t, -1, 1, 0, 0);
 	}
 }
 
@@ -469,7 +475,8 @@
 	int i;
 	int err;
 
-	if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL)))
+	port = kzalloc(sizeof(struct adi_port), GFP_KERNEL);
+	if (!port)
 		return -ENOMEM;
 
 	port->gameport = gameport;
@@ -477,10 +484,8 @@
 	gameport_set_drvdata(gameport, port);
 
 	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
-	if (err) {
-		kfree(port);
-		return err;
-	}
+	if (err)
+		goto fail1;
 
 	adi_init_digital(gameport);
 	adi_read_packet(port);
@@ -490,13 +495,18 @@
 
 	for (i = 0; i < 2; i++) {
 		adi_id_decode(port->adi + i, port);
-		adi_init_input(port->adi + i, port, i);
+
+		if (!port->adi[i].length)
+			continue;
+
+		err = adi_init_input(port->adi + i, port, i);
+		if (err)
+			goto fail2;
 	}
 
 	if (!port->adi[0].length && !port->adi[1].length) {
-		gameport_close(gameport);
-		kfree(port);
-		return -ENODEV;
+		err = -ENODEV;
+		goto fail2;
 	}
 
 	gameport_set_poll_handler(gameport, adi_poll);
@@ -511,12 +521,18 @@
 	for (i = 0; i < 2; i++)
 		if (port->adi[i].length > 0) {
 			adi_init_center(port->adi + i);
-			input_register_device(&port->adi[i].dev);
-			printk(KERN_INFO "input: %s [%s] on %s\n",
-				port->adi[i].name, port->adi[i].cname, gameport->phys);
+			input_register_device(port->adi[i].dev);
 		}
 
 	return 0;
+
+ fail2:	for (i = 0; i < 2; i++)
+		if (port->adi[i].dev)
+			input_free_device(port->adi[i].dev);
+	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(port);
+	return err;
 }
 
 static void adi_disconnect(struct gameport *gameport)
@@ -526,7 +542,7 @@
 
 	for (i = 0; i < 2; i++)
 		if (port->adi[i].length > 0)
-			input_unregister_device(&port->adi[i].dev);
+			input_unregister_device(port->adi[i].dev);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(port);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index e996183..8558a99 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -53,11 +53,9 @@
 
 static int amijoy_used;
 static DECLARE_MUTEX(amijoy_sem);
-static struct input_dev amijoy_dev[2];
+static struct input_dev *amijoy_dev[2];
 static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
 
-static char *amijoy_name = "Amiga joystick";
-
 static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
 	int i, data = 0, button = 0;
@@ -70,15 +68,15 @@
 				case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
 			}
 
-			input_regs(amijoy_dev + i, fp);
+			input_regs(amijoy_dev[i], fp);
 
-			input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
+			input_report_key(amijoy_dev[i], BTN_TRIGGER, button);
 
-			input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
+			input_report_abs(amijoy_dev[i], ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
 			data = ~(data ^ (data << 1));
-			input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
+			input_report_abs(amijoy_dev[i], ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
 
-			input_sync(amijoy_dev + i);
+			input_sync(amijoy_dev[i]);
 		}
 	return IRQ_HANDLED;
 }
@@ -114,39 +112,52 @@
 static int __init amijoy_init(void)
 {
 	int i, j;
+	int err;
 
-	for (i = 0; i < 2; i++)
-		if (amijoy[i]) {
-			if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
-						"amijoy [Denise]")) {
-				if (i == 1 && amijoy[0]) {
-					input_unregister_device(amijoy_dev);
-					release_mem_region(CUSTOM_PHYSADDR+10, 2);
-				}
-				return -EBUSY;
-			}
+	for (i = 0; i < 2; i++) {
+		if (!amijoy[i])
+			continue;
 
-			amijoy_dev[i].open = amijoy_open;
-			amijoy_dev[i].close = amijoy_close;
-			amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-			amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-			amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-			for (j = 0; j < 2; j++) {
-				amijoy_dev[i].absmin[ABS_X + j] = -1;
-				amijoy_dev[i].absmax[ABS_X + j] = 1;
-			}
-
-			amijoy_dev[i].name = amijoy_name;
-			amijoy_dev[i].phys = amijoy_phys[i];
-			amijoy_dev[i].id.bustype = BUS_AMIGA;
-			amijoy_dev[i].id.vendor = 0x0001;
-			amijoy_dev[i].id.product = 0x0003;
-			amijoy_dev[i].id.version = 0x0100;
-
-			input_register_device(amijoy_dev + i);
-			printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
+		amijoy_dev[i] = input_allocate_device();
+		if (!amijoy_dev[i]) {
+			err = -ENOMEM;
+			goto fail;
 		}
+
+		if (!request_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2, "amijoy [Denise]")) {
+			input_free_device(amijoy_dev[i]);
+			err = -EBUSY;
+			goto fail;
+		}
+
+		amijoy_dev[i]->name = "Amiga joystick";
+		amijoy_dev[i]->phys = amijoy_phys[i];
+		amijoy_dev[i]->id.bustype = BUS_AMIGA;
+		amijoy_dev[i]->id.vendor = 0x0001;
+		amijoy_dev[i]->id.product = 0x0003;
+		amijoy_dev[i]->id.version = 0x0100;
+
+		amijoy_dev[i]->open = amijoy_open;
+		amijoy_dev[i]->close = amijoy_close;
+
+		amijoy_dev[i]->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		amijoy_dev[i]->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+		amijoy_dev[i]->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+		for (j = 0; j < 2; j++) {
+			amijoy_dev[i]->absmin[ABS_X + j] = -1;
+			amijoy_dev[i]->absmax[ABS_X + j] = 1;
+		}
+
+		input_register_device(amijoy_dev[i]);
+	}
 	return 0;
+
+ fail:	while (--i >= 0)
+		if (amijoy[i]) {
+			input_unregister_device(amijoy_dev[i]);
+			release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
+		}
+	return err;
 }
 
 static void __exit amijoy_exit(void)
@@ -155,8 +166,8 @@
 
 	for (i = 0; i < 2; i++)
 		if (amijoy[i]) {
-			input_unregister_device(amijoy_dev + i);
-			release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
+			input_unregister_device(amijoy_dev[i]);
+			release_mem_region(CUSTOM_PHYSADDR + 10 + i * 2, 2);
 		}
 }
 
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 64b1313..3121961 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/gameport.h>
+#include <linux/jiffies.h>
 #include <asm/timex.h>
 
 #define DRIVER_DESC	"Analog joystick and gamepad driver"
@@ -111,7 +112,7 @@
 static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
 
 struct analog {
-	struct input_dev dev;
+	struct input_dev *dev;
 	int mask;
 	short *buttons;
 	char name[ANALOG_MAX_NAME_LENGTH];
@@ -182,7 +183,7 @@
 
 static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
 {
-	struct input_dev *dev = &analog->dev;
+	struct input_dev *dev = analog->dev;
 	int i, j;
 
 	if (analog->mask & ANALOG_HAT_FCS)
@@ -428,27 +429,30 @@
  * analog_init_device()
  */
 
-static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
+static int analog_init_device(struct analog_port *port, struct analog *analog, int index)
 {
+	struct input_dev *input_dev;
 	int i, j, t, v, w, x, y, z;
 
 	analog_name(analog);
 	sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
 	analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
 
-	init_input_dev(&analog->dev);
+	analog->dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
-	analog->dev.name = analog->name;
-	analog->dev.phys = analog->phys;
-	analog->dev.id.bustype = BUS_GAMEPORT;
-	analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
-	analog->dev.id.product = analog->mask >> 4;
-	analog->dev.id.version = 0x0100;
+	input_dev->name = analog->name;
+	input_dev->phys = analog->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
+	input_dev->id.product = analog->mask >> 4;
+	input_dev->id.version = 0x0100;
 
-	analog->dev.open = analog_open;
-	analog->dev.close = analog_close;
-	analog->dev.private = port;
-	analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->open = analog_open;
+	input_dev->close = analog_close;
+	input_dev->private = port;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = j = 0; i < 4; i++)
 		if (analog->mask & (1 << i)) {
@@ -461,8 +465,6 @@
 			v = (x >> 3);
 			w = (x >> 3);
 
-			set_bit(t, analog->dev.absbit);
-
 			if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
 				x = y;
 
@@ -472,11 +474,7 @@
 				w = (x >> 4);
 			}
 
-			analog->dev.absmax[t] = (x << 1) - v;
-			analog->dev.absmin[t] = v;
-			analog->dev.absfuzz[t] = port->fuzz;
-			analog->dev.absflat[t] = w;
-
+			input_set_abs_params(input_dev, t, v, (x << 1) - v, port->fuzz, w);
 			j++;
 		}
 
@@ -484,41 +482,30 @@
 		if (analog->mask & analog_exts[i])
 			for (x = 0; x < 2; x++) {
 				t = analog_hats[j++];
-				set_bit(t, analog->dev.absbit);
-				analog->dev.absmax[t] = 1;
-				analog->dev.absmin[t] = -1;
+				input_set_abs_params(input_dev, t, -1, 1, 0, 0);
 			}
 
 	for (i = j = 0; i < 4; i++)
 		if (analog->mask & (0x10 << i))
-			set_bit(analog->buttons[j++], analog->dev.keybit);
+			set_bit(analog->buttons[j++], input_dev->keybit);
 
 	if (analog->mask & ANALOG_BTNS_CHF)
 		for (i = 0; i < 2; i++)
-			set_bit(analog->buttons[j++], analog->dev.keybit);
+			set_bit(analog->buttons[j++], input_dev->keybit);
 
 	if (analog->mask & ANALOG_HBTN_CHF)
 		for (i = 0; i < 4; i++)
-			set_bit(analog->buttons[j++], analog->dev.keybit);
+			set_bit(analog->buttons[j++], input_dev->keybit);
 
 	for (i = 0; i < 4; i++)
 		if (analog->mask & (ANALOG_BTN_TL << i))
-			set_bit(analog_pads[i], analog->dev.keybit);
+			set_bit(analog_pads[i], input_dev->keybit);
 
 	analog_decode(analog, port->axes, port->initial, port->buttons);
 
-	input_register_device(&analog->dev);
+	input_register_device(analog->dev);
 
-	printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
-
-	if (port->cooked)
-		printk(" [ADC port]\n");
-	else
-		printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
-		port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
-		port->speed > 10000 ? "M" : "k",
-		port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
-				    : (port->loop * 1000000) / port->speed);
+	return 0;
 }
 
 /*
@@ -659,37 +646,41 @@
 		return - ENOMEM;
 
 	err = analog_init_port(gameport, drv, port);
-	if (err) {
-		kfree(port);
-		return err;
-	}
+	if (err)
+		goto fail1;
 
 	err = analog_init_masks(port);
-	if (err) {
-		gameport_close(gameport);
-		gameport_set_drvdata(gameport, NULL);
-		kfree(port);
-		return err;
-	}
+	if (err)
+		goto fail2;
 
 	gameport_set_poll_handler(gameport, analog_poll);
 	gameport_set_poll_interval(gameport, 10);
 
 	for (i = 0; i < 2; i++)
-		if (port->analog[i].mask)
-			analog_init_device(port, port->analog + i, i);
+		if (port->analog[i].mask) {
+			err = analog_init_device(port, port->analog + i, i);
+			if (err)
+				goto fail3;
+		}
 
 	return 0;
+
+ fail3: while (--i >= 0)
+		input_unregister_device(port->analog[i].dev);
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(port);
+	return err;
 }
 
 static void analog_disconnect(struct gameport *gameport)
 {
-	int i;
 	struct analog_port *port = gameport_get_drvdata(gameport);
+	int i;
 
 	for (i = 0; i < 2; i++)
 		if (port->analog[i].mask)
-			input_unregister_device(&port->analog[i].dev);
+			input_unregister_device(port->analog[i].dev);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 0b2e9fa..1909f7e 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -34,6 +34,7 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Creative Labs Blaster GamePad Cobra driver"
 
@@ -44,13 +45,11 @@
 #define COBRA_MAX_STROBE	45	/* 45 us max wait for first strobe */
 #define COBRA_LENGTH		36
 
-static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
-
 static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };
 
 struct cobra {
 	struct gameport *gameport;
-	struct input_dev dev[2];
+	struct input_dev *dev[2];
 	int reads;
 	int bads;
 	unsigned char exists;
@@ -128,7 +127,7 @@
 	for (i = 0; i < 2; i++)
 		if (cobra->exists & r & (1 << i)) {
 
-			dev = cobra->dev + i;
+			dev = cobra->dev[i];
 
 			input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
 			input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
@@ -159,11 +158,13 @@
 static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct cobra *cobra;
+	struct input_dev *input_dev;
 	unsigned int data[2];
 	int i, j;
 	int err;
 
-	if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL)))
+	cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL);
+	if (!cobra)
 		return -ENOMEM;
 
 	cobra->gameport = gameport;
@@ -191,38 +192,46 @@
 	gameport_set_poll_handler(gameport, cobra_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	for (i = 0; i < 2; i++)
-		if ((cobra->exists >> i) & 1) {
+	for (i = 0; i < 2; i++) {
+		if (~(cobra->exists >> i) & 1)
+			continue;
 
-			sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
-
-			cobra->dev[i].private = cobra;
-			cobra->dev[i].open = cobra_open;
-			cobra->dev[i].close = cobra_close;
-
-			cobra->dev[i].name = cobra_name;
-			cobra->dev[i].phys = cobra->phys[i];
-			cobra->dev[i].id.bustype = BUS_GAMEPORT;
-			cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
-			cobra->dev[i].id.product = 0x0008;
-			cobra->dev[i].id.version = 0x0100;
-
-			cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-			input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
-			input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
-
-			for (j = 0; cobra_btn[j]; j++)
-				set_bit(cobra_btn[j], cobra->dev[i].keybit);
-
-			input_register_device(&cobra->dev[i]);
-			printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
+		cobra->dev[i] = input_dev = input_allocate_device();
+		if (!input_dev) {
+			err = -ENOMEM;
+			goto fail3;
 		}
 
+		sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
+
+		input_dev->name = "Creative Labs Blaster GamePad Cobra";
+		input_dev->phys = cobra->phys[i];
+		input_dev->id.bustype = BUS_GAMEPORT;
+		input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
+		input_dev->id.product = 0x0008;
+		input_dev->id.version = 0x0100;
+		input_dev->cdev.dev = &gameport->dev;
+		input_dev->private = cobra;
+
+		input_dev->open = cobra_open;
+		input_dev->close = cobra_close;
+
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
+		input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
+		for (j = 0; cobra_btn[j]; j++)
+			set_bit(cobra_btn[j], input_dev->keybit);
+
+		input_register_device(cobra->dev[i]);
+	}
+
 	return 0;
 
-fail2:	gameport_close(gameport);
-fail1:	gameport_set_drvdata(gameport, NULL);
+ fail3:	for (i = 0; i < 2; i++)
+		if (cobra->dev[i])
+			input_unregister_device(cobra->dev[i]);
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
 	kfree(cobra);
 	return err;
 }
@@ -234,7 +243,7 @@
 
 	for (i = 0; i < 2; i++)
 		if ((cobra->exists >> i) & 1)
-			input_unregister_device(cobra->dev + i);
+			input_unregister_device(cobra->dev[i]);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(cobra);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 2a3e4bb2..499344c 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -43,25 +43,28 @@
 MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
 MODULE_LICENSE("GPL");
 
-static int db9[] __initdata = { -1, 0 };
-static int db9_nargs __initdata = 0;
-module_param_array_named(dev, db9, int, &db9_nargs, 0);
+struct db9_config {
+	int args[2];
+	int nargs;
+};
+
+#define DB9_MAX_PORTS		3
+static struct db9_config db9[DB9_MAX_PORTS] __initdata;
+
+module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0);
 MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
-
-static int db9_2[] __initdata = { -1, 0 };
-static int db9_nargs_2 __initdata = 0;
-module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0);
+module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
 MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
-
-static int db9_3[] __initdata = { -1, 0 };
-static int db9_nargs_3 __initdata = 0;
-module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0);
+module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
 MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
 
 __obsolete_setup("db9=");
 __obsolete_setup("db9_2=");
 __obsolete_setup("db9_3=");
 
+#define DB9_ARG_PARPORT		0
+#define DB9_ARG_MODE		1
+
 #define DB9_MULTI_STICK		0x01
 #define DB9_MULTI2_STICK	0x02
 #define DB9_GENESIS_PAD		0x03
@@ -87,40 +90,53 @@
 #define DB9_NORMAL		0x0a
 #define DB9_NOSELECT		0x08
 
-#define DB9_MAX_DEVICES		2
-
 #define DB9_GENESIS6_DELAY	14
 #define DB9_REFRESH_TIME	HZ/100
 
+#define DB9_MAX_DEVICES		2
+
+struct db9_mode_data {
+	const char *name;
+	const short *buttons;
+	int n_buttons;
+	int n_pads;
+	int n_axis;
+	int bidirectional;
+	int reverse;
+};
+
 struct db9 {
-	struct input_dev dev[DB9_MAX_DEVICES];
+	struct input_dev *dev[DB9_MAX_DEVICES];
 	struct timer_list timer;
 	struct pardevice *pd;
 	int mode;
 	int used;
 	struct semaphore sem;
-	char phys[2][32];
+	char phys[DB9_MAX_DEVICES][32];
 };
 
 static struct db9 *db9_base[3];
 
-static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
-static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
-static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
-
-static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
-static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
-					db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
-					db9_cd32_btn, db9_cd32_btn };
-static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
-				      NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
-				     "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
-
-static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
-static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
+static const short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
+static const short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
+static const short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
 static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
-static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
+
+static const struct db9_mode_data db9_modes[] = {
+	{ NULL,					 NULL,		  0,  0,  0,  0,  0 },
+	{ "Multisystem joystick",		 db9_multi_btn,	  1,  1,  2,  1,  1 },
+	{ "Multisystem joystick (2 fire)",	 db9_multi_btn,	  2,  1,  2,  1,  1 },
+	{ "Genesis pad",			 db9_genesis_btn, 4,  1,  2,  1,  1 },
+	{ NULL,					 NULL,		  0,  0,  0,  0,  0 },
+	{ "Genesis 5 pad",			 db9_genesis_btn, 6,  1,  2,  1,  1 },
+	{ "Genesis 6 pad",			 db9_genesis_btn, 8,  1,  2,  1,  1 },
+	{ "Saturn pad",				 db9_cd32_btn,	  9,  6,  7,  0,  1 },
+	{ "Multisystem (0.8.0.2) joystick",	 db9_multi_btn,	  1,  1,  2,  1,  1 },
+	{ "Multisystem (0.8.0.2-dual) joystick", db9_multi_btn,	  1,  2,  2,  1,  1 },
+	{ "Amiga CD-32 pad",			 db9_cd32_btn,	  7,  1,  2,  1,  1 },
+	{ "Saturn dpp",				 db9_cd32_btn,	  9,  6,  7,  0,  0 },
+	{ "Saturn dpp dual",			 db9_cd32_btn,	  9,  12, 7,  0,  0 },
+};
 
 /*
  * Saturn controllers
@@ -342,7 +358,7 @@
 	default:
 		return -1;
 	}
-	max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES);
+	max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
 	for (tmp = 0, i = 0; i < n; i++) {
 		id = db9_saturn_read_packet(port, data, type + i, 1);
 		tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
@@ -354,17 +370,18 @@
 {
 	struct db9 *db9 = (void *) private;
 	struct parport *port = db9->pd->port;
-	struct input_dev *dev = db9->dev;
+	struct input_dev *dev = db9->dev[0];
+	struct input_dev *dev2 = db9->dev[1];
 	int data, i;
 
-	switch(db9->mode) {
+	switch (db9->mode) {
 		case DB9_MULTI_0802_2:
 
 			data = parport_read_data(port) >> 3;
 
-			input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
-			input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
-			input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
+			input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
+			input_report_abs(dev2, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
+			input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
 
 		case DB9_MULTI_0802:
 
@@ -405,7 +422,7 @@
 			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
 
 			parport_write_control(port, DB9_NORMAL);
-			data=parport_read_data(port);
+			data = parport_read_data(port);
 
 			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
 			input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@@ -414,7 +431,7 @@
 		case DB9_GENESIS5_PAD:
 
 			parport_write_control(port, DB9_NOSELECT);
-			data=parport_read_data(port);
+			data = parport_read_data(port);
 
 			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
 			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
@@ -422,7 +439,7 @@
 			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
 
 			parport_write_control(port, DB9_NORMAL);
-			data=parport_read_data(port);
+			data = parport_read_data(port);
 
 			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
 			input_report_key(dev, BTN_X,     ~data & DB9_FIRE2);
@@ -434,7 +451,7 @@
 
 			parport_write_control(port, DB9_NOSELECT); /* 1 */
 			udelay(DB9_GENESIS6_DELAY);
-			data=parport_read_data(port);
+			data = parport_read_data(port);
 
 			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
 			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
@@ -443,7 +460,7 @@
 
 			parport_write_control(port, DB9_NORMAL);
 			udelay(DB9_GENESIS6_DELAY);
-			data=parport_read_data(port);
+			data = parport_read_data(port);
 
 			input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
 			input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
@@ -477,7 +494,7 @@
 
 		case DB9_CD32_PAD:
 
-			data=parport_read_data(port);
+			data = parport_read_data(port);
 
 			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
 			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
@@ -489,7 +506,7 @@
 				parport_write_control(port, 0x02);
 				parport_write_control(port, 0x0a);
 				input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
-				}
+			}
 
 			parport_write_control(port, 0x00);
 			break;
@@ -513,7 +530,7 @@
 	if (!db9->used++) {
 		parport_claim(db9->pd);
 		parport_write_data(port, 0xff);
-		if (db9_reverse[db9->mode]) {
+		if (db9_modes[db9->mode].reverse) {
 			parport_data_reverse(port);
 			parport_write_control(port, DB9_NORMAL);
 		}
@@ -539,117 +556,160 @@
 	up(&db9->sem);
 }
 
-static struct db9 __init *db9_probe(int *config, int nargs)
+static struct db9 __init *db9_probe(int parport, int mode)
 {
 	struct db9 *db9;
+	const struct db9_mode_data *db9_mode;
 	struct parport *pp;
+	struct pardevice *pd;
+	struct input_dev *input_dev;
 	int i, j;
+	int err;
 
-	if (config[0] < 0)
-		return NULL;
-
-	if (nargs < 2) {
-		printk(KERN_ERR "db9.c: Device type must be specified.\n");
-		return NULL;
+	if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
+		printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
+		err = -EINVAL;
+		goto err_out;
 	}
 
-	if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
-		printk(KERN_ERR "db9.c: bad config\n");
-		return NULL;
-	}
+	db9_mode = &db9_modes[mode];
 
-	pp = parport_find_number(config[0]);
+	pp = parport_find_number(parport);
 	if (!pp) {
 		printk(KERN_ERR "db9.c: no such parport\n");
-		return NULL;
+		err = -ENODEV;
+		goto err_out;
 	}
 
-	if (db9_bidirectional[config[1]]) {
-		if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
-			printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
-			parport_put_port(pp);
-			return NULL;
-		}
+	if (db9_mode[mode].bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
+		printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
+		err = -EINVAL;
+		goto err_put_pp;
 	}
 
-	if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) {
-		parport_put_port(pp);
-		return NULL;
+	pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+	if (!pd) {
+		printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
+		err = -EBUSY;
+		goto err_put_pp;
+	}
+
+	db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
+	if (!db9) {
+		printk(KERN_ERR "db9.c: Not enough memory\n");
+		err = -ENOMEM;
+		goto err_unreg_pardev;
 	}
 
 	init_MUTEX(&db9->sem);
-	db9->mode = config[1];
+	db9->pd = pd;
+	db9->mode = mode;
 	init_timer(&db9->timer);
 	db9->timer.data = (long) db9;
 	db9->timer.function = db9_timer;
 
-	db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-	parport_put_port(pp);
+	for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) {
 
-	if (!db9->pd) {
-		printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
-		kfree(db9);
-		return NULL;
-	}
-
-	for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
+		db9->dev[i] = input_dev = input_allocate_device();
+		if (!input_dev) {
+			printk(KERN_ERR "db9.c: Not enough memory for input device\n");
+			err = -ENOMEM;
+			goto err_free_devs;
+		}
 
 		sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
 
-		db9->dev[i].private = db9;
-		db9->dev[i].open = db9_open;
-		db9->dev[i].close = db9_close;
+		input_dev->name = db9_mode->name;
+		input_dev->phys = db9->phys[i];
+		input_dev->id.bustype = BUS_PARPORT;
+		input_dev->id.vendor = 0x0002;
+		input_dev->id.product = mode;
+		input_dev->id.version = 0x0100;
+		input_dev->private = db9;
 
-		db9->dev[i].name = db9_name[db9->mode];
-		db9->dev[i].phys = db9->phys[i];
-		db9->dev[i].id.bustype = BUS_PARPORT;
-		db9->dev[i].id.vendor = 0x0002;
-		db9->dev[i].id.product = config[1];
-		db9->dev[i].id.version = 0x0100;
+		input_dev->open = db9_open;
+		input_dev->close = db9_close;
 
-		db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-		for (j = 0; j < db9_buttons[db9->mode]; j++)
-			set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit);
-		for (j = 0; j < db9_num_axis[db9->mode]; j++) {
-			set_bit(db9_abs[j], db9->dev[i].absbit);
-			if (j < 2) {
-				db9->dev[i].absmin[db9_abs[j]] = -1;
-				db9->dev[i].absmax[db9_abs[j]] = 1;
-			} else {
-				db9->dev[i].absmin[db9_abs[j]] = 1;
-				db9->dev[i].absmax[db9_abs[j]] = 255;
-				db9->dev[i].absflat[db9_abs[j]] = 0;
-			}
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		for (j = 0; j < db9_mode->n_buttons; j++)
+			set_bit(db9_mode->buttons[j], input_dev->keybit);
+		for (j = 0; j < db9_mode->n_axis; j++) {
+			if (j < 2)
+				input_set_abs_params(input_dev, db9_abs[j], -1, 1, 0, 0);
+			else
+				input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
 		}
-		input_register_device(db9->dev + i);
-		printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
+
+		input_register_device(input_dev);
 	}
 
+	parport_put_port(pp);
 	return db9;
+
+ err_free_devs:
+	while (--i >= 0)
+		input_unregister_device(db9->dev[i]);
+	kfree(db9);
+ err_unreg_pardev:
+	parport_unregister_device(pd);
+ err_put_pp:
+	parport_put_port(pp);
+ err_out:
+	return ERR_PTR(err);
+}
+
+static void __exit db9_remove(struct db9 *db9)
+{
+	int i;
+
+	for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
+		input_unregister_device(db9->dev[i]);
+	parport_unregister_device(db9->pd);
+	kfree(db9);
 }
 
 static int __init db9_init(void)
 {
-	db9_base[0] = db9_probe(db9, db9_nargs);
-	db9_base[1] = db9_probe(db9_2, db9_nargs_2);
-	db9_base[2] = db9_probe(db9_3, db9_nargs_3);
+	int i;
+	int have_dev = 0;
+	int err = 0;
 
-	if (db9_base[0] || db9_base[1] || db9_base[2])
-		return 0;
+	for (i = 0; i < DB9_MAX_PORTS; i++) {
+		if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
+			continue;
 
-	return -ENODEV;
+		if (db9[i].nargs < 2) {
+			printk(KERN_ERR "db9.c: Device type must be specified.\n");
+			err = -EINVAL;
+			break;
+		}
+
+		db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT],
+					db9[i].args[DB9_ARG_MODE]);
+		if (IS_ERR(db9_base[i])) {
+			err = PTR_ERR(db9_base[i]);
+			break;
+		}
+
+		have_dev = 1;
+	}
+
+	if (err) {
+		while (--i >= 0)
+			db9_remove(db9_base[i]);
+		return err;
+	}
+
+	return have_dev ? 0 : -ENODEV;
 }
 
 static void __exit db9_exit(void)
 {
-	int i, j;
+	int i;
 
-	for (i = 0; i < 3; i++)
-		if (db9_base[i]) {
-			for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++)
-				input_unregister_device(db9_base[i]->dev + j);
-		parport_unregister_device(db9_base[i]->pd);
-	}
+	for (i = 0; i < DB9_MAX_PORTS; i++)
+		if (db9_base[i])
+			db9_remove(db9_base[i]);
 }
 
 module_init(db9_init);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 5427bf9..7df2d82 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -41,20 +41,22 @@
 MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
 MODULE_LICENSE("GPL");
 
-static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs __initdata = 0;
-module_param_array_named(map, gc, int, &gc_nargs, 0);
-MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+#define GC_MAX_PORTS		3
+#define GC_MAX_DEVICES		5
 
-static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs_2 __initdata = 0;
-module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0);
-MODULE_PARM_DESC(map2, "Describers second set of devices");
+struct gc_config {
+	int args[GC_MAX_DEVICES + 1];
+	int nargs;
+};
 
-static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_nargs_3 __initdata = 0;
-module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0);
-MODULE_PARM_DESC(map3, "Describers third set of devices");
+static struct gc_config gc[GC_MAX_PORTS] __initdata;
+
+module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
+MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
+MODULE_PARM_DESC(map2, "Describes second set of devices");
+module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
+MODULE_PARM_DESC(map3, "Describes third set of devices");
 
 __obsolete_setup("gc=");
 __obsolete_setup("gc_2=");
@@ -77,12 +79,12 @@
 
 struct gc {
 	struct pardevice *pd;
-	struct input_dev dev[5];
+	struct input_dev *dev[GC_MAX_DEVICES];
 	struct timer_list timer;
 	unsigned char pads[GC_MAX + 1];
 	int used;
 	struct semaphore sem;
-	char phys[5][32];
+	char phys[GC_MAX_DEVICES][32];
 };
 
 static struct gc *gc_base[3];
@@ -330,7 +332,6 @@
 static void gc_timer(unsigned long private)
 {
 	struct gc *gc = (void *) private;
-	struct input_dev *dev = gc->dev;
 	unsigned char data[GC_MAX_LENGTH];
 	unsigned char data_psx[5][GC_PSX_BYTES];
 	int i, j, s;
@@ -357,16 +358,16 @@
 					if (data[31 - j] & s) axes[1] |= 1 << j;
 				}
 
-				input_report_abs(dev + i, ABS_X,  axes[0]);
-				input_report_abs(dev + i, ABS_Y, -axes[1]);
+				input_report_abs(gc->dev[i], ABS_X,  axes[0]);
+				input_report_abs(gc->dev[i], ABS_Y, -axes[1]);
 
-				input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
-				input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
+				input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
+				input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
 
 				for (j = 0; j < 10; j++)
-					input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
+					input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
 
-				input_sync(dev + i);
+				input_sync(gc->dev[i]);
 			}
 		}
 	}
@@ -384,19 +385,19 @@
 			s = gc_status_bit[i];
 
 			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
-				input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
-				input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
+				input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
+				input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
 			}
 
 			if (s & gc->pads[GC_NES])
 				for (j = 0; j < 4; j++)
-					input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
+					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
 
 			if (s & gc->pads[GC_SNES])
 				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
+					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
 
-			input_sync(dev + i);
+			input_sync(gc->dev[i]);
 		}
 	}
 
@@ -413,15 +414,15 @@
 			s = gc_status_bit[i];
 
 			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
-				input_report_abs(dev + i, ABS_X,  !(s & data[2]) - !(s & data[3]));
-				input_report_abs(dev + i, ABS_Y,  !(s & data[0]) - !(s & data[1]));
-				input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
+				input_report_abs(gc->dev[i], ABS_X,  !(s & data[2]) - !(s & data[3]));
+				input_report_abs(gc->dev[i], ABS_Y,  !(s & data[0]) - !(s & data[1]));
+				input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
 			}
 
 			if (s & gc->pads[GC_MULTI2])
-				input_report_key(dev + i, BTN_THUMB, s & data[5]);
+				input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);
 
-			input_sync(dev + i);
+			input_sync(gc->dev[i]);
 		}
 	}
 
@@ -438,44 +439,44 @@
 
 				case GC_PSX_RUMBLE:
 
-					input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
-					input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
+					input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
+					input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);
 
 				case GC_PSX_NEGCON:
 				case GC_PSX_ANALOG:
 
-					if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+					if (gc->pads[GC_DDR] & gc_status_bit[i]) {
 						for(j = 0; j < 4; j++)
-							input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
 					} else {
 						for (j = 0; j < 4; j++)
-							input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
+							input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);
 
-						input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
-						input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
 					}
 
 					for (j = 0; j < 8; j++)
-						input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
+						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-					input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
-					input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
+					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);
+					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-					input_sync(dev + i);
+					input_sync(gc->dev[i]);
 
 					break;
 
 				case GC_PSX_NORMAL:
-					if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+					if (gc->pads[GC_DDR] & gc_status_bit[i]) {
 						for(j = 0; j < 4; j++)
-							input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
 					} else {
-						input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
-						input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
 
 						/* for some reason if the extra axes are left unset they drift */
 						/* for (j = 0; j < 4; j++)
-							input_report_abs(dev + i, gc_psx_abs[j+2], 128);
+							input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
 						 * This needs to be debugged properly,
 						 * maybe fuzz processing needs to be done in input_sync()
 						 *				 --vojtech
@@ -483,12 +484,12 @@
 					}
 
 					for (j = 0; j < 8; j++)
-						input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
+						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-					input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
-					input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
+					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);
+					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-					input_sync(dev + i);
+					input_sync(gc->dev[i]);
 
 					break;
 
@@ -533,177 +534,212 @@
 	up(&gc->sem);
 }
 
-static struct gc __init *gc_probe(int *config, int nargs)
+static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
+{
+	struct input_dev *input_dev;
+	int i;
+
+	if (!pad_type)
+		return 0;
+
+	if (pad_type < 1 || pad_type > GC_MAX) {
+		printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
+		return -EINVAL;
+	}
+
+	gc->dev[idx] = input_dev = input_allocate_device();
+	if (!input_dev) {
+		printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");
+		return -ENOMEM;
+	}
+
+	input_dev->name = gc_names[pad_type];
+	input_dev->phys = gc->phys[idx];
+	input_dev->id.bustype = BUS_PARPORT;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = pad_type;
+	input_dev->id.version = 0x0100;
+	input_dev->private = gc;
+
+	input_dev->open = gc_open;
+	input_dev->close = gc_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; i < 2; i++)
+		input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
+
+	gc->pads[0] |= gc_status_bit[idx];
+	gc->pads[pad_type] |= gc_status_bit[idx];
+
+	switch (pad_type) {
+
+		case GC_N64:
+			for (i = 0; i < 10; i++)
+				set_bit(gc_n64_btn[i], input_dev->keybit);
+
+			for (i = 0; i < 2; i++) {
+				input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);
+				input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
+			}
+
+			break;
+
+		case GC_SNES:
+			for (i = 4; i < 8; i++)
+				set_bit(gc_snes_btn[i], input_dev->keybit);
+		case GC_NES:
+			for (i = 0; i < 4; i++)
+				set_bit(gc_snes_btn[i], input_dev->keybit);
+			break;
+
+		case GC_MULTI2:
+			set_bit(BTN_THUMB, input_dev->keybit);
+		case GC_MULTI:
+			set_bit(BTN_TRIGGER, input_dev->keybit);
+			break;
+
+		case GC_PSX:
+			for (i = 0; i < 6; i++)
+				input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);
+			for (i = 0; i < 12; i++)
+				set_bit(gc_psx_btn[i], input_dev->keybit);
+
+			break;
+
+		case GC_DDR:
+			for (i = 0; i < 4; i++)
+				set_bit(gc_psx_ddr_btn[i], input_dev->keybit);
+			for (i = 0; i < 12; i++)
+				set_bit(gc_psx_btn[i], input_dev->keybit);
+
+			break;
+	}
+
+	return 0;
+}
+
+static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
 {
 	struct gc *gc;
 	struct parport *pp;
-	int i, j;
+	struct pardevice *pd;
+	int i;
+	int err;
 
-	if (config[0] < 0)
-		return NULL;
-
-	if (nargs < 2) {
-		printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
-		return NULL;
-	}
-
-	pp = parport_find_number(config[0]);
-
+	pp = parport_find_number(parport);
 	if (!pp) {
 		printk(KERN_ERR "gamecon.c: no such parport\n");
-		return NULL;
+		err = -EINVAL;
+		goto err_out;
 	}
 
-	if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) {
-		parport_put_port(pp);
-		return NULL;
+	pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+	if (!pd) {
+		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
+		err = -EBUSY;
+		goto err_put_pp;
+	}
+
+	gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
+	if (!gc) {
+		printk(KERN_ERR "gamecon.c: Not enough memory\n");
+		err = -ENOMEM;
+		goto err_unreg_pardev;
 	}
 
 	init_MUTEX(&gc->sem);
-
-	gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
-	parport_put_port(pp);
-
-	if (!gc->pd) {
-		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
-		kfree(gc);
-		return NULL;
-	}
-
-	parport_claim(gc->pd);
-
+	gc->pd = pd;
 	init_timer(&gc->timer);
 	gc->timer.data = (long) gc;
 	gc->timer.function = gc_timer;
 
-	for (i = 0; i < nargs - 1; i++) {
-
-		if (!config[i + 1])
+	for (i = 0; i < n_pads; i++) {
+		if (!pads[i])
 			continue;
 
-		if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
-			printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
-			continue;
-		}
-
-                gc->dev[i].private = gc;
-                gc->dev[i].open = gc_open;
-                gc->dev[i].close = gc_close;
-
-                gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-		for (j = 0; j < 2; j++) {
-			set_bit(ABS_X + j, gc->dev[i].absbit);
-			gc->dev[i].absmin[ABS_X + j] = -1;
-			gc->dev[i].absmax[ABS_X + j] =  1;
-		}
-
-		gc->pads[0] |= gc_status_bit[i];
-		gc->pads[config[i + 1]] |= gc_status_bit[i];
-
-		switch(config[i + 1]) {
-
-			case GC_N64:
-				for (j = 0; j < 10; j++)
-					set_bit(gc_n64_btn[j], gc->dev[i].keybit);
-
-				for (j = 0; j < 2; j++) {
-					set_bit(ABS_X + j, gc->dev[i].absbit);
-					gc->dev[i].absmin[ABS_X + j] = -127;
-					gc->dev[i].absmax[ABS_X + j] =  126;
-					gc->dev[i].absflat[ABS_X + j] = 2;
-					set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
-					gc->dev[i].absmin[ABS_HAT0X + j] = -1;
-					gc->dev[i].absmax[ABS_HAT0X + j] =  1;
-				}
-
-				break;
-
-			case GC_SNES:
-				for (j = 4; j < 8; j++)
-					set_bit(gc_snes_btn[j], gc->dev[i].keybit);
-			case GC_NES:
-				for (j = 0; j < 4; j++)
-					set_bit(gc_snes_btn[j], gc->dev[i].keybit);
-				break;
-
-			case GC_MULTI2:
-				set_bit(BTN_THUMB, gc->dev[i].keybit);
-			case GC_MULTI:
-				set_bit(BTN_TRIGGER, gc->dev[i].keybit);
-				break;
-
-			case GC_PSX:
-			case GC_DDR:
-				if(config[i + 1] == GC_DDR) {
-					for (j = 0; j < 4; j++)
-						set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
-				} else {
-					for (j = 0; j < 6; j++) {
-						set_bit(gc_psx_abs[j], gc->dev[i].absbit);
-						gc->dev[i].absmin[gc_psx_abs[j]] = 4;
-						gc->dev[i].absmax[gc_psx_abs[j]] = 252;
-						gc->dev[i].absflat[gc_psx_abs[j]] = 2;
-					}
-				}
-
-				for (j = 0; j < 12; j++)
-					set_bit(gc_psx_btn[j], gc->dev[i].keybit);
-
-				break;
-		}
-
 		sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+		err = gc_setup_pad(gc, i, pads[i]);
+		if (err)
+			goto err_free_devs;
 
-                gc->dev[i].name = gc_names[config[i + 1]];
-		gc->dev[i].phys = gc->phys[i];
-                gc->dev[i].id.bustype = BUS_PARPORT;
-                gc->dev[i].id.vendor = 0x0001;
-                gc->dev[i].id.product = config[i + 1];
-                gc->dev[i].id.version = 0x0100;
+		input_register_device(gc->dev[i]);
 	}
 
-	parport_release(gc->pd);
-
 	if (!gc->pads[0]) {
-		parport_unregister_device(gc->pd);
-		kfree(gc);
-		return NULL;
+		printk(KERN_ERR "gamecon.c: No valid devices specified\n");
+		err = -EINVAL;
+		goto err_free_gc;
 	}
 
-	for (i = 0; i < 5; i++)
-		if (gc->pads[0] & gc_status_bit[i]) {
-			input_register_device(gc->dev + i);
-			printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
-		}
-
+	parport_put_port(pp);
 	return gc;
+
+ err_free_devs:
+	while (--i >= 0)
+		input_unregister_device(gc->dev[i]);
+ err_free_gc:
+	kfree(gc);
+ err_unreg_pardev:
+	parport_unregister_device(pd);
+ err_put_pp:
+	parport_put_port(pp);
+ err_out:
+	return ERR_PTR(err);
+}
+
+static void __exit gc_remove(struct gc *gc)
+{
+	int i;
+
+	for (i = 0; i < GC_MAX_DEVICES; i++)
+		if (gc->dev[i])
+			input_unregister_device(gc->dev[i]);
+	parport_unregister_device(gc->pd);
+	kfree(gc);
 }
 
 static int __init gc_init(void)
 {
-	gc_base[0] = gc_probe(gc, gc_nargs);
-	gc_base[1] = gc_probe(gc_2, gc_nargs_2);
-	gc_base[2] = gc_probe(gc_3, gc_nargs_3);
+	int i;
+	int have_dev = 0;
+	int err = 0;
 
-	if (gc_base[0] || gc_base[1] || gc_base[2])
-		return 0;
+	for (i = 0; i < GC_MAX_PORTS; i++) {
+		if (gc[i].nargs == 0 || gc[i].args[0] < 0)
+			continue;
 
-	return -ENODEV;
+		if (gc[i].nargs < 2) {
+			printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
+			err = -EINVAL;
+			break;
+		}
+
+		gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
+		if (IS_ERR(gc_base[i])) {
+			err = PTR_ERR(gc_base[i]);
+			break;
+		}
+
+		have_dev = 1;
+	}
+
+	if (err) {
+		while (--i >= 0)
+			gc_remove(gc_base[i]);
+		return err;
+	}
+
+	return have_dev ? 0 : -ENODEV;
 }
 
 static void __exit gc_exit(void)
 {
-	int i, j;
+	int i;
 
-	for (i = 0; i < 3; i++)
-		if (gc_base[i]) {
-			for (j = 0; j < 5; j++)
-				if (gc_base[i]->pads[0] & gc_status_bit[j])
-					input_unregister_device(gc_base[i]->dev + j);
-			parport_unregister_device(gc_base[i]->pd);
-		}
+	for (i = 0; i < GC_MAX_PORTS; i++)
+		if (gc_base[i])
+			gc_remove(gc_base[i]);
 }
 
 module_init(gc_init);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 8e4f92b..8a3ad45 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/gameport.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Genius Flight 2000 joystick driver"
 
@@ -81,7 +82,7 @@
 
 struct gf2k {
 	struct gameport *gameport;
-	struct input_dev dev;
+	struct input_dev *dev;
 	int reads;
 	int bads;
 	unsigned char id;
@@ -175,7 +176,7 @@
 
 static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
 {
-	struct input_dev *dev = &gf2k->dev;
+	struct input_dev *dev = gf2k->dev;
 	int i, t;
 
 	for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
@@ -239,13 +240,19 @@
 static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct gf2k *gf2k;
+	struct input_dev *input_dev;
 	unsigned char data[GF2K_LENGTH];
 	int i, err;
 
-	if (!(gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL)))
-		return -ENOMEM;
+	gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!gf2k || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
 
 	gf2k->gameport = gameport;
+	gf2k->dev = input_dev;
 
 	gameport_set_drvdata(gameport, gf2k);
 
@@ -295,53 +302,52 @@
 
 	gf2k->length = gf2k_lens[gf2k->id];
 
-	init_input_dev(&gf2k->dev);
+	input_dev->name = gf2k_names[gf2k->id];
+	input_dev->phys = gf2k->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
+	input_dev->id.product = gf2k->id;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &gameport->dev;
+	input_dev->private = gf2k;
 
-	gf2k->dev.private = gf2k;
-	gf2k->dev.open = gf2k_open;
-	gf2k->dev.close = gf2k_close;
-	gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	gf2k->dev.name = gf2k_names[gf2k->id];
-	gf2k->dev.phys = gf2k->phys;
-	gf2k->dev.id.bustype = BUS_GAMEPORT;
-	gf2k->dev.id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
-	gf2k->dev.id.product = gf2k->id;
-	gf2k->dev.id.version = 0x0100;
+	input_dev->open = gf2k_open;
+	input_dev->close = gf2k_close;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = 0; i < gf2k_axes[gf2k->id]; i++)
-		set_bit(gf2k_abs[i], gf2k->dev.absbit);
+		set_bit(gf2k_abs[i], input_dev->absbit);
 
 	for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
-		set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
-		gf2k->dev.absmin[ABS_HAT0X + i] = -1;
-		gf2k->dev.absmax[ABS_HAT0X + i] = 1;
+		set_bit(ABS_HAT0X + i, input_dev->absbit);
+		input_dev->absmin[ABS_HAT0X + i] = -1;
+		input_dev->absmax[ABS_HAT0X + i] = 1;
 	}
 
 	for (i = 0; i < gf2k_joys[gf2k->id]; i++)
-		set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
+		set_bit(gf2k_btn_joy[i], input_dev->keybit);
 
 	for (i = 0; i < gf2k_pads[gf2k->id]; i++)
-		set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
+		set_bit(gf2k_btn_pad[i], input_dev->keybit);
 
 	gf2k_read_packet(gameport, gf2k->length, data);
 	gf2k_read(gf2k, data);
 
 	for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
-		gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
-			  gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
-		gf2k->dev.absmin[gf2k_abs[i]] = 32;
-		gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
-		gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
+		input_dev->absmax[gf2k_abs[i]] = (i < 2) ? input_dev->abs[gf2k_abs[i]] * 2 - 32 :
+			  input_dev->abs[gf2k_abs[0]] + input_dev->abs[gf2k_abs[1]] - 32;
+		input_dev->absmin[gf2k_abs[i]] = 32;
+		input_dev->absfuzz[gf2k_abs[i]] = 8;
+		input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
 	}
 
-	input_register_device(&gf2k->dev);
-	printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
+	input_register_device(gf2k->dev);
 
 	return 0;
 
-fail2:	gameport_close(gameport);
-fail1:	gameport_set_drvdata(gameport, NULL);
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
+	input_free_device(input_dev);
 	kfree(gf2k);
 	return err;
 }
@@ -350,7 +356,7 @@
 {
 	struct gf2k *gf2k = gameport_get_drvdata(gameport);
 
-	input_unregister_device(&gf2k->dev);
+	input_unregister_device(gf2k->dev);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(gf2k);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 9d3f910..a936e7a 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Gravis GrIP protocol joystick driver"
 
@@ -55,7 +56,7 @@
 
 struct grip {
 	struct gameport *gameport;
-	struct input_dev dev[2];
+	struct input_dev *dev[2];
 	unsigned char mode[2];
 	int reads;
 	int bads;
@@ -190,7 +191,7 @@
 
 	for (i = 0; i < 2; i++) {
 
-		dev = grip->dev + i;
+		dev = grip->dev[i];
 		grip->reads++;
 
 		switch (grip->mode[i]) {
@@ -297,6 +298,7 @@
 static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct grip *grip;
+	struct input_dev *input_dev;
 	unsigned int data[GRIP_LENGTH_XT];
 	int i, j, t;
 	int err;
@@ -339,48 +341,56 @@
 	gameport_set_poll_handler(gameport, grip_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	for (i = 0; i < 2; i++)
-		if (grip->mode[i]) {
+	for (i = 0; i < 2; i++) {
+		if (!grip->mode[i])
+			continue;
 
-			sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
-
-			grip->dev[i].private = grip;
-
-			grip->dev[i].open = grip_open;
-			grip->dev[i].close = grip_close;
-
-			grip->dev[i].name = grip_name[grip->mode[i]];
-			grip->dev[i].phys = grip->phys[i];
-			grip->dev[i].id.bustype = BUS_GAMEPORT;
-			grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
-			grip->dev[i].id.product = grip->mode[i];
-			grip->dev[i].id.version = 0x0100;
-
-			grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-			for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
-
-				if (j < grip_cen[grip->mode[i]])
-					input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
-				else if (j < grip_anx[grip->mode[i]])
-					input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
-				else
-					input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
-			}
-
-			for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
-				if (t > 0)
-					set_bit(t, grip->dev[i].keybit);
-
-			printk(KERN_INFO "input: %s on %s\n",
-				grip_name[grip->mode[i]], gameport->phys);
-			input_register_device(grip->dev + i);
+		grip->dev[i] = input_dev = input_allocate_device();
+		if (!input_dev) {
+			err = -ENOMEM;
+			goto fail3;
 		}
 
+		sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
+
+		input_dev->name = grip_name[grip->mode[i]];
+		input_dev->phys = grip->phys[i];
+		input_dev->id.bustype = BUS_GAMEPORT;
+		input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+		input_dev->id.product = grip->mode[i];
+		input_dev->id.version = 0x0100;
+		input_dev->cdev.dev = &gameport->dev;
+		input_dev->private = grip;
+
+		input_dev->open = grip_open;
+		input_dev->close = grip_close;
+
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+		for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
+
+			if (j < grip_cen[grip->mode[i]])
+				input_set_abs_params(input_dev, t, 14, 52, 1, 2);
+			else if (j < grip_anx[grip->mode[i]])
+				input_set_abs_params(input_dev, t, 3, 57, 1, 0);
+			else
+				input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+		}
+
+		for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
+			if (t > 0)
+				set_bit(t, input_dev->keybit);
+
+		input_register_device(grip->dev[i]);
+	}
+
 	return 0;
 
-fail2:	gameport_close(gameport);
-fail1:	gameport_set_drvdata(gameport, NULL);
+ fail3: for (i = 0; i < 2; i++)
+		if (grip->dev[i])
+			input_unregister_device(grip->dev[i]);
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
 	kfree(grip);
 	return err;
 }
@@ -391,8 +401,8 @@
 	int i;
 
 	for (i = 0; i < 2; i++)
-		if (grip->mode[i])
-			input_unregister_device(grip->dev + i);
+		if (grip->dev[i])
+			input_unregister_device(grip->dev[i]);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(grip);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index da17eee..51a9122 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Gravis Grip Multiport driver"
 
@@ -32,23 +33,37 @@
 #define dbg(format, arg...) do {} while (0)
 #endif
 
+#define GRIP_MAX_PORTS	4
 /*
  * Grip multiport state
  */
 
+struct grip_port {
+	struct input_dev *dev;
+	int mode;
+	int registered;
+
+	/* individual gamepad states */
+	int buttons;
+	int xaxes;
+	int yaxes;
+	int dirty;     /* has the state been updated? */
+};
+
 struct grip_mp {
 	struct gameport *gameport;
-	struct input_dev dev[4];
-	int mode[4];
-	int registered[4];
+	struct grip_port *port[GRIP_MAX_PORTS];
+//	struct input_dev *dev[4];
+//	int mode[4];
+//	int registered[4];
 	int reads;
 	int bads;
 
 	/* individual gamepad states */
-	int buttons[4];
-	int xaxes[4];
-	int yaxes[4];
-	int dirty[4];     /* has the state been updated? */
+//	int buttons[4];
+//	int xaxes[4];
+//	int yaxes[4];
+//	int dirty[4];     /* has the state been updated? */
 };
 
 /*
@@ -85,16 +100,16 @@
 #define GRIP_MODE_GP		2
 #define GRIP_MODE_C64		3
 
-static int grip_btn_gp[]  = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
-static int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
+static const int grip_btn_gp[]  = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
+static const int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
 
-static int grip_abs_gp[]  = { ABS_X, ABS_Y, -1 };
-static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_gp[]  = { ABS_X, ABS_Y, -1 };
+static const int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
 
-static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
-static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
+static const int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
+static const int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
 
-static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
+static const char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
 
 static const int init_seq[] = {
 	1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
@@ -104,9 +119,9 @@
 
 /* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
 
-static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
+static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
 
-static void register_slot(int i, struct grip_mp *grip);
+static int register_slot(int i, struct grip_mp *grip);
 
 /*
  * Returns whether an odd or even number of bits are on in pkt.
@@ -353,9 +368,10 @@
 
 static int get_and_decode_packet(struct grip_mp *grip, int flags)
 {
+	struct grip_port *port;
 	u32 packet;
 	int joytype = 0;
-	int slot = 0;
+	int slot;
 
 	/* Get a packet and check for validity */
 
@@ -377,6 +393,8 @@
 	if ((slot < 0) || (slot > 3))
 		return flags;
 
+	port = grip->port[slot];
+
 	/*
 	 * Handle "reset" packets, which occur at startup, and when gamepads
 	 * are removed or plugged in.  May contain configuration of a new gamepad.
@@ -385,14 +403,14 @@
 	joytype = (packet >> 16) & 0x1f;
 	if (!joytype) {
 
-		if (grip->registered[slot]) {
+		if (port->registered) {
 			printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
-			       grip_name[grip->mode[slot]], slot);
-			input_unregister_device(grip->dev + slot);
-			grip->registered[slot] = 0;
+			       grip_name[port->mode], slot);
+			input_unregister_device(port->dev);
+			port->registered = 0;
 		}
 		dbg("Reset: grip multiport slot %d\n", slot);
-		grip->mode[slot] = GRIP_MODE_RESET;
+		port->mode = GRIP_MODE_RESET;
 		flags |= IO_SLOT_CHANGE;
 		return flags;
 	}
@@ -402,17 +420,17 @@
 	if (joytype == 0x1f) {
 
 		int dir = (packet >> 8) & 0xf;          /* eight way directional value */
-		grip->buttons[slot] = (~packet) & 0xff;
-		grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1;
-		grip->xaxes[slot] = (axis_map[dir] & 3) - 1;
-		grip->dirty[slot] = 1;
+		port->buttons = (~packet) & 0xff;
+		port->yaxes = ((axis_map[dir] >> 2) & 3) - 1;
+		port->xaxes = (axis_map[dir] & 3) - 1;
+		port->dirty = 1;
 
-		if (grip->mode[slot] == GRIP_MODE_RESET)
+		if (port->mode == GRIP_MODE_RESET)
 			flags |= IO_SLOT_CHANGE;
 
-		grip->mode[slot] = GRIP_MODE_GP;
+		port->mode = GRIP_MODE_GP;
 
-		if (!grip->registered[slot]) {
+		if (!port->registered) {
 			dbg("New Grip pad in multiport slot %d.\n", slot);
 			register_slot(slot, grip);
 		}
@@ -445,9 +463,9 @@
 		return 0;
 
 	for (slot = 0; slot < 4; slot++) {
-		if (grip->mode[slot] == GRIP_MODE_RESET)
+		if (grip->port[slot]->mode == GRIP_MODE_RESET)
 			invalid = 1;
-		if (grip->mode[slot] != GRIP_MODE_NONE)
+		if (grip->port[slot]->mode != GRIP_MODE_NONE)
 			active = 1;
 	}
 
@@ -484,7 +502,7 @@
 
 	/* Get packets, store multiport state, and check state's validity */
 	for (tries = 0; tries < 4096; tries++) {
-		if ( slots_valid(grip) ) {
+		if (slots_valid(grip)) {
 			initialized = 1;
 			break;
 		}
@@ -499,24 +517,24 @@
 
 static void report_slot(struct grip_mp *grip, int slot)
 {
-	struct input_dev *dev = &(grip->dev[slot]);
-	int i, buttons = grip->buttons[slot];
+	struct grip_port *port = grip->port[slot];
+	int i;
 
 	/* Store button states with linux input driver */
 
 	for (i = 0; i < 8; i++)
-		input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1);
+		input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1);
 
 	/* Store axis states with linux driver */
 
-	input_report_abs(dev, ABS_X, grip->xaxes[slot]);
-	input_report_abs(dev, ABS_Y, grip->yaxes[slot]);
+	input_report_abs(port->dev, ABS_X, port->xaxes);
+	input_report_abs(port->dev, ABS_Y, port->yaxes);
 
 	/* Tell the receiver of the events to process them */
 
-	input_sync(dev);
+	input_sync(port->dev);
 
-	grip->dirty[slot] = 0;
+	port->dirty = 0;
 }
 
 /*
@@ -540,7 +558,7 @@
 	}
 
 	for (i = 0; i < 4; i++)
-		if (grip->dirty[i])
+		if (grip->port[i]->dirty)
 			report_slot(grip, i);
 }
 
@@ -571,35 +589,43 @@
  * Tell the linux input layer about a newly plugged-in gamepad.
  */
 
-static void register_slot(int slot, struct grip_mp *grip)
+static int register_slot(int slot, struct grip_mp *grip)
 {
+	struct grip_port *port = grip->port[slot];
+	struct input_dev *input_dev;
 	int j, t;
 
-	grip->dev[slot].private = grip;
-	grip->dev[slot].open = grip_open;
-	grip->dev[slot].close = grip_close;
-	grip->dev[slot].name = grip_name[grip->mode[slot]];
-	grip->dev[slot].id.bustype = BUS_GAMEPORT;
-	grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
-	grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
-	grip->dev[slot].id.version = 0x0100;
-	grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	port->dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
-	for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
-		input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
+	input_dev->name = grip_name[port->mode];
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
+	input_dev->id.product = 0x0100 + port->mode;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &grip->gameport->dev;
+	input_dev->private = grip;
 
-	for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
+	input_dev->open = grip_open;
+	input_dev->close = grip_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++)
+		input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+
+	for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++)
 		if (t > 0)
-			set_bit(t, grip->dev[slot].keybit);
+			set_bit(t, input_dev->keybit);
 
-	input_register_device(grip->dev + slot);
-	grip->registered[slot] = 1;
+	input_register_device(port->dev);
+	port->registered = 1;
 
-	if (grip->dirty[slot])	            /* report initial state, if any */
+	if (port->dirty)	            /* report initial state, if any */
 		report_slot(grip, slot);
 
-	printk(KERN_INFO "grip_mp: added %s, slot %d\n",
-	       grip_name[grip->mode[slot]], slot);
+	return 0;
 }
 
 static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
@@ -626,7 +652,7 @@
 		goto fail2;
 	}
 
-	if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+	if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) {
 		/* nothing plugged in */
 		err = -ENODEV;
 		goto fail2;
@@ -646,8 +672,8 @@
 	int i;
 
 	for (i = 0; i < 4; i++)
-		if (grip->registered[i])
-			input_unregister_device(grip->dev + i);
+		if (grip->port[i]->registered)
+			input_unregister_device(grip->port[i]->dev);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(grip);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 6a70ec4..6e2c721 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Guillemot Digital joystick driver"
 
@@ -67,7 +68,7 @@
 
 struct guillemot {
 	struct gameport *gameport;
-	struct input_dev dev;
+	struct input_dev *dev;
 	int bads;
 	int reads;
 	struct guillemot_type *type;
@@ -123,7 +124,7 @@
 static void guillemot_poll(struct gameport *gameport)
 {
 	struct guillemot *guillemot = gameport_get_drvdata(gameport);
-	struct input_dev *dev = &guillemot->dev;
+	struct input_dev *dev = guillemot->dev;
 	u8 data[GUILLEMOT_MAX_LENGTH];
 	int i;
 
@@ -179,14 +180,20 @@
 static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct guillemot *guillemot;
+	struct input_dev *input_dev;
 	u8 data[GUILLEMOT_MAX_LENGTH];
 	int i, t;
 	int err;
 
-	if (!(guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL)))
-		return -ENOMEM;
+	guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!guillemot || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
 
 	guillemot->gameport = gameport;
+	guillemot->dev = input_dev;
 
 	gameport_set_drvdata(gameport, guillemot);
 
@@ -216,41 +223,40 @@
 	gameport_set_poll_interval(gameport, 20);
 
 	sprintf(guillemot->phys, "%s/input0", gameport->phys);
-
 	guillemot->type = guillemot_type + i;
 
-	guillemot->dev.private = guillemot;
-	guillemot->dev.open = guillemot_open;
-	guillemot->dev.close = guillemot_close;
+	input_dev->name = guillemot_type[i].name;
+	input_dev->phys = guillemot->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
+	input_dev->id.product = guillemot_type[i].id;
+	input_dev->id.version = (int)data[14] << 8 | data[15];
+	input_dev->cdev.dev = &gameport->dev;
+	input_dev->private = guillemot;
 
-	guillemot->dev.name = guillemot_type[i].name;
-	guillemot->dev.phys = guillemot->phys;
-	guillemot->dev.id.bustype = BUS_GAMEPORT;
-	guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
-	guillemot->dev.id.product = guillemot_type[i].id;
-	guillemot->dev.id.version = (int)data[14] << 8 | data[15];
+	input_dev->open = guillemot_open;
+	input_dev->close = guillemot_close;
 
-	guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
-		input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
+		input_set_abs_params(input_dev, t, 0, 255, 0, 0);
 
 	if (guillemot->type->hat) {
-		input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
-		input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
+		input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+		input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
 	}
 
 	for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
-		set_bit(t, guillemot->dev.keybit);
+		set_bit(t, input_dev->keybit);
 
-	input_register_device(&guillemot->dev);
-	printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
-		guillemot->type->name, data[14], data[15], gameport->phys);
+	input_register_device(guillemot->dev);
 
 	return 0;
 
 fail2:	gameport_close(gameport);
 fail1:  gameport_set_drvdata(gameport, NULL);
+	input_free_device(input_dev);
 	kfree(guillemot);
 	return err;
 }
@@ -260,7 +266,7 @@
 	struct guillemot *guillemot = gameport_get_drvdata(gameport);
 
 	printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
-	input_unregister_device(&guillemot->dev);
+	input_unregister_device(guillemot->dev);
 	gameport_close(gameport);
 	kfree(guillemot);
 }
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index e31b7b9..64b9c31 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -144,7 +144,7 @@
 	int is_update;
 
 /* Check this effect type is supported by this device */
-	if (!test_bit(effect->type, iforce->dev.ffbit))
+	if (!test_bit(effect->type, iforce->dev->ffbit))
 		return -EINVAL;
 
 /*
@@ -152,30 +152,31 @@
  */
 	if (effect->id == -1) {
 
-		for (id=0; id < FF_EFFECTS_MAX; ++id)
-			if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
+		for (id = 0; id < FF_EFFECTS_MAX; ++id)
+			if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags))
+				break;
 
-		if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
+		if (id == FF_EFFECTS_MAX || id >= iforce->dev->ff_effects_max)
 			return -ENOMEM;
 
 		effect->id = id;
 		iforce->core_effects[id].owner = current->pid;
-		iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED);	/* Only IS_USED bit must be set */
+		iforce->core_effects[id].flags[0] = (1 << FF_CORE_IS_USED);	/* Only IS_USED bit must be set */
 
 		is_update = FALSE;
 	}
 	else {
 		/* We want to update an effect */
-		if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES;
+		if (!CHECK_OWNERSHIP(effect->id, iforce))
+			return -EACCES;
 
 		/* Parameter type cannot be updated */
 		if (effect->type != iforce->core_effects[effect->id].effect.type)
 			return -EINVAL;
 
 		/* Check the effect is not already being updated */
-		if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
+		if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags))
 			return -EAGAIN;
-		}
 
 		is_update = TRUE;
 	}
@@ -339,15 +340,19 @@
 
 int iforce_init_device(struct iforce *iforce)
 {
+	struct input_dev *input_dev;
 	unsigned char c[] = "CEOV";
 	int i;
 
+	input_dev = input_allocate_device();
+	if (input_dev)
+		return -ENOMEM;
+
 	init_waitqueue_head(&iforce->wait);
 	spin_lock_init(&iforce->xmit_lock);
 	init_MUTEX(&iforce->mem_mutex);
 	iforce->xmit.buf = iforce->xmit_data;
-
-	iforce->dev.ff_effects_max = 10;
+	iforce->dev = input_dev;
 
 /*
  * Input device fields.
@@ -356,26 +361,27 @@
 	switch (iforce->bus) {
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
 	case IFORCE_USB:
-		iforce->dev.id.bustype = BUS_USB;
-		iforce->dev.dev = &iforce->usbdev->dev;
+		input_dev->id.bustype = BUS_USB;
+		input_dev->cdev.dev = &iforce->usbdev->dev;
 		break;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
 	case IFORCE_232:
-		iforce->dev.id.bustype = BUS_RS232;
-		iforce->dev.dev = &iforce->serio->dev;
+		input_dev->id.bustype = BUS_RS232;
+		input_dev->cdev.dev = &iforce->serio->dev;
 		break;
 #endif
 	}
 
-	iforce->dev.private = iforce;
-	iforce->dev.name = "Unknown I-Force device";
-	iforce->dev.open = iforce_open;
-	iforce->dev.close = iforce_release;
-	iforce->dev.flush = iforce_flush;
-	iforce->dev.event = iforce_input_event;
-	iforce->dev.upload_effect = iforce_upload_effect;
-	iforce->dev.erase_effect = iforce_erase_effect;
+	input_dev->private = iforce;
+	input_dev->name = "Unknown I-Force device";
+	input_dev->open = iforce_open;
+	input_dev->close = iforce_release;
+	input_dev->flush = iforce_flush;
+	input_dev->event = iforce_input_event;
+	input_dev->upload_effect = iforce_upload_effect;
+	input_dev->erase_effect = iforce_erase_effect;
+	input_dev->ff_effects_max = 10;
 
 /*
  * On-device memory allocation.
@@ -399,7 +405,8 @@
 
 	if (i == 20) { /* 5 seconds */
 		printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
-		return -1;
+		input_free_device(input_dev);
+		return -ENODEV;
 	}
 
 /*
@@ -407,12 +414,12 @@
  */
 
 	if (!iforce_get_id_packet(iforce, "M"))
-		iforce->dev.id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
+		input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
 		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
 
 	if (!iforce_get_id_packet(iforce, "P"))
-		iforce->dev.id.product = (iforce->edata[2] << 8) | iforce->edata[1];
+		input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
 	else
 		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
 
@@ -422,15 +429,15 @@
 		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
 
 	if (!iforce_get_id_packet(iforce, "N"))
-		iforce->dev.ff_effects_max = iforce->edata[1];
+		iforce->dev->ff_effects_max = iforce->edata[1];
 	else
 		printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
 
 	/* Check if the device can store more effects than the driver can really handle */
-	if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
+	if (iforce->dev->ff_effects_max > FF_EFFECTS_MAX) {
 		printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n",
-			iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
-		iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
+			iforce->dev->ff_effects_max, FF_EFFECTS_MAX);
+		iforce->dev->ff_effects_max = FF_EFFECTS_MAX;
 	}
 
 /*
@@ -453,29 +460,28 @@
  */
 
 	for (i = 0; iforce_device[i].idvendor; i++)
-		if (iforce_device[i].idvendor == iforce->dev.id.vendor &&
-		    iforce_device[i].idproduct == iforce->dev.id.product)
+		if (iforce_device[i].idvendor == input_dev->id.vendor &&
+		    iforce_device[i].idproduct == input_dev->id.product)
 			break;
 
 	iforce->type = iforce_device + i;
-	iforce->dev.name = iforce->type->name;
+	input_dev->name = iforce->type->name;
 
 /*
  * Set input device bitfields and ranges.
  */
 
-	iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
 
 	for (i = 0; iforce->type->btn[i] >= 0; i++) {
 		signed short t = iforce->type->btn[i];
-		set_bit(t, iforce->dev.keybit);
+		set_bit(t, input_dev->keybit);
 	}
-	set_bit(BTN_DEAD, iforce->dev.keybit);
+	set_bit(BTN_DEAD, input_dev->keybit);
 
 	for (i = 0; iforce->type->abs[i] >= 0; i++) {
 
 		signed short t = iforce->type->abs[i];
-		set_bit(t, iforce->dev.absbit);
 
 		switch (t) {
 
@@ -483,52 +489,42 @@
 			case ABS_Y:
 			case ABS_WHEEL:
 
-				iforce->dev.absmax[t] =  1920;
-				iforce->dev.absmin[t] = -1920;
-				iforce->dev.absflat[t] = 128;
-				iforce->dev.absfuzz[t] = 16;
-
-				set_bit(t, iforce->dev.ffbit);
+				input_set_abs_params(input_dev, t, -1920, 1920, 16, 128);
+				set_bit(t, input_dev->ffbit);
 				break;
 
 			case ABS_THROTTLE:
 			case ABS_GAS:
 			case ABS_BRAKE:
 
-				iforce->dev.absmax[t] = 255;
-				iforce->dev.absmin[t] = 0;
+				input_set_abs_params(input_dev, t, 0, 255, 0, 0);
 				break;
 
 			case ABS_RUDDER:
 
-				iforce->dev.absmax[t] = 127;
-				iforce->dev.absmin[t] = -128;
+				input_set_abs_params(input_dev, t, -128, 127, 0, 0);
 				break;
 
 			case ABS_HAT0X:
 			case ABS_HAT0Y:
 		        case ABS_HAT1X:
 		        case ABS_HAT1Y:
-				iforce->dev.absmax[t] =  1;
-				iforce->dev.absmin[t] = -1;
+
+				input_set_abs_params(input_dev, t, -1, 1, 0, 0);
 				break;
 		}
 	}
 
 	for (i = 0; iforce->type->ff[i] >= 0; i++)
-		set_bit(iforce->type->ff[i], iforce->dev.ffbit);
+		set_bit(iforce->type->ff[i], input_dev->ffbit);
 
 /*
  * Register input device.
  */
 
-	input_register_device(&iforce->dev);
+	input_register_device(iforce->dev);
 
-	printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open);
-
-	printk(KERN_INFO "input: %s [%d effects, %ld bytes memory]\n",
-		iforce->dev.name, iforce->dev.ff_effects_max,
-		iforce->device_memory.end);
+	printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
 
 	return 0;
 }
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index e5a31e5..4a26292 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -139,7 +139,8 @@
 static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
 {
 	int i;
-	for (i=0; i<iforce->dev.ff_effects_max; ++i) {
+
+	for (i = 0; i < iforce->dev->ff_effects_max; ++i) {
 		if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
 		    (iforce->core_effects[i].mod1_chunk.start == addr ||
 		     iforce->core_effects[i].mod2_chunk.start == addr)) {
@@ -153,7 +154,7 @@
 
 void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &iforce->dev;
+	struct input_dev *dev = iforce->dev;
 	int i;
 	static int being_used = 0;
 
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 11f5190..64a78c5 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -131,11 +131,10 @@
 	struct iforce *iforce;
 	int err;
 
-	if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
+	iforce = kzalloc(sizeof(struct iforce), GFP_KERNEL);
+	if (!iforce)
 		return -ENOMEM;
 
-	memset(iforce, 0, sizeof(struct iforce));
-
 	iforce->bus = IFORCE_232;
 	iforce->serio = serio;
 
@@ -148,7 +147,8 @@
 		return err;
 	}
 
-	if (iforce_init_device(iforce)) {
+	err = iforce_init_device(iforce);
+	if (err) {
 		serio_close(serio);
 		serio_set_drvdata(serio, NULL);
 		kfree(iforce);
@@ -162,7 +162,7 @@
 {
 	struct iforce *iforce = serio_get_drvdata(serio);
 
-	input_unregister_device(&iforce->dev);
+	input_unregister_device(iforce->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
 	kfree(iforce);
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 58600f9..64b4a30 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -135,28 +135,24 @@
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *epirq, *epout;
 	struct iforce *iforce;
+	int err = -ENOMEM;
 
 	interface = intf->cur_altsetting;
 
 	epirq = &interface->endpoint[0].desc;
 	epout = &interface->endpoint[1].desc;
 
-	if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
+	if (!(iforce = kzalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
 		goto fail;
 
-	memset(iforce, 0, sizeof(struct iforce));
-
-	if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) {
+	if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL)))
 		goto fail;
-	}
 
-	if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) {
+	if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL)))
 		goto fail;
-	}
 
-	if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) {
+	if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL)))
 		goto fail;
-	}
 
 	iforce->bus = IFORCE_USB;
 	iforce->usbdev = dev;
@@ -174,7 +170,9 @@
 	usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
 			(void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
 
-	if (iforce_init_device(iforce)) goto fail;
+	err = iforce_init_device(iforce);
+	if (err)
+		goto fail;
 
 	usb_set_intfdata(intf, iforce);
 	return 0;
@@ -187,7 +185,7 @@
 		kfree(iforce);
 	}
 
-	return -ENODEV;
+	return err;
 }
 
 /* Called by iforce_delete() */
@@ -211,7 +209,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (iforce) {
 		iforce->usbdev = NULL;
-		input_unregister_device(&iforce->dev);
+		input_unregister_device(iforce->dev);
 
 		if (!open) {
 			iforce_delete_device(iforce);
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index bce247b..146f406 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -117,7 +117,7 @@
 };
 
 struct iforce {
-	struct input_dev dev;		/* Input device interface */
+	struct input_dev *dev;		/* Input device interface */
 	struct iforce_device *type;
 	int bus;
 
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index d7b3472..c4ed017 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"InterAct digital joystick driver"
 
@@ -54,7 +55,7 @@
 
 struct interact {
 	struct gameport *gameport;
-	struct input_dev dev;
+	struct input_dev *dev;
 	int bads;
 	int reads;
 	unsigned char type;
@@ -130,7 +131,7 @@
 static void interact_poll(struct gameport *gameport)
 {
 	struct interact *interact = gameport_get_drvdata(gameport);
-	struct input_dev *dev = &interact->dev;
+	struct input_dev *dev = interact->dev;
 	u32 data[3];
 	int i;
 
@@ -208,14 +209,20 @@
 static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct interact *interact;
+	struct input_dev *input_dev;
 	__u32 data[3];
 	int i, t;
 	int err;
 
-	if (!(interact = kzalloc(sizeof(struct interact), GFP_KERNEL)))
-		return -ENOMEM;
+	interact = kzalloc(sizeof(struct interact), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!interact || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
 
 	interact->gameport = gameport;
+	interact->dev = input_dev;
 
 	gameport_set_drvdata(gameport, interact);
 
@@ -249,41 +256,40 @@
 	interact->type = i;
 	interact->length = interact_type[i].length;
 
-	interact->dev.private = interact;
-	interact->dev.open = interact_open;
-	interact->dev.close = interact_close;
+	input_dev->name = interact_type[i].name;
+	input_dev->phys = interact->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
+	input_dev->id.product = interact_type[i].id;
+	input_dev->id.version = 0x0100;
+	input_dev->private = interact;
 
-	interact->dev.name = interact_type[i].name;
-	interact->dev.phys = interact->phys;
-	interact->dev.id.bustype = BUS_GAMEPORT;
-	interact->dev.id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
-	interact->dev.id.product = interact_type[i].id;
-	interact->dev.id.version = 0x0100;
+	input_dev->open = interact_open;
+	input_dev->close = interact_close;
 
-	interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
-		set_bit(t, interact->dev.absbit);
+		set_bit(t, input_dev->absbit);
 		if (i < interact_type[interact->type].b8) {
-			interact->dev.absmin[t] = 0;
-			interact->dev.absmax[t] = 255;
+			input_dev->absmin[t] = 0;
+			input_dev->absmax[t] = 255;
 		} else {
-			interact->dev.absmin[t] = -1;
-			interact->dev.absmax[t] = 1;
+			input_dev->absmin[t] = -1;
+			input_dev->absmax[t] = 1;
 		}
 	}
 
 	for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
-		set_bit(t, interact->dev.keybit);
+		set_bit(t, input_dev->keybit);
 
-	input_register_device(&interact->dev);
-	printk(KERN_INFO "input: %s on %s\n",
-		interact_type[interact->type].name, gameport->phys);
+	input_register_device(interact->dev);
 
 	return 0;
 
 fail2:	gameport_close(gameport);
 fail1:  gameport_set_drvdata(gameport, NULL);
+	input_free_device(input_dev);
 	kfree(interact);
 	return err;
 }
@@ -292,7 +298,7 @@
 {
 	struct interact *interact = gameport_get_drvdata(gameport);
 
-	input_unregister_device(&interact->dev);
+	input_unregister_device(interact->dev);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(interact);
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index 4234cca..88ec5a91 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #define DRIVER_DESC	"Gameport data dumper module"
 
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 1ba5036..ca3cc23 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -49,14 +49,13 @@
 
 static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
 static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
 
 /*
  * Per-Magellan data.
  */
 
 struct magellan {
-	struct input_dev dev;
+	struct input_dev *dev;
 	int idx;
 	unsigned char data[MAGELLAN_MAX_LENGTH];
 	char phys[32];
@@ -85,7 +84,7 @@
 
 static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
 {
-	struct input_dev *dev = &magellan->dev;
+	struct input_dev *dev = magellan->dev;
 	unsigned char *data = magellan->data;
 	int i, t;
 
@@ -138,9 +137,9 @@
 {
 	struct magellan* magellan = serio_get_drvdata(serio);
 
-	input_unregister_device(&magellan->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(magellan->dev);
 	kfree(magellan);
 }
 
@@ -153,52 +152,48 @@
 static int magellan_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct magellan *magellan;
-	int i, t;
-	int err;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
+	int i;
 
-	if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
-		return -ENOMEM;
+	magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!magellan || !input_dev)
+		goto fail;
 
-	memset(magellan, 0, sizeof(struct magellan));
-
-	magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	for (i = 0; i < 9; i++)
-		set_bit(magellan_buttons[i], magellan->dev.keybit);
-
-	for (i = 0; i < 6; i++) {
-		t = magellan_axes[i];
-		set_bit(t, magellan->dev.absbit);
-		magellan->dev.absmin[t] = -360;
-		magellan->dev.absmax[t] =  360;
-	}
-
+	magellan->dev = input_dev;
 	sprintf(magellan->phys, "%s/input0", serio->phys);
 
-	init_input_dev(&magellan->dev);
-	magellan->dev.private = magellan;
-	magellan->dev.name = magellan_name;
-	magellan->dev.phys = magellan->phys;
-	magellan->dev.id.bustype = BUS_RS232;
-	magellan->dev.id.vendor = SERIO_MAGELLAN;
-	magellan->dev.id.product = 0x0001;
-	magellan->dev.id.version = 0x0100;
-	magellan->dev.dev = &serio->dev;
+	input_dev->name = "LogiCad3D Magellan / SpaceMouse";
+	input_dev->phys = magellan->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_MAGELLAN;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = magellan;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; i < 9; i++)
+		set_bit(magellan_buttons[i], input_dev->keybit);
+
+	for (i = 0; i < 6; i++)
+		input_set_abs_params(input_dev, magellan_axes[i], -360, 360, 0, 0);
 
 	serio_set_drvdata(serio, magellan);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(magellan);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&magellan->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
-
+	input_register_device(magellan->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(magellan);
+	return err;
 }
 
 /*
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 9e03537..78dd163 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/gameport.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"Microsoft SideWinder joystick family driver"
 
@@ -113,7 +114,7 @@
 
 struct sw {
 	struct gameport *gameport;
-	struct input_dev dev[4];
+	struct input_dev *dev[4];
 	char name[64];
 	char phys[4][32];
 	int length;
@@ -301,7 +302,7 @@
 static int sw_parse(unsigned char *buf, struct sw *sw)
 {
 	int hat, i, j;
-	struct input_dev *dev = sw->dev;
+	struct input_dev *dev;
 
 	switch (sw->type) {
 
@@ -310,6 +311,8 @@
 			if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
 				return -1;
 
+			dev = sw->dev[0];
+
 			input_report_abs(dev, ABS_X,        (GB( 3,3) << 7) | GB(16,7));
 			input_report_abs(dev, ABS_Y,        (GB( 0,3) << 7) | GB(24,7));
 			input_report_abs(dev, ABS_RZ,       (GB(35,2) << 7) | GB(40,7));
@@ -335,13 +338,13 @@
 				if (sw_parity(GB(i*15,15)))
 					return -1;
 
-				input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
-				input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
+				input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
+				input_report_abs(sw->dev[i], ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
 
 				for (j = 0; j < 10; j++)
-					input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
+					input_report_key(sw->dev[i], sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
 
-				input_sync(dev + i);
+				input_sync(sw->dev[i]);
 			}
 
 			return 0;
@@ -352,6 +355,7 @@
 			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
 				return -1;
 
+			dev = sw->dev[0];
 			input_report_abs(dev, ABS_X,        GB( 9,10));
 			input_report_abs(dev, ABS_Y,        GB(19,10));
 			input_report_abs(dev, ABS_RZ,       GB(36, 6));
@@ -372,6 +376,7 @@
 			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
 				return -1;
 
+			dev = sw->dev[0];
 			input_report_abs(dev, ABS_X,        GB( 0,10));
 			input_report_abs(dev, ABS_Y,        GB(16,10));
 			input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
@@ -396,6 +401,7 @@
 			if (!sw_parity(GB(0,33)))
 				return -1;
 
+			dev = sw->dev[0];
 			input_report_abs(dev, ABS_RX,       GB( 0,10));
 			input_report_abs(dev, ABS_RUDDER,   GB(10, 6));
 			input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
@@ -581,6 +587,7 @@
 static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct sw *sw;
+	struct input_dev *input_dev;
 	int i, j, k, l;
 	int err;
 	unsigned char *buf = NULL;	/* [SW_LENGTH] */
@@ -729,42 +736,50 @@
 		sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
 		sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
 
-		sw->dev[i].private = sw;
+		input_dev = input_allocate_device();
+		if (!input_dev) {
+			err = -ENOMEM;
+			goto fail3;
+		}
 
-		sw->dev[i].open = sw_open;
-		sw->dev[i].close = sw_close;
+		input_dev->name = sw->name;
+		input_dev->phys = sw->phys[i];
+		input_dev->id.bustype = BUS_GAMEPORT;
+		input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
+		input_dev->id.product = sw->type;
+		input_dev->id.version = 0x0100;
+		input_dev->cdev.dev = &gameport->dev;
+		input_dev->private = sw;
 
-		sw->dev[i].name = sw->name;
-		sw->dev[i].phys = sw->phys[i];
-		sw->dev[i].id.bustype = BUS_GAMEPORT;
-		sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
-		sw->dev[i].id.product = sw->type;
-		sw->dev[i].id.version = 0x0100;
+		input_dev->open = sw_open;
+		input_dev->close = sw_close;
 
-		sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 		for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
 			code = sw_abs[sw->type][j];
-			set_bit(code, sw->dev[i].absbit);
-			sw->dev[i].absmax[code] = (1 << bits) - 1;
-			sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
-			sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
+			set_bit(code, input_dev->absbit);
+			input_dev->absmax[code] = (1 << bits) - 1;
+			input_dev->absmin[code] = (bits == 1) ? -1 : 0;
+			input_dev->absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
 			if (code != ABS_THROTTLE)
-				sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
+				input_dev->absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
 		}
 
 		for (j = 0; (code = sw_btn[sw->type][j]); j++)
-			set_bit(code, sw->dev[i].keybit);
+			set_bit(code, input_dev->keybit);
 
-		input_register_device(sw->dev + i);
-		printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
-			sw->name, comment, gameport->phys, m, l, k);
+		dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);
+
+		input_register_device(sw->dev[i]);
 	}
 
 	return 0;
 
-fail2:	gameport_close(gameport);
-fail1:	gameport_set_drvdata(gameport, NULL);
+ fail3: while (--i >= 0)
+		input_unregister_device(sw->dev[i]);
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
 	kfree(sw);
 	kfree(buf);
 	kfree(idbuf);
@@ -777,7 +792,7 @@
 	int i;
 
 	for (i = 0; i < sw->number; i++)
-		input_unregister_device(sw->dev + i);
+		input_unregister_device(sw->dev[i]);
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(sw);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index a436f22..d6f8db8 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -70,8 +70,7 @@
  */
 
 struct spaceball {
-	struct input_dev dev;
-	struct serio *serio;
+	struct input_dev *dev;
 	int idx;
 	int escape;
 	unsigned char data[SPACEBALL_MAX_LENGTH];
@@ -85,7 +84,7 @@
 
 static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
 {
-	struct input_dev *dev = &spaceball->dev;
+	struct input_dev *dev = spaceball->dev;
 	unsigned char *data = spaceball->data;
 	int i;
 
@@ -193,9 +192,9 @@
 {
 	struct spaceball* spaceball = serio_get_drvdata(serio);
 
-	input_unregister_device(&spaceball->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(spaceball->dev);
 	kfree(spaceball);
 }
 
@@ -208,69 +207,62 @@
 static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceball *spaceball;
-	int i, t, id;
-	int err;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
+	int i, id;
 
 	if ((id = serio->id.id) > SPACEBALL_MAX_ID)
 		return -ENODEV;
 
-	if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
-		return - ENOMEM;
+	spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!spaceball || !input_dev)
+		goto fail;
 
-	memset(spaceball, 0, sizeof(struct spaceball));
+	spaceball->dev = input_dev;
+	sprintf(spaceball->phys, "%s/input0", serio->phys);
 
-	spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->name = spaceball_names[id];
+	input_dev->phys = spaceball->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_SPACEBALL;
+	input_dev->id.product = id;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = spaceball;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 	switch (id) {
 		case SPACEBALL_4000FLX:
 		case SPACEBALL_4000FLX_L:
-			spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9);
-			spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
+			input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_9);
+			input_dev->keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
 		default:
-			spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
+			input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
 				| BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
 		case SPACEBALL_3003C:
-			spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
+			input_dev->keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
 	}
 
-	for (i = 0; i < 6; i++) {
-		t = spaceball_axes[i];
-		set_bit(t, spaceball->dev.absbit);
-		spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
-		spaceball->dev.absmax[t] = i < 3 ?  8000 :  1600;
-		spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
-		spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
+	for (i = 0; i < 3; i++) {
+		input_set_abs_params(input_dev, ABS_X + i, -8000, 8000, 8, 40);
+		input_set_abs_params(input_dev, ABS_RX + i, -1600, 1600, 2, 8);
 	}
 
-	spaceball->serio = serio;
-	spaceball->dev.private = spaceball;
-
-	sprintf(spaceball->phys, "%s/input0", serio->phys);
-
-	init_input_dev(&spaceball->dev);
-	spaceball->dev.name = spaceball_names[id];
-	spaceball->dev.phys = spaceball->phys;
-	spaceball->dev.id.bustype = BUS_RS232;
-	spaceball->dev.id.vendor = SERIO_SPACEBALL;
-	spaceball->dev.id.product = id;
-	spaceball->dev.id.version = 0x0100;
-	spaceball->dev.dev = &serio->dev;
-
 	serio_set_drvdata(serio, spaceball);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(spaceball);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&spaceball->dev);
-
-	printk(KERN_INFO "input: %s on serio%s\n",
-		spaceball_names[id], serio->phys);
-
+	input_register_device(spaceball->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(spaceball);
+	return err;
 }
 
 /*
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 01fd2e4..7c123a0 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -52,15 +52,13 @@
 
 static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
 static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
-static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
 
 /*
  * Per-Orb data.
  */
 
 struct spaceorb {
-	struct input_dev dev;
-	struct serio *serio;
+	struct input_dev *dev;
 	int idx;
 	unsigned char data[SPACEORB_MAX_LENGTH];
 	char phys[32];
@@ -78,7 +76,7 @@
 
 static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
 {
-	struct input_dev *dev = &spaceorb->dev;
+	struct input_dev *dev = spaceorb->dev;
 	unsigned char *data = spaceorb->data;
 	unsigned char c = 0;
 	int axes[6];
@@ -95,8 +93,8 @@
 		case 'R':				/* Reset packet */
 			spaceorb->data[spaceorb->idx - 1] = 0;
 			for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
-			printk(KERN_INFO "input: %s [%s] on %s\n",
-				 spaceorb_name, spaceorb->data + i, spaceorb->serio->phys);
+			printk(KERN_INFO "input: %s [%s] is %s\n",
+				 dev->name, spaceorb->data + i, spaceorb->phys);
 			break;
 
 		case 'D':				/* Ball + button data */
@@ -123,7 +121,7 @@
 
 		case 'E':				/* Error packet */
 			if (spaceorb->idx != 4) return;
-			printk(KERN_ERR "joy-spaceorb: Device error. [ ");
+			printk(KERN_ERR "spaceorb: Device error. [ ");
 			for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
 			printk("]\n");
 			break;
@@ -154,9 +152,9 @@
 {
 	struct spaceorb* spaceorb = serio_get_drvdata(serio);
 
-	input_unregister_device(&spaceorb->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(spaceorb->dev);
 	kfree(spaceorb);
 }
 
@@ -169,52 +167,48 @@
 static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceorb *spaceorb;
-	int i, t;
-	int err;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
+	int i;
 
-	if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
-		return -ENOMEM;
+	spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!spaceorb || !input_dev)
+		goto fail;
 
-	memset(spaceorb, 0, sizeof(struct spaceorb));
-
-	spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	for (i = 0; i < 6; i++)
-		set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
-
-	for (i = 0; i < 6; i++) {
-		t = spaceorb_axes[i];
-		set_bit(t, spaceorb->dev.absbit);
-		spaceorb->dev.absmin[t] = -508;
-		spaceorb->dev.absmax[t] =  508;
-	}
-
-	spaceorb->serio = serio;
-	spaceorb->dev.private = spaceorb;
-
+	spaceorb->dev = input_dev;
 	sprintf(spaceorb->phys, "%s/input0", serio->phys);
 
-	init_input_dev(&spaceorb->dev);
-	spaceorb->dev.name = spaceorb_name;
-	spaceorb->dev.phys = spaceorb->phys;
-	spaceorb->dev.id.bustype = BUS_RS232;
-	spaceorb->dev.id.vendor = SERIO_SPACEORB;
-	spaceorb->dev.id.product = 0x0001;
-	spaceorb->dev.id.version = 0x0100;
-	spaceorb->dev.dev = &serio->dev;
+	input_dev->name = "SpaceTec SpaceOrb 360 / Avenger";
+	input_dev->phys = spaceorb->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_SPACEORB;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = spaceorb;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; i < 6; i++)
+		set_bit(spaceorb_buttons[i], input_dev->keybit);
+
+	for (i = 0; i < 6; i++)
+		input_set_abs_params(input_dev, spaceorb_axes[i], -508, 508, 0, 0);
 
 	serio_set_drvdata(serio, spaceorb);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(spaceorb);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&spaceorb->dev);
-
+	input_register_device(spaceorb->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(spaceorb);
+	return err;
 }
 
 /*
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 6f6e675..0a9ed1d 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -48,14 +48,12 @@
 
 #define STINGER_MAX_LENGTH 8
 
-static char *stinger_name = "Gravis Stinger";
-
 /*
  * Per-Stinger data.
  */
 
 struct stinger {
-	struct input_dev dev;
+	struct input_dev *dev;
 	int idx;
 	unsigned char data[STINGER_MAX_LENGTH];
 	char phys[32];
@@ -68,7 +66,7 @@
 
 static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
 {
-	struct input_dev *dev = &stinger->dev;
+	struct input_dev *dev = stinger->dev;
 	unsigned char *data = stinger->data;
 
 	if (!stinger->idx) return;
@@ -126,9 +124,9 @@
 {
 	struct stinger *stinger = serio_get_drvdata(serio);
 
-	input_unregister_device(&stinger->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(stinger->dev);
 	kfree(stinger);
 }
 
@@ -141,53 +139,46 @@
 static int stinger_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct stinger *stinger;
-	int i;
-	int err;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 
-	if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
-		return -ENOMEM;
+	stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!stinger || !input_dev)
+		goto fail;
 
-	memset(stinger, 0, sizeof(struct stinger));
-
-	stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
-					   BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
-					   BIT(BTN_START) | BIT(BTN_SELECT);
-	stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
+	stinger->dev = input_dev;
 	sprintf(stinger->phys, "%s/serio0", serio->phys);
 
-	init_input_dev(&stinger->dev);
-	stinger->dev.name = stinger_name;
-	stinger->dev.phys = stinger->phys;
-	stinger->dev.id.bustype = BUS_RS232;
-	stinger->dev.id.vendor = SERIO_STINGER;
-	stinger->dev.id.product = 0x0001;
-	stinger->dev.id.version = 0x0100;
-	stinger->dev.dev = &serio->dev;
+	input_dev->name = "Gravis Stinger";
+	input_dev->phys = stinger->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_STINGER;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = stinger;
 
-	for (i = 0; i < 2; i++) {
-		stinger->dev.absmax[ABS_X+i] =  64;
-		stinger->dev.absmin[ABS_X+i] = -64;
-		stinger->dev.absflat[ABS_X+i] = 4;
-	}
-
-	stinger->dev.private = stinger;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
+					 BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) |
+					 BIT(BTN_START) | BIT(BTN_SELECT);
+	input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 4);
+	input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 4);
 
 	serio_set_drvdata(serio, stinger);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(stinger);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&stinger->dev);
-
-	printk(KERN_INFO "input: %s on %s\n",  stinger_name, serio->phys);
-
+	input_register_device(stinger->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(stinger);
+	return err;
 }
 
 /*
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 7431efc..60e2aac 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
+#include <linux/jiffies.h>
 
 #define DRIVER_DESC	"ThrustMaster DirectConnect joystick driver"
 
@@ -63,37 +64,70 @@
 #define TMDC_ABS_HAT		4
 #define TMDC_BTN		16
 
-static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
-static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
+static const unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
+static const unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
 
-static signed char tmdc_abs[TMDC_ABS] =
+static const signed char tmdc_abs[TMDC_ABS] =
 	{ ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
-static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
+static const signed char tmdc_abs_hat[TMDC_ABS_HAT] =
 	{ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
-static signed char tmdc_abs_at[TMDC_ABS] =
+static const signed char tmdc_abs_at[TMDC_ABS] =
 	{ ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
-static signed char tmdc_abs_fm[TMDC_ABS] =
+static const signed char tmdc_abs_fm[TMDC_ABS] =
 	{ ABS_RX, ABS_RY, ABS_X, ABS_Y };
 
-static short tmdc_btn_pad[TMDC_BTN] =
+static const short tmdc_btn_pad[TMDC_BTN] =
 	{ BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
-static short tmdc_btn_joy[TMDC_BTN] =
+static const short tmdc_btn_joy[TMDC_BTN] =
 	{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
 	  BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
-static short tmdc_btn_fm[TMDC_BTN] =
+static const short tmdc_btn_fm[TMDC_BTN] =
         { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
-static short tmdc_btn_at[TMDC_BTN] =
+static const short tmdc_btn_at[TMDC_BTN] =
         { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
           BTN_BASE3, BTN_BASE2, BTN_BASE };
 
-static struct {
+static const struct {
         int x;
         int y;
 } tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
 
+static const struct tmdc_model {
+	unsigned char id;
+	const char *name;
+	char abs;
+	char hats;
+	char btnc[4];
+	char btno[4];
+	const signed char *axes;
+	const short *buttons;
+} tmdc_models[] = {
+	{   1, "ThrustMaster Millenium 3D Inceptor",	  6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
+	{   3, "ThrustMaster Rage 3D Gamepad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+	{   4, "ThrustMaster Attack Throttle",		  5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
+	{   8, "ThrustMaster FragMaster",		  4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
+	{ 163, "Thrustmaster Fusion GamePad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
+	{   0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }
+};
+
+
+struct tmdc_port {
+	struct input_dev *dev;
+	char name[64];
+	char phys[32];
+	int mode;
+	const signed char *abs;
+	const short *btn;
+	unsigned char absc;
+	unsigned char btnc[4];
+	unsigned char btno[4];
+};
+
 struct tmdc {
 	struct gameport *gameport;
-	struct input_dev dev[2];
+	struct tmdc_port *port[2];
+#if 0
+	struct input_dev *dev[2];
 	char name[2][64];
 	char phys[2][32];
 	int mode[2];
@@ -102,6 +136,7 @@
 	unsigned char absc[2];
 	unsigned char btnc[2][4];
 	unsigned char btno[2][4];
+#endif
 	int reads;
 	int bads;
 	unsigned char exists;
@@ -156,6 +191,50 @@
 	return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
 }
 
+static int tmdc_parse_packet(struct tmdc_port *port, unsigned char *data)
+{
+	int i, k, l;
+
+	if (data[TMDC_BYTE_ID] != port->mode)
+		return -1;
+
+	for (i = 0; i < port->absc; i++) {
+		if (port->abs[i] < 0)
+			return 0;
+
+		input_report_abs(port->dev, port->abs[i], data[tmdc_byte_a[i]]);
+	}
+
+	switch (port->mode) {
+
+		case TMDC_MODE_M3DI:
+
+			i = tmdc_byte_d[0];
+			input_report_abs(port->dev, ABS_HAT0X, ((data[i] >> 3) & 1) - ((data[i] >> 1) & 1));
+			input_report_abs(port->dev, ABS_HAT0Y, ((data[i] >> 2) & 1) - ( data[i]       & 1));
+			break;
+
+		case TMDC_MODE_AT:
+
+			i = tmdc_byte_a[3];
+			input_report_abs(port->dev, ABS_HAT0X, tmdc_hat_to_axis[(data[i] - 141) / 25].x);
+			input_report_abs(port->dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[i] - 141) / 25].y);
+			break;
+
+	}
+
+	for (k = l = 0; k < 4; k++) {
+		for (i = 0; i < port->btnc[k]; i++)
+			input_report_key(port->dev, port->btn[i + l],
+				((data[tmdc_byte_d[k]] >> (i + port->btno[k])) & 1));
+		l += port->btnc[k];
+	}
+
+	input_sync(port->dev);
+
+	return 0;
+}
+
 /*
  * tmdc_poll() reads and analyzes ThrustMaster joystick data.
  */
@@ -164,57 +243,21 @@
 {
 	unsigned char data[2][TMDC_MAX_LENGTH];
 	struct tmdc *tmdc = gameport_get_drvdata(gameport);
-	struct input_dev *dev;
 	unsigned char r, bad = 0;
-	int i, j, k, l;
+	int i;
 
 	tmdc->reads++;
 
 	if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
 		bad = 1;
-	else
+	else {
+		for (i = 0; i < 2; i++) {
+			if (r & (1 << i) & tmdc->exists) {
 
-	for (j = 0; j < 2; j++)
-		if (r & (1 << j) & tmdc->exists) {
-
-			if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
-				bad = 1;
-				continue;
+				if (tmdc_parse_packet(tmdc->port[i], data[i]))
+					bad = 1;
 			}
-
-			dev = tmdc->dev + j;
-
-			for (i = 0; i < tmdc->absc[j]; i++) {
-				if (tmdc->abs[j][i] < 0) continue;
-				input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
-			}
-
-			switch (tmdc->mode[j]) {
-
-				case TMDC_MODE_M3DI:
-
-					i = tmdc_byte_d[0];
-					input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
-					input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i]       & 1));
-					break;
-
-				case TMDC_MODE_AT:
-
-					i = tmdc_byte_a[3];
-					input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
-					input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
-					break;
-
-			}
-
-			for (k = l = 0; k < 4; k++) {
-				for (i = 0; i < tmdc->btnc[j][k]; i++)
-					input_report_key(dev, tmdc->btn[j][i + l],
-						((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
-				l += tmdc->btnc[j][k];
-			}
-
-			input_sync(dev);
+		}
 	}
 
 	tmdc->bads += bad;
@@ -235,31 +278,89 @@
 	gameport_stop_polling(tmdc->gameport);
 }
 
+static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
+{
+	const struct tmdc_model *model;
+	struct tmdc_port *port;
+	struct input_dev *input_dev;
+	int i, j, b = 0;
+
+	tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!port || !input_dev) {
+		kfree(port);
+		input_free_device(input_dev);
+		return -ENOMEM;
+	}
+
+	port->mode = data[TMDC_BYTE_ID];
+
+	for (model = tmdc_models; model->id && model->id != port->mode; model++)
+		/* empty */;
+
+	port->abs = model->axes;
+	port->btn = model->buttons;
+
+	if (!model->id) {
+		port->absc = data[TMDC_BYTE_DEF] >> 4;
+		for (i = 0; i < 4; i++)
+			port->btnc[i] = i < (data[TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
+	} else {
+		port->absc = model->abs;
+		for (i = 0; i < 4; i++)
+			port->btnc[i] = model->btnc[i];
+	}
+
+	for (i = 0; i < 4; i++)
+		port->btno[i] = model->btno[i];
+
+	snprintf(port->name, sizeof(port->name), model->name,
+		 port->absc, (data[TMDC_BYTE_DEF] & 0xf) << 3, port->mode);
+	snprintf(port->phys, sizeof(port->phys), "%s/input%d", tmdc->gameport->phys, i);
+
+	port->dev = input_dev;
+
+	input_dev->name = port->name;
+	input_dev->phys = port->phys;
+	input_dev->id.bustype = BUS_GAMEPORT;
+	input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
+	input_dev->id.product = model->id;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &tmdc->gameport->dev;
+	input_dev->private = tmdc;
+
+	input_dev->open = tmdc_open;
+	input_dev->close = tmdc_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; i < port->absc && i < TMDC_ABS; i++)
+		if (port->abs[i] >= 0)
+			input_set_abs_params(input_dev, port->abs[i], 8, 248, 2, 4);
+
+	for (i = 0; i < model->hats && i < TMDC_ABS_HAT; i++)
+		input_set_abs_params(input_dev, tmdc_abs_hat[i], -1, 1, 0, 0);
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < port->btnc[i] && j < TMDC_BTN; j++)
+			set_bit(port->btn[j + b], input_dev->keybit);
+		b += port->btnc[i];
+	}
+
+	input_register_device(port->dev);
+
+	return 0;
+}
+
 /*
  * tmdc_probe() probes for ThrustMaster type joysticks.
  */
 
 static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
-	static struct models {
-		unsigned char id;
-		char *name;
-		char abs;
-		char hats;
-		char btnc[4];
-		char btno[4];
-		signed char *axes;
-		short *buttons;
-	} models[] = {	{   1, "ThrustMaster Millenium 3D Inceptor",	  6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
-			{   3, "ThrustMaster Rage 3D Gamepad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
-			{   4, "ThrustMaster Attack Throttle",		  5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
-			{   8, "ThrustMaster FragMaster",		  4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
-			{ 163, "Thrustmaster Fusion GamePad",		  2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
-			{   0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
-
 	unsigned char data[2][TMDC_MAX_LENGTH];
 	struct tmdc *tmdc;
-	int i, j, k, l, m;
+	int i;
 	int err;
 
 	if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
@@ -281,68 +382,25 @@
 	gameport_set_poll_handler(gameport, tmdc_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	for (j = 0; j < 2; j++)
-		if (tmdc->exists & (1 << j)) {
+	for (i = 0; i < 2; i++) {
+		if (tmdc->exists & (1 << i)) {
 
-			tmdc->mode[j] = data[j][TMDC_BYTE_ID];
-
-			for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
-
-			tmdc->abs[j] = models[m].axes;
-			tmdc->btn[j] = models[m].buttons;
-
-			if (!models[m].id) {
-				models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
-				for (k = 0; k < 4; k++)
-					models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
-			}
-
-			tmdc->absc[j] = models[m].abs;
-			for (k = 0; k < 4; k++) {
-				tmdc->btnc[j][k] = models[m].btnc[k];
-				tmdc->btno[j][k] = models[m].btno[k];
-			}
-
-			sprintf(tmdc->name[j], models[m].name, models[m].abs,
-				(data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
-
-			sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
-
-			tmdc->dev[j].private = tmdc;
-			tmdc->dev[j].open = tmdc_open;
-			tmdc->dev[j].close = tmdc_close;
-
-			tmdc->dev[j].name = tmdc->name[j];
-			tmdc->dev[j].phys = tmdc->phys[j];
-			tmdc->dev[j].id.bustype = BUS_GAMEPORT;
-			tmdc->dev[j].id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
-			tmdc->dev[j].id.product = models[m].id;
-			tmdc->dev[j].id.version = 0x0100;
-
-			tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
-				if (tmdc->abs[j][i] >= 0)
-					input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
-
-			for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
-				input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
-
-
-			for (k = l = 0; k < 4; k++) {
-				for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
-					set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
-				l += models[m].btnc[k];
-			}
-
-			input_register_device(tmdc->dev + j);
-			printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
+			err = tmdc_setup_port(tmdc, i, data[i]);
+			if (err)
+				goto fail3;
 		}
+	}
 
 	return 0;
 
-fail2:	gameport_close(gameport);
-fail1:	gameport_set_drvdata(gameport, NULL);
+ fail3: while (--i >= 0) {
+		if (tmdc->port[i]) {
+			input_unregister_device(tmdc->port[i]->dev);
+			kfree(tmdc->port[i]);
+		}
+	}
+ fail2:	gameport_close(gameport);
+ fail1:	gameport_set_drvdata(gameport, NULL);
 	kfree(tmdc);
 	return err;
 }
@@ -352,9 +410,12 @@
 	struct tmdc *tmdc = gameport_get_drvdata(gameport);
 	int i;
 
-	for (i = 0; i < 2; i++)
-		if (tmdc->exists & (1 << i))
-			input_unregister_device(tmdc->dev + i);
+	for (i = 0; i < 2; i++) {
+		if (tmdc->port[i]) {
+			input_unregister_device(tmdc->port[i]->dev);
+			kfree(tmdc->port[i]);
+		}
+	}
 	gameport_close(gameport);
 	gameport_set_drvdata(gameport, NULL);
 	kfree(tmdc);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 0c5b9c8..7e97649 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -42,19 +42,21 @@
 MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
 MODULE_LICENSE("GPL");
 
-static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs __initdata = 0;
-module_param_array_named(map, tgfx, int, &tgfx_nargs, 0);
+#define TGFX_MAX_PORTS		3
+#define TGFX_MAX_DEVICES	7
+
+struct tgfx_config {
+	int args[TGFX_MAX_DEVICES + 1];
+	int nargs;
+};
+
+static struct tgfx_config tgfx[TGFX_MAX_PORTS] __initdata;
+
+module_param_array_named(map, tgfx[0].args, int, &tgfx[0].nargs, 0);
 MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
-
-static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs_2 __initdata = 0;
-module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0);
+module_param_array_named(map2, tgfx[1].args, int, &tgfx[1].nargs, 0);
 MODULE_PARM_DESC(map2, "Describes second set of devices");
-
-static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_nargs_3 __initdata = 0;
-module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0);
+module_param_array_named(map3, tgfx[2].args, int, &tgfx[2].nargs, 0);
 MODULE_PARM_DESC(map3, "Describes third set of devices");
 
 __obsolete_setup("tgfx=");
@@ -75,17 +77,17 @@
 #define TGFX_TOP2		0x08
 
 static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
-static char *tgfx_name = "TurboGraFX Multisystem joystick";
 
 static struct tgfx {
 	struct pardevice *pd;
 	struct timer_list timer;
-	struct input_dev dev[7];
-	char phys[7][32];
+	struct input_dev *dev[TGFX_MAX_DEVICES];
+	char name[TGFX_MAX_DEVICES][64];
+	char phys[TGFX_MAX_DEVICES][32];
 	int sticks;
 	int used;
 	struct semaphore sem;
-} *tgfx_base[3];
+} *tgfx_base[TGFX_MAX_PORTS];
 
 /*
  * tgfx_timer() reads and analyzes TurboGraFX joystick data.
@@ -100,7 +102,7 @@
 	for (i = 0; i < 7; i++)
 		if (tgfx->sticks & (1 << i)) {
 
-			dev = tgfx->dev + i;
+			dev = tgfx->dev[i];
 
 			parport_write_data(tgfx->pd->port, ~(1 << i));
 			data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
@@ -153,118 +155,165 @@
 	up(&tgfx->sem);
 }
 
+
+
 /*
  * tgfx_probe() probes for tg gamepads.
  */
 
-static struct tgfx __init *tgfx_probe(int *config, int nargs)
+static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
 {
 	struct tgfx *tgfx;
+	struct input_dev *input_dev;
 	struct parport *pp;
+	struct pardevice *pd;
 	int i, j;
+	int err;
 
-	if (config[0] < 0)
-		return NULL;
-
-	if (nargs < 2) {
-		printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
-		return NULL;
-	}
-
-	pp = parport_find_number(config[0]);
-
+	pp = parport_find_number(parport);
 	if (!pp) {
 		printk(KERN_ERR "turbografx.c: no such parport\n");
-		return NULL;
+		err = -EINVAL;
+		goto err_out;
 	}
 
-	if (!(tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL))) {
-		parport_put_port(pp);
-		return NULL;
+	pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+	if (!pd) {
+		printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
+		err = -EBUSY;
+		goto err_put_pp;
+	}
+
+	tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
+	if (!tgfx) {
+		printk(KERN_ERR "turbografx.c: Not enough memory\n");
+		err = -ENOMEM;
+		goto err_unreg_pardev;
 	}
 
 	init_MUTEX(&tgfx->sem);
-
-	tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-
-	parport_put_port(pp);
-
-	if (!tgfx->pd) {
-		printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
-		kfree(tgfx);
-		return NULL;
-	}
-
+	tgfx->pd = pd;
 	init_timer(&tgfx->timer);
 	tgfx->timer.data = (long) tgfx;
 	tgfx->timer.function = tgfx_timer;
 
-	tgfx->sticks = 0;
+	for (i = 0; i < n_devs; i++) {
+		if (n_buttons[i] < 1)
+			continue;
 
-	for (i = 0; i < nargs - 1; i++)
-		if (config[i+1] > 0 && config[i+1] < 6) {
-
-			tgfx->sticks |= (1 << i);
-
-			tgfx->dev[i].private = tgfx;
-			tgfx->dev[i].open = tgfx_open;
-			tgfx->dev[i].close = tgfx_close;
-
-			sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name);
-
-			tgfx->dev[i].name = tgfx_name;
-			tgfx->dev[i].phys = tgfx->phys[i];
-			tgfx->dev[i].id.bustype = BUS_PARPORT;
-			tgfx->dev[i].id.vendor = 0x0003;
-			tgfx->dev[i].id.product = config[i+1];
-			tgfx->dev[i].id.version = 0x0100;
-
-			tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-			tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
-			for (j = 0; j < config[i+1]; j++)
-				set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
-
-			tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
-			tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
-
-			input_register_device(tgfx->dev + i);
-			printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
-				config[i+1], tgfx->pd->port->name);
+		if (n_buttons[i] > 6) {
+			printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
+			err = -EINVAL;
+			goto err_free_devs;
 		}
 
+		tgfx->dev[i] = input_dev = input_allocate_device();
+		if (!input_dev) {
+			printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
+			err = -ENOMEM;
+			goto err_free_devs;
+		}
+
+		tgfx->sticks |= (1 << i);
+		snprintf(tgfx->name[i], sizeof(tgfx->name[i]),
+			 "TurboGraFX %d-button Multisystem joystick", n_buttons[i]);
+		snprintf(tgfx->phys[i], sizeof(tgfx->phys[i]),
+			 "%s/input%d", tgfx->pd->port->name, i);
+
+		input_dev->name = tgfx->name[i];
+		input_dev->phys = tgfx->phys[i];
+		input_dev->id.bustype = BUS_PARPORT;
+		input_dev->id.vendor = 0x0003;
+		input_dev->id.product = n_buttons[i];
+		input_dev->id.version = 0x0100;
+
+		input_dev->private = tgfx;
+		input_dev->open = tgfx_open;
+		input_dev->close = tgfx_close;
+
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
+		input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
+
+		for (j = 0; j < n_buttons[i]; j++)
+			set_bit(tgfx_buttons[j], input_dev->keybit);
+
+		input_register_device(tgfx->dev[i]);
+	}
+
         if (!tgfx->sticks) {
-		parport_unregister_device(tgfx->pd);
-		kfree(tgfx);
-		return NULL;
+		printk(KERN_ERR "turbografx.c: No valid devices specified\n");
+		err = -EINVAL;
+		goto err_free_tgfx;
         }
 
 	return tgfx;
+
+ err_free_devs:
+	while (--i >= 0)
+		input_unregister_device(tgfx->dev[i]);
+ err_free_tgfx:
+	kfree(tgfx);
+ err_unreg_pardev:
+	parport_unregister_device(pd);
+ err_put_pp:
+	parport_put_port(pp);
+ err_out:
+	return ERR_PTR(err);
+}
+
+static void __exit tgfx_remove(struct tgfx *tgfx)
+{
+	int i;
+
+	for (i = 0; i < TGFX_MAX_DEVICES; i++)
+		if (tgfx->dev[i])
+			input_unregister_device(tgfx->dev[i]);
+	parport_unregister_device(tgfx->pd);
+	kfree(tgfx);
 }
 
 static int __init tgfx_init(void)
 {
-	tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
-	tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
-	tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3);
+	int i;
+	int have_dev = 0;
+	int err = 0;
 
-	if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
-		return 0;
+	for (i = 0; i < TGFX_MAX_PORTS; i++) {
+		if (tgfx[i].nargs == 0 || tgfx[i].args[0] < 0)
+			continue;
 
-	return -ENODEV;
+		if (tgfx[i].nargs < 2) {
+			printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
+			err = -EINVAL;
+			break;
+		}
+
+		tgfx_base[i] = tgfx_probe(tgfx[i].args[0], tgfx[i].args + 1, tgfx[i].nargs - 1);
+		if (IS_ERR(tgfx_base[i])) {
+			err = PTR_ERR(tgfx_base[i]);
+			break;
+		}
+
+		have_dev = 1;
+	}
+
+	if (err) {
+		while (--i >= 0)
+			tgfx_remove(tgfx_base[i]);
+		return err;
+	}
+
+	return have_dev ? 0 : -ENODEV;
 }
 
 static void __exit tgfx_exit(void)
 {
-	int i, j;
+	int i;
 
-	for (i = 0; i < 3; i++)
-		if (tgfx_base[i]) {
-			for (j = 0; j < 7; j++)
-				if (tgfx_base[i]->sticks & (1 << j))
-					input_unregister_device(tgfx_base[i]->dev + j);
-		parport_unregister_device(tgfx_base[i]->pd);
-	}
+	for (i = 0; i < TGFX_MAX_PORTS; i++)
+		if (tgfx_base[i])
+			tgfx_remove(tgfx_base[i]);
 }
 
 module_init(tgfx_init);
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 0379bc1..cd3a1e7 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -69,8 +69,6 @@
 
 #define TWIDJOY_MAX_LENGTH 5
 
-static char *twidjoy_name = "Handykey Twiddler";
-
 static struct twidjoy_button_spec {
 	int bitshift;
 	int bitmask;
@@ -95,7 +93,7 @@
  */
 
 struct twidjoy {
-	struct input_dev dev;
+	struct input_dev *dev;
 	int idx;
 	unsigned char data[TWIDJOY_MAX_LENGTH];
 	char phys[32];
@@ -108,37 +106,33 @@
 
 static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
 {
-	if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
-		struct input_dev *dev = &twidjoy->dev;
-		unsigned char *data = twidjoy->data;
-		struct twidjoy_button_spec *bp;
-		int button_bits, abs_x, abs_y;
+	struct input_dev *dev = twidjoy->dev;
+	unsigned char *data = twidjoy->data;
+	struct twidjoy_button_spec *bp;
+	int button_bits, abs_x, abs_y;
 
-		button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
+	button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
 
-		input_regs(dev, regs);
+	input_regs(dev, regs);
 
-		for (bp = twidjoy_buttons; bp->bitmask; bp++) {
-			int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
-			int i;
+	for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+		int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
+		int i;
 
-			for (i = 0; i < bp->bitmask; i++)
-				input_report_key(dev, bp->buttons[i], i+1 == value);
-		}
-
-		abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
-		if (data[4] & 0x08) abs_x -= 256;
-
-		abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
-		if (data[3] & 0x02) abs_y -= 256;
-
-		input_report_abs(dev, ABS_X, -abs_x);
-		input_report_abs(dev, ABS_Y, +abs_y);
-
-		input_sync(dev);
+		for (i = 0; i < bp->bitmask; i++)
+			input_report_key(dev, bp->buttons[i], i+1 == value);
 	}
 
-	return;
+	abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
+	if (data[4] & 0x08) abs_x -= 256;
+
+	abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
+	if (data[3] & 0x02) abs_y -= 256;
+
+	input_report_abs(dev, ABS_X, -abs_x);
+	input_report_abs(dev, ABS_Y, +abs_y);
+
+	input_sync(dev);
 }
 
 /*
@@ -179,9 +173,9 @@
 {
 	struct twidjoy *twidjoy = serio_get_drvdata(serio);
 
-	input_unregister_device(&twidjoy->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(twidjoy->dev);
 	kfree(twidjoy);
 }
 
@@ -195,59 +189,49 @@
 {
 	struct twidjoy_button_spec *bp;
 	struct twidjoy *twidjoy;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 	int i;
-	int err;
 
-	if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
-		return -ENOMEM;
+	twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!twidjoy || !input_dev)
+		goto fail;
 
-	memset(twidjoy, 0, sizeof(struct twidjoy));
-
+	twidjoy->dev = input_dev;
 	sprintf(twidjoy->phys, "%s/input0", serio->phys);
 
-	init_input_dev(&twidjoy->dev);
-	twidjoy->dev.name = twidjoy_name;
-	twidjoy->dev.phys = twidjoy->phys;
-	twidjoy->dev.id.bustype = BUS_RS232;
-	twidjoy->dev.id.vendor = SERIO_TWIDJOY;
-	twidjoy->dev.id.product = 0x0001;
-	twidjoy->dev.id.version = 0x0100;
-	twidjoy->dev.dev = &serio->dev;
+	input_dev->name = "Handykey Twiddler";
+	input_dev->phys = twidjoy->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_TWIDJOY;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = twidjoy;
 
-	twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+	input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
+	input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
 
-	for (bp = twidjoy_buttons; bp->bitmask; bp++) {
+	for (bp = twidjoy_buttons; bp->bitmask; bp++)
 		for (i = 0; i < bp->bitmask; i++)
-			set_bit(bp->buttons[i], twidjoy->dev.keybit);
-	}
-
-	twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-
-	for (i = 0; i < 2; i++) {
-		twidjoy->dev.absmax[ABS_X+i] =  50;
-		twidjoy->dev.absmin[ABS_X+i] = -50;
-
-		/* TODO: arndt 20010708: Are these values appropriate? */
-		twidjoy->dev.absfuzz[ABS_X+i] = 4;
-		twidjoy->dev.absflat[ABS_X+i] = 4;
-	}
-
-	twidjoy->dev.private = twidjoy;
+			set_bit(bp->buttons[i], input_dev->keybit);
 
 	serio_set_drvdata(serio, twidjoy);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(twidjoy);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&twidjoy->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
-
+	input_register_device(twidjoy->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(twidjoy);
+	return err;
 }
 
 /*
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 6976a21..99a642d 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -47,14 +47,13 @@
 
 #define WARRIOR_MAX_LENGTH	16
 static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
-static char *warrior_name = "Logitech WingMan Warrior";
 
 /*
  * Per-Warrior data.
  */
 
 struct warrior {
-	struct input_dev dev;
+	struct input_dev *dev;
 	int idx, len;
 	unsigned char data[WARRIOR_MAX_LENGTH];
 	char phys[32];
@@ -67,7 +66,7 @@
 
 static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
 {
-	struct input_dev *dev = &warrior->dev;
+	struct input_dev *dev = warrior->dev;
 	unsigned char *data = warrior->data;
 
 	if (!warrior->idx) return;
@@ -131,9 +130,9 @@
 {
 	struct warrior *warrior = serio_get_drvdata(serio);
 
-	input_unregister_device(&warrior->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(warrior->dev);
 	kfree(warrior);
 }
 
@@ -146,60 +145,48 @@
 static int warrior_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct warrior *warrior;
-	int i;
-	int err;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 
-	if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
-		return -ENOMEM;
+	warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!warrior || !input_dev)
+		goto fail;
 
-	memset(warrior, 0, sizeof(struct warrior));
-
-	warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
-	warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
-	warrior->dev.relbit[0] = BIT(REL_DIAL);
-	warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
-
+	warrior->dev = input_dev;
 	sprintf(warrior->phys, "%s/input0", serio->phys);
 
-	init_input_dev(&warrior->dev);
-	warrior->dev.name = warrior_name;
-	warrior->dev.phys = warrior->phys;
-	warrior->dev.id.bustype = BUS_RS232;
-	warrior->dev.id.vendor = SERIO_WARRIOR;
-	warrior->dev.id.product = 0x0001;
-	warrior->dev.id.version = 0x0100;
-	warrior->dev.dev = &serio->dev;
+	input_dev->name = "Logitech WingMan Warrior";
+	input_dev->phys = warrior->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_WARRIOR;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = warrior;
 
-	for (i = 0; i < 2; i++) {
-		warrior->dev.absmax[ABS_X+i] = -64;
-		warrior->dev.absmin[ABS_X+i] =  64;
-		warrior->dev.absflat[ABS_X+i] = 8;
-	}
-
-	warrior->dev.absmax[ABS_THROTTLE] = -112;
-	warrior->dev.absmin[ABS_THROTTLE] =  112;
-
-	for (i = 0; i < 2; i++) {
-		warrior->dev.absmax[ABS_HAT0X+i] = -1;
-		warrior->dev.absmin[ABS_HAT0X+i] =  1;
-	}
-
-	warrior->dev.private = warrior;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
+	input_dev->relbit[0] = BIT(REL_DIAL);
+	input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8);
+	input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8);
+	input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0);
+	input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
+	input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
 
 	serio_set_drvdata(serio, warrior);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(warrior);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&warrior->dev);
-
-	printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
-
+	input_register_device(warrior->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(warrior);
+	return err;
 }
 
 /*
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 4e8e8ea..4c8fb1f 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -155,10 +155,7 @@
 	[7] = KERN_WARNING "amikbd: keyboard interrupt\n"
 };
 
-static struct input_dev amikbd_dev;
-
-static char *amikbd_name = "Amiga keyboard";
-static char *amikbd_phys = "amikbd/input0";
+static struct input_dev *amikbd_dev;
 
 static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
@@ -176,16 +173,16 @@
 
 		scancode = amikbd_keycode[scancode];
 
-		input_regs(&amikbd_dev, fp);
+		input_regs(amikbd_dev, fp);
 
 		if (scancode == KEY_CAPSLOCK) {	/* CapsLock is a toggle switch key on Amiga */
-			input_report_key(&amikbd_dev, scancode, 1);
-			input_report_key(&amikbd_dev, scancode, 0);
-			input_sync(&amikbd_dev);
+			input_report_key(amikbd_dev, scancode, 1);
+			input_report_key(amikbd_dev, scancode, 0);
 		} else {
-			input_report_key(&amikbd_dev, scancode, down);
-			input_sync(&amikbd_dev);
+			input_report_key(amikbd_dev, scancode, down);
 		}
+
+		input_sync(amikbd_dev);
 	} else				/* scancodes >= 0x78 are error codes */
 		printk(amikbd_messages[scancode - 0x78]);
 
@@ -202,39 +199,41 @@
 	if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
 		return -EBUSY;
 
-	init_input_dev(&amikbd_dev);
+	amikbd_dev = input_allocate_device();
+	if (!amikbd_dev) {
+		printk(KERN_ERR "amikbd: not enough memory for input device\n");
+		release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
+		return -ENOMEM;
+	}
 
-	amikbd_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-	amikbd_dev.keycode = amikbd_keycode;
-	amikbd_dev.keycodesize = sizeof(unsigned char);
-	amikbd_dev.keycodemax = ARRAY_SIZE(amikbd_keycode);
+	amikbd_dev->name = "Amiga Keyboard";
+	amikbd_dev->phys = "amikbd/input0";
+	amikbd_dev->id.bustype = BUS_AMIGA;
+	amikbd_dev->id.vendor = 0x0001;
+	amikbd_dev->id.product = 0x0001;
+	amikbd_dev->id.version = 0x0100;
+
+	amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	amikbd_dev->keycode = amikbd_keycode;
+	amikbd_dev->keycodesize = sizeof(unsigned char);
+	amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
 
 	for (i = 0; i < 0x78; i++)
 		if (amikbd_keycode[i])
-			set_bit(amikbd_keycode[i], amikbd_dev.keybit);
+			set_bit(amikbd_keycode[i], amikbd_dev->keybit);
 
 	ciaa.cra &= ~0x41;	 /* serial data in, turn off TA */
 	request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
 
-	amikbd_dev.name = amikbd_name;
-	amikbd_dev.phys = amikbd_phys;
-	amikbd_dev.id.bustype = BUS_AMIGA;
-	amikbd_dev.id.vendor = 0x0001;
-	amikbd_dev.id.product = 0x0001;
-	amikbd_dev.id.version = 0x0100;
-
-	input_register_device(&amikbd_dev);
-
-	printk(KERN_INFO "input: %s\n", amikbd_name);
-
+	input_register_device(amikbd_dev);
 	return 0;
 }
 
 static void __exit amikbd_exit(void)
 {
-	input_unregister_device(&amikbd_dev);
 	free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
-	release_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100);
+	input_unregister_device(amikbd_dev);
+	release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
 }
 
 module_init(amikbd_init);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 1ad8c2e..820c7fd 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -185,12 +185,12 @@
 
 struct atkbd {
 
-	struct ps2dev	ps2dev;
+	struct ps2dev ps2dev;
+	struct input_dev *dev;
 
 	/* Written only during init */
 	char name[64];
 	char phys[32];
-	struct input_dev dev;
 
 	unsigned short id;
 	unsigned char keycode[512];
@@ -290,7 +290,7 @@
 	if (!atkbd->enabled)
 		goto out;
 
-	input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
+	input_event(atkbd->dev, EV_MSC, MSC_RAW, code);
 
 	if (atkbd->translated) {
 
@@ -326,10 +326,10 @@
 			atkbd->release = 1;
 			goto out;
 		case ATKBD_RET_HANGUEL:
-			atkbd_report_key(&atkbd->dev, regs, KEY_HANGUEL, 3);
+			atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3);
 			goto out;
 		case ATKBD_RET_HANJA:
-			atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
+			atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3);
 			goto out;
 		case ATKBD_RET_ERR:
 			printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
@@ -345,7 +345,7 @@
 	}
 
 	if (atkbd->keycode[code] != ATKBD_KEY_NULL)
-		input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
+		input_event(atkbd->dev, EV_MSC, MSC_SCAN, code);
 
 	switch (atkbd->keycode[code]) {
 		case ATKBD_KEY_NULL:
@@ -365,7 +365,7 @@
 				       "to make it known.\n",
 				       code & 0x80 ? "e0" : "", code & 0x7f);
 			}
-			input_sync(&atkbd->dev);
+			input_sync(atkbd->dev);
 			break;
 		case ATKBD_SCR_1:
 			scroll = 1 - atkbd->release * 2;
@@ -390,7 +390,7 @@
 			break;
 		default:
 			value = atkbd->release ? 0 :
-				(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
+				(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev->key)));
 
 			switch (value) {	/* Workaround Toshiba laptop multiple keypress */
 				case 0:
@@ -398,7 +398,7 @@
 					break;
 				case 1:
 					atkbd->last = code;
-					atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
+					atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2;
 					break;
 				case 2:
 					if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
@@ -406,16 +406,16 @@
 					break;
 			}
 
-			atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
+			atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value);
 	}
 
 	if (atkbd->scroll) {
-		input_regs(&atkbd->dev, regs);
+		input_regs(atkbd->dev, regs);
 		if (click != -1)
-			input_report_key(&atkbd->dev, BTN_MIDDLE, click);
-		input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
-		input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
-		input_sync(&atkbd->dev);
+			input_report_key(atkbd->dev, BTN_MIDDLE, click);
+		input_report_rel(atkbd->dev, REL_WHEEL, scroll);
+		input_report_rel(atkbd->dev, REL_HWHEEL, hscroll);
+		input_sync(atkbd->dev);
 	}
 
 	atkbd->release = 0;
@@ -463,7 +463,6 @@
 
 			return 0;
 
-
 		case EV_REP:
 
 			if (atkbd->softrepeat) return 0;
@@ -693,7 +692,7 @@
 	device_remove_file(&serio->dev, &atkbd_attr_softrepeat);
 	device_remove_file(&serio->dev, &atkbd_attr_softraw);
 
-	input_unregister_device(&atkbd->dev);
+	input_unregister_device(atkbd->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
 	kfree(atkbd);
@@ -701,7 +700,7 @@
 
 
 /*
- * atkbd_set_device_attrs() initializes keyboard's keycode table
+ * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
  */
 
@@ -737,53 +736,58 @@
 
 static void atkbd_set_device_attrs(struct atkbd *atkbd)
 {
+	struct input_dev *input_dev = atkbd->dev;
 	int i;
 
-	memset(&atkbd->dev, 0, sizeof(struct input_dev));
+	if (atkbd->extra)
+		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
+	else
+		sprintf(atkbd->name, "AT %s Set %d keyboard",
+			atkbd->translated ? "Translated" : "Raw", atkbd->set);
 
-	init_input_dev(&atkbd->dev);
+	sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys);
 
-	atkbd->dev.name = atkbd->name;
-	atkbd->dev.phys = atkbd->phys;
-	atkbd->dev.id.bustype = BUS_I8042;
-	atkbd->dev.id.vendor = 0x0001;
-	atkbd->dev.id.product = atkbd->translated ? 1 : atkbd->set;
-	atkbd->dev.id.version = atkbd->id;
-	atkbd->dev.event = atkbd_event;
-	atkbd->dev.private = atkbd;
-	atkbd->dev.dev = &atkbd->ps2dev.serio->dev;
+	input_dev->name = atkbd->name;
+	input_dev->phys = atkbd->phys;
+	input_dev->id.bustype = BUS_I8042;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
+	input_dev->id.version = atkbd->id;
+	input_dev->event = atkbd_event;
+	input_dev->private = atkbd;
+	input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
 
-	atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
 
 	if (atkbd->write) {
-		atkbd->dev.evbit[0] |= BIT(EV_LED);
-		atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+		input_dev->evbit[0] |= BIT(EV_LED);
+		input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
 	}
 
 	if (atkbd->extra)
-		atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
+		input_dev->ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) |
 					BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
 
 	if (!atkbd->softrepeat) {
-		atkbd->dev.rep[REP_DELAY] = 250;
-		atkbd->dev.rep[REP_PERIOD] = 33;
+		input_dev->rep[REP_DELAY] = 250;
+		input_dev->rep[REP_PERIOD] = 33;
 	}
 
-	atkbd->dev.mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
+	input_dev->mscbit[0] = atkbd->softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
 
 	if (atkbd->scroll) {
-		atkbd->dev.evbit[0] |= BIT(EV_REL);
-		atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
-		set_bit(BTN_MIDDLE, atkbd->dev.keybit);
+		input_dev->evbit[0] |= BIT(EV_REL);
+		input_dev->relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
+		set_bit(BTN_MIDDLE, input_dev->keybit);
 	}
 
-	atkbd->dev.keycode = atkbd->keycode;
-	atkbd->dev.keycodesize = sizeof(unsigned char);
-	atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
+	input_dev->keycode = atkbd->keycode;
+	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
 
 	for (i = 0; i < 512; i++)
 		if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
-			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
+			set_bit(atkbd->keycode[i], input_dev->keybit);
 }
 
 /*
@@ -796,13 +800,15 @@
 static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct atkbd *atkbd;
-	int err;
+	struct input_dev *dev;
+	int err = -ENOMEM;
 
-	if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
-		return - ENOMEM;
+	atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
+	dev = input_allocate_device();
+	if (!atkbd || !dev)
+		goto fail;
 
-	memset(atkbd, 0, sizeof(struct atkbd));
-
+	atkbd->dev = dev;
 	ps2_init(&atkbd->ps2dev, serio);
 
 	switch (serio->id.type) {
@@ -828,19 +834,15 @@
 	serio_set_drvdata(serio, atkbd);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(atkbd);
-		return err;
-	}
+	if (err)
+		goto fail;
 
 	if (atkbd->write) {
 
 		if (atkbd_probe(atkbd)) {
 			serio_close(serio);
-			serio_set_drvdata(serio, NULL);
-			kfree(atkbd);
-			return -ENODEV;
+			err = -ENODEV;
+			goto fail;
 		}
 
 		atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -851,19 +853,9 @@
 		atkbd->id = 0xab00;
 	}
 
-	if (atkbd->extra)
-		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
-	else
-		sprintf(atkbd->name, "AT %s Set %d keyboard",
-			atkbd->translated ? "Translated" : "Raw", atkbd->set);
-
-	sprintf(atkbd->phys, "%s/input0", serio->phys);
-
 	atkbd_set_keycode_table(atkbd);
 	atkbd_set_device_attrs(atkbd);
 
-	input_register_device(&atkbd->dev);
-
 	device_create_file(&serio->dev, &atkbd_attr_extra);
 	device_create_file(&serio->dev, &atkbd_attr_scroll);
 	device_create_file(&serio->dev, &atkbd_attr_set);
@@ -872,9 +864,14 @@
 
 	atkbd_enable(atkbd);
 
-	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
+	input_register_device(atkbd->dev);
 
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(dev);
+	kfree(atkbd);
+	return err;
 }
 
 /*
@@ -896,9 +893,9 @@
 	atkbd_disable(atkbd);
 
 	if (atkbd->write) {
-		param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
-		         | (test_bit(LED_NUML,    atkbd->dev.led) ? 2 : 0)
-		         | (test_bit(LED_CAPSL,   atkbd->dev.led) ? 4 : 0);
+		param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
+		         | (test_bit(LED_NUML,    atkbd->dev->led) ? 2 : 0)
+		         | (test_bit(LED_CAPSL,   atkbd->dev->led) ? 4 : 0);
 
 		if (atkbd_probe(atkbd))
 			return -1;
@@ -1008,6 +1005,7 @@
 
 static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
 {
+	struct input_dev *new_dev;
 	unsigned long value;
 	char *rest;
 
@@ -1019,12 +1017,19 @@
 		return -EINVAL;
 
 	if (atkbd->extra != value) {
-		/* unregister device as it's properties will change */
-		input_unregister_device(&atkbd->dev);
+		/*
+		 * Since device's properties will change we need to
+		 * unregister old device. But allocate new one first
+		 * to make sure we have it.
+		 */
+		if (!(new_dev = input_allocate_device()))
+			return -ENOMEM;
+		input_unregister_device(atkbd->dev);
+		atkbd->dev = new_dev;
 		atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
 		atkbd_activate(atkbd);
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(&atkbd->dev);
+		input_register_device(atkbd->dev);
 	}
 	return count;
 }
@@ -1036,6 +1041,7 @@
 
 static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
 {
+	struct input_dev *new_dev;
 	unsigned long value;
 	char *rest;
 
@@ -1044,12 +1050,14 @@
 		return -EINVAL;
 
 	if (atkbd->scroll != value) {
-		/* unregister device as it's properties will change */
-		input_unregister_device(&atkbd->dev);
+		if (!(new_dev = input_allocate_device()))
+			return -ENOMEM;
+		input_unregister_device(atkbd->dev);
+		atkbd->dev = new_dev;
 		atkbd->scroll = value;
 		atkbd_set_keycode_table(atkbd);
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(&atkbd->dev);
+		input_register_device(atkbd->dev);
 	}
 	return count;
 }
@@ -1061,6 +1069,7 @@
 
 static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 {
+	struct input_dev *new_dev;
 	unsigned long value;
 	char *rest;
 
@@ -1072,13 +1081,15 @@
 		return -EINVAL;
 
 	if (atkbd->set != value) {
-		/* unregister device as it's properties will change */
-		input_unregister_device(&atkbd->dev);
+		if (!(new_dev = input_allocate_device()))
+			return -ENOMEM;
+		input_unregister_device(atkbd->dev);
+		atkbd->dev = new_dev;
 		atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
 		atkbd_activate(atkbd);
 		atkbd_set_keycode_table(atkbd);
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(&atkbd->dev);
+		input_register_device(atkbd->dev);
 	}
 	return count;
 }
@@ -1090,6 +1101,7 @@
 
 static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
 {
+	struct input_dev *new_dev;
 	unsigned long value;
 	char *rest;
 
@@ -1101,15 +1113,16 @@
 		return -EINVAL;
 
 	if (atkbd->softrepeat != value) {
-		/* unregister device as it's properties will change */
-		input_unregister_device(&atkbd->dev);
+		if (!(new_dev = input_allocate_device()))
+			return -ENOMEM;
+		input_unregister_device(atkbd->dev);
+		atkbd->dev = new_dev;
 		atkbd->softrepeat = value;
 		if (atkbd->softrepeat)
 			atkbd->softraw = 1;
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(&atkbd->dev);
+		input_register_device(atkbd->dev);
 	}
-
 	return count;
 }
 
@@ -1121,6 +1134,7 @@
 
 static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
 {
+	struct input_dev *new_dev;
 	unsigned long value;
 	char *rest;
 
@@ -1129,11 +1143,13 @@
 		return -EINVAL;
 
 	if (atkbd->softraw != value) {
-		/* unregister device as it's properties will change */
-		input_unregister_device(&atkbd->dev);
+		if (!(new_dev = input_allocate_device()))
+			return -ENOMEM;
+		input_unregister_device(atkbd->dev);
+		atkbd->dev = new_dev;
 		atkbd->softraw = value;
 		atkbd_set_device_attrs(atkbd);
-		input_register_device(&atkbd->dev);
+		input_register_device(atkbd->dev);
 	}
 	return count;
 }
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index cd4b6e7..3210d29 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -70,8 +70,7 @@
 
 struct corgikbd {
 	unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
-	struct input_dev input;
-	char phys[32];
+	struct input_dev *input;
 
 	spinlock_t lock;
 	struct timer_list timer;
@@ -147,7 +146,7 @@
 	spin_lock_irqsave(&corgikbd_data->lock, flags);
 
 	if (regs)
-		input_regs(&corgikbd_data->input, regs);
+		input_regs(corgikbd_data->input, regs);
 
 	num_pressed = 0;
 	for (col = 0; col < KB_COLS; col++) {
@@ -169,14 +168,14 @@
 			scancode = SCANCODE(row, col);
 			pressed = rowd & KB_ROWMASK(row);
 
-			input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
+			input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);
 
 			if (pressed)
 				num_pressed++;
 
 			if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
 					&& time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
-				input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+				input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
 				corgikbd_data->suspend_jiffies=jiffies;
 			}
 		}
@@ -185,7 +184,7 @@
 
 	corgikbd_activate_all();
 
-	input_sync(&corgikbd_data->input);
+	input_sync(corgikbd_data->input);
 
 	/* if any keys are pressed, enable the timer */
 	if (num_pressed)
@@ -249,9 +248,9 @@
 		if (hinge_count >= HINGE_STABLE_COUNT) {
 			spin_lock_irqsave(&corgikbd_data->lock, flags);
 
-			input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
-			input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
-			input_sync(&corgikbd_data->input);
+			input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
+			input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+			input_sync(corgikbd_data->input);
 
 			spin_unlock_irqrestore(&corgikbd_data->lock, flags);
 		}
@@ -260,24 +259,22 @@
 }
 
 #ifdef CONFIG_PM
-static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int corgikbd_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		struct corgikbd *corgikbd = dev_get_drvdata(dev);
-		corgikbd->suspended = 1;
-	}
+	struct corgikbd *corgikbd = dev_get_drvdata(dev);
+	corgikbd->suspended = 1;
+
 	return 0;
 }
 
-static int corgikbd_resume(struct device *dev, uint32_t level)
+static int corgikbd_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		struct corgikbd *corgikbd = dev_get_drvdata(dev);
+	struct corgikbd *corgikbd = dev_get_drvdata(dev);
 
-		/* Upon resume, ignore the suspend key for a short while */
-		corgikbd->suspend_jiffies=jiffies;
-		corgikbd->suspended = 0;
-	}
+	/* Upon resume, ignore the suspend key for a short while */
+	corgikbd->suspend_jiffies=jiffies;
+	corgikbd->suspended = 0;
+
 	return 0;
 }
 #else
@@ -287,16 +284,21 @@
 
 static int __init corgikbd_probe(struct device *dev)
 {
-	int i;
 	struct corgikbd *corgikbd;
+	struct input_dev *input_dev;
+	int i;
 
 	corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
-	if (!corgikbd)
+	input_dev = input_allocate_device();
+	if (!corgikbd || !input_dev) {
+		kfree(corgikbd);
+		input_free_device(input_dev);
 		return -ENOMEM;
+	}
 
-	dev_set_drvdata(dev,corgikbd);
-	strcpy(corgikbd->phys, "corgikbd/input0");
+	dev_set_drvdata(dev, corgikbd);
 
+	corgikbd->input = input_dev;
 	spin_lock_init(&corgikbd->lock);
 
 	/* Init Keyboard rescan timer */
@@ -311,28 +313,30 @@
 
 	corgikbd->suspend_jiffies=jiffies;
 
-	init_input_dev(&corgikbd->input);
-	corgikbd->input.private = corgikbd;
-	corgikbd->input.name = "Corgi Keyboard";
-	corgikbd->input.dev = dev;
-	corgikbd->input.phys = corgikbd->phys;
-	corgikbd->input.id.bustype = BUS_HOST;
-	corgikbd->input.id.vendor = 0x0001;
-	corgikbd->input.id.product = 0x0001;
-	corgikbd->input.id.version = 0x0100;
-	corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
-	corgikbd->input.keycode = corgikbd->keycode;
-	corgikbd->input.keycodesize = sizeof(unsigned char);
-	corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
-
 	memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
-	for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
-		set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
-	clear_bit(0, corgikbd->input.keybit);
-	set_bit(SW_0, corgikbd->input.swbit);
-	set_bit(SW_1, corgikbd->input.swbit);
 
-	input_register_device(&corgikbd->input);
+	input_dev->name = "Corgi Keyboard";
+	input_dev->phys = "corgikbd/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = dev;
+	input_dev->private = corgikbd;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+	input_dev->keycode = corgikbd->keycode;
+	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
+
+	for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
+		set_bit(corgikbd->keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
+	set_bit(SW_0, input_dev->swbit);
+	set_bit(SW_1, input_dev->swbit);
+
+	input_register_device(corgikbd->input);
+
 	mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
 
 	/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@@ -349,8 +353,6 @@
 	for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
 		pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
 
-	printk(KERN_INFO "input: Corgi Keyboard Registered\n");
-
 	return 0;
 }
 
@@ -365,7 +367,7 @@
 	del_timer_sync(&corgikbd->htimer);
 	del_timer_sync(&corgikbd->timer);
 
-	input_unregister_device(&corgikbd->input);
+	input_unregister_device(corgikbd->input);
 
 	kfree(corgikbd);
 
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index ef78bff..0a90962 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -204,7 +204,7 @@
 	hil_packet packet;
 	int idx;
 
-	kbd = (struct hil_kbd *)serio->private;
+	kbd = serio_get_drvdata(serio);
 	if (kbd == NULL) {
 		BUG();
 		return IRQ_HANDLED;
@@ -234,7 +234,7 @@
 {
 	struct hil_kbd *kbd;
 
-	kbd = (struct hil_kbd *)serio->private;
+	kbd = serio_get_drvdata(serio);
 	if (kbd == NULL) {
 		BUG();
 		return;
@@ -245,20 +245,20 @@
 	kfree(kbd);
 }
 
-static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
+static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct hil_kbd	*kbd;
 	uint8_t		did, *idd;
 	int		i;
 	
-	if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
-
-	if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
+	kbd = kmalloc(sizeof(*kbd), GFP_KERNEL);
+	if (!kbd)
+		return -ENOMEM;
 	memset(kbd, 0, sizeof(struct hil_kbd));
 
 	if (serio_open(serio, drv)) goto bail0;
 
-	serio->private = kbd;
+	serio_set_drvdata(serio, kbd);
 	kbd->serio = serio;
 	kbd->dev.private = kbd;
 
@@ -342,19 +342,31 @@
 	down(&(kbd->sem));
 	up(&(kbd->sem));
 
-	return;
+	return 0;
  bail1:
 	serio_close(serio);
  bail0:
 	kfree(kbd);
+	serio_set_drvdata(serio, NULL);
+	return -EIO;
 }
 
+static struct serio_device_id hil_kbd_ids[] = {
+	{
+		.type = SERIO_HIL_MLC,
+		.proto = SERIO_HIL,
+		.id = SERIO_ANY,
+		.extra = SERIO_ANY,
+	},
+	{ 0 }
+};
 
 struct serio_driver hil_kbd_serio_drv = {
 	.driver		= {
 		.name	= "hil_kbd",
 	},
 	.description	= "HP HIL keyboard driver",
+	.id_table	= hil_kbd_ids,
 	.connect 	= hil_kbd_connect,
 	.disconnect 	= hil_kbd_disconnect,
 	.interrupt 	= hil_kbd_interrupt
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
index eecb77d..e95bc05 100644
--- a/drivers/input/keyboard/hilkbd.c
+++ b/drivers/input/keyboard/hilkbd.c
@@ -22,7 +22,7 @@
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <linux/init.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/hil.h>
 #include <linux/spinlock.h>
 
@@ -278,11 +278,11 @@
 hil_init_chip(struct parisc_device *dev)
 {
 	if (!dev->irq) {
-		printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
+		printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start);
 		return -ENODEV;
 	}
 
-	hil_base = dev->hpa;
+	hil_base = dev->hpa.start;
 	hil_irq  = dev->irq;
 	hil_dev.dev_id = dev;
 	
@@ -299,7 +299,7 @@
 MODULE_DEVICE_TABLE(parisc, hil_tbl);
 
 static struct parisc_driver hil_driver = {
-	.name =		"HIL",
+	.name =		"hil",
 	.id_table =	hil_tbl,
 	.probe =	hil_init_chip,
 };
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 098963c..7f06780 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -102,7 +102,7 @@
 module_param (ctrlclick_volume, int, 0);
 MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
 
-static int lk201_compose_is_alt = 0;
+static int lk201_compose_is_alt;
 module_param (lk201_compose_is_alt, int, 0);
 MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key "
 		"will act as an Alt key");
@@ -274,7 +274,7 @@
 };
 
 #define CHECK_LED(LED, BITS) do {		\
-	if (test_bit (LED, lk->dev.led))	\
+	if (test_bit (LED, lk->dev->led))	\
 		leds_on |= BITS;		\
 	else					\
 		leds_off |= BITS;		\
@@ -287,7 +287,7 @@
 	lk_keycode_t keycode[LK_NUM_KEYCODES];
 	int ignore_bytes;
 	unsigned char id[LK_NUM_IGNORE_BYTES];
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	struct work_struct tq;
 	char name[64];
@@ -423,8 +423,7 @@
 	DBG (KERN_INFO "Got byte 0x%02x\n", data);
 
 	if (lk->ignore_bytes > 0) {
-		DBG (KERN_INFO "Ignoring a byte on %s\n",
-				lk->name);
+		DBG (KERN_INFO "Ignoring a byte on %s\n", lk->name);
 		lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data;
 
 		if (lk->ignore_bytes == 0)
@@ -435,14 +434,14 @@
 
 	switch (data) {
 		case LK_ALL_KEYS_UP:
-			input_regs (&lk->dev, regs);
+			input_regs (lk->dev, regs);
 			for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
 				if (lk->keycode[i] != KEY_RESERVED)
-					input_report_key (&lk->dev, lk->keycode[i], 0);
-			input_sync (&lk->dev);
+					input_report_key (lk->dev, lk->keycode[i], 0);
+			input_sync (lk->dev);
 			break;
 		case LK_METRONOME:
-			DBG (KERN_INFO "Got LK_METRONOME and don't "
+			DBG (KERN_INFO "Got %#d and don't "
 					"know how to handle...\n");
 			break;
 		case LK_OUTPUT_ERROR:
@@ -482,12 +481,12 @@
 
 		default:
 			if (lk->keycode[data] != KEY_RESERVED) {
-				input_regs (&lk->dev, regs);
-				if (!test_bit (lk->keycode[data], lk->dev.key))
-					input_report_key (&lk->dev, lk->keycode[data], 1);
+				input_regs (lk->dev, regs);
+				if (!test_bit (lk->keycode[data], lk->dev->key))
+					input_report_key (lk->dev, lk->keycode[data], 1);
 				else
-					input_report_key (&lk->dev, lk->keycode[data], 0);
-				input_sync (&lk->dev);
+					input_report_key (lk->dev, lk->keycode[data], 0);
+				input_sync (lk->dev);
                         } else
                                 printk (KERN_WARNING "%s: Unknown key with "
 						"scancode 0x%02x on %s.\n",
@@ -605,7 +604,7 @@
 	lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
 
 	/* Enable/disable keyclick (and possibly set volume) */
-	if (test_bit (SND_CLICK, lk->dev.snd)) {
+	if (test_bit (SND_CLICK, lk->dev->snd)) {
 		lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
 		lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
 		lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@@ -616,7 +615,7 @@
 	}
 
 	/* Sound the bell if needed */
-	if (test_bit (SND_BELL, lk->dev.snd))
+	if (test_bit (SND_BELL, lk->dev->snd))
 		lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
 }
 
@@ -627,71 +626,70 @@
 lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct lkkbd *lk;
+	struct input_dev *input_dev;
 	int i;
 	int err;
 
-	if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset (lk, 0, sizeof (struct lkkbd));
-
-	init_input_dev (&lk->dev);
-	set_bit (EV_KEY, lk->dev.evbit);
-	set_bit (EV_LED, lk->dev.evbit);
-	set_bit (EV_SND, lk->dev.evbit);
-	set_bit (EV_REP, lk->dev.evbit);
-	set_bit (LED_CAPSL, lk->dev.ledbit);
-	set_bit (LED_SLEEP, lk->dev.ledbit);
-	set_bit (LED_COMPOSE, lk->dev.ledbit);
-	set_bit (LED_SCROLLL, lk->dev.ledbit);
-	set_bit (SND_BELL, lk->dev.sndbit);
-	set_bit (SND_CLICK, lk->dev.sndbit);
+	lk = kzalloc (sizeof (struct lkkbd), GFP_KERNEL);
+	input_dev = input_allocate_device ();
+	if (!lk || !input_dev) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	lk->serio = serio;
-
+	lk->dev = input_dev;
 	INIT_WORK (&lk->tq, lkkbd_reinit, lk);
-
 	lk->bell_volume = bell_volume;
 	lk->keyclick_volume = keyclick_volume;
 	lk->ctrlclick_volume = ctrlclick_volume;
+	memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
 
-	lk->dev.keycode = lk->keycode;
-	lk->dev.keycodesize = sizeof (lk_keycode_t);
-	lk->dev.keycodemax = LK_NUM_KEYCODES;
+	strlcpy (lk->name, "DEC LK keyboard", sizeof(lk->name));
+	snprintf (lk->phys, sizeof(lk->phys), "%s/input0", serio->phys);
 
-	lk->dev.event = lkkbd_event;
-	lk->dev.private = lk;
+	input_dev->name = lk->name;
+	input_dev->phys = lk->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_LKKBD;
+	input_dev->id.product = 0;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->event = lkkbd_event;
+	input_dev->private = lk;
+
+	set_bit (EV_KEY, input_dev->evbit);
+	set_bit (EV_LED, input_dev->evbit);
+	set_bit (EV_SND, input_dev->evbit);
+	set_bit (EV_REP, input_dev->evbit);
+	set_bit (LED_CAPSL, input_dev->ledbit);
+	set_bit (LED_SLEEP, input_dev->ledbit);
+	set_bit (LED_COMPOSE, input_dev->ledbit);
+	set_bit (LED_SCROLLL, input_dev->ledbit);
+	set_bit (SND_BELL, input_dev->sndbit);
+	set_bit (SND_CLICK, input_dev->sndbit);
+
+	input_dev->keycode = lk->keycode;
+	input_dev->keycodesize = sizeof (lk_keycode_t);
+	input_dev->keycodemax = LK_NUM_KEYCODES;
+	for (i = 0; i < LK_NUM_KEYCODES; i++)
+		set_bit (lk->keycode[i], input_dev->keybit);
 
 	serio_set_drvdata (serio, lk);
 
 	err = serio_open (serio, drv);
-	if (err) {
-		serio_set_drvdata (serio, NULL);
-		kfree (lk);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	sprintf (lk->name, "DEC LK keyboard");
-	sprintf (lk->phys, "%s/input0", serio->phys);
-
-	memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
-	for (i = 0; i < LK_NUM_KEYCODES; i++)
-		set_bit (lk->keycode[i], lk->dev.keybit);
-
-	lk->dev.name = lk->name;
-	lk->dev.phys = lk->phys;
-	lk->dev.id.bustype = BUS_RS232;
-	lk->dev.id.vendor = SERIO_LKKBD;
-	lk->dev.id.product = 0;
-	lk->dev.id.version = 0x0100;
-	lk->dev.dev = &serio->dev;
-
-	input_register_device (&lk->dev);
-
-	printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
+	input_register_device (lk->dev);
 	lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
 
 	return 0;
+
+ fail:	serio_set_drvdata (serio, NULL);
+	input_free_device (input_dev);
+	kfree (lk);
+	return err;
 }
 
 /*
@@ -702,9 +700,11 @@
 {
 	struct lkkbd *lk = serio_get_drvdata (serio);
 
-	input_unregister_device (&lk->dev);
+	input_get_device (lk->dev);
+	input_unregister_device (lk->dev);
 	serio_close (serio);
 	serio_set_drvdata (serio, NULL);
+	input_put_device (lk->dev);
 	kfree (lk);
 }
 
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c
index eecbde2..cc6aaf9 100644
--- a/drivers/input/keyboard/maple_keyb.c
+++ b/drivers/input/keyboard/maple_keyb.c
@@ -37,7 +37,7 @@
 
 
 struct dc_kbd {
-	struct input_dev dev;
+	struct input_dev *dev;
 	unsigned char new[8];
 	unsigned char old[8];
 };
@@ -46,30 +46,24 @@
 static void dc_scan_kbd(struct dc_kbd *kbd)
 {
 	int i;
-	struct input_dev *dev = &kbd->dev;
+	struct input_dev *dev = kbd->dev;
 
-	for(i=0; i<8; i++)
-		input_report_key(dev,
-				 dc_kbd_keycode[i+224],
-				 (kbd->new[0]>>i)&1);
+	for (i = 0; i < 8; i++)
+		input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
 
-	for(i=2; i<8; i++) {
+	for (i = 2; i < 8; i++) {
 
-		if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) {
-			if(dc_kbd_keycode[kbd->old[i]])
-				input_report_key(dev,
-						 dc_kbd_keycode[kbd->old[i]],
-						 0);
+		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) {
+			if (dc_kbd_keycode[kbd->old[i]])
+				input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0);
 			else
 				printk("Unknown key (scancode %#x) released.",
 				       kbd->old[i]);
 		}
 
-		if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) {
+		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) {
 			if(dc_kbd_keycode[kbd->new[i]])
-				input_report_key(dev,
-						 dc_kbd_keycode[kbd->new[i]],
-						 1);
+				input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1);
 			else
 				printk("Unknown key (scancode %#x) pressed.",
 				       kbd->new[i]);
@@ -89,43 +83,39 @@
 	unsigned long *buf = mq->recvbuf;
 
 	if (buf[1] == mapledev->function) {
-		memcpy(kbd->new, buf+2, 8);
+		memcpy(kbd->new, buf + 2, 8);
 		dc_scan_kbd(kbd);
 	}
 }
 
 static int dc_kbd_connect(struct maple_device *dev)
 {
-	int i;
-	unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
 	struct dc_kbd *kbd;
+	struct input_dev *input_dev;
+	unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
+	int i;
 
-	if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL)))
-		return -1;
-	memset(kbd, 0, sizeof(struct dc_kbd));
+	dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!kbd || !input_dev) {
+		kfree(kbd);
+		input_free_device(input_dev);
+		return -ENOMEM;
+	}
 
-	dev->private_data = kbd;
+	kbd->dev = input_dev;
 
-	kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	input_dev->name = dev->product_name;
+	input_dev->id.bustype = BUS_MAPLE;
+	input_dev->private = kbd;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	for (i = 0; i < 255; i++)
+		set_bit(dc_kbd_keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
 
-	init_input_dev(&kbd->dev);
-
-	for (i=0; i<255; i++)
-		set_bit(dc_kbd_keycode[i], kbd->dev.keybit);
-
-	clear_bit(0, kbd->dev.keybit);
-
-	kbd->dev.private = kbd;
-
-	kbd->dev.name = dev->product_name;
-	kbd->dev.id.bustype = BUS_MAPLE;
-
-	input_register_device(&kbd->dev);
+	input_register_device(kbd->dev);
 
 	maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
-
-	printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name);
-
 	return 0;
 }
 
@@ -134,7 +124,7 @@
 {
 	struct dc_kbd *kbd = dev->private_data;
 
-	input_unregister_device(&kbd->dev);
+	input_unregister_device(kbd->dev);
 	kfree(kbd);
 }
 
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 2e8ce16..d10983c 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -57,11 +57,9 @@
 	KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
 };
 
-static char *nkbd_name = "Newton Keyboard";
-
 struct nkbd {
 	unsigned char keycode[128];
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	char phys[32];
 };
@@ -73,13 +71,13 @@
 
 	/* invalid scan codes are probably the init sequence, so we ignore them */
 	if (nkbd->keycode[data & NKBD_KEY]) {
-		input_regs(&nkbd->dev, regs);
-		input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
-		input_sync(&nkbd->dev);
+		input_regs(nkbd->dev, regs);
+		input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
+		input_sync(nkbd->dev);
 	}
 
 	else if (data == 0xe7) /* end of init sequence */
-		printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+		printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);
 	return IRQ_HANDLED;
 
 }
@@ -87,62 +85,59 @@
 static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct nkbd *nkbd;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 	int i;
-	int err;
 
-	if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset(nkbd, 0, sizeof(struct nkbd));
-
-	nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!nkbd || !input_dev)
+		goto fail;
 
 	nkbd->serio = serio;
+	nkbd->dev = input_dev;
+	sprintf(nkbd->phys, "%s/input0", serio->phys);
+	memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
 
-	init_input_dev(&nkbd->dev);
-	nkbd->dev.keycode = nkbd->keycode;
-	nkbd->dev.keycodesize = sizeof(unsigned char);
-	nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
-	nkbd->dev.private = nkbd;
+	input_dev->name = "Newton Keyboard";
+	input_dev->phys = nkbd->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_NEWTON;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = nkbd;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	input_dev->keycode = nkbd->keycode;
+	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
+	for (i = 0; i < 128; i++)
+		set_bit(nkbd->keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
 
 	serio_set_drvdata(serio, nkbd);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(nkbd);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
-	for (i = 0; i < 128; i++)
-		set_bit(nkbd->keycode[i], nkbd->dev.keybit);
-	clear_bit(0, nkbd->dev.keybit);
-
-	sprintf(nkbd->phys, "%s/input0", serio->phys);
-
-	nkbd->dev.name = nkbd_name;
-	nkbd->dev.phys = nkbd->phys;
-	nkbd->dev.id.bustype = BUS_RS232;
-	nkbd->dev.id.vendor = SERIO_NEWTON;
-	nkbd->dev.id.product = 0x0001;
-	nkbd->dev.id.version = 0x0100;
-	nkbd->dev.dev = &serio->dev;
-
-	input_register_device(&nkbd->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
-
+	input_register_device(nkbd->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(nkbd);
+	return err;
 }
 
 static void nkbd_disconnect(struct serio *serio)
 {
 	struct nkbd *nkbd = serio_get_drvdata(serio);
 
-	input_unregister_device(&nkbd->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(nkbd->dev);
 	kfree(nkbd);
 }
 
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 344f460..cee9c73 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -85,7 +85,7 @@
 
 struct spitzkbd {
 	unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
-	struct input_dev input;
+	struct input_dev *input;
 	char phys[32];
 
 	spinlock_t lock;
@@ -187,8 +187,7 @@
 
 	spin_lock_irqsave(&spitzkbd_data->lock, flags);
 
-	if (regs)
-		input_regs(&spitzkbd_data->input, regs);
+	input_regs(spitzkbd_data->input, regs);
 
 	num_pressed = 0;
 	for (col = 0; col < KB_COLS; col++) {
@@ -210,7 +209,7 @@
 			scancode = SCANCODE(row, col);
 			pressed = rowd & KB_ROWMASK(row);
 
-			input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+			input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
 
 			if (pressed)
 				num_pressed++;
@@ -220,15 +219,15 @@
 
 	spitzkbd_activate_all();
 
-	input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
-	input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+	input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+	input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey);
 
 	if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
-		input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+		input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
 		spitzkbd_data->suspend_jiffies = jiffies;
 	}
 
-	input_sync(&spitzkbd_data->input);
+	input_sync(spitzkbd_data->input);
 
 	/* if any keys are pressed, enable the timer */
 	if (num_pressed)
@@ -259,6 +258,7 @@
 static void spitzkbd_timer_callback(unsigned long data)
 {
 	struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+
 	spitzkbd_scankeyboard(spitzkbd_data, NULL);
 }
 
@@ -298,9 +298,9 @@
 	if (hinge_count >= HINGE_STABLE_COUNT) {
 		spin_lock_irqsave(&spitzkbd_data->lock, flags);
 
-		input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
-		input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
-		input_sync(&spitzkbd_data->input);
+		input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+		input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+		input_sync(spitzkbd_data->input);
 
 		spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
 	} else {
@@ -309,34 +309,32 @@
 }
 
 #ifdef CONFIG_PM
-static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int spitzkbd_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		int i;
-		struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
-		spitzkbd->suspended = 1;
+	int i;
+	struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+	spitzkbd->suspended = 1;
 
-		/* Set Strobe lines as inputs - *except* strobe line 0 leave this
-		   enabled so we can detect a power button press for resume */
-		for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
-			pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
-	}
+	/* Set Strobe lines as inputs - *except* strobe line 0 leave this
+	   enabled so we can detect a power button press for resume */
+	for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+		pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+
 	return 0;
 }
 
-static int spitzkbd_resume(struct device *dev, uint32_t level)
+static int spitzkbd_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		int i;
-		struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+	int i;
+	struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
 
-		for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
-			pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+	for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+		pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
 
-		/* Upon resume, ignore the suspend key for a short while */
-		spitzkbd->suspend_jiffies = jiffies;
-		spitzkbd->suspended = 0;
-	}
+	/* Upon resume, ignore the suspend key for a short while */
+	spitzkbd->suspend_jiffies = jiffies;
+	spitzkbd->suspended = 0;
+
 	return 0;
 }
 #else
@@ -346,14 +344,21 @@
 
 static int __init spitzkbd_probe(struct device *dev)
 {
-	int i;
 	struct spitzkbd *spitzkbd;
+	struct input_dev *input_dev;
+	int i;
 
 	spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
 	if (!spitzkbd)
 		return -ENOMEM;
 
-	dev_set_drvdata(dev,spitzkbd);
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		kfree(spitzkbd);
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(dev, spitzkbd);
 	strcpy(spitzkbd->phys, "spitzkbd/input0");
 
 	spin_lock_init(&spitzkbd->lock);
@@ -368,30 +373,34 @@
 	spitzkbd->htimer.function = spitzkbd_hinge_timer;
 	spitzkbd->htimer.data = (unsigned long) spitzkbd;
 
-	spitzkbd->suspend_jiffies=jiffies;
+	spitzkbd->suspend_jiffies = jiffies;
 
-	init_input_dev(&spitzkbd->input);
-	spitzkbd->input.private = spitzkbd;
-	spitzkbd->input.name = "Spitz Keyboard";
-	spitzkbd->input.dev = dev;
-	spitzkbd->input.phys = spitzkbd->phys;
-	spitzkbd->input.id.bustype = BUS_HOST;
-	spitzkbd->input.id.vendor = 0x0001;
-	spitzkbd->input.id.product = 0x0001;
-	spitzkbd->input.id.version = 0x0100;
-	spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
-	spitzkbd->input.keycode = spitzkbd->keycode;
-	spitzkbd->input.keycodesize = sizeof(unsigned char);
-	spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+	spitzkbd->input = input_dev;
+
+	input_dev->private = spitzkbd;
+	input_dev->name = "Spitz Keyboard";
+	input_dev->phys = spitzkbd->phys;
+	input_dev->cdev.dev = dev;
+
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+	input_dev->keycode = spitzkbd->keycode;
+	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode);
 
 	memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
 	for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
-		set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit);
-	clear_bit(0, spitzkbd->input.keybit);
-	set_bit(SW_0, spitzkbd->input.swbit);
-	set_bit(SW_1, spitzkbd->input.swbit);
+		set_bit(spitzkbd->keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
+	set_bit(SW_0, input_dev->swbit);
+	set_bit(SW_1, input_dev->swbit);
 
-	input_register_device(&spitzkbd->input);
+	input_register_device(input_dev);
+
 	mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
 
 	/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
@@ -444,7 +453,7 @@
 	del_timer_sync(&spitzkbd->htimer);
 	del_timer_sync(&spitzkbd->timer);
 
-	input_unregister_device(&spitzkbd->input);
+	input_unregister_device(spitzkbd->input);
 
 	kfree(spitzkbd);
 
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 4bae5d8..b15b6d8 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -76,13 +76,14 @@
 
 struct sunkbd {
 	unsigned char keycode[128];
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	struct work_struct tq;
 	wait_queue_head_t wait;
 	char name[64];
 	char phys[32];
 	char type;
+	unsigned char enabled;
 	volatile s8 reset;
 	volatile s8 layout;
 };
@@ -124,10 +125,13 @@
 			break;
 
 		default:
+			if (!sunkbd->enabled)
+				break;
+
 			if (sunkbd->keycode[data & SUNKBD_KEY]) {
-				input_regs(&sunkbd->dev, regs);
-                                input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
-				input_sync(&sunkbd->dev);
+				input_regs(sunkbd->dev, regs);
+                                input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
+				input_sync(sunkbd->dev);
                         } else {
                                 printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
                                         data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
@@ -184,7 +188,7 @@
 	sunkbd->reset = -2;
 	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
 	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
-	if (sunkbd->reset <0)
+	if (sunkbd->reset < 0)
 		return -1;
 
 	sunkbd->type = sunkbd->reset;
@@ -213,10 +217,17 @@
 
 	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
 	sunkbd->serio->write(sunkbd->serio,
-		(!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) |
-		(!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led));
-	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd));
-	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd));
+		(!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
+		(!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led));
+	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
+	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
+}
+
+static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
+{
+	serio_pause_rx(sunkbd->serio);
+	sunkbd->enabled = 1;
+	serio_continue_rx(sunkbd->serio);
 }
 
 /*
@@ -226,70 +237,64 @@
 static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sunkbd *sunkbd;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 	int i;
-	int err;
 
-	if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset(sunkbd, 0, sizeof(struct sunkbd));
-
-	init_input_dev(&sunkbd->dev);
-	init_waitqueue_head(&sunkbd->wait);
-
-	sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
-	sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
-	sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+	sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!sunkbd || !input_dev)
+		goto fail;
 
 	sunkbd->serio = serio;
-
+	sunkbd->dev = input_dev;
+	init_waitqueue_head(&sunkbd->wait);
 	INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
-
-	sunkbd->dev.keycode = sunkbd->keycode;
-	sunkbd->dev.keycodesize = sizeof(unsigned char);
-	sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
-
-	sunkbd->dev.event = sunkbd_event;
-	sunkbd->dev.private = sunkbd;
+	snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
 
 	serio_set_drvdata(serio, sunkbd);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(sunkbd);
-		return err;
-	}
+	if (err)
+		goto fail;
 
 	if (sunkbd_initialize(sunkbd) < 0) {
 		serio_close(serio);
-		serio_set_drvdata(serio, NULL);
-		kfree(sunkbd);
-		return -ENODEV;
+		goto fail;
 	}
 
 	sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
-
 	memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
+
+	input_dev->name = sunkbd->name;
+	input_dev->phys = sunkbd->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor  = SERIO_SUNKBD;
+	input_dev->id.product = sunkbd->type;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = sunkbd;
+	input_dev->event = sunkbd_event;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
+	input_dev->ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
+	input_dev->sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
+
+	input_dev->keycode = sunkbd->keycode;
+	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
 	for (i = 0; i < 128; i++)
-		set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
-	clear_bit(0, sunkbd->dev.keybit);
+		set_bit(sunkbd->keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
 
-	sprintf(sunkbd->phys, "%s/input0", serio->phys);
-
-	sunkbd->dev.name = sunkbd->name;
-	sunkbd->dev.phys = sunkbd->phys;
-	sunkbd->dev.id.bustype = BUS_RS232;
-	sunkbd->dev.id.vendor = SERIO_SUNKBD;
-	sunkbd->dev.id.product = sunkbd->type;
-	sunkbd->dev.id.version = 0x0100;
-	sunkbd->dev.dev = &serio->dev;
-
-	input_register_device(&sunkbd->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
-
+	sunkbd_enable(sunkbd, 1);
+	input_register_device(sunkbd->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(sunkbd);
+	return err;
 }
 
 /*
@@ -299,7 +304,9 @@
 static void sunkbd_disconnect(struct serio *serio)
 {
 	struct sunkbd *sunkbd = serio_get_drvdata(serio);
-	input_unregister_device(&sunkbd->dev);
+
+	sunkbd_enable(sunkbd, 0);
+	input_unregister_device(sunkbd->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
 	kfree(sunkbd);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 19eaec7..4135e3e 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -56,11 +56,9 @@
 	106
 };
 
-static char *xtkbd_name = "XT Keyboard";
-
 struct xtkbd {
 	unsigned char keycode[256];
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	char phys[32];
 };
@@ -77,9 +75,9 @@
 		default:
 
 			if (xtkbd->keycode[data & XTKBD_KEY]) {
-				input_regs(&xtkbd->dev, regs);
-				input_report_key(&xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
-				input_sync(&xtkbd->dev);
+				input_regs(xtkbd->dev, regs);
+				input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
+				input_sync(xtkbd->dev);
 			} else {
 				printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
 					data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
@@ -91,62 +89,60 @@
 static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct xtkbd *xtkbd;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 	int i;
-	int err;
 
-	if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset(xtkbd, 0, sizeof(struct xtkbd));
-
-	xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!xtkbd || !input_dev)
+		goto fail;
 
 	xtkbd->serio = serio;
+	xtkbd->dev = input_dev;
+	sprintf(xtkbd->phys, "%s/input0", serio->phys);
+	memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
 
-	init_input_dev(&xtkbd->dev);
-	xtkbd->dev.keycode = xtkbd->keycode;
-	xtkbd->dev.keycodesize = sizeof(unsigned char);
-	xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
-	xtkbd->dev.private = xtkbd;
+	input_dev->name = "XT Keyboard";
+	input_dev->phys = xtkbd->phys;
+	input_dev->id.bustype = BUS_XTKBD;
+	input_dev->id.vendor  = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = xtkbd;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	input_dev->keycode = xtkbd->keycode;
+	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
+
+	for (i = 0; i < 255; i++)
+		set_bit(xtkbd->keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
 
 	serio_set_drvdata(serio, xtkbd);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(xtkbd);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
-	for (i = 0; i < 255; i++)
-		set_bit(xtkbd->keycode[i], xtkbd->dev.keybit);
-	clear_bit(0, xtkbd->dev.keybit);
-
-	sprintf(xtkbd->phys, "%s/input0", serio->phys);
-
-	xtkbd->dev.name = xtkbd_name;
-	xtkbd->dev.phys = xtkbd->phys;
-	xtkbd->dev.id.bustype = BUS_XTKBD;
-	xtkbd->dev.id.vendor = 0x0001;
-	xtkbd->dev.id.product = 0x0001;
-	xtkbd->dev.id.version = 0x0100;
-	xtkbd->dev.dev = &serio->dev;
-
-	input_register_device(&xtkbd->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
-
+	input_register_device(xtkbd->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(xtkbd);
+	return err;
 }
 
 static void xtkbd_disconnect(struct serio *serio)
 {
 	struct xtkbd *xtkbd = serio_get_drvdata(serio);
 
-	input_unregister_device(&xtkbd->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(xtkbd->dev);
 	kfree(xtkbd);
 }
 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index bb934e6..b3eaac1 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -14,7 +14,7 @@
 
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
-	depends on ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
+	depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
 	help
 	  Say Y here if you want the standard PC Speaker to be used for
 	  bells and whistles.
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 64abdd9..04489ad 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -24,9 +24,7 @@
 MODULE_DESCRIPTION("m68k beeper driver");
 MODULE_LICENSE("GPL");
 
-static char m68kspkr_name[] = "m68k beeper";
-static char m68kspkr_phys[] = "m68k/generic";
-static struct input_dev m68kspkr_dev;
+static struct input_dev *m68kspkr_dev;
 
 static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -51,32 +49,34 @@
 
 static int __init m68kspkr_init(void)
 {
-        if (!mach_beep){
-		printk("%s: no lowlevel beep support\n", m68kspkr_name);
-		return -1;
+        if (!mach_beep) {
+		printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
+		return -ENODEV;
         }
 
-	m68kspkr_dev.evbit[0] = BIT(EV_SND);
-	m68kspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-	m68kspkr_dev.event = m68kspkr_event;
+	m68kspkr_dev = input_allocate_device();
+	if (!m68kspkr_dev)
+		return -ENOMEM;
 
-	m68kspkr_dev.name = m68kspkr_name;
-	m68kspkr_dev.phys = m68kspkr_phys;
-	m68kspkr_dev.id.bustype = BUS_HOST;
-	m68kspkr_dev.id.vendor = 0x001f;
-	m68kspkr_dev.id.product = 0x0001;
-	m68kspkr_dev.id.version = 0x0100;
+	m68kspkr_dev->name = "m68k beeper";
+	m68kspkr_dev->phys = "m68k/generic";
+	m68kspkr_dev->id.bustype = BUS_HOST;
+	m68kspkr_dev->id.vendor = 0x001f;
+	m68kspkr_dev->id.product = 0x0001;
+	m68kspkr_dev->id.version = 0x0100;
 
-	input_register_device(&m68kspkr_dev);
+	m68kspkr_dev->evbit[0] = BIT(EV_SND);
+	m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	m68kspkr_dev->event = m68kspkr_event;
 
-        printk(KERN_INFO "input: %s\n", m68kspkr_name);
+	input_register_device(m68kspkr_dev);
 
 	return 0;
 }
 
 static void __exit m68kspkr_exit(void)
 {
-        input_unregister_device(&m68kspkr_dev);
+        input_unregister_device(m68kspkr_dev);
 }
 
 module_init(m68kspkr_init);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 3013194..e34633c 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -23,9 +23,7 @@
 MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
-static char pcspkr_name[] = "PC Speaker";
-static char pcspkr_phys[] = "isa0061/input0";
-static struct input_dev pcspkr_dev;
+static struct input_dev *pcspkr_dev;
 
 static DEFINE_SPINLOCK(i8253_beep_lock);
 
@@ -68,27 +66,29 @@
 
 static int __init pcspkr_init(void)
 {
-	pcspkr_dev.evbit[0] = BIT(EV_SND);
-	pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-	pcspkr_dev.event = pcspkr_event;
+	pcspkr_dev = input_allocate_device();
+	if (!pcspkr_dev)
+		return -ENOMEM;
 
-	pcspkr_dev.name = pcspkr_name;
-	pcspkr_dev.phys = pcspkr_phys;
-	pcspkr_dev.id.bustype = BUS_ISA;
-	pcspkr_dev.id.vendor = 0x001f;
-	pcspkr_dev.id.product = 0x0001;
-	pcspkr_dev.id.version = 0x0100;
+	pcspkr_dev->name = "PC Speaker";
+	pcspkr_dev->name = "isa0061/input0";
+	pcspkr_dev->id.bustype = BUS_ISA;
+	pcspkr_dev->id.vendor = 0x001f;
+	pcspkr_dev->id.product = 0x0001;
+	pcspkr_dev->id.version = 0x0100;
 
-	input_register_device(&pcspkr_dev);
+	pcspkr_dev->evbit[0] = BIT(EV_SND);
+	pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	pcspkr_dev->event = pcspkr_event;
 
-        printk(KERN_INFO "input: %s\n", pcspkr_name);
+	input_register_device(pcspkr_dev);
 
 	return 0;
 }
 
 static void __exit pcspkr_exit(void)
 {
-        input_unregister_device(&pcspkr_dev);
+        input_unregister_device(pcspkr_dev);
 	/* turn off the speaker */
 	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 }
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index cdc3fb3..29d97b1 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -17,28 +17,24 @@
 #endif
 
 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
-MODULE_DESCRIPTION("PC Speaker beeper driver");
+MODULE_DESCRIPTION("Sparc Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
 static unsigned long beep_iobase;
-
-static char *sparcspkr_isa_name = "Sparc ISA Speaker";
-static char *sparcspkr_ebus_name = "Sparc EBUS Speaker";
-static char *sparcspkr_phys = "sparc/input0";
-static struct input_dev sparcspkr_dev;
+static struct input_dev *sparcspkr_dev;
 
 DEFINE_SPINLOCK(beep_lock);
 
 static void __init init_sparcspkr_struct(void)
 {
-	sparcspkr_dev.evbit[0] = BIT(EV_SND);
-	sparcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	sparcspkr_dev->evbit[0] = BIT(EV_SND);
+	sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 
-	sparcspkr_dev.phys = sparcspkr_phys;
-	sparcspkr_dev.id.bustype = BUS_ISA;
-	sparcspkr_dev.id.vendor = 0x001f;
-	sparcspkr_dev.id.product = 0x0001;
-	sparcspkr_dev.id.version = 0x0100;
+	sparcspkr_dev->phys = "sparc/input0";
+	sparcspkr_dev->id.bustype = BUS_ISA;
+	sparcspkr_dev->id.vendor = 0x001f;
+	sparcspkr_dev->id.product = 0x0001;
+	sparcspkr_dev->id.version = 0x0100;
 }
 
 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -84,14 +80,15 @@
 {
 	beep_iobase = edev->resource[0].start;
 
-	init_sparcspkr_struct();
+	sparcspkr_dev = input_allocate_device();
+	if (!sparcspkr_dev)
+		return -ENOMEM;
 
-	sparcspkr_dev.name = sparcspkr_ebus_name;
-	sparcspkr_dev.event = ebus_spkr_event;
+	sparcspkr_dev->name = "Sparc EBUS Speaker";
+	sparcspkr_dev->event = ebus_spkr_event;
 
-	input_register_device(&sparcspkr_dev);
+	input_register_device(sparcspkr_dev);
 
-        printk(KERN_INFO "input: %s\n", sparcspkr_ebus_name);
 	return 0;
 }
 
@@ -137,15 +134,17 @@
 {
 	beep_iobase = isa_dev->resource.start;
 
+	sparcspkr_dev = input_allocate_device();
+	if (!sparcspkr_dev)
+		return -ENOMEM;
+
 	init_sparcspkr_struct();
 
-	sparcspkr_dev.name = sparcspkr_isa_name;
-	sparcspkr_dev.event = isa_spkr_event;
-	sparcspkr_dev.id.bustype = BUS_ISA;
+	sparcspkr_dev->name = "Sparc ISA Speaker";
+	sparcspkr_dev->event = isa_spkr_event;
 
-	input_register_device(&sparcspkr_dev);
+	input_register_device(sparcspkr_dev);
 
-        printk(KERN_INFO "input: %s\n", sparcspkr_isa_name);
 	return 0;
 }
 #endif
@@ -182,7 +181,7 @@
 
 static void __exit sparcspkr_exit(void)
 {
-	input_unregister_device(&sparcspkr_dev);
+	input_unregister_device(sparcspkr_dev);
 }
 
 module_init(sparcspkr_init);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b20783f..4acc7fd 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -79,8 +79,8 @@
 {
 	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = &psmouse->dev;
-	struct input_dev *dev2 = &priv->dev2;
+	struct input_dev *dev = psmouse->dev;
+	struct input_dev *dev2 = priv->dev2;
 	int x, y, z, ges, fin, left, right, middle;
 	int back = 0, forward = 0;
 
@@ -379,20 +379,24 @@
 static void alps_disconnect(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
+
 	psmouse_reset(psmouse);
-	input_unregister_device(&priv->dev2);
+	input_unregister_device(priv->dev2);
 	kfree(priv);
 }
 
 int alps_init(struct psmouse *psmouse)
 {
 	struct alps_data *priv;
+	struct input_dev *dev1 = psmouse->dev, *dev2;
 	int version;
 
-	psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL);
-	if (!priv)
+	psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+	dev2 = input_allocate_device();
+	if (!priv || !dev2)
 		goto init_fail;
-	memset(priv, 0, sizeof(struct alps_data));
+
+	priv->dev2 = dev2;
 
 	if (!(priv->i = alps_get_model(psmouse, &version)))
 		goto init_fail;
@@ -411,41 +415,39 @@
 	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
 		goto init_fail;
 
-	psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
-	psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
-	psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
-	psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	dev1->evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
+	dev1->keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+	dev1->keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
+	dev1->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
-	psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
-	input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0);
-	input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0);
-	input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
+	dev1->evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
+	input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
+	input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
+	input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
 
 	if (priv->i->flags & ALPS_WHEEL) {
-		psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
-		psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
+		dev1->evbit[LONG(EV_REL)] |= BIT(EV_REL);
+		dev1->relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
 	}
 
 	if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
-		psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
-		psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+		dev1->keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
+		dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
 	}
 
 	sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
-	priv->dev2.phys = priv->phys;
-	priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
-	priv->dev2.id.bustype = BUS_I8042;
-	priv->dev2.id.vendor = 0x0002;
-	priv->dev2.id.product = PSMOUSE_ALPS;
-	priv->dev2.id.version = 0x0000;
+	dev2->phys = priv->phys;
+	dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
+	dev2->id.bustype = BUS_I8042;
+	dev2->id.vendor  = 0x0002;
+	dev2->id.product = PSMOUSE_ALPS;
+	dev2->id.version = 0x0000;
 
-	priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
-	priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
+	dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
-	input_register_device(&priv->dev2);
-
-	printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
+	input_register_device(priv->dev2);
 
 	psmouse->protocol_handler = alps_process_byte;
 	psmouse->disconnect = alps_disconnect;
@@ -455,6 +457,7 @@
 	return 0;
 
 init_fail:
+	input_free_device(dev2);
 	kfree(priv);
 	return -1;
 }
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index aba103d..e428f8d 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -22,7 +22,7 @@
 };
 
 struct alps_data {
-	struct input_dev dev2;		/* Relative device */
+	struct input_dev *dev2;		/* Relative device */
 	char name[32];			/* Name */
 	char phys[32];			/* Phys */
 	struct alps_model_info *i; 	/* Info */
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index e994849..d13d4c8 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -34,10 +34,7 @@
 MODULE_LICENSE("GPL");
 
 static int amimouse_lastx, amimouse_lasty;
-static struct input_dev amimouse_dev;
-
-static char *amimouse_name = "Amiga mouse";
-static char *amimouse_phys = "amimouse/input0";
+static struct input_dev *amimouse_dev;
 
 static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
@@ -62,16 +59,16 @@
 
 	potgor = custom.potgor;
 
-	input_regs(&amimouse_dev, fp);
+	input_regs(amimouse_dev, fp);
 
-	input_report_rel(&amimouse_dev, REL_X, dx);
-	input_report_rel(&amimouse_dev, REL_Y, dy);
+	input_report_rel(amimouse_dev, REL_X, dx);
+	input_report_rel(amimouse_dev, REL_Y, dy);
 
-	input_report_key(&amimouse_dev, BTN_LEFT,   ciaa.pra & 0x40);
-	input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
-	input_report_key(&amimouse_dev, BTN_RIGHT,  potgor & 0x0400);
+	input_report_key(amimouse_dev, BTN_LEFT,   ciaa.pra & 0x40);
+	input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
+	input_report_key(amimouse_dev, BTN_RIGHT,  potgor & 0x0400);
 
-	input_sync(&amimouse_dev);
+	input_sync(amimouse_dev);
 
 	return IRQ_HANDLED;
 }
@@ -103,28 +100,30 @@
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
 		return -ENODEV;
 
-	amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	amimouse_dev.open = amimouse_open;
-	amimouse_dev.close = amimouse_close;
+	if (!(amimouse_dev = input_allocate_device()))
+		return -ENOMEM;
 
-	amimouse_dev.name = amimouse_name;
-	amimouse_dev.phys = amimouse_phys;
-	amimouse_dev.id.bustype = BUS_AMIGA;
-	amimouse_dev.id.vendor = 0x0001;
-	amimouse_dev.id.product = 0x0002;
-	amimouse_dev.id.version = 0x0100;
+	amimouse_dev->name = "Amiga mouse";
+	amimouse_dev->phys = "amimouse/input0";
+	amimouse_dev->id.bustype = BUS_AMIGA;
+	amimouse_dev->id.vendor = 0x0001;
+	amimouse_dev->id.product = 0x0002;
+	amimouse_dev->id.version = 0x0100;
 
-	input_register_device(&amimouse_dev);
+	amimouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	amimouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	amimouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	amimouse_dev->open = amimouse_open;
+	amimouse_dev->close = amimouse_close;
 
-        printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
+	input_register_device(amimouse_dev);
+
 	return 0;
 }
 
 static void __exit amimouse_exit(void)
 {
-        input_unregister_device(&amimouse_dev);
+        input_unregister_device(amimouse_dev);
 }
 
 module_init(amimouse_init);
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index bc22849..c2bf2ed 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -196,7 +196,7 @@
 	hil_packet packet;
 	int idx;
 
-	ptr = (struct hil_ptr *)serio->private;
+	ptr = serio_get_drvdata(serio);
 	if (ptr == NULL) {
 		BUG();
 		return IRQ_HANDLED;
@@ -227,7 +227,7 @@
 {
 	struct hil_ptr *ptr;
 
-	ptr = (struct hil_ptr *)serio->private;
+	ptr = serio_get_drvdata(serio);
 	if (ptr == NULL) {
 		BUG();
 		return;
@@ -238,21 +238,19 @@
 	kfree(ptr);
 }
 
-static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
+static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
 	struct hil_ptr	*ptr;
 	char		*txt;
 	unsigned int	i, naxsets, btntype;
 	uint8_t		did, *idd;
 
-	if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
-
-	if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
+	if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM;
 	memset(ptr, 0, sizeof(struct hil_ptr));
 
 	if (serio_open(serio, driver)) goto bail0;
 
-	serio->private = ptr;
+	serio_set_drvdata(serio, ptr);
 	ptr->serio = serio;
 	ptr->dev.private = ptr;
 
@@ -380,23 +378,34 @@
 		(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
 		did);
 
-	return;
+	return 0;
  bail1:
 	serio_close(serio);
  bail0:
 	kfree(ptr);
-	return;
+	serio_set_drvdata(serio, NULL);
+	return -ENODEV;
 }
 
+static struct serio_device_id hil_ptr_ids[] = {
+	{
+		.type = SERIO_HIL_MLC,
+		.proto = SERIO_HIL,
+		.id = SERIO_ANY,
+		.extra = SERIO_ANY,
+	},
+	{ 0 }
+};
 
 static struct serio_driver hil_ptr_serio_driver = {
 	.driver		= {
 		.name	= "hil_ptr",
 	},
 	.description	= "HP HIL mouse/tablet driver",
-	.connect =	hil_ptr_connect,
-	.disconnect =	hil_ptr_disconnect,
-	.interrupt =	hil_ptr_interrupt
+	.id_table	= hil_ptr_ids,
+	.connect	= hil_ptr_connect,
+	.disconnect	= hil_ptr_disconnect,
+	.interrupt	= hil_ptr_interrupt
 };
 
 static int __init hil_ptr_init(void)
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 1f62c01..afc66f5 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -87,7 +87,36 @@
 
 __obsolete_setup("inport_irq=");
 
-static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct input_dev *inport_dev;
+
+static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned char buttons;
+
+	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+	outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+
+	input_regs(inport_dev, regs);
+
+	outb(INPORT_REG_X, INPORT_CONTROL_PORT);
+	input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
+
+	outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
+	input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT));
+
+	outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
+	buttons = inb(INPORT_DATA_PORT);
+
+	input_report_key(inport_dev, BTN_MIDDLE, buttons & 1);
+	input_report_key(inport_dev, BTN_LEFT,   buttons & 2);
+	input_report_key(inport_dev, BTN_RIGHT,  buttons & 4);
+
+	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
+	outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
+
+	input_sync(inport_dev);
+	return IRQ_HANDLED;
+}
 
 static int inport_open(struct input_dev *dev)
 {
@@ -106,54 +135,9 @@
 	free_irq(inport_irq, NULL);
 }
 
-static struct input_dev inport_dev = {
-	.evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
-	.keybit	= { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
-	.relbit	= { BIT(REL_X) | BIT(REL_Y) },
-	.open	= inport_open,
-	.close	= inport_close,
-	.name	= INPORT_NAME,
-	.phys	= "isa023c/input0",
-	.id = {
-		.bustype = BUS_ISA,
-		.vendor  = INPORT_VENDOR,
-		.product = 0x0001,
-		.version = 0x0100,
-	},
-};
-
-static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned char buttons;
-
-	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
-	outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
-	input_regs(&inport_dev, regs);
-
-	outb(INPORT_REG_X, INPORT_CONTROL_PORT);
-	input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
-
-	outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
-	input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
-
-	outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
-	buttons = inb(INPORT_DATA_PORT);
-
-	input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
-	input_report_key(&inport_dev, BTN_LEFT,   buttons & 2);
-	input_report_key(&inport_dev, BTN_RIGHT,  buttons & 4);
-
-	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
-	outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
-
-	input_sync(&inport_dev);
-	return IRQ_HANDLED;
-}
-
 static int __init inport_init(void)
 {
-	unsigned char a,b,c;
+	unsigned char a, b, c;
 
 	if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
 		printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@@ -163,26 +147,44 @@
 	a = inb(INPORT_SIGNATURE_PORT);
 	b = inb(INPORT_SIGNATURE_PORT);
 	c = inb(INPORT_SIGNATURE_PORT);
-	if (( a == b ) || ( a != c )) {
+	if (a == b || a != c) {
 		release_region(INPORT_BASE, INPORT_EXTENT);
 		printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
 		return -ENODEV;
 	}
 
+	if (!(inport_dev = input_allocate_device())) {
+		printk(KERN_ERR "inport.c: Not enough memory for input device\n");
+		release_region(INPORT_BASE, INPORT_EXTENT);
+		return -ENOMEM;
+	}
+
+	inport_dev->name = INPORT_NAME;
+	inport_dev->phys = "isa023c/input0";
+	inport_dev->id.bustype = BUS_ISA;
+	inport_dev->id.vendor  = INPORT_VENDOR;
+	inport_dev->id.product = 0x0001;
+	inport_dev->id.version = 0x0100;
+
+	inport_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	inport_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	inport_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+	inport_dev->open  = inport_open;
+	inport_dev->close = inport_close;
+
 	outb(INPORT_RESET, INPORT_CONTROL_PORT);
 	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
 	outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
 
-	input_register_device(&inport_dev);
-
-	printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n", INPORT_BASE, inport_irq);
+	input_register_device(inport_dev);
 
 	return 0;
 }
 
 static void __exit inport_exit(void)
 {
-	input_unregister_device(&inport_dev);
+	input_unregister_device(inport_dev);
 	release_region(INPORT_BASE, INPORT_EXTENT);
 }
 
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index bd9df9b..5599142 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -34,7 +34,7 @@
 static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
 	unsigned char *packet = psmouse->packet;
-	struct input_dev *dev = &psmouse->dev;
+	struct input_dev *dev = psmouse->dev;
 
 	if (psmouse->pktcnt != 3)
 		return PSMOUSE_GOOD_DATA;
@@ -113,15 +113,17 @@
 
 int lifebook_init(struct psmouse *psmouse)
 {
+	struct input_dev *input_dev = psmouse->dev;
+
 	if (lifebook_absolute_mode(psmouse))
 		return -1;
 
-	psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
-	psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0);
-	input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0);
+	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
+	input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
 
 	psmouse->protocol_handler = lifebook_process_byte;
 	psmouse->set_resolution = lifebook_set_resolution;
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 8b52431..9c7ce38 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -77,39 +77,7 @@
 
 __obsolete_setup("logibm_irq=");
 
-static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static int logibm_open(struct input_dev *dev)
-{
-	if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
-		printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
-		return -EBUSY;
-	}
-	outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
-	return 0;
-}
-
-static void logibm_close(struct input_dev *dev)
-{
-	outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
-	free_irq(logibm_irq, NULL);
-}
-
-static struct input_dev logibm_dev = {
-	.evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
-	.keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
-	.relbit	= { BIT(REL_X) | BIT(REL_Y) },
-	.open	= logibm_open,
-	.close	= logibm_close,
-	.name	= "Logitech bus mouse",
-	.phys	= "isa023c/input0",
-	.id	= {
-		.bustype = BUS_ISA,
-		.vendor  = 0x0003,
-		.product = 0x0001,
-		.version = 0x0100,
-	},
-};
+static struct input_dev *logibm_dev;
 
 static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -127,18 +95,34 @@
 	dy |= (buttons & 0xf) << 4;
 	buttons = ~buttons >> 5;
 
-	input_regs(&logibm_dev, regs);
-	input_report_rel(&logibm_dev, REL_X, dx);
-	input_report_rel(&logibm_dev, REL_Y, dy);
-	input_report_key(&logibm_dev, BTN_RIGHT,  buttons & 1);
-	input_report_key(&logibm_dev, BTN_MIDDLE, buttons & 2);
-	input_report_key(&logibm_dev, BTN_LEFT,   buttons & 4);
-	input_sync(&logibm_dev);
+	input_regs(logibm_dev, regs);
+	input_report_rel(logibm_dev, REL_X, dx);
+	input_report_rel(logibm_dev, REL_Y, dy);
+	input_report_key(logibm_dev, BTN_RIGHT,  buttons & 1);
+	input_report_key(logibm_dev, BTN_MIDDLE, buttons & 2);
+	input_report_key(logibm_dev, BTN_LEFT,   buttons & 4);
+	input_sync(logibm_dev);
 
 	outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
 	return IRQ_HANDLED;
 }
 
+static int logibm_open(struct input_dev *dev)
+{
+	if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
+		printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
+		return -EBUSY;
+	}
+	outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
+	return 0;
+}
+
+static void logibm_close(struct input_dev *dev)
+{
+	outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
+	free_irq(logibm_irq, NULL);
+}
+
 static int __init logibm_init(void)
 {
 	if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
@@ -159,16 +143,34 @@
 	outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
 	outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
 
-	input_register_device(&logibm_dev);
+	if (!(logibm_dev = input_allocate_device())) {
+		printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
+		release_region(LOGIBM_BASE, LOGIBM_EXTENT);
+		return -ENOMEM;
+	}
 
-	printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
+	logibm_dev->name = "Logitech bus mouse";
+	logibm_dev->phys = "isa023c/input0";
+	logibm_dev->id.bustype = BUS_ISA;
+	logibm_dev->id.vendor  = 0x0003;
+	logibm_dev->id.product = 0x0001;
+	logibm_dev->id.version = 0x0100;
+
+	logibm_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	logibm_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	logibm_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+	logibm_dev->open  = logibm_open;
+	logibm_dev->close = logibm_close;
+
+	input_register_device(logibm_dev);
 
 	return 0;
 }
 
 static void __exit logibm_exit(void)
 {
-	input_unregister_device(&logibm_dev);
+	input_unregister_device(logibm_dev);
 	release_region(LOGIBM_BASE, LOGIBM_EXTENT);
 }
 
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 7df9652..0f69ff4 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -40,7 +40,7 @@
 
 static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
-	struct input_dev *dev = &psmouse->dev;
+	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
 
 	if (psmouse->pktcnt < 3)
@@ -257,25 +257,27 @@
 static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info,
 				       int using_ps2pp)
 {
+	struct input_dev *input_dev = psmouse->dev;
+
 	if (model_info->features & PS2PP_SIDE_BTN)
-		set_bit(BTN_SIDE, psmouse->dev.keybit);
+		set_bit(BTN_SIDE, input_dev->keybit);
 
 	if (model_info->features & PS2PP_EXTRA_BTN)
-		set_bit(BTN_EXTRA, psmouse->dev.keybit);
+		set_bit(BTN_EXTRA, input_dev->keybit);
 
 	if (model_info->features & PS2PP_TASK_BTN)
-		set_bit(BTN_TASK, psmouse->dev.keybit);
+		set_bit(BTN_TASK, input_dev->keybit);
 
 	if (model_info->features & PS2PP_NAV_BTN) {
-		set_bit(BTN_FORWARD, psmouse->dev.keybit);
-		set_bit(BTN_BACK, psmouse->dev.keybit);
+		set_bit(BTN_FORWARD, input_dev->keybit);
+		set_bit(BTN_BACK, input_dev->keybit);
 	}
 
 	if (model_info->features & PS2PP_WHEEL)
-		set_bit(REL_WHEEL, psmouse->dev.relbit);
+		set_bit(REL_WHEEL, input_dev->relbit);
 
 	if (model_info->features & PS2PP_HWHEEL)
-		set_bit(REL_HWHEEL, psmouse->dev.relbit);
+		set_bit(REL_HWHEEL, input_dev->relbit);
 
 	switch (model_info->kind) {
 		case PS2PP_KIND_WHEEL:
@@ -387,7 +389,7 @@
 		}
 
 		if (buttons < 3)
-			clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
+			clear_bit(BTN_MIDDLE, psmouse->dev->keybit);
 
 		if (model_info)
 			ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
index e90c60c..b5b34fe 100644
--- a/drivers/input/mouse/maplemouse.c
+++ b/drivers/input/mouse/maplemouse.c
@@ -41,13 +41,12 @@
 	unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
 	struct input_dev *input_dev;
 
-	if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL)))
-		return -1;
+	dev->private_data = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
 	dev->private_data = input_dev;
 
-	memset(input_dev, 0, sizeof(struct dc_mouse));
-	init_input_dev(input_dev);
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
 	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
@@ -59,8 +58,6 @@
 
 	maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
 
-	printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name);
-
 	return 0;
 }
 
@@ -70,7 +67,6 @@
 	struct input_dev *input_dev = dev->private_data;
 
 	input_unregister_device(input_dev);
-	kfree(input_dev);
 }
 
 
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 93393d5..d284ea7 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -53,13 +53,10 @@
 static int pc110pad_irq = 10;
 static int pc110pad_io = 0x15e0;
 
-static struct input_dev pc110pad_dev;
+static struct input_dev *pc110pad_dev;
 static int pc110pad_data[3];
 static int pc110pad_count;
 
-static char *pc110pad_name = "IBM PC110 TouchPad";
-static char *pc110pad_phys = "isa15e0/input0";
-
 static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
 {
 	int value     = inb_p(pc110pad_io);
@@ -74,14 +71,14 @@
 	if (pc110pad_count < 3)
 		return IRQ_HANDLED;
 
-	input_regs(&pc110pad_dev, regs);
-	input_report_key(&pc110pad_dev, BTN_TOUCH,
+	input_regs(pc110pad_dev, regs);
+	input_report_key(pc110pad_dev, BTN_TOUCH,
 		pc110pad_data[0] & 0x01);
-	input_report_abs(&pc110pad_dev, ABS_X,
+	input_report_abs(pc110pad_dev, ABS_X,
 		pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
-	input_report_abs(&pc110pad_dev, ABS_Y,
+	input_report_abs(pc110pad_dev, ABS_Y,
 		pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
-	input_sync(&pc110pad_dev);
+	input_sync(pc110pad_dev);
 
 	pc110pad_count = 0;
 	return IRQ_HANDLED;
@@ -94,9 +91,9 @@
 
 static int pc110pad_open(struct input_dev *dev)
 {
-	pc110pad_interrupt(0,NULL,NULL);
-	pc110pad_interrupt(0,NULL,NULL);
-	pc110pad_interrupt(0,NULL,NULL);
+	pc110pad_interrupt(0, NULL, NULL);
+	pc110pad_interrupt(0, NULL, NULL);
+	pc110pad_interrupt(0, NULL, NULL);
 	outb(PC110PAD_ON, pc110pad_io + 2);
 	pc110pad_count = 0;
 
@@ -127,45 +124,46 @@
 
 	outb(PC110PAD_OFF, pc110pad_io + 2);
 
-	if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL))
-	{
+	if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
 		release_region(pc110pad_io, 4);
 		printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
 		return -EBUSY;
 	}
 
-        pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-        pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-        pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	if (!(pc110pad_dev = input_allocate_device())) {
+		free_irq(pc110pad_irq, NULL);
+		release_region(pc110pad_io, 4);
+		printk(KERN_ERR "pc110pad: Not enough memory.\n");
+		return -ENOMEM;
+	}
 
-	pc110pad_dev.absmax[ABS_X] = 0x1ff;
-	pc110pad_dev.absmax[ABS_Y] = 0x0ff;
+	pc110pad_dev->name = "IBM PC110 TouchPad";
+	pc110pad_dev->phys = "isa15e0/input0";
+	pc110pad_dev->id.bustype = BUS_ISA;
+	pc110pad_dev->id.vendor = 0x0003;
+	pc110pad_dev->id.product = 0x0001;
+	pc110pad_dev->id.version = 0x0100;
 
-	pc110pad_dev.open = pc110pad_open;
-        pc110pad_dev.close = pc110pad_close;
+	pc110pad_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	pc110pad_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+	pc110pad_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 
-	pc110pad_dev.name = pc110pad_name;
-	pc110pad_dev.phys = pc110pad_phys;
-	pc110pad_dev.id.bustype = BUS_ISA;
-	pc110pad_dev.id.vendor = 0x0003;
-	pc110pad_dev.id.product = 0x0001;
-	pc110pad_dev.id.version = 0x0100;
+	pc110pad_dev->absmax[ABS_X] = 0x1ff;
+	pc110pad_dev->absmax[ABS_Y] = 0x0ff;
 
-	input_register_device(&pc110pad_dev);
+	pc110pad_dev->open = pc110pad_open;
+	pc110pad_dev->close = pc110pad_close;
 
-	printk(KERN_INFO "input: %s at %#x irq %d\n",
-		pc110pad_name, pc110pad_io, pc110pad_irq);
+	input_register_device(pc110pad_dev);
 
 	return 0;
 }
 
 static void __exit pc110pad_exit(void)
 {
-	input_unregister_device(&pc110pad_dev);
-
 	outb(PC110PAD_OFF, pc110pad_io + 2);
-
 	free_irq(pc110pad_irq, NULL);
+	input_unregister_device(pc110pad_dev);
 	release_region(pc110pad_io, 4);
 }
 
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index af24313..6ee9999 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -114,7 +114,7 @@
 
 static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
-	struct input_dev *dev = &psmouse->dev;
+	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
 
 	if (psmouse->pktcnt < psmouse->pktsize)
@@ -333,12 +333,11 @@
 		return -1;
 
 	if (set_properties) {
-		set_bit(BTN_EXTRA, psmouse->dev.keybit);
-		set_bit(BTN_SIDE, psmouse->dev.keybit);
-		set_bit(REL_WHEEL, psmouse->dev.relbit);
+		set_bit(BTN_EXTRA, psmouse->dev->keybit);
+		set_bit(BTN_SIDE, psmouse->dev->keybit);
+		set_bit(REL_WHEEL, psmouse->dev->relbit);
 
 		psmouse->vendor = "Genius";
-		psmouse->name = "Wheel Mouse";
 		psmouse->pktsize = 4;
 	}
 
@@ -365,8 +364,8 @@
 		return -1;
 
 	if (set_properties) {
-		set_bit(BTN_MIDDLE, psmouse->dev.keybit);
-		set_bit(REL_WHEEL, psmouse->dev.relbit);
+		set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+		set_bit(REL_WHEEL, psmouse->dev->relbit);
 
 		if (!psmouse->vendor) psmouse->vendor = "Generic";
 		if (!psmouse->name) psmouse->name = "Wheel Mouse";
@@ -398,10 +397,10 @@
 		return -1;
 
 	if (set_properties) {
-		set_bit(BTN_MIDDLE, psmouse->dev.keybit);
-		set_bit(REL_WHEEL, psmouse->dev.relbit);
-		set_bit(BTN_SIDE, psmouse->dev.keybit);
-		set_bit(BTN_EXTRA, psmouse->dev.keybit);
+		set_bit(BTN_MIDDLE, psmouse->dev->keybit);
+		set_bit(REL_WHEEL, psmouse->dev->relbit);
+		set_bit(BTN_SIDE, psmouse->dev->keybit);
+		set_bit(BTN_EXTRA, psmouse->dev->keybit);
 
 		if (!psmouse->vendor) psmouse->vendor = "Generic";
 		if (!psmouse->name) psmouse->name = "Explorer Mouse";
@@ -433,7 +432,7 @@
 		return -1;
 
 	if (set_properties) {
-		set_bit(BTN_EXTRA, psmouse->dev.keybit);
+		set_bit(BTN_EXTRA, psmouse->dev->keybit);
 
 		psmouse->vendor = "Kensington";
 		psmouse->name = "ThinkingMouse";
@@ -839,9 +838,9 @@
 
 	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 
-	input_unregister_device(&psmouse->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(psmouse->dev);
 	kfree(psmouse);
 
 	if (parent)
@@ -852,16 +851,14 @@
 
 static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
 {
-	memset(&psmouse->dev, 0, sizeof(struct input_dev));
+	struct input_dev *input_dev = psmouse->dev;
 
-	init_input_dev(&psmouse->dev);
+	input_dev->private = psmouse;
+	input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
 
-	psmouse->dev.private = psmouse;
-	psmouse->dev.dev = &psmouse->ps2dev.serio->dev;
-
-	psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
 
 	psmouse->set_rate = psmouse_set_rate;
 	psmouse->set_resolution = psmouse_set_resolution;
@@ -883,12 +880,12 @@
 	sprintf(psmouse->devname, "%s %s %s",
 		psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
 
-	psmouse->dev.name = psmouse->devname;
-	psmouse->dev.phys = psmouse->phys;
-	psmouse->dev.id.bustype = BUS_I8042;
-	psmouse->dev.id.vendor = 0x0002;
-	psmouse->dev.id.product = psmouse->type;
-	psmouse->dev.id.version = psmouse->model;
+	input_dev->name = psmouse->devname;
+	input_dev->phys = psmouse->phys;
+	input_dev->id.bustype = BUS_I8042;
+	input_dev->id.vendor = 0x0002;
+	input_dev->id.product = psmouse->type;
+	input_dev->id.version = psmouse->model;
 
 	return 0;
 }
@@ -900,7 +897,8 @@
 static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct psmouse *psmouse, *parent = NULL;
-	int retval;
+	struct input_dev *input_dev;
+	int retval = -ENOMEM;
 
 	down(&psmouse_sem);
 
@@ -913,12 +911,13 @@
 		psmouse_deactivate(parent);
 	}
 
-	if (!(psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL))) {
-		retval = -ENOMEM;
+	psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!psmouse || !input_dev)
 		goto out;
-	}
 
 	ps2_init(&psmouse->ps2dev, serio);
+	psmouse->dev = input_dev;
 	sprintf(psmouse->phys, "%s/input0", serio->phys);
 
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -926,16 +925,11 @@
 	serio_set_drvdata(serio, psmouse);
 
 	retval = serio_open(serio, drv);
-	if (retval) {
-		serio_set_drvdata(serio, NULL);
-		kfree(psmouse);
+	if (retval)
 		goto out;
-	}
 
 	if (psmouse_probe(psmouse) < 0) {
 		serio_close(serio);
-		serio_set_drvdata(serio, NULL);
-		kfree(psmouse);
 		retval = -ENODEV;
 		goto out;
 	}
@@ -947,13 +941,11 @@
 
 	psmouse_switch_protocol(psmouse, NULL);
 
-	input_register_device(&psmouse->dev);
-	printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
-
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
-
 	psmouse_initialize(psmouse);
 
+	input_register_device(psmouse->dev);
+
 	if (parent && parent->pt_activate)
 		parent->pt_activate(parent);
 
@@ -964,6 +956,12 @@
 	retval = 0;
 
 out:
+	if (retval) {
+		serio_set_drvdata(serio, NULL);
+		input_free_device(input_dev);
+		kfree(psmouse);
+	}
+
 	/* If this is a pass-through port the parent needs to be re-activated */
 	if (parent)
 		psmouse_activate(parent);
@@ -1161,6 +1159,7 @@
 {
 	struct serio *serio = psmouse->ps2dev.serio;
 	struct psmouse *parent = NULL;
+	struct input_dev *new_dev;
 	struct psmouse_protocol *proto;
 	int retry = 0;
 
@@ -1170,9 +1169,13 @@
 	if (psmouse->type == proto->type)
 		return count;
 
+	if (!(new_dev = input_allocate_device()))
+		return -ENOMEM;
+
 	while (serio->child) {
 		if (++retry > 3) {
 			printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
+			input_free_device(new_dev);
 			return -EIO;
 		}
 
@@ -1182,11 +1185,15 @@
 		serio_pin_driver_uninterruptible(serio);
 		down(&psmouse_sem);
 
-		if (serio->drv != &psmouse_drv)
+		if (serio->drv != &psmouse_drv) {
+			input_free_device(new_dev);
 			return -ENODEV;
+		}
 
-		if (psmouse->type == proto->type)
+		if (psmouse->type == proto->type) {
+			input_free_device(new_dev);
 			return count; /* switched by other thread */
+		}
 	}
 
 	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
@@ -1199,8 +1206,9 @@
 		psmouse->disconnect(psmouse);
 
 	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
-	input_unregister_device(&psmouse->dev);
+	input_unregister_device(psmouse->dev);
 
+	psmouse->dev = new_dev;
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
 	if (psmouse_switch_protocol(psmouse, proto) < 0) {
@@ -1212,8 +1220,7 @@
 	psmouse_initialize(psmouse);
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
-	input_register_device(&psmouse->dev);
-	printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
+	input_register_device(psmouse->dev);
 
 	if (parent && parent->pt_activate)
 		parent->pt_activate(parent);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 45d2bd7..7c4192b 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -36,7 +36,7 @@
 
 struct psmouse {
 	void *private;
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct ps2dev ps2dev;
 	char *vendor;
 	char *name;
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 8fe1212..09b6ffd 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -34,20 +34,7 @@
 MODULE_LICENSE("GPL");
 
 static short rpcmouse_lastx, rpcmouse_lasty;
-
-static struct input_dev rpcmouse_dev = {
-	.evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
-	.keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
-	.relbit	= { BIT(REL_X) | BIT(REL_Y) },
-	.name	= "Acorn RiscPC Mouse",
-	.phys	= "rpcmouse/input0",
-	.id	= {
-		.bustype = BUS_HOST,
-		.vendor  = 0x0005,
-		.product = 0x0001,
-		.version = 0x0100,
-	},
-};
+static struct input_dev *rpcmouse_dev;
 
 static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -78,29 +65,41 @@
 	return IRQ_HANDLED;
 }
 
+
 static int __init rpcmouse_init(void)
 {
-	init_input_dev(&rpcmouse_dev);
+	if (!(rpcmouse_dev = input_allocate_device()))
+		return -ENOMEM;
+
+	rpcmouse_dev->name = "Acorn RiscPC Mouse";
+	rpcmouse_dev->phys = "rpcmouse/input0";
+	rpcmouse_dev->id.bustype = BUS_HOST;
+	rpcmouse_dev->id.vendor  = 0x0005;
+	rpcmouse_dev->id.product = 0x0001;
+	rpcmouse_dev->id.version = 0x0100;
+
+	rpcmouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	rpcmouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	rpcmouse_dev->relbit[0]	= BIT(REL_X) | BIT(REL_Y);
 
 	rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX);
 	rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY);
 
-	if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", &rpcmouse_dev)) {
+	if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", rpcmouse_dev)) {
 		printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
-		return -1;
+		input_free_device(rpcmouse_dev);
+		return -EBUSY;
 	}
 
-	input_register_device(&rpcmouse_dev);
-
-	printk(KERN_INFO "input: Acorn RiscPC mouse\n");
+	input_register_device(rpcmouse_dev);
 
 	return 0;
 }
 
 static void __exit rpcmouse_exit(void)
 {
-	input_unregister_device(&rpcmouse_dev);
-	free_irq(IRQ_VSYNCPULSE, &rpcmouse_dev);
+	free_irq(IRQ_VSYNCPULSE, rpcmouse_dev);
+	input_unregister_device(rpcmouse_dev);
 }
 
 module_init(rpcmouse_init);
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index d12b93a..4bf5843 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -48,7 +48,7 @@
 					"Logitech MZ++ Mouse"};
 
 struct sermouse {
-	struct input_dev dev;
+	struct input_dev *dev;
 	signed char buf[8];
 	unsigned char count;
 	unsigned char type;
@@ -64,7 +64,7 @@
 
 static void sermouse_process_msc(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &sermouse->dev;
+	struct input_dev *dev = sermouse->dev;
 	signed char *buf = sermouse->buf;
 
 	input_regs(dev, regs);
@@ -107,7 +107,7 @@
 
 static void sermouse_process_ms(struct sermouse *sermouse, signed char data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &sermouse->dev;
+	struct input_dev *dev = sermouse->dev;
 	signed char *buf = sermouse->buf;
 
 	if (data & 0x40) sermouse->count = 0;
@@ -230,9 +230,9 @@
 {
 	struct sermouse *sermouse = serio_get_drvdata(serio);
 
-	input_unregister_device(&sermouse->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_unregister_device(sermouse->dev);
 	kfree(sermouse);
 }
 
@@ -244,56 +244,52 @@
 static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sermouse *sermouse;
-	unsigned char c;
-	int err;
+	struct input_dev *input_dev;
+	unsigned char c = serio->id.extra;
+	int err = -ENOMEM;
 
-	if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
-		return -ENODEV;
+	sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!sermouse || !input_dev)
+		goto fail;
 
-	if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset(sermouse, 0, sizeof(struct sermouse));
-
-	init_input_dev(&sermouse->dev);
-	sermouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	sermouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
-	sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	sermouse->dev.private = sermouse;
-
-	sermouse->type = serio->id.proto;
-	c = serio->id.extra;
-
-	if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
-	if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
-	if (c & 0x04) set_bit(BTN_EXTRA, sermouse->dev.keybit);
-	if (c & 0x10) set_bit(REL_WHEEL, sermouse->dev.relbit);
-	if (c & 0x20) set_bit(REL_HWHEEL, sermouse->dev.relbit);
-
+	sermouse->dev = input_dev;
 	sprintf(sermouse->phys, "%s/input0", serio->phys);
+	sermouse->type = serio->id.proto;
 
-	sermouse->dev.name = sermouse_protocols[sermouse->type];
-	sermouse->dev.phys = sermouse->phys;
-	sermouse->dev.id.bustype = BUS_RS232;
-	sermouse->dev.id.vendor = sermouse->type;
-	sermouse->dev.id.product = c;
-	sermouse->dev.id.version = 0x0100;
-	sermouse->dev.dev = &serio->dev;
+	input_dev->name = sermouse_protocols[sermouse->type];
+	input_dev->phys = sermouse->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor  = sermouse->type;
+	input_dev->id.product = c;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	input_dev->private = sermouse;
+
+	if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
+	if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
+	if (c & 0x04) set_bit(BTN_EXTRA, input_dev->keybit);
+	if (c & 0x10) set_bit(REL_WHEEL, input_dev->relbit);
+	if (c & 0x20) set_bit(REL_HWHEEL, input_dev->relbit);
 
 	serio_set_drvdata(serio, sermouse);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(sermouse);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&sermouse->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
+	input_register_device(sermouse->dev);
 
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(sermouse);
+	return err;
 }
 
 static struct serio_device_id sermouse_serio_ids[] = {
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 0293094..97cdfd6 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -342,7 +342,7 @@
  */
 static void synaptics_process_packet(struct psmouse *psmouse)
 {
-	struct input_dev *dev = &psmouse->dev;
+	struct input_dev *dev = psmouse->dev;
 	struct synaptics_data *priv = psmouse->private;
 	struct synaptics_hw_state hw;
 	int num_fingers;
@@ -473,7 +473,7 @@
 
 static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
-	struct input_dev *dev = &psmouse->dev;
+	struct input_dev *dev = psmouse->dev;
 	struct synaptics_data *priv = psmouse->private;
 
 	input_regs(dev, regs);
@@ -645,7 +645,7 @@
 		SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
 		priv->model_id, priv->capabilities, priv->ext_cap);
 
-	set_input_params(&psmouse->dev, priv);
+	set_input_params(psmouse->dev, priv);
 
 	psmouse->protocol_handler = synaptics_process_byte;
 	psmouse->set_rate = synaptics_set_rate;
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index f024be9..36e9442 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -112,7 +112,7 @@
 
 
 struct vsxxxaa {
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 #define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
 	unsigned char buf[BUFLEN];
@@ -211,7 +211,7 @@
 static void
 vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
 {
-	struct input_dev *dev = &mouse->dev;
+	struct input_dev *dev = mouse->dev;
 	unsigned char *buf = mouse->buf;
 	int left, middle, right;
 	int dx, dy;
@@ -269,7 +269,7 @@
 static void
 vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
 {
-	struct input_dev *dev = &mouse->dev;
+	struct input_dev *dev = mouse->dev;
 	unsigned char *buf = mouse->buf;
 	int left, middle, right, touch;
 	int x, y;
@@ -323,7 +323,7 @@
 static void
 vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
 {
-	struct input_dev *dev = &mouse->dev;
+	struct input_dev *dev = mouse->dev;
 	unsigned char *buf = mouse->buf;
 	int left, middle, right;
 	unsigned char error;
@@ -483,9 +483,9 @@
 {
 	struct vsxxxaa *mouse = serio_get_drvdata (serio);
 
-	input_unregister_device (&mouse->dev);
 	serio_close (serio);
 	serio_set_drvdata (serio, NULL);
+	input_unregister_device (mouse->dev);
 	kfree (mouse);
 }
 
@@ -493,61 +493,57 @@
 vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct vsxxxaa *mouse;
-	int err;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 
-	if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
-		return -ENOMEM;
+	mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL);
+	input_dev = input_allocate_device ();
+	if (!mouse || !input_dev)
+		goto fail;
 
-	memset (mouse, 0, sizeof (struct vsxxxaa));
-
-	init_input_dev (&mouse->dev);
-	set_bit (EV_KEY, mouse->dev.evbit);		/* We have buttons */
-	set_bit (EV_REL, mouse->dev.evbit);
-	set_bit (EV_ABS, mouse->dev.evbit);
-	set_bit (BTN_LEFT, mouse->dev.keybit);		/* We have 3 buttons */
-	set_bit (BTN_MIDDLE, mouse->dev.keybit);
-	set_bit (BTN_RIGHT, mouse->dev.keybit);
-	set_bit (BTN_TOUCH, mouse->dev.keybit);		/* ...and Tablet */
-	set_bit (REL_X, mouse->dev.relbit);
-	set_bit (REL_Y, mouse->dev.relbit);
-	set_bit (ABS_X, mouse->dev.absbit);
-	set_bit (ABS_Y, mouse->dev.absbit);
-
-	mouse->dev.absmin[ABS_X] = 0;
-	mouse->dev.absmax[ABS_X] = 1023;
-	mouse->dev.absmin[ABS_Y] = 0;
-	mouse->dev.absmax[ABS_Y] = 1023;
-
-	mouse->dev.private = mouse;
-
+	mouse->dev = input_dev;
+	mouse->serio = serio;
 	sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
 	sprintf (mouse->phys, "%s/input0", serio->phys);
-	mouse->dev.name = mouse->name;
-	mouse->dev.phys = mouse->phys;
-	mouse->dev.id.bustype = BUS_RS232;
-	mouse->dev.dev = &serio->dev;
-	mouse->serio = serio;
+
+	input_dev->name = mouse->name;
+	input_dev->phys = mouse->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = mouse;
+
+	set_bit (EV_KEY, input_dev->evbit);		/* We have buttons */
+	set_bit (EV_REL, input_dev->evbit);
+	set_bit (EV_ABS, input_dev->evbit);
+	set_bit (BTN_LEFT, input_dev->keybit);		/* We have 3 buttons */
+	set_bit (BTN_MIDDLE, input_dev->keybit);
+	set_bit (BTN_RIGHT, input_dev->keybit);
+	set_bit (BTN_TOUCH, input_dev->keybit);		/* ...and Tablet */
+	set_bit (REL_X, input_dev->relbit);
+	set_bit (REL_Y, input_dev->relbit);
+	input_set_abs_params (input_dev, ABS_X, 0, 1023, 0, 0);
+	input_set_abs_params (input_dev, ABS_Y, 0, 1023, 0, 0);
 
 	serio_set_drvdata (serio, mouse);
 
 	err = serio_open (serio, drv);
-	if (err) {
-		serio_set_drvdata (serio, NULL);
-		kfree (mouse);
-		return err;
-	}
+	if (err)
+		goto fail;
 
 	/*
 	 * Request selftest. Standard packet format and differential
 	 * mode will be requested after the device ID'ed successfully.
 	 */
-	mouse->serio->write (mouse->serio, 'T'); /* Test */
+	serio->write (serio, 'T'); /* Test */
 
-	input_register_device (&mouse->dev);
-
-	printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+	input_register_device (input_dev);
 
 	return 0;
+
+ fail:	serio_set_drvdata (serio, NULL);
+	input_free_device (input_dev);
+	kfree (mouse);
+	return err;
 }
 
 static struct serio_device_id vsxxaa_serio_ids[] = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index c6194a9..2d0af44 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#define MOUSEDEV_MINOR_BASE 	32
+#define MOUSEDEV_MINOR_BASE	32
 #define MOUSEDEV_MINORS		32
 #define MOUSEDEV_MIX		31
 
@@ -24,7 +24,6 @@
 #include <linux/random.h>
 #include <linux/major.h>
 #include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 #include <linux/miscdevice.h>
 #endif
@@ -621,6 +620,7 @@
 static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct mousedev *mousedev;
+	struct class_device *cdev;
 	int minor = 0;
 
 	for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
@@ -649,11 +649,13 @@
 
 	mousedev_table[minor] = mousedev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
-	class_device_create(input_class,
+	cdev = class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			dev->dev, "mouse%d", minor);
+			dev->cdev.dev, mousedev->name);
+
+	/* temporary symlink to keep userspace happy */
+	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+			  mousedev->name);
 
 	return &mousedev->handle;
 }
@@ -663,9 +665,9 @@
 	struct mousedev *mousedev = handle->private;
 	struct mousedev_list *list;
 
-	class_device_destroy(input_class,
+	sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
-	devfs_remove("input/mouse%d", mousedev->minor);
 	mousedev->exist = 0;
 
 	if (mousedev->open) {
@@ -738,9 +740,7 @@
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
-	class_device_create(input_class,
+	class_device_create(&input_class, NULL,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -759,8 +759,7 @@
 	if (psaux_registered)
 		misc_deregister(&psaux_mouse);
 #endif
-	devfs_remove("input/mice");
-	class_device_destroy(input_class,
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
 }
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 897e4c1..a7b0de0 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -211,9 +211,6 @@
 	writeb(0xff, addr+GSC_RESET);
 	gscps2_flush(ps2port);
 	spin_unlock_irqrestore(&ps2port->lock, flags);
-
-	/* enable it */
-	gscps2_enable(ps2port, ENABLE);
 }
 
 static LIST_HEAD(ps2port_list);
@@ -307,6 +304,9 @@
 
 	gscps2_reset(ps2port);
 
+	/* enable it */
+	gscps2_enable(ps2port, ENABLE);
+
 	gscps2_interrupt(0, NULL, NULL);
 
 	return 0;
@@ -331,7 +331,7 @@
 {
 	struct gscps2port *ps2port;
 	struct serio *serio;
-	unsigned long hpa = dev->hpa;
+	unsigned long hpa = dev->hpa.start;
 	int ret;
 
 	if (!dev->irq)
@@ -370,8 +370,6 @@
 	serio->port_data	= ps2port;
 	serio->dev.parent	= &dev->dev;
 
-	list_add_tail(&ps2port->node, &ps2port_list);
-
 	ret = -EBUSY;
 	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
 		goto fail_miserably;
@@ -396,15 +394,16 @@
 
 	serio_register_port(ps2port->port);
 
+	list_add_tail(&ps2port->node, &ps2port_list);
+
 	return 0;
 
 fail:
 	free_irq(dev->irq, ps2port);
 
 fail_miserably:
-	list_del(&ps2port->node);
 	iounmap(ps2port->addr);
-	release_mem_region(dev->hpa, GSC_STATUS + 4);
+	release_mem_region(dev->hpa.start, GSC_STATUS + 4);
 
 fail_nomem:
 	kfree(ps2port);
@@ -444,7 +443,7 @@
 };
 
 static struct parisc_driver parisc_ps2_driver = {
-	.name		= "GSC PS2",
+	.name		= "gsc_ps2",
 	.id_table	= gscps2_device_tbl,
 	.probe		= gscps2_probe,
 	.remove		= gscps2_remove,
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index c243cb6f..5704204 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -801,7 +801,8 @@
 	struct hil_mlc_serio_map *map;
 	struct hil_mlc *mlc;
 
-	if (serio->private != NULL) return -EBUSY;
+	if (serio_get_drvdata(serio) != NULL)
+		return -EBUSY;
 
 	map = serio->port_data;
 	if (map == NULL) {
@@ -832,11 +833,18 @@
 		return;
 	}
 
-	serio->private = NULL;
+	serio_set_drvdata(serio, NULL);
 	serio->drv = NULL;
 	/* TODO wake up interruptable */
 }
 
+static struct serio_device_id hil_mlc_serio_id = {
+	.type = SERIO_HIL_MLC,
+	.proto = SERIO_HIL,
+	.extra = SERIO_ANY,
+	.id = SERIO_ANY,
+};
+
 int hil_mlc_register(hil_mlc *mlc) {
 	int i;
         unsigned long flags;
@@ -867,7 +875,7 @@
 		mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
 		mlc->serio[i] = mlc_serio;
 		memset(mlc_serio, 0, sizeof(*mlc_serio));
-		mlc_serio->type			= SERIO_HIL | SERIO_HIL_MLC;
+		mlc_serio->id			= hil_mlc_serio_id;
 		mlc_serio->write		= hil_mlc_serio_write;
 		mlc_serio->open			= hil_mlc_serio_open;
 		mlc_serio->close		= hil_mlc_serio_close;
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 7629452..a10348b 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -764,7 +764,7 @@
 static int __init hp_sdc_init_hppa(struct parisc_device *d);
 
 static struct parisc_driver hp_sdc_driver = {
-	.name =		"HP SDC",
+	.name =		"hp_sdc",
 	.id_table =	hp_sdc_tbl,
 	.probe =	hp_sdc_init_hppa,
 };
@@ -875,9 +875,9 @@
 	hp_sdc.dev		= d;
 	hp_sdc.irq		= d->irq;
 	hp_sdc.nmi		= d->aux_irq;
-	hp_sdc.base_io		= d->hpa;
-	hp_sdc.data_io		= d->hpa + 0x800;
-	hp_sdc.status_io	= d->hpa + 0x801;
+	hp_sdc.base_io		= d->hpa.start;
+	hp_sdc.data_io		= d->hpa.start + 0x800;
+	hp_sdc.status_io	= d->hpa.start + 0x801;
 
 	return hp_sdc_init();
 }
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index e3c44ff..1c9426f 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <asm/semaphore.h>
 
 #define PREFIX "HP SDC MLC: "
 
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 40d451c..4bc40f1 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -911,12 +911,10 @@
  * Here we try to restore the original BIOS settings
  */
 
-static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
+static int i8042_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_DISABLE) {
-		del_timer_sync(&i8042_timer);
-		i8042_controller_reset();
-	}
+	del_timer_sync(&i8042_timer);
+	i8042_controller_reset();
 
 	return 0;
 }
@@ -926,13 +924,10 @@
  * Here we try to reset everything back to a state in which suspended
  */
 
-static int i8042_resume(struct device *dev, u32 level)
+static int i8042_resume(struct device *dev)
 {
 	int i;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	if (i8042_ctl_test())
 		return -1;
 
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 4c7fbe5..0ba3e65 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -41,8 +41,7 @@
 };
 
 struct corgi_ts {
-	char phys[32];
-	struct input_dev input;
+	struct input_dev *input;
 	struct timer_list timer;
 	struct ts_event tc;
 	int pendown;
@@ -182,14 +181,12 @@
 	if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
 		return;
 
-	if (regs)
-		input_regs(&corgi_ts->input, regs);
-
-	input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x);
-	input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y);
-	input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
-	input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
-	input_sync(&corgi_ts->input);
+	input_regs(corgi_ts->input, regs);
+	input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x);
+	input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y);
+	input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
+	input_report_key(corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
+	input_sync(corgi_ts->input);
 }
 
 static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
@@ -234,34 +231,32 @@
 }
 
 #ifdef CONFIG_PM
-static int corgits_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int corgits_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+	struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
 
-		if (corgi_ts->pendown) {
-			del_timer_sync(&corgi_ts->timer);
-			corgi_ts->tc.pressure = 0;
-			new_data(corgi_ts, NULL);
-			corgi_ts->pendown = 0;
-		}
-		corgi_ts->power_mode = PWR_MODE_SUSPEND;
-
-		corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	if (corgi_ts->pendown) {
+		del_timer_sync(&corgi_ts->timer);
+		corgi_ts->tc.pressure = 0;
+		new_data(corgi_ts, NULL);
+		corgi_ts->pendown = 0;
 	}
+	corgi_ts->power_mode = PWR_MODE_SUSPEND;
+
+	corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+
 	return 0;
 }
 
-static int corgits_resume(struct device *dev, uint32_t level)
+static int corgits_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+	struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
 
-		corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
-		/* Enable Falling Edge */
-		set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
-		corgi_ts->power_mode = PWR_MODE_ACTIVE;
-	}
+	corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	/* Enable Falling Edge */
+	set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
+	corgi_ts->power_mode = PWR_MODE_ACTIVE;
+
 	return 0;
 }
 #else
@@ -273,39 +268,44 @@
 {
 	struct corgi_ts *corgi_ts;
 	struct platform_device *pdev = to_platform_device(dev);
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 
-	if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
-		return -ENOMEM;
+	corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!corgi_ts || !input_dev)
+		goto fail;
 
 	dev_set_drvdata(dev, corgi_ts);
 
-	memset(corgi_ts, 0, sizeof(struct corgi_ts));
-
 	corgi_ts->machinfo = dev->platform_data;
 	corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
 
 	if (corgi_ts->irq_gpio < 0) {
-		kfree(corgi_ts);
-		return -ENODEV;
+		err = -ENODEV;
+		goto fail;
 	}
 
-	init_input_dev(&corgi_ts->input);
-	corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
-	input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
-	input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
+	corgi_ts->input = input_dev;
 
-	strcpy(corgi_ts->phys, "corgits/input0");
+	init_timer(&corgi_ts->timer);
+	corgi_ts->timer.data = (unsigned long) corgi_ts;
+	corgi_ts->timer.function = corgi_ts_timer;
 
-	corgi_ts->input.private = corgi_ts;
-	corgi_ts->input.name = "Corgi Touchscreen";
-	corgi_ts->input.dev = dev;
-	corgi_ts->input.phys = corgi_ts->phys;
-	corgi_ts->input.id.bustype = BUS_HOST;
-	corgi_ts->input.id.vendor = 0x0001;
-	corgi_ts->input.id.product = 0x0002;
-	corgi_ts->input.id.version = 0x0100;
+	input_dev->name = "Corgi Touchscreen";
+	input_dev->phys = "corgits/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0002;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = dev;
+	input_dev->private = corgi_ts;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
 
 	pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
 
@@ -319,25 +319,24 @@
 	corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
 	mdelay(5);
 
-	init_timer(&corgi_ts->timer);
-	corgi_ts->timer.data = (unsigned long) corgi_ts;
-	corgi_ts->timer.function = corgi_ts_timer;
-
-	input_register_device(&corgi_ts->input);
-	corgi_ts->power_mode = PWR_MODE_ACTIVE;
-
 	if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
-		input_unregister_device(&corgi_ts->input);
-		kfree(corgi_ts);
-		return -EBUSY;
+		err = -EBUSY;
+		goto fail;
 	}
 
+	input_register_device(corgi_ts->input);
+
+	corgi_ts->power_mode = PWR_MODE_ACTIVE;
+
 	/* Enable Falling Edge */
 	set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
 
-	printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
-
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(corgi_ts);
+	return err;
+
 }
 
 static int corgits_remove(struct device *dev)
@@ -347,7 +346,7 @@
 	free_irq(corgi_ts->irq_gpio, NULL);
 	del_timer_sync(&corgi_ts->timer);
 	corgi_ts->machinfo->put_hsync();
-	input_unregister_device(&corgi_ts->input);
+	input_unregister_device(corgi_ts->input);
 	kfree(corgi_ts);
 	return 0;
 }
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 3cdc9ca..c86a2eb 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -36,14 +36,12 @@
 
 #define	ELO_MAX_LENGTH	10
 
-static char *elo_name = "Elo Serial TouchScreen";
-
 /*
  * Per-touchscreen data.
  */
 
 struct elo {
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	int id;
 	int idx;
@@ -54,7 +52,7 @@
 
 static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &elo->dev;
+	struct input_dev *dev = elo->dev;
 
 	elo->csum += elo->data[elo->idx] = data;
 
@@ -80,7 +78,7 @@
 				input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
 				input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
 				input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
-				input_report_key(dev, BTN_TOUCH, elo->data[2] & 3);
+				input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]);
 				input_sync(dev);
 			}
 			elo->idx = 0;
@@ -91,7 +89,7 @@
 
 static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &elo->dev;
+	struct input_dev *dev = elo->dev;
 
 	elo->data[elo->idx] = data;
 
@@ -129,7 +127,7 @@
 		case 5:
 			if ((data & 0xf0) == 0) {
 				input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
-				input_report_key(dev, BTN_TOUCH, elo->data[5]);
+				input_report_key(dev, BTN_TOUCH, !!elo->data[5]);
 			}
 			input_sync(dev);
 			elo->idx = 0;
@@ -139,7 +137,7 @@
 
 static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &elo->dev;
+	struct input_dev *dev = elo->dev;
 
 	elo->data[elo->idx] = data;
 
@@ -191,7 +189,7 @@
 {
 	struct elo* elo = serio_get_drvdata(serio);
 
-	input_unregister_device(&elo->dev);
+	input_unregister_device(elo->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
 	kfree(elo);
@@ -206,67 +204,68 @@
 static int elo_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct elo *elo;
+	struct input_dev *input_dev;
 	int err;
 
-	if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL)))
-		return -ENOMEM;
+	elo = kzalloc(sizeof(struct elo), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!elo || !input_dev) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
-	memset(elo, 0, sizeof(struct elo));
-
-	init_input_dev(&elo->dev);
-	elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
+	elo->serio = serio;
 	elo->id = serio->id.id;
+	elo->dev = input_dev;
+	snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
+
+	input_dev->private = elo;
+	input_dev->name = "Elo Serial TouchScreen";
+	input_dev->phys = elo->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_ELO;
+	input_dev->id.product = elo->id;
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 
 	switch (elo->id) {
 
 		case 0: /* 10-byte protocol */
-			input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
-			input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
-			input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
+			input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
+			input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
+			input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
 			break;
 
 		case 1: /* 6-byte protocol */
-			input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
+			input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
 
 		case 2: /* 4-byte protocol */
-			input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
-			input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+			input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
+			input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
 			break;
 
 		case 3: /* 3-byte protocol */
-			input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0);
-			input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0);
+			input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
+			input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
 			break;
 	}
 
-	elo->serio = serio;
-
-	sprintf(elo->phys, "%s/input0", serio->phys);
-
-	elo->dev.private = elo;
-	elo->dev.name = elo_name;
-	elo->dev.phys = elo->phys;
-	elo->dev.id.bustype = BUS_RS232;
-	elo->dev.id.vendor = SERIO_ELO;
-	elo->dev.id.product = elo->id;
-	elo->dev.id.version = 0x0100;
-
 	serio_set_drvdata(serio, elo);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(elo);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&elo->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
-
+	input_register_device(elo->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(elo);
+	return err;
 }
 
 /*
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 53a27e4..466da19 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -48,14 +48,12 @@
 
 #define	GUNZE_MAX_LENGTH	10
 
-static char *gunze_name = "Gunze AHL-51S TouchScreen";
-
 /*
  * Per-touchscreen data.
  */
 
 struct gunze {
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	int idx;
 	unsigned char data[GUNZE_MAX_LENGTH];
@@ -64,7 +62,7 @@
 
 static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
 {
-	struct input_dev *dev = &gunze->dev;
+	struct input_dev *dev = gunze->dev;
 
 	if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
 		(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
@@ -100,11 +98,13 @@
 
 static void gunze_disconnect(struct serio *serio)
 {
-	struct gunze* gunze = serio_get_drvdata(serio);
+	struct gunze *gunze = serio_get_drvdata(serio);
 
-	input_unregister_device(&gunze->dev);
+	input_get_device(gunze->dev);
+	input_unregister_device(gunze->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_put_device(gunze->dev);
 	kfree(gunze);
 }
 
@@ -117,45 +117,45 @@
 static int gunze_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct gunze *gunze;
+	struct input_dev *input_dev;
 	int err;
 
-	if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset(gunze, 0, sizeof(struct gunze));
-
-	init_input_dev(&gunze->dev);
-	gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0);
-	input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0);
+	gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!gunze || !input_dev) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	gunze->serio = serio;
-
+	gunze->dev = input_dev;
 	sprintf(gunze->phys, "%s/input0", serio->phys);
 
-	gunze->dev.private = gunze;
-	gunze->dev.name = gunze_name;
-	gunze->dev.phys = gunze->phys;
-	gunze->dev.id.bustype = BUS_RS232;
-	gunze->dev.id.vendor = SERIO_GUNZE;
-	gunze->dev.id.product = 0x0051;
-	gunze->dev.id.version = 0x0100;
+	input_dev->private = gunze;
+	input_dev->name = "Gunze AHL-51S TouchScreen";
+	input_dev->phys = gunze->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_GUNZE;
+	input_dev->id.product = 0x0051;
+	input_dev->id.version = 0x0100;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 24, 1000, 0, 0);
 
 	serio_set_drvdata(serio, gunze);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(gunze);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&gunze->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
-
+	input_register_device(gunze->dev);
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(gunze);
+	return err;
 }
 
 /*
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index bcfa1e3..a18d56b 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -39,7 +39,6 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/pm.h>
 
 /* SA1100 serial defines */
 #include <asm/arch/hardware.h>
@@ -93,16 +92,12 @@
 #define H3600_SCANCODE_LEFT	8	 /* 8 -> left */
 #define H3600_SCANCODE_DOWN	9	 /* 9 -> down */
 
-static char *h3600_name = "H3600 TouchScreen";
-
 /*
  * Per-touchscreen data.
  */
 struct h3600_dev {
-	struct input_dev dev;
-	struct pm_dev *pm_dev;
+	struct input_dev *dev;
 	struct serio *serio;
-	struct pm_dev *pm_dev;
 	unsigned char event;	/* event ID from packet */
 	unsigned char chksum;
 	unsigned char len;
@@ -163,33 +158,6 @@
 	return 0;
 }
 
-static int suspended = 0;
-static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req,
-				void *data)
-{
-	struct input_dev *dev = (struct input_dev *) data;
-
-	switch (req) {
-	case PM_SUSPEND: /* enter D1-D3 */
-		suspended = 1;
-		h3600_flite_power(dev, FLITE_PWR_OFF);
-		break;
-	case PM_BLANK:
-		if (!suspended)
-			h3600_flite_power(dev, FLITE_PWR_OFF);
-		break;
-	case PM_RESUME:  /* enter D0 */
-		/* same as unblank */
-	case PM_UNBLANK:
-		if (suspended) {
-			//initSerial();
-			suspended = 0;
-		}
-		h3600_flite_power(dev, FLITE_PWR_ON);
-		break;
-	}
-	return 0;
-}
 #endif
 
 /*
@@ -199,7 +167,7 @@
  */
 static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs)
 {
-	struct input_dev *dev = &ts->dev;
+	struct input_dev *dev = ts->dev;
 	static int touched = 0;
 	int key, down = 0;
 
@@ -295,6 +263,7 @@
 static int h3600ts_event(struct input_dev *dev, unsigned int type,
 			 unsigned int code, int value)
 {
+#if 0
 	struct h3600_dev *ts = dev->private;
 
 	switch (type) {
@@ -304,6 +273,8 @@
 		}
 	}
 	return -1;
+#endif
+	return 0;
 }
 
 /*
@@ -380,14 +351,48 @@
 static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct h3600_dev *ts;
+	struct input_dev *input_dev;
 	int err;
 
-	if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
-		return -ENOMEM;
+	ts = kzalloc(sizeof(struct h3600_dev), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
 
-	memset(ts, 0, sizeof(struct h3600_dev));
+	ts->serio = serio;
+	ts->dev = input_dev;
+	sprintf(ts->phys, "%s/input0", serio->phys);
 
-	init_input_dev(&ts->dev);
+	input_dev->name = "H3600 TouchScreen";
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_H3600;
+	input_dev->id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
+	input_dev->id.version = 0x0100;
+	input_dev->cdev.dev = &serio->dev;
+	input_dev->private = ts;
+
+	input_dev->event = h3600ts_event;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
+	input_dev->ledbit[0] = BIT(LED_SLEEP);
+	input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0);
+
+	set_bit(KEY_RECORD, input_dev->keybit);
+	set_bit(KEY_Q, input_dev->keybit);
+	set_bit(KEY_PROG1, input_dev->keybit);
+	set_bit(KEY_PROG2, input_dev->keybit);
+	set_bit(KEY_PROG3, input_dev->keybit);
+	set_bit(KEY_UP, input_dev->keybit);
+	set_bit(KEY_RIGHT, input_dev->keybit);
+	set_bit(KEY_LEFT, input_dev->keybit);
+	set_bit(KEY_DOWN, input_dev->keybit);
+	set_bit(KEY_ENTER, input_dev->keybit);
+	set_bit(KEY_SUSPEND, input_dev->keybit);
+	set_bit(BTN_TOUCH, input_dev->keybit);
 
 	/* Device specific stuff */
 	set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES);
@@ -397,73 +402,35 @@
 			SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
 			"h3600_action", &ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
-		kfree(ts);
-		return -EBUSY;
+		err = -EBUSY;
+		goto fail2;
 	}
 
 	if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
 			SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
 			"h3600_suspend", &ts->dev)) {
-		free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
 		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
-		kfree(ts);
-		return -EBUSY;
+		err = -EBUSY;
+		goto fail3;
 	}
 
-	/* Now we have things going we setup our input device */
-	ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR);
-	ts->dev.ledbit[0] = BIT(LED_SLEEP);
-	input_set_abs_params(&ts->dev, ABS_X, 60, 985, 0, 0);
-	input_set_abs_params(&ts->dev, ABS_Y, 35, 1024, 0, 0);
-
-	set_bit(KEY_RECORD, ts->dev.keybit);
-	set_bit(KEY_Q, ts->dev.keybit);
-	set_bit(KEY_PROG1, ts->dev.keybit);
-	set_bit(KEY_PROG2, ts->dev.keybit);
-	set_bit(KEY_PROG3, ts->dev.keybit);
-	set_bit(KEY_UP, ts->dev.keybit);
-	set_bit(KEY_RIGHT, ts->dev.keybit);
-	set_bit(KEY_LEFT, ts->dev.keybit);
-	set_bit(KEY_DOWN, ts->dev.keybit);
-	set_bit(KEY_ENTER, ts->dev.keybit);
-	ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
-	ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
-
-	ts->serio = serio;
-
-	sprintf(ts->phys, "%s/input0", serio->phys);
-
-	ts->dev.event = h3600ts_event;
-	ts->dev.private = ts;
-	ts->dev.name = h3600_name;
-	ts->dev.phys = ts->phys;
-	ts->dev.id.bustype = BUS_RS232;
-	ts->dev.id.vendor = SERIO_H3600;
-	ts->dev.id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
-	ts->dev.id.version = 0x0100;
-
 	serio_set_drvdata(serio, ts);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
-		free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
-		serio_set_drvdata(serio, NULL);
-		kfree(ts);
+	if (err)
 		return err;
-	}
 
 	//h3600_flite_control(1, 25);     /* default brightness */
-#ifdef CONFIG_PM
-	ts->pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT,
-				h3600ts_pm_callback);
-	printk("registered pm callback\n");
-#endif
-	input_register_device(&ts->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", h3600_name, serio->phys);
+	input_register_device(ts->dev);
 
 	return 0;
+
+fail3:	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
+fail2:	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
+fail1:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(ts);
+	return err;
 }
 
 /*
@@ -476,9 +443,11 @@
 
 	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
 	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
-	input_unregister_device(&ts->dev);
+	input_get_device(ts->dev);
+	input_unregister_device(ts->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_put_device(ts->dev);
 	kfree(ts);
 }
 
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index 7e14044..957dd5a 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -21,10 +21,8 @@
 
 static void do_softint(void *data);
 
-static struct input_dev hp680_ts_dev;
+static struct input_dev *hp680_ts_dev;
 static DECLARE_WORK(work, do_softint, 0);
-static char *hp680_ts_name = "HP Jornada touchscreen";
-static char *hp680_ts_phys = "input0";
 
 static void do_softint(void *data)
 {
@@ -58,14 +56,14 @@
 	}
 
 	if (touched) {
-		input_report_key(&hp680_ts_dev, BTN_TOUCH, 1);
-		input_report_abs(&hp680_ts_dev, ABS_X, absx);
-		input_report_abs(&hp680_ts_dev, ABS_Y, absy);
+		input_report_key(hp680_ts_dev, BTN_TOUCH, 1);
+		input_report_abs(hp680_ts_dev, ABS_X, absx);
+		input_report_abs(hp680_ts_dev, ABS_Y, absy);
 	} else {
-		input_report_key(&hp680_ts_dev, BTN_TOUCH, 0);
+		input_report_key(hp680_ts_dev, BTN_TOUCH, 0);
 	}
 
-	input_sync(&hp680_ts_dev);
+	input_sync(hp680_ts_dev);
 	enable_irq(HP680_TS_IRQ);
 }
 
@@ -92,27 +90,29 @@
 	scpcr |= SCPCR_TS_ENABLE;
 	ctrl_outw(scpcr, SCPCR);
 
-	memset(&hp680_ts_dev, 0, sizeof(hp680_ts_dev));
-	init_input_dev(&hp680_ts_dev);
+	hp680_ts_dev = input_allocate_device();
+	if (!hp680_ts_dev)
+		return -ENOMEM;
 
-	hp680_ts_dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
-	hp680_ts_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-	hp680_ts_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+	hp680_ts_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+	hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
 
-	hp680_ts_dev.absmin[ABS_X] = HP680_TS_ABS_X_MIN;
-	hp680_ts_dev.absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
-	hp680_ts_dev.absmax[ABS_X] = HP680_TS_ABS_X_MAX;
-	hp680_ts_dev.absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
+	hp680_ts_dev->absmin[ABS_X] = HP680_TS_ABS_X_MIN;
+	hp680_ts_dev->absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
+	hp680_ts_dev->absmax[ABS_X] = HP680_TS_ABS_X_MAX;
+	hp680_ts_dev->absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
 
-	hp680_ts_dev.name = hp680_ts_name;
-	hp680_ts_dev.phys = hp680_ts_phys;
-	input_register_device(&hp680_ts_dev);
+	hp680_ts_dev->name = "HP Jornada touchscreen";
+	hp680_ts_dev->phys = "hp680_ts/input0";
 
-	if (request_irq
-	    (HP680_TS_IRQ, hp680_ts_interrupt, SA_INTERRUPT, MODNAME, 0) < 0) {
-		printk(KERN_ERR "hp680_touchscreen.c : Can't allocate irq %d\n",
+	input_register_device(hp680_ts_dev);
+
+	if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
+			SA_INTERRUPT, MODNAME, 0) < 0) {
+		printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
 		       HP680_TS_IRQ);
-		input_unregister_device(&hp680_ts_dev);
+		input_unregister_device(hp680_ts_dev);
 		return -EBUSY;
 	}
 
@@ -124,7 +124,7 @@
 	free_irq(HP680_TS_IRQ, 0);
 	cancel_delayed_work(&work);
 	flush_scheduled_work();
-	input_unregister_device(&hp680_ts_dev);
+	input_unregister_device(hp680_ts_dev);
 }
 
 module_init(hp680_ts_init);
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
index afaaebe..4844d25 100644
--- a/drivers/input/touchscreen/mk712.c
+++ b/drivers/input/touchscreen/mk712.c
@@ -77,7 +77,7 @@
 #define MK712_READ_ONE_POINT			0x20
 #define MK712_POWERUP				0x40
 
-static struct input_dev mk712_dev;
+static struct input_dev *mk712_dev;
 static DEFINE_SPINLOCK(mk712_lock);
 
 static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -88,7 +88,7 @@
 	static unsigned short last_y;
 
 	spin_lock(&mk712_lock);
-	input_regs(&mk712_dev, regs);
+	input_regs(mk712_dev, regs);
 
 	status = inb(mk712_io + MK712_STATUS);
 
@@ -100,7 +100,7 @@
 	if (~status & MK712_STATUS_TOUCH)
 	{
 		debounce = 1;
-		input_report_key(&mk712_dev, BTN_TOUCH, 0);
+		input_report_key(mk712_dev, BTN_TOUCH, 0);
 		goto end;
 	}
 
@@ -110,15 +110,15 @@
 		goto end;
 	}
 
-	input_report_key(&mk712_dev, BTN_TOUCH, 1);
-	input_report_abs(&mk712_dev, ABS_X, last_x);
-	input_report_abs(&mk712_dev, ABS_Y, last_y);
+	input_report_key(mk712_dev, BTN_TOUCH, 1);
+	input_report_abs(mk712_dev, ABS_X, last_x);
+	input_report_abs(mk712_dev, ABS_Y, last_y);
 
 end:
 
 	last_x = inw(mk712_io + MK712_X) & 0x0fff;
 	last_y = inw(mk712_io + MK712_Y) & 0x0fff;
-	input_sync(&mk712_dev);
+	input_sync(mk712_dev);
 	spin_unlock(&mk712_lock);
 	return IRQ_HANDLED;
 }
@@ -154,30 +154,11 @@
 	spin_unlock_irqrestore(&mk712_lock, flags);
 }
 
-static struct input_dev mk712_dev = {
-	.evbit   = { BIT(EV_KEY) | BIT(EV_ABS) },
-	.keybit  = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
-	.absbit  = { BIT(ABS_X) | BIT(ABS_Y) },
-	.open    = mk712_open,
-	.close   = mk712_close,
-	.name    = "ICS MicroClock MK712 TouchScreen",
-	.phys    = "isa0260/input0",
-	.absmin  = { [ABS_X] = 0, [ABS_Y] = 0 },
-	.absmax  = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff },
-	.absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 },
-	.id      = {
-		.bustype = BUS_ISA,
-		.vendor  = 0x0005,
-		.product = 0x0001,
-		.version = 0x0100,
-	},
-};
-
 int __init mk712_init(void)
 {
+	int err;
 
-	if(!request_region(mk712_io, 8, "mk712"))
-	{
+	if (!request_region(mk712_io, 8, "mk712")) {
 		printk(KERN_WARNING "mk712: unable to get IO region\n");
 		return -ENODEV;
 	}
@@ -188,28 +169,49 @@
 	    (inw(mk712_io + MK712_Y) & 0xf000) ||
 	    (inw(mk712_io + MK712_STATUS) & 0xf333)) {
 		printk(KERN_WARNING "mk712: device not present\n");
-		release_region(mk712_io, 8);
-		return -ENODEV;
+		err = -ENODEV;
+		goto fail;
 	}
 
-	if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev))
-	{
+	if (!(mk712_dev = input_allocate_device())) {
+		printk(KERN_ERR "mk712: not enough memory\n");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
+	mk712_dev->phys = "isa0260/input0";
+	mk712_dev->id.bustype = BUS_ISA;
+	mk712_dev->id.vendor  = 0x0005;
+	mk712_dev->id.product = 0x0001;
+	mk712_dev->id.version = 0x0100;
+
+	mk712_dev->open    = mk712_open;
+	mk712_dev->close   = mk712_close;
+
+	mk712_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	mk712_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(mk712_dev, ABS_X, 0, 0xfff, 88, 0);
+	input_set_abs_params(mk712_dev, ABS_Y, 0, 0xfff, 88, 0);
+
+	if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
 		printk(KERN_WARNING "mk712: unable to get IRQ\n");
-		release_region(mk712_io, 8);
-		return -EBUSY;
+		err = -EBUSY;
+		goto fail;
 	}
 
-	input_register_device(&mk712_dev);
-
-	printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
-
+	input_register_device(mk712_dev);
 	return 0;
+
+ fail:	input_free_device(mk712_dev);
+	release_region(mk712_io, 8);
+	return err;
 }
 
 static void __exit mk712_exit(void)
 {
-	input_unregister_device(&mk712_dev);
-	free_irq(mk712_irq, &mk712_dev);
+	input_unregister_device(mk712_dev);
+	free_irq(mk712_irq, mk712_dev);
 	release_region(mk712_io, 8);
 }
 
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index aa8ee78..1d0d37e 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -51,14 +51,12 @@
 #define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
 #define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
 
-static char *mtouch_name = "MicroTouch Serial TouchScreen";
-
 /*
  * Per-touchscreen data.
  */
 
 struct mtouch {
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct serio *serio;
 	int idx;
 	unsigned char data[MTOUCH_MAX_LENGTH];
@@ -67,7 +65,7 @@
 
 static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
 {
-	struct input_dev *dev = &mtouch->dev;
+	struct input_dev *dev = mtouch->dev;
 
 	if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
 		input_regs(dev, regs);
@@ -116,9 +114,11 @@
 {
 	struct mtouch* mtouch = serio_get_drvdata(serio);
 
-	input_unregister_device(&mtouch->dev);
+	input_get_device(mtouch->dev);
+	input_unregister_device(mtouch->dev);
 	serio_close(serio);
 	serio_set_drvdata(serio, NULL);
+	input_put_device(mtouch->dev);
 	kfree(mtouch);
 }
 
@@ -131,46 +131,46 @@
 static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct mtouch *mtouch;
+	struct input_dev *input_dev;
 	int err;
 
-	if (!(mtouch = kmalloc(sizeof(*mtouch), GFP_KERNEL)))
-		return -ENOMEM;
-
-	memset(mtouch, 0, sizeof(*mtouch));
-
-	init_input_dev(&mtouch->dev);
-	mtouch->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	mtouch->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-	input_set_abs_params(&mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
-	input_set_abs_params(&mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
+	mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!mtouch || !input_dev) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	mtouch->serio = serio;
-
+	mtouch->dev = input_dev;
 	sprintf(mtouch->phys, "%s/input0", serio->phys);
 
-	mtouch->dev.private = mtouch;
-	mtouch->dev.name = mtouch_name;
-	mtouch->dev.phys = mtouch->phys;
-	mtouch->dev.id.bustype = BUS_RS232;
-	mtouch->dev.id.vendor = SERIO_MICROTOUCH;
-	mtouch->dev.id.product = 0;
-	mtouch->dev.id.version = 0x0100;
+	input_dev->private = mtouch;
+	input_dev->name = "MicroTouch Serial TouchScreen";
+	input_dev->phys = mtouch->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_MICROTOUCH;
+	input_dev->id.product = 0;
+	input_dev->id.version = 0x0100;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
+	input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
 
 	serio_set_drvdata(serio, mtouch);
 
 	err = serio_open(serio, drv);
-	if (err) {
-		serio_set_drvdata(serio, NULL);
-		kfree(mtouch);
-		return err;
-	}
+	if (err)
+		goto fail;
 
-	input_register_device(&mtouch->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", mtouch->dev.name, serio->phys);
+	input_register_device(mtouch->dev);
 
 	return 0;
+
+ fail:	serio_set_drvdata(serio, NULL);
+	input_free_device(input_dev);
+	kfree(mtouch);
+	return err;
 }
 
 /*
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 50c63a1..ca15479 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -53,7 +53,6 @@
 #include <linux/random.h>
 #include <linux/time.h>
 #include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
 
 #ifndef CONFIG_INPUT_TSDEV_SCREEN_X
 #define CONFIG_INPUT_TSDEV_SCREEN_X	240
@@ -369,6 +368,7 @@
 					  struct input_device_id *id)
 {
 	struct tsdev *tsdev;
+	struct class_device *cdev;
 	int minor, delta;
 
 	for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
@@ -410,13 +410,13 @@
 
 	tsdev_table[minor] = tsdev;
 
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
-	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
-			S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
-	class_device_create(input_class,
+	cdev = class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			dev->dev, "ts%d", minor);
+			dev->cdev.dev, tsdev->name);
+
+	/* temporary symlink to keep userspace happy */
+	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
+			  tsdev->name);
 
 	return &tsdev->handle;
 }
@@ -426,10 +426,9 @@
 	struct tsdev *tsdev = handle->private;
 	struct tsdev_list *list;
 
-	class_device_destroy(input_class,
+	sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
-	devfs_remove("input/ts%d", tsdev->minor);
-	devfs_remove("input/tsraw%d", tsdev->minor);
 	tsdev->exist = 0;
 
 	if (tsdev->open) {
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 04fb606..11ae0fd 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1505,7 +1505,7 @@
 		return PTR_ERR(capi_class);
 	}
 
-	class_device_create(capi_class, MKDEV(capi_major, 0), NULL, "capi");
+	class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
 	devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
 			"isdn/capi20");
 
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 3abd7fc..7b564c0 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ctype.h>
+#include <linux/sched.h>	/* current */
 
 MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
 MODULE_AUTHOR("Carsten Paeth");
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 7333377a..e3866b0 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1063,7 +1063,7 @@
 				Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
 			}
 			ack_len += skb->truesize;
-			bch->tx_skb = 0;
+			bch->tx_skb = NULL;
 			bch->tx_cnt = 0;
 			dev_kfree_skb(skb);
 		} else
@@ -1659,10 +1659,10 @@
 }
 
 static struct pci_driver hfc4s8s_driver = {
-      name:"hfc4s8s_l1",
-      probe:hfc4s8s_probe,
-      remove:__devexit_p(hfc4s8s_remove),
-      id_table:hfc4s8s_ids,
+      .name	= "hfc4s8s_l1",
+      .probe	= hfc4s8s_probe,
+      .remove	= __devexit_p(hfc4s8s_remove),
+      .id_table	= hfc4s8s_ids,
 };
 
 /**********************/
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index c0dc1e3..d2ead17 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -905,5 +905,5 @@
 	adb_dev_class = class_create(THIS_MODULE, "adb");
 	if (IS_ERR(adb_dev_class))
 		return;
-	class_device_create(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+	class_device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
 }
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index db654e8..cdb6d02 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -206,7 +206,7 @@
 };
 
 struct adbhid {
-	struct input_dev input;
+	struct input_dev *input;
 	int id;
 	int default_id;
 	int original_handler_id;
@@ -291,10 +291,10 @@
 
 	switch (keycode) {
 	case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */
-		input_regs(&ahid->input, regs);
-		input_report_key(&ahid->input, KEY_CAPSLOCK, 1);
-		input_report_key(&ahid->input, KEY_CAPSLOCK, 0);
-		input_sync(&ahid->input);
+		input_regs(ahid->input, regs);
+		input_report_key(ahid->input, KEY_CAPSLOCK, 1);
+		input_report_key(ahid->input, KEY_CAPSLOCK, 0);
+		input_sync(ahid->input);
 		return;
 #ifdef CONFIG_PPC_PMAC
 	case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */
@@ -347,10 +347,10 @@
 	}
 
 	if (adbhid[id]->keycode[keycode]) {
-		input_regs(&adbhid[id]->input, regs);
-		input_report_key(&adbhid[id]->input,
+		input_regs(adbhid[id]->input, regs);
+		input_report_key(adbhid[id]->input,
 				 adbhid[id]->keycode[keycode], !up_flag);
-		input_sync(&adbhid[id]->input);
+		input_sync(adbhid[id]->input);
 	} else
 		printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,
 		       up_flag ? "released" : "pressed");
@@ -441,20 +441,20 @@
                 break;
 	}
 
-	input_regs(&adbhid[id]->input, regs);
+	input_regs(adbhid[id]->input, regs);
 
-	input_report_key(&adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
-	input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
+	input_report_key(adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
+	input_report_key(adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
 
 	if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)
-		input_report_key(&adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));
+		input_report_key(adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));
 
-	input_report_rel(&adbhid[id]->input, REL_X,
+	input_report_rel(adbhid[id]->input, REL_X,
 			 ((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ));
-	input_report_rel(&adbhid[id]->input, REL_Y,
+	input_report_rel(adbhid[id]->input, REL_Y,
 			 ((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 ));
 
-	input_sync(&adbhid[id]->input);
+	input_sync(adbhid[id]->input);
 }
 
 static void
@@ -467,7 +467,7 @@
 		return;
 	}
 
-	input_regs(&adbhid[id]->input, regs);
+	input_regs(adbhid[id]->input, regs);
 
 	switch (adbhid[id]->original_handler_id) {
 	default:
@@ -477,19 +477,19 @@
 
 		switch (data[1] & 0x0f) {
 		case 0x0:	/* microphone */
-			input_report_key(&adbhid[id]->input, KEY_SOUND, down);
+			input_report_key(adbhid[id]->input, KEY_SOUND, down);
 			break;
 
 		case 0x1:	/* mute */
-			input_report_key(&adbhid[id]->input, KEY_MUTE, down);
+			input_report_key(adbhid[id]->input, KEY_MUTE, down);
 			break;
 
 		case 0x2:	/* volume decrease */
-			input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);
+			input_report_key(adbhid[id]->input, KEY_VOLUMEDOWN, down);
 			break;
 
 		case 0x3:	/* volume increase */
-			input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);
+			input_report_key(adbhid[id]->input, KEY_VOLUMEUP, down);
 			break;
 
 		default:
@@ -513,19 +513,19 @@
 
 		switch (data[1] & 0x0f) {
 		case 0x8:	/* mute */
-			input_report_key(&adbhid[id]->input, KEY_MUTE, down);
+			input_report_key(adbhid[id]->input, KEY_MUTE, down);
 			break;
 
 		case 0x7:	/* volume decrease */
-			input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);
+			input_report_key(adbhid[id]->input, KEY_VOLUMEDOWN, down);
 			break;
 
 		case 0x6:	/* volume increase */
-			input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);
+			input_report_key(adbhid[id]->input, KEY_VOLUMEUP, down);
 			break;
 
 		case 0xb:	/* eject */
-			input_report_key(&adbhid[id]->input, KEY_EJECTCD, down);
+			input_report_key(adbhid[id]->input, KEY_EJECTCD, down);
 			break;
 
 		case 0xa:	/* brightness decrease */
@@ -539,7 +539,7 @@
 				}
 			}
 #endif /* CONFIG_PMAC_BACKLIGHT */
-			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
+			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
 			break;
 
 		case 0x9:	/* brightness increase */
@@ -553,19 +553,19 @@
 				}
 			}
 #endif /* CONFIG_PMAC_BACKLIGHT */
-			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down);
+			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
 			break;
 
 		case 0xc:	/* videomode switch */
-			input_report_key(&adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
+			input_report_key(adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
 			break;
 
 		case 0xd:	/* keyboard illumination toggle */
-			input_report_key(&adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
+			input_report_key(adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
 			break;
 
 		case 0xe:	/* keyboard illumination decrease */
-			input_report_key(&adbhid[id]->input, KEY_KBDILLUMDOWN, down);
+			input_report_key(adbhid[id]->input, KEY_KBDILLUMDOWN, down);
 			break;
 
 		case 0xf:
@@ -573,7 +573,7 @@
 			case 0x8f:
 			case 0x0f:
 				/* keyboard illumination increase */
-				input_report_key(&adbhid[id]->input, KEY_KBDILLUMUP, down);
+				input_report_key(adbhid[id]->input, KEY_KBDILLUMUP, down);
 				break;
 
 			case 0x7f:
@@ -596,7 +596,7 @@
 	  break;
 	}
 
-	input_sync(&adbhid[id]->input);
+	input_sync(adbhid[id]->input);
 }
 
 static struct adb_request led_request;
@@ -683,7 +683,7 @@
 			int i;
 			for (i = 1; i < 16; i++) {
 				if (adbhid[i])
-					del_timer_sync(&adbhid[i]->input.timer);
+					del_timer_sync(&adbhid[i]->input->timer);
 			}
 		}
 
@@ -699,153 +699,163 @@
 	return NOTIFY_DONE;
 }
 
-static void
+static int
 adbhid_input_register(int id, int default_id, int original_handler_id,
 		      int current_handler_id, int mouse_kind)
 {
+	struct adbhid *hid;
+	struct input_dev *input_dev;
+	int err;
 	int i;
 
 	if (adbhid[id]) {
 		printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);
-		return;
+		return -EEXIST;
 	}
 
-	if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL)))
-		return;
+	adbhid[id] = hid = kzalloc(sizeof(struct adbhid), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!hid || !input_dev) {
+		err = -ENOMEM;
+		goto fail;
 
-	memset(adbhid[id], 0, sizeof(struct adbhid));
-	sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
+	}
 
-	init_input_dev(&adbhid[id]->input);
+	sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);
 
-	adbhid[id]->id = default_id;
-	adbhid[id]->original_handler_id = original_handler_id;
-	adbhid[id]->current_handler_id = current_handler_id;
-	adbhid[id]->mouse_kind = mouse_kind;
-	adbhid[id]->flags = 0;
-	adbhid[id]->input.private = adbhid[id];
-	adbhid[id]->input.name = adbhid[id]->name;
-	adbhid[id]->input.phys = adbhid[id]->phys;
-	adbhid[id]->input.id.bustype = BUS_ADB;
-	adbhid[id]->input.id.vendor = 0x0001;
-	adbhid[id]->input.id.product = (id << 12) | (default_id << 8) | original_handler_id;
-	adbhid[id]->input.id.version = 0x0100;
+	hid->id = default_id;
+	hid->original_handler_id = original_handler_id;
+	hid->current_handler_id = current_handler_id;
+	hid->mouse_kind = mouse_kind;
+	hid->flags = 0;
+	input_dev->private = hid;
+	input_dev->name = hid->name;
+	input_dev->phys = hid->phys;
+	input_dev->id.bustype = BUS_ADB;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = (id << 12) | (default_id << 8) | original_handler_id;
+	input_dev->id.version = 0x0100;
 
 	switch (default_id) {
 	case ADB_KEYBOARD:
-		if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) {
-			kfree(adbhid[id]);
-			return;
+		hid->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL);
+		if (!hid->keycode) {
+			err = -ENOMEM;
+			goto fail;
 		}
 
-		sprintf(adbhid[id]->name, "ADB keyboard");
+		sprintf(hid->name, "ADB keyboard");
 
-		memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
+		memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));
 
 		printk(KERN_INFO "Detected ADB keyboard, type ");
 		switch (original_handler_id) {
 		default:
 			printk("<unknown>.\n");
-			adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN;
+			input_dev->id.version = ADB_KEYBOARD_UNKNOWN;
 			break;
 
 		case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
 		case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
 		case 0xC0: case 0xC3: case 0xC6:
 			printk("ANSI.\n");
-			adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI;
+			input_dev->id.version = ADB_KEYBOARD_ANSI;
 			break;
 
 		case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
 		case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
 		case 0xC4: case 0xC7:
 			printk("ISO, swapping keys.\n");
-			adbhid[id]->input.id.version = ADB_KEYBOARD_ISO;
-			i = adbhid[id]->keycode[10];
-			adbhid[id]->keycode[10] = adbhid[id]->keycode[50];
-			adbhid[id]->keycode[50] = i;
+			input_dev->id.version = ADB_KEYBOARD_ISO;
+			i = hid->keycode[10];
+			hid->keycode[10] = hid->keycode[50];
+			hid->keycode[50] = i;
 			break;
 
 		case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:
 		case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:
 			printk("JIS.\n");
-			adbhid[id]->input.id.version = ADB_KEYBOARD_JIS;
+			input_dev->id.version = ADB_KEYBOARD_JIS;
 			break;
 		}
 
 		for (i = 0; i < 128; i++)
-			if (adbhid[id]->keycode[i])
-				set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit);
+			if (hid->keycode[i])
+				set_bit(hid->keycode[i], input_dev->keybit);
 
-		adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-		adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
-		adbhid[id]->input.event = adbhid_kbd_event;
-		adbhid[id]->input.keycodemax = 127;
-		adbhid[id]->input.keycodesize = 1;
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+		input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
+		input_dev->event = adbhid_kbd_event;
+		input_dev->keycodemax = 127;
+		input_dev->keycodesize = 1;
 		break;
 
 	case ADB_MOUSE:
-		sprintf(adbhid[id]->name, "ADB mouse");
+		sprintf(hid->name, "ADB mouse");
 
-		adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-		adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-		adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+		input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+		input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
 		break;
 
 	case ADB_MISC:
 		switch (original_handler_id) {
 		case 0x02: /* Adjustable keyboard button device */
-			sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons");
-			adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-			set_bit(KEY_SOUND, adbhid[id]->input.keybit);
-			set_bit(KEY_MUTE, adbhid[id]->input.keybit);
-			set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);
-			set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);
+			sprintf(hid->name, "ADB adjustable keyboard buttons");
+			input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+			set_bit(KEY_SOUND, input_dev->keybit);
+			set_bit(KEY_MUTE, input_dev->keybit);
+			set_bit(KEY_VOLUMEUP, input_dev->keybit);
+			set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
 			break;
 		case 0x1f: /* Powerbook button device */
-			sprintf(adbhid[id]->name, "ADB Powerbook buttons");
-			adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-			set_bit(KEY_MUTE, adbhid[id]->input.keybit);
-			set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);
-			set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);
-			set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit);
-			set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit);
-			set_bit(KEY_EJECTCD, adbhid[id]->input.keybit);
-			set_bit(KEY_SWITCHVIDEOMODE, adbhid[id]->input.keybit);
-			set_bit(KEY_KBDILLUMTOGGLE, adbhid[id]->input.keybit);
-			set_bit(KEY_KBDILLUMDOWN, adbhid[id]->input.keybit);
-			set_bit(KEY_KBDILLUMUP, adbhid[id]->input.keybit);
+			sprintf(hid->name, "ADB Powerbook buttons");
+			input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+			set_bit(KEY_MUTE, input_dev->keybit);
+			set_bit(KEY_VOLUMEUP, input_dev->keybit);
+			set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
+			set_bit(KEY_BRIGHTNESSUP, input_dev->keybit);
+			set_bit(KEY_BRIGHTNESSDOWN, input_dev->keybit);
+			set_bit(KEY_EJECTCD, input_dev->keybit);
+			set_bit(KEY_SWITCHVIDEOMODE, input_dev->keybit);
+			set_bit(KEY_KBDILLUMTOGGLE, input_dev->keybit);
+			set_bit(KEY_KBDILLUMDOWN, input_dev->keybit);
+			set_bit(KEY_KBDILLUMUP, input_dev->keybit);
 			break;
 		}
-		if (adbhid[id]->name[0])
+		if (hid->name[0])
 			break;
 		/* else fall through */
 
 	default:
 		printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n");
-		kfree(adbhid[id]);
-		return;
+		err = -ENODEV;
+		goto fail;
 	}
 
-	adbhid[id]->input.keycode = adbhid[id]->keycode;
+	input_dev->keycode = hid->keycode;
 
-	input_register_device(&adbhid[id]->input);
-
-	printk(KERN_INFO "input: %s on %s\n",
-	       adbhid[id]->name, adbhid[id]->phys);
+	input_register_device(input_dev);
 
 	if (default_id == ADB_KEYBOARD) {
 		/* HACK WARNING!! This should go away as soon there is an utility
 		 * to control that for event devices.
 		 */
-		adbhid[id]->input.rep[REP_DELAY] = 500;   /* input layer default: 250 */
-		adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */
+		input_dev->rep[REP_DELAY] = 500;   /* input layer default: 250 */
+		input_dev->rep[REP_PERIOD] = 66; /* input layer default: 33 */
 	}
+
+	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(hid);
+	adbhid[id] = NULL;
+	return err;
 }
 
 static void adbhid_input_unregister(int id)
 {
-	input_unregister_device(&adbhid[id]->input);
+	input_unregister_device(adbhid[id]->input);
 	if (adbhid[id]->keycode)
 		kfree(adbhid[id]->keycode);
 	kfree(adbhid[id]);
@@ -858,7 +868,7 @@
 			int cur_handler_id, int mk)
 {
 	if (adbhid[id]) {
-		if (adbhid[id]->input.id.product !=
+		if (adbhid[id]->input->id.product !=
 		    ((id << 12)|(default_id << 8)|org_handler_id)) {
 			adbhid_input_unregister(id);
 			adbhid_input_register(id, default_id, org_handler_id,
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 5ad3a5a..a666361 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -16,8 +16,8 @@
 #include <linux/module.h>
 
 
-static struct input_dev emumousebtn;
-static void emumousebtn_input_register(void);
+static struct input_dev *emumousebtn;
+static int emumousebtn_input_register(void);
 static int mouse_emulate_buttons = 0;
 static int mouse_button2_keycode = KEY_RIGHTCTRL;	/* right control key */
 static int mouse_button3_keycode = KEY_RIGHTALT;	/* right option key */
@@ -90,10 +90,10 @@
 		    && (keycode == mouse_button2_keycode
 			|| keycode == mouse_button3_keycode)) {
 			if (mouse_emulate_buttons == 1) {
-			 	input_report_key(&emumousebtn,
+				input_report_key(emumousebtn,
 						 keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT,
 						 down);
-				input_sync(&emumousebtn);
+				input_sync(emumousebtn);
 				return 1;
 			}
 			mouse_last_keycode = down ? keycode : 0;
@@ -105,30 +105,34 @@
 
 EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
 
-static void emumousebtn_input_register(void)
+static int emumousebtn_input_register(void)
 {
-	emumousebtn.name = "Macintosh mouse button emulation";
+	emumousebtn = input_allocate_device();
+	if (!emumousebtn)
+		return -ENOMEM;
 
-	init_input_dev(&emumousebtn);
+	emumousebtn->name = "Macintosh mouse button emulation";
+	emumousebtn->id.bustype = BUS_ADB;
+	emumousebtn->id.vendor = 0x0001;
+	emumousebtn->id.product = 0x0001;
+	emumousebtn->id.version = 0x0100;
 
-	emumousebtn.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	emumousebtn.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	emumousebtn.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	emumousebtn->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+	emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
 
-	emumousebtn.id.bustype = BUS_ADB;
-	emumousebtn.id.vendor = 0x0001;
-	emumousebtn.id.product = 0x0001;
-	emumousebtn.id.version = 0x0100;
+	input_register_device(emumousebtn);
 
-	input_register_device(&emumousebtn);
-
-	printk(KERN_INFO "input: Macintosh mouse button emulation\n");
+	return 0;
 }
 
 int __init mac_hid_init(void)
 {
+	int err;
 
-	emumousebtn_input_register();
+	err = emumousebtn_input_register();
+	if (err)
+		return err;
 
 #if defined(CONFIG_SYSCTL)
 	mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 1ee0033..c34c96d 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -17,6 +17,8 @@
 #include <linux/pci_ids.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/slab.h>
+
 #include <asm/machdep.h>
 #include <asm/macio.h>
 #include <asm/pmac_feature.h>
diff --git a/drivers/mca/mca-device.c b/drivers/mca/mca-device.c
index 76d430a..e7adf89 100644
--- a/drivers/mca/mca-device.c
+++ b/drivers/mca/mca-device.c
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/mca.h>
+#include <linux/string.h>
 
 /**
  *	mca_device_read_stored_pos - read POS register from stored data
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 2fba2bb..01654fc 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -91,7 +91,7 @@
 
 #define WRITE_POOL_SIZE 256
 /* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+static void *write_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	return kmalloc(sizeof(struct page_list), gfp_flags);
 }
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index b6148f6..cf66310 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -15,7 +15,7 @@
 #include <linux/crypto.h>
 #include <linux/workqueue.h>
 #include <asm/atomic.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 #include <asm/page.h>
 
 #include "dm.h"
@@ -164,9 +164,7 @@
 		return -ENOMEM;
 	}
 
-	sg.page = virt_to_page(cc->key);
-	sg.offset = offset_in_page(cc->key);
-	sg.length = cc->key_size;
+	sg_set_buf(&sg, cc->key, cc->key_size);
 	crypto_digest_digest(hash_tfm, &sg, 1, salt);
 	crypto_free_tfm(hash_tfm);
 
@@ -207,14 +205,12 @@
 
 static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
 {
-	struct scatterlist sg = { NULL, };
+	struct scatterlist sg;
 
 	memset(iv, 0, cc->iv_size);
 	*(u64 *)iv = cpu_to_le64(sector);
 
-	sg.page = virt_to_page(iv);
-	sg.offset = offset_in_page(iv);
-	sg.length = cc->iv_size;
+	sg_set_buf(&sg, iv, cc->iv_size);
 	crypto_cipher_encrypt((struct crypto_tfm *)cc->iv_gen_private,
 	                      &sg, &sg, cc->iv_size);
 
@@ -331,7 +327,7 @@
 {
 	struct bio *bio;
 	unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
+	gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
 	unsigned int i;
 
 	/*
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index a0e700d..31fccb4 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -22,6 +22,7 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
 #include <media/ir-common.h>
 
 /* -------------------------------------------------------------------------- */
@@ -252,7 +253,6 @@
 	if (ir_codes)
 		memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
 
-        init_input_dev(dev);
 	dev->keycode     = ir->ir_codes;
 	dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
 	dev->keycodemax  = IR_KEYTAB_SIZE;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 6db0929..a1607e7 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -137,7 +137,8 @@
 	struct urb *stream_urb [STREAM_URB_COUNT];
 
 #ifdef ENABLE_RC
-	struct input_dev rc_input_dev;
+	struct input_dev *rc_input_dev;
+	char phys[64];
 	struct work_struct rc_query_work;
 	int rc_input_event;
 	u32 rc_last_code;
@@ -683,6 +684,7 @@
 };
 
 #ifdef ENABLE_RC
+
 static void cinergyt2_query_rc (void *data)
 {
 	struct cinergyt2 *cinergyt2 = data;
@@ -703,7 +705,7 @@
 			/* stop key repeat */
 			if (cinergyt2->rc_input_event != KEY_MAX) {
 				dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
-				input_report_key(&cinergyt2->rc_input_dev,
+				input_report_key(cinergyt2->rc_input_dev,
 						 cinergyt2->rc_input_event, 0);
 				cinergyt2->rc_input_event = KEY_MAX;
 			}
@@ -722,7 +724,7 @@
 			/* keyrepeat bit -> just repeat last rc_input_event */
 		} else {
 			cinergyt2->rc_input_event = KEY_MAX;
-			for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) {
+			for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) {
 				if (rc_keys[i + 0] == rc_events[n].type &&
 				    rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
 					cinergyt2->rc_input_event = rc_keys[i + 2];
@@ -736,11 +738,11 @@
 			    cinergyt2->rc_last_code != ~0) {
 				/* emit a key-up so the double event is recognized */
 				dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
-				input_report_key(&cinergyt2->rc_input_dev,
+				input_report_key(cinergyt2->rc_input_dev,
 						 cinergyt2->rc_input_event, 0);
 			}
 			dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
-			input_report_key(&cinergyt2->rc_input_dev,
+			input_report_key(cinergyt2->rc_input_dev,
 					 cinergyt2->rc_input_event, 1);
 			cinergyt2->rc_last_code = rc_events[n].value;
 		}
@@ -752,7 +754,59 @@
 
 	up(&cinergyt2->sem);
 }
-#endif
+
+static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
+{
+	struct input_dev *input_dev;
+	int i;
+
+	cinergyt2->rc_input_dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
+
+	usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
+	strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
+	cinergyt2->rc_input_event = KEY_MAX;
+	cinergyt2->rc_last_code = ~0;
+	INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
+
+	input_dev->name = DRIVER_NAME " remote control";
+	input_dev->phys = cinergyt2->phys;
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	for (i = 0; ARRAY_SIZE(rc_keys); i += 3)
+		set_bit(rc_keys[i + 2], input_dev->keybit);
+	input_dev->keycodesize = 0;
+	input_dev->keycodemax = 0;
+
+	input_register_device(cinergyt2->rc_input_dev);
+	schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
+}
+
+static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
+{
+	cancel_delayed_work(&cinergyt2->rc_query_work);
+	flush_scheduled_work();
+	input_unregister_device(cinergyt2->rc_input_dev);
+}
+
+static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
+{
+	cancel_delayed_work(&cinergyt2->rc_query_work);
+}
+
+static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2)
+{
+	schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
+}
+
+#else
+
+static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; }
+static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { }
+static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { }
+static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { }
+
+#endif /* ENABLE_RC */
 
 static void cinergyt2_query (void *data)
 {
@@ -789,9 +843,6 @@
 {
 	struct cinergyt2 *cinergyt2;
 	int err;
-#ifdef ENABLE_RC
-	int i;
-#endif
 
 	if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
 		dprintk(1, "out of memory?!?\n");
@@ -846,30 +897,17 @@
 			    &cinergyt2_fe_template, cinergyt2,
 			    DVB_DEVICE_FRONTEND);
 
-#ifdef ENABLE_RC
-	cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-	cinergyt2->rc_input_dev.keycodesize = 0;
-	cinergyt2->rc_input_dev.keycodemax = 0;
-	cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
+	err = cinergyt2_register_rc(cinergyt2);
+	if (err)
+		goto bailout;
 
-	for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3)
-		set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit);
-
-	input_register_device(&cinergyt2->rc_input_dev);
-
-	cinergyt2->rc_input_event = KEY_MAX;
-	cinergyt2->rc_last_code = ~0;
-
-	INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
-	schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-#endif
 	return 0;
 
 bailout:
 	dvb_dmxdev_release(&cinergyt2->dmxdev);
 	dvb_dmx_release(&cinergyt2->demux);
-	dvb_unregister_adapter (&cinergyt2->adapter);
-	cinergyt2_free_stream_urbs (cinergyt2);
+	dvb_unregister_adapter(&cinergyt2->adapter);
+	cinergyt2_free_stream_urbs(cinergyt2);
 	kfree(cinergyt2);
 	return -ENOMEM;
 }
@@ -881,11 +919,7 @@
 	if (down_interruptible(&cinergyt2->sem))
 		return;
 
-#ifdef ENABLE_RC
-	cancel_delayed_work(&cinergyt2->rc_query_work);
-	flush_scheduled_work();
-	input_unregister_device(&cinergyt2->rc_input_dev);
-#endif
+	cinergyt2_unregister_rc(cinergyt2);
 
 	cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
 	dvb_net_release(&cinergyt2->dvbnet);
@@ -908,9 +942,8 @@
 
 	if (state.event > PM_EVENT_ON) {
 		struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-#ifdef ENABLE_RC
-		cancel_delayed_work(&cinergyt2->rc_query_work);
-#endif
+
+		cinergyt2_suspend_rc(cinergyt2);
 		cancel_delayed_work(&cinergyt2->query_work);
 		if (cinergyt2->streaming)
 			cinergyt2_stop_stream_xfer(cinergyt2);
@@ -938,9 +971,8 @@
 		schedule_delayed_work(&cinergyt2->query_work, HZ/2);
 	}
 
-#ifdef ENABLE_RC
-	schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-#endif
+	cinergyt2_resume_rc(cinergyt2);
+
 	up(&cinergyt2->sem);
 	return 0;
 }
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 88757e2..2aa767f 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -36,6 +36,7 @@
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/rwsem.h>
+#include <linux/sched.h>
 
 #include "dvb_ca_en50221.h"
 #include "dvb_ringbuffer.h"
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 4b7adca..477b4fa 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -235,7 +235,7 @@
 			S_IFCHR | S_IRUSR | S_IWUSR,
 			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
-	class_device_create(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+	class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
 			    NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
 
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 5aa12eb..b595476 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@
 		  .cold_ids = { &dtt200u_usb_table[0], NULL },
 		  .warm_ids = { &dtt200u_usb_table[1], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
@@ -192,7 +192,7 @@
 		  .cold_ids = { &dtt200u_usb_table[2], NULL },
 		  .warm_ids = { &dtt200u_usb_table[3], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index fc7800f..e5c6d98 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -39,9 +39,9 @@
 			d->last_event = event;
 		case REMOTE_KEY_REPEAT:
 			deb_rc("key repeated\n");
-			input_event(&d->rc_input_dev, EV_KEY, d->last_event, 1);
-			input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
-			input_sync(&d->rc_input_dev);
+			input_event(d->rc_input_dev, EV_KEY, event, 1);
+			input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+			input_sync(d->rc_input_dev);
 			break;
 		default:
 			break;
@@ -53,8 +53,8 @@
 			deb_rc("NO KEY PRESSED\n");
 			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
 				deb_rc("releasing event %d\n",d->last_event);
-				input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
-				input_sync(&d->rc_input_dev);
+				input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+				input_sync(d->rc_input_dev);
 			}
 			d->last_state = REMOTE_NO_KEY_PRESSED;
 			d->last_event = 0;
@@ -63,8 +63,8 @@
 			deb_rc("KEY PRESSED\n");
 			deb_rc("pressing event %d\n",event);
 
-			input_event(&d->rc_input_dev, EV_KEY, event, 1);
-			input_sync(&d->rc_input_dev);
+			input_event(d->rc_input_dev, EV_KEY, event, 1);
+			input_sync(d->rc_input_dev);
 
 			d->last_event = event;
 			d->last_state = REMOTE_KEY_PRESSED;
@@ -73,8 +73,8 @@
 			deb_rc("KEY_REPEAT\n");
 			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
 				deb_rc("repeating event %d\n",d->last_event);
-				input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
-				input_sync(&d->rc_input_dev);
+				input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
+				input_sync(d->rc_input_dev);
 				d->last_state = REMOTE_KEY_REPEAT;
 			}
 		default:
@@ -89,24 +89,30 @@
 int dvb_usb_remote_init(struct dvb_usb_device *d)
 {
 	int i;
+
 	if (d->props.rc_key_map == NULL ||
 		d->props.rc_query == NULL ||
 		dvb_usb_disable_rc_polling)
 		return 0;
 
-	/* Initialise the remote-control structures.*/
-	init_input_dev(&d->rc_input_dev);
+	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
+	strlcpy(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
-	d->rc_input_dev.evbit[0] = BIT(EV_KEY);
-	d->rc_input_dev.keycodesize = sizeof(unsigned char);
-	d->rc_input_dev.keycodemax = KEY_MAX;
-	d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
+	d->rc_input_dev = input_allocate_device();
+	if (!d->rc_input_dev)
+		return -ENOMEM;
+
+	d->rc_input_dev->evbit[0] = BIT(EV_KEY);
+	d->rc_input_dev->keycodesize = sizeof(unsigned char);
+	d->rc_input_dev->keycodemax = KEY_MAX;
+	d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
+	d->rc_input_dev->phys = d->rc_phys;
 
 	/* set the bits for the keys */
-	deb_rc("key map size: %d\n",d->props.rc_key_map_size);
+	deb_rc("key map size: %d\n", d->props.rc_key_map_size);
 	for (i = 0; i < d->props.rc_key_map_size; i++) {
 		deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
-		set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
+		set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
 	}
 
 	/* Start the remote-control polling. */
@@ -114,14 +120,14 @@
 		d->props.rc_interval = 100; /* default */
 
 	/* setting these two values to non-zero, we have to manage key repeats */
-	d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
-	d->rc_input_dev.rep[REP_DELAY]  = d->props.rc_interval + 150;
+	d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
+	d->rc_input_dev->rep[REP_DELAY]  = d->props.rc_interval + 150;
 
-	input_register_device(&d->rc_input_dev);
+	input_register_device(d->rc_input_dev);
 
 	INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
 
-	info("schedule remote query interval to %d msecs.",d->props.rc_interval);
+	info("schedule remote query interval to %d msecs.", d->props.rc_interval);
 	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
 
 	d->state |= DVB_USB_STATE_REMOTE;
@@ -134,7 +140,7 @@
 	if (d->state & DVB_USB_STATE_REMOTE) {
 		cancel_delayed_work(&d->rc_query_work);
 		flush_scheduled_work();
-		input_unregister_device(&d->rc_input_dev);
+		input_unregister_device(d->rc_input_dev);
 	}
 	d->state &= ~DVB_USB_STATE_REMOTE;
 	return 0;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 0e4f103..b4a1a98 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -300,7 +300,8 @@
 	int (*fe_init)  (struct dvb_frontend *);
 
 	/* remote control */
-	struct input_dev rc_input_dev;
+	struct input_dev *rc_input_dev;
+	char rc_phys[64];
 	struct work_struct rc_query_work;
 	u32 last_event;
 	int last_state;
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 0f57abe..75765e3 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,7 +247,7 @@
 		  .cold_ids = { &vp7045_usb_table[2], NULL },
 		  .warm_ids = { &vp7045_usb_table[3], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index f5fdc5c..f6d4ee7 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -36,6 +36,9 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "bcm3510.h"
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index 21433e1..6b05536 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -27,6 +27,8 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dib3000-common.h"
 #include "dib3000mb_priv.h"
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 441de66..c024fad 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -26,6 +26,8 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dib3000-common.h"
 #include "dib3000mc_priv.h"
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index cff93b9..794be52 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -22,6 +22,8 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "dvb_dummy_fe.h"
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 7142b9c..8dde72b 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -37,6 +37,8 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <asm/byteorder.h>
 
 #include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index e455aec..e384549 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -29,6 +29,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "mt312_priv.h"
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index cc1bc0e..f0c610f 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -35,6 +35,8 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "mt352_priv.h"
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index 35a1d60..30786b1 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -32,6 +32,8 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "nxt2002.h"
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index b6d0eec..817b044 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -36,6 +36,8 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <asm/byteorder.h>
 
 #include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index ad56a99..8a9db23 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -34,6 +34,8 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <asm/byteorder.h>
 
 #include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index c7fe27f..f265418 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -26,6 +26,8 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
 
 #include "dvb_frontend.h"
 #include "s5h1420.h"
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 764a95a..1c6b2e9 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -32,6 +32,8 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "sp8870.h"
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index d868a69..73384e7 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -14,6 +14,8 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "sp887x.h"
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 8d09afd..6122ba7 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -24,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "stv0297.h"
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 2d62931..889d925 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -48,6 +48,7 @@
 #include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <asm/div64.h>
 
 #include "dvb_frontend.h"
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 74cea9f..3529c61 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -32,6 +32,10 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
 #include "dvb_frontend.h"
 #include "tda1004x.h"
 
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 168e013..c05cf186 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -30,6 +30,7 @@
 #include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include "dvb_frontend.h"
 #include "tda8083.h"
 
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 357a372..f5e59fc 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -15,7 +15,7 @@
 
 static int av_cnt;
 static struct av7110 *av_list[4];
-static struct input_dev input_dev;
+static struct input_dev *input_dev;
 
 static u16 key_map [256] = {
 	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
@@ -43,10 +43,10 @@
 
 static void av7110_emit_keyup(unsigned long data)
 {
-	if (!data || !test_bit(data, input_dev.key))
+	if (!data || !test_bit(data, input_dev->key))
 		return;
 
-	input_event(&input_dev, EV_KEY, data, !!0);
+	input_event(input_dev, EV_KEY, data, !!0);
 }
 
 
@@ -112,13 +112,13 @@
 	if (timer_pending(&keyup_timer)) {
 		del_timer(&keyup_timer);
 		if (keyup_timer.data != keycode || new_toggle != old_toggle) {
-			input_event(&input_dev, EV_KEY, keyup_timer.data, !!0);
-			input_event(&input_dev, EV_KEY, keycode, !0);
+			input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
+			input_event(input_dev, EV_KEY, keycode, !0);
 		} else
-			input_event(&input_dev, EV_KEY, keycode, 2);
+			input_event(input_dev, EV_KEY, keycode, 2);
 
 	} else
-		input_event(&input_dev, EV_KEY, keycode, !0);
+		input_event(input_dev, EV_KEY, keycode, !0);
 
 	keyup_timer.expires = jiffies + UP_TIMEOUT;
 	keyup_timer.data = keycode;
@@ -132,13 +132,13 @@
 {
 	int i;
 
-	memset(input_dev.keybit, 0, sizeof(input_dev.keybit));
+	memset(input_dev->keybit, 0, sizeof(input_dev->keybit));
 
-	for (i = 0; i < sizeof(key_map) / sizeof(key_map[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(key_map); i++) {
 		if (key_map[i] > KEY_MAX)
 			key_map[i] = 0;
 		else if (key_map[i] > KEY_RESERVED)
-			set_bit(key_map[i], input_dev.keybit);
+			set_bit(key_map[i], input_dev->keybit);
 	}
 }
 
@@ -216,12 +216,17 @@
 		init_timer(&keyup_timer);
 		keyup_timer.data = 0;
 
-		input_dev.name = "DVB on-card IR receiver";
-		set_bit(EV_KEY, input_dev.evbit);
-		set_bit(EV_REP, input_dev.evbit);
+		input_dev = input_allocate_device();
+		if (!input_dev)
+			return -ENOMEM;
+
+		input_dev->name = "DVB on-card IR receiver";
+
+		set_bit(EV_KEY, input_dev->evbit);
+		set_bit(EV_REP, input_dev->evbit);
 		input_register_keys();
-		input_register_device(&input_dev);
-		input_dev.timer.function = input_repeat_key;
+		input_register_device(input_dev);
+		input_dev->timer.function = input_repeat_key;
 
 		e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
 		if (e) {
@@ -256,7 +261,7 @@
 	if (av_cnt == 1) {
 		del_timer_sync(&keyup_timer);
 		remove_proc_entry("av7110_ir", NULL);
-		input_unregister_device(&input_dev);
+		input_unregister_device(input_dev);
 	}
 
 	av_cnt--;
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 2980db3..51c30ba 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -64,7 +64,7 @@
 
 struct budget_ci {
 	struct budget budget;
-	struct input_dev input_dev;
+	struct input_dev *input_dev;
 	struct tasklet_struct msp430_irq_tasklet;
 	struct tasklet_struct ciintf_irq_tasklet;
 	int slot_status;
@@ -145,7 +145,7 @@
 static void msp430_ir_interrupt(unsigned long data)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) data;
-	struct input_dev *dev = &budget_ci->input_dev;
+	struct input_dev *dev = budget_ci->input_dev;
 	unsigned int code =
 		ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
 
@@ -181,25 +181,27 @@
 static int msp430_ir_init(struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
+	struct input_dev *input_dev;
 	int i;
 
-	memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
+	budget_ci->input_dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
 	sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
-	budget_ci->input_dev.name = budget_ci->ir_dev_name;
 
-	set_bit(EV_KEY, budget_ci->input_dev.evbit);
+	input_dev->name = budget_ci->ir_dev_name;
 
-	for (i = 0; i < sizeof(key_map) / sizeof(*key_map); i++)
+	set_bit(EV_KEY, input_dev->evbit);
+	for (i = 0; i < ARRAY_SIZE(key_map); i++)
 		if (key_map[i])
-			set_bit(key_map[i], budget_ci->input_dev.keybit);
+			set_bit(key_map[i], input_dev->keybit);
 
-	input_register_device(&budget_ci->input_dev);
+	input_register_device(budget_ci->input_dev);
 
-	budget_ci->input_dev.timer.function = msp430_ir_debounce;
+	input_dev->timer.function = msp430_ir_debounce;
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
-
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
 	return 0;
@@ -208,7 +210,7 @@
 static void msp430_ir_deinit(struct budget_ci *budget_ci)
 {
 	struct saa7146_dev *saa = budget_ci->budget.dev;
-	struct input_dev *dev = &budget_ci->input_dev;
+	struct input_dev *dev = budget_ci->input_dev;
 
 	saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 3d08fc8..832d179 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -152,7 +152,8 @@
 	struct list_head	filter_info_list;
 	spinlock_t		filter_info_list_lock;
 
-	struct input_dev	rc_input_dev;
+	struct input_dev	*rc_input_dev;
+	char			rc_phys[64];
 
 	int			active; /* Loaded successfully */
 };
@@ -235,9 +236,9 @@
 		 * this should/could be added later ...
 		 * for now lets report each signal as a key down and up*/
 		dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
-		input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],1);
-		input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],0);
-		input_sync(&dec->rc_input_dev);
+		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
+		input_sync(dec->rc_input_dev);
 	}
 
 exit:	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1181,29 +1182,38 @@
 		     (unsigned long)dec);
 }
 
-static void ttusb_init_rc( struct ttusb_dec *dec)
+static int ttusb_init_rc(struct ttusb_dec *dec)
 {
+	struct input_dev *input_dev;
 	u8 b[] = { 0x00, 0x01 };
 	int i;
 
-	init_input_dev(&dec->rc_input_dev);
+	usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
+	strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
 
-	dec->rc_input_dev.name = "ttusb_dec remote control";
-	dec->rc_input_dev.evbit[0] = BIT(EV_KEY);
-	dec->rc_input_dev.keycodesize = sizeof(u16);
-	dec->rc_input_dev.keycodemax = 0x1a;
-	dec->rc_input_dev.keycode = rc_keys;
+	dec->rc_input_dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
-	 for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
-                set_bit(rc_keys[i], dec->rc_input_dev.keybit);
+	input_dev->name = "ttusb_dec remote control";
+	input_dev->phys = dec->rc_phys;
+	input_dev->evbit[0] = BIT(EV_KEY);
+	input_dev->keycodesize = sizeof(u16);
+	input_dev->keycodemax = 0x1a;
+	input_dev->keycode = rc_keys;
 
-	input_register_device(&dec->rc_input_dev);
+	for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
+                set_bit(rc_keys[i], input_dev->keybit);
 
-	if(usb_submit_urb(dec->irq_urb,GFP_KERNEL)) {
+	input_register_device(input_dev);
+
+	if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
 		printk("%s: usb_submit_urb failed\n",__FUNCTION__);
-	}
+
 	/* enable irq pipe */
 	ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
+
+	return 0;
 }
 
 static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
@@ -1513,7 +1523,7 @@
 	  * As the irq is submitted after the interface is changed,
 	  * this is the best method i figured out.
 	  * Any others?*/
-	if(dec->interface == TTUSB_DEC_INTERFACE_IN)
+	if (dec->interface == TTUSB_DEC_INTERFACE_IN)
 		usb_kill_urb(dec->irq_urb);
 
 	usb_free_urb(dec->irq_urb);
@@ -1521,7 +1531,10 @@
 	usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
 		           dec->irq_buffer, dec->irq_dma_handle);
 
-	input_unregister_device(&dec->rc_input_dev);
+	if (dec->rc_input_dev) {
+		input_unregister_device(dec->rc_input_dev);
+		dec->rc_input_dev = NULL;
+	}
 }
 
 
@@ -1659,7 +1672,7 @@
 
 	ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
 
-	if(enable_rc)
+	if (enable_rc)
 		ttusb_init_rc(dec);
 
 	return 0;
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index df79d5e..e092140 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include "miropcm20-rds-core.h"
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 7a312f7..e0e7c7a 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -240,7 +240,7 @@
 
 /* for gpio-connected remote control */
 struct bttv_input {
-	struct input_dev      dev;
+	struct input_dev      *dev;
 	struct ir_input_state ir;
 	char                  name[32];
 	char                  phys[32];
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index d81b21d..c27fe4c3 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -260,7 +260,7 @@
 
 struct cx88_IR {
 	struct cx88_core *core;
-	struct input_dev input;
+	struct input_dev *input;
 	struct ir_input_state ir;
 	char name[32];
 	char phys[32];
@@ -315,23 +315,23 @@
 	if (ir->mask_keydown) {
 		/* bit set on keydown */
 		if (gpio & ir->mask_keydown) {
-			ir_input_keydown(&ir->input, &ir->ir, data, data);
+			ir_input_keydown(ir->input, &ir->ir, data, data);
 		} else {
-			ir_input_nokey(&ir->input, &ir->ir);
+			ir_input_nokey(ir->input, &ir->ir);
 		}
 
 	} else if (ir->mask_keyup) {
 		/* bit cleared on keydown */
 		if (0 == (gpio & ir->mask_keyup)) {
-			ir_input_keydown(&ir->input, &ir->ir, data, data);
+			ir_input_keydown(ir->input, &ir->ir, data, data);
 		} else {
-			ir_input_nokey(&ir->input, &ir->ir);
+			ir_input_nokey(ir->input, &ir->ir);
 		}
 
 	} else {
 		/* can't distinguish keydown/up :-/ */
-		ir_input_keydown(&ir->input, &ir->ir, data, data);
-		ir_input_nokey(&ir->input, &ir->ir);
+		ir_input_keydown(ir->input, &ir->ir, data, data);
+		ir_input_nokey(ir->input, &ir->ir);
 	}
 }
 
@@ -357,13 +357,19 @@
 int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 {
 	struct cx88_IR *ir;
+	struct input_dev *input_dev;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	int ir_type = IR_TYPE_OTHER;
 
-	ir = kmalloc(sizeof(*ir), GFP_KERNEL);
-	if (NULL == ir)
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ir || !input_dev) {
+		kfree(ir);
+		input_free_device(input_dev);
 		return -ENOMEM;
-	memset(ir, 0, sizeof(*ir));
+	}
+
+	ir->input = input_dev;
 
 	/* detect & configure */
 	switch (core->board) {
@@ -425,6 +431,7 @@
 
 	if (NULL == ir_codes) {
 		kfree(ir);
+		input_free_device(input_dev);
 		return -ENODEV;
 	}
 
@@ -433,19 +440,19 @@
 		 cx88_boards[core->board].name);
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
 
-	ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
-	ir->input.name = ir->name;
-	ir->input.phys = ir->phys;
-	ir->input.id.bustype = BUS_PCI;
-	ir->input.id.version = 1;
+	ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	input_dev->name = ir->name;
+	input_dev->phys = ir->phys;
+	input_dev->id.bustype = BUS_PCI;
+	input_dev->id.version = 1;
 	if (pci->subsystem_vendor) {
-		ir->input.id.vendor = pci->subsystem_vendor;
-		ir->input.id.product = pci->subsystem_device;
+		input_dev->id.vendor = pci->subsystem_vendor;
+		input_dev->id.product = pci->subsystem_device;
 	} else {
-		ir->input.id.vendor = pci->vendor;
-		ir->input.id.product = pci->device;
+		input_dev->id.vendor = pci->vendor;
+		input_dev->id.product = pci->device;
 	}
-	ir->input.dev = &pci->dev;
+	input_dev->cdev.dev = &pci->dev;
 
 	/* record handles to ourself */
 	ir->core = core;
@@ -465,8 +472,7 @@
 	}
 
 	/* all done */
-	input_register_device(&ir->input);
-	printk("%s: registered IR remote control\n", core->name);
+	input_register_device(ir->input);
 
 	return 0;
 }
@@ -484,7 +490,7 @@
 		flush_scheduled_work();
 	}
 
-	input_unregister_device(&ir->input);
+	input_unregister_device(ir->input);
 	kfree(ir);
 
 	/* done */
@@ -515,7 +521,7 @@
 	if (!ir->scount) {
 		/* nothing to sample */
 		if (ir->ir.keypressed && time_after(jiffies, ir->release))
-			ir_input_nokey(&ir->input, &ir->ir);
+			ir_input_nokey(ir->input, &ir->ir);
 		return;
 	}
 
@@ -557,7 +563,7 @@
 
 		ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f);
 
-		ir_input_keydown(&ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
+		ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
 		ir->release = jiffies + msecs_to_jiffies(120);
 		break;
 	case CX88_BOARD_HAUPPAUGE:
@@ -566,7 +572,7 @@
 		ir_dprintk("biphase decoded: %x\n", ircode);
 		if ((ircode & 0xfffff000) != 0x3000)
 			break;
-		ir_input_keydown(&ir->input, &ir->ir, ircode & 0x3f, ircode);
+		ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode);
 		ir->release = jiffies + msecs_to_jiffies(120);
 		break;
 	}
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index b2b0384..26dd06e 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -9,16 +9,16 @@
  *  published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include <linux/videodev.h>
 /* IndyCam decodes stream of photons into digital image representation ;-) */
@@ -44,8 +44,6 @@
 #define indycam_regdump(client)
 #endif
 
-#define VINO_ADAPTER	(I2C_ALGO_SGI | I2C_HW_SGI_VINO)
-
 struct indycam {
 	struct i2c_client *client;
 	int version;
@@ -300,7 +298,7 @@
 static int indycam_probe(struct i2c_adapter *adap)
 {
 	/* Indy specific crap */
-	if (adap->id == VINO_ADAPTER)
+	if (adap->id == I2C_HW_SGI_VINO)
 		return indycam_attach(adap, INDYCAM_ADDR, 0);
 	/* Feel free to add probe here :-) */
 	return -ENODEV;
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index cf292da..234151e 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -158,7 +158,7 @@
 
 struct IR {
 	struct bttv_sub_device  *sub;
-	struct input_dev        input;
+	struct input_dev        *input;
 	struct ir_input_state   ir;
 	char                    name[32];
 	char                    phys[32];
@@ -217,23 +217,23 @@
 	if (ir->mask_keydown) {
 		/* bit set on keydown */
 		if (gpio & ir->mask_keydown) {
-			ir_input_keydown(&ir->input,&ir->ir,data,data);
+			ir_input_keydown(ir->input, &ir->ir, data, data);
 		} else {
-			ir_input_nokey(&ir->input,&ir->ir);
+			ir_input_nokey(ir->input, &ir->ir);
 		}
 
 	} else if (ir->mask_keyup) {
 		/* bit cleared on keydown */
 		if (0 == (gpio & ir->mask_keyup)) {
-			ir_input_keydown(&ir->input,&ir->ir,data,data);
+			ir_input_keydown(ir->input, &ir->ir, data, data);
 		} else {
-			ir_input_nokey(&ir->input,&ir->ir);
+			ir_input_nokey(ir->input, &ir->ir);
 		}
 
 	} else {
 		/* can't disturgissh keydown/up :-/ */
-		ir_input_keydown(&ir->input,&ir->ir,data,data);
-		ir_input_nokey(&ir->input,&ir->ir);
+		ir_input_keydown(ir->input, &ir->ir, data, data);
+		ir_input_nokey(ir->input, &ir->ir);
 	}
 }
 
@@ -268,13 +268,17 @@
 {
 	struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
 	struct IR *ir;
+	struct input_dev *input_dev;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	int ir_type = IR_TYPE_OTHER;
 
-	ir = kmalloc(sizeof(*ir),GFP_KERNEL);
-	if (NULL == ir)
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ir || !input_dev) {
+		kfree(ir);
+		input_free_device(input_dev);
 		return -ENOMEM;
-	memset(ir,0,sizeof(*ir));
+	}
 
 	/* detect & configure */
 	switch (sub->core->type) {
@@ -328,6 +332,7 @@
 	}
 	if (NULL == ir_codes) {
 		kfree(ir);
+		input_free_device(input_dev);
 		return -ENODEV;
 	}
 
@@ -341,19 +346,19 @@
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
 		 pci_name(sub->core->pci));
 
-	ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
-	ir->input.name = ir->name;
-	ir->input.phys = ir->phys;
-	ir->input.id.bustype = BUS_PCI;
-	ir->input.id.version = 1;
+	ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	input_dev->name = ir->name;
+	input_dev->phys = ir->phys;
+	input_dev->id.bustype = BUS_PCI;
+	input_dev->id.version = 1;
 	if (sub->core->pci->subsystem_vendor) {
-		ir->input.id.vendor  = sub->core->pci->subsystem_vendor;
-		ir->input.id.product = sub->core->pci->subsystem_device;
+		input_dev->id.vendor  = sub->core->pci->subsystem_vendor;
+		input_dev->id.product = sub->core->pci->subsystem_device;
 	} else {
-		ir->input.id.vendor  = sub->core->pci->vendor;
-		ir->input.id.product = sub->core->pci->device;
+		input_dev->id.vendor  = sub->core->pci->vendor;
+		input_dev->id.product = sub->core->pci->device;
 	}
-	ir->input.dev = &sub->core->pci->dev;
+	input_dev->cdev.dev = &sub->core->pci->dev;
 
 	if (ir->polling) {
 		INIT_WORK(&ir->work, ir_work, ir);
@@ -364,9 +369,8 @@
 	}
 
 	/* all done */
-	dev_set_drvdata(dev,ir);
-	input_register_device(&ir->input);
-	printk(DEVNAME ": %s detected at %s\n",ir->input.name,ir->input.phys);
+	dev_set_drvdata(dev, ir);
+	input_register_device(ir->input);
 
 	return 0;
 }
@@ -380,7 +384,7 @@
 		flush_scheduled_work();
 	}
 
-	input_unregister_device(&ir->input);
+	input_unregister_device(ir->input);
 	kfree(ir);
 	return 0;
 }
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 67105b9..9703d3d 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -121,10 +121,9 @@
 
 };
 
-struct IR;
 struct IR {
 	struct i2c_client      c;
-	struct input_dev       input;
+	struct input_dev       *input;
 	struct ir_input_state  ir;
 
 	struct work_struct     work;
@@ -271,9 +270,9 @@
 	}
 
 	if (0 == rc) {
-		ir_input_nokey(&ir->input,&ir->ir);
+		ir_input_nokey(ir->input, &ir->ir);
 	} else {
-		ir_input_keydown(&ir->input,&ir->ir, ir_key, ir_raw);
+		ir_input_keydown(ir->input, &ir->ir, ir_key, ir_raw);
 	}
 }
 
@@ -318,11 +317,18 @@
 	char *name;
 	int ir_type;
         struct IR *ir;
+	struct input_dev *input_dev;
 
-        if (NULL == (ir = kmalloc(sizeof(struct IR),GFP_KERNEL)))
+	ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ir || !input_dev) {
+		kfree(ir);
+		input_free_device(input_dev);
                 return -ENOMEM;
-	memset(ir,0,sizeof(*ir));
+	}
+
 	ir->c = client_template;
+	ir->input = input_dev;
 
 	i2c_set_clientdata(&ir->c, ir);
 	ir->c.adapter = adap;
@@ -375,13 +381,12 @@
 		 ir->c.dev.bus_id);
 
 	/* init + register input device */
-	ir_input_init(&ir->input,&ir->ir,ir_type,ir_codes);
-	ir->input.id.bustype = BUS_I2C;
-	ir->input.name       = ir->c.name;
-	ir->input.phys       = ir->phys;
-	input_register_device(&ir->input);
-	printk(DEVNAME ": %s detected at %s [%s]\n",
-	       ir->input.name,ir->input.phys,adap->name);
+	ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	input_dev->id.bustype	= BUS_I2C;
+	input_dev->name		= ir->c.name;
+	input_dev->phys		= ir->phys;
+
+	input_register_device(ir->input);
 
 	/* start polling via eventd */
 	INIT_WORK(&ir->work, ir_work, ir);
@@ -402,7 +407,7 @@
 	flush_scheduled_work();
 
 	/* unregister devices */
-	input_unregister_device(&ir->input);
+	input_unregister_device(ir->input);
 	i2c_detach_client(&ir->c);
 
 	/* free memory */
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index f0d43fc..262890c 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -1420,8 +1420,8 @@
 static int msp_probe(struct i2c_adapter *adap);
 static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
 
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level);
-static int msp_resume(struct device * dev, u32 level);
+static int msp_suspend(struct device * dev, pm_message_t state);
+static int msp_resume(struct device * dev);
 
 static void msp_wake_thread(struct i2c_client *client);
 
@@ -1821,7 +1821,7 @@
 	return 0;
 }
 
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
+static int msp_suspend(struct device * dev, pm_message_t state)
 {
 	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
 
@@ -1830,7 +1830,7 @@
 	return 0;
 }
 
-static int msp_resume(struct device * dev, u32 level)
+static int msp_resume(struct device * dev)
 {
 	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
 
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 1f456c4..242cb23 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -425,9 +425,9 @@
 
 	if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 	    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-		ir_input_keydown(&ir->dev,&ir->ir,data,data);
+		ir_input_keydown(ir->dev, &ir->ir, data, data);
 	} else {
-		ir_input_nokey(&ir->dev,&ir->ir);
+		ir_input_nokey(ir->dev, &ir->ir);
 	}
 	return 0;
 }
@@ -456,6 +456,7 @@
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
 	struct saa7134_ir *ir;
+	struct input_dev *input_dev;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	u32 mask_keycode = 0;
 	u32 mask_keydown = 0;
@@ -535,10 +536,13 @@
 		return -ENODEV;
 	}
 
-	ir = kmalloc(sizeof(*ir),GFP_KERNEL);
-	if (NULL == ir)
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ir || !input_dev) {
+		kfree(ir);
+		input_free_device(input_dev);
 		return -ENOMEM;
-	memset(ir,0,sizeof(*ir));
+	}
 
 	/* init hardware-specific stuff */
 	ir->mask_keycode = mask_keycode;
@@ -552,19 +556,19 @@
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
 		 pci_name(dev->pci));
 
-	ir_input_init(&ir->dev, &ir->ir, ir_type, ir_codes);
-	ir->dev.name = ir->name;
-	ir->dev.phys = ir->phys;
-	ir->dev.id.bustype = BUS_PCI;
-	ir->dev.id.version = 1;
+	ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	input_dev->name = ir->name;
+	input_dev->phys = ir->phys;
+	input_dev->id.bustype = BUS_PCI;
+	input_dev->id.version = 1;
 	if (dev->pci->subsystem_vendor) {
-		ir->dev.id.vendor  = dev->pci->subsystem_vendor;
-		ir->dev.id.product = dev->pci->subsystem_device;
+		input_dev->id.vendor  = dev->pci->subsystem_vendor;
+		input_dev->id.product = dev->pci->subsystem_device;
 	} else {
-		ir->dev.id.vendor  = dev->pci->vendor;
-		ir->dev.id.product = dev->pci->device;
+		input_dev->id.vendor  = dev->pci->vendor;
+		input_dev->id.product = dev->pci->device;
 	}
-	ir->dev.dev = &dev->pci->dev;
+	input_dev->cdev.dev = &dev->pci->dev;
 
 	/* all done */
 	dev->remote = ir;
@@ -576,8 +580,7 @@
 		add_timer(&ir->timer);
 	}
 
-	input_register_device(&dev->remote->dev);
-	printk("%s: registered input device for IR\n",dev->name);
+	input_register_device(ir->dev);
 	return 0;
 }
 
@@ -586,9 +589,9 @@
 	if (NULL == dev->remote)
 		return;
 
-	input_unregister_device(&dev->remote->dev);
 	if (dev->remote->polling)
 		del_timer_sync(&dev->remote->timer);
+	input_unregister_device(dev->remote->dev);
 	kfree(dev->remote);
 	dev->remote = NULL;
 }
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 3ea0914..860b895 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -351,7 +351,7 @@
 
 /* IR input */
 struct saa7134_ir {
-	struct input_dev           dev;
+	struct input_dev           *dev;
 	struct ir_input_state      ir;
 	char                       name[32];
 	char                       phys[32];
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index 454f5c1..3ddbb62 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -9,16 +9,16 @@
  *  published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include <linux/videodev.h>
 #include <linux/video_decoder.h>
@@ -33,8 +33,6 @@
 MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
 MODULE_LICENSE("GPL");
 
-#define VINO_ADAPTER	(I2C_ALGO_SGI | I2C_HW_SGI_VINO)
-
 struct saa7191 {
 	struct i2c_client *client;
 
@@ -337,7 +335,7 @@
 static int saa7191_probe(struct i2c_adapter *adap)
 {
 	/* Always connected to VINO */
-	if (adap->id == VINO_ADAPTER)
+	if (adap->id == I2C_HW_SGI_VINO)
 		return saa7191_attach(adap, SAA7191_ADDR, 0);
 	/* Feel free to add probe here :-) */
 	return -ENODEV;
@@ -364,7 +362,7 @@
 
 		cap->flags  = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
 			      VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
-		cap->inputs = (client->adapter->id == VINO_ADAPTER) ? 2 : 1;
+		cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1;
 		cap->outputs = 1;
 		break;
 	}
@@ -422,7 +420,7 @@
 		int *iarg = arg;
 
 		switch (client->adapter->id) {
-		case VINO_ADAPTER:
+		case I2C_HW_SGI_VINO:
 			return saa7191_set_input(client, *iarg);
 		default:
 			if (*iarg != 0)
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 0456dda..94053f1 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -784,13 +784,13 @@
 	return 0;
 }
 
-static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tda9887_suspend(struct device * dev, pm_message_t state)
 {
 	dprintk("tda9887: suspend\n");
 	return 0;
 }
 
-static int tda9887_resume(struct device * dev, u32 level)
+static int tda9887_resume(struct device * dev)
 {
 	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
 	struct tda9887 *t = i2c_get_clientdata(c);
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 0557202..ad85bef 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -697,7 +697,7 @@
 	return 0;
 }
 
-static int tuner_suspend(struct device *dev, pm_message_t state, u32 level)
+static int tuner_suspend(struct device *dev, pm_message_t state)
 {
 	struct i2c_client *c = container_of (dev, struct i2c_client, dev);
 	struct tuner *t = i2c_get_clientdata (c);
@@ -707,7 +707,7 @@
 	return 0;
 }
 
-static int tuner_resume(struct device *dev, u32 level)
+static int tuner_resume(struct device *dev)
 {
 	struct i2c_client *c = container_of (dev, struct i2c_client, dev);
 	struct tuner *t = i2c_get_clientdata (c);
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index d8a0f76..ed4394e 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -26,14 +26,15 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/time.h>
 #include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/version.h>
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index c5bcfd7..9eefedb 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -36,9 +36,6 @@
 extern void i2o_device_remove(struct i2o_device *);
 extern int i2o_device_parse_lct(struct i2o_controller *);
 
-extern int i2o_device_init(void);
-extern void i2o_device_exit(void);
-
 /* IOP */
 extern struct i2o_controller *i2o_iop_alloc(void);
 extern void i2o_iop_free(struct i2o_controller *);
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 018ca88..40d4ea8 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -90,7 +90,7 @@
 	};
 
 	if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
-		printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.",
+		printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
 		       req_status);
 	else
 		printk(KERN_DEBUG "TRANSPORT_%s.\n",
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 21f16ba..8eb50cd 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -16,6 +16,8 @@
 #include <linux/module.h>
 #include <linux/i2o.h>
 #include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include "core.h"
 
 /**
@@ -45,10 +47,10 @@
 	writel(type, &msg->body[0]);
 
 	return i2o_msg_post_wait(dev->iop, m, 60);
-};
+}
 
 /**
- * 	i2o_device_claim - claim a device for use by an OSM
+ *	i2o_device_claim - claim a device for use by an OSM
  *	@dev: I2O device to claim
  *	@drv: I2O driver which wants to claim the device
  *
@@ -73,7 +75,7 @@
 	up(&dev->lock);
 
 	return rc;
-};
+}
 
 /**
  *	i2o_device_claim_release - release a device that the OSM is using
@@ -119,7 +121,8 @@
 	up(&dev->lock);
 
 	return rc;
-};
+}
+
 
 /**
  *	i2o_device_release - release the memory for a I2O device
@@ -135,39 +138,47 @@
 	pr_debug("i2o: device %s released\n", dev->bus_id);
 
 	kfree(i2o_dev);
-};
+}
+
 
 /**
- *	i2o_device_class_release - Remove I2O device attributes
- *	@cd: I2O class device which is added to the I2O device class
+ *	i2o_device_class_show_class_id - Displays class id of I2O device
+ *	@cd: class device of which the class id should be displayed
+ *	@buf: buffer into which the class id should be printed
  *
- *	Removes attributes from the I2O device again. Also search each device
- *	on the controller for I2O devices which refert to this device as parent
- *	or user and remove this links also.
+ *	Returns the number of bytes which are printed into the buffer.
  */
-static void i2o_device_class_release(struct class_device *cd)
+static ssize_t i2o_device_show_class_id(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
 {
-	struct i2o_device *i2o_dev, *tmp;
-	struct i2o_controller *c;
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
 
-	i2o_dev = to_i2o_device(cd->dev);
-	c = i2o_dev->iop;
+	sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);
+	return strlen(buf) + 1;
+}
 
-	sysfs_remove_link(&i2o_dev->device.kobj, "parent");
-	sysfs_remove_link(&i2o_dev->device.kobj, "user");
+/**
+ *	i2o_device_class_show_tid - Displays TID of I2O device
+ *	@cd: class device of which the TID should be displayed
+ *	@buf: buffer into which the class id should be printed
+ *
+ *	Returns the number of bytes which are printed into the buffer.
+ */
+static ssize_t i2o_device_show_tid(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
 
-	list_for_each_entry(tmp, &c->devices, list) {
-		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
-			sysfs_remove_link(&tmp->device.kobj, "parent");
-		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
-			sysfs_remove_link(&tmp->device.kobj, "user");
-	}
-};
+	sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);
+	return strlen(buf) + 1;
+}
 
-/* I2O device class */
-static struct class i2o_device_class = {
-	.name = "i2o_device",
-	.release = i2o_device_class_release
+struct device_attribute i2o_device_attrs[] = {
+	__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
+	__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
+	__ATTR_NULL
 };
 
 /**
@@ -193,11 +204,69 @@
 
 	dev->device.bus = &i2o_bus_type;
 	dev->device.release = &i2o_device_release;
-	dev->classdev.class = &i2o_device_class;
-	dev->classdev.dev = &dev->device;
 
 	return dev;
-};
+}
+
+/**
+ *	i2o_setup_sysfs_links - Adds attributes to the I2O device
+ *	@cd: I2O class device which is added to the I2O device class
+ *
+ *	This function get called when a I2O device is added to the class. It
+ *	creates the attributes for each device and creates user/parent symlink
+ *	if necessary.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev)
+{
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_device *tmp;
+
+	/* create user entries for this device */
+	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+	if (tmp && tmp != i2o_dev)
+		sysfs_create_link(&i2o_dev->device.kobj,
+				  &tmp->device.kobj, "user");
+
+	/* create user entries refering to this device */
+	list_for_each_entry(tmp, &c->devices, list)
+		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid &&
+		    tmp != i2o_dev)
+			sysfs_create_link(&tmp->device.kobj,
+					  &i2o_dev->device.kobj, "user");
+
+	/* create parent entries for this device */
+	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+	if (tmp && tmp != i2o_dev)
+		sysfs_create_link(&i2o_dev->device.kobj,
+				  &tmp->device.kobj, "parent");
+
+	/* create parent entries refering to this device */
+	list_for_each_entry(tmp, &c->devices, list)
+		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid &&
+		    tmp != i2o_dev)
+		sysfs_create_link(&tmp->device.kobj,
+				  &i2o_dev->device.kobj, "parent");
+}
+
+static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
+{
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_device *tmp;
+
+	sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+	sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+	list_for_each_entry(tmp, &c->devices, list) {
+		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+			sysfs_remove_link(&tmp->device.kobj, "parent");
+		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+			sysfs_remove_link(&tmp->device.kobj, "user");
+	}
+}
+
+
 
 /**
  *	i2o_device_add - allocate a new I2O device and add it to the IOP
@@ -222,28 +291,25 @@
 	}
 
 	dev->lct_data = *entry;
+	dev->iop = c;
 
 	snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
 		 dev->lct_data.tid);
 
-	snprintf(dev->classdev.class_id, BUS_ID_SIZE, "%d:%03x", c->unit,
-		 dev->lct_data.tid);
-
-	dev->iop = c;
 	dev->device.parent = &c->device;
 
 	device_register(&dev->device);
 
 	list_add_tail(&dev->list, &c->devices);
 
-	class_device_register(&dev->classdev);
+	i2o_setup_sysfs_links(dev);
 
 	i2o_driver_notify_device_add_all(dev);
 
 	pr_debug("i2o: device %s added\n", dev->device.bus_id);
 
 	return dev;
-};
+}
 
 /**
  *	i2o_device_remove - remove an I2O device from the I2O core
@@ -256,10 +322,10 @@
 void i2o_device_remove(struct i2o_device *i2o_dev)
 {
 	i2o_driver_notify_device_remove_all(i2o_dev);
-	class_device_unregister(&i2o_dev->classdev);
+	i2o_remove_sysfs_links(i2o_dev);
 	list_del(&i2o_dev->list);
 	device_unregister(&i2o_dev->device);
-};
+}
 
 /**
  *	i2o_device_parse_lct - Parse a previously fetched LCT and create devices
@@ -337,99 +403,8 @@
 	up(&c->lct_lock);
 
 	return 0;
-};
+}
 
-/**
- *	i2o_device_class_show_class_id - Displays class id of I2O device
- *	@cd: class device of which the class id should be displayed
- *	@buf: buffer into which the class id should be printed
- *
- *	Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
-					      char *buf)
-{
-	struct i2o_device *dev = to_i2o_device(cd->dev);
-
-	sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
-	return strlen(buf) + 1;
-};
-
-/**
- *	i2o_device_class_show_tid - Displays TID of I2O device
- *	@cd: class device of which the TID should be displayed
- *	@buf: buffer into which the class id should be printed
- *
- *	Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
-{
-	struct i2o_device *dev = to_i2o_device(cd->dev);
-
-	sprintf(buf, "0x%03x\n", dev->lct_data.tid);
-	return strlen(buf) + 1;
-};
-
-/* I2O device class attributes */
-static CLASS_DEVICE_ATTR(class_id, S_IRUGO, i2o_device_class_show_class_id,
-			 NULL);
-static CLASS_DEVICE_ATTR(tid, S_IRUGO, i2o_device_class_show_tid, NULL);
-
-/**
- *	i2o_device_class_add - Adds attributes to the I2O device
- *	@cd: I2O class device which is added to the I2O device class
- *
- *	This function get called when a I2O device is added to the class. It
- *	creates the attributes for each device and creates user/parent symlink
- *	if necessary.
- *
- *	Returns 0 on success or negative error code on failure.
- */
-static int i2o_device_class_add(struct class_device *cd)
-{
-	struct i2o_device *i2o_dev, *tmp;
-	struct i2o_controller *c;
-
-	i2o_dev = to_i2o_device(cd->dev);
-	c = i2o_dev->iop;
-
-	class_device_create_file(cd, &class_device_attr_class_id);
-	class_device_create_file(cd, &class_device_attr_tid);
-
-	/* create user entries for this device */
-	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
-	if (tmp && (tmp != i2o_dev))
-		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
-				  "user");
-
-	/* create user entries refering to this device */
-	list_for_each_entry(tmp, &c->devices, list)
-	    if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
-		&& (tmp != i2o_dev))
-		sysfs_create_link(&tmp->device.kobj,
-				  &i2o_dev->device.kobj, "user");
-
-	/* create parent entries for this device */
-	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
-	if (tmp && (tmp != i2o_dev))
-		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
-				  "parent");
-
-	/* create parent entries refering to this device */
-	list_for_each_entry(tmp, &c->devices, list)
-	    if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
-		&& (tmp != i2o_dev))
-		sysfs_create_link(&tmp->device.kobj,
-				  &i2o_dev->device.kobj, "parent");
-
-	return 0;
-};
-
-/* I2O device class interface */
-static struct class_interface i2o_device_class_interface = {
-	.class = &i2o_device_class,
-	.add = i2o_device_class_add
-};
 
 /*
  *	Run time support routines
@@ -553,11 +528,11 @@
 }
 
 /*
- * 	if oper == I2O_PARAMS_TABLE_GET, get from all rows
- * 		if fieldcount == -1 return all fields
+ *	if oper == I2O_PARAMS_TABLE_GET, get from all rows
+ *		if fieldcount == -1 return all fields
  *			ibuf and ibuflen are unused (use NULL, 0)
- * 		else return specific fields
- *  			ibuf contains fieldindexes
+ *		else return specific fields
+ *			ibuf contains fieldindexes
  *
  * 	if oper == I2O_PARAMS_LIST_GET, get from specific rows
  * 		if fieldcount == -1 return all fields
@@ -602,35 +577,6 @@
 	return size;
 }
 
-/**
- *	i2o_device_init - Initialize I2O devices
- *
- *	Registers the I2O device class.
- *
- *	Returns 0 on success or negative error code on failure.
- */
-int i2o_device_init(void)
-{
-	int rc;
-
-	rc = class_register(&i2o_device_class);
-	if (rc)
-		return rc;
-
-	return class_interface_register(&i2o_device_class_interface);
-};
-
-/**
- *	i2o_device_exit - I2O devices exit function
- *
- *	Unregisters the I2O device class.
- */
-void i2o_device_exit(void)
-{
-	class_interface_register(&i2o_device_class_interface);
-	class_unregister(&i2o_device_class);
-};
-
 EXPORT_SYMBOL(i2o_device_claim);
 EXPORT_SYMBOL(i2o_device_claim_release);
 EXPORT_SYMBOL(i2o_parm_field_get);
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 739bfde..0fb9c4e 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -17,6 +17,9 @@
 #include <linux/module.h>
 #include <linux/rwsem.h>
 #include <linux/i2o.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include "core.h"
 
 #define OSM_NAME	"i2o"
@@ -58,9 +61,12 @@
 };
 
 /* I2O bus type */
+extern struct device_attribute i2o_device_attrs[];
+
 struct bus_type i2o_bus_type = {
 	.name = "i2o",
 	.match = i2o_bus_match,
+	.dev_attrs = i2o_device_attrs,
 };
 
 /**
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index bda2c62..b675b4e 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -30,6 +30,10 @@
 #include <linux/module.h>
 #include <linux/i2o.h>
 #include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/param.h>		/* HZ */
 #include "core.h"
 
 #define OSM_NAME "exec-osm"
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 42f8b81..61b837d 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/i2o.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include "core.h"
 
 #define OSM_NAME	"i2o"
@@ -833,6 +834,7 @@
 	list_for_each_entry_safe(dev, tmp, &c->devices, list)
 	    i2o_device_remove(dev);
 
+	class_device_unregister(c->classdev);
 	device_del(&c->device);
 
 	/* Ask the IOP to switch to RESET state */
@@ -1077,9 +1079,7 @@
 };
 
 /* I2O controller class */
-static struct class i2o_controller_class = {
-	.name = "i2o_controller",
-};
+static struct class *i2o_controller_class;
 
 /**
  *	i2o_iop_alloc - Allocate and initialize a i2o_controller struct
@@ -1110,14 +1110,10 @@
 	sprintf(c->name, "iop%d", c->unit);
 
 	device_initialize(&c->device);
-	class_device_initialize(&c->classdev);
 
 	c->device.release = &i2o_iop_release;
-	c->classdev.class = &i2o_controller_class;
-	c->classdev.dev = &c->device;
 
 	snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
-	snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit);
 
 #if BITS_PER_LONG == 64
 	spin_lock_init(&c->context_list_lock);
@@ -1146,7 +1142,9 @@
 		goto iop_reset;
 	}
 
-	if ((rc = class_device_add(&c->classdev))) {
+	c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
+			&c->device, "iop%d", c->unit);
+	if (IS_ERR(c->classdev)) {
 		osm_err("%s: could not add controller class\n", c->name);
 		goto device_del;
 	}
@@ -1184,7 +1182,7 @@
 	return 0;
 
       class_del:
-	class_device_del(&c->classdev);
+	class_device_unregister(c->classdev);
 
       device_del:
 	device_del(&c->device);
@@ -1246,13 +1244,10 @@
 
 	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
 
-	rc = i2o_device_init();
-	if (rc)
-		goto exit;
-
-	if ((rc = class_register(&i2o_controller_class))) {
+	i2o_controller_class = class_create(THIS_MODULE, "i2o_controller");
+	if (IS_ERR(i2o_controller_class)) {
 		osm_err("can't register class i2o_controller\n");
-		goto device_exit;
+		goto exit;
 	}
 
 	if ((rc = i2o_driver_init()))
@@ -1273,10 +1268,7 @@
 	i2o_driver_exit();
 
       class_exit:
-	class_unregister(&i2o_controller_class);
-
-      device_exit:
-	i2o_device_exit();
+	class_destroy(i2o_controller_class);
 
       exit:
 	return rc;
@@ -1292,8 +1284,7 @@
 	i2o_pci_exit();
 	i2o_exec_exit();
 	i2o_driver_exit();
-	class_unregister(&i2o_controller_class);
-	i2o_device_exit();
+	class_destroy(i2o_controller_class);
 };
 
 module_init(i2o_iop_init);
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index e9806fb..720e7a3 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -219,26 +219,24 @@
 	return 0;
 }
 
-static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state, u32 level)
+static int mcp_sa11x0_suspend(struct device *dev, pm_message_t state)
 {
 	struct mcp *mcp = dev_get_drvdata(dev);
 
-	if (level == SUSPEND_DISABLE) {
-		priv(mcp)->mccr0 = Ser4MCCR0;
-		priv(mcp)->mccr1 = Ser4MCCR1;
-		Ser4MCCR0 &= ~MCCR0_MCE;
-	}
+	priv(mcp)->mccr0 = Ser4MCCR0;
+	priv(mcp)->mccr1 = Ser4MCCR1;
+	Ser4MCCR0 &= ~MCCR0_MCE;
+
 	return 0;
 }
 
-static int mcp_sa11x0_resume(struct device *dev, u32 level)
+static int mcp_sa11x0_resume(struct device *dev)
 {
 	struct mcp *mcp = dev_get_drvdata(dev);
 
-	if (level == RESUME_RESTORE_STATE) {
-		Ser4MCCR1 = priv(mcp)->mccr1;
-		Ser4MCCR0 = priv(mcp)->mccr0;
-	}
+	Ser4MCCR1 = priv(mcp)->mccr1;
+	Ser4MCCR0 = priv(mcp)->mccr0;
+
 	return 0;
 }
 
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index a260f83..a984c0e 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -32,15 +32,18 @@
 #include <linux/suspend.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
+#include <linux/delay.h>
 
 #include <asm/dma.h>
 #include <asm/semaphore.h>
+#include <asm/arch/collie.h>
+#include <asm/mach-types.h>
 
 #include "ucb1x00.h"
 
 
 struct ucb1x00_ts {
-	struct input_dev	idev;
+	struct input_dev	*idev;
 	struct ucb1x00		*ucb;
 
 	wait_queue_head_t	irq_wait;
@@ -56,16 +59,16 @@
 
 static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
 {
-	input_report_abs(&ts->idev, ABS_X, x);
-	input_report_abs(&ts->idev, ABS_Y, y);
-	input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
-	input_sync(&ts->idev);
+	input_report_abs(ts->idev, ABS_X, x);
+	input_report_abs(ts->idev, ABS_Y, y);
+	input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+	input_sync(ts->idev);
 }
 
 static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
 {
-	input_report_abs(&ts->idev, ABS_PRESSURE, 0);
-	input_sync(&ts->idev);
+	input_report_abs(ts->idev, ABS_PRESSURE, 0);
+	input_sync(ts->idev);
 }
 
 /*
@@ -85,12 +88,23 @@
  */
 static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
 {
-	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-			UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	if (machine_is_collie()) {
+		ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0);
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				  UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW |
+				  UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-	return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+		udelay(55);
+
+		return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync);
+	} else {
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				  UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+				  UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+				  UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+
+		return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+	}
 }
 
 /*
@@ -101,12 +115,16 @@
  */
 static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
 {
-	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	if (machine_is_collie())
+		ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
+	else {
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				  UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+				  UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				  UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+				  UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	}
 	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
 			UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
 			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
@@ -124,12 +142,17 @@
  */
 static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
 {
-	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-			UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	if (machine_is_collie())
+		ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK);
+	else {
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				  UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+				  UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+		ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+				  UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+				  UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+	}
+
 	ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
 			UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
 			UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
@@ -163,6 +186,15 @@
 	return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
 }
 
+static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts)
+{
+	unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
+	if (machine_is_collie())
+		return (!(val & (UCB_TS_CR_TSPX_LOW)));
+	else
+		return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW));
+}
+
 /*
  * This is a RT kernel thread that handles the ADC accesses
  * (mainly so we can use semaphores in the UCB1200 core code
@@ -186,7 +218,7 @@
 
 	add_wait_queue(&ts->irq_wait, &wait);
 	while (!kthread_should_stop()) {
-		unsigned int x, y, p, val;
+		unsigned int x, y, p;
 		signed long timeout;
 
 		ts->restart = 0;
@@ -206,12 +238,12 @@
 		msleep(10);
 
 		ucb1x00_enable(ts->ucb);
-		val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
 
-		if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
+
+		if (ucb1x00_ts_pen_down(ts)) {
 			set_task_state(tsk, TASK_INTERRUPTIBLE);
 
-			ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+			ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
 			ucb1x00_disable(ts->ucb);
 
 			/*
@@ -341,26 +373,30 @@
 {
 	struct ucb1x00_ts *ts;
 
-	ts = kmalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
+	ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
 	if (!ts)
 		return -ENOMEM;
 
-	memset(ts, 0, sizeof(struct ucb1x00_ts));
+	ts->idev = input_allocate_device();
+	if (!ts->idev) {
+		kfree(ts);
+		return -ENOMEM;
+	}
 
 	ts->ucb = dev->ucb;
 	ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
 
-	ts->idev.name       = "Touchscreen panel";
-	ts->idev.id.product = ts->ucb->id;
-	ts->idev.open       = ucb1x00_ts_open;
-	ts->idev.close      = ucb1x00_ts_close;
+	ts->idev->name       = "Touchscreen panel";
+	ts->idev->id.product = ts->ucb->id;
+	ts->idev->open       = ucb1x00_ts_open;
+	ts->idev->close      = ucb1x00_ts_close;
 
-	__set_bit(EV_ABS, ts->idev.evbit);
-	__set_bit(ABS_X, ts->idev.absbit);
-	__set_bit(ABS_Y, ts->idev.absbit);
-	__set_bit(ABS_PRESSURE, ts->idev.absbit);
+	__set_bit(EV_ABS, ts->idev->evbit);
+	__set_bit(ABS_X, ts->idev->absbit);
+	__set_bit(ABS_Y, ts->idev->absbit);
+	__set_bit(ABS_PRESSURE, ts->idev->absbit);
 
-	input_register_device(&ts->idev);
+	input_register_device(ts->idev);
 
 	dev->priv = ts;
 
@@ -370,7 +406,8 @@
 static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
 {
 	struct ucb1x00_ts *ts = dev->priv;
-	input_unregister_device(&ts->idev);
+
+	input_unregister_device(ts->idev);
 	kfree(ts);
 }
 
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4991bbd..c483a86 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -60,4 +60,13 @@
 
 	  If unsure, say N.
 
+config MMC_AU1X
+	tristate "Alchemy AU1XX0 MMC Card Interface support"
+	depends on SOC_AU1X00 && MMC
+	help
+	  This selects the AMD Alchemy(R) Multimedia card interface.
+	  iIf you have a Alchemy platform with a MMC slot, say Y or M here.
+
+	  If unsure, say N.
+
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 89510c2..e351e71 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -18,5 +18,6 @@
 obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
+obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
new file mode 100644
index 0000000..aaf0463
--- /dev/null
+++ b/drivers/mmc/au1xmmc.c
@@ -0,0 +1,1026 @@
+/*
+ * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver
+ *
+ *  Copyright (c) 2005, Advanced Micro Devices, Inc.
+ *
+ *  Developed with help from the 2.4.30 MMC AU1XXX controller including
+ *  the following copyright notices:
+ *     Copyright (c) 2003-2004 Embedded Edge, LLC.
+ *     Portions Copyright (C) 2002 Embedix, Inc
+ *     Copyright 2002 Hewlett-Packard Company
+
+ *  2.6 version of this driver inspired by:
+ *     (drivers/mmc/wbsd.c) Copyright (C) 2004-2005 Pierre Ossman,
+ *     All Rights Reserved.
+ *     (drivers/mmc/pxa.c) Copyright (C) 2003 Russell King,
+ *     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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Why is a timer used to detect insert events?
+ *
+ * From the AU1100 MMC application guide:
+ * If the Au1100-based design is intended to support both MultiMediaCards
+ * and 1- or 4-data bit SecureDigital cards, then the solution is to
+ * connect a weak (560KOhm) pull-up resistor to connector pin 1.
+ * In doing so, a MMC card never enters SPI-mode communications,
+ * but now the SecureDigital card-detect feature of CD/DAT3 is ineffective
+ * (the low to high transition will not occur).
+ *
+ * So we use the timer to check the status manually.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/scatterlist.h>
+
+#include <au1xxx.h>
+#include "au1xmmc.h"
+
+#define DRIVER_NAME "au1xxx-mmc"
+
+/* Set this to enable special debugging macros */
+/* #define MMC_DEBUG */
+
+#ifdef MMC_DEBUG
+#define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
+#else
+#define DEBUG(fmt, idx, args...)
+#endif
+
+const struct {
+	u32 iobase;
+	u32 tx_devid, rx_devid;
+	u16 bcsrpwr;
+	u16 bcsrstatus;
+	u16 wpstatus;
+} au1xmmc_card_table[] = {
+	{ SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
+	  BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
+#ifndef CONFIG_MIPS_DB1200
+	{ SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
+	  BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
+#endif
+};
+
+#define AU1XMMC_CONTROLLER_COUNT \
+	(sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
+
+/* This array stores pointers for the hosts (used by the IRQ handler) */
+struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
+static int dma = 1;
+
+#ifdef MODULE
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
+#endif
+
+static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
+{
+	u32 val = au_readl(HOST_CONFIG(host));
+	val |= mask;
+	au_writel(val, HOST_CONFIG(host));
+	au_sync();
+}
+
+static inline void FLUSH_FIFO(struct au1xmmc_host *host)
+{
+	u32 val = au_readl(HOST_CONFIG2(host));
+
+	au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+	au_sync_delay(1);
+
+	/* SEND_STOP will turn off clock control - this re-enables it */
+	val &= ~SD_CONFIG2_DF;
+
+	au_writel(val, HOST_CONFIG2(host));
+	au_sync();
+}
+
+static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
+{
+	u32 val = au_readl(HOST_CONFIG(host));
+	val &= ~mask;
+	au_writel(val, HOST_CONFIG(host));
+	au_sync();
+}
+
+static inline void SEND_STOP(struct au1xmmc_host *host)
+{
+
+	/* We know the value of CONFIG2, so avoid a read we don't need */
+	u32 mask = SD_CONFIG2_EN;
+
+	WARN_ON(host->status != HOST_S_DATA);
+	host->status = HOST_S_STOP;
+
+	au_writel(mask | SD_CONFIG2_DF, HOST_CONFIG2(host));
+	au_sync();
+
+	/* Send the stop commmand */
+	au_writel(STOP_CMD, HOST_CMD(host));
+}
+
+static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
+{
+
+	u32 val = au1xmmc_card_table[host->id].bcsrpwr;
+
+	bcsr->board &= ~val;
+	if (state) bcsr->board |= val;
+
+	au_sync_delay(1);
+}
+
+static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
+{
+	return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus)
+		? 1 : 0;
+}
+
+static inline int au1xmmc_card_readonly(struct au1xmmc_host *host)
+{
+	return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
+		? 1 : 0;
+}
+
+static void au1xmmc_finish_request(struct au1xmmc_host *host)
+{
+
+	struct mmc_request *mrq = host->mrq;
+
+	host->mrq = NULL;
+	host->flags &= HOST_F_ACTIVE;
+
+	host->dma.len = 0;
+	host->dma.dir = 0;
+
+	host->pio.index  = 0;
+	host->pio.offset = 0;
+	host->pio.len = 0;
+
+	host->status = HOST_S_IDLE;
+
+	bcsr->disk_leds |= (1 << 8);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void au1xmmc_tasklet_finish(unsigned long param)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+	au1xmmc_finish_request(host);
+}
+
+static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
+				struct mmc_command *cmd)
+{
+
+	u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
+
+	switch(cmd->flags) {
+	case MMC_RSP_R1:
+		mmccmd |= SD_CMD_RT_1;
+		break;
+	case MMC_RSP_R1B:
+		mmccmd |= SD_CMD_RT_1B;
+		break;
+	case MMC_RSP_R2:
+		mmccmd |= SD_CMD_RT_2;
+		break;
+	case MMC_RSP_R3:
+		mmccmd |= SD_CMD_RT_3;
+		break;
+	}
+
+	switch(cmd->opcode) {
+	case MMC_READ_SINGLE_BLOCK:
+	case SD_APP_SEND_SCR:
+		mmccmd |= SD_CMD_CT_2;
+		break;
+	case MMC_READ_MULTIPLE_BLOCK:
+		mmccmd |= SD_CMD_CT_4;
+		break;
+	case MMC_WRITE_BLOCK:
+		mmccmd |= SD_CMD_CT_1;
+		break;
+
+	case MMC_WRITE_MULTIPLE_BLOCK:
+		mmccmd |= SD_CMD_CT_3;
+		break;
+	case MMC_STOP_TRANSMISSION:
+		mmccmd |= SD_CMD_CT_7;
+		break;
+	}
+
+	au_writel(cmd->arg, HOST_CMDARG(host));
+	au_sync();
+
+	if (wait)
+		IRQ_OFF(host, SD_CONFIG_CR);
+
+	au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+	au_sync();
+
+	/* Wait for the command to go on the line */
+
+	while(1) {
+		if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO))
+			break;
+	}
+
+	/* Wait for the command to come back */
+
+	if (wait) {
+		u32 status = au_readl(HOST_STATUS(host));
+
+		while(!(status & SD_STATUS_CR))
+			status = au_readl(HOST_STATUS(host));
+
+		/* Clear the CR status */
+		au_writel(SD_STATUS_CR, HOST_STATUS(host));
+
+		IRQ_ON(host, SD_CONFIG_CR);
+	}
+
+	return MMC_ERR_NONE;
+}
+
+static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
+{
+
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_data *data;
+	u32 crc;
+
+	WARN_ON(host->status != HOST_S_DATA && host->status != HOST_S_STOP);
+
+	if (host->mrq == NULL)
+		return;
+
+	data = mrq->cmd->data;
+
+	if (status == 0)
+		status = au_readl(HOST_STATUS(host));
+
+	/* The transaction is really over when the SD_STATUS_DB bit is clear */
+
+	while((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
+		status = au_readl(HOST_STATUS(host));
+
+	data->error = MMC_ERR_NONE;
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
+
+        /* Process any errors */
+
+	crc = (status & (SD_STATUS_WC | SD_STATUS_RC));
+	if (host->flags & HOST_F_XMIT)
+		crc |= ((status & 0x07) == 0x02) ? 0 : 1;
+
+	if (crc)
+		data->error = MMC_ERR_BADCRC;
+
+	/* Clear the CRC bits */
+	au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+
+	data->bytes_xfered = 0;
+
+	if (data->error == MMC_ERR_NONE) {
+		if (host->flags & HOST_F_DMA) {
+			u32 chan = DMA_CHANNEL(host);
+
+			chan_tab_t *c = *((chan_tab_t **) chan);
+			au1x_dma_chan_t *cp = c->chan_ptr;
+			data->bytes_xfered = cp->ddma_bytecnt;
+		}
+		else
+			data->bytes_xfered =
+				(data->blocks * (1 << data->blksz_bits)) -
+				host->pio.len;
+	}
+
+	au1xmmc_finish_request(host);
+}
+
+static void au1xmmc_tasklet_data(unsigned long param)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+
+	u32 status = au_readl(HOST_STATUS(host));
+	au1xmmc_data_complete(host, status);
+}
+
+#define AU1XMMC_MAX_TRANSFER 8
+
+static void au1xmmc_send_pio(struct au1xmmc_host *host)
+{
+
+	struct mmc_data *data = 0;
+	int sg_len, max, count = 0;
+	unsigned char *sg_ptr;
+	u32 status = 0;
+	struct scatterlist *sg;
+
+	data = host->mrq->data;
+
+	if (!(host->flags & HOST_F_XMIT))
+		return;
+
+	/* This is the pointer to the data buffer */
+	sg = &data->sg[host->pio.index];
+	sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+
+	/* This is the space left inside the buffer */
+	sg_len = data->sg[host->pio.index].length - host->pio.offset;
+
+	/* Check to if we need less then the size of the sg_buffer */
+
+	max = (sg_len > host->pio.len) ? host->pio.len : sg_len;
+	if (max > AU1XMMC_MAX_TRANSFER) max = AU1XMMC_MAX_TRANSFER;
+
+	for(count = 0; count < max; count++ ) {
+		unsigned char val;
+
+		status = au_readl(HOST_STATUS(host));
+
+		if (!(status & SD_STATUS_TH))
+			break;
+
+		val = *sg_ptr++;
+
+		au_writel((unsigned long) val, HOST_TXPORT(host));
+		au_sync();
+	}
+
+	host->pio.len -= count;
+	host->pio.offset += count;
+
+	if (count == sg_len) {
+		host->pio.index++;
+		host->pio.offset = 0;
+	}
+
+	if (host->pio.len == 0) {
+		IRQ_OFF(host, SD_CONFIG_TH);
+
+		if (host->flags & HOST_F_STOP)
+			SEND_STOP(host);
+
+		tasklet_schedule(&host->data_task);
+	}
+}
+
+static void au1xmmc_receive_pio(struct au1xmmc_host *host)
+{
+
+	struct mmc_data *data = 0;
+	int sg_len = 0, max = 0, count = 0;
+	unsigned char *sg_ptr = 0;
+	u32 status = 0;
+	struct scatterlist *sg;
+
+	data = host->mrq->data;
+
+	if (!(host->flags & HOST_F_RECV))
+		return;
+
+	max = host->pio.len;
+
+	if (host->pio.index < host->dma.len) {
+		sg = &data->sg[host->pio.index];
+		sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset;
+
+		/* This is the space left inside the buffer */
+		sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;
+
+		/* Check to if we need less then the size of the sg_buffer */
+		if (sg_len < max) max = sg_len;
+	}
+
+	if (max > AU1XMMC_MAX_TRANSFER)
+		max = AU1XMMC_MAX_TRANSFER;
+
+	for(count = 0; count < max; count++ ) {
+		u32 val;
+		status = au_readl(HOST_STATUS(host));
+
+		if (!(status & SD_STATUS_NE))
+			break;
+
+		if (status & SD_STATUS_RC) {
+			DEBUG("RX CRC Error [%d + %d].\n", host->id,
+					host->pio.len, count);
+			break;
+		}
+
+		if (status & SD_STATUS_RO) {
+			DEBUG("RX Overrun [%d + %d]\n", host->id,
+					host->pio.len, count);
+			break;
+		}
+		else if (status & SD_STATUS_RU) {
+			DEBUG("RX Underrun [%d + %d]\n", host->id,
+					host->pio.len,	count);
+			break;
+		}
+
+		val = au_readl(HOST_RXPORT(host));
+
+		if (sg_ptr)
+			*sg_ptr++ = (unsigned char) (val & 0xFF);
+	}
+
+	host->pio.len -= count;
+	host->pio.offset += count;
+
+	if (sg_len && count == sg_len) {
+		host->pio.index++;
+		host->pio.offset = 0;
+	}
+
+	if (host->pio.len == 0) {
+		//IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF);
+		IRQ_OFF(host, SD_CONFIG_NE);
+
+		if (host->flags & HOST_F_STOP)
+			SEND_STOP(host);
+
+		tasklet_schedule(&host->data_task);
+	}
+}
+
+/* static void au1xmmc_cmd_complete
+   This is called when a command has been completed - grab the response
+   and check for errors.  Then start the data transfer if it is indicated.
+*/
+
+static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
+{
+
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd;
+	int trans;
+
+	if (!host->mrq)
+		return;
+
+	cmd = mrq->cmd;
+	cmd->error = MMC_ERR_NONE;
+
+	if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) {
+
+		/* Techincally, we should be getting all 48 bits of the response
+		 * (SD_RESP1 + SD_RESP2), but because our response omits the CRC,
+		 * our data ends up being shifted 8 bits to the right.  In this case,
+		 * that means that the OSR data starts at bit 31, so we can just
+		 * read RESP0 and return that
+		 */
+
+		cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+	}
+	else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
+		u32 r[4];
+		int i;
+
+		r[0] = au_readl(host->iobase + SD_RESP3);
+		r[1] = au_readl(host->iobase + SD_RESP2);
+		r[2] = au_readl(host->iobase + SD_RESP1);
+		r[3] = au_readl(host->iobase + SD_RESP0);
+
+		/* The CRC is omitted from the response, so really we only got
+		 * 120 bytes, but the engine expects 128 bits, so we have to shift
+		 * things up
+		 */
+
+		for(i = 0; i < 4; i++) {
+			cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;
+			if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;
+		}
+	}
+
+        /* Figure out errors */
+
+	if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC))
+		cmd->error = MMC_ERR_BADCRC;
+
+	trans = host->flags & (HOST_F_XMIT | HOST_F_RECV);
+
+	if (!trans || cmd->error != MMC_ERR_NONE) {
+
+		IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF);
+		tasklet_schedule(&host->finish_task);
+		return;
+	}
+
+	host->status = HOST_S_DATA;
+
+	if (host->flags & HOST_F_DMA) {
+		u32 channel = DMA_CHANNEL(host);
+
+		/* Start the DMA as soon as the buffer gets something in it */
+
+		if (host->flags & HOST_F_RECV) {
+			u32 mask = SD_STATUS_DB | SD_STATUS_NE;
+
+			while((status & mask) != mask)
+				status = au_readl(HOST_STATUS(host));
+		}
+
+		au1xxx_dbdma_start(channel);
+	}
+}
+
+static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
+{
+
+	unsigned int pbus = get_au1x00_speed();
+	unsigned int divisor;
+	u32 config;
+
+	/* From databook:
+	   divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
+	*/
+
+	pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
+	pbus /= 2;
+
+	divisor = ((pbus / rate) / 2) - 1;
+
+	config = au_readl(HOST_CONFIG(host));
+
+	config &= ~(SD_CONFIG_DIV);
+	config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
+
+	au_writel(config, HOST_CONFIG(host));
+	au_sync();
+}
+
+static int
+au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
+{
+
+	int datalen = data->blocks * (1 << data->blksz_bits);
+
+	if (dma != 0)
+		host->flags |= HOST_F_DMA;
+
+	if (data->flags & MMC_DATA_READ)
+		host->flags |= HOST_F_RECV;
+	else
+		host->flags |= HOST_F_XMIT;
+
+	if (host->mrq->stop)
+		host->flags |= HOST_F_STOP;
+
+	host->dma.dir = DMA_BIDIRECTIONAL;
+
+	host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+				   data->sg_len, host->dma.dir);
+
+	if (host->dma.len == 0)
+		return MMC_ERR_TIMEOUT;
+
+	au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));
+
+	if (host->flags & HOST_F_DMA) {
+		int i;
+		u32 channel = DMA_CHANNEL(host);
+
+		au1xxx_dbdma_stop(channel);
+
+		for(i = 0; i < host->dma.len; i++) {
+			u32 ret = 0, flags = DDMA_FLAGS_NOIE;
+			struct scatterlist *sg = &data->sg[i];
+			int sg_len = sg->length;
+
+			int len = (datalen > sg_len) ? sg_len : datalen;
+
+			if (i == host->dma.len - 1)
+				flags = DDMA_FLAGS_IE;
+
+    			if (host->flags & HOST_F_XMIT){
+      				ret = au1xxx_dbdma_put_source_flags(channel,
+					(void *) (page_address(sg->page) +
+						  sg->offset),
+					len, flags);
+			}
+    			else {
+      				ret = au1xxx_dbdma_put_dest_flags(channel,
+					(void *) (page_address(sg->page) +
+						  sg->offset),
+					len, flags);
+			}
+
+    			if (!ret)
+				goto dataerr;
+
+			datalen -= len;
+		}
+	}
+	else {
+		host->pio.index = 0;
+		host->pio.offset = 0;
+		host->pio.len = datalen;
+
+		if (host->flags & HOST_F_XMIT)
+			IRQ_ON(host, SD_CONFIG_TH);
+		else
+			IRQ_ON(host, SD_CONFIG_NE);
+			//IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);
+	}
+
+	return MMC_ERR_NONE;
+
+ dataerr:
+	dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir);
+	return MMC_ERR_TIMEOUT;
+}
+
+/* static void au1xmmc_request
+   This actually starts a command or data transaction
+*/
+
+static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
+{
+
+	struct au1xmmc_host *host = mmc_priv(mmc);
+	int ret = MMC_ERR_NONE;
+
+	WARN_ON(irqs_disabled());
+	WARN_ON(host->status != HOST_S_IDLE);
+
+	host->mrq = mrq;
+	host->status = HOST_S_CMD;
+
+	bcsr->disk_leds &= ~(1 << 8);
+
+	if (mrq->data) {
+		FLUSH_FIFO(host);
+		ret = au1xmmc_prepare_data(host, mrq->data);
+	}
+
+	if (ret == MMC_ERR_NONE)
+		ret = au1xmmc_send_command(host, 0, mrq->cmd);
+
+	if (ret != MMC_ERR_NONE) {
+		mrq->cmd->error = ret;
+		au1xmmc_finish_request(host);
+	}
+}
+
+static void au1xmmc_reset_controller(struct au1xmmc_host *host)
+{
+
+	/* Apply the clock */
+	au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+        au_sync_delay(1);
+
+	au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+	au_sync_delay(5);
+
+	au_writel(~0, HOST_STATUS(host));
+	au_sync();
+
+	au_writel(0, HOST_BLKSIZE(host));
+	au_writel(0x001fffff, HOST_TIMEOUT(host));
+	au_sync();
+
+	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+        au_sync();
+
+	au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+	au_sync_delay(1);
+
+	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+	au_sync();
+
+	/* Configure interrupts */
+	au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+	au_sync();
+}
+
+
+static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
+{
+	struct au1xmmc_host *host = mmc_priv(mmc);
+
+	DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
+	      host->id, ios->power_mode, ios->clock, ios->vdd,
+	      ios->bus_mode);
+
+	if (ios->power_mode == MMC_POWER_OFF)
+		au1xmmc_set_power(host, 0);
+	else if (ios->power_mode == MMC_POWER_ON) {
+		au1xmmc_set_power(host, 1);
+	}
+
+	if (ios->clock && ios->clock != host->clock) {
+		au1xmmc_set_clock(host, ios->clock);
+		host->clock = ios->clock;
+	}
+}
+
+static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
+	u32 status;
+
+	/* Avoid spurious interrupts */
+
+	if (!host->mrq)
+		return;
+
+	if (host->flags & HOST_F_STOP)
+		SEND_STOP(host);
+
+	tasklet_schedule(&host->data_task);
+}
+
+#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
+#define STATUS_DATA_IN  (SD_STATUS_NE)
+#define STATUS_DATA_OUT (SD_STATUS_TH)
+
+static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	u32 status;
+	int i, ret = 0;
+
+	disable_irq(AU1100_SD_IRQ);
+
+	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+		struct au1xmmc_host * host = au1xmmc_hosts[i];
+		u32 handled = 1;
+
+		status = au_readl(HOST_STATUS(host));
+
+		if (host->mrq && (status & STATUS_TIMEOUT)) {
+			if (status & SD_STATUS_RAT)
+				host->mrq->cmd->error = MMC_ERR_TIMEOUT;
+
+			else if (status & SD_STATUS_DT)
+				host->mrq->data->error = MMC_ERR_TIMEOUT;
+
+			/* In PIO mode, interrupts might still be enabled */
+			IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
+
+			//IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);
+			tasklet_schedule(&host->finish_task);
+		}
+#if 0
+		else if (status & SD_STATUS_DD) {
+
+			/* Sometimes we get a DD before a NE in PIO mode */
+
+			if (!(host->flags & HOST_F_DMA) &&
+					(status & SD_STATUS_NE))
+				au1xmmc_receive_pio(host);
+			else {
+				au1xmmc_data_complete(host, status);
+				//tasklet_schedule(&host->data_task);
+			}
+		}
+#endif
+		else if (status & (SD_STATUS_CR)) {
+			if (host->status == HOST_S_CMD)
+				au1xmmc_cmd_complete(host,status);
+		}
+		else if (!(host->flags & HOST_F_DMA)) {
+			if ((host->flags & HOST_F_XMIT) &&
+			    (status & STATUS_DATA_OUT))
+				au1xmmc_send_pio(host);
+			else if ((host->flags & HOST_F_RECV) &&
+			    (status & STATUS_DATA_IN))
+				au1xmmc_receive_pio(host);
+		}
+		else if (status & 0x203FBC70) {
+			DEBUG("Unhandled status %8.8x\n", host->id, status);
+			handled = 0;
+		}
+
+		au_writel(status, HOST_STATUS(host));
+		au_sync();
+
+		ret |= handled;
+	}
+
+	enable_irq(AU1100_SD_IRQ);
+	return ret;
+}
+
+static void au1xmmc_poll_event(unsigned long arg)
+{
+	struct au1xmmc_host *host = (struct au1xmmc_host *) arg;
+
+	int card = au1xmmc_card_inserted(host);
+        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
+
+	if (card != controller) {
+		host->flags &= ~HOST_F_ACTIVE;
+		if (card) host->flags |= HOST_F_ACTIVE;
+		mmc_detect_change(host->mmc, 0);
+	}
+
+	if (host->mrq != NULL) {
+		u32 status = au_readl(HOST_STATUS(host));
+		DEBUG("PENDING - %8.8x\n", host->id, status);
+	}
+
+	mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
+}
+
+static dbdev_tab_t au1xmmc_mem_dbdev =
+{
+	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0
+};
+
+static void au1xmmc_init_dma(struct au1xmmc_host *host)
+{
+
+	u32 rxchan, txchan;
+
+	int txid = au1xmmc_card_table[host->id].tx_devid;
+	int rxid = au1xmmc_card_table[host->id].rx_devid;
+
+	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
+	   of 8 bits.  And since devices are shared, we need to create
+	   our own to avoid freaking out other devices
+	*/
+
+	int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
+
+	txchan = au1xxx_dbdma_chan_alloc(memid, txid,
+					 au1xmmc_dma_callback, (void *) host);
+
+	rxchan = au1xxx_dbdma_chan_alloc(rxid, memid,
+					 au1xmmc_dma_callback, (void *) host);
+
+	au1xxx_dbdma_set_devwidth(txchan, 8);
+	au1xxx_dbdma_set_devwidth(rxchan, 8);
+
+	au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);
+	au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);
+
+	host->tx_chan = txchan;
+	host->rx_chan = rxchan;
+}
+
+struct mmc_host_ops au1xmmc_ops = {
+	.request	= au1xmmc_request,
+	.set_ios	= au1xmmc_set_ios,
+};
+
+static int au1xmmc_probe(struct device *dev)
+{
+
+	int i, ret = 0;
+
+	/* THe interrupt is shared among all controllers */
+	ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, SA_INTERRUPT, "MMC", 0);
+
+	if (ret) {
+		printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n",
+				AU1100_SD_IRQ, ret);
+		return -ENXIO;
+	}
+
+	disable_irq(AU1100_SD_IRQ);
+
+	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+		struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), dev);
+		struct au1xmmc_host *host = 0;
+
+		if (!mmc) {
+			printk(DRIVER_NAME "ERROR: no mem for host %d\n", i);
+			au1xmmc_hosts[i] = 0;
+			continue;
+		}
+
+		mmc->ops = &au1xmmc_ops;
+
+		mmc->f_min =   450000;
+		mmc->f_max = 24000000;
+
+		mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
+		mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
+
+		mmc->ocr_avail = AU1XMMC_OCR;
+
+		host = mmc_priv(mmc);
+		host->mmc = mmc;
+
+		host->id = i;
+		host->iobase = au1xmmc_card_table[host->id].iobase;
+		host->clock = 0;
+		host->power_mode = MMC_POWER_OFF;
+
+		host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;
+		host->status = HOST_S_IDLE;
+
+		init_timer(&host->timer);
+
+		host->timer.function = au1xmmc_poll_event;
+		host->timer.data = (unsigned long) host;
+		host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
+
+		tasklet_init(&host->data_task, au1xmmc_tasklet_data,
+				(unsigned long) host);
+
+		tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
+				(unsigned long) host);
+
+		spin_lock_init(&host->lock);
+
+		if (dma != 0)
+			au1xmmc_init_dma(host);
+
+		au1xmmc_reset_controller(host);
+
+		mmc_add_host(mmc);
+		au1xmmc_hosts[i] = host;
+
+		add_timer(&host->timer);
+
+		printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",
+		       host->id, host->iobase, dma ? "dma" : "pio");
+	}
+
+	enable_irq(AU1100_SD_IRQ);
+
+	return 0;
+}
+
+static int au1xmmc_remove(struct device *dev)
+{
+
+	int i;
+
+	disable_irq(AU1100_SD_IRQ);
+
+	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {
+		struct au1xmmc_host *host = au1xmmc_hosts[i];
+		if (!host) continue;
+
+		tasklet_kill(&host->data_task);
+		tasklet_kill(&host->finish_task);
+
+		del_timer_sync(&host->timer);
+		au1xmmc_set_power(host, 0);
+
+		mmc_remove_host(host->mmc);
+
+		au1xxx_dbdma_chan_free(host->tx_chan);
+		au1xxx_dbdma_chan_free(host->rx_chan);
+
+		au_writel(0x0, HOST_ENABLE(host));
+		au_sync();
+	}
+
+	free_irq(AU1100_SD_IRQ, 0);
+	return 0;
+}
+
+static struct device_driver au1xmmc_driver = {
+	.name          = DRIVER_NAME,
+	.bus           = &platform_bus_type,
+	.probe         = au1xmmc_probe,
+	.remove        = au1xmmc_remove,
+	.suspend       = NULL,
+	.resume        = NULL
+};
+
+static int __init au1xmmc_init(void)
+{
+	return driver_register(&au1xmmc_driver);
+}
+
+static void __exit au1xmmc_exit(void)
+{
+	driver_unregister(&au1xmmc_driver);
+}
+
+module_init(au1xmmc_init);
+module_exit(au1xmmc_exit);
+
+#ifdef MODULE
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
+MODULE_LICENSE("GPL");
+#endif
+
diff --git a/drivers/mmc/au1xmmc.h b/drivers/mmc/au1xmmc.h
new file mode 100644
index 0000000..341cbdf
--- /dev/null
+++ b/drivers/mmc/au1xmmc.h
@@ -0,0 +1,96 @@
+#ifndef _AU1XMMC_H_
+#define _AU1XMMC_H_
+
+/* Hardware definitions */
+
+#define AU1XMMC_DESCRIPTOR_COUNT 1
+#define AU1XMMC_DESCRIPTOR_SIZE  2048
+
+#define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30  | \
+		      MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33  | \
+		      MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)
+
+/* Easy access macros */
+
+#define HOST_STATUS(h)	((h)->iobase + SD_STATUS)
+#define HOST_CONFIG(h)	((h)->iobase + SD_CONFIG)
+#define HOST_ENABLE(h)	((h)->iobase + SD_ENABLE)
+#define HOST_TXPORT(h)	((h)->iobase + SD_TXPORT)
+#define HOST_RXPORT(h)	((h)->iobase + SD_RXPORT)
+#define HOST_CMDARG(h)	((h)->iobase + SD_CMDARG)
+#define HOST_BLKSIZE(h)	((h)->iobase + SD_BLKSIZE)
+#define HOST_CMD(h)	((h)->iobase + SD_CMD)
+#define HOST_CONFIG2(h)	((h)->iobase + SD_CONFIG2)
+#define HOST_TIMEOUT(h)	((h)->iobase + SD_TIMEOUT)
+#define HOST_DEBUG(h)	((h)->iobase + SD_DEBUG)
+
+#define DMA_CHANNEL(h) \
+	( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)
+
+/* This gives us a hard value for the stop command that we can write directly
+ * to the command register
+ */
+
+#define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO)
+
+/* This is the set of interrupts that we configure by default */
+
+#if 0
+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \
+		SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
+#endif
+
+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \
+		SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)
+/* The poll event (looking for insert/remove events runs twice a second */
+#define AU1XMMC_DETECT_TIMEOUT (HZ/2)
+
+struct au1xmmc_host {
+  struct mmc_host *mmc;
+  struct mmc_request *mrq;
+
+  u32 id;
+
+  u32 flags;
+  u32 iobase;
+  u32 clock;
+  u32 bus_width;
+  u32 power_mode;
+
+  int status;
+
+   struct {
+	   int len;
+	   int dir;
+  } dma;
+
+   struct {
+	   int index;
+	   int offset;
+	   int len;
+  } pio;
+
+  u32 tx_chan;
+  u32 rx_chan;
+
+  struct timer_list timer;
+  struct tasklet_struct finish_task;
+  struct tasklet_struct data_task;
+
+  spinlock_t lock;
+};
+
+/* Status flags used by the host structure */
+
+#define HOST_F_XMIT   0x0001
+#define HOST_F_RECV   0x0002
+#define HOST_F_DMA    0x0010
+#define HOST_F_ACTIVE 0x0100
+#define HOST_F_STOP   0x1000
+
+#define HOST_S_IDLE   0x0001
+#define HOST_S_CMD    0x0002
+#define HOST_S_DATA   0x0003
+#define HOST_S_STOP   0x0004
+
+#endif
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index fa83f15..9b62985 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -85,6 +85,12 @@
 	up(&open_lock);
 }
 
+static inline int mmc_blk_readonly(struct mmc_card *card)
+{
+	return mmc_card_readonly(card) ||
+	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+}
+
 static int mmc_blk_open(struct inode *inode, struct file *filp)
 {
 	struct mmc_blk_data *md;
@@ -97,7 +103,7 @@
 		ret = 0;
 
 		if ((filp->f_mode & FMODE_WRITE) &&
-			mmc_card_readonly(md->queue.card))
+			mmc_blk_readonly(md->queue.card))
 			ret = -EROFS;
 	}
 
@@ -410,7 +416,7 @@
 	printk(KERN_INFO "%s: %s %s %dKiB %s\n",
 		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
 		(card->csd.capacity << card->csd.read_blkbits) / 1024,
-		mmc_card_readonly(card)?"(ro)":"");
+		mmc_blk_readonly(card)?"(ro)":"");
 
 	mmc_set_drvdata(card, md);
 	add_disk(md->disk);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 91c7484..1e6bdba 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/scatterlist.h>
+#include <asm/sizes.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/clock.h>
 #include <asm/mach/mmc.h>
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index b53af57..d575e3a 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -29,7 +29,6 @@
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/scatterlist.h>
 #include <asm/sizes.h>
 
@@ -571,23 +570,23 @@
 }
 
 #ifdef CONFIG_PM
-static int pxamci_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxamci_suspend(struct device *dev, pm_message_t state)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (mmc && level == SUSPEND_DISABLE)
+	if (mmc)
 		ret = mmc_suspend_host(mmc, state);
 
 	return ret;
 }
 
-static int pxamci_resume(struct device *dev, u32 level)
+static int pxamci_resume(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (mmc && level == RESUME_ENABLE)
+	if (mmc)
 		ret = mmc_resume_host(mmc);
 
 	return ret;
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 3cbca7c..3ace875 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1033,13 +1033,16 @@
 	}
 	else
 	{
-		setup &= ~WBSD_DAT3_H;
+		if (setup & WBSD_DAT3_H)
+		{
+			setup &= ~WBSD_DAT3_H;
 
-		/*
-		 * We cannot resume card detection immediatly
-		 * because of capacitance and delays in the chip.
-		 */
-		mod_timer(&host->ignore_timer, jiffies + HZ/100);
+			/*
+			 * We cannot resume card detection immediatly
+			 * because of capacitance and delays in the chip.
+			 */
+			mod_timer(&host->ignore_timer, jiffies + HZ/100);
+		}
 	}
 	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
 
@@ -1461,8 +1464,10 @@
 		{
 			id = 0xFFFF;
 
-			outb(unlock_codes[j], config_ports[i]);
-			outb(unlock_codes[j], config_ports[i]);
+			host->config = config_ports[i];
+			host->unlock_code = unlock_codes[j];
+
+			wbsd_unlock_config(host);
 
 			outb(WBSD_CONF_ID_HI, config_ports[i]);
 			id = inb(config_ports[i] + 1) << 8;
@@ -1470,13 +1475,13 @@
 			outb(WBSD_CONF_ID_LO, config_ports[i]);
 			id |= inb(config_ports[i] + 1);
 
+			wbsd_lock_config(host);
+
 			for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
 			{
 				if (id == valid_ids[k])
 				{
 					host->chip_id = id;
-					host->config = config_ports[i];
-					host->unlock_code = unlock_codes[i];
 
 					return 0;
 				}
@@ -1487,13 +1492,14 @@
 				DBG("Unknown hardware (id %x) found at %x\n",
 					id, config_ports[i]);
 			}
-
-			outb(LOCK_CODE, config_ports[i]);
 		}
 
 		release_region(config_ports[i], 2);
 	}
 
+	host->config = 0;
+	host->unlock_code = 0;
+
 	return -ENODEV;
 }
 
@@ -1699,8 +1705,10 @@
  * Configure the resources the chip should use.
  */
 
-static void __devinit wbsd_chip_config(struct wbsd_host* host)
+static void wbsd_chip_config(struct wbsd_host* host)
 {
+	wbsd_unlock_config(host);
+
 	/*
 	 * Reset the chip.
 	 */
@@ -1733,16 +1741,20 @@
 	 */
 	wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
 	wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+
+	wbsd_lock_config(host);
 }
 
 /*
  * Check that configured resources are correct.
  */
 
-static int __devinit wbsd_chip_validate(struct wbsd_host* host)
+static int wbsd_chip_validate(struct wbsd_host* host)
 {
 	int base, irq, dma;
 
+	wbsd_unlock_config(host);
+
 	/*
 	 * Select SD/MMC function.
 	 */
@@ -1758,6 +1770,8 @@
 
 	dma = wbsd_read_config(host, WBSD_CONF_DRQ);
 
+	wbsd_lock_config(host);
+
 	/*
 	 * Validate against given configuration.
 	 */
@@ -1771,6 +1785,20 @@
 	return 1;
 }
 
+/*
+ * Powers down the SD function
+ */
+
+static void wbsd_chip_poweroff(struct wbsd_host* host)
+{
+	wbsd_unlock_config(host);
+
+	wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+	wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
+
+	wbsd_lock_config(host);
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Devices setup and shutdown                                                *
@@ -1844,7 +1872,11 @@
 	 */
 #ifdef CONFIG_PM
 	if (host->config)
+	{
+		wbsd_unlock_config(host);
 		wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
+		wbsd_lock_config(host);
+	}
 #endif
 	/*
 	 * Allow device to initialise itself properly.
@@ -1885,16 +1917,11 @@
 
 	mmc_remove_host(mmc);
 
+	/*
+	 * Power down the SD/MMC function.
+	 */
 	if (!pnp)
-	{
-		/*
-		 * Power down the SD/MMC function.
-		 */
-		wbsd_unlock_config(host);
-		wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-		wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
-		wbsd_lock_config(host);
-	}
+		wbsd_chip_poweroff(host);
 
 	wbsd_release_resources(host);
 
@@ -1955,23 +1982,59 @@
  */
 
 #ifdef CONFIG_PM
-static int wbsd_suspend(struct device *dev, pm_message_t state, u32 level)
+
+static int wbsd_suspend(struct device *dev, pm_message_t state)
 {
-	DBGF("Not yet supported\n");
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct wbsd_host *host;
+	int ret;
+
+	if (!mmc)
+		return 0;
+
+	DBG("Suspending...\n");
+
+	ret = mmc_suspend_host(mmc, state);
+	if (!ret)
+		return ret;
+
+	host = mmc_priv(mmc);
+
+	wbsd_chip_poweroff(host);
 
 	return 0;
 }
 
-static int wbsd_resume(struct device *dev, u32 level)
+static int wbsd_resume(struct device *dev)
 {
-	DBGF("Not yet supported\n");
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct wbsd_host *host;
 
-	return 0;
+	if (!mmc)
+		return 0;
+
+	DBG("Resuming...\n");
+
+	host = mmc_priv(mmc);
+
+	wbsd_chip_config(host);
+
+	/*
+	 * Allow device to initialise itself properly.
+	 */
+	mdelay(5);
+
+	wbsd_init_device(host);
+
+	return mmc_resume_host(mmc);
 }
-#else
+
+#else /* CONFIG_PM */
+
 #define wbsd_suspend NULL
 #define wbsd_resume NULL
-#endif
+
+#endif /* CONFIG_PM */
 
 static struct platform_device *wbsd_device;
 
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index 62d235a..4f6778f3 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/mtd/jedec.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index dfd335e..df987a5 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -44,6 +44,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #ifdef HAVE_PARTITIONS
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index a423a38..765c017 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -22,6 +22,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 
 #define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args)
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
index 0ba0ff7..63104c7 100644
--- a/drivers/mtd/maps/bast-flash.c
+++ b/drivers/mtd/maps/bast-flash.c
@@ -33,6 +33,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/device.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index da8584a..c68b31d 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -20,6 +20,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 938c41f..e5b7416 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
index 0bc79c9..f995196 100644
--- a/drivers/mtd/maps/dilnetpc.c
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -30,12 +30,15 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <asm/io.h>
+#include <linux/string.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/concat.h>
 
+#include <asm/io.h>
+
 /*
 ** The DIL/NetPC keeps its BIOS in two distinct flash blocks.
 ** Destroying any of these blocks transforms the DNPC into
diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c
index ab6dbe2..1df6188 100644
--- a/drivers/mtd/maps/epxa10db-flash.c
+++ b/drivers/mtd/maps/epxa10db-flash.c
@@ -27,12 +27,15 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <asm/io.h>
+#include <linux/slab.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
+#include <asm/io.h>
 #include <asm/hardware.h>
+
 #ifdef CONFIG_EPXA10DB
 #define BOARD_NAME "EPXA10DB"
 #else
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
index 068bb6a..00f7bbe 100644
--- a/drivers/mtd/maps/fortunet.c
+++ b/drivers/mtd/maps/fortunet.c
@@ -7,11 +7,14 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <asm/io.h>
+#include <linux/string.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
+#include <asm/io.h>
+
 #define MAX_NUM_REGIONS		4
 #define MAX_NUM_PARTITIONS	8
 
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index a9f86c7..1e5d6e1 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -22,11 +22,13 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 3fcc328..da316e5 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -20,11 +20,14 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
+
 #include <asm/io.h>
 #include <asm/mach/flash.h>
 
diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
index 1298de4..2337e0c 100644
--- a/drivers/mtd/maps/lubbock-flash.c
+++ b/drivers/mtd/maps/lubbock-flash.c
@@ -15,10 +15,13 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/slab.h>
+
 #include <linux/dma-mapping.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
+
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
diff --git a/drivers/mtd/maps/mainstone-flash.c b/drivers/mtd/maps/mainstone-flash.c
index 87e93fa..da0f8a6 100644
--- a/drivers/mtd/maps/mainstone-flash.c
+++ b/drivers/mtd/maps/mainstone-flash.c
@@ -16,9 +16,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
+
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c
index 4961090..da36e8d 100644
--- a/drivers/mtd/maps/omap-toto-flash.c
+++ b/drivers/mtd/maps/omap-toto-flash.c
@@ -12,9 +12,9 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index b17bca6..fa84566 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -36,6 +36,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/slab.h>
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 18dbd3a..d9c64e9 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 118b045..a0577ea 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -30,6 +30,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/device.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 8dcaa35..c81bec7 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -21,6 +21,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/concat.h>
 
+#include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
@@ -129,20 +130,21 @@
 	char name[16];
 	struct map_info map;
 	struct mtd_info *mtd;
-	struct flash_platform_data *data;
+	struct flash_platform_data *plat;
 };
 
 struct sa_info {
 	struct mtd_partition	*parts;
 	struct mtd_info		*mtd;
 	int			num_subdev;
+	unsigned int		nr_parts;
 	struct sa_subdev_info	subdev[0];
 };
 
 static void sa1100_set_vpp(struct map_info *map, int on)
 {
 	struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
-	subdev->data->set_vpp(on);
+	subdev->plat->set_vpp(on);
 }
 
 static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
@@ -186,7 +188,7 @@
 		goto out;
 	}
 
-	if (subdev->data->set_vpp)
+	if (subdev->plat->set_vpp)
 		subdev->map.set_vpp = sa1100_set_vpp;
 
 	subdev->map.phys = phys;
@@ -203,7 +205,7 @@
 	 * Now let's probe for the actual flash.  Do it here since
 	 * specific machine settings might have been set above.
 	 */
-	subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
+	subdev->mtd = do_map_probe(subdev->plat->map_name, &subdev->map);
 	if (subdev->mtd == NULL) {
 		ret = -ENXIO;
 		goto err;
@@ -222,13 +224,17 @@
 	return ret;
 }
 
-static void sa1100_destroy(struct sa_info *info)
+static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *plat)
 {
 	int i;
 
 	if (info->mtd) {
-		del_mtd_partitions(info->mtd);
-
+		if (info->nr_parts == 0)
+			del_mtd_device(info->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+		else
+			del_mtd_partitions(info->mtd);
+#endif
 #ifdef CONFIG_MTD_CONCAT
 		if (info->mtd != info->subdev[0].mtd)
 			mtd_concat_destroy(info->mtd);
@@ -241,10 +247,13 @@
 	for (i = info->num_subdev - 1; i >= 0; i--)
 		sa1100_destroy_subdev(&info->subdev[i]);
 	kfree(info);
+
+	if (plat->exit)
+		plat->exit();
 }
 
 static struct sa_info *__init
-sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
+sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
 {
 	struct sa_info *info;
 	int nr, size, i, ret = 0;
@@ -274,6 +283,12 @@
 
 	memset(info, 0, size);
 
+	if (plat->init) {
+		ret = plat->init();
+		if (ret)
+			goto err;
+	}
+
 	/*
 	 * Claim and then map the memory regions.
 	 */
@@ -286,8 +301,8 @@
 			break;
 
 		subdev->map.name = subdev->name;
-		sprintf(subdev->name, "sa1100-%d", i);
-		subdev->data = flash;
+		sprintf(subdev->name, "%s-%d", plat->name, i);
+		subdev->plat = plat;
 
 		ret = sa1100_probe_subdev(subdev, res);
 		if (ret)
@@ -308,7 +323,7 @@
 	 * otherwise fail.  Either way, it'll be called "sa1100".
 	 */
 	if (info->num_subdev == 1) {
-		strcpy(info->subdev[0].name, "sa1100");
+		strcpy(info->subdev[0].name, plat->name);
 		info->mtd = info->subdev[0].mtd;
 		ret = 0;
 	} else if (info->num_subdev > 1) {
@@ -321,7 +336,7 @@
 			cdev[i] = info->subdev[i].mtd;
 
 		info->mtd = mtd_concat_create(cdev, info->num_subdev,
-					      "sa1100");
+					      plat->name);
 		if (info->mtd == NULL)
 			ret = -ENXIO;
 #else
@@ -335,7 +350,7 @@
 		return info;
 
  err:
-	sa1100_destroy(info);
+	sa1100_destroy(info, plat);
  out:
 	return ERR_PTR(ret);
 }
@@ -345,16 +360,16 @@
 static int __init sa1100_mtd_probe(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct flash_platform_data *flash = pdev->dev.platform_data;
+	struct flash_platform_data *plat = pdev->dev.platform_data;
 	struct mtd_partition *parts;
 	const char *part_type = NULL;
 	struct sa_info *info;
 	int err, nr_parts = 0;
 
-	if (!flash)
+	if (!plat)
 		return -ENODEV;
 
-	info = sa1100_setup_mtd(pdev, flash);
+	info = sa1100_setup_mtd(pdev, plat);
 	if (IS_ERR(info)) {
 		err = PTR_ERR(info);
 		goto out;
@@ -371,8 +386,8 @@
 	} else
 #endif
 	{
-		parts = flash->parts;
-		nr_parts = flash->nr_parts;
+		parts = plat->parts;
+		nr_parts = plat->nr_parts;
 		part_type = "static";
 	}
 
@@ -386,6 +401,8 @@
 		add_mtd_partitions(info->mtd, parts, nr_parts);
 	}
 
+	info->nr_parts = nr_parts;
+
 	dev_set_drvdata(dev, info);
 	err = 0;
 
@@ -396,33 +413,44 @@
 static int __exit sa1100_mtd_remove(struct device *dev)
 {
 	struct sa_info *info = dev_get_drvdata(dev);
+	struct flash_platform_data *plat = dev->platform_data;
+
 	dev_set_drvdata(dev, NULL);
-	sa1100_destroy(info);
+	sa1100_destroy(info, plat);
+
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1100_mtd_suspend(struct device *dev, pm_message_t state)
 {
 	struct sa_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (info && level == SUSPEND_SAVE_STATE)
+	if (info)
 		ret = info->mtd->suspend(info->mtd);
 
 	return ret;
 }
 
-static int sa1100_mtd_resume(struct device *dev, u32 level)
+static int sa1100_mtd_resume(struct device *dev)
 {
 	struct sa_info *info = dev_get_drvdata(dev);
-	if (info && level == RESUME_RESTORE_STATE)
+	if (info)
 		info->mtd->resume(info->mtd);
 	return 0;
 }
+
+static void sa1100_mtd_shutdown(struct device *dev)
+{
+	struct sa_info *info = dev_get_drvdata(dev);
+	if (info && info->mtd->suspend(info->mtd) == 0)
+		info->mtd->resume(info->mtd);
+}
 #else
 #define sa1100_mtd_suspend NULL
 #define sa1100_mtd_resume  NULL
+#define sa1100_mtd_shutdown NULL
 #endif
 
 static struct device_driver sa1100_mtd_driver = {
@@ -432,6 +460,7 @@
 	.remove		= __exit_p(sa1100_mtd_remove),
 	.suspend	= sa1100_mtd_suspend,
 	.resume		= sa1100_mtd_resume,
+	.shutdown	= sa1100_mtd_shutdown,
 };
 
 static int __init sa1100_mtd_init(void)
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 995e999..4e28b97 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -27,12 +27,14 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <asm/io.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
+#include <asm/io.h>
+
 #define FLASH_ADDR 0x40000000
 #define FLASH_SIZE 0x00800000
 #define FLASH_BANK_MAX 4
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index b7c32c2..400dd9c 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/sched.h>	/* TASK_* */
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/blktrans.h>
 
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 1ed602a..16df1e4 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/sched.h>	/* TASK_* */
 #include <asm/uaccess.h>
 
 #include <linux/device.h>
@@ -24,10 +25,10 @@
 	if (!mtd)
 		return;
 
-	class_device_create(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+	class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
 			    NULL, "mtd%d", mtd->index);
 	
-	class_device_create(mtd_class, 
+	class_device_create(mtd_class, NULL,
 			    MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
 			    NULL, "mtd%dro", mtd->index);
 }
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 8f66d09..f3e65af 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -14,7 +14,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-
+#include <linux/sched.h>	/* TASK_* */
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/concat.h>
 
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index b47ebcb..b58ba23 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -51,6 +51,7 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index bc53744..f822cd3 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1027,8 +1027,7 @@
 		if (!(cpr8(Cmd) & CmdReset))
 			return;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(10);
+		schedule_timeout_uninterruptible(10);
 	}
 
 	printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
@@ -1575,6 +1574,7 @@
 	.set_wol		= cp_set_wol,
 	.get_strings		= cp_get_strings,
 	.get_ethtool_stats	= cp_get_ethtool_stats,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1773,6 +1773,7 @@
 	for (i = 0; i < 3; i++)
 		((u16 *) (dev->dev_addr))[i] =
 		    le16_to_cpu (read_eeprom (regs, i + 7, addr_len));
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	dev->open = cp_open;
 	dev->stop = cp_close;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 4c2cf7b..30bee11 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -552,7 +552,8 @@
 
 	{ "RTL-8100B/8139D",
 	  HW_REVID(1, 1, 1, 0, 1, 0, 1),
-	  HasLWake,
+	  HasHltClk /* XXX undocumented? */
+	| HasLWake,
 	},
 
 	{ "RTL-8101",
@@ -970,6 +971,7 @@
 	for (i = 0; i < 3; i++)
 		((u16 *) (dev->dev_addr))[i] =
 		    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	/* The Rtl8139-specific entries in the device structure. */
 	dev->open = rtl8139_open;
@@ -2465,6 +2467,7 @@
 	.get_strings		= rtl8139_get_strings,
 	.get_stats_count	= rtl8139_get_stats_count,
 	.get_ethtool_stats	= rtl8139_get_ethtool_stats,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c748b0e..6d4f9ce 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -475,6 +475,14 @@
 	  the moment only acceleration of IPv4 is supported.  This option
 	  enables offloading for checksums on transmit.  If unsure, say Y.
 
+config MIPS_SIM_NET
+	tristate "MIPS simulator Network device (EXPERIMENTAL)"
+	depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL
+	help
+	  The MIPSNET device is a simple Ethernet network device which is
+	  emulated by the MIPS Simulator.
+	  If you are not using a MIPSsim or are unsure, say N.
+
 config SGI_O2MACE_ETH
 	tristate "SGI O2 MACE Fast Ethernet support"
 	depends on NET_ETHERNET && SGI_IP32=y
@@ -1155,38 +1163,74 @@
 	  be called ibmveth.
 
 config IBM_EMAC
-	bool "IBM PPC4xx EMAC driver support"
+	tristate "PowerPC 4xx on-chip Ethernet support"
 	depends on 4xx
-	select CRC32
-	---help---
-	  This driver supports the IBM PPC4xx EMAC family of on-chip
-	  Ethernet controllers.
-
-config IBM_EMAC_ERRMSG
-	bool "Verbose error messages"
-	depends on IBM_EMAC && BROKEN
+	help
+	  This driver supports the PowerPC 4xx EMAC family of on-chip
+          Ethernet controllers.
 
 config IBM_EMAC_RXB
 	int "Number of receive buffers"
 	depends on IBM_EMAC
-	default "128" if IBM_EMAC4
-	default "64"
+	default "128"
 
 config IBM_EMAC_TXB
 	int "Number of transmit buffers"
 	depends on IBM_EMAC
-	default "128" if IBM_EMAC4
-	default "8"
+	default "64"
 
-config IBM_EMAC_FGAP
-	int "Frame gap"
+config IBM_EMAC_POLL_WEIGHT
+	int "MAL NAPI polling weight"
 	depends on IBM_EMAC
-	default "8"
+	default "32"
 
-config IBM_EMAC_SKBRES
-	int "Skb reserve amount"
+config IBM_EMAC_RX_COPY_THRESHOLD
+	int "RX skb copy threshold (bytes)"
+	depends on IBM_EMAC
+	default "256"
+
+config IBM_EMAC_RX_SKB_HEADROOM
+	int "Additional RX skb headroom (bytes)"
 	depends on IBM_EMAC
 	default "0"
+	help
+	  Additional receive skb headroom. Note, that driver
+	  will always reserve at least 2 bytes to make IP header
+	  aligned, so usualy there is no need to add any additional
+	  headroom.
+	  
+	  If unsure, set to 0.
+
+config IBM_EMAC_PHY_RX_CLK_FIX
+	bool "PHY Rx clock workaround"
+	depends on IBM_EMAC && (405EP || 440GX || 440EP)
+	help
+	  Enable this if EMAC attached to a PHY which doesn't generate
+	  RX clock if there is no link, if this is the case, you will 
+	  see "TX disable timeout" or "RX disable timeout" in the system
+	  log.
+	  
+	  If unsure, say N.
+
+config IBM_EMAC_DEBUG
+	bool "Debugging"
+	depends on IBM_EMAC
+	default n
+
+config IBM_EMAC_ZMII
+	bool
+	depends on IBM_EMAC && (NP405H || NP405L || 44x)
+	default y
+
+config IBM_EMAC_RGMII
+	bool
+	depends on IBM_EMAC && 440GX
+	default y
+		
+config IBM_EMAC_TAH
+	bool
+	depends on IBM_EMAC && 440GX
+	default y
 
 config NET_PCI
 	bool "EISA, VLB, PCI and on board controllers"
@@ -1330,7 +1374,7 @@
 
 config CS89x0
 	tristate "CS89x0 support"
-	depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105
+	depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 || MACH_MP1000
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards. If you have a
 	  network (Ethernet) card of this type, say Y and read the
@@ -1767,6 +1811,7 @@
 	  controller on the Renesas H8/300 processor.
 
 source "drivers/net/fec_8xx/Kconfig"
+source "drivers/net/fs_enet/Kconfig"
 
 endmenu
 
@@ -2083,6 +2128,7 @@
 config GIANFAR
 	tristate "Gianfar Ethernet"
 	depends on 85xx || 83xx
+	select PHYLIB
 	help
 	  This driver supports the Gigabit TSEC on the MPC85xx 
 	  family of chips, and the FEC on the 8540
@@ -2192,8 +2238,8 @@
 	depends on PCI
 	---help---
 	  This driver supports the 10Gbe XFrame NIC of S2IO. 
-	  For help regarding driver compilation, installation and 
-	  tuning please look into ~/drivers/net/s2io/README.txt.
+	  More specific information on configuring the driver is in 
+	  <file:Documentation/networking/s2io.txt>.
 
 config S2IO_NAPI
 	bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
@@ -2243,6 +2289,20 @@
 	tristate "iSeries Virtual Ethernet driver support"
 	depends on PPC_ISERIES
 
+config RIONET
+	tristate "RapidIO Ethernet over messaging driver support"
+	depends on NETDEVICES && RAPIDIO
+
+config RIONET_TX_SIZE
+	int "Number of outbound queue entries"
+	depends on RIONET
+	default "128"
+
+config RIONET_RX_SIZE
+	int "Number of inbound queue entries"
+	depends on RIONET
+	default "128"
+
 config FDDI
 	bool "FDDI driver support"
 	depends on (PCI || EISA)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8aeec9f..7c313cb 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -13,7 +13,7 @@
 obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
 
 #
 # link order important here
@@ -64,6 +64,7 @@
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_RIONET) += rionet.o
 
 #
 # end link order section
@@ -166,6 +167,7 @@
 obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
 obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
 obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
@@ -201,3 +203,6 @@
 obj-$(CONFIG_ETRAX_ETHERNET) += cris/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
+
+obj-$(CONFIG_FS_ENET) += fs_enet/
+
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index dbecc6b..b8953de 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -871,10 +871,8 @@
 	if (ap->info)
 		pci_free_consistent(ap->pdev, sizeof(struct ace_info),
 				    ap->info, ap->info_dma);
-	if (ap->skb)
-		kfree(ap->skb);
-	if (ap->trace_buf)
-		kfree(ap->trace_buf);
+	kfree(ap->skb);
+	kfree(ap->trace_buf);
 
 	if (dev->irq)
 		free_irq(dev->irq, dev);
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
old mode 100755
new mode 100644
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
old mode 100755
new mode 100644
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index c56d86d..3d50e95 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -29,6 +29,7 @@
 
 #include <asm/system.h>
 #include <asm/irq.h>
+#include <asm/hardware.h>
 #include <asm/io.h>
 
 #define TX_BUFFERS 15
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index c82b9cd..332e995 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -151,13 +151,6 @@
 	SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
 	SUPPORTED_Autoneg
 
-static char *phy_link[] = 
-{	"unknown", 
-	"10Base2", "10BaseT", 
-	"AUI",
-	"100BaseT", "100BaseTX", "100BaseFX"
-};
-
 int bcm_5201_init(struct net_device *dev, int phy_addr)
 {
 	s16 data;
@@ -785,6 +778,7 @@
 	{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
 	{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
 	{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
+	{"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
 	{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
 	{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
 	{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
@@ -1045,7 +1039,7 @@
 #endif
 
 	if (aup->mii->chip_info == NULL) {
-		printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
+		printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
 				dev->name);
 		return -1;
 	}
@@ -1546,6 +1540,9 @@
 		printk(KERN_ERR "%s: out of memory\n", dev->name);
 		goto err_out;
 	}
+	aup->mii->next = NULL;
+	aup->mii->chip_info = NULL;
+	aup->mii->status = 0;
 	aup->mii->mii_control_reg = 0;
 	aup->mii->mii_data_reg = 0;
 
@@ -1609,8 +1606,7 @@
 	/* here we should have a valid dev plus aup-> register addresses
 	 * so we can reset the mac properly.*/
 	reset_mac(dev);
-	if (aup->mii)
-		kfree(aup->mii);
+	kfree(aup->mii);
 	for (i = 0; i < NUM_RX_DMA; i++) {
 		if (aup->rx_db_inuse[i])
 			ReleaseDB(aup, aup->rx_db_inuse[i]);
@@ -1809,8 +1805,7 @@
 		if (dev) {
 			aup = (struct au1000_private *) dev->priv;
 			unregister_netdev(dev);
-			if (aup->mii)
-				kfree(aup->mii);
+			kfree(aup->mii);
 			for (j = 0; j < NUM_RX_DMA; j++) {
 				if (aup->rx_db_inuse[j])
 					ReleaseDB(aup, aup->rx_db_inuse[j]);
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 94939f5..0ee3e27 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/version.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -106,6 +107,29 @@
 static void b44_poll_controller(struct net_device *dev);
 #endif
 
+static int dma_desc_align_mask;
+static int dma_desc_sync_size;
+
+static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
+                                                dma_addr_t dma_base,
+                                                unsigned long offset,
+                                                enum dma_data_direction dir)
+{
+	dma_sync_single_range_for_device(&pdev->dev, dma_base,
+	                                 offset & dma_desc_align_mask,
+	                                 dma_desc_sync_size, dir);
+}
+
+static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
+                                             dma_addr_t dma_base,
+                                             unsigned long offset,
+                                             enum dma_data_direction dir)
+{
+	dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
+	                              offset & dma_desc_align_mask,
+	                              dma_desc_sync_size, dir);
+}
+
 static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
 {
 	return readl(bp->regs + reg);
@@ -668,6 +692,11 @@
 	dp->ctrl = cpu_to_le32(ctrl);
 	dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
 
+	if (bp->flags & B44_FLAG_RX_RING_HACK)
+		b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+		                             dest_idx * sizeof(dp),
+		                             DMA_BIDIRECTIONAL);
+
 	return RX_PKT_BUF_SZ;
 }
 
@@ -692,6 +721,11 @@
 	pci_unmap_addr_set(dest_map, mapping,
 			   pci_unmap_addr(src_map, mapping));
 
+	if (bp->flags & B44_FLAG_RX_RING_HACK)
+		b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
+		                          src_idx * sizeof(src_desc),
+		                          DMA_BIDIRECTIONAL);
+
 	ctrl = src_desc->ctrl;
 	if (dest_idx == (B44_RX_RING_SIZE - 1))
 		ctrl |= cpu_to_le32(DESC_CTRL_EOT);
@@ -700,8 +734,14 @@
 
 	dest_desc->ctrl = ctrl;
 	dest_desc->addr = src_desc->addr;
+
 	src_map->skb = NULL;
 
+	if (bp->flags & B44_FLAG_RX_RING_HACK)
+		b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
+		                             dest_idx * sizeof(dest_desc),
+		                             DMA_BIDIRECTIONAL);
+
 	pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
 				       RX_PKT_BUF_SZ,
 				       PCI_DMA_FROMDEVICE);
@@ -959,6 +999,11 @@
 	bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
 	bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
 
+	if (bp->flags & B44_FLAG_TX_RING_HACK)
+		b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
+		                             entry * sizeof(bp->tx_ring[0]),
+		                             DMA_TO_DEVICE);
+
 	entry = NEXT_TX(entry);
 
 	bp->tx_prod = entry;
@@ -1064,6 +1109,16 @@
 	memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
 	memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
 
+	if (bp->flags & B44_FLAG_RX_RING_HACK)
+		dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
+		                           DMA_TABLE_BYTES,
+		                           PCI_DMA_BIDIRECTIONAL);
+
+	if (bp->flags & B44_FLAG_TX_RING_HACK)
+		dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
+		                           DMA_TABLE_BYTES,
+		                           PCI_DMA_TODEVICE);
+
 	for (i = 0; i < bp->rx_pending; i++) {
 		if (b44_alloc_rx_skb(bp, -1, i) < 0)
 			break;
@@ -1076,23 +1131,33 @@
  */
 static void b44_free_consistent(struct b44 *bp)
 {
-	if (bp->rx_buffers) {
-		kfree(bp->rx_buffers);
-		bp->rx_buffers = NULL;
-	}
-	if (bp->tx_buffers) {
-		kfree(bp->tx_buffers);
-		bp->tx_buffers = NULL;
-	}
+	kfree(bp->rx_buffers);
+	bp->rx_buffers = NULL;
+	kfree(bp->tx_buffers);
+	bp->tx_buffers = NULL;
 	if (bp->rx_ring) {
-		pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
-				    bp->rx_ring, bp->rx_ring_dma);
+		if (bp->flags & B44_FLAG_RX_RING_HACK) {
+			dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
+				         DMA_TABLE_BYTES,
+				         DMA_BIDIRECTIONAL);
+			kfree(bp->rx_ring);
+		} else
+			pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+					    bp->rx_ring, bp->rx_ring_dma);
 		bp->rx_ring = NULL;
+		bp->flags &= ~B44_FLAG_RX_RING_HACK;
 	}
 	if (bp->tx_ring) {
-		pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
-				    bp->tx_ring, bp->tx_ring_dma);
+		if (bp->flags & B44_FLAG_TX_RING_HACK) {
+			dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
+				         DMA_TABLE_BYTES,
+				         DMA_TO_DEVICE);
+			kfree(bp->tx_ring);
+		} else
+			pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
+					    bp->tx_ring, bp->tx_ring_dma);
 		bp->tx_ring = NULL;
+		bp->flags &= ~B44_FLAG_TX_RING_HACK;
 	}
 }
 
@@ -1118,12 +1183,56 @@
 
 	size = DMA_TABLE_BYTES;
 	bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
-	if (!bp->rx_ring)
-		goto out_err;
+	if (!bp->rx_ring) {
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *rx_ring;
+		dma_addr_t rx_ring_dma;
+
+		if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+			goto out_err;
+
+		memset(rx_ring, 0, size);
+		rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
+		                             DMA_TABLE_BYTES,
+		                             DMA_BIDIRECTIONAL);
+
+		if (rx_ring_dma + size > B44_DMA_MASK) {
+			kfree(rx_ring);
+			goto out_err;
+		}
+
+		bp->rx_ring = rx_ring;
+		bp->rx_ring_dma = rx_ring_dma;
+		bp->flags |= B44_FLAG_RX_RING_HACK;
+	}
 
 	bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
-	if (!bp->tx_ring)
-		goto out_err;
+	if (!bp->tx_ring) {
+		/* Allocation may have failed due to pci_alloc_consistent
+		   insisting on use of GFP_DMA, which is more restrictive
+		   than necessary...  */
+		struct dma_desc *tx_ring;
+		dma_addr_t tx_ring_dma;
+
+		if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
+			goto out_err;
+
+		memset(tx_ring, 0, size);
+		tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
+		                             DMA_TABLE_BYTES,
+		                             DMA_TO_DEVICE);
+
+		if (tx_ring_dma + size > B44_DMA_MASK) {
+			kfree(tx_ring);
+			goto out_err;
+		}
+
+		bp->tx_ring = tx_ring;
+		bp->tx_ring_dma = tx_ring_dma;
+		bp->flags |= B44_FLAG_TX_RING_HACK;
+	}
 
 	return 0;
 
@@ -1507,14 +1616,14 @@
 
 	cmd->advertising = 0;
 	if (bp->flags & B44_FLAG_ADV_10HALF)
-		cmd->advertising |= ADVERTISE_10HALF;
+		cmd->advertising |= ADVERTISED_10baseT_Half;
 	if (bp->flags & B44_FLAG_ADV_10FULL)
-		cmd->advertising |= ADVERTISE_10FULL;
+		cmd->advertising |= ADVERTISED_10baseT_Full;
 	if (bp->flags & B44_FLAG_ADV_100HALF)
-		cmd->advertising |= ADVERTISE_100HALF;
+		cmd->advertising |= ADVERTISED_100baseT_Half;
 	if (bp->flags & B44_FLAG_ADV_100FULL)
-		cmd->advertising |= ADVERTISE_100FULL;
-	cmd->advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+		cmd->advertising |= ADVERTISED_100baseT_Full;
+	cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
 	cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ?
 		SPEED_100 : SPEED_10;
 	cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
@@ -1676,6 +1785,7 @@
 	.set_pauseparam		= b44_set_pauseparam,
 	.get_msglevel		= b44_get_msglevel,
 	.set_msglevel		= b44_set_msglevel,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1718,6 +1828,7 @@
 	bp->dev->dev_addr[3] = eeprom[80];
 	bp->dev->dev_addr[4] = eeprom[83];
 	bp->dev->dev_addr[5] = eeprom[82];
+	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
 
 	bp->phy_addr = eeprom[90] & 0x1f;
 
@@ -1930,6 +2041,8 @@
 	b44_free_rings(bp);
 
 	spin_unlock_irq(&bp->lock);
+
+	free_irq(dev->irq, dev);
 	pci_disable_device(pdev);
 	return 0;
 }
@@ -1946,6 +2059,9 @@
 	if (!netif_running(dev))
 		return 0;
 
+	if (request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev))
+		printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
+
 	spin_lock_irq(&bp->lock);
 
 	b44_init_rings(bp);
@@ -1971,6 +2087,12 @@
 
 static int __init b44_init(void)
 {
+	unsigned int dma_desc_align_size = dma_get_cache_alignment();
+
+	/* Setup paramaters for syncing RX/TX DMA descriptors */
+	dma_desc_align_mask = ~(dma_desc_align_size - 1);
+	dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
+
 	return pci_module_init(&b44_driver);
 }
 
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 11c40a2..593cb0a 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -400,6 +400,8 @@
 #define B44_FLAG_ADV_100HALF	0x04000000
 #define B44_FLAG_ADV_100FULL	0x08000000
 #define B44_FLAG_INTERNAL_PHY	0x10000000
+#define B44_FLAG_RX_RING_HACK	0x20000000
+#define B44_FLAG_TX_RING_HACK	0x40000000
 
 	u32			rx_offset;
 
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 0ee2889..bbca8ae 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1690,10 +1690,8 @@
 {
 	macio_unregister_driver(&bmac_driver);
 
-	if (bmac_emergency_rxbuf != NULL) {
-		kfree(bmac_emergency_rxbuf);
-		bmac_emergency_rxbuf = NULL;
-	}
+	kfree(bmac_emergency_rxbuf);
+	bmac_emergency_rxbuf = NULL;
 }
 
 MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 3a2ace0..11d2523 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -314,20 +314,16 @@
 				    bp->tx_desc_ring, bp->tx_desc_mapping);
 		bp->tx_desc_ring = NULL;
 	}
-	if (bp->tx_buf_ring) {
-		kfree(bp->tx_buf_ring);
-		bp->tx_buf_ring = NULL;
-	}
+	kfree(bp->tx_buf_ring);
+	bp->tx_buf_ring = NULL;
 	if (bp->rx_desc_ring) {
 		pci_free_consistent(bp->pdev,
 				    sizeof(struct rx_bd) * RX_DESC_CNT,
 				    bp->rx_desc_ring, bp->rx_desc_mapping);
 		bp->rx_desc_ring = NULL;
 	}
-	if (bp->rx_buf_ring) {
-		kfree(bp->rx_buf_ring);
-		bp->rx_buf_ring = NULL;
-	}
+	kfree(bp->rx_buf_ring);
+	bp->rx_buf_ring = NULL;
 }
 
 static int
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f264ff1..8032126 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4241,6 +4241,43 @@
 	return 0;
 }
 
+static void bond_activebackup_xmit_copy(struct sk_buff *skb,
+                                        struct bonding *bond,
+                                        struct slave *slave)
+{
+	struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
+	struct ethhdr *eth_data;
+	u8 *hwaddr;
+	int res;
+
+	if (!skb2) {
+		printk(KERN_ERR DRV_NAME ": Error: "
+		       "bond_activebackup_xmit_copy(): skb_copy() failed\n");
+		return;
+	}
+
+	skb2->mac.raw = (unsigned char *)skb2->data;
+	eth_data = eth_hdr(skb2);
+
+	/* Pick an appropriate source MAC address
+	 *	-- use slave's perm MAC addr, unless used by bond
+	 *	-- otherwise, borrow active slave's perm MAC addr
+	 *	   since that will not be used
+	 */
+	hwaddr = slave->perm_hwaddr;
+	if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
+		hwaddr = bond->curr_active_slave->perm_hwaddr;
+
+	/* Set source MAC address appropriately */
+	memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
+
+	res = bond_dev_queue_xmit(bond, skb2, slave->dev);
+	if (res)
+		dev_kfree_skb(skb2);
+
+	return;
+}
+
 /*
  * in active-backup mode, we know that bond->curr_active_slave is always valid if
  * the bond has a usable interface.
@@ -4257,10 +4294,26 @@
 		goto out;
 	}
 
-	if (bond->curr_active_slave) { /* one usable interface */
-		res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+	if (!bond->curr_active_slave)
+		goto out;
+
+	/* Xmit IGMP frames on all slaves to ensure rapid fail-over
+	   for multicast traffic on snooping switches */
+	if (skb->protocol == __constant_htons(ETH_P_IP) &&
+	    skb->nh.iph->protocol == IPPROTO_IGMP) {
+		struct slave *slave, *active_slave;
+		int i;
+
+		active_slave = bond->curr_active_slave;
+		bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
+		                            active_slave->prev)
+			if (IS_UP(slave->dev) &&
+			    (slave->link == BOND_LINK_UP))
+				bond_activebackup_xmit_copy(skb, bond, slave);
 	}
 
+	res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
+
 out:
 	if (res) {
 		/* no suitable interface, frame not sent */
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 2e61742..50f43db 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -489,7 +489,7 @@
 /* local page allocation routines for the receive buffers. jumbo pages
  * require at least 8K contiguous and 8K aligned buffers.
  */
-static cas_page_t *cas_page_alloc(struct cas *cp, const int flags)
+static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
 {
 	cas_page_t *page;
 
@@ -561,7 +561,7 @@
 }
 
 /* replenish spares if needed */
-static void cas_spare_recover(struct cas *cp, const int flags)
+static void cas_spare_recover(struct cas *cp, const gfp_t flags)
 {
 	struct list_head list, *elem, *tmp;
 	int needed, i;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index a6078ad..bfdae10 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -182,6 +182,10 @@
 #define CIRRUS_DEFAULT_IRQ	VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
 static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
 static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
+#elif defined(CONFIG_MACH_MP1000)
+#include <asm/arch/mp1000-seprom.h>
+static unsigned int netcard_portlist[] __initdata = {MP1000_EIO_BASE+0x300, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_EINT3,0,0,0};
 #else
 static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -590,6 +594,10 @@
 			cnt -= j;
 		}
 	} else
+#elif defined(CONFIG_MACH_MP1000)
+	if (1) {
+		memcpy(dev->dev_addr, get_eeprom_mac_address(), ETH_ALEN);
+	} else
 #endif
 
         if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) == 
@@ -649,6 +657,10 @@
 	if (1) {
 		printk(KERN_NOTICE "cs89x0: No EEPROM on HiCO.SH4\n");
 	} else
+#elif defined(CONFIG_MACH_MP1000)
+	if (1) {
+		lp->force |= FORCE_RJ45;
+	} else
 #endif
 	if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
 		printk(KERN_WARNING "cs89x0: No EEPROM, relying on command line....\n");
@@ -1231,7 +1243,7 @@
 	else
 #endif
 	{
-#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105)
+#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) && !defined(CONFIG_MACH_MP1000)
 		if (((1 << dev->irq) & lp->irq_map) == 0) {
 			printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index decea26..f19d1eb 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -16,7 +16,7 @@
 
 #include <linux/config.h>
 
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
+#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) || defined (CONFIG_MACH_MP1000)
 /* IXDP2401/IXDP2801 uses dword-aligned register addressing */
 #define CS89x0_PORT(reg) ((reg) * 2)
 #else
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 521c831..f130bda 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -5,7 +5,7 @@
  *
  *      adopted from sunlance.c by Richard van den Berg
  *
- *      Copyright (C) 2002, 2003  Maciej W. Rozycki
+ *      Copyright (C) 2002, 2003, 2005  Maciej W. Rozycki
  *
  *      additional sources:
  *      - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
@@ -57,13 +57,15 @@
 #include <linux/string.h>
 
 #include <asm/addrspace.h>
+#include <asm/system.h>
+
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
 #include <asm/dec/kn01.h>
 #include <asm/dec/machtype.h>
+#include <asm/dec/system.h>
 #include <asm/dec/tc.h>
-#include <asm/system.h>
 
 static char version[] __devinitdata =
 "declance.c: v0.009 by Linux MIPS DECstation task force\n";
@@ -79,10 +81,6 @@
 #define PMAD_LANCE 2
 #define PMAX_LANCE 3
 
-#ifndef CONFIG_TC
-unsigned long system_base;
-unsigned long dmaptr;
-#endif
 
 #define LE_CSR0 0
 #define LE_CSR1 1
@@ -237,7 +235,7 @@
 /*
  * This works *only* for the ring descriptors
  */
-#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
+#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1)
 
 struct lance_private {
 	struct net_device *next;
@@ -697,12 +695,13 @@
 	spin_unlock(&lp->lock);
 }
 
-static void lance_dma_merr_int(const int irq, void *dev_id,
-				struct pt_regs *regs)
+static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
+				      struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 
 	printk("%s: DMA error\n", dev->name);
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t
@@ -1026,10 +1025,6 @@
 	unsigned long esar_base;
 	unsigned char *esar;
 
-#ifndef CONFIG_TC
-	system_base = KN01_LANCE_BASE;
-#endif
-
 	if (dec_lance_debug && version_printed++ == 0)
 		printk(version);
 
@@ -1062,16 +1057,16 @@
 	switch (type) {
 #ifdef CONFIG_TC
 	case ASIC_LANCE:
-		dev->base_addr = system_base + IOASIC_LANCE;
+		dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
 
 		/* buffer space for the on-board LANCE shared memory */
 		/*
 		 * FIXME: ugly hack!
 		 */
-		dev->mem_start = KSEG1ADDR(0x00020000);
+		dev->mem_start = CKSEG1ADDR(0x00020000);
 		dev->mem_end = dev->mem_start + 0x00020000;
 		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
-		esar_base = system_base + IOASIC_ESAR;
+		esar_base = CKSEG1ADDR(dec_kn_slot_base + IOASIC_ESAR);
 
 		/* Workaround crash with booting KN04 2.1k from Disk */
 		memset((void *)dev->mem_start, 0,
@@ -1101,14 +1096,14 @@
 		/* Setup I/O ASIC LANCE DMA.  */
 		lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
 		ioasic_write(IO_REG_LANCE_DMA_P,
-			     PHYSADDR(dev->mem_start) << 3);
+			     CPHYSADDR(dev->mem_start) << 3);
 
 		break;
 
 	case PMAD_LANCE:
 		claim_tc_card(slot);
 
-		dev->mem_start = get_tc_base_addr(slot);
+		dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
 		dev->base_addr = dev->mem_start + 0x100000;
 		dev->irq = get_tc_irq_nr(slot);
 		esar_base = dev->mem_start + 0x1c0002;
@@ -1137,9 +1132,9 @@
 
 	case PMAX_LANCE:
 		dev->irq = dec_interrupt[DEC_IRQ_LANCE];
-		dev->base_addr = KN01_LANCE_BASE;
-		dev->mem_start = KN01_LANCE_BASE + 0x01000000;
-		esar_base = KN01_RTC_BASE + 1;
+		dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE);
+		dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM);
+		esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1);
 		lp->dma_irq = -1;
 
 		/*
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index e54fc10..abce1f7 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1140,11 +1140,11 @@
 }
 
 static int
-dm9000_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+dm9000_drv_suspend(struct device *dev, pm_message_t state)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 
-	if (ndev && level == SUSPEND_DISABLE) {
+	if (ndev) {
 		if (netif_running(ndev)) {
 			netif_device_detach(ndev);
 			dm9000_shutdown(ndev);
@@ -1154,12 +1154,12 @@
 }
 
 static int
-dm9000_drv_resume(struct device *dev, u32 level)
+dm9000_drv_resume(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	board_info_t *db = (board_info_t *) ndev->priv;
 
-	if (ndev && level == RESUME_ENABLE) {
+	if (ndev) {
 
 		if (netif_running(ndev)) {
 			dm9000_reset(db);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 40887f0..eb169a8 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2201,6 +2201,7 @@
 	.phys_id		= e100_phys_id,
 	.get_stats_count	= e100_get_stats_count,
 	.get_ethtool_stats	= e100_get_ethtool_stats,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
@@ -2351,7 +2352,8 @@
 	e100_phy_init(nic);
 
 	memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
-	if(!is_valid_ether_addr(netdev->dev_addr)) {
+	memcpy(netdev->perm_addr, nic->eeprom, ETH_ALEN);
+	if(!is_valid_ether_addr(netdev->perm_addr)) {
 		DPRINTK(PROBE, ERR, "Invalid MAC address from "
 			"EEPROM, aborting.\n");
 		err = -EAGAIN;
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 092757b..3f653a9 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,6 +72,10 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
 
 #define BAR_0		0
 #define BAR_1		1
@@ -165,10 +169,33 @@
 	uint16_t next_to_watch;
 };
 
-struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
-struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
+struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
 
-struct e1000_desc_ring {
+struct e1000_tx_ring {
+	/* pointer to the descriptor ring memory */
+	void *desc;
+	/* physical address of the descriptor ring */
+	dma_addr_t dma;
+	/* length of descriptor ring in bytes */
+	unsigned int size;
+	/* number of descriptors in the ring */
+	unsigned int count;
+	/* next descriptor to associate a buffer with */
+	unsigned int next_to_use;
+	/* next descriptor to check for DD status bit */
+	unsigned int next_to_clean;
+	/* array of buffer information structs */
+	struct e1000_buffer *buffer_info;
+
+	struct e1000_buffer previous_buffer_info;
+	spinlock_t tx_lock;
+	uint16_t tdh;
+	uint16_t tdt;
+	uint64_t pkt;
+};
+
+struct e1000_rx_ring {
 	/* pointer to the descriptor ring memory */
 	void *desc;
 	/* physical address of the descriptor ring */
@@ -186,6 +213,10 @@
 	/* arrays of page information for packet split */
 	struct e1000_ps_page *ps_page;
 	struct e1000_ps_page_dma *ps_page_dma;
+
+	uint16_t rdh;
+	uint16_t rdt;
+	uint64_t pkt;
 };
 
 #define E1000_DESC_UNUSED(R) \
@@ -227,9 +258,10 @@
 	unsigned long led_status;
 
 	/* TX */
-	struct e1000_desc_ring tx_ring;
-	struct e1000_buffer previous_buffer_info;
-	spinlock_t tx_lock;
+	struct e1000_tx_ring *tx_ring;      /* One per active queue */
+#ifdef CONFIG_E1000_MQ
+	struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
+#endif
 	uint32_t txd_cmd;
 	uint32_t tx_int_delay;
 	uint32_t tx_abs_int_delay;
@@ -246,19 +278,33 @@
 
 	/* RX */
 #ifdef CONFIG_E1000_NAPI
-	boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
-			  int work_to_do);
+	boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+			       struct e1000_rx_ring *rx_ring,
+			       int *work_done, int work_to_do);
 #else
-	boolean_t (*clean_rx) (struct e1000_adapter *adapter);
+	boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+			       struct e1000_rx_ring *rx_ring);
 #endif
-	void (*alloc_rx_buf) (struct e1000_adapter *adapter);
-	struct e1000_desc_ring rx_ring;
+	void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+			      struct e1000_rx_ring *rx_ring);
+	struct e1000_rx_ring *rx_ring;      /* One per active queue */
+#ifdef CONFIG_E1000_NAPI
+	struct net_device *polling_netdev;  /* One per active queue */
+#endif
+#ifdef CONFIG_E1000_MQ
+	struct net_device **cpu_netdev;     /* per-cpu */
+	struct call_async_data_struct rx_sched_call_data;
+	int cpu_for_queue[4];
+#endif
+	int num_queues;
+
 	uint64_t hw_csum_err;
 	uint64_t hw_csum_good;
+	uint64_t rx_hdr_split;
 	uint32_t rx_int_delay;
 	uint32_t rx_abs_int_delay;
 	boolean_t rx_csum;
-	boolean_t rx_ps;
+	unsigned int rx_ps_pages;
 	uint32_t gorcl;
 	uint64_t gorcl_old;
 	uint16_t rx_ps_bsize0;
@@ -278,8 +324,8 @@
 	struct e1000_phy_stats phy_stats;
 
 	uint32_t test_icr;
-	struct e1000_desc_ring test_tx_ring;
-	struct e1000_desc_ring test_rx_ring;
+	struct e1000_tx_ring test_tx_ring;
+	struct e1000_rx_ring test_rx_ring;
 
 
 	int msg_enable;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index f133ff0..9c7feae 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -39,10 +39,10 @@
 extern void e1000_down(struct e1000_adapter *adapter);
 extern void e1000_reset(struct e1000_adapter *adapter);
 extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-extern int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_tx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
 extern void e1000_update_stats(struct e1000_adapter *adapter);
 
 struct e1000_stats {
@@ -91,7 +91,8 @@
 	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
 	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
 	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+	{ "rx_header_split", E1000_STAT(rx_hdr_split) },
 };
 #define E1000_STATS_LEN	\
 	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -546,8 +547,10 @@
 	ret_val = e1000_write_eeprom(hw, first_word,
 				     last_word - first_word + 1, eeprom_buff);
 
-	/* Update the checksum over the first part of the EEPROM if needed */
-	if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
+	/* Update the checksum over the first part of the EEPROM if needed 
+	 * and flush shadow RAM for 82573 conrollers */
+	if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) || 
+				(hw->mac_type == e1000_82573)))
 		e1000_update_eeprom_checksum(hw);
 
 	kfree(eeprom_buff);
@@ -576,8 +579,8 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	e1000_mac_type mac_type = adapter->hw.mac_type;
-	struct e1000_desc_ring *txdr = &adapter->tx_ring;
-	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+	struct e1000_tx_ring *txdr = adapter->tx_ring;
+	struct e1000_rx_ring *rxdr = adapter->rx_ring;
 
 	ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
 		E1000_MAX_82544_RXD;
@@ -597,20 +600,40 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	e1000_mac_type mac_type = adapter->hw.mac_type;
-	struct e1000_desc_ring *txdr = &adapter->tx_ring;
-	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
-	struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
-	int err;
+	struct e1000_tx_ring *txdr, *tx_old, *tx_new;
+	struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
+	int i, err, tx_ring_size, rx_ring_size;
+
+	tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+	rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+
+	if (netif_running(adapter->netdev))
+		e1000_down(adapter);
 
 	tx_old = adapter->tx_ring;
 	rx_old = adapter->rx_ring;
 
+	adapter->tx_ring = kmalloc(tx_ring_size, GFP_KERNEL);
+	if (!adapter->tx_ring) {
+		err = -ENOMEM;
+		goto err_setup_rx;
+	}
+	memset(adapter->tx_ring, 0, tx_ring_size);
+
+	adapter->rx_ring = kmalloc(rx_ring_size, GFP_KERNEL);
+	if (!adapter->rx_ring) {
+		kfree(adapter->tx_ring);
+		err = -ENOMEM;
+		goto err_setup_rx;
+	}
+	memset(adapter->rx_ring, 0, rx_ring_size);
+
+	txdr = adapter->tx_ring;
+	rxdr = adapter->rx_ring;
+
 	if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
 
-	if(netif_running(adapter->netdev))
-		e1000_down(adapter);
-
 	rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
 	rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
 		E1000_MAX_RXD : E1000_MAX_82544_RXD));
@@ -621,11 +644,16 @@
 		E1000_MAX_TXD : E1000_MAX_82544_TXD));
 	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
 
+	for (i = 0; i < adapter->num_queues; i++) {
+		txdr[i].count = txdr->count;
+		rxdr[i].count = rxdr->count;
+	}
+
 	if(netif_running(adapter->netdev)) {
 		/* Try to get new resources before deleting old */
-		if((err = e1000_setup_rx_resources(adapter)))
+		if ((err = e1000_setup_all_rx_resources(adapter)))
 			goto err_setup_rx;
-		if((err = e1000_setup_tx_resources(adapter)))
+		if ((err = e1000_setup_all_tx_resources(adapter)))
 			goto err_setup_tx;
 
 		/* save the new, restore the old in order to free it,
@@ -635,8 +663,10 @@
 		tx_new = adapter->tx_ring;
 		adapter->rx_ring = rx_old;
 		adapter->tx_ring = tx_old;
-		e1000_free_rx_resources(adapter);
-		e1000_free_tx_resources(adapter);
+		e1000_free_all_rx_resources(adapter);
+		e1000_free_all_tx_resources(adapter);
+		kfree(tx_old);
+		kfree(rx_old);
 		adapter->rx_ring = rx_new;
 		adapter->tx_ring = tx_new;
 		if((err = e1000_up(adapter)))
@@ -645,7 +675,7 @@
 
 	return 0;
 err_setup_tx:
-	e1000_free_rx_resources(adapter);
+	e1000_free_all_rx_resources(adapter);
 err_setup_rx:
 	adapter->rx_ring = rx_old;
 	adapter->tx_ring = tx_old;
@@ -696,6 +726,11 @@
 	 * Some bits that get toggled are ignored.
 	 */
         switch (adapter->hw.mac_type) {
+	/* there are several bits on newer hardware that are r/w */
+	case e1000_82571:
+	case e1000_82572:
+		toggle = 0x7FFFF3FF;
+		break;
 	case e1000_82573:
 		toggle = 0x7FFFF033;
 		break;
@@ -898,8 +933,8 @@
 static void
 e1000_free_desc_rings(struct e1000_adapter *adapter)
 {
-	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	int i;
 
@@ -930,19 +965,16 @@
 	if(rxdr->desc)
 		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
 
-	if(txdr->buffer_info)
-		kfree(txdr->buffer_info);
-	if(rxdr->buffer_info)
-		kfree(rxdr->buffer_info);
-
+	kfree(txdr->buffer_info);
+	kfree(rxdr->buffer_info);
 	return;
 }
 
 static int
 e1000_setup_desc_rings(struct e1000_adapter *adapter)
 {
-	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	uint32_t rctl;
 	int size, i, ret_val;
@@ -1245,6 +1277,8 @@
 	case e1000_82541_rev_2:
 	case e1000_82547:
 	case e1000_82547_rev_2:
+	case e1000_82571:
+	case e1000_82572:
 	case e1000_82573:
 		return e1000_integrated_phy_loopback(adapter);
 		break;
@@ -1340,8 +1374,8 @@
 static int
 e1000_run_loopback_test(struct e1000_adapter *adapter)
 {
-	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
-	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	int i, j, k, l, lc, good_cnt, ret_val=0;
 	unsigned long time;
@@ -1509,6 +1543,7 @@
 		data[2] = 0;
 		data[3] = 0;
 	}
+	msleep_interruptible(4 * 1000);
 }
 
 static void
@@ -1625,7 +1660,7 @@
 	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
 		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
 
-	if(adapter->hw.mac_type < e1000_82573) {
+	if(adapter->hw.mac_type < e1000_82571) {
 		if(!adapter->blink_timer.function) {
 			init_timer(&adapter->blink_timer);
 			adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1739,6 +1774,7 @@
 	.phys_id                = e1000_phys_id,
 	.get_stats_count        = e1000_get_stats_count,
 	.get_ethtool_stats      = e1000_get_ethtool_stats,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 void e1000_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 045f542..8fc876d 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -83,14 +83,14 @@
 
 static const
 uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
-    { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
-      22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
-      32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
-      43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
-      57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
-      73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
-      91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
-      108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
+    { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+      0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+      6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+      21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
+      40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
+      60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
+      83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
+      104, 109, 114, 118, 121, 124};
 
 
 /******************************************************************************
@@ -286,7 +286,6 @@
     case E1000_DEV_ID_82546GB_FIBER:
     case E1000_DEV_ID_82546GB_SERDES:
     case E1000_DEV_ID_82546GB_PCIE:
-    case E1000_DEV_ID_82546GB_QUAD_COPPER:
         hw->mac_type = e1000_82546_rev_3;
         break;
     case E1000_DEV_ID_82541EI:
@@ -305,8 +304,19 @@
     case E1000_DEV_ID_82547GI:
         hw->mac_type = e1000_82547_rev_2;
         break;
+    case E1000_DEV_ID_82571EB_COPPER:
+    case E1000_DEV_ID_82571EB_FIBER:
+    case E1000_DEV_ID_82571EB_SERDES:
+            hw->mac_type = e1000_82571;
+        break;
+    case E1000_DEV_ID_82572EI_COPPER:
+    case E1000_DEV_ID_82572EI_FIBER:
+    case E1000_DEV_ID_82572EI_SERDES:
+        hw->mac_type = e1000_82572;
+        break;
     case E1000_DEV_ID_82573E:
     case E1000_DEV_ID_82573E_IAMT:
+    case E1000_DEV_ID_82573L:
         hw->mac_type = e1000_82573;
         break;
     default:
@@ -315,6 +325,8 @@
     }
 
     switch(hw->mac_type) {
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         hw->eeprom_semaphore_present = TRUE;
         /* fall through */
@@ -351,6 +363,8 @@
     switch (hw->device_id) {
     case E1000_DEV_ID_82545GM_SERDES:
     case E1000_DEV_ID_82546GB_SERDES:
+    case E1000_DEV_ID_82571EB_SERDES:
+    case E1000_DEV_ID_82572EI_SERDES:
         hw->media_type = e1000_media_type_internal_serdes;
         break;
     default:
@@ -523,6 +537,8 @@
             E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
             E1000_WRITE_FLUSH(hw);
             /* fall through */
+        case e1000_82571:
+        case e1000_82572:
             ret_val = e1000_get_auto_rd_done(hw);
             if(ret_val)
                 /* We don't want to continue accessing MAC registers. */
@@ -683,6 +699,9 @@
         switch (hw->mac_type) {
         default:
             break;
+        case e1000_82571:
+        case e1000_82572:
+            ctrl |= (1 << 22);
         case e1000_82573:
             ctrl |= E1000_TXDCTL_COUNT_DESC;
             break;
@@ -694,6 +713,26 @@
         e1000_enable_tx_pkt_filtering(hw); 
     }
 
+    switch (hw->mac_type) {
+    default:
+        break;
+    case e1000_82571:
+    case e1000_82572:
+        ctrl = E1000_READ_REG(hw, TXDCTL1);
+        ctrl &= ~E1000_TXDCTL_WTHRESH;
+        ctrl |= E1000_TXDCTL_COUNT_DESC | E1000_TXDCTL_FULL_TX_DESC_WB;
+        ctrl |= (1 << 22);
+        E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+        break;
+    }
+
+
+
+    if (hw->mac_type == e1000_82573) {
+        uint32_t gcr = E1000_READ_REG(hw, GCR);
+        gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+        E1000_WRITE_REG(hw, GCR, gcr);
+    }
 
     /* Clear all of the statistics registers (clear on read).  It is
      * important that we do this after we have tried to establish link
@@ -878,6 +917,14 @@
 
     DEBUGFUNC("e1000_setup_fiber_serdes_link");
 
+    /* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
+     * until explicitly turned off or a power cycle is performed.  A read to
+     * the register does not indicate its status.  Therefore, we ensure
+     * loopback mode is disabled during initialization.
+     */
+    if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
+        E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+
     /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
      * set when the optics detect a signal. On older adapters, it will be
      * cleared when there is a signal.  This applies to fiber media only.
@@ -2943,6 +2990,8 @@
 
     switch (hw->mac_type) {
     case e1000_82541_rev_2:
+    case e1000_82571:
+    case e1000_82572:
         ret_val = e1000_phy_hw_reset(hw);
         if(ret_val)
             return ret_val;
@@ -2981,6 +3030,16 @@
 
     DEBUGFUNC("e1000_detect_gig_phy");
 
+    /* The 82571 firmware may still be configuring the PHY.  In this
+     * case, we cannot access the PHY until the configuration is done.  So
+     * we explicitly set the PHY values. */
+    if(hw->mac_type == e1000_82571 ||
+       hw->mac_type == e1000_82572) {
+        hw->phy_id = IGP01E1000_I_PHY_ID;
+        hw->phy_type = e1000_phy_igp_2;
+        return E1000_SUCCESS;
+    }
+
     /* Read the PHY ID Registers to identify which PHY is onboard. */
     ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
     if(ret_val)
@@ -3334,6 +3393,21 @@
         eeprom->use_eerd = FALSE;
         eeprom->use_eewr = FALSE;
         break;
+    case e1000_82571:
+    case e1000_82572:
+        eeprom->type = e1000_eeprom_spi;
+        eeprom->opcode_bits = 8;
+        eeprom->delay_usec = 1;
+        if (eecd & E1000_EECD_ADDR_BITS) {
+            eeprom->page_size = 32;
+            eeprom->address_bits = 16;
+        } else {
+            eeprom->page_size = 8;
+            eeprom->address_bits = 8;
+        }
+        eeprom->use_eerd = FALSE;
+        eeprom->use_eewr = FALSE;
+        break;
     case e1000_82573:
         eeprom->type = e1000_eeprom_spi;
         eeprom->opcode_bits = 8;
@@ -3543,25 +3617,26 @@
     eecd = E1000_READ_REG(hw, EECD);
 
     if (hw->mac_type != e1000_82573) {
-    /* Request EEPROM Access */
-    if(hw->mac_type > e1000_82544) {
-        eecd |= E1000_EECD_REQ;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        eecd = E1000_READ_REG(hw, EECD);
-        while((!(eecd & E1000_EECD_GNT)) &&
-              (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
-            i++;
-            udelay(5);
-            eecd = E1000_READ_REG(hw, EECD);
-        }
-        if(!(eecd & E1000_EECD_GNT)) {
-            eecd &= ~E1000_EECD_REQ;
+        /* Request EEPROM Access */
+        if(hw->mac_type > e1000_82544) {
+            eecd |= E1000_EECD_REQ;
             E1000_WRITE_REG(hw, EECD, eecd);
-            DEBUGOUT("Could not acquire EEPROM grant\n");
-            return -E1000_ERR_EEPROM;
+            eecd = E1000_READ_REG(hw, EECD);
+            while((!(eecd & E1000_EECD_GNT)) &&
+                  (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+                i++;
+                udelay(5);
+                eecd = E1000_READ_REG(hw, EECD);
+            }
+            if(!(eecd & E1000_EECD_GNT)) {
+                eecd &= ~E1000_EECD_REQ;
+                E1000_WRITE_REG(hw, EECD, eecd);
+                DEBUGOUT("Could not acquire EEPROM grant\n");
+                e1000_put_hw_eeprom_semaphore(hw);
+                return -E1000_ERR_EEPROM;
+            }
         }
     }
-    }
 
     /* Setup EEPROM for Read/Write */
 
@@ -4064,7 +4139,7 @@
         return -E1000_ERR_EEPROM;
     }
 
-    /* 82573 reads only through eerd */
+    /* 82573 writes only through eewr */
     if(eeprom->use_eewr == TRUE)
         return e1000_write_eeprom_eewr(hw, offset, words, data);
 
@@ -4353,9 +4428,16 @@
         hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
         hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
     }
-    if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
-       (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
+    switch (hw->mac_type) {
+    default:
+        break;
+    case e1000_82546:
+    case e1000_82546_rev_3:
+    case e1000_82571:
+        if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
             hw->perm_mac_addr[5] ^= 0x01;
+        break;
+    }
 
     for(i = 0; i < NODE_ADDRESS_SIZE; i++)
         hw->mac_addr[i] = hw->perm_mac_addr[i];
@@ -4385,6 +4467,12 @@
     e1000_rar_set(hw, hw->mac_addr, 0);
 
     rar_num = E1000_RAR_ENTRIES;
+
+    /* Reserve a spot for the Locally Administered Address to work around
+     * an 82571 issue in which a reset on one port will reload the MAC on
+     * the other port. */
+    if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+        rar_num -= 1;
     /* Zero out the other 15 receive addresses. */
     DEBUGOUT("Clearing RAR[1-15]\n");
     for(i = 1; i < rar_num; i++) {
@@ -4427,6 +4515,12 @@
     /* Clear RAR[1-15] */
     DEBUGOUT(" Clearing RAR[1-15]\n");
     num_rar_entry = E1000_RAR_ENTRIES;
+    /* Reserve a spot for the Locally Administered Address to work around
+     * an 82571 issue in which a reset on one port will reload the MAC on
+     * the other port. */
+    if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
+        num_rar_entry -= 1;
+
     for(i = rar_used_count; i < num_rar_entry; i++) {
         E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
         E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -4984,7 +5078,6 @@
     temp = E1000_READ_REG(hw, ICTXQEC);
     temp = E1000_READ_REG(hw, ICTXQMTC);
     temp = E1000_READ_REG(hw, ICRXDMTC);
-
 }
 
 /******************************************************************************
@@ -5151,6 +5244,8 @@
         hw->bus_speed = e1000_bus_speed_unknown;
         hw->bus_width = e1000_bus_width_unknown;
         break;
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         hw->bus_type = e1000_bus_type_pci_express;
         hw->bus_speed = e1000_bus_speed_2500;
@@ -5250,6 +5345,7 @@
     int32_t ret_val;
     uint16_t agc_value = 0;
     uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+    uint16_t max_agc = 0;
     uint16_t i, phy_data;
     uint16_t cable_length;
 
@@ -5338,6 +5434,40 @@
                        IGP01E1000_AGC_RANGE) : 0;
         *max_length = e1000_igp_cable_length_table[agc_value] +
                       IGP01E1000_AGC_RANGE;
+    } else if (hw->phy_type == e1000_phy_igp_2) {
+        uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+                                                         {IGP02E1000_PHY_AGC_A,
+                                                          IGP02E1000_PHY_AGC_B,
+                                                          IGP02E1000_PHY_AGC_C,
+                                                          IGP02E1000_PHY_AGC_D};
+        /* Read the AGC registers for all channels */
+        for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
+            ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+            if (ret_val)
+                return ret_val;
+
+	    /* Getting bits 15:9, which represent the combination of course and
+             * fine gain values.  The result is a number that can be put into
+             * the lookup table to obtain the approximate cable length. */
+            cur_agc = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+                      IGP02E1000_AGC_LENGTH_MASK;
+
+            /* Remove min & max AGC values from calculation. */
+            if (e1000_igp_2_cable_length_table[min_agc] > e1000_igp_2_cable_length_table[cur_agc])
+                min_agc = cur_agc;
+	    if (e1000_igp_2_cable_length_table[max_agc] < e1000_igp_2_cable_length_table[cur_agc])
+                max_agc = cur_agc;
+
+            agc_value += e1000_igp_2_cable_length_table[cur_agc];
+        }
+
+        agc_value -= (e1000_igp_2_cable_length_table[min_agc] + e1000_igp_2_cable_length_table[max_agc]);
+        agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
+
+        /* Calculate cable length with the error range of +/- 10 meters. */
+        *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+                       (agc_value - IGP02E1000_AGC_RANGE) : 0;
+        *max_length = agc_value + IGP02E1000_AGC_RANGE;
     }
 
     return E1000_SUCCESS;
@@ -6465,6 +6595,8 @@
     default:
         msec_delay(5);
         break;
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         while(timeout) {
             if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
@@ -6494,10 +6626,31 @@
 int32_t
 e1000_get_phy_cfg_done(struct e1000_hw *hw)
 {
+    int32_t timeout = PHY_CFG_TIMEOUT;
+    uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
+
     DEBUGFUNC("e1000_get_phy_cfg_done");
 
-    /* Simply wait for 10ms */
-    msec_delay(10);
+    switch (hw->mac_type) {
+    default:
+        msec_delay(10);
+        break;
+    case e1000_82571:
+    case e1000_82572:
+        while (timeout) {
+            if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+                break;
+            else
+                msec_delay(1);
+            timeout--;
+        }
+
+        if (!timeout) {
+            DEBUGOUT("MNG configuration cycle has not completed.\n");
+            return -E1000_ERR_RESET;
+        }
+        break;
+    }
 
     return E1000_SUCCESS;
 }
@@ -6569,8 +6722,7 @@
         return;
 
     swsm = E1000_READ_REG(hw, SWSM);
-    /* Release both semaphores. */
-    swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+        swsm &= ~(E1000_SWSM_SWESMBI);
     E1000_WRITE_REG(hw, SWSM, swsm);
 }
 
@@ -6606,6 +6758,8 @@
      * if this is the case.  We read FWSM to determine the manageability mode.
      */
     switch (hw->mac_type) {
+    case e1000_82571:
+    case e1000_82572:
     case e1000_82573:
         fwsm = E1000_READ_REG(hw, FWSM);
         if((fwsm & E1000_FWSM_MODE_MASK) != 0)
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 51c2b3a..4f2c196 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -57,6 +57,8 @@
     e1000_82541_rev_2,
     e1000_82547,
     e1000_82547_rev_2,
+    e1000_82571,
+    e1000_82572,
     e1000_82573,
     e1000_num_macs
 } e1000_mac_type;
@@ -478,10 +480,16 @@
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82546GB_PCIE        0x108A
 #define E1000_DEV_ID_82547EI             0x1019
+#define E1000_DEV_ID_82571EB_COPPER      0x105E
+#define E1000_DEV_ID_82571EB_FIBER       0x105F
+#define E1000_DEV_ID_82571EB_SERDES      0x1060
+#define E1000_DEV_ID_82572EI_COPPER      0x107D
+#define E1000_DEV_ID_82572EI_FIBER       0x107E
+#define E1000_DEV_ID_82572EI_SERDES      0x107F
 #define E1000_DEV_ID_82573E              0x108B
 #define E1000_DEV_ID_82573E_IAMT         0x108C
+#define E1000_DEV_ID_82573L              0x109A
 
-#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -833,6 +841,8 @@
 #define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 #define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
 
+#define E1000_DISABLE_SERDES_LOOPBACK   0x0400
+
 /* Register Set. (82543, 82544)
  *
  * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
@@ -853,6 +863,7 @@
 #define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
 #define E1000_FLA      0x0001C  /* Flash Access - RW */
 #define E1000_MDIC     0x00020  /* MDI Control - RW */
+#define E1000_SCTL     0x00024  /* SerDes Control - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
 #define E1000_FCT      0x00030  /* Flow Control Type - RW */
@@ -864,6 +875,12 @@
 #define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
 #define E1000_IAM      0x000E0  /* Interrupt Acknowledge Auto Mask */
 #define E1000_RCTL     0x00100  /* RX Control - RW */
+#define E1000_RDTR1    0x02820  /* RX Delay Timer (1) - RW */
+#define E1000_RDBAL1   0x02900  /* RX Descriptor Base Address Low (1) - RW */
+#define E1000_RDBAH1   0x02904  /* RX Descriptor Base Address High (1) - RW */
+#define E1000_RDLEN1   0x02908  /* RX Descriptor Length (1) - RW */
+#define E1000_RDH1     0x02910  /* RX Descriptor Head (1) - RW */
+#define E1000_RDT1     0x02918  /* RX Descriptor Tail (1) - RW */
 #define E1000_FCTTV    0x00170  /* Flow Control Transmit Timer Value - RW */
 #define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
 #define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
@@ -895,6 +912,12 @@
 #define E1000_RDH      0x02810  /* RX Descriptor Head - RW */
 #define E1000_RDT      0x02818  /* RX Descriptor Tail - RW */
 #define E1000_RDTR     0x02820  /* RX Delay Timer - RW */
+#define E1000_RDBAL0   E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
+#define E1000_RDBAH0   E1000_RDBAH /* RX Desc Base Address High (0) - RW */
+#define E1000_RDLEN0   E1000_RDLEN /* RX Desc Length (0) - RW */
+#define E1000_RDH0     E1000_RDH   /* RX Desc Head (0) - RW */
+#define E1000_RDT0     E1000_RDT   /* RX Desc Tail (0) - RW */
+#define E1000_RDTR0    E1000_RDTR  /* RX Delay Timer (0) - RW */
 #define E1000_RXDCTL   0x02828  /* RX Descriptor Control - RW */
 #define E1000_RADV     0x0282C  /* RX Interrupt Absolute Delay Timer - RW */
 #define E1000_RSRPD    0x02C00  /* RX Small Packet Detect - RW */
@@ -980,15 +1003,15 @@
 #define E1000_BPTC     0x040F4  /* Broadcast Packets TX Count - R/clr */
 #define E1000_TSCTC    0x040F8  /* TCP Segmentation Context TX - R/clr */
 #define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC       0x4100  /* Interrupt Assertion Count */
-#define E1000_ICRXPTC   0x4104  /* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC   0x4108  /* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC   0x410C  /* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC   0x4110  /* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC   0x4118  /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC  0x411C  /* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC  0x4120  /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC    0x4124  /* Interrupt Cause Receiver Overrun Count */
+#define E1000_IAC      0x04100  /* Interrupt Assertion Count */
+#define E1000_ICRXPTC  0x04104  /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC  0x04108  /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC  0x0410C  /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC  0x04110  /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC  0x04118  /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C  /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x04120  /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC   0x04124  /* Interrupt Cause Receiver Overrun Count */
 #define E1000_RXCSUM   0x05000  /* RX Checksum Control - RW */
 #define E1000_RFCTL    0x05008  /* Receive Filter Control*/
 #define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
@@ -1018,6 +1041,14 @@
 #define E1000_FWSM      0x05B54 /* FW Semaphore */
 #define E1000_FFLT_DBG  0x05F04 /* Debug Register */
 #define E1000_HICR      0x08F00 /* Host Inteface Control */
+
+/* RSS registers */
+#define E1000_CPUVEC    0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC      0x05818 /* Multiple Receive Control - RW */
+#define E1000_RETA      0x05C00 /* Redirection Table - RW Array */
+#define E1000_RSSRK     0x05C80 /* RSS Random Key - RW Array */
+#define E1000_RSSIM     0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR     0x05868 /* RSS Interrupt Request */
 /* Register Set (82542)
  *
  * Some of the 82542 registers are located at different offsets than they are
@@ -1032,6 +1063,7 @@
 #define E1000_82542_CTRL_EXT E1000_CTRL_EXT
 #define E1000_82542_FLA      E1000_FLA
 #define E1000_82542_MDIC     E1000_MDIC
+#define E1000_82542_SCTL     E1000_SCTL
 #define E1000_82542_FCAL     E1000_FCAL
 #define E1000_82542_FCAH     E1000_FCAH
 #define E1000_82542_FCT      E1000_FCT
@@ -1049,6 +1081,18 @@
 #define E1000_82542_RDLEN    0x00118
 #define E1000_82542_RDH      0x00120
 #define E1000_82542_RDT      0x00128
+#define E1000_82542_RDTR0    E1000_82542_RDTR
+#define E1000_82542_RDBAL0   E1000_82542_RDBAL
+#define E1000_82542_RDBAH0   E1000_82542_RDBAH
+#define E1000_82542_RDLEN0   E1000_82542_RDLEN
+#define E1000_82542_RDH0     E1000_82542_RDH
+#define E1000_82542_RDT0     E1000_82542_RDT
+#define E1000_82542_RDTR1    0x00130
+#define E1000_82542_RDBAL1   0x00138
+#define E1000_82542_RDBAH1   0x0013C
+#define E1000_82542_RDLEN1   0x00140
+#define E1000_82542_RDH1     0x00148
+#define E1000_82542_RDT1     0x00150
 #define E1000_82542_FCRTH    0x00160
 #define E1000_82542_FCRTL    0x00168
 #define E1000_82542_FCTTV    E1000_FCTTV
@@ -1197,6 +1241,13 @@
 #define E1000_82542_ICRXOC      E1000_ICRXOC
 #define E1000_82542_HICR        E1000_HICR
 
+#define E1000_82542_CPUVEC      E1000_CPUVEC
+#define E1000_82542_MRQC        E1000_MRQC
+#define E1000_82542_RETA        E1000_RETA
+#define E1000_82542_RSSRK       E1000_RSSRK
+#define E1000_82542_RSSIM       E1000_RSSIM
+#define E1000_82542_RSSIR       E1000_RSSIR
+
 /* Statistics counters collected by the MAC */
 struct e1000_hw_stats {
     uint64_t crcerrs;
@@ -1336,6 +1387,7 @@
     boolean_t serdes_link_down;
     boolean_t tbi_compatibility_en;
     boolean_t tbi_compatibility_on;
+    boolean_t laa_is_present;
     boolean_t phy_reset_disable;
     boolean_t fc_send_xon;
     boolean_t fc_strict_ieee;
@@ -1374,6 +1426,7 @@
 #define E1000_CTRL_BEM32    0x00000400  /* Big Endian 32 mode */
 #define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
+#define E1000_CTRL_D_UD_EN  0x00002000  /* Dock/Undock enable */
 #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
@@ -1491,6 +1544,8 @@
 #define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
 #define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
 #define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
+#define E1000_CTRL_EXT_CANC           0x04000000  /* Interrupt delay cancellation */
+#define E1000_CTRL_EXT_DRV_LOAD       0x10000000  /* Driver loaded bit for FW */
 #define E1000_CTRL_EXT_IAME           0x08000000  /* Interrupt acknowledge Auto-mask */
 #define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000  /* Clear Interrupt timers after IMS clear */
 
@@ -1524,6 +1579,7 @@
 #define E1000_LEDCTL_LED2_BLINK           0x00800000
 #define E1000_LEDCTL_LED3_MODE_MASK       0x0F000000
 #define E1000_LEDCTL_LED3_MODE_SHIFT      24
+#define E1000_LEDCTL_LED3_BLINK_RATE      0x20000000
 #define E1000_LEDCTL_LED3_IVRT            0x40000000
 #define E1000_LEDCTL_LED3_BLINK           0x80000000
 
@@ -1784,6 +1840,16 @@
 #define E1000_RXCSUM_IPPCSE    0x00001000   /* IP payload checksum enable */
 #define E1000_RXCSUM_PCSD      0x00002000   /* packet checksum disabled */
 
+/* Multiple Receive Queue Control */
+#define E1000_MRQC_ENABLE_MASK              0x00000003
+#define E1000_MRQC_ENABLE_RSS_2Q            0x00000001
+#define E1000_MRQC_ENABLE_RSS_INT           0x00000004
+#define E1000_MRQC_RSS_FIELD_MASK           0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP       0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4           0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP       0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX        0x00080000
+#define E1000_MRQC_RSS_FIELD_IPV6           0x00100000
 
 /* Definitions for power management and wakeup registers */
 /* Wake Up Control */
@@ -1928,6 +1994,7 @@
 #define E1000_MDALIGN          4096
 
 #define E1000_GCR_BEM32                 0x00400000
+#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
 #define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
 #define E1000_FACTPS_LAN0_VALID                     0x00000004
@@ -1980,6 +2047,7 @@
 /* EEPROM Word Offsets */
 #define EEPROM_COMPAT                 0x0003
 #define EEPROM_ID_LED_SETTINGS        0x0004
+#define EEPROM_VERSION                0x0005
 #define EEPROM_SERDES_AMPLITUDE       0x0006 /* For SERDES output amplitude adjustment. */
 #define EEPROM_PHY_CLASS_WORD         0x0007
 #define EEPROM_INIT_CONTROL1_REG      0x000A
@@ -1990,6 +2058,8 @@
 #define EEPROM_FLASH_VERSION          0x0032
 #define EEPROM_CHECKSUM_REG           0x003F
 
+#define E1000_EEPROM_CFG_DONE         0x00040000   /* MNG config cycle done */
+
 /* Word definitions for ID LED Settings */
 #define ID_LED_RESERVED_0000 0x0000
 #define ID_LED_RESERVED_FFFF 0xFFFF
@@ -2108,6 +2178,8 @@
 #define E1000_PBA_22K 0x0016
 #define E1000_PBA_24K 0x0018
 #define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_38K 0x0026
 #define E1000_PBA_40K 0x0028
 #define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
 
@@ -2592,11 +2664,11 @@
 
 /* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
 #define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
-#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113
 
 /* The precision error of the cable length is +/- 10 meters */
 #define IGP01E1000_AGC_RANGE    10
-#define IGP02E1000_AGC_RANGE    10
+#define IGP02E1000_AGC_RANGE    15
 
 /* IGP01E1000 PCS Initialization register */
 /* bits 3:6 in the PCS registers stores the channels polarity */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index ee687c9..efbbda7 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -43,7 +43,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION		"6.0.60-k2"DRIVERNAPI
+#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
 char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
@@ -80,6 +80,9 @@
 	INTEL_E1000_ETHERNET_DEVICE(0x1026),
 	INTEL_E1000_ETHERNET_DEVICE(0x1027),
 	INTEL_E1000_ETHERNET_DEVICE(0x1028),
+	INTEL_E1000_ETHERNET_DEVICE(0x105E),
+	INTEL_E1000_ETHERNET_DEVICE(0x105F),
+	INTEL_E1000_ETHERNET_DEVICE(0x1060),
 	INTEL_E1000_ETHERNET_DEVICE(0x1075),
 	INTEL_E1000_ETHERNET_DEVICE(0x1076),
 	INTEL_E1000_ETHERNET_DEVICE(0x1077),
@@ -88,10 +91,13 @@
 	INTEL_E1000_ETHERNET_DEVICE(0x107A),
 	INTEL_E1000_ETHERNET_DEVICE(0x107B),
 	INTEL_E1000_ETHERNET_DEVICE(0x107C),
+	INTEL_E1000_ETHERNET_DEVICE(0x107D),
+	INTEL_E1000_ETHERNET_DEVICE(0x107E),
+	INTEL_E1000_ETHERNET_DEVICE(0x107F),
 	INTEL_E1000_ETHERNET_DEVICE(0x108A),
 	INTEL_E1000_ETHERNET_DEVICE(0x108B),
 	INTEL_E1000_ETHERNET_DEVICE(0x108C),
-	INTEL_E1000_ETHERNET_DEVICE(0x1099),
+	INTEL_E1000_ETHERNET_DEVICE(0x109A),
 	/* required last entry */
 	{0,}
 };
@@ -102,10 +108,18 @@
 void e1000_down(struct e1000_adapter *adapter);
 void e1000_reset(struct e1000_adapter *adapter);
 int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
-int e1000_setup_tx_resources(struct e1000_adapter *adapter);
-int e1000_setup_rx_resources(struct e1000_adapter *adapter);
-void e1000_free_tx_resources(struct e1000_adapter *adapter);
-void e1000_free_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+                             struct e1000_tx_ring *txdr);
+int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+                             struct e1000_rx_ring *rxdr);
+void e1000_free_tx_resources(struct e1000_adapter *adapter,
+                             struct e1000_tx_ring *tx_ring);
+void e1000_free_rx_resources(struct e1000_adapter *adapter,
+                             struct e1000_rx_ring *rx_ring);
 void e1000_update_stats(struct e1000_adapter *adapter);
 
 /* Local Function Prototypes */
@@ -114,14 +128,22 @@
 static void e1000_exit_module(void);
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void __devexit e1000_remove(struct pci_dev *pdev);
+static int e1000_alloc_queues(struct e1000_adapter *adapter);
+#ifdef CONFIG_E1000_MQ
+static void e1000_setup_queue_mapping(struct e1000_adapter *adapter);
+#endif
 static int e1000_sw_init(struct e1000_adapter *adapter);
 static int e1000_open(struct net_device *netdev);
 static int e1000_close(struct net_device *netdev);
 static void e1000_configure_tx(struct e1000_adapter *adapter);
 static void e1000_configure_rx(struct e1000_adapter *adapter);
 static void e1000_setup_rctl(struct e1000_adapter *adapter);
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+                                struct e1000_tx_ring *tx_ring);
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+                                struct e1000_rx_ring *rx_ring);
 static void e1000_set_multi(struct net_device *netdev);
 static void e1000_update_phy_info(unsigned long data);
 static void e1000_watchdog(unsigned long data);
@@ -132,19 +154,26 @@
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
 static int e1000_set_mac(struct net_device *netdev, void *p);
 static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+                                    struct e1000_tx_ring *tx_ring);
 #ifdef CONFIG_E1000_NAPI
-static int e1000_clean(struct net_device *netdev, int *budget);
+static int e1000_clean(struct net_device *poll_dev, int *budget);
 static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                                    struct e1000_rx_ring *rx_ring,
                                     int *work_done, int work_to_do);
 static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                                       struct e1000_rx_ring *rx_ring,
                                        int *work_done, int work_to_do);
 #else
-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                                    struct e1000_rx_ring *rx_ring);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                                       struct e1000_rx_ring *rx_ring);
 #endif
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+                                   struct e1000_rx_ring *rx_ring);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+                                      struct e1000_rx_ring *rx_ring);
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
 			   int cmd);
@@ -162,8 +191,8 @@
 static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
 static void e1000_restore_vlan(struct e1000_adapter *adapter);
 
-static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
 #ifdef CONFIG_PM
+static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
 static int e1000_resume(struct pci_dev *pdev);
 #endif
 
@@ -172,6 +201,11 @@
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+#ifdef CONFIG_E1000_MQ
+/* for multiple Rx queues */
+void e1000_rx_schedule(void *data);
+#endif
+
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -289,7 +323,7 @@
 e1000_up(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	int err;
+	int i, err;
 
 	/* hardware has been reset, we need to reload some things */
 
@@ -308,7 +342,8 @@
 	e1000_configure_tx(adapter);
 	e1000_setup_rctl(adapter);
 	e1000_configure_rx(adapter);
-	adapter->alloc_rx_buf(adapter);
+	for (i = 0; i < adapter->num_queues; i++)
+		adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
 
 #ifdef CONFIG_PCI_MSI
 	if(adapter->hw.mac_type > e1000_82547_rev_2) {
@@ -344,6 +379,9 @@
 	struct net_device *netdev = adapter->netdev;
 
 	e1000_irq_disable(adapter);
+#ifdef CONFIG_E1000_MQ
+	while (atomic_read(&adapter->rx_sched_call_data.count) != 0);
+#endif
 	free_irq(adapter->pdev->irq, netdev);
 #ifdef CONFIG_PCI_MSI
 	if(adapter->hw.mac_type > e1000_82547_rev_2 &&
@@ -363,11 +401,10 @@
 	netif_stop_queue(netdev);
 
 	e1000_reset(adapter);
-	e1000_clean_tx_ring(adapter);
-	e1000_clean_rx_ring(adapter);
+	e1000_clean_all_tx_rings(adapter);
+	e1000_clean_all_rx_rings(adapter);
 
-	/* If WoL is not enabled
-	 * and management mode is not IAMT
+	/* If WoL is not enabled and management mode is not IAMT
 	 * Power down the PHY so no link is implied when interface is down */
 	if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
 	   adapter->hw.media_type == e1000_media_type_copper &&
@@ -398,6 +435,10 @@
 	case e1000_82547_rev_2:
 		pba = E1000_PBA_30K;
 		break;
+	case e1000_82571:
+	case e1000_82572:
+		pba = E1000_PBA_38K;
+		break;
 	case e1000_82573:
 		pba = E1000_PBA_12K;
 		break;
@@ -475,6 +516,7 @@
 	struct net_device *netdev;
 	struct e1000_adapter *adapter;
 	unsigned long mmio_start, mmio_len;
+	uint32_t ctrl_ext;
 	uint32_t swsm;
 
 	static int cards_found = 0;
@@ -614,8 +656,9 @@
 	if(e1000_read_mac_addr(&adapter->hw))
 		DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
 
-	if(!is_valid_ether_addr(netdev->dev_addr)) {
+	if(!is_valid_ether_addr(netdev->perm_addr)) {
 		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 		err = -EIO;
 		goto err_eeprom;
@@ -687,6 +730,12 @@
 
 	/* Let firmware know the driver has taken over */
 	switch(adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+		break;
 	case e1000_82573:
 		swsm = E1000_READ_REG(&adapter->hw, SWSM);
 		E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -731,7 +780,11 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	uint32_t ctrl_ext;
 	uint32_t manc, swsm;
+#ifdef CONFIG_E1000_NAPI
+	int i;
+#endif
 
 	flush_scheduled_work();
 
@@ -745,6 +798,12 @@
 	}
 
 	switch(adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+		break;
 	case e1000_82573:
 		swsm = E1000_READ_REG(&adapter->hw, SWSM);
 		E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -756,13 +815,27 @@
 	}
 
 	unregister_netdev(netdev);
+#ifdef CONFIG_E1000_NAPI
+	for (i = 0; i < adapter->num_queues; i++)
+		__dev_put(&adapter->polling_netdev[i]);
+#endif
 
 	if(!e1000_check_phy_reset_block(&adapter->hw))
 		e1000_phy_hw_reset(&adapter->hw);
 
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+#ifdef CONFIG_E1000_NAPI
+	kfree(adapter->polling_netdev);
+#endif
+
 	iounmap(adapter->hw.hw_addr);
 	pci_release_regions(pdev);
 
+#ifdef CONFIG_E1000_MQ
+	free_percpu(adapter->cpu_netdev);
+	free_percpu(adapter->cpu_tx_ring);
+#endif
 	free_netdev(netdev);
 
 	pci_disable_device(pdev);
@@ -783,6 +856,9 @@
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
+#ifdef CONFIG_E1000_NAPI
+	int i;
+#endif
 
 	/* PCI config space info */
 
@@ -840,14 +916,123 @@
 		hw->master_slave = E1000_MASTER_SLAVE;
 	}
 
+#ifdef CONFIG_E1000_MQ
+	/* Number of supported queues */
+	switch (hw->mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		adapter->num_queues = 2;
+		break;
+	default:
+		adapter->num_queues = 1;
+		break;
+	}
+	adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+#else
+	adapter->num_queues = 1;
+#endif
+
+	if (e1000_alloc_queues(adapter)) {
+		DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+		return -ENOMEM;
+	}
+
+#ifdef CONFIG_E1000_NAPI
+	for (i = 0; i < adapter->num_queues; i++) {
+		adapter->polling_netdev[i].priv = adapter;
+		adapter->polling_netdev[i].poll = &e1000_clean;
+		adapter->polling_netdev[i].weight = 64;
+		dev_hold(&adapter->polling_netdev[i]);
+		set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
+	}
+#endif
+
+#ifdef CONFIG_E1000_MQ
+	e1000_setup_queue_mapping(adapter);
+#endif
+
 	atomic_set(&adapter->irq_sem, 1);
 	spin_lock_init(&adapter->stats_lock);
-	spin_lock_init(&adapter->tx_lock);
 
 	return 0;
 }
 
 /**
+ * e1000_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+ * number of queues at compile-time.  The polling_netdev array is
+ * intended for Multiqueue, but should work fine with a single queue.
+ **/
+
+static int __devinit
+e1000_alloc_queues(struct e1000_adapter *adapter)
+{
+	int size;
+
+	size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+	adapter->tx_ring = kmalloc(size, GFP_KERNEL);
+	if (!adapter->tx_ring)
+		return -ENOMEM;
+	memset(adapter->tx_ring, 0, size);
+
+	size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+	adapter->rx_ring = kmalloc(size, GFP_KERNEL);
+	if (!adapter->rx_ring) {
+		kfree(adapter->tx_ring);
+		return -ENOMEM;
+	}
+	memset(adapter->rx_ring, 0, size);
+
+#ifdef CONFIG_E1000_NAPI
+	size = sizeof(struct net_device) * adapter->num_queues;
+	adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
+	if (!adapter->polling_netdev) {
+		kfree(adapter->tx_ring);
+		kfree(adapter->rx_ring);
+		return -ENOMEM;
+	}
+	memset(adapter->polling_netdev, 0, size);
+#endif
+
+	return E1000_SUCCESS;
+}
+
+#ifdef CONFIG_E1000_MQ
+static void __devinit
+e1000_setup_queue_mapping(struct e1000_adapter *adapter)
+{
+	int i, cpu;
+
+	adapter->rx_sched_call_data.func = e1000_rx_schedule;
+	adapter->rx_sched_call_data.info = adapter->netdev;
+	cpus_clear(adapter->rx_sched_call_data.cpumask);
+
+	adapter->cpu_netdev = alloc_percpu(struct net_device *);
+	adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+
+	lock_cpu_hotplug();
+	i = 0;
+	for_each_online_cpu(cpu) {
+		*per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
+		/* This is incomplete because we'd like to assign separate
+		 * physical cpus to these netdev polling structures and
+		 * avoid saturating a subset of cpus.
+		 */
+		if (i < adapter->num_queues) {
+			*per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
+			adapter->cpu_for_queue[i] = cpu;
+		} else
+			*per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
+
+		i++;
+	}
+	unlock_cpu_hotplug();
+}
+#endif
+
+/**
  * e1000_open - Called when a network interface is made active
  * @netdev: network interface device structure
  *
@@ -868,12 +1053,12 @@
 
 	/* allocate transmit descriptors */
 
-	if((err = e1000_setup_tx_resources(adapter)))
+	if ((err = e1000_setup_all_tx_resources(adapter)))
 		goto err_setup_tx;
 
 	/* allocate receive descriptors */
 
-	if((err = e1000_setup_rx_resources(adapter)))
+	if ((err = e1000_setup_all_rx_resources(adapter)))
 		goto err_setup_rx;
 
 	if((err = e1000_up(adapter)))
@@ -887,9 +1072,9 @@
 	return E1000_SUCCESS;
 
 err_up:
-	e1000_free_rx_resources(adapter);
+	e1000_free_all_rx_resources(adapter);
 err_setup_rx:
-	e1000_free_tx_resources(adapter);
+	e1000_free_all_tx_resources(adapter);
 err_setup_tx:
 	e1000_reset(adapter);
 
@@ -915,8 +1100,8 @@
 
 	e1000_down(adapter);
 
-	e1000_free_tx_resources(adapter);
-	e1000_free_rx_resources(adapter);
+	e1000_free_all_tx_resources(adapter);
+	e1000_free_all_rx_resources(adapter);
 
 	if((adapter->hw.mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
@@ -951,25 +1136,28 @@
 /**
  * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
  * @adapter: board private structure
+ * @txdr:    tx descriptor ring (for a specific queue) to setup
  *
  * Return 0 on success, negative on failure
  **/
 
 int
-e1000_setup_tx_resources(struct e1000_adapter *adapter)
+e1000_setup_tx_resources(struct e1000_adapter *adapter,
+                         struct e1000_tx_ring *txdr)
 {
-	struct e1000_desc_ring *txdr = &adapter->tx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	int size;
 
 	size = sizeof(struct e1000_buffer) * txdr->count;
-	txdr->buffer_info = vmalloc(size);
+
+	txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
 	if(!txdr->buffer_info) {
 		DPRINTK(PROBE, ERR,
 		"Unable to allocate memory for the transmit descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(txdr->buffer_info, 0, size);
+	memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
 
 	/* round up to nearest 4K */
 
@@ -1018,11 +1206,41 @@
 
 	txdr->next_to_use = 0;
 	txdr->next_to_clean = 0;
+	spin_lock_init(&txdr->tx_lock);
 
 	return 0;
 }
 
 /**
+ * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
+ * 				  (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not).  It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+{
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_queues; i++) {
+		err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+		if (err) {
+			DPRINTK(PROBE, ERR,
+				"Allocation for Tx Queue %u failed\n", i);
+			break;
+		}
+	}
+
+	return err;
+}
+
+/**
  * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
  * @adapter: board private structure
  *
@@ -1032,23 +1250,43 @@
 static void
 e1000_configure_tx(struct e1000_adapter *adapter)
 {
-	uint64_t tdba = adapter->tx_ring.dma;
-	uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
-	uint32_t tctl, tipg;
-
-	E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000ffffffffULL));
-	E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
-
-	E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
+	uint64_t tdba;
+	struct e1000_hw *hw = &adapter->hw;
+	uint32_t tdlen, tctl, tipg, tarc;
 
 	/* Setup the HW Tx Head and Tail descriptor pointers */
 
-	E1000_WRITE_REG(&adapter->hw, TDH, 0);
-	E1000_WRITE_REG(&adapter->hw, TDT, 0);
+	switch (adapter->num_queues) {
+	case 2:
+		tdba = adapter->tx_ring[1].dma;
+		tdlen = adapter->tx_ring[1].count *
+			sizeof(struct e1000_tx_desc);
+		E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL));
+		E1000_WRITE_REG(hw, TDBAH1, (tdba >> 32));
+		E1000_WRITE_REG(hw, TDLEN1, tdlen);
+		E1000_WRITE_REG(hw, TDH1, 0);
+		E1000_WRITE_REG(hw, TDT1, 0);
+		adapter->tx_ring[1].tdh = E1000_TDH1;
+		adapter->tx_ring[1].tdt = E1000_TDT1;
+		/* Fall Through */
+	case 1:
+	default:
+		tdba = adapter->tx_ring[0].dma;
+		tdlen = adapter->tx_ring[0].count *
+			sizeof(struct e1000_tx_desc);
+		E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+		E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
+		E1000_WRITE_REG(hw, TDLEN, tdlen);
+		E1000_WRITE_REG(hw, TDH, 0);
+		E1000_WRITE_REG(hw, TDT, 0);
+		adapter->tx_ring[0].tdh = E1000_TDH;
+		adapter->tx_ring[0].tdt = E1000_TDT;
+		break;
+	}
 
 	/* Set the default values for the Tx Inter Packet Gap timer */
 
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_82542_rev2_0:
 	case e1000_82542_rev2_1:
 		tipg = DEFAULT_82542_TIPG_IPGT;
@@ -1056,67 +1294,81 @@
 		tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
 		break;
 	default:
-		if(adapter->hw.media_type == e1000_media_type_fiber ||
-		   adapter->hw.media_type == e1000_media_type_internal_serdes)
+		if (hw->media_type == e1000_media_type_fiber ||
+		    hw->media_type == e1000_media_type_internal_serdes)
 			tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
 		else
 			tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
 		tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
 		tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
 	}
-	E1000_WRITE_REG(&adapter->hw, TIPG, tipg);
+	E1000_WRITE_REG(hw, TIPG, tipg);
 
 	/* Set the Tx Interrupt Delay register */
 
-	E1000_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
-	if(adapter->hw.mac_type >= e1000_82540)
-		E1000_WRITE_REG(&adapter->hw, TADV, adapter->tx_abs_int_delay);
+	E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+	if (hw->mac_type >= e1000_82540)
+		E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
 
 	/* Program the Transmit Control Register */
 
-	tctl = E1000_READ_REG(&adapter->hw, TCTL);
+	tctl = E1000_READ_REG(hw, TCTL);
 
 	tctl &= ~E1000_TCTL_CT;
-	tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
+	tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC |
 		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
 
-	E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+	E1000_WRITE_REG(hw, TCTL, tctl);
 
-	e1000_config_collision_dist(&adapter->hw);
+	if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
+		tarc = E1000_READ_REG(hw, TARC0);
+		tarc |= ((1 << 25) | (1 << 21));
+		E1000_WRITE_REG(hw, TARC0, tarc);
+		tarc = E1000_READ_REG(hw, TARC1);
+		tarc |= (1 << 25);
+		if (tctl & E1000_TCTL_MULR)
+			tarc &= ~(1 << 28);
+		else
+			tarc |= (1 << 28);
+		E1000_WRITE_REG(hw, TARC1, tarc);
+	}
+
+	e1000_config_collision_dist(hw);
 
 	/* Setup Transmit Descriptor Settings for eop descriptor */
 	adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
 		E1000_TXD_CMD_IFCS;
 
-	if(adapter->hw.mac_type < e1000_82543)
+	if (hw->mac_type < e1000_82543)
 		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
 	else
 		adapter->txd_cmd |= E1000_TXD_CMD_RS;
 
 	/* Cache if we're 82544 running in PCI-X because we'll
 	 * need this to apply a workaround later in the send path. */
-	if(adapter->hw.mac_type == e1000_82544 &&
-	   adapter->hw.bus_type == e1000_bus_type_pcix)
+	if (hw->mac_type == e1000_82544 &&
+	    hw->bus_type == e1000_bus_type_pcix)
 		adapter->pcix_82544 = 1;
 }
 
 /**
  * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
  * @adapter: board private structure
+ * @rxdr:    rx descriptor ring (for a specific queue) to setup
  *
  * Returns 0 on success, negative on failure
  **/
 
 int
-e1000_setup_rx_resources(struct e1000_adapter *adapter)
+e1000_setup_rx_resources(struct e1000_adapter *adapter,
+                         struct e1000_rx_ring *rxdr)
 {
-	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	int size, desc_len;
 
 	size = sizeof(struct e1000_buffer) * rxdr->count;
-	rxdr->buffer_info = vmalloc(size);
-	if(!rxdr->buffer_info) {
+	rxdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
+	if (!rxdr->buffer_info) {
 		DPRINTK(PROBE, ERR,
 		"Unable to allocate memory for the receive descriptor ring\n");
 		return -ENOMEM;
@@ -1156,13 +1408,13 @@
 
 	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
 
-	if(!rxdr->desc) {
+	if (!rxdr->desc) {
+		DPRINTK(PROBE, ERR,
+		"Unable to allocate memory for the receive descriptor ring\n");
 setup_rx_desc_die:
 		vfree(rxdr->buffer_info);
 		kfree(rxdr->ps_page);
 		kfree(rxdr->ps_page_dma);
-		DPRINTK(PROBE, ERR,
-		"Unable to allocate memory for the receive descriptor ring\n");
 		return -ENOMEM;
 	}
 
@@ -1174,9 +1426,12 @@
 				     "at %p\n", rxdr->size, rxdr->desc);
 		/* Try again, without freeing the previous */
 		rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
-		if(!rxdr->desc) {
 		/* Failed allocation, critical failure */
+		if (!rxdr->desc) {
 			pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+			DPRINTK(PROBE, ERR,
+				"Unable to allocate memory "
+				"for the receive descriptor ring\n");
 			goto setup_rx_desc_die;
 		}
 
@@ -1188,10 +1443,7 @@
 			DPRINTK(PROBE, ERR,
 				"Unable to allocate aligned memory "
 				"for the receive descriptor ring\n");
-			vfree(rxdr->buffer_info);
-			kfree(rxdr->ps_page);
-			kfree(rxdr->ps_page_dma);
-			return -ENOMEM;
+			goto setup_rx_desc_die;
 		} else {
 			/* Free old allocation, new allocation was successful */
 			pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
@@ -1206,15 +1458,48 @@
 }
 
 /**
+ * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
+ * 				  (Descriptors) for all queues
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not).  It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+{
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_queues; i++) {
+		err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+		if (err) {
+			DPRINTK(PROBE, ERR,
+				"Allocation for Rx Queue %u failed\n", i);
+			break;
+		}
+	}
+
+	return err;
+}
+
+/**
  * e1000_setup_rctl - configure the receive control registers
  * @adapter: Board private structure
  **/
-
+#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+			(((S) & (PAGE_SIZE - 1)) ? 1 : 0))
 static void
 e1000_setup_rctl(struct e1000_adapter *adapter)
 {
 	uint32_t rctl, rfctl;
 	uint32_t psrctl = 0;
+#ifdef CONFIG_E1000_PACKET_SPLIT
+	uint32_t pages = 0;
+#endif
 
 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
 
@@ -1235,7 +1520,7 @@
 		rctl |= E1000_RCTL_LPE;
 
 	/* Setup buffer sizes */
-	if(adapter->hw.mac_type == e1000_82573) {
+	if(adapter->hw.mac_type >= e1000_82571) {
 		/* We can now specify buffers in 1K increments.
 		 * BSIZE and BSEX are ignored in this case. */
 		rctl |= adapter->rx_buffer_len << 0x11;
@@ -1268,11 +1553,14 @@
 	 * followed by the page buffers.  Therefore, skb->data is
 	 * sized to hold the largest protocol header.
 	 */
-	adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2) 
-			  && (adapter->netdev->mtu 
-	                      < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
+	pages = PAGE_USE_COUNT(adapter->netdev->mtu);
+	if ((adapter->hw.mac_type > e1000_82547_rev_2) && (pages <= 3) &&
+	    PAGE_SIZE <= 16384)
+		adapter->rx_ps_pages = pages;
+	else
+		adapter->rx_ps_pages = 0;
 #endif
-	if(adapter->rx_ps) {
+	if (adapter->rx_ps_pages) {
 		/* Configure extra packet-split registers */
 		rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
 		rfctl |= E1000_RFCTL_EXTEN;
@@ -1284,12 +1572,19 @@
 		
 		psrctl |= adapter->rx_ps_bsize0 >>
 			E1000_PSRCTL_BSIZE0_SHIFT;
-		psrctl |= PAGE_SIZE >>
-			E1000_PSRCTL_BSIZE1_SHIFT;
-		psrctl |= PAGE_SIZE <<
-			E1000_PSRCTL_BSIZE2_SHIFT;
-		psrctl |= PAGE_SIZE <<
-			E1000_PSRCTL_BSIZE3_SHIFT;
+
+		switch (adapter->rx_ps_pages) {
+		case 3:
+			psrctl |= PAGE_SIZE <<
+				E1000_PSRCTL_BSIZE3_SHIFT;
+		case 2:
+			psrctl |= PAGE_SIZE <<
+				E1000_PSRCTL_BSIZE2_SHIFT;
+		case 1:
+			psrctl |= PAGE_SIZE >>
+				E1000_PSRCTL_BSIZE1_SHIFT;
+			break;
+		}
 
 		E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
 	}
@@ -1307,91 +1602,181 @@
 static void
 e1000_configure_rx(struct e1000_adapter *adapter)
 {
-	uint64_t rdba = adapter->rx_ring.dma;
-	uint32_t rdlen, rctl, rxcsum;
+	uint64_t rdba;
+	struct e1000_hw *hw = &adapter->hw;
+	uint32_t rdlen, rctl, rxcsum, ctrl_ext;
+#ifdef CONFIG_E1000_MQ
+	uint32_t reta, mrqc;
+	int i;
+#endif
 
-	if(adapter->rx_ps) {
-		rdlen = adapter->rx_ring.count *
+	if (adapter->rx_ps_pages) {
+		rdlen = adapter->rx_ring[0].count *
 			sizeof(union e1000_rx_desc_packet_split);
 		adapter->clean_rx = e1000_clean_rx_irq_ps;
 		adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
 	} else {
-		rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
+		rdlen = adapter->rx_ring[0].count *
+			sizeof(struct e1000_rx_desc);
 		adapter->clean_rx = e1000_clean_rx_irq;
 		adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
 	}
 
 	/* disable receives while setting up the descriptors */
-	rctl = E1000_READ_REG(&adapter->hw, RCTL);
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+	rctl = E1000_READ_REG(hw, RCTL);
+	E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
 
 	/* set the Receive Delay Timer Register */
-	E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
+	E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
 
-	if(adapter->hw.mac_type >= e1000_82540) {
-		E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
+	if (hw->mac_type >= e1000_82540) {
+		E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
 		if(adapter->itr > 1)
-			E1000_WRITE_REG(&adapter->hw, ITR,
+			E1000_WRITE_REG(hw, ITR,
 				1000000000 / (adapter->itr * 256));
 	}
 
-	/* Setup the Base and Length of the Rx Descriptor Ring */
-	E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
-	E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
+	if (hw->mac_type >= e1000_82571) {
+		/* Reset delay timers after every interrupt */
+		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+		ctrl_ext |= E1000_CTRL_EXT_CANC;
+		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+		E1000_WRITE_FLUSH(hw);
+	}
 
-	E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
+	/* Setup the HW Rx Head and Tail Descriptor Pointers and
+	 * the Base and Length of the Rx Descriptor Ring */
+	switch (adapter->num_queues) {
+#ifdef CONFIG_E1000_MQ
+	case 2:
+		rdba = adapter->rx_ring[1].dma;
+		E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL));
+		E1000_WRITE_REG(hw, RDBAH1, (rdba >> 32));
+		E1000_WRITE_REG(hw, RDLEN1, rdlen);
+		E1000_WRITE_REG(hw, RDH1, 0);
+		E1000_WRITE_REG(hw, RDT1, 0);
+		adapter->rx_ring[1].rdh = E1000_RDH1;
+		adapter->rx_ring[1].rdt = E1000_RDT1;
+		/* Fall Through */
+#endif
+	case 1:
+	default:
+		rdba = adapter->rx_ring[0].dma;
+		E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+		E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
+		E1000_WRITE_REG(hw, RDLEN, rdlen);
+		E1000_WRITE_REG(hw, RDH, 0);
+		E1000_WRITE_REG(hw, RDT, 0);
+		adapter->rx_ring[0].rdh = E1000_RDH;
+		adapter->rx_ring[0].rdt = E1000_RDT;
+		break;
+	}
 
-	/* Setup the HW Rx Head and Tail Descriptor Pointers */
-	E1000_WRITE_REG(&adapter->hw, RDH, 0);
-	E1000_WRITE_REG(&adapter->hw, RDT, 0);
+#ifdef CONFIG_E1000_MQ
+	if (adapter->num_queues > 1) {
+		uint32_t random[10];
+
+		get_random_bytes(&random[0], 40);
+
+		if (hw->mac_type <= e1000_82572) {
+			E1000_WRITE_REG(hw, RSSIR, 0);
+			E1000_WRITE_REG(hw, RSSIM, 0);
+		}
+
+		switch (adapter->num_queues) {
+		case 2:
+		default:
+			reta = 0x00800080;
+			mrqc = E1000_MRQC_ENABLE_RSS_2Q;
+			break;
+		}
+
+		/* Fill out redirection table */
+		for (i = 0; i < 32; i++)
+			E1000_WRITE_REG_ARRAY(hw, RETA, i, reta);
+		/* Fill out hash function seeds */
+		for (i = 0; i < 10; i++)
+			E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]);
+
+		mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+			 E1000_MRQC_RSS_FIELD_IPV4_TCP);
+		E1000_WRITE_REG(hw, MRQC, mrqc);
+	}
+
+	/* Multiqueue and packet checksumming are mutually exclusive. */
+	if (hw->mac_type >= e1000_82571) {
+		rxcsum = E1000_READ_REG(hw, RXCSUM);
+		rxcsum |= E1000_RXCSUM_PCSD;
+		E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+	}
+
+#else
 
 	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
-	if(adapter->hw.mac_type >= e1000_82543) {
-		rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
+	if (hw->mac_type >= e1000_82543) {
+		rxcsum = E1000_READ_REG(hw, RXCSUM);
 		if(adapter->rx_csum == TRUE) {
 			rxcsum |= E1000_RXCSUM_TUOFL;
 
-			/* Enable 82573 IPv4 payload checksum for UDP fragments
+			/* Enable 82571 IPv4 payload checksum for UDP fragments
 			 * Must be used in conjunction with packet-split. */
-			if((adapter->hw.mac_type > e1000_82547_rev_2) && 
-			   (adapter->rx_ps)) {
+			if ((hw->mac_type >= e1000_82571) && 
+			   (adapter->rx_ps_pages)) {
 				rxcsum |= E1000_RXCSUM_IPPCSE;
 			}
 		} else {
 			rxcsum &= ~E1000_RXCSUM_TUOFL;
 			/* don't need to clear IPPCSE as it defaults to 0 */
 		}
-		E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
+		E1000_WRITE_REG(hw, RXCSUM, rxcsum);
 	}
+#endif /* CONFIG_E1000_MQ */
 
-	if (adapter->hw.mac_type == e1000_82573)
-		E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
+	if (hw->mac_type == e1000_82573)
+		E1000_WRITE_REG(hw, ERT, 0x0100);
 
 	/* Enable Receives */
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+	E1000_WRITE_REG(hw, RCTL, rctl);
 }
 
 /**
- * e1000_free_tx_resources - Free Tx Resources
+ * e1000_free_tx_resources - Free Tx Resources per Queue
+ * @adapter: board private structure
+ * @tx_ring: Tx descriptor ring for a specific queue
+ *
+ * Free all transmit software resources
+ **/
+
+void
+e1000_free_tx_resources(struct e1000_adapter *adapter,
+                        struct e1000_tx_ring *tx_ring)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	e1000_clean_tx_ring(adapter, tx_ring);
+
+	vfree(tx_ring->buffer_info);
+	tx_ring->buffer_info = NULL;
+
+	pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+
+	tx_ring->desc = NULL;
+}
+
+/**
+ * e1000_free_all_tx_resources - Free Tx Resources for All Queues
  * @adapter: board private structure
  *
  * Free all transmit software resources
  **/
 
 void
-e1000_free_tx_resources(struct e1000_adapter *adapter)
+e1000_free_all_tx_resources(struct e1000_adapter *adapter)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	int i;
 
-	e1000_clean_tx_ring(adapter);
-
-	vfree(adapter->tx_ring.buffer_info);
-	adapter->tx_ring.buffer_info = NULL;
-
-	pci_free_consistent(pdev, adapter->tx_ring.size,
-	                    adapter->tx_ring.desc, adapter->tx_ring.dma);
-
-	adapter->tx_ring.desc = NULL;
+	for (i = 0; i < adapter->num_queues; i++)
+		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
 static inline void
@@ -1414,21 +1799,22 @@
 /**
  * e1000_clean_tx_ring - Free Tx Buffers
  * @adapter: board private structure
+ * @tx_ring: ring to be cleaned
  **/
 
 static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter)
+e1000_clean_tx_ring(struct e1000_adapter *adapter,
+                    struct e1000_tx_ring *tx_ring)
 {
-	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct e1000_buffer *buffer_info;
 	unsigned long size;
 	unsigned int i;
 
 	/* Free all the Tx ring sk_buffs */
 
-	if (likely(adapter->previous_buffer_info.skb != NULL)) {
+	if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
 		e1000_unmap_and_free_tx_resource(adapter,
-				&adapter->previous_buffer_info);
+				&tx_ring->previous_buffer_info);
 	}
 
 	for(i = 0; i < tx_ring->count; i++) {
@@ -1446,24 +1832,39 @@
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
 
-	E1000_WRITE_REG(&adapter->hw, TDH, 0);
-	E1000_WRITE_REG(&adapter->hw, TDT, 0);
+	writel(0, adapter->hw.hw_addr + tx_ring->tdh);
+	writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+}
+
+/**
+ * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_queues; i++)
+		e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
 }
 
 /**
  * e1000_free_rx_resources - Free Rx Resources
  * @adapter: board private structure
+ * @rx_ring: ring to clean the resources from
  *
  * Free all receive software resources
  **/
 
 void
-e1000_free_rx_resources(struct e1000_adapter *adapter)
+e1000_free_rx_resources(struct e1000_adapter *adapter,
+                        struct e1000_rx_ring *rx_ring)
 {
-	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 
-	e1000_clean_rx_ring(adapter);
+	e1000_clean_rx_ring(adapter, rx_ring);
 
 	vfree(rx_ring->buffer_info);
 	rx_ring->buffer_info = NULL;
@@ -1478,14 +1879,31 @@
 }
 
 /**
- * e1000_clean_rx_ring - Free Rx Buffers
+ * e1000_free_all_rx_resources - Free Rx Resources for All Queues
  * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+void
+e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_queues; i++)
+		e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
+}
+
+/**
+ * e1000_clean_rx_ring - Free Rx Buffers per Queue
+ * @adapter: board private structure
+ * @rx_ring: ring to free buffers from
  **/
 
 static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter)
+e1000_clean_rx_ring(struct e1000_adapter *adapter,
+                    struct e1000_rx_ring *rx_ring)
 {
-	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	struct e1000_buffer *buffer_info;
 	struct e1000_ps_page *ps_page;
 	struct e1000_ps_page_dma *ps_page_dma;
@@ -1508,7 +1926,7 @@
 			dev_kfree_skb(buffer_info->skb);
 			buffer_info->skb = NULL;
 
-			for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+			for(j = 0; j < adapter->rx_ps_pages; j++) {
 				if(!ps_page->ps_page[j]) break;
 				pci_unmap_single(pdev,
 						 ps_page_dma->ps_page_dma[j],
@@ -1534,8 +1952,22 @@
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 
-	E1000_WRITE_REG(&adapter->hw, RDH, 0);
-	E1000_WRITE_REG(&adapter->hw, RDT, 0);
+	writel(0, adapter->hw.hw_addr + rx_ring->rdh);
+	writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+}
+
+/**
+ * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+
+static void
+e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_queues; i++)
+		e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
 }
 
 /* The 82542 2.0 (revision 2) needs to have the receive unit in reset
@@ -1556,7 +1988,7 @@
 	mdelay(5);
 
 	if(netif_running(netdev))
-		e1000_clean_rx_ring(adapter);
+		e1000_clean_all_rx_rings(adapter);
 }
 
 static void
@@ -1576,7 +2008,7 @@
 
 	if(netif_running(netdev)) {
 		e1000_configure_rx(adapter);
-		e1000_alloc_rx_buffers(adapter);
+		e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
 	}
 }
 
@@ -1607,6 +2039,22 @@
 
 	e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
 
+	/* With 82571 controllers, LAA may be overwritten (with the default)
+	 * due to controller reset from the other port. */
+	if (adapter->hw.mac_type == e1000_82571) {
+		/* activate the work around */
+		adapter->hw.laa_is_present = 1;
+
+		/* Hold a copy of the LAA in RAR[14] This is done so that 
+		 * between the time RAR[0] gets clobbered  and the time it 
+		 * gets fixed (in e1000_watchdog), the actual LAA is in one 
+		 * of the RARs and no incoming packets directed to this port
+		 * are dropped. Eventaully the LAA will be in RAR[0] and 
+		 * RAR[14] */
+		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 
+					E1000_RAR_ENTRIES - 1);
+	}
+
 	if(adapter->hw.mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
 
@@ -1629,12 +2077,13 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	struct dev_mc_list *mc_ptr;
-	unsigned long flags;
 	uint32_t rctl;
 	uint32_t hash_value;
-	int i;
+	int i, rar_entries = E1000_RAR_ENTRIES;
 
-	spin_lock_irqsave(&adapter->tx_lock, flags);
+	/* reserve RAR[14] for LAA over-write work-around */
+	if (adapter->hw.mac_type == e1000_82571)
+		rar_entries--;
 
 	/* Check for Promiscuous and All Multicast modes */
 
@@ -1659,11 +2108,12 @@
 	/* load the first 14 multicast address into the exact filters 1-14
 	 * RAR 0 is used for the station MAC adddress
 	 * if there are not 14 addresses, go ahead and clear the filters
+	 * -- with 82571 controllers only 0-13 entries are filled here
 	 */
 	mc_ptr = netdev->mc_list;
 
-	for(i = 1; i < E1000_RAR_ENTRIES; i++) {
-		if(mc_ptr) {
+	for(i = 1; i < rar_entries; i++) {
+		if (mc_ptr) {
 			e1000_rar_set(hw, mc_ptr->dmi_addr, i);
 			mc_ptr = mc_ptr->next;
 		} else {
@@ -1686,8 +2136,6 @@
 
 	if(hw->mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
-
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 }
 
 /* Need to wait a few seconds after link up to get diagnostic information from
@@ -1759,7 +2207,7 @@
 e1000_watchdog_task(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	struct e1000_desc_ring *txdr = &adapter->tx_ring;
+	struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
 	uint32_t link;
 
 	e1000_check_for_link(&adapter->hw);
@@ -1818,8 +2266,8 @@
 
 	e1000_update_adaptive(&adapter->hw);
 
-	if(!netif_carrier_ok(netdev)) {
-		if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
+	if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
 			/* We've lost link, so the controller stops DMA,
 			 * but we've got queued Tx work that's never going
 			 * to get done, so reset controller to flush Tx.
@@ -1847,6 +2295,11 @@
 	/* Force detection of hung controller every watchdog period */
 	adapter->detect_tx_hung = TRUE;
 
+	/* With 82571 controllers, LAA may be overwritten due to controller 
+	 * reset from the other port. Set the appropriate LAA in RAR[0] */
+	if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
+		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+
 	/* Reset the timer */
 	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
 }
@@ -1859,7 +2312,8 @@
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
 static inline int
-e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+          struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
@@ -1910,8 +2364,8 @@
 		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
 			       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
 
-		i = adapter->tx_ring.next_to_use;
-		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+		i = tx_ring->next_to_use;
+		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
 
 		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
 		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
@@ -1923,8 +2377,8 @@
 		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
 		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
 
-		if(++i == adapter->tx_ring.count) i = 0;
-		adapter->tx_ring.next_to_use = i;
+		if (++i == tx_ring->count) i = 0;
+		tx_ring->next_to_use = i;
 
 		return 1;
 	}
@@ -1934,7 +2388,8 @@
 }
 
 static inline boolean_t
-e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+              struct sk_buff *skb)
 {
 	struct e1000_context_desc *context_desc;
 	unsigned int i;
@@ -1943,8 +2398,8 @@
 	if(likely(skb->ip_summed == CHECKSUM_HW)) {
 		css = skb->h.raw - skb->data;
 
-		i = adapter->tx_ring.next_to_use;
-		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+		i = tx_ring->next_to_use;
+		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
 
 		context_desc->upper_setup.tcp_fields.tucss = css;
 		context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
@@ -1952,8 +2407,8 @@
 		context_desc->tcp_seg_setup.data = 0;
 		context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
 
-		if(unlikely(++i == adapter->tx_ring.count)) i = 0;
-		adapter->tx_ring.next_to_use = i;
+		if (unlikely(++i == tx_ring->count)) i = 0;
+		tx_ring->next_to_use = i;
 
 		return TRUE;
 	}
@@ -1965,11 +2420,10 @@
 #define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
 
 static inline int
-e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
-	unsigned int first, unsigned int max_per_txd,
-	unsigned int nr_frags, unsigned int mss)
+e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+             struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
+             unsigned int nr_frags, unsigned int mss)
 {
-	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct e1000_buffer *buffer_info;
 	unsigned int len = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
@@ -2065,9 +2519,9 @@
 }
 
 static inline void
-e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
+e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+               int tx_flags, int count)
 {
-	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct e1000_tx_desc *tx_desc = NULL;
 	struct e1000_buffer *buffer_info;
 	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -2113,7 +2567,7 @@
 	wmb();
 
 	tx_ring->next_to_use = i;
-	E1000_WRITE_REG(&adapter->hw, TDT, i);
+	writel(i, adapter->hw.hw_addr + tx_ring->tdt);
 }
 
 /**
@@ -2206,6 +2660,7 @@
 e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_tx_ring *tx_ring;
 	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
 	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
 	unsigned int tx_flags = 0;
@@ -2218,7 +2673,13 @@
 	unsigned int f;
 	len -= skb->data_len;
 
-	if(unlikely(skb->len <= 0)) {
+#ifdef CONFIG_E1000_MQ
+	tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#else
+	tx_ring = adapter->tx_ring;
+#endif
+
+	if (unlikely(skb->len <= 0)) {
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
@@ -2262,21 +2723,42 @@
 	if(adapter->pcix_82544)
 		count += nr_frags;
 
- 	local_irq_save(flags); 
- 	if (!spin_trylock(&adapter->tx_lock)) { 
- 		/* Collision - tell upper layer to requeue */ 
- 		local_irq_restore(flags); 
- 		return NETDEV_TX_LOCKED; 
- 	} 
+#ifdef NETIF_F_TSO
+	/* TSO Workaround for 82571/2 Controllers -- if skb->data
+	 * points to just header, pull a few bytes of payload from 
+	 * frags into skb->data */
+	if (skb_shinfo(skb)->tso_size) {
+		uint8_t hdr_len;
+		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+		if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) && 
+			(adapter->hw.mac_type == e1000_82571 ||
+			adapter->hw.mac_type == e1000_82572)) {
+			unsigned int pull_size;
+			pull_size = min((unsigned int)4, skb->data_len);
+			if (!__pskb_pull_tail(skb, pull_size)) {
+				printk(KERN_ERR "__pskb_pull_tail failed.\n");
+				dev_kfree_skb_any(skb);
+				return -EFAULT;
+			}
+		}
+	}
+#endif
+
 	if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
 		e1000_transfer_dhcp_info(adapter, skb);
 
+	local_irq_save(flags);
+	if (!spin_trylock(&tx_ring->tx_lock)) {
+		/* Collision - tell upper layer to requeue */
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
 
 	/* need: count + 2 desc gap to keep tail from touching
 	 * head, otherwise try next time */
-	if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2)) {
+	if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 2)) {
 		netif_stop_queue(netdev);
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -2284,7 +2766,7 @@
 		if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
-			spin_unlock_irqrestore(&adapter->tx_lock, flags);
+			spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
 			return NETDEV_TX_BUSY;
 		}
 	}
@@ -2294,37 +2776,37 @@
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
 
-	first = adapter->tx_ring.next_to_use;
+	first = tx_ring->next_to_use;
 	
-	tso = e1000_tso(adapter, skb);
+	tso = e1000_tso(adapter, tx_ring, skb);
 	if (tso < 0) {
 		dev_kfree_skb_any(skb);
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
 		return NETDEV_TX_OK;
 	}
 
 	if (likely(tso))
 		tx_flags |= E1000_TX_FLAGS_TSO;
-	else if(likely(e1000_tx_csum(adapter, skb)))
+	else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
 	/* Old method was to assume IPv4 packet by default if TSO was enabled.
-	 * 82573 hardware supports TSO capabilities for IPv6 as well...
+	 * 82571 hardware supports TSO capabilities for IPv6 as well...
 	 * no longer assume, we must. */
-	if(likely(skb->protocol == ntohs(ETH_P_IP)))
+	if (likely(skb->protocol == ntohs(ETH_P_IP)))
 		tx_flags |= E1000_TX_FLAGS_IPV4;
 
-	e1000_tx_queue(adapter,
-		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
-		tx_flags);
+	e1000_tx_queue(adapter, tx_ring, tx_flags,
+	               e1000_tx_map(adapter, tx_ring, skb, first,
+	                            max_per_txd, nr_frags, mss));
 
 	netdev->trans_start = jiffies;
 
 	/* Make sure there is space in the ring for the next send. */
-	if(unlikely(E1000_DESC_UNUSED(&adapter->tx_ring) < MAX_SKB_FRAGS + 2))
+	if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 2))
 		netif_stop_queue(netdev);
 
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
 	return NETDEV_TX_OK;
 }
 
@@ -2388,9 +2870,18 @@
 			return -EINVAL;
 	}
 
-#define MAX_STD_JUMBO_FRAME_SIZE 9216
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
 	/* might want this to be bigger enum check... */
-	if (adapter->hw.mac_type == e1000_82573 &&
+	/* 82571 controllers limit jumbo frame size to 10500 bytes */
+	if ((adapter->hw.mac_type == e1000_82571 || 
+	     adapter->hw.mac_type == e1000_82572) &&
+	    max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+		DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
+				    "on 82571 and 82572 controllers.\n");
+		return -EINVAL;
+	}
+
+	if(adapter->hw.mac_type == e1000_82573 &&
 	    max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
 		DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
 				    "on 82573\n");
@@ -2578,6 +3069,29 @@
 	spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
+#ifdef CONFIG_E1000_MQ
+void
+e1000_rx_schedule(void *data)
+{
+	struct net_device *poll_dev, *netdev = data;
+	struct e1000_adapter *adapter = netdev->priv;
+	int this_cpu = get_cpu();
+
+	poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu);
+	if (poll_dev == NULL) {
+		put_cpu();
+		return;
+	}
+
+	if (likely(netif_rx_schedule_prep(poll_dev)))
+		__netif_rx_schedule(poll_dev);
+	else
+		e1000_irq_enable(adapter);
+
+	put_cpu();
+}
+#endif
+
 /**
  * e1000_intr - Interrupt Handler
  * @irq: interrupt number
@@ -2592,8 +3106,8 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	uint32_t icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
-	unsigned int i;
+#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+	int i;
 #endif
 
 	if(unlikely(!icr))
@@ -2605,17 +3119,31 @@
 	}
 
 #ifdef CONFIG_E1000_NAPI
-	if(likely(netif_rx_schedule_prep(netdev))) {
-
-		/* Disable interrupts and register for poll. The flush 
-		  of the posted write is intentionally left out.
-		*/
-
-		atomic_inc(&adapter->irq_sem);
-		E1000_WRITE_REG(hw, IMC, ~0);
-		__netif_rx_schedule(netdev);
+	atomic_inc(&adapter->irq_sem);
+	E1000_WRITE_REG(hw, IMC, ~0);
+	E1000_WRITE_FLUSH(hw);
+#ifdef CONFIG_E1000_MQ
+	if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
+		cpu_set(adapter->cpu_for_queue[0],
+			adapter->rx_sched_call_data.cpumask);
+		for (i = 1; i < adapter->num_queues; i++) {
+			cpu_set(adapter->cpu_for_queue[i],
+				adapter->rx_sched_call_data.cpumask);
+			atomic_inc(&adapter->irq_sem);
+		}
+		atomic_set(&adapter->rx_sched_call_data.count, i);
+		smp_call_async_mask(&adapter->rx_sched_call_data);
+	} else {
+		printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
 	}
-#else
+#else /* if !CONFIG_E1000_MQ */
+	if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
+		__netif_rx_schedule(&adapter->polling_netdev[0]);
+	else
+		e1000_irq_enable(adapter);
+#endif /* CONFIG_E1000_MQ */
+
+#else /* if !CONFIG_E1000_NAPI */
 	/* Writing IMC and IMS is needed for 82547.
 	   Due to Hub Link bus being occupied, an interrupt
 	   de-assertion message is not able to be sent.
@@ -2632,13 +3160,14 @@
 	}
 
 	for(i = 0; i < E1000_MAX_INTR; i++)
-		if(unlikely(!adapter->clean_rx(adapter) &
-		   !e1000_clean_tx_irq(adapter)))
+		if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+		   !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
 			break;
 
 	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
 		e1000_irq_enable(adapter);
-#endif
+
+#endif /* CONFIG_E1000_NAPI */
 
 	return IRQ_HANDLED;
 }
@@ -2650,22 +3179,37 @@
  **/
 
 static int
-e1000_clean(struct net_device *netdev, int *budget)
+e1000_clean(struct net_device *poll_dev, int *budget)
 {
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int work_to_do = min(*budget, netdev->quota);
-	int tx_cleaned;
-	int work_done = 0;
+	struct e1000_adapter *adapter;
+	int work_to_do = min(*budget, poll_dev->quota);
+	int tx_cleaned, i = 0, work_done = 0;
 
-	tx_cleaned = e1000_clean_tx_irq(adapter);
-	adapter->clean_rx(adapter, &work_done, work_to_do);
+	/* Must NOT use netdev_priv macro here. */
+	adapter = poll_dev->priv;
+
+	/* Keep link state information with original netdev */
+	if (!netif_carrier_ok(adapter->netdev))
+		goto quit_polling;
+
+	while (poll_dev != &adapter->polling_netdev[i]) {
+		i++;
+		if (unlikely(i == adapter->num_queues))
+			BUG();
+	}
+
+	tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+	adapter->clean_rx(adapter, &adapter->rx_ring[i],
+	                  &work_done, work_to_do);
 
 	*budget -= work_done;
-	netdev->quota -= work_done;
+	poll_dev->quota -= work_done;
 	
-	if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
 	/* If no Tx and not enough Rx work done, exit the polling mode */
-		netif_rx_complete(netdev);
+	if((!tx_cleaned && (work_done == 0)) ||
+	   !netif_running(adapter->netdev)) {
+quit_polling:
+		netif_rx_complete(poll_dev);
 		e1000_irq_enable(adapter);
 		return 0;
 	}
@@ -2680,9 +3224,9 @@
  **/
 
 static boolean_t
-e1000_clean_tx_irq(struct e1000_adapter *adapter)
+e1000_clean_tx_irq(struct e1000_adapter *adapter,
+                   struct e1000_tx_ring *tx_ring)
 {
-	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_tx_desc *tx_desc, *eop_desc;
 	struct e1000_buffer *buffer_info;
@@ -2693,12 +3237,12 @@
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
-	while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+	while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
 		/* Premature writeback of Tx descriptors clear (free buffers
 		 * and unmap pci_mapping) previous_buffer_info */
-		if (likely(adapter->previous_buffer_info.skb != NULL)) {
+		if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
 			e1000_unmap_and_free_tx_resource(adapter,
-					&adapter->previous_buffer_info);
+					&tx_ring->previous_buffer_info);
 		}
 
 		for(cleaned = FALSE; !cleaned; ) {
@@ -2714,7 +3258,7 @@
 #ifdef NETIF_F_TSO
 			} else {
 				if (cleaned) {
-					memcpy(&adapter->previous_buffer_info,
+					memcpy(&tx_ring->previous_buffer_info,
 					       buffer_info,
 					       sizeof(struct e1000_buffer));
 					memset(buffer_info, 0,
@@ -2732,6 +3276,8 @@
 
 			if(unlikely(++i == tx_ring->count)) i = 0;
 		}
+
+		tx_ring->pkt++;
 		
 		eop = tx_ring->buffer_info[i].next_to_watch;
 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
@@ -2739,15 +3285,15 @@
 
 	tx_ring->next_to_clean = i;
 
-	spin_lock(&adapter->tx_lock);
+	spin_lock(&tx_ring->tx_lock);
 
 	if(unlikely(cleaned && netif_queue_stopped(netdev) &&
 		    netif_carrier_ok(netdev)))
 		netif_wake_queue(netdev);
 
-	spin_unlock(&adapter->tx_lock);
-	if(adapter->detect_tx_hung) {
+	spin_unlock(&tx_ring->tx_lock);
 
+	if (adapter->detect_tx_hung) {
 		/* Detect a transmit hang in hardware, this serializes the
 		 * check with the clearing of time_stamp and movement of i */
 		adapter->detect_tx_hung = FALSE;
@@ -2771,8 +3317,8 @@
 					"  next_to_watch        <%x>\n"
 					"  jiffies              <%lx>\n"
 					"  next_to_watch.status <%x>\n",
-				E1000_READ_REG(&adapter->hw, TDH),
-				E1000_READ_REG(&adapter->hw, TDT),
+				readl(adapter->hw.hw_addr + tx_ring->tdh),
+				readl(adapter->hw.hw_addr + tx_ring->tdt),
 				tx_ring->next_to_use,
 				i,
 				(unsigned long long)tx_ring->buffer_info[i].dma,
@@ -2784,12 +3330,10 @@
 		}
 	}
 #ifdef NETIF_F_TSO
-
-	if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
-	    time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ)))
+	if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+	    time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
 		e1000_unmap_and_free_tx_resource(
-		    adapter, &adapter->previous_buffer_info);
-
+		    adapter, &tx_ring->previous_buffer_info);
 #endif
 	return cleaned;
 }
@@ -2852,13 +3396,14 @@
 
 static boolean_t
 #ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
-                   int work_to_do)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                   struct e1000_rx_ring *rx_ring,
+                   int *work_done, int work_to_do)
 #else
-e1000_clean_rx_irq(struct e1000_adapter *adapter)
+e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                   struct e1000_rx_ring *rx_ring)
 #endif
 {
-	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_rx_desc *rx_desc;
@@ -2944,6 +3489,7 @@
 		}
 #endif /* CONFIG_E1000_NAPI */
 		netdev->last_rx = jiffies;
+		rx_ring->pkt++;
 
 next_desc:
 		rx_desc->status = 0;
@@ -2953,7 +3499,7 @@
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 	}
 	rx_ring->next_to_clean = i;
-	adapter->alloc_rx_buf(adapter);
+	adapter->alloc_rx_buf(adapter, rx_ring);
 
 	return cleaned;
 }
@@ -2965,13 +3511,14 @@
 
 static boolean_t
 #ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
-                      int work_to_do)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                      struct e1000_rx_ring *rx_ring,
+                      int *work_done, int work_to_do)
 #else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+                      struct e1000_rx_ring *rx_ring)
 #endif
 {
-	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	union e1000_rx_desc_packet_split *rx_desc;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
@@ -3027,7 +3574,7 @@
 		/* Good Receive */
 		skb_put(skb, length);
 
-		for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+		for(j = 0; j < adapter->rx_ps_pages; j++) {
 			if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
 				break;
 
@@ -3048,11 +3595,13 @@
 				  rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
 		skb->protocol = eth_type_trans(skb, netdev);
 
-#ifdef HAVE_RX_ZERO_COPY
 		if(likely(rx_desc->wb.upper.header_status &
-			  E1000_RXDPS_HDRSTAT_HDRSP))
+			  E1000_RXDPS_HDRSTAT_HDRSP)) {
+			adapter->rx_hdr_split++;
+#ifdef HAVE_RX_ZERO_COPY
 			skb_shinfo(skb)->zero_copy = TRUE;
 #endif
+	        }
 #ifdef CONFIG_E1000_NAPI
 		if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -3071,6 +3620,7 @@
 		}
 #endif /* CONFIG_E1000_NAPI */
 		netdev->last_rx = jiffies;
+		rx_ring->pkt++;
 
 next_desc:
 		rx_desc->wb.middle.status_error &= ~0xFF;
@@ -3081,7 +3631,7 @@
 		staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
 	}
 	rx_ring->next_to_clean = i;
-	adapter->alloc_rx_buf(adapter);
+	adapter->alloc_rx_buf(adapter, rx_ring);
 
 	return cleaned;
 }
@@ -3092,9 +3642,9 @@
  **/
 
 static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+                       struct e1000_rx_ring *rx_ring)
 {
-	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_rx_desc *rx_desc;
@@ -3178,7 +3728,7 @@
 			 * applicable for weak-ordered memory model archs,
 			 * such as IA-64). */
 			wmb();
-			E1000_WRITE_REG(&adapter->hw, RDT, i);
+			writel(i, adapter->hw.hw_addr + rx_ring->rdt);
 		}
 
 		if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3194,9 +3744,9 @@
  **/
 
 static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+                          struct e1000_rx_ring *rx_ring)
 {
-	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	union e1000_rx_desc_packet_split *rx_desc;
@@ -3215,22 +3765,26 @@
 		rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
 
 		for(j = 0; j < PS_PAGE_BUFFERS; j++) {
-			if(unlikely(!ps_page->ps_page[j])) {
-				ps_page->ps_page[j] =
-					alloc_page(GFP_ATOMIC);
-				if(unlikely(!ps_page->ps_page[j]))
-					goto no_buffers;
-				ps_page_dma->ps_page_dma[j] =
-					pci_map_page(pdev,
-						     ps_page->ps_page[j],
-						     0, PAGE_SIZE,
-						     PCI_DMA_FROMDEVICE);
-			}
-			/* Refresh the desc even if buffer_addrs didn't
-			 * change because each write-back erases this info.
-			 */
-			rx_desc->read.buffer_addr[j+1] =
-				cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+			if (j < adapter->rx_ps_pages) {
+				if (likely(!ps_page->ps_page[j])) {
+					ps_page->ps_page[j] =
+						alloc_page(GFP_ATOMIC);
+					if (unlikely(!ps_page->ps_page[j]))
+						goto no_buffers;
+					ps_page_dma->ps_page_dma[j] =
+						pci_map_page(pdev,
+							    ps_page->ps_page[j],
+							    0, PAGE_SIZE,
+							    PCI_DMA_FROMDEVICE);
+				}
+				/* Refresh the desc even if buffer_addrs didn't
+				 * change because each write-back erases 
+				 * this info.
+				 */
+				rx_desc->read.buffer_addr[j+1] =
+				     cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+			} else
+				rx_desc->read.buffer_addr[j+1] = ~0;
 		}
 
 		skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
@@ -3264,7 +3818,7 @@
 			 * descriptors are 32 bytes...so we increment tail
 			 * twice as much.
 			 */
-			E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
+			writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
 		}
 
 		if(unlikely(++i == rx_ring->count)) i = 0;
@@ -3640,6 +4194,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static int
 e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -3715,6 +4270,12 @@
 	}
 
 	switch(adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+		break;
 	case e1000_82573:
 		swsm = E1000_READ_REG(&adapter->hw, SWSM);
 		E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3730,13 +4291,13 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
 static int
 e1000_resume(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	uint32_t manc, ret_val, swsm;
+	uint32_t ctrl_ext;
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
@@ -3762,6 +4323,12 @@
 	}
 
 	switch(adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+		break;
 	case e1000_82573:
 		swsm = E1000_READ_REG(&adapter->hw, SWSM);
 		E1000_WRITE_REG(&adapter->hw, SWSM,
@@ -3786,7 +4353,7 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	disable_irq(adapter->pdev->irq);
 	e1000_intr(adapter->pdev->irq, netdev, NULL);
-	e1000_clean_tx_irq(adapter);
+	e1000_clean_tx_irq(adapter, adapter->tx_ring);
 	enable_irq(adapter->pdev->irq);
 }
 #endif
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 676247f..38695d5 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -306,7 +306,8 @@
 			.def  = E1000_DEFAULT_TXD,
 			.arg  = { .r = { .min = E1000_MIN_TXD }}
 		};
-		struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+		struct e1000_tx_ring *tx_ring = adapter->tx_ring;
+		int i;
 		e1000_mac_type mac_type = adapter->hw.mac_type;
 		opt.arg.r.max = mac_type < e1000_82544 ?
 			E1000_MAX_TXD : E1000_MAX_82544_TXD;
@@ -319,6 +320,8 @@
 		} else {
 			tx_ring->count = opt.def;
 		}
+		for (i = 0; i < adapter->num_queues; i++)
+			tx_ring[i].count = tx_ring->count;
 	}
 	{ /* Receive Descriptor Count */
 		struct e1000_option opt = {
@@ -329,7 +332,8 @@
 			.def  = E1000_DEFAULT_RXD,
 			.arg  = { .r = { .min = E1000_MIN_RXD }}
 		};
-		struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+		struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+		int i;
 		e1000_mac_type mac_type = adapter->hw.mac_type;
 		opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
 			E1000_MAX_82544_RXD;
@@ -342,6 +346,8 @@
 		} else {
 			rx_ring->count = opt.def;
 		}
+		for (i = 0; i < adapter->num_queues; i++)
+			rx_ring[i].count = rx_ring->count;
 	}
 	{ /* Checksum Offload Enable/Disable */
 		struct e1000_option opt = {
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index dcb3028..a806dfe 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -552,8 +552,7 @@
 	{
 		unsigned short int WS[32]=WakeupSeq;
 
-		if (check_region(WakeupPort, 2)==0) {
-
+		if (request_region(WakeupPort, 2, "eepro wakeup")) {
 			if (net_debug>5)
 				printk(KERN_DEBUG "Waking UP\n");
 
@@ -563,7 +562,10 @@
 				outb_p(WS[i],WakeupPort);
 				if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
 			}
-		} else printk(KERN_WARNING "Checkregion Failed!\n");
+
+			release_region(WakeupPort, 2);
+		} else
+			printk(KERN_WARNING "PnP wakeup region busy!\n");
 	}
 #endif
 
@@ -705,7 +707,7 @@
 					dev->name, (unsigned)dev->base_addr);
 			break;
 		case LAN595FX:
-			printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", 
+			printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
 					dev->name, (unsigned)dev->base_addr);
 			break;
 		case LAN595TX:
@@ -713,7 +715,7 @@
 					dev->name, (unsigned)dev->base_addr);
 			break;
 		case LAN595:
-			printk("%s: Intel 82595-based lan card at %#x,", 
+			printk("%s: Intel 82595-based lan card at %#x,",
 					dev->name, (unsigned)dev->base_addr);
 	}
 
@@ -726,7 +728,7 @@
 
 	if (dev->irq > 2)
 		printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
-	else 
+	else
 		printk(", %s.\n", ifmap[dev->if_port]);
 
 	if (net_debug > 3) {
@@ -756,7 +758,7 @@
 	int err;
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
-	if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { 
+	if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
 		if (!autoprobe)
 			printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n",
 				ioaddr);
@@ -838,15 +840,15 @@
  		/* Mask off INT number */
  		int count = lp->word[1] & 7;
  		unsigned irqMask = lp->word[7];
- 
+
  		while (count--)
  			irqMask &= irqMask - 1;
- 
+
  		count = ffs(irqMask);
- 
+
  		if (count)
  			dev->irq = count - 1;
- 
+
  		if (dev->irq < 2) {
  			printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
  			goto exit;
@@ -854,7 +856,7 @@
  			dev->irq = 9;
  		}
  	}
- 
+
  	dev->open               = eepro_open;
  	dev->stop               = eepro_close;
  	dev->hard_start_xmit    = eepro_send_packet;
@@ -863,7 +865,7 @@
  	dev->tx_timeout		= eepro_tx_timeout;
  	dev->watchdog_timeo	= TX_TIMEOUT;
 	dev->ethtool_ops	= &eepro_ethtool_ops;
- 
+
 	/* print boot time info */
 	eepro_print_info(dev);
 
@@ -1047,8 +1049,8 @@
 
 
 	/* Initialize the RCV and XMT upper and lower limits */
-	outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); 
-	outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); 
+	outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
+	outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
 	outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
 	outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
 
@@ -1065,12 +1067,12 @@
 	eepro_clear_int(ioaddr);
 
 	/* Initialize RCV */
-	outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); 
+	outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
 	lp->rx_start = lp->rcv_lower_limit;
-	outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP); 
+	outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
 
 	/* Initialize XMT */
-	outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); 
+	outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
 	lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
 	lp->tx_last = 0;
 
@@ -1411,7 +1413,7 @@
 				outb(0x08, ioaddr + STATUS_REG);
 
 				if (i & 0x20) { /* command ABORTed */
-					printk(KERN_NOTICE "%s: multicast setup failed.\n", 
+					printk(KERN_NOTICE "%s: multicast setup failed.\n",
 						dev->name);
 					break;
 				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */
@@ -1512,7 +1514,7 @@
 		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 
 	if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
-		if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {	
+		if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
 				/* Arrrr!!!, must keep the xmt header together,
 				several days were lost to chase this one down. */
 			last = lp->xmt_lower_limit;
@@ -1643,7 +1645,7 @@
 			else if (rcv_status & 0x0800)
 				lp->stats.rx_crc_errors++;
 
-			printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", 
+			printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
 				dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
 		}
 
@@ -1674,10 +1676,10 @@
 {
 	struct eepro_local *lp = netdev_priv(dev);
 	short ioaddr = dev->base_addr;
-	short boguscount = 25; 
+	short boguscount = 25;
 	short xmt_status;
 
-	while ((lp->tx_start != lp->tx_end) && boguscount--) { 
+	while ((lp->tx_start != lp->tx_end) && boguscount--) {
 
 		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
 		xmt_status = inw(ioaddr+IO_PORT);
@@ -1723,7 +1725,7 @@
 {
 	struct eepro_local	*lp = (struct eepro_local *)dev->priv;
 
-	cmd->supported = 	SUPPORTED_10baseT_Half | 
+	cmd->supported = 	SUPPORTED_10baseT_Half |
 				SUPPORTED_10baseT_Full |
 				SUPPORTED_Autoneg;
 	cmd->advertising =	ADVERTISED_10baseT_Half |
@@ -1797,10 +1799,9 @@
 MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
 MODULE_LICENSE("GPL");
 
-static int num_params;
-module_param_array(io, int, &num_params, 0);
-module_param_array(irq, int, &num_params, 0);
-module_param_array(mem, int, &num_params, 0);
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
 module_param(autodetect, int, 0);
 MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
 MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 87f5227..f119ec4 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1334,7 +1334,7 @@
 static int epic_poll(struct net_device *dev, int *budget)
 {
 	struct epic_private *ep = dev->priv;
-	int work_done, orig_budget;
+	int work_done = 0, orig_budget;
 	long ioaddr = dev->base_addr;
 
 	orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
@@ -1343,7 +1343,7 @@
 
 	epic_tx(dev, ep);
 
-	work_done = epic_rx(dev, *budget);
+	work_done += epic_rx(dev, *budget);
 
 	epic_rx_err(dev, ep);
 
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index d6eefdb..22aec6e 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -95,6 +95,8 @@
  *			   of nv_remove
  *      0.42: 06 Aug 2005: Fix lack of link speed initialization
  *			   in the second (and later) nv_open call
+ *      0.43: 10 Aug 2005: Add support for tx checksum.
+ *      0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -106,7 +108,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.41"
+#define FORCEDETH_VERSION		"0.44"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -145,6 +147,7 @@
 #define DEV_NEED_LINKTIMER	0x0002	/* poll link settings. Relies on the timer irq */
 #define DEV_HAS_LARGEDESC	0x0004	/* device supports jumbo frames and needs packet format 2 */
 #define DEV_HAS_HIGH_DMA        0x0008  /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM        0x0010  /* device supports tx and rx checksum offloads */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -241,6 +244,9 @@
 #define NVREG_TXRXCTL_IDLE	0x0008
 #define NVREG_TXRXCTL_RESET	0x0010
 #define NVREG_TXRXCTL_RXCHECK	0x0400
+#define NVREG_TXRXCTL_DESC_1	0
+#define NVREG_TXRXCTL_DESC_2	0x02100
+#define NVREG_TXRXCTL_DESC_3	0x02200
 	NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR		0x0001
 #define NVREG_MIISTAT_LINKCHANGE	0x0008
@@ -335,6 +341,10 @@
 /* error and valid are the same for both */
 #define NV_TX2_ERROR		(1<<30)
 #define NV_TX2_VALID		(1<<31)
+#define NV_TX2_TSO		(1<<28)
+#define NV_TX2_TSO_SHIFT	14
+#define NV_TX2_CHECKSUM_L3	(1<<27)
+#define NV_TX2_CHECKSUM_L4	(1<<26)
 
 #define NV_RX_DESCRIPTORVALID	(1<<16)
 #define NV_RX_MISSEDFRAME	(1<<17)
@@ -417,14 +427,14 @@
 
 /* 
  * desc_ver values:
- * This field has two purposes:
- * - Newer nics uses a different ring layout. The layout is selected by
- *   comparing np->desc_ver with DESC_VER_xy.
- * - It contains bits that are forced on when writing to NvRegTxRxControl.
+ * The nic supports three different descriptor types:
+ * - DESC_VER_1: Original
+ * - DESC_VER_2: support for jumbo frames.
+ * - DESC_VER_3: 64-bit format.
  */
-#define DESC_VER_1	0x0
-#define DESC_VER_2	(0x02100|NVREG_TXRXCTL_RXCHECK)
-#define DESC_VER_3      (0x02200|NVREG_TXRXCTL_RXCHECK)
+#define DESC_VER_1	1
+#define DESC_VER_2	2
+#define DESC_VER_3	3
 
 /* PHY defines */
 #define PHY_OUI_MARVELL	0x5043
@@ -491,6 +501,7 @@
 	u32 orig_mac[2];
 	u32 irqmask;
 	u32 desc_ver;
+	u32 txrxctl_bits;
 
 	void __iomem *base;
 
@@ -534,7 +545,7 @@
 
 static inline u8 __iomem *get_hwbase(struct net_device *dev)
 {
-	return get_nvpriv(dev)->base;
+	return ((struct fe_priv *)netdev_priv(dev))->base;
 }
 
 static inline void pci_push(u8 __iomem *base)
@@ -623,7 +634,7 @@
 
 static int phy_reset(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u32 miicontrol;
 	unsigned int tries = 0;
 
@@ -726,7 +737,7 @@
 
 static void nv_start_rx(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
 	dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
@@ -782,14 +793,14 @@
 
 static void nv_txrx_reset(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
 	dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
-	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
+	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
 	udelay(NV_TXRX_RESET_DELAY);
-	writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
+	writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
 }
 
@@ -801,7 +812,7 @@
  */
 static struct net_device_stats *nv_get_stats(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 
 	/* It seems that the nic always generates interrupts and doesn't
 	 * accumulate errors internally. Thus the current values in np->stats
@@ -817,7 +828,7 @@
  */
 static int nv_alloc_rx(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	unsigned int refill_rx = np->refill_rx;
 	int nr;
 
@@ -861,7 +872,7 @@
 static void nv_do_rx_refill(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 
 	disable_irq(dev->irq);
 	if (nv_alloc_rx(dev)) {
@@ -875,7 +886,7 @@
 
 static void nv_init_rx(struct net_device *dev) 
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	int i;
 
 	np->cur_rx = RX_RING;
@@ -889,15 +900,17 @@
 
 static void nv_init_tx(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	int i;
 
 	np->next_tx = np->nic_tx = 0;
-	for (i = 0; i < TX_RING; i++)
+	for (i = 0; i < TX_RING; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			np->tx_ring.orig[i].FlagLen = 0;
 	        else
 			np->tx_ring.ex[i].FlagLen = 0;
+		np->tx_skbuff[i] = NULL;
+	}
 }
 
 static int nv_init_ring(struct net_device *dev)
@@ -907,21 +920,44 @@
 	return nv_alloc_rx(dev);
 }
 
+static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	struct sk_buff *skb = np->tx_skbuff[skbnr];
+	unsigned int j, entry, fragments;
+			
+	dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
+		dev->name, skbnr, np->tx_skbuff[skbnr]);
+	
+	entry = skbnr;
+	if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
+		for (j = fragments; j >= 1; j--) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
+			pci_unmap_page(np->pci_dev, np->tx_dma[entry],
+				       frag->size,
+				       PCI_DMA_TODEVICE);
+			entry = (entry - 1) % TX_RING;
+		}
+	}
+	pci_unmap_single(np->pci_dev, np->tx_dma[entry],
+			 skb->len - skb->data_len,
+			 PCI_DMA_TODEVICE);
+	dev_kfree_skb_irq(skb);
+	np->tx_skbuff[skbnr] = NULL;
+}
+
 static void nv_drain_tx(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
-	int i;
+	struct fe_priv *np = netdev_priv(dev);
+	unsigned int i;
+	
 	for (i = 0; i < TX_RING; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			np->tx_ring.orig[i].FlagLen = 0;
 		else
 			np->tx_ring.ex[i].FlagLen = 0;
 		if (np->tx_skbuff[i]) {
-			pci_unmap_single(np->pci_dev, np->tx_dma[i],
-						np->tx_skbuff[i]->len,
-						PCI_DMA_TODEVICE);
-			dev_kfree_skb(np->tx_skbuff[i]);
-			np->tx_skbuff[i] = NULL;
+			nv_release_txskb(dev, i);
 			np->stats.tx_dropped++;
 		}
 	}
@@ -929,7 +965,7 @@
 
 static void nv_drain_rx(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	int i;
 	for (i = 0; i < RX_RING; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
@@ -959,28 +995,69 @@
  */
 static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
-	int nr = np->next_tx % TX_RING;
-
-	np->tx_skbuff[nr] = skb;
-	np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
-					PCI_DMA_TODEVICE);
-
-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-		np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
-	else {
-		np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
-		np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
-	}
+	struct fe_priv *np = netdev_priv(dev);
+	u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
+	unsigned int fragments = skb_shinfo(skb)->nr_frags;
+	unsigned int nr = (np->next_tx + fragments) % TX_RING;
+	unsigned int i;
 
 	spin_lock_irq(&np->lock);
-	wmb();
-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-		np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
+
+	if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
+		spin_unlock_irq(&np->lock);
+		netif_stop_queue(dev);
+		return NETDEV_TX_BUSY;
+	}
+
+	np->tx_skbuff[nr] = skb;
+	
+	if (fragments) {
+		dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
+		/* setup descriptors in reverse order */
+		for (i = fragments; i >= 1; i--) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+			np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
+							PCI_DMA_TODEVICE);
+
+			if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+				np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+				np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+			} else {
+				np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+				np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+				np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+			}
+			
+			nr = (nr - 1) % TX_RING;
+
+			if (np->desc_ver == DESC_VER_1)
+				tx_flags_extra &= ~NV_TX_LASTPACKET;
+			else
+				tx_flags_extra &= ~NV_TX2_LASTPACKET;		
+		}
+	}
+
+#ifdef NETIF_F_TSO
+	if (skb_shinfo(skb)->tso_size)
+		tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
 	else
-		np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
-	dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
-				dev->name, np->next_tx);
+#endif
+	tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
+
+	np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
+					PCI_DMA_TODEVICE);
+	
+	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+		np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
+		np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+	} else {
+		np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+		np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+		np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+	}	
+
+	dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
+				dev->name, np->next_tx, tx_flags_extra);
 	{
 		int j;
 		for (j=0; j<64; j++) {
@@ -991,15 +1068,13 @@
 		dprintk("\n");
 	}
 
-	np->next_tx++;
+	np->next_tx += 1 + fragments;
 
 	dev->trans_start = jiffies;
-	if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
-		netif_stop_queue(dev);
 	spin_unlock_irq(&np->lock);
-	writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+	writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 	pci_push(get_hwbase(dev));
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 /*
@@ -1009,9 +1084,10 @@
  */
 static void nv_tx_done(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u32 Flags;
-	int i;
+	unsigned int i;
+	struct sk_buff *skb;
 
 	while (np->nic_tx != np->next_tx) {
 		i = np->nic_tx % TX_RING;
@@ -1026,35 +1102,38 @@
 		if (Flags & NV_TX_VALID)
 			break;
 		if (np->desc_ver == DESC_VER_1) {
-			if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
-							NV_TX_UNDERFLOW|NV_TX_ERROR)) {
-				if (Flags & NV_TX_UNDERFLOW)
-					np->stats.tx_fifo_errors++;
-				if (Flags & NV_TX_CARRIERLOST)
-					np->stats.tx_carrier_errors++;
-				np->stats.tx_errors++;
-			} else {
-				np->stats.tx_packets++;
-				np->stats.tx_bytes += np->tx_skbuff[i]->len;
+			if (Flags & NV_TX_LASTPACKET) {
+				skb = np->tx_skbuff[i];
+				if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+					     NV_TX_UNDERFLOW|NV_TX_ERROR)) {
+					if (Flags & NV_TX_UNDERFLOW)
+						np->stats.tx_fifo_errors++;
+					if (Flags & NV_TX_CARRIERLOST)
+						np->stats.tx_carrier_errors++;
+					np->stats.tx_errors++;
+				} else {
+					np->stats.tx_packets++;
+					np->stats.tx_bytes += skb->len;
+				}
+				nv_release_txskb(dev, i);
 			}
 		} else {
-			if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
-							NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
-				if (Flags & NV_TX2_UNDERFLOW)
-					np->stats.tx_fifo_errors++;
-				if (Flags & NV_TX2_CARRIERLOST)
-					np->stats.tx_carrier_errors++;
-				np->stats.tx_errors++;
-			} else {
-				np->stats.tx_packets++;
-				np->stats.tx_bytes += np->tx_skbuff[i]->len;
+			if (Flags & NV_TX2_LASTPACKET) {
+				skb = np->tx_skbuff[i];
+				if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
+					     NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
+					if (Flags & NV_TX2_UNDERFLOW)
+						np->stats.tx_fifo_errors++;
+					if (Flags & NV_TX2_CARRIERLOST)
+						np->stats.tx_carrier_errors++;
+					np->stats.tx_errors++;
+				} else {
+					np->stats.tx_packets++;
+					np->stats.tx_bytes += skb->len;
+				}				
+				nv_release_txskb(dev, i);
 			}
 		}
-		pci_unmap_single(np->pci_dev, np->tx_dma[i],
-					np->tx_skbuff[i]->len,
-					PCI_DMA_TODEVICE);
-		dev_kfree_skb_irq(np->tx_skbuff[i]);
-		np->tx_skbuff[i] = NULL;
 		np->nic_tx++;
 	}
 	if (np->next_tx - np->nic_tx < TX_LIMIT_START)
@@ -1067,7 +1146,7 @@
  */
 static void nv_tx_timeout(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
 	printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
@@ -1200,7 +1279,7 @@
 
 static void nv_rx_process(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u32 Flags;
 
 	for (;;) {
@@ -1355,7 +1434,7 @@
  */
 static int nv_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	int old_mtu;
 
 	if (new_mtu < 64 || new_mtu > np->pkt_limit)
@@ -1408,7 +1487,7 @@
 		writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
 			base + NvRegRingSizes);
 		pci_push(base);
-		writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
+		writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 		pci_push(base);
 
 		/* restart rx engine */
@@ -1440,7 +1519,7 @@
  */
 static int nv_set_mac_address(struct net_device *dev, void *addr)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	struct sockaddr *macaddr = (struct sockaddr*)addr;
 
 	if(!is_valid_ether_addr(macaddr->sa_data))
@@ -1475,7 +1554,7 @@
  */
 static void nv_set_multicast(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	u32 addr[2];
 	u32 mask[2];
@@ -1535,7 +1614,7 @@
 
 static int nv_update_linkspeed(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	int adv, lpa;
 	int newls = np->linkspeed;
@@ -1705,7 +1784,7 @@
 static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	u32 events;
 	int i;
@@ -1777,7 +1856,7 @@
 static void nv_do_nic_poll(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
 	disable_irq(dev->irq);
@@ -1801,7 +1880,7 @@
 
 static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	strcpy(info->driver, "forcedeth");
 	strcpy(info->version, FORCEDETH_VERSION);
 	strcpy(info->bus_info, pci_name(np->pci_dev));
@@ -1809,7 +1888,7 @@
 
 static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	wolinfo->supported = WAKE_MAGIC;
 
 	spin_lock_irq(&np->lock);
@@ -1820,7 +1899,7 @@
 
 static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 
 	spin_lock_irq(&np->lock);
@@ -2021,7 +2100,7 @@
 
 static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	u32 *rbuf = buf;
 	int i;
@@ -2035,7 +2114,7 @@
 
 static int nv_nway_reset(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	int ret;
 
 	spin_lock_irq(&np->lock);
@@ -2065,11 +2144,12 @@
 	.get_regs_len = nv_get_regs_len,
 	.get_regs = nv_get_regs,
 	.nway_reset = nv_nway_reset,
+	.get_perm_addr = ethtool_op_get_perm_addr,
 };
 
 static int nv_open(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
 	int ret, oom, i;
 
@@ -2114,9 +2194,9 @@
 	/* 5) continue setup */
 	writel(np->linkspeed, base + NvRegLinkSpeed);
 	writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
-	writel(np->desc_ver, base + NvRegTxRxControl);
+	writel(np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
-	writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
+	writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
 	reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
 			NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
 			KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
@@ -2205,7 +2285,7 @@
 
 static int nv_close(struct net_device *dev)
 {
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base;
 
 	spin_lock_irq(&np->lock);
@@ -2261,7 +2341,7 @@
 	if (!dev)
 		goto out;
 
-	np = get_nvpriv(dev);
+	np = netdev_priv(dev);
 	np->pci_dev = pci_dev;
 	spin_lock_init(&np->lock);
 	SET_MODULE_OWNER(dev);
@@ -2313,19 +2393,32 @@
 		if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
 			printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
 					pci_name(pci_dev));
+		} else {
+			dev->features |= NETIF_F_HIGHDMA;
 		}
+		np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
 	} else if (id->driver_data & DEV_HAS_LARGEDESC) {
 		/* packet format 2: supports jumbo frames */
 		np->desc_ver = DESC_VER_2;
+		np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
 	} else {
 		/* original packet format */
 		np->desc_ver = DESC_VER_1;
+		np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
 	}
 
 	np->pkt_limit = NV_PKTLIMIT_1;
 	if (id->driver_data & DEV_HAS_LARGEDESC)
 		np->pkt_limit = NV_PKTLIMIT_2;
 
+	if (id->driver_data & DEV_HAS_CHECKSUM) {
+		np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+#ifdef NETIF_F_TSO
+		dev->features |= NETIF_F_TSO;
+#endif
+ 	}
+
 	err = -ENOMEM;
 	np->base = ioremap(addr, NV_PCI_REGSZ);
 	if (!np->base)
@@ -2377,8 +2470,9 @@
 	dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
 	dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
 	dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	if (!is_valid_ether_addr(dev->dev_addr)) {
+	if (!is_valid_ether_addr(dev->perm_addr)) {
 		/*
 		 * Bad mac address. At least one bios sets the mac address
 		 * to 01:23:45:67:89:ab
@@ -2403,9 +2497,9 @@
 	np->wolenabled = 0;
 
 	if (np->desc_ver == DESC_VER_1) {
-		np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
+		np->tx_flags = NV_TX_VALID;
 	} else {
-		np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
+		np->tx_flags = NV_TX2_VALID;
 	}
 	np->irqmask = NVREG_IRQMASK_WANTED;
 	if (id->driver_data & DEV_NEED_TIMERIRQ)
@@ -2494,7 +2588,7 @@
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
 	struct net_device *dev = pci_get_drvdata(pci_dev);
-	struct fe_priv *np = get_nvpriv(dev);
+	struct fe_priv *np = netdev_priv(dev);
 
 	unregister_netdev(dev);
 
@@ -2525,35 +2619,35 @@
 	},
 	{	/* nForce3 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* nForce3 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* nForce3 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* nForce3 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* CK804 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
 	},
 	{	/* CK804 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
 	},
 	{	/* MCP04 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
 	},
 	{	/* MCP04 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
 	},
 	{	/* MCP51 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
@@ -2565,11 +2659,11 @@
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
 	},
 	{0,},
 };
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
new file mode 100644
index 0000000..6aaee67
--- /dev/null
+++ b/drivers/net/fs_enet/Kconfig
@@ -0,0 +1,20 @@
+config FS_ENET
+       tristate "Freescale Ethernet Driver"
+       depends on NET_ETHERNET && (CPM1 || CPM2)
+       select MII
+
+config FS_ENET_HAS_SCC
+	bool "Chip has an SCC usable for ethernet"
+	depends on FS_ENET && (CPM1 || CPM2)
+	default y
+
+config FS_ENET_HAS_FCC
+	bool "Chip has an FCC usable for ethernet"
+	depends on FS_ENET && CPM2
+	default y
+
+config FS_ENET_HAS_FEC
+	bool "Chip has an FEC usable for ethernet"
+	depends on FS_ENET && CPM1
+	default y
+
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
new file mode 100644
index 0000000..d6dd3f2
--- /dev/null
+++ b/drivers/net/fs_enet/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+
+obj-$(CONFIG_FS_ENET) += fs_enet.o
+
+obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o
+obj-$(CONFIG_8260) += mac-fcc.o
+
+fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
new file mode 100644
index 0000000..44fac73
--- /dev/null
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -0,0 +1,1226 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ * 
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+static char version[] __devinitdata =
+    DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
+MODULE_DESCRIPTION("Freescale Ethernet Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+MODULE_PARM(fs_enet_debug, "i");
+MODULE_PARM_DESC(fs_enet_debug,
+		 "Freescale bitmapped debugging message enable value");
+
+int fs_enet_debug = -1;		/* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
+
+static void fs_set_multicast_list(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	(*fep->ops->set_multicast_list)(dev);
+}
+
+/* NAPI receive function */
+static int fs_enet_rx_napi(struct net_device *dev, int *budget)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	cbd_t *bdp;
+	struct sk_buff *skb, *skbn, *skbt;
+	int received = 0;
+	u16 pkt_len, sc;
+	int curidx;
+	int rx_work_limit = 0;	/* pacify gcc */
+
+	rx_work_limit = min(dev->quota, *budget);
+
+	if (!netif_running(dev))
+		return 0;
+
+	/*
+	 * First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = fep->cur_rx;
+
+	/* clear RX status bits for napi*/
+	(*fep->ops->napi_clear_rx_event)(dev);
+
+	while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
+
+		curidx = bdp - fep->rx_bd_base;
+
+		/*
+		 * Since we have allocated space to hold a complete frame,
+		 * the last indicator should be set.
+		 */
+		if ((sc & BD_ENET_RX_LAST) == 0)
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s rcv is not +last\n",
+			       dev->name);
+
+		/*
+		 * Check for errors. 
+		 */
+		if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
+			  BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			fep->stats.rx_errors++;
+			/* Frame too long or too short. */
+			if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+				fep->stats.rx_length_errors++;
+			/* Frame alignment */
+			if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+				fep->stats.rx_frame_errors++;
+			/* CRC Error */
+			if (sc & BD_ENET_RX_CR)
+				fep->stats.rx_crc_errors++;
+			/* FIFO overrun */
+			if (sc & BD_ENET_RX_OV)
+				fep->stats.rx_crc_errors++;
+
+			skb = fep->rx_skbuff[curidx];
+
+			dma_unmap_single(fep->dev, skb->data,
+				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+				DMA_FROM_DEVICE);
+
+			skbn = skb;
+
+		} else {
+
+			/* napi, got packet but no quota */
+			if (--rx_work_limit < 0)
+				break;
+
+			skb = fep->rx_skbuff[curidx];
+
+			dma_unmap_single(fep->dev, skb->data,
+				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+				DMA_FROM_DEVICE);
+
+			/*
+			 * Process the incoming frame.
+			 */
+			fep->stats.rx_packets++;
+			pkt_len = CBDR_DATLEN(bdp) - 4;	/* remove CRC */
+			fep->stats.rx_bytes += pkt_len + 4;
+
+			if (pkt_len <= fpi->rx_copybreak) {
+				/* +2 to make IP header L1 cache aligned */
+				skbn = dev_alloc_skb(pkt_len + 2);
+				if (skbn != NULL) {
+					skb_reserve(skbn, 2);	/* align IP header */
+					memcpy(skbn->data, skb->data, pkt_len);
+					/* swap */
+					skbt = skb;
+					skb = skbn;
+					skbn = skbt;
+				}
+			} else
+				skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+
+			if (skbn != NULL) {
+				skb->dev = dev;
+				skb_put(skb, pkt_len);	/* Make room */
+				skb->protocol = eth_type_trans(skb, dev);
+				received++;
+				netif_receive_skb(skb);
+			} else {
+				printk(KERN_WARNING DRV_MODULE_NAME
+				       ": %s Memory squeeze, dropping packet.\n",
+				       dev->name);
+				fep->stats.rx_dropped++;
+				skbn = skb;
+			}
+		}
+
+		fep->rx_skbuff[curidx] = skbn;
+		CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
+			     L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+			     DMA_FROM_DEVICE));
+		CBDW_DATLEN(bdp, 0);
+		CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
+
+		/*
+		 * Update BD pointer to next entry. 
+		 */
+		if ((sc & BD_ENET_RX_WRAP) == 0)
+			bdp++;
+		else
+			bdp = fep->rx_bd_base;
+
+		(*fep->ops->rx_bd_done)(dev);
+	}
+
+	fep->cur_rx = bdp;
+
+	dev->quota -= received;
+	*budget -= received;
+
+	if (rx_work_limit < 0)
+		return 1;	/* not done */
+
+	/* done */
+	netif_rx_complete(dev);
+
+	(*fep->ops->napi_enable_rx)(dev);
+
+	return 0;
+}
+
+/* non NAPI receive function */
+static int fs_enet_rx_non_napi(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	cbd_t *bdp;
+	struct sk_buff *skb, *skbn, *skbt;
+	int received = 0;
+	u16 pkt_len, sc;
+	int curidx;
+	/*
+	 * First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = fep->cur_rx;
+
+	while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
+
+		curidx = bdp - fep->rx_bd_base;
+
+		/*
+		 * Since we have allocated space to hold a complete frame,
+		 * the last indicator should be set.
+		 */
+		if ((sc & BD_ENET_RX_LAST) == 0)
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s rcv is not +last\n",
+			       dev->name);
+
+		/*
+		 * Check for errors. 
+		 */
+		if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
+			  BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
+			fep->stats.rx_errors++;
+			/* Frame too long or too short. */
+			if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+				fep->stats.rx_length_errors++;
+			/* Frame alignment */
+			if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
+				fep->stats.rx_frame_errors++;
+			/* CRC Error */
+			if (sc & BD_ENET_RX_CR)
+				fep->stats.rx_crc_errors++;
+			/* FIFO overrun */
+			if (sc & BD_ENET_RX_OV)
+				fep->stats.rx_crc_errors++;
+
+			skb = fep->rx_skbuff[curidx];
+
+			dma_unmap_single(fep->dev, skb->data,
+				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+				DMA_FROM_DEVICE);
+
+			skbn = skb;
+
+		} else {
+
+			skb = fep->rx_skbuff[curidx];
+
+			dma_unmap_single(fep->dev, skb->data,
+				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+				DMA_FROM_DEVICE);
+
+			/*
+			 * Process the incoming frame.
+			 */
+			fep->stats.rx_packets++;
+			pkt_len = CBDR_DATLEN(bdp) - 4;	/* remove CRC */
+			fep->stats.rx_bytes += pkt_len + 4;
+
+			if (pkt_len <= fpi->rx_copybreak) {
+				/* +2 to make IP header L1 cache aligned */
+				skbn = dev_alloc_skb(pkt_len + 2);
+				if (skbn != NULL) {
+					skb_reserve(skbn, 2);	/* align IP header */
+					memcpy(skbn->data, skb->data, pkt_len);
+					/* swap */
+					skbt = skb;
+					skb = skbn;
+					skbn = skbt;
+				}
+			} else
+				skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+
+			if (skbn != NULL) {
+				skb->dev = dev;
+				skb_put(skb, pkt_len);	/* Make room */
+				skb->protocol = eth_type_trans(skb, dev);
+				received++;
+				netif_rx(skb);
+			} else {
+				printk(KERN_WARNING DRV_MODULE_NAME
+				       ": %s Memory squeeze, dropping packet.\n",
+				       dev->name);
+				fep->stats.rx_dropped++;
+				skbn = skb;
+			}
+		}
+
+		fep->rx_skbuff[curidx] = skbn;
+		CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
+			     L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+			     DMA_FROM_DEVICE));
+		CBDW_DATLEN(bdp, 0);
+		CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
+
+		/*
+		 * Update BD pointer to next entry. 
+		 */
+		if ((sc & BD_ENET_RX_WRAP) == 0)
+			bdp++;
+		else
+			bdp = fep->rx_bd_base;
+
+		(*fep->ops->rx_bd_done)(dev);
+	}
+
+	fep->cur_rx = bdp;
+
+	return 0;
+}
+
+static void fs_enet_tx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	struct sk_buff *skb;
+	int dirtyidx, do_wake, do_restart;
+	u16 sc;
+
+	spin_lock(&fep->lock);
+	bdp = fep->dirty_tx;
+
+	do_wake = do_restart = 0;
+	while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
+
+		dirtyidx = bdp - fep->tx_bd_base;
+
+		if (fep->tx_free == fep->tx_ring)
+			break;
+
+		skb = fep->tx_skbuff[dirtyidx];
+
+		/*
+		 * Check for errors. 
+		 */
+		if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+			  BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
+
+			if (sc & BD_ENET_TX_HB)	/* No heartbeat */
+				fep->stats.tx_heartbeat_errors++;
+			if (sc & BD_ENET_TX_LC)	/* Late collision */
+				fep->stats.tx_window_errors++;
+			if (sc & BD_ENET_TX_RL)	/* Retrans limit */
+				fep->stats.tx_aborted_errors++;
+			if (sc & BD_ENET_TX_UN)	/* Underrun */
+				fep->stats.tx_fifo_errors++;
+			if (sc & BD_ENET_TX_CSL)	/* Carrier lost */
+				fep->stats.tx_carrier_errors++;
+
+			if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+				fep->stats.tx_errors++;
+				do_restart = 1;
+			}
+		} else
+			fep->stats.tx_packets++;
+
+		if (sc & BD_ENET_TX_READY)
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s HEY! Enet xmit interrupt and TX_READY.\n",
+			       dev->name);
+
+		/*
+		 * Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (sc & BD_ENET_TX_DEF)
+			fep->stats.collisions++;
+
+		/* unmap */
+		dma_unmap_single(fep->dev, skb->data, skb->len, DMA_TO_DEVICE);
+
+		/*
+		 * Free the sk buffer associated with this last transmit. 
+		 */
+		dev_kfree_skb_irq(skb);
+		fep->tx_skbuff[dirtyidx] = NULL;
+
+		/*
+		 * Update pointer to next buffer descriptor to be transmitted. 
+		 */
+		if ((sc & BD_ENET_TX_WRAP) == 0)
+			bdp++;
+		else
+			bdp = fep->tx_bd_base;
+
+		/*
+		 * Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (!fep->tx_free++)
+			do_wake = 1;
+	}
+
+	fep->dirty_tx = bdp;
+
+	if (do_restart)
+		(*fep->ops->tx_restart)(dev);
+
+	spin_unlock(&fep->lock);
+
+	if (do_wake)
+		netif_wake_queue(dev);
+}
+
+/*
+ * The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static irqreturn_t
+fs_enet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct fs_enet_private *fep;
+	const struct fs_platform_info *fpi;
+	u32 int_events;
+	u32 int_clr_events;
+	int nr, napi_ok;
+	int handled;
+
+	fep = netdev_priv(dev);
+	fpi = fep->fpi;
+
+	nr = 0;
+	while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) {
+
+		nr++;
+
+		int_clr_events = int_events;
+		if (fpi->use_napi)
+			int_clr_events &= ~fep->ev_napi_rx;
+
+		(*fep->ops->clear_int_events)(dev, int_clr_events);
+
+		if (int_events & fep->ev_err)
+			(*fep->ops->ev_error)(dev, int_events);
+
+		if (int_events & fep->ev_rx) {
+			if (!fpi->use_napi)
+				fs_enet_rx_non_napi(dev);
+			else {
+				napi_ok = netif_rx_schedule_prep(dev);
+
+				(*fep->ops->napi_disable_rx)(dev);
+				(*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
+
+				/* NOTE: it is possible for FCCs in NAPI mode    */
+				/* to submit a spurious interrupt while in poll  */
+				if (napi_ok)
+					__netif_rx_schedule(dev);
+			}
+		}
+
+		if (int_events & fep->ev_tx)
+			fs_enet_tx(dev);
+	}
+
+	handled = nr > 0;
+	return IRQ_RETVAL(handled);
+}
+
+void fs_init_bds(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	struct sk_buff *skb;
+	int i;
+
+	fs_cleanup_bds(dev);
+
+	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+	fep->tx_free = fep->tx_ring;
+	fep->cur_rx = fep->rx_bd_base;
+
+	/*
+	 * Initialize the receive buffer descriptors. 
+	 */
+	for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
+		skb = dev_alloc_skb(ENET_RX_FRSIZE);
+		if (skb == NULL) {
+			printk(KERN_WARNING DRV_MODULE_NAME
+			       ": %s Memory squeeze, unable to allocate skb\n",
+			       dev->name);
+			break;
+		}
+		fep->rx_skbuff[i] = skb;
+		skb->dev = dev;
+		CBDW_BUFADDR(bdp,
+			dma_map_single(fep->dev, skb->data,
+				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+				DMA_FROM_DEVICE));
+		CBDW_DATLEN(bdp, 0);	/* zero */
+		CBDW_SC(bdp, BD_ENET_RX_EMPTY |
+			((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
+	}
+	/*
+	 * if we failed, fillup remainder 
+	 */
+	for (; i < fep->rx_ring; i++, bdp++) {
+		fep->rx_skbuff[i] = NULL;
+		CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP);
+	}
+
+	/*
+	 * ...and the same for transmit.  
+	 */
+	for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
+		fep->tx_skbuff[i] = NULL;
+		CBDW_BUFADDR(bdp, 0);
+		CBDW_DATLEN(bdp, 0);
+		CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP);
+	}
+}
+
+void fs_cleanup_bds(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct sk_buff *skb;
+	int i;
+
+	/*
+	 * Reset SKB transmit buffers.  
+	 */
+	for (i = 0; i < fep->tx_ring; i++) {
+		if ((skb = fep->tx_skbuff[i]) == NULL)
+			continue;
+
+		/* unmap */
+		dma_unmap_single(fep->dev, skb->data, skb->len, DMA_TO_DEVICE);
+
+		fep->tx_skbuff[i] = NULL;
+		dev_kfree_skb(skb);
+	}
+
+	/*
+	 * Reset SKB receive buffers 
+	 */
+	for (i = 0; i < fep->rx_ring; i++) {
+		if ((skb = fep->rx_skbuff[i]) == NULL)
+			continue;
+
+		/* unmap */
+		dma_unmap_single(fep->dev, skb->data,
+			L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
+			DMA_FROM_DEVICE);
+
+		fep->rx_skbuff[i] = NULL;
+
+		dev_kfree_skb(skb);
+	}
+}
+
+/**********************************************************************************/
+
+static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	int curidx;
+	u16 sc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fep->tx_lock, flags);
+
+	/*
+	 * Fill in a Tx ring entry 
+	 */
+	bdp = fep->cur_tx;
+
+	if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+		/*
+		 * Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since the tx queue should be stopped.
+		 */
+		printk(KERN_WARNING DRV_MODULE_NAME
+		       ": %s tx queue full!.\n", dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	curidx = bdp - fep->tx_bd_base;
+	/*
+	 * Clear all of the status flags. 
+	 */
+	CBDC_SC(bdp, BD_ENET_TX_STATS);
+
+	/*
+	 * Save skb pointer. 
+	 */
+	fep->tx_skbuff[curidx] = skb;
+
+	fep->stats.tx_bytes += skb->len;
+
+	/*
+	 * Push the data cache so the CPM does not get stale memory data. 
+	 */
+	CBDW_BUFADDR(bdp, dma_map_single(fep->dev,
+				skb->data, skb->len, DMA_TO_DEVICE));
+	CBDW_DATLEN(bdp, skb->len);
+
+	dev->trans_start = jiffies;
+
+	/*
+	 * If this was the last BD in the ring, start at the beginning again. 
+	 */
+	if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
+		fep->cur_tx++;
+	else
+		fep->cur_tx = fep->tx_bd_base;
+
+	if (!--fep->tx_free)
+		netif_stop_queue(dev);
+
+	/* Trigger transmission start */
+	sc = BD_ENET_TX_READY | BD_ENET_TX_INTR |
+	     BD_ENET_TX_LAST | BD_ENET_TX_TC;
+
+	/* note that while FEC does not have this bit
+	 * it marks it as available for software use
+	 * yay for hw reuse :) */
+	if (skb->len <= 60)
+		sc |= BD_ENET_TX_PAD;
+	CBDS_SC(bdp, sc);
+
+	(*fep->ops->tx_kickstart)(dev);
+
+	spin_unlock_irqrestore(&fep->tx_lock, flags);
+
+	return NETDEV_TX_OK;
+}
+
+static int fs_request_irq(struct net_device *dev, int irq, const char *name,
+		irqreturn_t (*irqf)(int irq, void *dev_id, struct pt_regs *regs))
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	(*fep->ops->pre_request_irq)(dev, irq);
+	return request_irq(irq, irqf, SA_SHIRQ, name, dev);
+}
+
+static void fs_free_irq(struct net_device *dev, int irq)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	free_irq(irq, dev);
+	(*fep->ops->post_free_irq)(dev, irq);
+}
+
+/**********************************************************************************/
+
+/* This interrupt occurs when the PHY detects a link change. */
+static irqreturn_t
+fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct fs_enet_private *fep;
+	const struct fs_platform_info *fpi;
+
+	fep = netdev_priv(dev);
+	fpi = fep->fpi;
+
+	/*
+	 * Acknowledge the interrupt if possible. If we have not
+	 * found the PHY yet we can't process or acknowledge the
+	 * interrupt now. Instead we ignore this interrupt for now,
+	 * which we can do since it is edge triggered. It will be
+	 * acknowledged later by fs_enet_open().
+	 */
+	if (!fep->phy)
+		return IRQ_NONE;
+
+	fs_mii_ack_int(dev);
+	fs_mii_link_status_change_check(dev, 0);
+
+	return IRQ_HANDLED;
+}
+
+static void fs_timeout(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int wake = 0;
+
+	fep->stats.tx_errors++;
+
+	spin_lock_irqsave(&fep->lock, flags);
+
+	if (dev->flags & IFF_UP) {
+		(*fep->ops->stop)(dev);
+		(*fep->ops->restart)(dev);
+	}
+
+	wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	if (wake)
+		netif_wake_queue(dev);
+}
+
+static int fs_enet_open(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	int r;
+
+	/* Install our interrupt handler. */
+	r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
+	if (r != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s Could not allocate FEC IRQ!", dev->name);
+		return -EINVAL;
+	}
+
+	/* Install our phy interrupt handler */
+	if (fpi->phy_irq != -1) {
+
+		r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
+		if (r != 0) {
+			printk(KERN_ERR DRV_MODULE_NAME
+			       ": %s Could not allocate PHY IRQ!", dev->name);
+			fs_free_irq(dev, fep->interrupt);
+			return -EINVAL;
+		}
+	}
+
+	fs_mii_startup(dev);
+	netif_carrier_off(dev);
+	fs_mii_link_status_change_check(dev, 1);
+
+	return 0;
+}
+
+static int fs_enet_close(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	unsigned long flags;
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+	fs_mii_shutdown(dev);
+
+	spin_lock_irqsave(&fep->lock, flags);
+	(*fep->ops->stop)(dev);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	/* release any irqs */
+	if (fpi->phy_irq != -1)
+		fs_free_irq(dev, fpi->phy_irq);
+	fs_free_irq(dev, fep->interrupt);
+
+	return 0;
+}
+
+static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	return &fep->stats;
+}
+
+/*************************************************************************/
+
+static void fs_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_MODULE_NAME);
+	strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int fs_get_regs_len(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	return (*fep->ops->get_regs_len)(dev);
+}
+
+static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			 void *p)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int r, len;
+
+	len = regs->len;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	r = (*fep->ops->get_regs)(dev, p, &len);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	if (r == 0)
+		regs->version = 0;
+}
+
+static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	rc = mii_ethtool_gset(&fep->mii_if, cmd);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	return rc;
+}
+
+static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	rc = mii_ethtool_sset(&fep->mii_if, cmd);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	return rc;
+}
+
+static int fs_nway_reset(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	return mii_nway_restart(&fep->mii_if);
+}
+
+static u32 fs_get_msglevel(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	return fep->msg_enable;
+}
+
+static void fs_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fep->msg_enable = value;
+}
+
+static struct ethtool_ops fs_ethtool_ops = {
+	.get_drvinfo = fs_get_drvinfo,
+	.get_regs_len = fs_get_regs_len,
+	.get_settings = fs_get_settings,
+	.set_settings = fs_set_settings,
+	.nway_reset = fs_nway_reset,
+	.get_link = ethtool_op_get_link,
+	.get_msglevel = fs_get_msglevel,
+	.set_msglevel = fs_set_msglevel,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,	/* local! */
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_regs = fs_get_regs,
+};
+
+static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
+	unsigned long flags;
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&fep->lock, flags);
+	rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+	spin_unlock_irqrestore(&fep->lock, flags);
+	return rc;
+}
+
+extern int fs_mii_connect(struct net_device *dev);
+extern void fs_mii_disconnect(struct net_device *dev);
+
+static struct net_device *fs_init_instance(struct device *dev,
+		const struct fs_platform_info *fpi)
+{
+	struct net_device *ndev = NULL;
+	struct fs_enet_private *fep = NULL;
+	int privsize, i, r, err = 0, registered = 0;
+
+	/* guard */
+	if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
+		return ERR_PTR(-EINVAL);
+
+	privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
+			    (fpi->rx_ring + fpi->tx_ring));
+
+	ndev = alloc_etherdev(privsize);
+	if (!ndev) {
+		err = -ENOMEM;
+		goto err;
+	}
+	SET_MODULE_OWNER(ndev);
+
+	fep = netdev_priv(ndev);
+	memset(fep, 0, privsize);	/* clear everything */
+
+	fep->dev = dev;
+	dev_set_drvdata(dev, ndev);
+	fep->fpi = fpi;
+	if (fpi->init_ioports)
+		fpi->init_ioports();
+
+#ifdef CONFIG_FS_ENET_HAS_FEC
+	if (fs_get_fec_index(fpi->fs_no) >= 0)
+		fep->ops = &fs_fec_ops;
+#endif
+
+#ifdef CONFIG_FS_ENET_HAS_SCC
+	if (fs_get_scc_index(fpi->fs_no) >=0 )
+		fep->ops = &fs_scc_ops;
+#endif
+
+#ifdef CONFIG_FS_ENET_HAS_FCC
+	if (fs_get_fcc_index(fpi->fs_no) >= 0)
+		fep->ops = &fs_fcc_ops;
+#endif
+
+	if (fep->ops == NULL) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s No matching ops found (%d).\n",
+		       ndev->name, fpi->fs_no);
+		err = -EINVAL;
+		goto err;
+	}
+
+	r = (*fep->ops->setup_data)(ndev);
+	if (r != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s setup_data failed\n",
+			ndev->name);
+		err = r;
+		goto err;
+	}
+
+	/* point rx_skbuff, tx_skbuff */
+	fep->rx_skbuff = (struct sk_buff **)&fep[1];
+	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
+
+	/* init locks */
+	spin_lock_init(&fep->lock);
+	spin_lock_init(&fep->tx_lock);
+
+	/*
+	 * Set the Ethernet address. 
+	 */
+	for (i = 0; i < 6; i++)
+		ndev->dev_addr[i] = fpi->macaddr[i];
+	
+	r = (*fep->ops->allocate_bd)(ndev);
+	
+	if (fep->ring_base == NULL) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
+		err = r;
+		goto err;
+	}
+
+	/*
+	 * Set receive and transmit descriptor base.
+	 */
+	fep->rx_bd_base = fep->ring_base;
+	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
+
+	/* initialize ring size variables */
+	fep->tx_ring = fpi->tx_ring;
+	fep->rx_ring = fpi->rx_ring;
+
+	/*
+	 * The FEC Ethernet specific entries in the device structure. 
+	 */
+	ndev->open = fs_enet_open;
+	ndev->hard_start_xmit = fs_enet_start_xmit;
+	ndev->tx_timeout = fs_timeout;
+	ndev->watchdog_timeo = 2 * HZ;
+	ndev->stop = fs_enet_close;
+	ndev->get_stats = fs_enet_get_stats;
+	ndev->set_multicast_list = fs_set_multicast_list;
+	if (fpi->use_napi) {
+		ndev->poll = fs_enet_rx_napi;
+		ndev->weight = fpi->napi_weight;
+	}
+	ndev->ethtool_ops = &fs_ethtool_ops;
+	ndev->do_ioctl = fs_ioctl;
+
+	init_timer(&fep->phy_timer_list);
+
+	netif_carrier_off(ndev);
+
+	err = register_netdev(ndev);
+	if (err != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s register_netdev failed.\n", ndev->name);
+		goto err;
+	}
+	registered = 1;
+
+	err = fs_mii_connect(ndev);
+	if (err != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s fs_mii_connect failed.\n", ndev->name);
+		goto err;
+	}
+
+	return ndev;
+
+      err:
+	if (ndev != NULL) {
+
+		if (registered)
+			unregister_netdev(ndev);
+
+		if (fep != NULL) {
+			(*fep->ops->free_bd)(ndev);
+			(*fep->ops->cleanup_data)(ndev);
+		}
+
+		free_netdev(ndev);
+	}
+
+	dev_set_drvdata(dev, NULL);
+
+	return ERR_PTR(err);
+}
+
+static int fs_cleanup_instance(struct net_device *ndev)
+{
+	struct fs_enet_private *fep;
+	const struct fs_platform_info *fpi;
+	struct device *dev;
+
+	if (ndev == NULL)
+		return -EINVAL;
+
+	fep = netdev_priv(ndev);
+	if (fep == NULL)
+		return -EINVAL;
+
+	fpi = fep->fpi;
+
+	fs_mii_disconnect(ndev);
+
+	unregister_netdev(ndev);
+
+	dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
+			  fep->ring_base, fep->ring_mem_addr);
+
+	/* reset it */
+	(*fep->ops->cleanup_data)(ndev);
+
+	dev = fep->dev;
+	if (dev != NULL) {
+		dev_set_drvdata(dev, NULL);
+		fep->dev = NULL;
+	}
+
+	free_netdev(ndev);
+
+	return 0;
+}
+
+/**************************************************************************************/
+
+/* handy pointer to the immap */
+void *fs_enet_immap = NULL;
+
+static int setup_immap(void)
+{
+	phys_addr_t paddr = 0;
+	unsigned long size = 0;
+
+#ifdef CONFIG_CPM1
+	paddr = IMAP_ADDR;
+	size = 0x10000;	/* map 64K */
+#endif
+
+#ifdef CONFIG_CPM2
+	paddr = CPM_MAP_ADDR;
+	size = 0x40000;	/* map 256 K */
+#endif
+	fs_enet_immap = ioremap(paddr, size);
+	if (fs_enet_immap == NULL)
+		return -EBADF;	/* XXX ahem; maybe just BUG_ON? */
+
+	return 0;
+}
+
+static void cleanup_immap(void)
+{
+	if (fs_enet_immap != NULL) {
+		iounmap(fs_enet_immap);
+		fs_enet_immap = NULL;
+	}
+}
+
+/**************************************************************************************/
+
+static int __devinit fs_enet_probe(struct device *dev)
+{
+	struct net_device *ndev;
+
+	/* no fixup - no device */
+	if (dev->platform_data == NULL) {
+		printk(KERN_INFO "fs_enet: "
+				"probe called with no platform data; "
+				"remove unused devices\n");
+		return -ENODEV;
+	}
+
+	ndev = fs_init_instance(dev, dev->platform_data);
+	if (IS_ERR(ndev))
+		return PTR_ERR(ndev);
+	return 0;
+}
+
+static int fs_enet_remove(struct device *dev)
+{
+	return fs_cleanup_instance(dev_get_drvdata(dev));
+}
+
+static struct device_driver fs_enet_fec_driver = {
+	.name	  	= "fsl-cpm-fec",
+	.bus		= &platform_bus_type,
+	.probe		= fs_enet_probe,
+	.remove		= fs_enet_remove,
+#ifdef CONFIG_PM
+/*	.suspend	= fs_enet_suspend,	TODO */
+/*	.resume		= fs_enet_resume,	TODO */
+#endif
+};
+
+static struct device_driver fs_enet_scc_driver = {
+	.name	  	= "fsl-cpm-scc",
+	.bus		= &platform_bus_type,
+	.probe		= fs_enet_probe,
+	.remove		= fs_enet_remove,
+#ifdef CONFIG_PM
+/*	.suspend	= fs_enet_suspend,	TODO */
+/*	.resume		= fs_enet_resume,	TODO */
+#endif
+};
+
+static struct device_driver fs_enet_fcc_driver = {
+	.name	  	= "fsl-cpm-fcc",
+	.bus		= &platform_bus_type,
+	.probe		= fs_enet_probe,
+	.remove		= fs_enet_remove,
+#ifdef CONFIG_PM
+/*	.suspend	= fs_enet_suspend,	TODO */
+/*	.resume		= fs_enet_resume,	TODO */
+#endif
+};
+
+static int __init fs_init(void)
+{
+	int r;
+
+	printk(KERN_INFO
+			"%s", version);
+
+	r = setup_immap();
+	if (r != 0)
+		return r;
+	r = driver_register(&fs_enet_fec_driver);
+	if (r != 0)
+		goto err;
+
+	r = driver_register(&fs_enet_fcc_driver);
+	if (r != 0)
+		goto err;
+
+	r = driver_register(&fs_enet_scc_driver);
+	if (r != 0)
+		goto err;
+
+	return 0;
+err:
+	cleanup_immap();
+	return r;
+	
+}
+
+static void __exit fs_cleanup(void)
+{
+	driver_unregister(&fs_enet_fec_driver);
+	driver_unregister(&fs_enet_fcc_driver);
+	driver_unregister(&fs_enet_scc_driver);
+	cleanup_immap();
+}
+
+/**************************************************************************************/
+
+module_init(fs_init);
+module_exit(fs_cleanup);
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c
new file mode 100644
index 0000000..c677037
--- /dev/null
+++ b/drivers/net/fs_enet/fs_enet-mii.c
@@ -0,0 +1,507 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ * 
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
+ * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ *
+ * 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.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/*
+ * Generic PHY support.
+ * Should work for all PHYs, but link change is detected by polling
+ */
+
+static void generic_timer_callback(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->phy_timer_list.expires = jiffies + HZ / 2;
+
+	add_timer(&fep->phy_timer_list);
+
+	fs_mii_link_status_change_check(dev, 0);
+}
+
+static void generic_startup(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->phy_timer_list.expires = jiffies + HZ / 2;	/* every 500ms */
+	fep->phy_timer_list.data = (unsigned long)dev;
+	fep->phy_timer_list.function = generic_timer_callback;
+	add_timer(&fep->phy_timer_list);
+}
+
+static void generic_shutdown(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	del_timer_sync(&fep->phy_timer_list);
+}
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9161 is used on the NETTA board			     */
+
+/* register definitions */
+
+#define MII_DM9161_ANAR		4	/* Aux. Config Register         */
+#define MII_DM9161_ACR		16	/* Aux. Config Register         */
+#define MII_DM9161_ACSR		17	/* Aux. Config/Status Register  */
+#define MII_DM9161_10TCSR	18	/* 10BaseT Config/Status Reg.   */
+#define MII_DM9161_INTR		21	/* Interrupt Register           */
+#define MII_DM9161_RECR		22	/* Receive Error Counter Reg.   */
+#define MII_DM9161_DISCR	23	/* Disconnect Counter Register  */
+
+static void dm9161_startup(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
+	/* Start autonegotiation */
+	fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ*8);
+}
+
+static void dm9161_ack_int(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
+}
+
+static void dm9161_shutdown(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
+}
+
+/**********************************************************************************/
+
+static const struct phy_info phy_info[] = {
+	{
+		.id = 0x00181b88,
+		.name = "DM9161",
+		.startup = dm9161_startup,
+		.ack_int = dm9161_ack_int,
+		.shutdown = dm9161_shutdown,
+	}, {
+		.id = 0,
+		.name = "GENERIC",
+		.startup = generic_startup,
+		.shutdown = generic_shutdown,
+	},
+};
+
+/**********************************************************************************/
+
+static int phy_id_detect(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	struct fs_enet_mii_bus *bus = fep->mii_bus;
+	int i, r, start, end, phytype, physubtype;
+	const struct phy_info *phy;
+	int phy_hwid, phy_id;
+
+	phy_hwid = -1;
+	fep->phy = NULL;
+
+	/* auto-detect? */
+	if (fpi->phy_addr == -1) {
+		start = 1;
+		end = 32;
+	} else {		/* direct */
+		start = fpi->phy_addr;
+		end = start + 1;
+	}
+
+	for (phy_id = start; phy_id < end; phy_id++) {
+		/* skip already used phy addresses on this bus */ 
+		if (bus->usage_map & (1 << phy_id))
+			continue;
+		r = fs_mii_read(dev, phy_id, MII_PHYSID1);
+		if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
+			continue;
+		r = fs_mii_read(dev, phy_id, MII_PHYSID2);
+		if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
+			continue;
+		phy_hwid = (phytype << 16) | physubtype;
+		if (phy_hwid != -1)
+			break;
+	}
+
+	if (phy_hwid == -1) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s No PHY detected! range=0x%02x-0x%02x\n",
+			dev->name, start, end);
+		return -1;
+	}
+
+	for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
+		if (phy->id == (phy_hwid >> 4) || phy->id == 0)
+			break;
+
+	if (i >= ARRAY_SIZE(phy_info)) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       ": %s PHY id 0x%08x is not supported!\n",
+		       dev->name, phy_hwid);
+		return -1;
+	}
+
+	fep->phy = phy;
+
+	/* mark this address as used */
+	bus->usage_map |= (1 << phy_id);
+
+	printk(KERN_INFO DRV_MODULE_NAME
+	       ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
+	       dev->name, phy_id, fep->phy->name, phy_hwid,
+	       fpi->phy_addr == -1 ? " (auto-detected)" : "");
+
+	return phy_id;
+}
+
+void fs_mii_startup(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->phy->startup)
+		(*fep->phy->startup) (dev);
+}
+
+void fs_mii_shutdown(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->phy->shutdown)
+		(*fep->phy->shutdown) (dev);
+}
+
+void fs_mii_ack_int(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->phy->ack_int)
+		(*fep->phy->ack_int) (dev);
+}
+
+#define MII_LINK	0x0001
+#define MII_HALF	0x0002
+#define MII_FULL	0x0004
+#define MII_BASE4	0x0008
+#define MII_10M		0x0010
+#define MII_100M	0x0020
+#define MII_1G		0x0040
+#define MII_10G		0x0080
+
+/* return full mii info at one gulp, with a usable form */
+static unsigned int mii_full_status(struct mii_if_info *mii)
+{
+	unsigned int status;
+	int bmsr, adv, lpa, neg;
+	struct fs_enet_private* fep = netdev_priv(mii->dev);
+	
+	/* first, a dummy read, needed to latch some MII phys */
+	(void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+	bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+
+	/* no link */
+	if ((bmsr & BMSR_LSTATUS) == 0)
+		return 0;
+
+	status = MII_LINK;
+	
+	/* Lets look what ANEG says if it's supported - otherwize we shall
+	   take the right values from the platform info*/
+	if(!mii->force_media) {
+		/* autoneg not completed; don't bother */
+		if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
+			return 0;
+
+		adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
+		lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
+
+		neg = lpa & adv;
+	} else {
+		neg = fep->fpi->bus_info->lpa;
+	}
+
+	if (neg & LPA_100FULL)
+		status |= MII_FULL | MII_100M;
+	else if (neg & LPA_100BASE4)
+		status |= MII_FULL | MII_BASE4 | MII_100M;
+	else if (neg & LPA_100HALF)
+		status |= MII_HALF | MII_100M;
+	else if (neg & LPA_10FULL)
+		status |= MII_FULL | MII_10M;
+	else
+		status |= MII_HALF | MII_10M;
+	
+	return status;
+}
+
+void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct mii_if_info *mii = &fep->mii_if;
+	unsigned int mii_status;
+	int ok_to_print, link, duplex, speed;
+	unsigned long flags;
+
+	ok_to_print = netif_msg_link(fep);
+
+	mii_status = mii_full_status(mii);
+
+	if (!init_media && mii_status == fep->last_mii_status)
+		return;
+
+	fep->last_mii_status = mii_status;
+
+	link = !!(mii_status & MII_LINK);
+	duplex = !!(mii_status & MII_FULL);
+	speed = (mii_status & MII_100M) ? 100 : 10;
+
+	if (link == 0) {
+		netif_carrier_off(mii->dev);
+		netif_stop_queue(dev);
+		if (!init_media) {
+			spin_lock_irqsave(&fep->lock, flags);
+			(*fep->ops->stop)(dev);
+			spin_unlock_irqrestore(&fep->lock, flags);
+		}
+
+		if (ok_to_print)
+			printk(KERN_INFO "%s: link down\n", mii->dev->name);
+
+	} else {
+
+		mii->full_duplex = duplex;
+
+		netif_carrier_on(mii->dev);
+
+		spin_lock_irqsave(&fep->lock, flags);
+		fep->duplex = duplex;
+		fep->speed = speed;
+		(*fep->ops->restart)(dev);
+		spin_unlock_irqrestore(&fep->lock, flags);
+
+		netif_start_queue(dev);
+
+		if (ok_to_print)
+			printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
+			       dev->name, speed, duplex ? "full" : "half");
+	}
+}
+
+/**********************************************************************************/
+
+int fs_mii_read(struct net_device *dev, int phy_id, int location)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_mii_bus *bus = fep->mii_bus;
+
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&bus->mii_lock, flags);
+	ret = (*bus->mii_read)(bus, phy_id, location);
+	spin_unlock_irqrestore(&bus->mii_lock, flags);
+
+	return ret;
+}
+
+void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_mii_bus *bus = fep->mii_bus;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bus->mii_lock, flags);
+	(*bus->mii_write)(bus, phy_id, location, value);
+	spin_unlock_irqrestore(&bus->mii_lock, flags);
+}
+
+/*****************************************************************************/
+
+/* list of all registered mii buses */
+static LIST_HEAD(fs_mii_bus_list);
+
+static struct fs_enet_mii_bus *lookup_bus(int method, int id)
+{
+	struct list_head *ptr;
+	struct fs_enet_mii_bus *bus;
+
+	list_for_each(ptr, &fs_mii_bus_list) {
+		bus = list_entry(ptr, struct fs_enet_mii_bus, list);
+		if (bus->bus_info->method == method &&
+			bus->bus_info->id == id)
+			return bus;
+	}
+	return NULL;
+}
+
+static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
+{
+	struct fs_enet_mii_bus *bus;
+	int ret = 0;
+
+	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+	if (bus == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	memset(bus, 0, sizeof(*bus));
+	spin_lock_init(&bus->mii_lock);
+	bus->bus_info = bi;
+	bus->refs = 0;
+	bus->usage_map = 0;
+
+	/* perform initialization */
+	switch (bi->method) {
+
+		case fsmii_fixed:
+			ret = fs_mii_fixed_init(bus);
+			if (ret != 0)
+				goto err;
+			break;
+
+		case fsmii_bitbang:
+			ret = fs_mii_bitbang_init(bus);
+			if (ret != 0)
+				goto err;
+			break;
+#ifdef CONFIG_FS_ENET_HAS_FEC
+		case fsmii_fec:
+			ret = fs_mii_fec_init(bus);
+			if (ret != 0)
+				goto err;
+			break;
+#endif
+		default:
+			ret = -EINVAL;
+			goto err;
+	}
+
+	list_add(&bus->list, &fs_mii_bus_list);
+
+	return bus;
+
+err:
+	if (bus)
+		kfree(bus);
+	return ERR_PTR(ret);
+}
+
+static void destroy_bus(struct fs_enet_mii_bus *bus)
+{
+	/* remove from bus list */
+	list_del(&bus->list);
+
+	/* nothing more needed */
+	kfree(bus);
+}
+
+int fs_mii_connect(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	struct fs_enet_mii_bus *bus = NULL;
+
+	/* check method validity */
+	switch (fpi->bus_info->method) {
+		case fsmii_fixed:
+		case fsmii_bitbang:
+			break;
+#ifdef CONFIG_FS_ENET_HAS_FEC
+		case fsmii_fec:
+			break;
+#endif
+		default:
+			printk(KERN_ERR DRV_MODULE_NAME
+			       ": %s Unknown MII bus method (%d)!\n",
+			       dev->name, fpi->bus_info->method);
+			return -EINVAL; 
+	}
+
+	bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
+
+	/* if not found create new bus */
+	if (bus == NULL) {
+		bus = create_bus(fpi->bus_info);
+		if (IS_ERR(bus)) {
+			printk(KERN_ERR DRV_MODULE_NAME
+			       ": %s MII bus creation failure!\n", dev->name);
+			return PTR_ERR(bus);
+		}
+	}
+
+	bus->refs++;
+
+	fep->mii_bus = bus;
+
+	fep->mii_if.dev = dev;
+	fep->mii_if.phy_id_mask = 0x1f;
+	fep->mii_if.reg_num_mask = 0x1f;
+	fep->mii_if.mdio_read = fs_mii_read;
+	fep->mii_if.mdio_write = fs_mii_write;
+	fep->mii_if.force_media = fpi->bus_info->disable_aneg;
+	fep->mii_if.phy_id = phy_id_detect(dev);
+
+	return 0;
+}
+
+void fs_mii_disconnect(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_mii_bus *bus = NULL;
+
+	bus = fep->mii_bus;
+	fep->mii_bus = NULL;
+
+	if (--bus->refs <= 0)
+		destroy_bus(bus);
+}
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
new file mode 100644
index 0000000..1105543
--- /dev/null
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -0,0 +1,245 @@
+#ifndef FS_ENET_H
+#define FS_ENET_H
+
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/list.h>
+
+#include <linux/fs_enet_pd.h>
+
+#include <asm/dma-mapping.h>
+
+#ifdef CONFIG_CPM1
+#include <asm/commproc.h>
+#endif
+
+#ifdef CONFIG_CPM2
+#include <asm/cpm2.h>
+#endif
+
+/* hw driver ops */
+struct fs_ops {
+	int (*setup_data)(struct net_device *dev);
+	int (*allocate_bd)(struct net_device *dev);
+	void (*free_bd)(struct net_device *dev);
+	void (*cleanup_data)(struct net_device *dev);
+	void (*set_multicast_list)(struct net_device *dev);
+	void (*restart)(struct net_device *dev);
+	void (*stop)(struct net_device *dev);
+	void (*pre_request_irq)(struct net_device *dev, int irq);
+	void (*post_free_irq)(struct net_device *dev, int irq);
+	void (*napi_clear_rx_event)(struct net_device *dev);
+	void (*napi_enable_rx)(struct net_device *dev);
+	void (*napi_disable_rx)(struct net_device *dev);
+	void (*rx_bd_done)(struct net_device *dev);
+	void (*tx_kickstart)(struct net_device *dev);
+	u32 (*get_int_events)(struct net_device *dev);
+	void (*clear_int_events)(struct net_device *dev, u32 int_events);
+	void (*ev_error)(struct net_device *dev, u32 int_events);
+	int (*get_regs)(struct net_device *dev, void *p, int *sizep);
+	int (*get_regs_len)(struct net_device *dev);
+	void (*tx_restart)(struct net_device *dev);
+};
+
+struct phy_info {
+	unsigned int id;
+	const char *name;
+	void (*startup) (struct net_device * dev);
+	void (*shutdown) (struct net_device * dev);
+	void (*ack_int) (struct net_device * dev);
+};
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define MAX_MTU 1508		/* Allow fullsized pppoe packets over VLAN */
+#define MIN_MTU 46		/* this is data size */
+#define CRC_LEN 4
+
+#define PKT_MAXBUF_SIZE		(MAX_MTU+ETH_HLEN+CRC_LEN)
+#define PKT_MINBUF_SIZE		(MIN_MTU+ETH_HLEN+CRC_LEN)
+
+/* Must be a multiple of 32 (to cover both FEC & FCC) */
+#define PKT_MAXBLR_SIZE		((PKT_MAXBUF_SIZE + 31) & ~31)
+/* This is needed so that invalidate_xxx wont invalidate too much */
+#define ENET_RX_FRSIZE		L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)
+
+struct fs_enet_mii_bus {
+	struct list_head list;
+	spinlock_t mii_lock;
+	const struct fs_mii_bus_info *bus_info;
+	int refs;
+	u32 usage_map;
+
+	int (*mii_read)(struct fs_enet_mii_bus *bus,
+			int phy_id, int location);
+
+	void (*mii_write)(struct fs_enet_mii_bus *bus,
+			int phy_id, int location, int value);
+
+	union {
+		struct {
+			unsigned int mii_speed;
+			void *fecp;
+		} fec;
+
+		struct {
+			/* note that the actual port size may */
+			/* be different; cpm(s) handle it OK  */
+			u8 mdio_msk;
+			u8 *mdio_dir;
+			u8 *mdio_dat;
+			u8 mdc_msk;
+			u8 *mdc_dir;
+			u8 *mdc_dat;
+		} bitbang;
+
+		struct {
+			u16 lpa;
+		} fixed;
+	};
+};
+
+int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
+int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
+
+struct fs_enet_private {
+	struct device *dev;	/* pointer back to the device (must be initialized first) */
+	spinlock_t lock;	/* during all ops except TX pckt processing */
+	spinlock_t tx_lock;	/* during fs_start_xmit and fs_tx         */
+	const struct fs_platform_info *fpi;
+	const struct fs_ops *ops;
+	int rx_ring, tx_ring;
+	dma_addr_t ring_mem_addr;
+	void *ring_base;
+	struct sk_buff **rx_skbuff;
+	struct sk_buff **tx_skbuff;
+	cbd_t *rx_bd_base;	/* Address of Rx and Tx buffers.    */
+	cbd_t *tx_bd_base;
+	cbd_t *dirty_tx;	/* ring entries to be free()ed.     */
+	cbd_t *cur_rx;
+	cbd_t *cur_tx;
+	int tx_free;
+	struct net_device_stats stats;
+	struct timer_list phy_timer_list;
+	const struct phy_info *phy;
+	u32 msg_enable;
+	struct mii_if_info mii_if;
+	unsigned int last_mii_status;
+	struct fs_enet_mii_bus *mii_bus;
+	int interrupt;
+
+	int duplex, speed;	/* current settings */
+
+	/* event masks */
+	u32 ev_napi_rx;		/* mask of NAPI rx events */
+	u32 ev_rx;		/* rx event mask          */
+	u32 ev_tx;		/* tx event mask          */
+	u32 ev_err;		/* error event mask       */
+
+	u16 bd_rx_empty;	/* mask of BD rx empty	  */
+	u16 bd_rx_err;		/* mask of BD rx errors   */
+
+	union {
+		struct {
+			int idx;		/* FEC1 = 0, FEC2 = 1  */
+			void *fecp;		/* hw registers        */
+			u32 hthi, htlo;		/* state for multicast */
+		} fec;
+
+		struct {
+			int idx;		/* FCC1-3 = 0-2	       */
+			void *fccp;		/* hw registers	       */
+			void *ep;		/* parameter ram       */
+			void *fcccp;		/* hw registers cont.  */
+			void *mem;		/* FCC DPRAM */
+			u32 gaddrh, gaddrl;	/* group address       */
+		} fcc;
+
+		struct {
+			int idx;		/* FEC1 = 0, FEC2 = 1  */
+			void *sccp;		/* hw registers        */
+			void *ep;		/* parameter ram       */
+			u32 hthi, htlo;		/* state for multicast */
+		} scc;
+
+	};
+};
+
+/***************************************************************************/
+
+int fs_mii_read(struct net_device *dev, int phy_id, int location);
+void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
+
+void fs_mii_startup(struct net_device *dev);
+void fs_mii_shutdown(struct net_device *dev);
+void fs_mii_ack_int(struct net_device *dev);
+
+void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
+
+void fs_init_bds(struct net_device *dev);
+void fs_cleanup_bds(struct net_device *dev);
+
+/***************************************************************************/
+
+#define DRV_MODULE_NAME		"fs_enet"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"1.0"
+#define DRV_MODULE_RELDATE	"Aug 8, 2005"
+
+/***************************************************************************/
+
+int fs_enet_platform_init(void);
+void fs_enet_platform_cleanup(void);
+
+/***************************************************************************/
+
+/* buffer descriptor access macros */
+
+/* access macros */
+#if defined(CONFIG_CPM1)
+/* for a a CPM1 __raw_xxx's are sufficient */
+#define __cbd_out32(addr, x)	__raw_writel(x, addr)
+#define __cbd_out16(addr, x)	__raw_writew(x, addr)
+#define __cbd_in32(addr)	__raw_readl(addr)
+#define __cbd_in16(addr)	__raw_readw(addr)
+#else
+/* for others play it safe */
+#define __cbd_out32(addr, x)	out_be32(addr, x)
+#define __cbd_out16(addr, x)	out_be16(addr, x)
+#define __cbd_in32(addr)	in_be32(addr)
+#define __cbd_in16(addr)	in_be16(addr)
+#endif
+
+/* write */
+#define CBDW_SC(_cbd, _sc) 		__cbd_out16(&(_cbd)->cbd_sc, (_sc))
+#define CBDW_DATLEN(_cbd, _datlen)	__cbd_out16(&(_cbd)->cbd_datlen, (_datlen))
+#define CBDW_BUFADDR(_cbd, _bufaddr)	__cbd_out32(&(_cbd)->cbd_bufaddr, (_bufaddr))
+
+/* read */
+#define CBDR_SC(_cbd) 			__cbd_in16(&(_cbd)->cbd_sc)
+#define CBDR_DATLEN(_cbd)		__cbd_in16(&(_cbd)->cbd_datlen)
+#define CBDR_BUFADDR(_cbd)		__cbd_in32(&(_cbd)->cbd_bufaddr)
+
+/* set bits */
+#define CBDS_SC(_cbd, _sc) 		CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc))
+
+/* clear bits */
+#define CBDC_SC(_cbd, _sc) 		CBDW_SC(_cbd, CBDR_SC(_cbd) & ~(_sc))
+
+/*******************************************************************/
+
+extern const struct fs_ops fs_fec_ops;
+extern const struct fs_ops fs_fcc_ops;
+extern const struct fs_ops fs_scc_ops;
+
+/*******************************************************************/
+
+/* handy pointer to the immap */
+extern void *fs_enet_immap;
+
+/*******************************************************************/
+
+#endif
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
new file mode 100644
index 0000000..a940b96
--- /dev/null
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -0,0 +1,578 @@
+/*
+ * FCC driver for Motorola MPC82xx (PQ2).
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+/* FCC access macros */
+
+#define __fcc_out32(addr, x)	out_be32((unsigned *)addr, x)
+#define __fcc_out16(addr, x)	out_be16((unsigned short *)addr, x)
+#define __fcc_out8(addr, x)	out_8((unsigned char *)addr, x)
+#define __fcc_in32(addr)	in_be32((unsigned *)addr)
+#define __fcc_in16(addr)	in_be16((unsigned short *)addr)
+#define __fcc_in8(addr)		in_8((unsigned char *)addr)
+
+/* parameter space */
+
+/* write, read, set bits, clear bits */
+#define W32(_p, _m, _v)	__fcc_out32(&(_p)->_m, (_v))
+#define R32(_p, _m)	__fcc_in32(&(_p)->_m)
+#define S32(_p, _m, _v)	W32(_p, _m, R32(_p, _m) | (_v))
+#define C32(_p, _m, _v)	W32(_p, _m, R32(_p, _m) & ~(_v))
+
+#define W16(_p, _m, _v)	__fcc_out16(&(_p)->_m, (_v))
+#define R16(_p, _m)	__fcc_in16(&(_p)->_m)
+#define S16(_p, _m, _v)	W16(_p, _m, R16(_p, _m) | (_v))
+#define C16(_p, _m, _v)	W16(_p, _m, R16(_p, _m) & ~(_v))
+
+#define W8(_p, _m, _v)	__fcc_out8(&(_p)->_m, (_v))
+#define R8(_p, _m)	__fcc_in8(&(_p)->_m)
+#define S8(_p, _m, _v)	W8(_p, _m, R8(_p, _m) | (_v))
+#define C8(_p, _m, _v)	W8(_p, _m, R8(_p, _m) & ~(_v))
+
+/*************************************************/
+
+#define FCC_MAX_MULTICAST_ADDRS	64
+
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end		0
+
+#define MAX_CR_CMD_LOOPS	10000
+
+static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 mcn, u32 op)
+{
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	cpm2_map_t *immap = fs_enet_immap;
+	cpm_cpm2_t *cpmp = &immap->im_cpm;
+	u32 v;
+	int i;
+
+	/* Currently I don't know what feature call will look like. But 
+	   I guess there'd be something like do_cpm_cmd() which will require page & sblock */
+	v = mk_cr_cmd(fpi->cp_page, fpi->cp_block, mcn, op);
+	W32(cpmp, cp_cpcr, v | CPM_CR_FLG);
+	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+		if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
+			break;
+
+	if (i >= MAX_CR_CMD_LOOPS) {
+		printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+		       __FUNCTION__);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int do_pd_setup(struct fs_enet_private *fep)
+{
+	struct platform_device *pdev = to_platform_device(fep->dev);
+	struct resource *r;
+
+	/* Fill out IRQ field */
+	fep->interrupt = platform_get_irq(pdev, 0);
+
+	/* Attach the memory for the FCC Parameter RAM */
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
+	fep->fcc.ep = (void *)r->start;
+
+	if (fep->fcc.ep == NULL)
+		return -EINVAL;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
+	fep->fcc.fccp = (void *)r->start;
+
+	if (fep->fcc.fccp == NULL)
+		return -EINVAL;
+
+	fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+
+	if (fep->fcc.fcccp == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+#define FCC_NAPI_RX_EVENT_MSK	(FCC_ENET_RXF | FCC_ENET_RXB)
+#define FCC_RX_EVENT		(FCC_ENET_RXF)
+#define FCC_TX_EVENT		(FCC_ENET_TXB)
+#define FCC_ERR_EVENT_MSK	(FCC_ENET_TXE | FCC_ENET_BSY)
+
+static int setup_data(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
+	if ((unsigned int)fep->fcc.idx >= 3)	/* max 3 FCCs */
+		return -EINVAL;
+
+	fep->fcc.mem = (void *)fpi->mem_offset;
+
+	if (do_pd_setup(fep) != 0)
+		return -EINVAL;
+
+	fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK;
+	fep->ev_rx = FCC_RX_EVENT;
+	fep->ev_tx = FCC_TX_EVENT;
+	fep->ev_err = FCC_ERR_EVENT_MSK;
+
+	return 0;
+}
+
+static int allocate_bd(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	fep->ring_base = dma_alloc_coherent(fep->dev,
+					    (fpi->tx_ring + fpi->rx_ring) *
+					    sizeof(cbd_t), &fep->ring_mem_addr,
+					    GFP_KERNEL);
+	if (fep->ring_base == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void free_bd(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	if (fep->ring_base)
+		dma_free_coherent(fep->dev,
+			(fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
+			fep->ring_base, fep->ring_mem_addr);
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	S32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_enet_t *ep = fep->fcc.ep;
+
+	W32(ep, fen_gaddrh, 0);
+	W32(ep, fen_gaddrl, 0);
+}
+
+static void set_multicast_one(struct net_device *dev, const u8 *mac)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_enet_t *ep = fep->fcc.ep;
+	u16 taddrh, taddrm, taddrl;
+
+	taddrh = ((u16)mac[5] << 8) | mac[4];
+	taddrm = ((u16)mac[3] << 8) | mac[2];
+	taddrl = ((u16)mac[1] << 8) | mac[0];
+
+	W16(ep, fen_taddrh, taddrh);
+	W16(ep, fen_taddrm, taddrm);
+	W16(ep, fen_taddrl, taddrl);
+	fcc_cr_cmd(fep, 0x0C, CPM_CR_SET_GADDR);
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+	fcc_enet_t *ep = fep->fcc.ep;
+
+	/* clear promiscuous always */
+	C32(fccp, fcc_fpsmr, FCC_PSMR_PRO);
+
+	/* if all multi or too many multicasts; just enable all */
+	if ((dev->flags & IFF_ALLMULTI) != 0 ||
+	    dev->mc_count > FCC_MAX_MULTICAST_ADDRS) {
+
+		W32(ep, fen_gaddrh, 0xffffffff);
+		W32(ep, fen_gaddrl, 0xffffffff);
+	}
+
+	/* read back */
+	fep->fcc.gaddrh = R32(ep, fen_gaddrh);
+	fep->fcc.gaddrl = R32(ep, fen_gaddrl);
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct dev_mc_list *pmc;
+
+	if ((dev->flags & IFF_PROMISC) == 0) {
+		set_multicast_start(dev);
+		for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+			set_multicast_one(dev, pmc->dmi_addr);
+		set_multicast_finish(dev);
+	} else
+		set_promiscuous_mode(dev);
+}
+
+static void restart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	fcc_t *fccp = fep->fcc.fccp;
+	fcc_c_t *fcccp = fep->fcc.fcccp;
+	fcc_enet_t *ep = fep->fcc.ep;
+	dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
+	u16 paddrh, paddrm, paddrl;
+	u16 mem_addr;
+	const unsigned char *mac;
+	int i;
+
+	C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+	/* clear everything (slow & steady does it) */
+	for (i = 0; i < sizeof(*ep); i++)
+		__fcc_out8((char *)ep + i, 0);
+
+	/* get physical address */
+	rx_bd_base_phys = fep->ring_mem_addr;
+	tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring;
+
+	/* point to bds */
+	W32(ep, fen_genfcc.fcc_rbase, rx_bd_base_phys);
+	W32(ep, fen_genfcc.fcc_tbase, tx_bd_base_phys);
+
+	/* Set maximum bytes per receive buffer.
+	 * It must be a multiple of 32.
+	 */
+	W16(ep, fen_genfcc.fcc_mrblr, PKT_MAXBLR_SIZE);
+
+	W32(ep, fen_genfcc.fcc_rstate, (CPMFCR_GBL | CPMFCR_EB) << 24);
+	W32(ep, fen_genfcc.fcc_tstate, (CPMFCR_GBL | CPMFCR_EB) << 24);
+
+	/* Allocate space in the reserved FCC area of DPRAM for the
+	 * internal buffers.  No one uses this space (yet), so we
+	 * can do this.  Later, we will add resource management for
+	 * this area.
+	 */
+
+	mem_addr = (u32) fep->fcc.mem;	/* de-fixup dpram offset */
+
+	W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
+	W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
+	W16(ep, fen_padptr, mem_addr + 64);
+
+	/* fill with special symbol...  */
+	memset(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
+
+	W32(ep, fen_genfcc.fcc_rbptr, 0);
+	W32(ep, fen_genfcc.fcc_tbptr, 0);
+	W32(ep, fen_genfcc.fcc_rcrc, 0);
+	W32(ep, fen_genfcc.fcc_tcrc, 0);
+	W16(ep, fen_genfcc.fcc_res1, 0);
+	W32(ep, fen_genfcc.fcc_res2, 0);
+
+	/* no CAM */
+	W32(ep, fen_camptr, 0);
+
+	/* Set CRC preset and mask */
+	W32(ep, fen_cmask, 0xdebb20e3);
+	W32(ep, fen_cpres, 0xffffffff);
+
+	W32(ep, fen_crcec, 0);		/* CRC Error counter       */
+	W32(ep, fen_alec, 0);		/* alignment error counter */
+	W32(ep, fen_disfc, 0);		/* discard frame counter   */
+	W16(ep, fen_retlim, 15);	/* Retry limit threshold   */
+	W16(ep, fen_pper, 0);		/* Normal persistence      */
+
+	/* set group address */
+	W32(ep, fen_gaddrh, fep->fcc.gaddrh);
+	W32(ep, fen_gaddrl, fep->fcc.gaddrh);
+
+	/* Clear hash filter tables */
+	W32(ep, fen_iaddrh, 0);
+	W32(ep, fen_iaddrl, 0);
+
+	/* Clear the Out-of-sequence TxBD  */
+	W16(ep, fen_tfcstat, 0);
+	W16(ep, fen_tfclen, 0);
+	W32(ep, fen_tfcptr, 0);
+
+	W16(ep, fen_mflr, PKT_MAXBUF_SIZE);	/* maximum frame length register */
+	W16(ep, fen_minflr, PKT_MINBUF_SIZE);	/* minimum frame length register */
+
+	/* set address */
+	mac = dev->dev_addr;
+	paddrh = ((u16)mac[5] << 8) | mac[4];
+	paddrm = ((u16)mac[3] << 8) | mac[2];
+	paddrl = ((u16)mac[1] << 8) | mac[0];
+
+	W16(ep, fen_paddrh, paddrh);
+	W16(ep, fen_paddrm, paddrm);
+	W16(ep, fen_paddrl, paddrl);
+
+	W16(ep, fen_taddrh, 0);
+	W16(ep, fen_taddrm, 0);
+	W16(ep, fen_taddrl, 0);
+
+	W16(ep, fen_maxd1, 1520);	/* maximum DMA1 length */
+	W16(ep, fen_maxd2, 1520);	/* maximum DMA2 length */
+
+	/* Clear stat counters, in case we ever enable RMON */
+	W32(ep, fen_octc, 0);
+	W32(ep, fen_colc, 0);
+	W32(ep, fen_broc, 0);
+	W32(ep, fen_mulc, 0);
+	W32(ep, fen_uspc, 0);
+	W32(ep, fen_frgc, 0);
+	W32(ep, fen_ospc, 0);
+	W32(ep, fen_jbrc, 0);
+	W32(ep, fen_p64c, 0);
+	W32(ep, fen_p65c, 0);
+	W32(ep, fen_p128c, 0);
+	W32(ep, fen_p256c, 0);
+	W32(ep, fen_p512c, 0);
+	W32(ep, fen_p1024c, 0);
+
+	W16(ep, fen_rfthr, 0);	/* Suggested by manual */
+	W16(ep, fen_rfcnt, 0);
+	W16(ep, fen_cftype, 0);
+
+	fs_init_bds(dev);
+
+	/* adjust to speed (for RMII mode) */
+	if (fpi->use_rmii) {
+		if (fep->speed == 100)
+			C8(fcccp, fcc_gfemr, 0x20);
+		else
+			S8(fcccp, fcc_gfemr, 0x20);
+	}
+
+	fcc_cr_cmd(fep, 0x0c, CPM_CR_INIT_TRX);
+
+	/* clear events */
+	W16(fccp, fcc_fcce, 0xffff);
+
+	/* Enable interrupts we wish to service */
+	W16(fccp, fcc_fccm, FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+	/* Set GFMR to enable Ethernet operating mode */
+	W32(fccp, fcc_gfmr, FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+	/* set sync/delimiters */
+	W16(fccp, fcc_fdsr, 0xd555);
+
+	W32(fccp, fcc_fpsmr, FCC_PSMR_ENCRC);
+
+	if (fpi->use_rmii)
+		S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
+
+	/* adjust to duplex mode */
+	if (fep->duplex)
+		S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
+	else
+		C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
+
+	S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+static void stop(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	/* stop ethernet */
+	C32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+	/* clear events */
+	W16(fccp, fcc_fcce, 0xffff);
+
+	/* clear interrupt mask */
+	W16(fccp, fcc_fccm, 0);
+
+	fs_cleanup_bds(dev);
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void post_free_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void napi_clear_rx_event(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	W16(fccp, fcc_fcce, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	S16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static u32 get_int_events(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	return (u32)R16(fccp, fcc_fcce);
+}
+
+static void clear_int_events(struct net_device *dev, u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	W16(fccp, fcc_fcce, int_events & 0xffff);
+}
+
+static void ev_error(struct net_device *dev, u32 int_events)
+{
+	printk(KERN_WARNING DRV_MODULE_NAME
+	       ": %s FS_ENET ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (*sizep < sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t))
+		return -EINVAL;
+
+	memcpy_fromio(p, fep->fcc.fccp, sizeof(fcc_t));
+	p = (char *)p + sizeof(fcc_t);
+
+	memcpy_fromio(p, fep->fcc.fcccp, sizeof(fcc_c_t));
+	p = (char *)p + sizeof(fcc_c_t);
+
+	memcpy_fromio(p, fep->fcc.ep, sizeof(fcc_enet_t));
+
+	return 0;
+}
+
+int get_regs_len(struct net_device *dev)
+{
+	return sizeof(fcc_t) + sizeof(fcc_c_t) + sizeof(fcc_enet_t);
+}
+
+/* Some transmit errors cause the transmitter to shut
+ * down.  We now issue a restart transmit.  Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either.  Also, To workaround 8260 device erratum 
+ * CPM37, we must disable and then re-enable the transmitter
+ * following a Late Collision, Underrun, or Retry Limit error.
+ */
+void tx_restart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
+	udelay(10);
+	S32(fccp, fcc_gfmr, FCC_GFMR_ENT);
+
+	fcc_cr_cmd(fep, 0x0C, CPM_CR_RESTART_TX);
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_fcc_ops = {
+	.setup_data		= setup_data,
+	.cleanup_data		= cleanup_data,
+	.set_multicast_list	= set_multicast_list,
+	.restart		= restart,
+	.stop			= stop,
+	.pre_request_irq	= pre_request_irq,
+	.post_free_irq		= post_free_irq,
+	.napi_clear_rx_event	= napi_clear_rx_event,
+	.napi_enable_rx		= napi_enable_rx,
+	.napi_disable_rx	= napi_disable_rx,
+	.rx_bd_done		= rx_bd_done,
+	.tx_kickstart		= tx_kickstart,
+	.get_int_events		= get_int_events,
+	.clear_int_events	= clear_int_events,
+	.ev_error		= ev_error,
+	.get_regs		= get_regs,
+	.get_regs_len		= get_regs_len,
+	.tx_restart		= tx_restart,
+	.allocate_bd		= allocate_bd,
+	.free_bd		= free_bd,
+};
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
new file mode 100644
index 0000000..5ef4e84
--- /dev/null
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -0,0 +1,653 @@
+/*
+ * Freescale Ethernet controllers
+ *
+ * Copyright (c) 2005 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_8xx
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+#endif
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+#if defined(CONFIG_CPM1)
+/* for a CPM1 __raw_xxx's are sufficient */
+#define __fs_out32(addr, x)	__raw_writel(x, addr)
+#define __fs_out16(addr, x)	__raw_writew(x, addr)
+#define __fs_in32(addr)	__raw_readl(addr)
+#define __fs_in16(addr)	__raw_readw(addr)
+#else
+/* for others play it safe */
+#define __fs_out32(addr, x)	out_be32(addr, x)
+#define __fs_out16(addr, x)	out_be16(addr, x)
+#define __fs_in32(addr)	in_be32(addr)
+#define __fs_in16(addr)	in_be16(addr)
+#endif
+
+/* write */
+#define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
+
+/* read */
+#define FR(_fecp, _reg)	__fs_in32(&(_fecp)->fec_ ## _reg)
+
+/* set bits */
+#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
+
+/* clear bits */
+#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
+
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY   0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS	64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR	0x80000000U	/* Heartbeat error          */
+#define FEC_ENET_BABR	0x40000000U	/* Babbling receiver        */
+#define FEC_ENET_BABT	0x20000000U	/* Babbling transmitter     */
+#define FEC_ENET_GRA	0x10000000U	/* Graceful stop complete   */
+#define FEC_ENET_TXF	0x08000000U	/* Full frame transmitted   */
+#define FEC_ENET_TXB	0x04000000U	/* A buffer was transmitted */
+#define FEC_ENET_RXF	0x02000000U	/* Full frame received      */
+#define FEC_ENET_RXB	0x01000000U	/* A buffer was received    */
+#define FEC_ENET_MII	0x00800000U	/* MII interrupt            */
+#define FEC_ENET_EBERR	0x00400000U	/* SDMA bus error           */
+
+#define FEC_ECNTRL_PINMUX	0x00000004
+#define FEC_ECNTRL_ETHER_EN	0x00000002
+#define FEC_ECNTRL_RESET	0x00000001
+
+#define FEC_RCNTRL_BC_REJ	0x00000010
+#define FEC_RCNTRL_PROM		0x00000008
+#define FEC_RCNTRL_MII_MODE	0x00000004
+#define FEC_RCNTRL_DRT		0x00000002
+#define FEC_RCNTRL_LOOP		0x00000001
+
+#define FEC_TCNTRL_FDEN		0x00000004
+#define FEC_TCNTRL_HBC		0x00000002
+#define FEC_TCNTRL_GTS		0x00000001
+
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end		0
+
+#define FEC_MII_LOOPS	10000
+
+/*
+ * Delay to wait for FEC reset command to complete (in us) 
+ */
+#define FEC_RESET_DELAY		50
+
+static int whack_reset(fec_t * fecp)
+{
+	int i;
+
+	FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
+	for (i = 0; i < FEC_RESET_DELAY; i++) {
+		if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0)
+			return 0;	/* OK */
+		udelay(1);
+	}
+
+	return -1;
+}
+
+static int do_pd_setup(struct fs_enet_private *fep)
+{
+	struct platform_device *pdev = to_platform_device(fep->dev); 
+	struct resource	*r;
+	
+	/* Fill out IRQ field */
+	fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
+	
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+	fep->fec.fecp =(void*)r->start;
+
+	if(fep->fec.fecp == NULL)
+		return -EINVAL;
+
+	return 0;
+	
+}
+
+#define FEC_NAPI_RX_EVENT_MSK	(FEC_ENET_RXF | FEC_ENET_RXB)
+#define FEC_RX_EVENT		(FEC_ENET_RXF)
+#define FEC_TX_EVENT		(FEC_ENET_TXF)
+#define FEC_ERR_EVENT_MSK	(FEC_ENET_HBERR | FEC_ENET_BABR | \
+				 FEC_ENET_BABT | FEC_ENET_EBERR)
+
+static int setup_data(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (do_pd_setup(fep) != 0)
+		return -EINVAL;
+
+	fep->fec.hthi = 0;
+	fep->fec.htlo = 0;
+
+	fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK;
+	fep->ev_rx = FEC_RX_EVENT;
+	fep->ev_tx = FEC_TX_EVENT;
+	fep->ev_err = FEC_ERR_EVENT_MSK;
+
+	return 0;
+}
+
+static int allocate_bd(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+	
+	fep->ring_base = dma_alloc_coherent(fep->dev,
+					    (fpi->tx_ring + fpi->rx_ring) *
+					    sizeof(cbd_t), &fep->ring_mem_addr,
+					    GFP_KERNEL);
+	if (fep->ring_base == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void free_bd(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	if(fep->ring_base)
+		dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring)
+					* sizeof(cbd_t),
+					fep->ring_base,
+					fep->ring_mem_addr);
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	fep->fec.hthi = 0;
+	fep->fec.htlo = 0;
+}
+
+static void set_multicast_one(struct net_device *dev, const u8 *mac)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	int temp, hash_index, i, j;
+	u32 crc, csrVal;
+	u8 byte, msb;
+
+	crc = 0xffffffff;
+	for (i = 0; i < 6; i++) {
+		byte = mac[i];
+		for (j = 0; j < 8; j++) {
+			msb = crc >> 31;
+			crc <<= 1;
+			if (msb ^ (byte & 0x1))
+				crc ^= FEC_CRC_POLY;
+			byte >>= 1;
+		}
+	}
+
+	temp = (crc & 0x3f) >> 1;
+	hash_index = ((temp & 0x01) << 4) |
+		     ((temp & 0x02) << 2) |
+		     ((temp & 0x04)) |
+		     ((temp & 0x08) >> 2) |
+		     ((temp & 0x10) >> 4);
+	csrVal = 1 << hash_index;
+	if (crc & 1)
+		fep->fec.hthi |= csrVal;
+	else
+		fep->fec.htlo |= csrVal;
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	/* if all multi or too many multicasts; just enable all */
+	if ((dev->flags & IFF_ALLMULTI) != 0 ||
+	    dev->mc_count > FEC_MAX_MULTICAST_ADDRS) {
+		fep->fec.hthi = 0xffffffffU;
+		fep->fec.htlo = 0xffffffffU;
+	}
+
+	FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
+	FW(fecp, hash_table_high, fep->fec.hthi);
+	FW(fecp, hash_table_low, fep->fec.htlo);
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct dev_mc_list *pmc;
+
+	if ((dev->flags & IFF_PROMISC) == 0) {
+		set_multicast_start(dev);
+		for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+			set_multicast_one(dev, pmc->dmi_addr);
+		set_multicast_finish(dev);
+	} else
+		set_promiscuous_mode(dev);
+}
+
+static void restart(struct net_device *dev)
+{
+#ifdef CONFIG_DUET
+	immap_t *immap = fs_enet_immap;
+	u32 cptr;
+#endif
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+	const struct fs_platform_info *fpi = fep->fpi;
+	dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
+	int r;
+	u32 addrhi, addrlo;
+
+	r = whack_reset(fep->fec.fecp);
+	if (r != 0)
+		printk(KERN_ERR DRV_MODULE_NAME
+				": %s FEC Reset FAILED!\n", dev->name);
+
+	/*
+	 * Set station address. 
+	 */
+	addrhi = ((u32) dev->dev_addr[0] << 24) |
+		 ((u32) dev->dev_addr[1] << 16) |
+		 ((u32) dev->dev_addr[2] <<  8) |
+		  (u32) dev->dev_addr[3];
+	addrlo = ((u32) dev->dev_addr[4] << 24) |
+		 ((u32) dev->dev_addr[5] << 16);
+	FW(fecp, addr_low, addrhi);
+	FW(fecp, addr_high, addrlo);
+
+	/*
+	 * Reset all multicast. 
+	 */
+	FW(fecp, hash_table_high, fep->fec.hthi);
+	FW(fecp, hash_table_low, fep->fec.htlo);
+
+	/*
+	 * Set maximum receive buffer size. 
+	 */
+	FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
+	FW(fecp, r_hash, PKT_MAXBUF_SIZE);
+
+	/* get physical address */
+	rx_bd_base_phys = fep->ring_mem_addr;
+	tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring;
+
+	/*
+	 * Set receive and transmit descriptor base. 
+	 */
+	FW(fecp, r_des_start, rx_bd_base_phys);
+	FW(fecp, x_des_start, tx_bd_base_phys);
+
+	fs_init_bds(dev);
+
+	/*
+	 * Enable big endian and don't care about SDMA FC. 
+	 */
+	FW(fecp, fun_code, 0x78000000);
+
+	/*
+	 * Set MII speed. 
+	 */
+	FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
+
+	/*
+	 * Clear any outstanding interrupt. 
+	 */
+	FW(fecp, ievent, 0xffc0);
+	FW(fecp, ivec, (fep->interrupt / 2) << 29);
+	
+
+	/*
+	 * adjust to speed (only for DUET & RMII) 
+	 */
+#ifdef CONFIG_DUET
+	if (fpi->use_rmii) {
+		cptr = in_be32(&immap->im_cpm.cp_cptr);
+		switch (fs_get_fec_index(fpi->fs_no)) {
+		case 0:
+			cptr |= 0x100;
+			if (fep->speed == 10)
+				cptr |= 0x0000010;
+			else if (fep->speed == 100)
+				cptr &= ~0x0000010;
+			break;
+		case 1:
+			cptr |= 0x80;
+			if (fep->speed == 10)
+				cptr |= 0x0000008;
+			else if (fep->speed == 100)
+				cptr &= ~0x0000008;
+			break;
+		default:
+			BUG();	/* should never happen */
+			break;
+		}
+		out_be32(&immap->im_cpm.cp_cptr, cptr);
+	}
+#endif
+
+	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+	/*
+	 * adjust to duplex mode 
+	 */
+	if (fep->duplex) {
+		FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
+		FS(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD enable */
+	} else {
+		FS(fecp, r_cntrl, FEC_RCNTRL_DRT);
+		FC(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD disable */
+	}
+
+	/*
+	 * Enable interrupts we wish to service. 
+	 */
+	FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB |
+	   FEC_ENET_RXF | FEC_ENET_RXB);
+
+	/*
+	 * And last, enable the transmit and receive processing. 
+	 */
+	FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+	FW(fecp, r_des_active, 0x01000000);
+}
+
+static void stop(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+	struct fs_enet_mii_bus *bus = fep->mii_bus;
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+	int i;
+
+	if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
+		return;		/* already down */
+
+	FW(fecp, x_cntrl, 0x01);	/* Graceful transmit stop */
+	for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) &&
+	     i < FEC_RESET_DELAY; i++)
+		udelay(1);
+
+	if (i == FEC_RESET_DELAY)
+		printk(KERN_WARNING DRV_MODULE_NAME
+		       ": %s FEC timeout on graceful transmit stop\n",
+		       dev->name);
+	/*
+	 * Disable FEC. Let only MII interrupts. 
+	 */
+	FW(fecp, imask, 0);
+	FC(fecp, ecntrl, FEC_ECNTRL_ETHER_EN);
+
+	fs_cleanup_bds(dev);
+
+	/* shut down FEC1? that's where the mii bus is */
+	if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) {
+		FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+		FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+		FW(fecp, ievent, FEC_ENET_MII);
+		FW(fecp, mii_speed, bus->fec.mii_speed);
+	}
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+	immap_t *immap = fs_enet_immap;
+	u32 siel;
+
+	/* SIU interrupt */
+	if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) {
+
+		siel = in_be32(&immap->im_siu_conf.sc_siel);
+		if ((irq & 1) == 0)
+			siel |= (0x80000000 >> irq);
+		else
+			siel &= ~(0x80000000 >> (irq & ~1));
+		out_be32(&immap->im_siu_conf.sc_siel, siel);
+	}
+}
+
+static void post_free_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void napi_clear_rx_event(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, r_des_active, 0x01000000);
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, x_des_active, 0x01000000);
+}
+
+static u32 get_int_events(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	return FR(fecp, ievent) & FR(fecp, imask);
+}
+
+static void clear_int_events(struct net_device *dev, u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fec_t *fecp = fep->fec.fecp;
+
+	FW(fecp, ievent, int_events);
+}
+
+static void ev_error(struct net_device *dev, u32 int_events)
+{
+	printk(KERN_WARNING DRV_MODULE_NAME
+	       ": %s FEC ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (*sizep < sizeof(fec_t))
+		return -EINVAL;
+
+	memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t));
+
+	return 0;
+}
+
+int get_regs_len(struct net_device *dev)
+{
+	return sizeof(fec_t);
+}
+
+void tx_restart(struct net_device *dev)
+{
+	/* nothing */
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_fec_ops = {
+	.setup_data		= setup_data,
+	.cleanup_data		= cleanup_data,
+	.set_multicast_list	= set_multicast_list,
+	.restart		= restart,
+	.stop			= stop,
+	.pre_request_irq	= pre_request_irq,
+	.post_free_irq		= post_free_irq,
+	.napi_clear_rx_event	= napi_clear_rx_event,
+	.napi_enable_rx		= napi_enable_rx,
+	.napi_disable_rx	= napi_disable_rx,
+	.rx_bd_done		= rx_bd_done,
+	.tx_kickstart		= tx_kickstart,
+	.get_int_events		= get_int_events,
+	.clear_int_events	= clear_int_events,
+	.ev_error		= ev_error,
+	.get_regs		= get_regs,
+	.get_regs_len		= get_regs_len,
+	.tx_restart		= tx_restart,
+	.allocate_bd		= allocate_bd,
+	.free_bd		= free_bd,
+};
+
+/***********************************************************************/
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+	fec_t *fecp = bus->fec.fecp;
+	int i, ret = -1;
+
+	if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+		BUG();
+
+	/* Add PHY address to register command.  */
+	FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
+
+	for (i = 0; i < FEC_MII_LOOPS; i++)
+		if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+			break;
+
+	if (i < FEC_MII_LOOPS) {
+		FW(fecp, ievent, FEC_ENET_MII);
+		ret = FR(fecp, mii_data) & 0xffff;
+	}
+
+	return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
+{
+	fec_t *fecp = bus->fec.fecp;
+	int i;
+
+	/* this must never happen */
+	if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+		BUG();
+
+	/* Add PHY address to register command.  */
+	FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
+
+	for (i = 0; i < FEC_MII_LOOPS; i++)
+		if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
+			break;
+
+	if (i < FEC_MII_LOOPS)
+		FW(fecp, ievent, FEC_ENET_MII);
+}
+
+int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
+{
+	bd_t *bd = (bd_t *)__res;
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+	fec_t *fecp;
+
+	if (bi->id != 0)
+		return -1;
+
+	bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
+	bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
+				& 0x3F) << 1;
+
+	fecp = bus->fec.fecp;
+
+	FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+	FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+	FW(fecp, ievent, FEC_ENET_MII);
+	FW(fecp, mii_speed, bus->fec.mii_speed);
+
+	bus->mii_read = mii_read;
+	bus->mii_write = mii_write;
+
+	return 0;
+}
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
new file mode 100644
index 0000000..d8c6e9c
--- /dev/null
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -0,0 +1,524 @@
+/*
+ * Ethernet on Serial Communications Controller (SCC) driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ * 
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_8xx
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+#endif
+
+#include "fs_enet.h"
+
+/*************************************************/
+
+#if defined(CONFIG_CPM1)
+/* for a 8xx __raw_xxx's are sufficient */
+#define __fs_out32(addr, x)	__raw_writel(x, addr)
+#define __fs_out16(addr, x)	__raw_writew(x, addr)
+#define __fs_out8(addr, x)	__raw_writeb(x, addr)
+#define __fs_in32(addr)	__raw_readl(addr)
+#define __fs_in16(addr)	__raw_readw(addr)
+#define __fs_in8(addr)	__raw_readb(addr)
+#else
+/* for others play it safe */
+#define __fs_out32(addr, x)	out_be32(addr, x)
+#define __fs_out16(addr, x)	out_be16(addr, x)
+#define __fs_in32(addr)	in_be32(addr)
+#define __fs_in16(addr)	in_be16(addr)
+#endif
+
+/* write, read, set bits, clear bits */
+#define W32(_p, _m, _v) __fs_out32(&(_p)->_m, (_v))
+#define R32(_p, _m)     __fs_in32(&(_p)->_m)
+#define S32(_p, _m, _v) W32(_p, _m, R32(_p, _m) | (_v))
+#define C32(_p, _m, _v) W32(_p, _m, R32(_p, _m) & ~(_v))
+
+#define W16(_p, _m, _v) __fs_out16(&(_p)->_m, (_v))
+#define R16(_p, _m)     __fs_in16(&(_p)->_m)
+#define S16(_p, _m, _v) W16(_p, _m, R16(_p, _m) | (_v))
+#define C16(_p, _m, _v) W16(_p, _m, R16(_p, _m) & ~(_v))
+
+#define W8(_p, _m, _v)  __fs_out8(&(_p)->_m, (_v))
+#define R8(_p, _m)      __fs_in8(&(_p)->_m)
+#define S8(_p, _m, _v)  W8(_p, _m, R8(_p, _m) | (_v))
+#define C8(_p, _m, _v)  W8(_p, _m, R8(_p, _m) & ~(_v))
+
+#define SCC_MAX_MULTICAST_ADDRS	64
+
+/*
+ * Delay to wait for SCC reset command to complete (in us) 
+ */
+#define SCC_RESET_DELAY		50
+#define MAX_CR_CMD_LOOPS	10000
+
+static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
+{
+	cpm8xx_t *cpmp = &((immap_t *)fs_enet_immap)->im_cpm;
+	u32 v, ch;
+	int i = 0;
+
+	ch = fep->scc.idx << 2;
+	v = mk_cr_cmd(ch, op);
+	W16(cpmp, cp_cpcr, v | CPM_CR_FLG);
+	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+		if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
+			break;
+
+	if (i >= MAX_CR_CMD_LOOPS) {
+		printk(KERN_ERR "%s(): Not able to issue CPM command\n",
+			__FUNCTION__);
+		return 1;
+	}
+	return 0;
+}
+
+static int do_pd_setup(struct fs_enet_private *fep)
+{
+	struct platform_device *pdev = to_platform_device(fep->dev);
+	struct resource *r;
+
+	/* Fill out IRQ field */
+	fep->interrupt = platform_get_irq_byname(pdev, "interrupt");
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+	fep->scc.sccp = (void *)r->start;
+
+	if (fep->scc.sccp == NULL)
+		return -EINVAL;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
+	fep->scc.ep = (void *)r->start;
+
+	if (fep->scc.ep == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+#define SCC_NAPI_RX_EVENT_MSK	(SCCE_ENET_RXF | SCCE_ENET_RXB)
+#define SCC_RX_EVENT		(SCCE_ENET_RXF)
+#define SCC_TX_EVENT		(SCCE_ENET_TXB)
+#define SCC_ERR_EVENT_MSK	(SCCE_ENET_TXE | SCCE_ENET_BSY)
+
+static int setup_data(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	fep->scc.idx = fs_get_scc_index(fpi->fs_no);
+	if ((unsigned int)fep->fcc.idx > 4)	/* max 4 SCCs */
+		return -EINVAL;
+
+	do_pd_setup(fep);
+
+	fep->scc.hthi = 0;
+	fep->scc.htlo = 0;
+
+	fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK;
+	fep->ev_rx = SCC_RX_EVENT;
+	fep->ev_tx = SCC_TX_EVENT;
+	fep->ev_err = SCC_ERR_EVENT_MSK;
+
+	return 0;
+}
+
+static int allocate_bd(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
+
+	fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) *
+					 sizeof(cbd_t), 8);
+	if (IS_DPERR(fep->ring_mem_addr))
+		return -ENOMEM;
+
+	fep->ring_base = cpm_dpram_addr(fep->ring_mem_addr);
+
+	return 0;
+}
+
+static void free_bd(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (fep->ring_base)
+		cpm_dpfree(fep->ring_mem_addr);
+}
+
+static void cleanup_data(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void set_promiscuous_mode(struct net_device *dev)
+{				
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+
+	S16(sccp, scc_psmr, SCC_PSMR_PRO);
+}
+
+static void set_multicast_start(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_enet_t *ep = fep->scc.ep;
+
+	W16(ep, sen_gaddr1, 0);
+	W16(ep, sen_gaddr2, 0);
+	W16(ep, sen_gaddr3, 0);
+	W16(ep, sen_gaddr4, 0);
+}
+
+static void set_multicast_one(struct net_device *dev, const u8 * mac)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_enet_t *ep = fep->scc.ep;
+	u16 taddrh, taddrm, taddrl;
+
+	taddrh = ((u16) mac[5] << 8) | mac[4];
+	taddrm = ((u16) mac[3] << 8) | mac[2];
+	taddrl = ((u16) mac[1] << 8) | mac[0];
+
+	W16(ep, sen_taddrh, taddrh);
+	W16(ep, sen_taddrm, taddrm);
+	W16(ep, sen_taddrl, taddrl);
+	scc_cr_cmd(fep, CPM_CR_SET_GADDR);
+}
+
+static void set_multicast_finish(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+	scc_enet_t *ep = fep->scc.ep;
+
+	/* clear promiscuous always */
+	C16(sccp, scc_psmr, SCC_PSMR_PRO);
+
+	/* if all multi or too many multicasts; just enable all */
+	if ((dev->flags & IFF_ALLMULTI) != 0 ||
+	    dev->mc_count > SCC_MAX_MULTICAST_ADDRS) {
+
+		W16(ep, sen_gaddr1, 0xffff);
+		W16(ep, sen_gaddr2, 0xffff);
+		W16(ep, sen_gaddr3, 0xffff);
+		W16(ep, sen_gaddr4, 0xffff);
+	}
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct dev_mc_list *pmc;
+
+	if ((dev->flags & IFF_PROMISC) == 0) {
+		set_multicast_start(dev);
+		for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next)
+			set_multicast_one(dev, pmc->dmi_addr);
+		set_multicast_finish(dev);
+	} else
+		set_promiscuous_mode(dev);
+}
+
+/*
+ * This function is called to start or restart the FEC during a link
+ * change.  This only happens when switching between half and full
+ * duplex.
+ */
+static void restart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+	scc_enet_t *ep = fep->scc.ep;
+	const struct fs_platform_info *fpi = fep->fpi;
+	u16 paddrh, paddrm, paddrl;
+	const unsigned char *mac;
+	int i;
+
+	C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* clear everything (slow & steady does it) */
+	for (i = 0; i < sizeof(*ep); i++)
+		__fs_out8((char *)ep + i, 0);
+
+	/* point to bds */
+	W16(ep, sen_genscc.scc_rbase, fep->ring_mem_addr);
+	W16(ep, sen_genscc.scc_tbase,
+	    fep->ring_mem_addr + sizeof(cbd_t) * fpi->rx_ring);
+
+	/* Initialize function code registers for big-endian.
+	 */
+	W8(ep, sen_genscc.scc_rfcr, SCC_EB);
+	W8(ep, sen_genscc.scc_tfcr, SCC_EB);
+
+	/* Set maximum bytes per receive buffer.
+	 * This appears to be an Ethernet frame size, not the buffer
+	 * fragment size.  It must be a multiple of four.
+	 */
+	W16(ep, sen_genscc.scc_mrblr, 0x5f0);
+
+	/* Set CRC preset and mask.
+	 */
+	W32(ep, sen_cpres, 0xffffffff);
+	W32(ep, sen_cmask, 0xdebb20e3);
+
+	W32(ep, sen_crcec, 0);	/* CRC Error counter */
+	W32(ep, sen_alec, 0);	/* alignment error counter */
+	W32(ep, sen_disfc, 0);	/* discard frame counter */
+
+	W16(ep, sen_pads, 0x8888);	/* Tx short frame pad character */
+	W16(ep, sen_retlim, 15);	/* Retry limit threshold */
+
+	W16(ep, sen_maxflr, 0x5ee);	/* maximum frame length register */
+
+	W16(ep, sen_minflr, PKT_MINBUF_SIZE);	/* minimum frame length register */
+
+	W16(ep, sen_maxd1, 0x000005f0);	/* maximum DMA1 length */
+	W16(ep, sen_maxd2, 0x000005f0);	/* maximum DMA2 length */
+
+	/* Clear hash tables.
+	 */
+	W16(ep, sen_gaddr1, 0);
+	W16(ep, sen_gaddr2, 0);
+	W16(ep, sen_gaddr3, 0);
+	W16(ep, sen_gaddr4, 0);
+	W16(ep, sen_iaddr1, 0);
+	W16(ep, sen_iaddr2, 0);
+	W16(ep, sen_iaddr3, 0);
+	W16(ep, sen_iaddr4, 0);
+
+	/* set address 
+	 */
+	mac = dev->dev_addr;
+	paddrh = ((u16) mac[5] << 8) | mac[4];
+	paddrm = ((u16) mac[3] << 8) | mac[2];
+	paddrl = ((u16) mac[1] << 8) | mac[0];
+
+	W16(ep, sen_paddrh, paddrh);
+	W16(ep, sen_paddrm, paddrm);
+	W16(ep, sen_paddrl, paddrl);
+
+	W16(ep, sen_pper, 0);
+	W16(ep, sen_taddrl, 0);
+	W16(ep, sen_taddrm, 0);
+	W16(ep, sen_taddrh, 0);
+
+	fs_init_bds(dev);
+
+	scc_cr_cmd(fep, CPM_CR_INIT_TRX);
+
+	W16(sccp, scc_scce, 0xffff);
+
+	/* Enable interrupts we wish to service. 
+	 */
+	W16(sccp, scc_sccm, SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+	/* Set GSMR_H to enable all normal operating modes.
+	 * Set GSMR_L to enable Ethernet to MC68160.
+	 */
+	W32(sccp, scc_gsmrh, 0);
+	W32(sccp, scc_gsmrl,
+	    SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 |
+	    SCC_GSMRL_MODE_ENET);
+
+	/* Set sync/delimiters.
+	 */
+	W16(sccp, scc_dsr, 0xd555);
+
+	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
+	 * start frame search 22 bit times after RENA.
+	 */
+	W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
+
+	/* Set full duplex mode if needed */
+	if (fep->duplex)
+		S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
+
+	S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+
+static void stop(struct net_device *dev)	
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+	int i;
+
+	for (i = 0; (R16(sccp, scc_sccm) == 0) && i < SCC_RESET_DELAY; i++)
+		udelay(1);
+
+	if (i == SCC_RESET_DELAY)
+		printk(KERN_WARNING DRV_MODULE_NAME
+		       ": %s SCC timeout on graceful transmit stop\n",
+		       dev->name);
+
+	W16(sccp, scc_sccm, 0);
+	C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	fs_cleanup_bds(dev);
+}
+
+static void pre_request_irq(struct net_device *dev, int irq)
+{
+	immap_t *immap = fs_enet_immap;
+	u32 siel;
+
+	/* SIU interrupt */
+	if (irq >= SIU_IRQ0 && irq < SIU_LEVEL7) {
+
+		siel = in_be32(&immap->im_siu_conf.sc_siel);
+		if ((irq & 1) == 0)
+			siel |= (0x80000000 >> irq);
+		else
+			siel &= ~(0x80000000 >> (irq & ~1));
+		out_be32(&immap->im_siu_conf.sc_siel, siel);
+	}
+}
+
+static void post_free_irq(struct net_device *dev, int irq)
+{
+	/* nothing */
+}
+
+static void napi_clear_rx_event(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+
+	W16(sccp, scc_scce, SCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_enable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+
+	S16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
+}
+
+static void napi_disable_rx(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+
+	C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK);
+}
+
+static void rx_bd_done(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static void tx_kickstart(struct net_device *dev)
+{
+	/* nothing */
+}
+
+static u32 get_int_events(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+
+	return (u32) R16(sccp, scc_scce);
+}
+
+static void clear_int_events(struct net_device *dev, u32 int_events)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	scc_t *sccp = fep->scc.sccp;
+
+	W16(sccp, scc_scce, int_events & 0xffff);
+}
+
+static void ev_error(struct net_device *dev, u32 int_events)
+{
+	printk(KERN_WARNING DRV_MODULE_NAME
+	       ": %s SCC ERROR(s) 0x%x\n", dev->name, int_events);
+}
+
+static int get_regs(struct net_device *dev, void *p, int *sizep)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	if (*sizep < sizeof(scc_t) + sizeof(scc_enet_t))
+		return -EINVAL;
+
+	memcpy_fromio(p, fep->scc.sccp, sizeof(scc_t));
+	p = (char *)p + sizeof(scc_t);
+
+	memcpy_fromio(p, fep->scc.ep, sizeof(scc_enet_t));
+
+	return 0;
+}
+
+static int get_regs_len(struct net_device *dev)
+{
+	return sizeof(scc_t) + sizeof(scc_enet_t);
+}
+
+static void tx_restart(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	scc_cr_cmd(fep, CPM_CR_RESTART_TX);
+}
+
+/*************************************************************************/
+
+const struct fs_ops fs_scc_ops = {
+	.setup_data		= setup_data,
+	.cleanup_data		= cleanup_data,
+	.set_multicast_list	= set_multicast_list,
+	.restart		= restart,
+	.stop			= stop,
+	.pre_request_irq	= pre_request_irq,
+	.post_free_irq		= post_free_irq,
+	.napi_clear_rx_event	= napi_clear_rx_event,
+	.napi_enable_rx		= napi_enable_rx,
+	.napi_disable_rx	= napi_disable_rx,
+	.rx_bd_done		= rx_bd_done,
+	.tx_kickstart		= tx_kickstart,
+	.get_int_events		= get_int_events,
+	.clear_int_events	= clear_int_events,
+	.ev_error		= ev_error,
+	.get_regs		= get_regs,
+	.get_regs_len		= get_regs_len,
+	.tx_restart		= tx_restart,
+	.allocate_bd		= allocate_bd,
+	.free_bd		= free_bd,
+};
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
new file mode 100644
index 0000000..24a5e2e
--- /dev/null
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -0,0 +1,405 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ * 
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+#ifdef CONFIG_8xx
+static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+{
+	immap_t *im = (immap_t *)fs_enet_immap;
+	void *dir, *dat, *ppar;
+	int adv;
+	u8 msk;
+
+	switch (port) {
+		case fsiop_porta:
+			dir = &im->im_ioport.iop_padir;
+			dat = &im->im_ioport.iop_padat;
+			ppar = &im->im_ioport.iop_papar;
+			break;
+
+		case fsiop_portb:
+			dir = &im->im_cpm.cp_pbdir;
+			dat = &im->im_cpm.cp_pbdat;
+			ppar = &im->im_cpm.cp_pbpar;
+			break;
+
+		case fsiop_portc:
+			dir = &im->im_ioport.iop_pcdir;
+			dat = &im->im_ioport.iop_pcdat;
+			ppar = &im->im_ioport.iop_pcpar;
+			break;
+
+		case fsiop_portd:
+			dir = &im->im_ioport.iop_pddir;
+			dat = &im->im_ioport.iop_pddat;
+			ppar = &im->im_ioport.iop_pdpar;
+			break;
+
+		case fsiop_porte:
+			dir = &im->im_cpm.cp_pedir;
+			dat = &im->im_cpm.cp_pedat;
+			ppar = &im->im_cpm.cp_pepar;
+			break;
+
+		default:
+			printk(KERN_ERR DRV_MODULE_NAME
+			       "Illegal port value %d!\n", port);
+			return -EINVAL;
+	}
+
+	adv = bit >> 3;
+	dir = (char *)dir + adv;
+	dat = (char *)dat + adv;
+	ppar = (char *)ppar + adv;
+
+	msk = 1 << (7 - (bit & 7));
+	if ((in_8(ppar) & msk) != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       "pin %d on port %d is not general purpose!\n", bit, port);
+		return -EINVAL;
+	}
+
+	*dirp = dir;
+	*datp = dat;
+	*mskp = msk;
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_8260
+static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+{
+	iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
+	void *dir, *dat, *ppar;
+	int adv;
+	u8 msk;
+
+	switch (port) {
+		case fsiop_porta:
+			dir = &io->iop_pdira;
+			dat = &io->iop_pdata;
+			ppar = &io->iop_ppara;
+			break;
+
+		case fsiop_portb:
+			dir = &io->iop_pdirb;
+			dat = &io->iop_pdatb;
+			ppar = &io->iop_pparb;
+			break;
+
+		case fsiop_portc:
+			dir = &io->iop_pdirc;
+			dat = &io->iop_pdatc;
+			ppar = &io->iop_pparc;
+			break;
+
+		case fsiop_portd:
+			dir = &io->iop_pdird;
+			dat = &io->iop_pdatd;
+			ppar = &io->iop_ppard;
+			break;
+
+		default:
+			printk(KERN_ERR DRV_MODULE_NAME
+			       "Illegal port value %d!\n", port);
+			return -EINVAL;
+	}
+
+	adv = bit >> 3;
+	dir = (char *)dir + adv;
+	dat = (char *)dat + adv;
+	ppar = (char *)ppar + adv;
+
+	msk = 1 << (7 - (bit & 7));
+	if ((in_8(ppar) & msk) != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+		       "pin %d on port %d is not general purpose!\n", bit, port);
+		return -EINVAL;
+	}
+
+	*dirp = dir;
+	*datp = dat;
+	*mskp = msk;
+
+	return 0;
+}
+#endif
+
+static inline void bb_set(u8 *p, u8 m)
+{
+	out_8(p, in_8(p) | m);
+}
+
+static inline void bb_clr(u8 *p, u8 m)
+{
+	out_8(p, in_8(p) & ~m);
+}
+
+static inline int bb_read(u8 *p, u8 m)
+{
+	return (in_8(p) & m) != 0;
+}
+
+static inline void mdio_active(struct fs_enet_mii_bus *bus)
+{
+	bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+}
+
+static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
+{
+	bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+}
+
+static inline int mdio_read(struct fs_enet_mii_bus *bus)
+{
+	return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+}
+
+static inline void mdio(struct fs_enet_mii_bus *bus, int what)
+{
+	if (what)
+		bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+	else
+		bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+}
+
+static inline void mdc(struct fs_enet_mii_bus *bus, int what)
+{
+	if (what)
+		bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+	else
+		bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+}
+
+static inline void mii_delay(struct fs_enet_mii_bus *bus)
+{
+	udelay(bus->bus_info->i.bitbang.delay);
+}
+
+/* Utility to send the preamble, address, and register (common to read and write). */
+static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
+{
+	int j;
+
+	/*
+	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
+	 * The IEEE spec says this is a PHY optional requirement.  The AMD
+	 * 79C874 requires one after power up and one after a MII communications
+	 * error.  This means that we are doing more preambles than we need,
+	 * but it is safer and will be much more robust.
+	 */
+
+	mdio_active(bus);
+	mdio(bus, 1);
+	for (j = 0; j < 32; j++) {
+		mdc(bus, 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+	}
+
+	/* send the start bit (01) and the read opcode (10) or write (10) */
+	mdc(bus, 0);
+	mdio(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, read);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, !read);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	/* send the PHY address */
+	for (j = 0; j < 5; j++) {
+		mdc(bus, 0);
+		mdio(bus, (addr & 0x10) != 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+		addr <<= 1;
+	}
+
+	/* send the register address */
+	for (j = 0; j < 5; j++) {
+		mdc(bus, 0);
+		mdio(bus, (reg & 0x10) != 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+		reg <<= 1;
+	}
+}
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+	u16 rdreg;
+	int ret, j;
+	u8 addr = phy_id & 0xff;
+	u8 reg = location & 0xff;
+
+	bitbang_pre(bus, 1, addr, reg);
+
+	/* tri-state our MDIO I/O pin so we can read */
+	mdc(bus, 0);
+	mdio_tristate(bus);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	/* check the turnaround bit: the PHY should be driving it to zero */
+	if (mdio_read(bus) != 0) {
+		/* PHY didn't drive TA low */
+		for (j = 0; j < 32; j++) {
+			mdc(bus, 0);
+			mii_delay(bus);
+			mdc(bus, 1);
+			mii_delay(bus);
+		}
+		ret = -1;
+		goto out;
+	}
+
+	mdc(bus, 0);
+	mii_delay(bus);
+
+	/* read 16 bits of register data, MSB first */
+	rdreg = 0;
+	for (j = 0; j < 16; j++) {
+		mdc(bus, 1);
+		mii_delay(bus);
+		rdreg <<= 1;
+		rdreg |= mdio_read(bus);
+		mdc(bus, 0);
+		mii_delay(bus);
+	}
+
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	ret = rdreg;
+out:
+	return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+{
+	int j;
+	u8 addr = phy_id & 0xff;
+	u8 reg = location & 0xff;
+	u16 value = val & 0xffff;
+
+	bitbang_pre(bus, 0, addr, reg);
+
+	/* send the turnaround (10) */
+	mdc(bus, 0);
+	mdio(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+	mdc(bus, 0);
+	mdio(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+
+	/* write 16 bits of register data, MSB first */
+	for (j = 0; j < 16; j++) {
+		mdc(bus, 0);
+		mdio(bus, (value & 0x8000) != 0);
+		mii_delay(bus);
+		mdc(bus, 1);
+		mii_delay(bus);
+		value <<= 1;
+	}
+
+	/*
+	 * Tri-state the MDIO line.
+	 */
+	mdio_tristate(bus);
+	mdc(bus, 0);
+	mii_delay(bus);
+	mdc(bus, 1);
+	mii_delay(bus);
+}
+
+int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
+{
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+	int r;
+
+	r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
+			 &bus->bitbang.mdio_dat,
+			 &bus->bitbang.mdio_msk,
+			 bi->i.bitbang.mdio_port,
+			 bi->i.bitbang.mdio_bit);
+	if (r != 0)
+		return r;
+
+	r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
+			 &bus->bitbang.mdc_dat,
+			 &bus->bitbang.mdc_msk,
+			 bi->i.bitbang.mdc_port,
+			 bi->i.bitbang.mdc_bit);
+	if (r != 0)
+		return r;
+
+	bus->mii_read = mii_read;
+	bus->mii_write = mii_write;
+
+	return 0;
+}
diff --git a/drivers/net/fs_enet/mii-fixed.c b/drivers/net/fs_enet/mii-fixed.c
new file mode 100644
index 0000000..b3e192d
--- /dev/null
+++ b/drivers/net/fs_enet/mii-fixed.c
@@ -0,0 +1,92 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ * 
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+
+static const u16 mii_regs[7] = {
+	0x3100,
+	0x786d,
+	0x0fff,
+	0x0fff,
+	0x01e1,
+	0x45e1,
+	0x0003,
+};
+
+static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+{
+	int ret = 0;
+
+	if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
+		return -1;
+
+	if (location != 5)
+		ret = mii_regs[location];
+	else
+		ret = bus->fixed.lpa;
+
+	return ret;
+}
+
+static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+{
+	/* do nothing */
+}
+
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
+{
+	const struct fs_mii_bus_info *bi = bus->bus_info;
+
+	bus->fixed.lpa = 0x45e1;	/* default 100Mb, full duplex */
+
+	/* if speed is fixed at 10Mb, remove 100Mb modes */
+	if (bi->i.fixed.speed == 10)
+		bus->fixed.lpa &= ~LPA_100;
+
+	/* if duplex is half, remove full duplex modes */
+	if (bi->i.fixed.duplex == 0)
+		bus->fixed.lpa &= ~LPA_DUPLEX;
+
+	bus->mii_read = mii_read;
+	bus->mii_write = mii_write;
+
+	return 0;
+}
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 6518334..ae5a2ed 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -29,12 +29,7 @@
  *  define the configuration needed by the board are defined in a
  *  board structure in arch/ppc/platforms (though I do not
  *  discount the possibility that other architectures could one
- *  day be supported.  One assumption the driver currently makes
- *  is that the PHY is configured in such a way to advertise all
- *  capabilities.  This is a sensible default, and on certain
- *  PHYs, changing this default encounters substantial errata
- *  issues.  Future versions may remove this requirement, but for
- *  now, it is best for the firmware to ensure this is the case.
+ *  day be supported.
  *
  *  The Gianfar Ethernet Controller uses a ring of buffer
  *  descriptors.  The beginning is indicated by a register
@@ -47,7 +42,7 @@
  *  corresponding bit in the IMASK register is also set (if
  *  interrupt coalescing is active, then the interrupt may not
  *  happen immediately, but will wait until either a set number
- *  of frames or amount of time have passed.).  In NAPI, the
+ *  of frames or amount of time have passed).  In NAPI, the
  *  interrupt handler will signal there is work to be done, and
  *  exit.  Without NAPI, the packet(s) will be handled
  *  immediately.  Both methods will start at the last known empty
@@ -75,6 +70,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -97,9 +93,11 @@
 #include <linux/version.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include "gianfar.h"
-#include "gianfar_phy.h"
+#include "gianfar_mii.h"
 
 #define TX_TIMEOUT      (1*HZ)
 #define SKB_ALLOC_TIMEOUT 1000000
@@ -113,9 +111,8 @@
 #endif
 
 const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.1";
+const char gfar_driver_version[] = "1.2";
 
-int startup_gfar(struct net_device *dev);
 static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void gfar_timeout(struct net_device *dev);
@@ -126,17 +123,13 @@
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void gfar_phy_change(void *data);
-static void gfar_phy_timer(unsigned long data);
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct device *device);
 static int gfar_remove(struct device *device);
-void free_skb_resources(struct gfar_private *priv);
+static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
 #ifdef CONFIG_GFAR_NAPI
@@ -144,7 +137,6 @@
 #endif
 int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
-static void gfar_phy_startup_timer(unsigned long data);
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
 static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
@@ -162,6 +154,9 @@
 	else
 		return 0;
 }
+
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start */
 static int gfar_probe(struct device *device)
 {
 	u32 tempval;
@@ -175,7 +170,7 @@
 
 	einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
 
-	if (einfo == NULL) {
+	if (NULL == einfo) {
 		printk(KERN_ERR "gfar %d: Missing additional data!\n",
 		       pdev->id);
 
@@ -185,7 +180,7 @@
 	/* Create an ethernet device instance */
 	dev = alloc_etherdev(sizeof (*priv));
 
-	if (dev == NULL)
+	if (NULL == dev)
 		return -ENOMEM;
 
 	priv = netdev_priv(dev);
@@ -207,20 +202,11 @@
 	priv->regs = (struct gfar *)
 		ioremap(r->start, sizeof (struct gfar));
 
-	if (priv->regs == NULL) {
+	if (NULL == priv->regs) {
 		err = -ENOMEM;
 		goto regs_fail;
 	}
 
-	/* Set the PHY base address */
-	priv->phyregs = (struct gfar *)
-	    ioremap(einfo->phy_reg_addr, sizeof (struct gfar));
-
-	if (priv->phyregs == NULL) {
-		err = -ENOMEM;
-		goto phy_regs_fail;
-	}
-
 	spin_lock_init(&priv->lock);
 
 	dev_set_drvdata(device, dev);
@@ -386,12 +372,10 @@
 	return 0;
 
 register_fail:
-	iounmap((void *) priv->phyregs);
-phy_regs_fail:
 	iounmap((void *) priv->regs);
 regs_fail:
 	free_netdev(dev);
-	return -ENOMEM;
+	return err;
 }
 
 static int gfar_remove(struct device *device)
@@ -402,108 +386,41 @@
 	dev_set_drvdata(device, NULL);
 
 	iounmap((void *) priv->regs);
-	iounmap((void *) priv->phyregs);
 	free_netdev(dev);
 
 	return 0;
 }
 
 
-/* Configure the PHY for dev.
- * returns 0 if success.  -1 if failure
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
  */
 static int init_phy(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct phy_info *curphy;
-	unsigned int timeout = PHY_INIT_TIMEOUT;
-	struct gfar *phyregs = priv->phyregs;
-	struct gfar_mii_info *mii_info;
-	int err;
+	uint gigabit_support =
+		priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+		SUPPORTED_1000baseT_Full : 0;
+	struct phy_device *phydev;
 
 	priv->oldlink = 0;
 	priv->oldspeed = 0;
 	priv->oldduplex = -1;
 
-	mii_info = kmalloc(sizeof(struct gfar_mii_info),
-			GFP_KERNEL);
+	phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
 
-	if(NULL == mii_info) {
-		if (netif_msg_ifup(priv))
-			printk(KERN_ERR "%s: Could not allocate mii_info\n",
-					dev->name);
-		return -ENOMEM;
+	if (IS_ERR(phydev)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
 	}
 
-	mii_info->speed = SPEED_1000;
-	mii_info->duplex = DUPLEX_FULL;
-	mii_info->pause = 0;
-	mii_info->link = 1;
+	/* Remove any features not supported by the controller */
+	phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+	phydev->advertising = phydev->supported;
 
-	mii_info->advertising = (ADVERTISED_10baseT_Half |
-			ADVERTISED_10baseT_Full |
-			ADVERTISED_100baseT_Half |
-			ADVERTISED_100baseT_Full |
-			ADVERTISED_1000baseT_Full);
-	mii_info->autoneg = 1;
-
-	spin_lock_init(&mii_info->mdio_lock);
-
-	mii_info->mii_id = priv->einfo->phyid;
-
-	mii_info->dev = dev;
-
-	mii_info->mdio_read = &read_phy_reg;
-	mii_info->mdio_write = &write_phy_reg;
-
-	priv->mii_info = mii_info;
-
-	/* Reset the management interface */
-	gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
-
-	/* Setup the MII Mgmt clock speed */
-	gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
-	/* Wait until the bus is free */
-	while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
-			timeout--)
-		cpu_relax();
-
-	if(timeout <= 0) {
-		printk(KERN_ERR "%s: The MII Bus is stuck!\n",
-				dev->name);
-		err = -1;
-		goto bus_fail;
-	}
-
-	/* get info for this PHY */
-	curphy = get_phy_info(priv->mii_info);
-
-	if (curphy == NULL) {
-		if (netif_msg_ifup(priv))
-			printk(KERN_ERR "%s: No PHY found\n", dev->name);
-		err = -1;
-		goto no_phy;
-	}
-
-	mii_info->phyinfo = curphy;
-
-	/* Run the commands which initialize the PHY */
-	if(curphy->init) {
-		err = curphy->init(priv->mii_info);
-
-		if (err)
-			goto phy_init_fail;
-	}
+	priv->phydev = phydev;
 
 	return 0;
-
-phy_init_fail:
-no_phy:
-bus_fail:
-	kfree(mii_info);
-
-	return err;
 }
 
 static void init_registers(struct net_device *dev)
@@ -603,24 +520,13 @@
 	struct gfar *regs = priv->regs;
 	unsigned long flags;
 
+	phy_stop(priv->phydev);
+
 	/* Lock it down */
 	spin_lock_irqsave(&priv->lock, flags);
 
-	/* Tell the kernel the link is down */
-	priv->mii_info->link = 0;
-	adjust_link(dev);
-
 	gfar_halt(dev);
 
-	if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
-		/* Clear any pending interrupts */
-		mii_clear_phy_interrupt(priv->mii_info);
-
-		/* Disable PHY Interrupts */
-		mii_configure_phy_interrupt(priv->mii_info,
-				MII_INTERRUPT_DISABLED);
-	}
-
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Free the IRQs */
@@ -629,13 +535,7 @@
 		free_irq(priv->interruptTransmit, dev);
 		free_irq(priv->interruptReceive, dev);
 	} else {
-		free_irq(priv->interruptTransmit, dev);
-	}
-
-	if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
-		free_irq(priv->einfo->interruptPHY, dev);
-	} else {
-		del_timer_sync(&priv->phy_info_timer);
+ 		free_irq(priv->interruptTransmit, dev);
 	}
 
 	free_skb_resources(priv);
@@ -649,7 +549,7 @@
 
 /* If there are any tx skbs or rx skbs still around, free them.
  * Then free tx_skbuff and rx_skbuff */
-void free_skb_resources(struct gfar_private *priv)
+static void free_skb_resources(struct gfar_private *priv)
 {
 	struct rxbd8 *rxbdp;
 	struct txbd8 *txbdp;
@@ -770,7 +670,7 @@
 	    (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
 					priv->tx_ring_size, GFP_KERNEL);
 
-	if (priv->tx_skbuff == NULL) {
+	if (NULL == priv->tx_skbuff) {
 		if (netif_msg_ifup(priv))
 			printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
 					dev->name);
@@ -785,7 +685,7 @@
 	    (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
 					priv->rx_ring_size, GFP_KERNEL);
 
-	if (priv->rx_skbuff == NULL) {
+	if (NULL == priv->rx_skbuff) {
 		if (netif_msg_ifup(priv))
 			printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
 					dev->name);
@@ -879,13 +779,7 @@
 		}
 	}
 
-	/* Set up the PHY change work queue */
-	INIT_WORK(&priv->tq, gfar_phy_change, dev);
-
-	init_timer(&priv->phy_info_timer);
-	priv->phy_info_timer.function = &gfar_phy_startup_timer;
-	priv->phy_info_timer.data = (unsigned long) priv->mii_info;
-	mod_timer(&priv->phy_info_timer, jiffies + HZ);
+	phy_start(priv->phydev);
 
 	/* Configure the coalescing support */
 	if (priv->txcoalescing)
@@ -933,11 +827,6 @@
 			priv->tx_bd_base,
 			gfar_read(&regs->tbase0));
 
-	if (priv->mii_info->phyinfo->close)
-		priv->mii_info->phyinfo->close(priv->mii_info);
-
-	kfree(priv->mii_info);
-
 	return err;
 }
 
@@ -1035,7 +924,7 @@
 	txbdp->status &= TXBD_WRAP;
 
 	/* Set up checksumming */
-	if ((dev->features & NETIF_F_IP_CSUM) 
+	if ((dev->features & NETIF_F_IP_CSUM)
 			&& (CHECKSUM_HW == skb->ip_summed)) {
 		fcb = gfar_add_fcb(skb, txbdp);
 		gfar_tx_checksum(skb, fcb);
@@ -1103,11 +992,9 @@
 	struct gfar_private *priv = netdev_priv(dev);
 	stop_gfar(dev);
 
-	/* Shutdown the PHY */
-	if (priv->mii_info->phyinfo->close)
-		priv->mii_info->phyinfo->close(priv->mii_info);
-
-	kfree(priv->mii_info);
+	/* Disconnect from the PHY */
+	phy_disconnect(priv->phydev);
+	priv->phydev = NULL;
 
 	netif_stop_queue(dev);
 
@@ -1343,7 +1230,7 @@
 	while ((!skb) && timeout--)
 		skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
 
-	if (skb == NULL)
+	if (NULL == skb)
 		return NULL;
 
 	/* We need the data buffer to be aligned properly.  We will reserve
@@ -1490,7 +1377,7 @@
 	struct gfar_private *priv = netdev_priv(dev);
 	struct rxfcb *fcb = NULL;
 
-	if (skb == NULL) {
+	if (NULL == skb) {
 		if (netif_msg_rx_err(priv))
 			printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
 		priv->stats.rx_dropped++;
@@ -1718,131 +1605,9 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct gfar_private *priv = netdev_priv(dev);
-
-	/* Clear the interrupt */
-	mii_clear_phy_interrupt(priv->mii_info);
-
-	/* Disable PHY interrupts */
-	mii_configure_phy_interrupt(priv->mii_info,
-			MII_INTERRUPT_DISABLED);
-
-	/* Schedule the phy change */
-	schedule_work(&priv->tq);
-
-	return IRQ_HANDLED;
-}
-
-/* Scheduled by the phy_interrupt/timer to handle PHY changes */
-static void gfar_phy_change(void *data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	struct gfar_private *priv = netdev_priv(dev);
-	int result = 0;
-
-	/* Delay to give the PHY a chance to change the
-	 * register state */
-	msleep(1);
-
-	/* Update the link, speed, duplex */
-	result = priv->mii_info->phyinfo->read_status(priv->mii_info);
-
-	/* Adjust the known status as long as the link
-	 * isn't still coming up */
-	if((0 == result) || (priv->mii_info->link == 0))
-		adjust_link(dev);
-
-	/* Reenable interrupts, if needed */
-	if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR)
-		mii_configure_phy_interrupt(priv->mii_info,
-				MII_INTERRUPT_ENABLED);
-}
-
-/* Called every so often on systems that don't interrupt
- * the core for PHY changes */
-static void gfar_phy_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	struct gfar_private *priv = netdev_priv(dev);
-
-	schedule_work(&priv->tq);
-
-	mod_timer(&priv->phy_info_timer, jiffies +
-			GFAR_PHY_CHANGE_TIME * HZ);
-}
-
-/* Keep trying aneg for some time
- * If, after GFAR_AN_TIMEOUT seconds, it has not
- * finished, we switch to forced.
- * Either way, once the process has completed, we either
- * request the interrupt, or switch the timer over to
- * using gfar_phy_timer to check status */
-static void gfar_phy_startup_timer(unsigned long data)
-{
-	int result;
-	static int secondary = GFAR_AN_TIMEOUT;
-	struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
-	struct gfar_private *priv = netdev_priv(mii_info->dev);
-
-	/* Configure the Auto-negotiation */
-	result = mii_info->phyinfo->config_aneg(mii_info);
-
-	/* If autonegotiation failed to start, and
-	 * we haven't timed out, reset the timer, and return */
-	if (result && secondary--) {
-		mod_timer(&priv->phy_info_timer, jiffies + HZ);
-		return;
-	} else if (result) {
-		/* Couldn't start autonegotiation.
-		 * Try switching to forced */
-		mii_info->autoneg = 0;
-		result = mii_info->phyinfo->config_aneg(mii_info);
-
-		/* Forcing failed!  Give up */
-		if(result) {
-			if (netif_msg_link(priv))
-				printk(KERN_ERR "%s: Forcing failed!\n",
-						mii_info->dev->name);
-			return;
-		}
-	}
-
-	/* Kill the timer so it can be restarted */
-	del_timer_sync(&priv->phy_info_timer);
-
-	/* Grab the PHY interrupt, if necessary/possible */
-	if (priv->einfo->board_flags & FSL_GIANFAR_BRD_HAS_PHY_INTR) {
-		if (request_irq(priv->einfo->interruptPHY,
-					phy_interrupt,
-					SA_SHIRQ,
-					"phy_interrupt",
-					mii_info->dev) < 0) {
-			if (netif_msg_intr(priv))
-				printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
-						mii_info->dev->name,
-					priv->einfo->interruptPHY);
-		} else {
-			mii_configure_phy_interrupt(priv->mii_info,
-					MII_INTERRUPT_ENABLED);
-			return;
-		}
-	}
-
-	/* Start the timer again, this time in order to
-	 * handle a change in status */
-	init_timer(&priv->phy_info_timer);
-	priv->phy_info_timer.function = &gfar_phy_timer;
-	priv->phy_info_timer.data = (unsigned long) mii_info->dev;
-	mod_timer(&priv->phy_info_timer, jiffies +
-			GFAR_PHY_CHANGE_TIME * HZ);
-}
-
 /* Called every time the controller might need to be made
  * aware of new link state.  The PHY code conveys this
- * information through variables in the priv structure, and this
+ * information through variables in the phydev structure, and this
  * function converts those variables into the appropriate
  * register values, and can bring down the device if needed.
  */
@@ -1850,84 +1615,68 @@
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar *regs = priv->regs;
-	u32 tempval;
-	struct gfar_mii_info *mii_info = priv->mii_info;
+	unsigned long flags;
+	struct phy_device *phydev = priv->phydev;
+	int new_state = 0;
 
-	if (mii_info->link) {
+	spin_lock_irqsave(&priv->lock, flags);
+	if (phydev->link) {
+		u32 tempval = gfar_read(&regs->maccfg2);
+
 		/* Now we make sure that we can be in full duplex mode.
 		 * If not, we operate in half-duplex mode. */
-		if (mii_info->duplex != priv->oldduplex) {
-			if (!(mii_info->duplex)) {
-				tempval = gfar_read(&regs->maccfg2);
+		if (phydev->duplex != priv->oldduplex) {
+			new_state = 1;
+			if (!(phydev->duplex))
 				tempval &= ~(MACCFG2_FULL_DUPLEX);
-				gfar_write(&regs->maccfg2, tempval);
-
-				if (netif_msg_link(priv))
-					printk(KERN_INFO "%s: Half Duplex\n",
-							dev->name);
-			} else {
-				tempval = gfar_read(&regs->maccfg2);
+			else
 				tempval |= MACCFG2_FULL_DUPLEX;
-				gfar_write(&regs->maccfg2, tempval);
 
-				if (netif_msg_link(priv))
-					printk(KERN_INFO "%s: Full Duplex\n",
-							dev->name);
-			}
-
-			priv->oldduplex = mii_info->duplex;
+			priv->oldduplex = phydev->duplex;
 		}
 
-		if (mii_info->speed != priv->oldspeed) {
-			switch (mii_info->speed) {
+		if (phydev->speed != priv->oldspeed) {
+			new_state = 1;
+			switch (phydev->speed) {
 			case 1000:
-				tempval = gfar_read(&regs->maccfg2);
 				tempval =
 				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
-				gfar_write(&regs->maccfg2, tempval);
 				break;
 			case 100:
 			case 10:
-				tempval = gfar_read(&regs->maccfg2);
 				tempval =
 				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
-				gfar_write(&regs->maccfg2, tempval);
 				break;
 			default:
 				if (netif_msg_link(priv))
 					printk(KERN_WARNING
-							"%s: Ack!  Speed (%d) is not 10/100/1000!\n",
-							dev->name, mii_info->speed);
+						"%s: Ack!  Speed (%d) is not 10/100/1000!\n",
+						dev->name, phydev->speed);
 				break;
 			}
 
-			if (netif_msg_link(priv))
-				printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
-						mii_info->speed);
-
-			priv->oldspeed = mii_info->speed;
+			priv->oldspeed = phydev->speed;
 		}
 
+		gfar_write(&regs->maccfg2, tempval);
+
 		if (!priv->oldlink) {
-			if (netif_msg_link(priv))
-				printk(KERN_INFO "%s: Link is up\n", dev->name);
+			new_state = 1;
 			priv->oldlink = 1;
-			netif_carrier_on(dev);
 			netif_schedule(dev);
 		}
-	} else {
-		if (priv->oldlink) {
-			if (netif_msg_link(priv))
-				printk(KERN_INFO "%s: Link is down\n",
-						dev->name);
-			priv->oldlink = 0;
-			priv->oldspeed = 0;
-			priv->oldduplex = -1;
-			netif_carrier_off(dev);
-		}
+	} else if (priv->oldlink) {
+		new_state = 1;
+		priv->oldlink = 0;
+		priv->oldspeed = 0;
+		priv->oldduplex = -1;
 	}
-}
 
+	if (new_state && netif_msg_link(priv))
+		phy_print_status(phydev);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
 
 /* Update the hash table based on the current list of multicast
  * addresses we subscribe to.  Also, change the promiscuity of
@@ -2122,12 +1871,23 @@
 
 static int __init gfar_init(void)
 {
-	return driver_register(&gfar_driver);
+	int err = gfar_mdio_init();
+
+	if (err)
+		return err;
+
+	err = driver_register(&gfar_driver);
+
+	if (err)
+		gfar_mdio_exit();
+	
+	return err;
 }
 
 static void __exit gfar_exit(void)
 {
 	driver_unregister(&gfar_driver);
+	gfar_mdio_exit();
 }
 
 module_init(gfar_init);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 28af087..c77ca6c 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -17,7 +17,6 @@
  *
  *  Still left to do:
  *      -Add support for module parameters
- *	-Add support for ethtool -s
  *	-Add patch for ethtool phys id
  */
 #ifndef __GIANFAR_H
@@ -37,7 +36,8 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
-#include <linux/fsl_devices.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -48,7 +48,8 @@
 #include <linux/workqueue.h>
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
-#include "gianfar_phy.h"
+#include <linux/fsl_devices.h>
+#include "gianfar_mii.h"
 
 /* The maximum number of packets to be handled in one call of gfar_poll */
 #define GFAR_DEV_WEIGHT 64
@@ -73,7 +74,7 @@
 #define PHY_INIT_TIMEOUT 100000
 #define GFAR_PHY_CHANGE_TIME 2
 
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
 #define DRV_NAME "gfar-enet"
 extern const char gfar_driver_name[];
 extern const char gfar_driver_version[];
@@ -578,12 +579,7 @@
 	u32	hafdup;		/* 0x.50c - Half Duplex Register */
 	u32	maxfrm;		/* 0x.510 - Maximum Frame Length Register */
 	u8	res18[12];
-	u32	miimcfg;	/* 0x.520 - MII Management Configuration Register */
-	u32	miimcom;	/* 0x.524 - MII Management Command Register */
-	u32	miimadd;	/* 0x.528 - MII Management Address Register */
-	u32	miimcon;	/* 0x.52c - MII Management Control Register */
-	u32	miimstat;	/* 0x.530 - MII Management Status Register */
-	u32	miimind;	/* 0x.534 - MII Management Indicator Register */
+	u8	gfar_mii_regs[24];	/* See gianfar_phy.h */
 	u8	res19[4];
 	u32	ifstat;		/* 0x.53c - Interface Status Register */
 	u32	macstnaddr1;	/* 0x.540 - Station Address Part 1 Register */
@@ -688,9 +684,6 @@
 	struct gfar *regs;	/* Pointer to the GFAR memory mapped Registers */
 	u32 *hash_regs[16];
 	int hash_width;
-	struct gfar *phyregs;
-	struct work_struct tq;
-	struct timer_list phy_info_timer;
 	struct net_device_stats stats; /* linux network statistics */
 	struct gfar_extra_stats extra_stats;
 	spinlock_t lock;
@@ -710,7 +703,8 @@
 	unsigned int interruptError;
 	struct gianfar_platform_data *einfo;
 
-	struct gfar_mii_info *mii_info;
+	struct phy_device *phydev;
+	struct mii_bus *mii_bus;
 	int oldspeed;
 	int oldduplex;
 	int oldlink;
@@ -732,4 +726,12 @@
 
 extern struct ethtool_ops *gfar_op_array[];
 
+extern irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_halt(struct net_device *dev);
+extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
+		int enable, u32 regnum, u32 read);
+void gfar_setup_stashing(struct net_device *dev);
+
 #endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index a451de6..68e3578 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -39,17 +39,18 @@
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include "gianfar.h"
 
 #define is_power_of_2(x)        ((x) != 0 && (((x) & ((x) - 1)) == 0))
 
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
 extern void gfar_start(struct net_device *dev);
 extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
 
+#define GFAR_MAX_COAL_USECS 0xffff
+#define GFAR_MAX_COAL_FRAMES 0xff
 static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
 		     u64 * buf);
 static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
@@ -182,38 +183,32 @@
 	drvinfo->eedump_len = 0;
 }
 
+
+static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct phy_device *phydev = priv->phydev;
+
+	if (NULL == phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
+}
+
+
 /* Return the current settings in the ethtool_cmd structure */
 static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	uint gigabit_support = 
-		priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
-			SUPPORTED_1000baseT_Full : 0;
-	uint gigabit_advert = 
-		priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
-			ADVERTISED_1000baseT_Full: 0;
+	struct phy_device *phydev = priv->phydev;
 
-	cmd->supported = (SUPPORTED_10baseT_Half
-			  | SUPPORTED_100baseT_Half
-			  | SUPPORTED_100baseT_Full
-			  | gigabit_support | SUPPORTED_Autoneg);
-
-	/* For now, we always advertise everything */
-	cmd->advertising = (ADVERTISED_10baseT_Half
-			    | ADVERTISED_100baseT_Half
-			    | ADVERTISED_100baseT_Full
-			    | gigabit_advert | ADVERTISED_Autoneg);
-
-	cmd->speed = priv->mii_info->speed;
-	cmd->duplex = priv->mii_info->duplex;
-	cmd->port = PORT_MII;
-	cmd->phy_address = priv->mii_info->mii_id;
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->autoneg = AUTONEG_ENABLE;
+	if (NULL == phydev)
+		return -ENODEV;
+	
 	cmd->maxtxpkt = priv->txcount;
 	cmd->maxrxpkt = priv->rxcount;
 
-	return 0;
+	return phy_ethtool_gset(phydev, cmd);
 }
 
 /* Return the length of the register structure */
@@ -241,14 +236,14 @@
 	unsigned int count;
 
 	/* The timer is different, depending on the interface speed */
-	switch (priv->mii_info->speed) {
-	case 1000:
+	switch (priv->phydev->speed) {
+	case SPEED_1000:
 		count = GFAR_GBIT_TIME;
 		break;
-	case 100:
+	case SPEED_100:
 		count = GFAR_100_TIME;
 		break;
-	case 10:
+	case SPEED_10:
 	default:
 		count = GFAR_10_TIME;
 		break;
@@ -265,14 +260,14 @@
 	unsigned int count;
 
 	/* The timer is different, depending on the interface speed */
-	switch (priv->mii_info->speed) {
-	case 1000:
+	switch (priv->phydev->speed) {
+	case SPEED_1000:
 		count = GFAR_GBIT_TIME;
 		break;
-	case 100:
+	case SPEED_100:
 		count = GFAR_100_TIME;
 		break;
-	case 10:
+	case SPEED_10:
 	default:
 		count = GFAR_10_TIME;
 		break;
@@ -292,6 +287,9 @@
 	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
 		return -EOPNOTSUPP;
 
+	if (NULL == priv->phydev)
+		return -ENODEV;
+
 	cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
 	cvals->rx_max_coalesced_frames = priv->rxcount;
 
@@ -348,6 +346,22 @@
 	else
 		priv->rxcoalescing = 1;
 
+	if (NULL == priv->phydev)
+		return -ENODEV;
+
+	/* Check the bounds of the values */
+	if (cvals->rx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+		pr_info("Coalescing is limited to %d microseconds\n",
+				GFAR_MAX_COAL_USECS);
+		return -EINVAL;
+	}
+
+	if (cvals->rx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+		pr_info("Coalescing is limited to %d frames\n",
+				GFAR_MAX_COAL_FRAMES);
+		return -EINVAL;
+	}
+
 	priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
 	priv->rxcount = cvals->rx_max_coalesced_frames;
 
@@ -358,6 +372,19 @@
 	else
 		priv->txcoalescing = 1;
 
+	/* Check the bounds of the values */
+	if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+		pr_info("Coalescing is limited to %d microseconds\n",
+				GFAR_MAX_COAL_USECS);
+		return -EINVAL;
+	}
+
+	if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+		pr_info("Coalescing is limited to %d frames\n",
+				GFAR_MAX_COAL_FRAMES);
+		return -EINVAL;
+	}
+
 	priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
 	priv->txcount = cvals->tx_max_coalesced_frames;
 
@@ -536,6 +563,7 @@
 
 struct ethtool_ops gfar_ethtool_ops = {
 	.get_settings = gfar_gsettings,
+	.set_settings = gfar_ssettings,
 	.get_drvinfo = gfar_gdrvinfo,
 	.get_regs_len = gfar_reglen,
 	.get_regs = gfar_get_regs,
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
new file mode 100644
index 0000000..1eca1db
--- /dev/null
+++ b/drivers/net/gianfar_mii.c
@@ -0,0 +1,219 @@
+/* 
+ * drivers/net/gianfar_mii.c
+ *
+ * Gianfar Ethernet Driver -- MIIM bus implementation
+ * Provides Bus interface for MIIM regs
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-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/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#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/version.h>
+#include <asm/ocp.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "gianfar.h"
+#include "gianfar_mii.h"
+
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+	struct gfar_mii *regs = bus->priv;
+
+	/* Set the PHY address and the register address we want to write */
+	gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+	/* Write out the value we want */
+	gfar_write(&regs->miimcon, value);
+
+	/* Wait for the transaction to finish */
+	while (gfar_read(&regs->miimind) & MIIMIND_BUSY)
+		cpu_relax();
+
+	return 0;
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct gfar_mii *regs = bus->priv;
+	u16 value;
+
+	/* Set the PHY address and the register address we want to read */
+	gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
+
+	/* Clear miimcom, and then initiate a read */
+	gfar_write(&regs->miimcom, 0);
+	gfar_write(&regs->miimcom, MII_READ_COMMAND);
+
+	/* Wait for the transaction to finish */
+	while (gfar_read(&regs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+		cpu_relax();
+
+	/* Grab the value of the register from miimstat */
+	value = gfar_read(&regs->miimstat);
+
+	return value;
+}
+
+
+/* Reset the MIIM registers, and wait for the bus to free */
+int gfar_mdio_reset(struct mii_bus *bus)
+{
+	struct gfar_mii *regs = bus->priv;
+	unsigned int timeout = PHY_INIT_TIMEOUT;
+
+	spin_lock_bh(&bus->mdio_lock);
+
+	/* Reset the management interface */
+	gfar_write(&regs->miimcfg, MIIMCFG_RESET);
+
+	/* Setup the MII Mgmt clock speed */
+	gfar_write(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+
+	/* Wait until the bus is free */
+	while ((gfar_read(&regs->miimind) & MIIMIND_BUSY) &&
+			timeout--)
+		cpu_relax();
+
+	spin_unlock_bh(&bus->mdio_lock);
+
+	if(timeout <= 0) {
+		printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+				bus->name);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+
+int gfar_mdio_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gianfar_mdio_data *pdata;
+	struct gfar_mii *regs;
+	struct mii_bus *new_bus;
+	int err = 0;
+
+	if (NULL == dev)
+		return -EINVAL;
+
+	new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+	if (NULL == new_bus)
+		return -ENOMEM;
+
+	new_bus->name = "Gianfar MII Bus",
+	new_bus->read = &gfar_mdio_read,
+	new_bus->write = &gfar_mdio_write,
+	new_bus->reset = &gfar_mdio_reset,
+	new_bus->id = pdev->id;
+
+	pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+
+	if (NULL == pdata) {
+		printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+		return -ENODEV;
+	}
+
+	/* Set the PHY base address */
+	regs = (struct gfar_mii *) ioremap(pdata->paddr, 
+			sizeof (struct gfar_mii));
+
+	if (NULL == regs) {
+		err = -ENOMEM;
+		goto reg_map_fail;
+	}
+
+	new_bus->priv = regs;
+
+	new_bus->irq = pdata->irq;
+
+	new_bus->dev = dev;
+	dev_set_drvdata(dev, new_bus);
+
+	err = mdiobus_register(new_bus);
+
+	if (0 != err) {
+		printk (KERN_ERR "%s: Cannot register as MDIO bus\n", 
+				new_bus->name);
+		goto bus_register_fail;
+	}
+
+	return 0;
+
+bus_register_fail:
+	iounmap((void *) regs);
+reg_map_fail:
+	kfree(new_bus);
+
+	return err;
+}
+
+
+int gfar_mdio_remove(struct device *dev)
+{
+	struct mii_bus *bus = dev_get_drvdata(dev);
+
+	mdiobus_unregister(bus);
+
+	dev_set_drvdata(dev, NULL);
+
+	iounmap((void *) (&bus->priv));
+	bus->priv = NULL;
+	kfree(bus);
+
+	return 0;
+}
+
+static struct device_driver gianfar_mdio_driver = {
+	.name = "fsl-gianfar_mdio",
+	.bus = &platform_bus_type,
+	.probe = gfar_mdio_probe,
+	.remove = gfar_mdio_remove,
+};
+
+int __init gfar_mdio_init(void)
+{
+	return driver_register(&gianfar_mdio_driver);
+}
+
+void __exit gfar_mdio_exit(void)
+{
+	driver_unregister(&gianfar_mdio_driver);
+}
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
new file mode 100644
index 0000000..56e5665
--- /dev/null
+++ b/drivers/net/gianfar_mii.h
@@ -0,0 +1,45 @@
+/* 
+ * drivers/net/gianfar_mii.h
+ *
+ * Gianfar Ethernet Driver -- MII Management Bus Implementation
+ * Driver for the MDIO bus controller in the Gianfar register space
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-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.
+ *
+ */
+#ifndef __GIANFAR_MII_H
+#define __GIANFAR_MII_H
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define MII_READ_COMMAND       0x00000001
+
+#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+		| SUPPORTED_100baseT_Half \
+		| SUPPORTED_100baseT_Full \
+		| SUPPORTED_Autoneg \
+		| SUPPORTED_MII)
+
+struct gfar_mii {
+	u32	miimcfg;	/* 0x.520 - MII Management Config Register */
+	u32	miimcom;	/* 0x.524 - MII Management Command Register */
+	u32	miimadd;	/* 0x.528 - MII Management Address Register */
+	u32	miimcon;	/* 0x.52c - MII Management Control Register */
+	u32	miimstat;	/* 0x.530 - MII Management Status Register */
+	u32	miimind;	/* 0x.534 - MII Management Indicator Register */
+};
+
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
+int __init gfar_mdio_init(void);
+void __exit gfar_mdio_exit(void);
+#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
deleted file mode 100644
index 7c965f2..0000000
--- a/drivers/net/gianfar_phy.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/* 
- * drivers/net/gianfar_phy.c
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-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/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-
-#include "gianfar.h"
-#include "gianfar_phy.h"
-
-static void config_genmii_advert(struct gfar_mii_info *mii_info);
-static void genmii_setup_forced(struct gfar_mii_info *mii_info);
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
-static int gbit_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_config_aneg(struct gfar_mii_info *mii_info);
-static int genmii_update_link(struct gfar_mii_info *mii_info);
-static int genmii_read_status(struct gfar_mii_info *mii_info);
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
-
-/* Write value to the PHY for this device to the register at regnum, */
-/* waiting until the write is done before it returns.  All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
-{
-	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regbase = priv->phyregs;
-
-	/* Set the PHY address and the register address we want to write */
-	gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
-	/* Write out the value we want */
-	gfar_write(&regbase->miimcon, value);
-
-	/* Wait for the transaction to finish */
-	while (gfar_read(&regbase->miimind) & MIIMIND_BUSY)
-		cpu_relax();
-}
-
-/* Reads from register regnum in the PHY for device dev, */
-/* returning the value.  Clears miimcom first.  All PHY */
-/* configuration has to be done through the TSEC1 MIIM regs */
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
-{
-	struct gfar_private *priv = netdev_priv(dev);
-	struct gfar *regbase = priv->phyregs;
-	u16 value;
-
-	/* Set the PHY address and the register address we want to read */
-	gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
-
-	/* Clear miimcom, and then initiate a read */
-	gfar_write(&regbase->miimcom, 0);
-	gfar_write(&regbase->miimcom, MII_READ_COMMAND);
-
-	/* Wait for the transaction to finish */
-	while (gfar_read(&regbase->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
-		cpu_relax();
-
-	/* Grab the value of the register from miimstat */
-	value = gfar_read(&regbase->miimstat);
-
-	return value;
-}
-
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
-{
-	if(mii_info->phyinfo->ack_interrupt)
-		mii_info->phyinfo->ack_interrupt(mii_info);
-}
-
-
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
-{
-	mii_info->interrupts = interrupts;
-	if(mii_info->phyinfo->config_intr)
-		mii_info->phyinfo->config_intr(mii_info);
-}
-
-
-/* Writes MII_ADVERTISE with the appropriate values, after
- * sanitizing advertise to make sure only supported features
- * are advertised 
- */
-static void config_genmii_advert(struct gfar_mii_info *mii_info)
-{
-	u32 advertise;
-	u16 adv;
-
-	/* Only allow advertising what this PHY supports */
-	mii_info->advertising &= mii_info->phyinfo->features;
-	advertise = mii_info->advertising;
-
-	/* Setup standard advertisement */
-	adv = phy_read(mii_info, MII_ADVERTISE);
-	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	if (advertise & ADVERTISED_10baseT_Half)
-		adv |= ADVERTISE_10HALF;
-	if (advertise & ADVERTISED_10baseT_Full)
-		adv |= ADVERTISE_10FULL;
-	if (advertise & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	phy_write(mii_info, MII_ADVERTISE, adv);
-}
-
-static void genmii_setup_forced(struct gfar_mii_info *mii_info)
-{
-	u16 ctrl;
-	u32 features = mii_info->phyinfo->features;
-	
-	ctrl = phy_read(mii_info, MII_BMCR);
-
-	ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
-	ctrl |= BMCR_RESET;
-
-	switch(mii_info->speed) {
-		case SPEED_1000:
-			if(features & (SUPPORTED_1000baseT_Half
-						| SUPPORTED_1000baseT_Full)) {
-				ctrl |= BMCR_SPEED1000;
-				break;
-			}
-			mii_info->speed = SPEED_100;
-		case SPEED_100:
-			if (features & (SUPPORTED_100baseT_Half
-						| SUPPORTED_100baseT_Full)) {
-				ctrl |= BMCR_SPEED100;
-				break;
-			}
-			mii_info->speed = SPEED_10;
-		case SPEED_10:
-			if (features & (SUPPORTED_10baseT_Half
-						| SUPPORTED_10baseT_Full))
-				break;
-		default: /* Unsupported speed! */
-			printk(KERN_ERR "%s: Bad speed!\n", 
-					mii_info->dev->name);
-			break;
-	}
-
-	phy_write(mii_info, MII_BMCR, ctrl);
-}
-
-
-/* Enable and Restart Autonegotiation */
-static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
-{
-	u16 ctl;
-
-	ctl = phy_read(mii_info, MII_BMCR);
-	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write(mii_info, MII_BMCR, ctl);
-}
-
-
-static int gbit_config_aneg(struct gfar_mii_info *mii_info)
-{
-	u16 adv;
-	u32 advertise;
-
-	if(mii_info->autoneg) {
-		/* Configure the ADVERTISE register */
-		config_genmii_advert(mii_info);
-		advertise = mii_info->advertising;
-
-		adv = phy_read(mii_info, MII_1000BASETCONTROL);
-		adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
-				MII_1000BASETCONTROL_HALFDUPLEXCAP);
-		if (advertise & SUPPORTED_1000baseT_Half)
-			adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
-		if (advertise & SUPPORTED_1000baseT_Full)
-			adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
-		phy_write(mii_info, MII_1000BASETCONTROL, adv);
-
-		/* Start/Restart aneg */
-		genmii_restart_aneg(mii_info);
-	} else
-		genmii_setup_forced(mii_info);
-
-	return 0;
-}
-
-static int marvell_config_aneg(struct gfar_mii_info *mii_info)
-{
-	/* The Marvell PHY has an errata which requires
-	 * that certain registers get written in order
-	 * to restart autonegotiation */
-	phy_write(mii_info, MII_BMCR, BMCR_RESET);
-
-	phy_write(mii_info, 0x1d, 0x1f);
-	phy_write(mii_info, 0x1e, 0x200c);
-	phy_write(mii_info, 0x1d, 0x5);
-	phy_write(mii_info, 0x1e, 0);
-	phy_write(mii_info, 0x1e, 0x100);
-
-	gbit_config_aneg(mii_info);
-
-	return 0;
-}
-static int genmii_config_aneg(struct gfar_mii_info *mii_info)
-{
-	if (mii_info->autoneg) {
-		config_genmii_advert(mii_info);
-		genmii_restart_aneg(mii_info);
-	} else
-		genmii_setup_forced(mii_info);
-
-	return 0;
-}
-
-
-static int genmii_update_link(struct gfar_mii_info *mii_info)
-{
-	u16 status;
-
-	/* Do a fake read */
-	phy_read(mii_info, MII_BMSR);
-
-	/* Read link and autonegotiation status */
-	status = phy_read(mii_info, MII_BMSR);
-	if ((status & BMSR_LSTATUS) == 0)
-		mii_info->link = 0;
-	else
-		mii_info->link = 1;
-
-	/* If we are autonegotiating, and not done, 
-	 * return an error */
-	if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
-		return -EAGAIN;
-
-	return 0;
-}
-
-static int genmii_read_status(struct gfar_mii_info *mii_info)
-{
-	u16 status;
-	int err;
-
-	/* Update the link, but return if there
-	 * was an error */
-	err = genmii_update_link(mii_info);
-	if (err)
-		return err;
-
-	if (mii_info->autoneg) {
-		status = phy_read(mii_info, MII_LPA);
-
-		if (status & (LPA_10FULL | LPA_100FULL))
-			mii_info->duplex = DUPLEX_FULL;
-		else
-			mii_info->duplex = DUPLEX_HALF;
-		if (status & (LPA_100FULL | LPA_100HALF))
-			mii_info->speed = SPEED_100;
-		else
-			mii_info->speed = SPEED_10;
-		mii_info->pause = 0;
-	}
-	/* On non-aneg, we assume what we put in BMCR is the speed,
-	 * though magic-aneg shouldn't prevent this case from occurring
-	 */
-
-	return 0;
-}
-static int marvell_read_status(struct gfar_mii_info *mii_info)
-{
-	u16 status;
-	int err;
-
-	/* Update the link, but return if there
-	 * was an error */
-	err = genmii_update_link(mii_info);
-	if (err)
-		return err;
-
-	/* If the link is up, read the speed and duplex */
-	/* If we aren't autonegotiating, assume speeds 
-	 * are as set */
-	if (mii_info->autoneg && mii_info->link) {
-		int speed;
-		status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
-
-#if 0
-		/* If speed and duplex aren't resolved,
-		 * return an error.  Isn't this handled
-		 * by checking aneg?
-		 */
-		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
-			return -EAGAIN;
-#endif
-
-		/* Get the duplexity */
-		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
-			mii_info->duplex = DUPLEX_FULL;
-		else
-			mii_info->duplex = DUPLEX_HALF;
-
-		/* Get the speed */
-		speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
-		switch(speed) {
-			case MII_M1011_PHY_SPEC_STATUS_1000:
-				mii_info->speed = SPEED_1000;
-				break;
-			case MII_M1011_PHY_SPEC_STATUS_100:
-				mii_info->speed = SPEED_100;
-				break;
-			default:
-				mii_info->speed = SPEED_10;
-				break;
-		}
-		mii_info->pause = 0;
-	}
-
-	return 0;
-}
-
-
-static int cis820x_read_status(struct gfar_mii_info *mii_info)
-{
-	u16 status;
-	int err;
-
-	/* Update the link, but return if there
-	 * was an error */
-	err = genmii_update_link(mii_info);
-	if (err)
-		return err;
-
-	/* If the link is up, read the speed and duplex */
-	/* If we aren't autonegotiating, assume speeds 
-	 * are as set */
-	if (mii_info->autoneg && mii_info->link) {
-		int speed;
-
-		status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
-		if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
-			mii_info->duplex = DUPLEX_FULL;
-		else
-			mii_info->duplex = DUPLEX_HALF;
-
-		speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
-
-		switch (speed) {
-		case MII_CIS8201_AUXCONSTAT_GBIT:
-			mii_info->speed = SPEED_1000;
-			break;
-		case MII_CIS8201_AUXCONSTAT_100:
-			mii_info->speed = SPEED_100;
-			break;
-		default:
-			mii_info->speed = SPEED_10;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
-{
-	/* Clear the interrupts by reading the reg */
-	phy_read(mii_info, MII_M1011_IEVENT);
-
-	return 0;
-}
-
-static int marvell_config_intr(struct gfar_mii_info *mii_info)
-{
-	if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
-	else
-		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
-
-	return 0;
-}
-
-static int cis820x_init(struct gfar_mii_info *mii_info)
-{
-	phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, 
-			MII_CIS8201_AUXCONSTAT_INIT);
-	phy_write(mii_info, MII_CIS8201_EXT_CON1,
-			MII_CIS8201_EXTCON1_INIT);
-
-	return 0;
-}
-
-static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
-{
-	phy_read(mii_info, MII_CIS8201_ISTAT);
-
-	return 0;
-}
-
-static int cis820x_config_intr(struct gfar_mii_info *mii_info)
-{
-	if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
-	else
-		phy_write(mii_info, MII_CIS8201_IMASK, 0);
-
-	return 0;
-}
-
-#define DM9161_DELAY 10
-
-static int dm9161_read_status(struct gfar_mii_info *mii_info)
-{
-	u16 status;
-	int err;
-
-	/* Update the link, but return if there
-	 * was an error */
-	err = genmii_update_link(mii_info);
-	if (err)
-		return err;
-
-	/* If the link is up, read the speed and duplex */
-	/* If we aren't autonegotiating, assume speeds 
-	 * are as set */
-	if (mii_info->autoneg && mii_info->link) {
-		status = phy_read(mii_info, MII_DM9161_SCSR);
-		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
-			mii_info->speed = SPEED_100;
-		else
-			mii_info->speed = SPEED_10;
-
-		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
-			mii_info->duplex = DUPLEX_FULL;
-		else
-			mii_info->duplex = DUPLEX_HALF;
-	}
-
-	return 0;
-}
-
-
-static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
-{
-	struct dm9161_private *priv = mii_info->priv;
-
-	if(0 == priv->resetdone)
-		return -EAGAIN;
-
-	return 0;
-}
-
-static void dm9161_timer(unsigned long data)
-{
-	struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
-	struct dm9161_private *priv = mii_info->priv;
-	u16 status = phy_read(mii_info, MII_BMSR);
-
-	if (status & BMSR_ANEGCOMPLETE) {
-		priv->resetdone = 1;
-	} else
-		mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-}
-
-static int dm9161_init(struct gfar_mii_info *mii_info)
-{
-	struct dm9161_private *priv;
-
-	/* Allocate the private data structure */
-	priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
-
-	if (NULL == priv)
-		return -ENOMEM;
-
-	mii_info->priv = priv;
-
-	/* Reset is not done yet */
-	priv->resetdone = 0;
-
-	/* Isolate the PHY */
-	phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
-
-	/* Do not bypass the scrambler/descrambler */
-	phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
-
-	/* Clear 10BTCSR to default */
-	phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
-
-	/* Reconnect the PHY, and enable Autonegotiation */
-	phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
-
-	/* Start a timer for DM9161_DELAY seconds to wait
-	 * for the PHY to be ready */
-	init_timer(&priv->timer);
-	priv->timer.function = &dm9161_timer;
-	priv->timer.data = (unsigned long) mii_info;
-	mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
-
-	return 0;
-}
-
-static void dm9161_close(struct gfar_mii_info *mii_info)
-{
-	struct dm9161_private *priv = mii_info->priv;
-
-	del_timer_sync(&priv->timer);
-	kfree(priv);
-}
-
-#if 0
-static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
-{
-	phy_read(mii_info, MII_DM9161_INTR);
-
-	return 0;
-}
-#endif
-
-/* Cicada 820x */
-static struct phy_info phy_info_cis820x = {
-	0x000fc440,
-	"Cicada Cis8204",
-	0x000fffc0,
-	.features	= MII_GBIT_FEATURES,
-	.init		= &cis820x_init,
-	.config_aneg	= &gbit_config_aneg,
-	.read_status	= &cis820x_read_status,
-	.ack_interrupt	= &cis820x_ack_interrupt,
-	.config_intr	= &cis820x_config_intr,
-};
-
-static struct phy_info phy_info_dm9161 = {
-	.phy_id		= 0x0181b880,
-	.name		= "Davicom DM9161E",
-	.phy_id_mask	= 0x0ffffff0,
-	.init		= dm9161_init,
-	.config_aneg	= dm9161_config_aneg,
-	.read_status	= dm9161_read_status,
-	.close		= dm9161_close,
-};
-
-static struct phy_info phy_info_marvell = {
-	.phy_id		= 0x01410c00,
-	.phy_id_mask	= 0xffffff00,
-	.name		= "Marvell 88E1101/88E1111",
-	.features	= MII_GBIT_FEATURES,
-	.config_aneg	= &marvell_config_aneg,
-	.read_status	= &marvell_read_status,
-	.ack_interrupt	= &marvell_ack_interrupt,
-	.config_intr	= &marvell_config_intr,
-};
-
-static struct phy_info phy_info_genmii= {
-	.phy_id		= 0x00000000,
-	.phy_id_mask	= 0x00000000,
-	.name		= "Generic MII",
-	.features	= MII_BASIC_FEATURES,
-	.config_aneg	= genmii_config_aneg,
-	.read_status	= genmii_read_status,
-};
-
-static struct phy_info *phy_info[] = {
-	&phy_info_cis820x,
-	&phy_info_marvell,
-	&phy_info_dm9161,
-	&phy_info_genmii,
-	NULL
-};
-
-u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
-{
-	u16 retval;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mii_info->mdio_lock, flags);
-	retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
-	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-
-	return retval;
-}
-
-void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&mii_info->mdio_lock, flags);
-	mii_info->mdio_write(mii_info->dev, 
-			mii_info->mii_id, 
-			regnum, val);
-	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
-}
-
-/* Use the PHY ID registers to determine what type of PHY is attached
- * to device dev.  return a struct phy_info structure describing that PHY
- */
-struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
-{
-	u16 phy_reg;
-	u32 phy_ID;
-	int i;
-	struct phy_info *theInfo = NULL;
-	struct net_device *dev = mii_info->dev;
-
-	/* Grab the bits from PHYIR1, and put them in the upper half */
-	phy_reg = phy_read(mii_info, MII_PHYSID1);
-	phy_ID = (phy_reg & 0xffff) << 16;
-
-	/* Grab the bits from PHYIR2, and put them in the lower half */
-	phy_reg = phy_read(mii_info, MII_PHYSID2);
-	phy_ID |= (phy_reg & 0xffff);
-
-	/* loop through all the known PHY types, and find one that */
-	/* matches the ID we read from the PHY. */
-	for (i = 0; phy_info[i]; i++)
-		if (phy_info[i]->phy_id == 
-				(phy_ID & phy_info[i]->phy_id_mask)) {
-			theInfo = phy_info[i];
-			break;
-		}
-
-	/* This shouldn't happen, as we have generic PHY support */
-	if (theInfo == NULL) {
-		printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
-		return NULL;
-	} else {
-		printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
-		       phy_ID);
-	}
-
-	return theInfo;
-}
diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
deleted file mode 100644
index 1e9b3ab..0000000
--- a/drivers/net/gianfar_phy.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* 
- * drivers/net/gianfar_phy.h
- *
- * Gianfar Ethernet Driver -- PHY handling
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright (c) 2002-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.
- *
- */
-#ifndef __GIANFAR_PHY_H
-#define __GIANFAR_PHY_H
-
-#define MII_end ((u32)-2)
-#define MII_read ((u32)-1)
-
-#define MIIMIND_BUSY            0x00000001
-#define MIIMIND_NOTVALID        0x00000004
-
-#define GFAR_AN_TIMEOUT         2000
-
-/* 1000BT control (Marvell & BCM54xx at least) */
-#define MII_1000BASETCONTROL			0x09
-#define MII_1000BASETCONTROL_FULLDUPLEXCAP	0x0200
-#define MII_1000BASETCONTROL_HALFDUPLEXCAP	0x0100
-
-/* Cicada Extended Control Register 1 */
-#define MII_CIS8201_EXT_CON1           0x17
-#define MII_CIS8201_EXTCON1_INIT       0x0000
-
-/* Cicada Interrupt Mask Register */
-#define MII_CIS8201_IMASK		0x19
-#define MII_CIS8201_IMASK_IEN		0x8000
-#define MII_CIS8201_IMASK_SPEED	0x4000
-#define MII_CIS8201_IMASK_LINK		0x2000
-#define MII_CIS8201_IMASK_DUPLEX	0x1000
-#define MII_CIS8201_IMASK_MASK		0xf000
-
-/* Cicada Interrupt Status Register */
-#define MII_CIS8201_ISTAT		0x1a
-#define MII_CIS8201_ISTAT_STATUS	0x8000
-#define MII_CIS8201_ISTAT_SPEED	0x4000
-#define MII_CIS8201_ISTAT_LINK		0x2000
-#define MII_CIS8201_ISTAT_DUPLEX	0x1000
-
-/* Cicada Auxiliary Control/Status Register */
-#define MII_CIS8201_AUX_CONSTAT        0x1c
-#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
-#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
-#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
-#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
-#define MII_CIS8201_AUXCONSTAT_100     0x0008
-                                                                                
-/* 88E1011 PHY Status Register */
-#define MII_M1011_PHY_SPEC_STATUS		0x11
-#define MII_M1011_PHY_SPEC_STATUS_1000		0x8000
-#define MII_M1011_PHY_SPEC_STATUS_100		0x4000
-#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK	0xc000
-#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX	0x2000
-#define MII_M1011_PHY_SPEC_STATUS_RESOLVED	0x0800
-#define MII_M1011_PHY_SPEC_STATUS_LINK		0x0400
-
-#define MII_M1011_IEVENT		0x13
-#define MII_M1011_IEVENT_CLEAR		0x0000
-
-#define MII_M1011_IMASK			0x12
-#define MII_M1011_IMASK_INIT		0x6400
-#define MII_M1011_IMASK_CLEAR		0x0000
-
-#define MII_DM9161_SCR		0x10
-#define MII_DM9161_SCR_INIT	0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MII_DM9161_SCSR	0x11
-#define MII_DM9161_SCSR_100F	0x8000
-#define MII_DM9161_SCSR_100H	0x4000
-#define MII_DM9161_SCSR_10F	0x2000
-#define MII_DM9161_SCSR_10H	0x1000
-
-/* DM9161 Interrupt Register */
-#define MII_DM9161_INTR	0x15
-#define MII_DM9161_INTR_PEND		0x8000
-#define MII_DM9161_INTR_DPLX_MASK	0x0800
-#define MII_DM9161_INTR_SPD_MASK	0x0400
-#define MII_DM9161_INTR_LINK_MASK	0x0200
-#define MII_DM9161_INTR_MASK		0x0100
-#define MII_DM9161_INTR_DPLX_CHANGE	0x0010
-#define MII_DM9161_INTR_SPD_CHANGE	0x0008
-#define MII_DM9161_INTR_LINK_CHANGE	0x0004
-#define MII_DM9161_INTR_INIT 		0x0000
-#define MII_DM9161_INTR_STOP	\
-(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
- | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
-
-/* DM9161 10BT Configuration/Status */
-#define MII_DM9161_10BTCSR	0x12
-#define MII_DM9161_10BTCSR_INIT	0x7800
-
-#define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
-				 SUPPORTED_10baseT_Full | \
-				 SUPPORTED_100baseT_Half | \
-				 SUPPORTED_100baseT_Full | \
-				 SUPPORTED_Autoneg | \
-				 SUPPORTED_TP | \
-				 SUPPORTED_MII)
-
-#define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
-				 SUPPORTED_1000baseT_Half | \
-				 SUPPORTED_1000baseT_Full)
-
-#define MII_READ_COMMAND       0x00000001
-
-#define MII_INTERRUPT_DISABLED 0x0
-#define MII_INTERRUPT_ENABLED 0x1
-/* Taken from mii_if_info and sungem_phy.h */
-struct gfar_mii_info {
-	/* Information about the PHY type */
-	/* And management functions */
-	struct phy_info *phyinfo;
-
-	/* forced speed & duplex (no autoneg)
-	 * partner speed & duplex & pause (autoneg)
-	 */
-	int speed;
-	int duplex;
-	int pause;
-
-	/* The most recently read link state */
-	int link;
-
-	/* Enabled Interrupts */
-	u32 interrupts;
-
-	u32 advertising;
-	int autoneg;
-	int mii_id;
-
-	/* private data pointer */
-	/* For use by PHYs to maintain extra state */
-	void *priv;
-
-	/* Provided by host chip */
-	struct net_device *dev;
-
-	/* A lock to ensure that only one thing can read/write
-	 * the MDIO bus at a time */
-	spinlock_t mdio_lock;
-
-	/* Provided by ethernet driver */
-	int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
-	void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY.  During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be ANDed with phy_id_mask to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * There are 6 commands which take a gfar_mii_info structure.
- * Each PHY must declare config_aneg, and read_status.
- */
-struct phy_info {
-	u32 phy_id;
-	char *name;
-	unsigned int phy_id_mask;
-	u32 features;
-
-	/* Called to initialize the PHY */
-	int (*init)(struct gfar_mii_info *mii_info);
-
-	/* Called to suspend the PHY for power */
-	int (*suspend)(struct gfar_mii_info *mii_info);
-
-	/* Reconfigures autonegotiation (or disables it) */
-	int (*config_aneg)(struct gfar_mii_info *mii_info);
-
-	/* Determines the negotiated speed and duplex */
-	int (*read_status)(struct gfar_mii_info *mii_info);
-
-	/* Clears any pending interrupts */
-	int (*ack_interrupt)(struct gfar_mii_info *mii_info);
-
-	/* Enables or disables interrupts */
-	int (*config_intr)(struct gfar_mii_info *mii_info);
-
-	/* Clears up any memory if needed */
-	void (*close)(struct gfar_mii_info *mii_info);
-};
-
-struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
-int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
-void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
-void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
-void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
-
-struct dm9161_private {
-	struct timer_list timer;
-	int resetdone;
-};
-
-#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index de087cd..896aa02 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -1,6 +1,7 @@
 config MKISS
 	tristate "Serial port KISS driver"
 	depends on AX25
+	select CRC16
 	---help---
 	  KISS is a protocol used for the exchange of data between a computer
 	  and a Terminal Node Controller (a small embedded system commonly
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 1756f0e..cb43a9d 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -144,7 +144,7 @@
 {
 	struct bpqdev *bpq;
 
-	list_for_each_entry(bpq, &bpq_devices, bpq_list) {
+	list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
 		if (bpq->ethdev == dev)
 			return bpq->axdev;
 	}
@@ -399,7 +399,7 @@
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 	
-	list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
+	list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) {
 		if (i == *pos)
 			return bpqdev;
 	}
@@ -418,7 +418,7 @@
 		p = ((struct bpqdev *)v)->bpq_list.next;
 
 	return (p == &bpq_devices) ? NULL 
-		: list_entry(p, struct bpqdev, bpq_list);
+		: rcu_dereference(list_entry(p, struct bpqdev, bpq_list));
 }
 
 static void bpq_seq_stop(struct seq_file *seq, void *v)
@@ -561,8 +561,6 @@
 	if (!dev_is_ethdev(dev))
 		return NOTIFY_DONE;
 
-	rcu_read_lock();
-
 	switch (event) {
 	case NETDEV_UP:		/* new ethernet device -> new BPQ interface */
 		if (bpq_get_ax25_dev(dev) == NULL)
@@ -581,7 +579,6 @@
 	default:
 		break;
 	}
-	rcu_read_unlock();
 
 	return NOTIFY_DONE;
 }
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d9fe64b..3e9accf 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -14,13 +14,14 @@
  *
  * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
  * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
+ * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
  */
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/system.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
+#include <linux/crc16.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -39,11 +40,6 @@
 
 #include <net/ax25.h>
 
-#ifdef CONFIG_INET
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#endif
-
 #define AX_MTU		236
 
 /* SLIP/KISS protocol characters. */
@@ -80,9 +76,13 @@
 
 	int		mode;
         int		crcmode;	/* MW: for FlexNet, SMACK etc.  */
-#define CRC_MODE_NONE   0
-#define CRC_MODE_FLEX   1
-#define CRC_MODE_SMACK  2
+	int		crcauto;	/* CRC auto mode */
+
+#define CRC_MODE_NONE		0
+#define CRC_MODE_FLEX		1
+#define CRC_MODE_SMACK		2
+#define CRC_MODE_FLEX_TEST	3
+#define CRC_MODE_SMACK_TEST	4
 
 	atomic_t		refcnt;
 	struct semaphore	dead_sem;
@@ -151,6 +151,21 @@
 	return 0;
 }
 
+static int check_crc_16(unsigned char *cp, int size)
+{
+	unsigned short crc = 0x0000;
+
+	if (size < 3)
+		return -1;
+
+	crc = crc16(0, cp, size);
+
+	if (crc != 0x0000)
+		return -1;
+
+	return 0;
+}
+
 /*
  * Standard encapsulation
  */
@@ -237,19 +252,42 @@
 
 	spin_lock_bh(&ax->buflock);
 	if (ax->rbuff[0] > 0x0f) {
-		if (ax->rbuff[0] & 0x20) {
-		        ax->crcmode = CRC_MODE_FLEX;
-			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
-			        ax->stats.rx_errors++;
+		if (ax->rbuff[0] & 0x80) {
+			if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
+				ax->stats.rx_errors++;
+				spin_unlock_bh(&ax->buflock);
+
 				return;
 			}
+			if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
+				printk(KERN_INFO
+				       "mkiss: %s: Switchting to crc-smack\n",
+				       ax->dev->name);
+				ax->crcmode = CRC_MODE_SMACK;
+			}
 			ax->rcount -= 2;
-                        /* dl9sau bugfix: the trailling two bytes flexnet crc
-                         * will not be passed to the kernel. thus we have
-                         * to correct the kissparm signature, because it
-                         * indicates a crc but there's none
+			*ax->rbuff &= ~0x80;
+		} else if (ax->rbuff[0] & 0x20)  {
+			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
+				ax->stats.rx_errors++;
+				spin_unlock_bh(&ax->buflock);
+				return;
+			}
+			if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
+				printk(KERN_INFO
+				       "mkiss: %s: Switchting to crc-flexnet\n",
+				       ax->dev->name);
+				ax->crcmode = CRC_MODE_FLEX;
+			}
+			ax->rcount -= 2;
+
+			/*
+			 * dl9sau bugfix: the trailling two bytes flexnet crc
+			 * will not be passed to the kernel. thus we have to
+			 * correct the kissparm signature, because it indicates
+			 * a crc but there's none
 			 */
-                        *ax->rbuff &= ~0x20;
+			*ax->rbuff &= ~0x20;
 		}
  	}
 	spin_unlock_bh(&ax->buflock);
@@ -352,10 +390,8 @@
 		       "MTU change cancelled.\n",
 		       ax->dev->name);
 		dev->mtu = ax->mtu;
-		if (xbuff != NULL)
-			kfree(xbuff);
-		if (rbuff != NULL)
-			kfree(rbuff);
+		kfree(xbuff);
+		kfree(rbuff);
 		return;
 	}
 
@@ -417,20 +453,69 @@
 	p = icp;
 
 	spin_lock_bh(&ax->buflock);
-        switch (ax->crcmode) {
-	         unsigned short crc;
+	if ((*p & 0x0f) != 0) {
+		/* Configuration Command (kissparms(1).
+		 * Protocol spec says: never append CRC.
+		 * This fixes a very old bug in the linux
+		 * kiss driver. -- dl9sau */
+		switch (*p & 0xff) {
+		case 0x85:
+			/* command from userspace especially for us,
+			 * not for delivery to the tnc */
+			if (len > 1) {
+				int cmd = (p[1] & 0xff);
+				switch(cmd) {
+				case 3:
+				  ax->crcmode = CRC_MODE_SMACK;
+				  break;
+				case 2:
+				  ax->crcmode = CRC_MODE_FLEX;
+				  break;
+				case 1:
+				  ax->crcmode = CRC_MODE_NONE;
+				  break;
+				case 0:
+				default:
+				  ax->crcmode = CRC_MODE_SMACK_TEST;
+				  cmd = 0;
+				}
+				ax->crcauto = (cmd ? 0 : 1);
+				printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
+			}
+			spin_unlock_bh(&ax->buflock);
+			netif_start_queue(dev);
 
-	case CRC_MODE_FLEX:
-	         *p |= 0x20;
-	         crc = calc_crc_flex(p, len);
-		 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
-		 break;
+			return;
+		default:
+			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+		}
+	} else {
+		unsigned short crc;
+		switch (ax->crcmode) {
+		case CRC_MODE_SMACK_TEST:
+			ax->crcmode  = CRC_MODE_FLEX_TEST;
+			printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
+			// fall through
+		case CRC_MODE_SMACK:
+			*p |= 0x80;
+			crc = swab16(crc16(0, p, len));
+			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+			break;
+		case CRC_MODE_FLEX_TEST:
+			ax->crcmode = CRC_MODE_NONE;
+			printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
+			// fall through
+		case CRC_MODE_FLEX:
+			*p |= 0x20;
+			crc = calc_crc_flex(p, len);
+			count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+			break;
 
-	default:
-	         count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
-		 break;
-	}
-	
+		default:
+			count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+		}
+  	}
+
 	set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
 	actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
 	ax->stats.tx_packets++;
@@ -439,8 +524,6 @@
 	ax->dev->trans_start = jiffies;
 	ax->xleft = count - actual;
 	ax->xhead = ax->xbuff + actual;
-
-	spin_unlock_bh(&ax->buflock);
 }
 
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
@@ -622,7 +705,7 @@
  * best way to fix this is to use a rwlock in the tty struct, but for now we
  * use a single global rwlock for all ttys in ppp line discipline.
  */
-static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(disc_data_lock);
 
 static struct mkiss *mkiss_get(struct tty_struct *tty)
 {
@@ -643,6 +726,8 @@
 		up(&ax->dead_sem);
 }
 
+static int crc_force = 0;	/* Can be overridden with insmod */
+
 static int mkiss_open(struct tty_struct *tty)
 {
 	struct net_device *dev;
@@ -682,6 +767,33 @@
 	if (register_netdev(dev))
 		goto out_free_buffers;
 
+	/* after register_netdev() - because else printk smashes the kernel */
+	switch (crc_force) {
+	case 3:
+		ax->crcmode  = CRC_MODE_SMACK;
+		printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
+		       ax->dev->name);
+		break;
+	case 2:
+		ax->crcmode  = CRC_MODE_FLEX;
+		printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
+		       ax->dev->name);
+		break;
+	case 1:
+		ax->crcmode  = CRC_MODE_NONE;
+		printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
+		       ax->dev->name);
+		break;
+	case 0:
+		/* fall through */
+	default:
+		crc_force = 0;
+		printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
+		       ax->dev->name);
+		ax->crcmode  = CRC_MODE_SMACK_TEST;
+	}
+	ax->crcauto = (crc_force ? 0 : 1);
+
 	netif_start_queue(dev);
 
 	/* Done.  We have linked the TTY line to a channel. */
@@ -765,7 +877,6 @@
 
 	case SIOCSIFHWADDR: {
 		char addr[AX25_ADDR_LEN];
-printk(KERN_INFO "In SIOCSIFHWADDR");
 
 		if (copy_from_user(&addr,
 		                   (void __user *) arg, AX25_ADDR_LEN)) {
@@ -864,6 +975,7 @@
 }
 
 static struct tty_ldisc ax_ldisc = {
+	.owner		= THIS_MODULE,
 	.magic		= TTY_LDISC_MAGIC,
 	.name		= "mkiss",
 	.open		= mkiss_open,
@@ -904,6 +1016,8 @@
 
 MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
 MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
+MODULE_PARM(crc_force, "i");
+MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_AX25);
 
diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
deleted file mode 100644
index 4ab7004..0000000
--- a/drivers/net/hamradio/mkiss.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
- *	Defines for the Multi-KISS driver.
- ****************************************************************************/
-
-#define AX25_MAXDEV	16		/* MAX number of AX25 channels;
-					   This can be overridden with
-					   insmod -oax25_maxdev=nnn	*/
-#define AX_MTU		236	
-
-/* SLIP/KISS protocol characters. */
-#define END             0300		/* indicates end of frame	*/
-#define ESC             0333		/* indicates byte stuffing	*/
-#define ESC_END         0334		/* ESC ESC_END means END 'data'	*/
-#define ESC_ESC         0335		/* ESC ESC_ESC means ESC 'data'	*/
-
-struct ax_disp {
-	int                magic;
-
-	/* Various fields. */
-	struct tty_struct  *tty;		/* ptr to TTY structure		*/
-	struct net_device      *dev;		/* easy for intr handling	*/
-
-	/* These are pointers to the malloc()ed frame buffers. */
-	unsigned char      *rbuff;		/* receiver buffer		*/
-	int                rcount;		/* received chars counter       */
-	unsigned char      *xbuff;		/* transmitter buffer		*/
-	unsigned char      *xhead;		/* pointer to next byte to XMIT */
-	int                xleft;		/* bytes left in XMIT queue     */
-
-	/* SLIP interface statistics. */
-	unsigned long      rx_packets;		/* inbound frames counter	*/
-	unsigned long      tx_packets;		/* outbound frames counter      */
-	unsigned long      rx_bytes;		/* inbound bytes counter        */
-	unsigned long      tx_bytes;		/* outbound bytes counter       */
-	unsigned long      rx_errors;		/* Parity, etc. errors          */
-	unsigned long      tx_errors;		/* Planned stuff                */
-	unsigned long      rx_dropped;		/* No memory for skb            */
-	unsigned long      tx_dropped;		/* When MTU change              */
-	unsigned long      rx_over_errors;	/* Frame bigger then SLIP buf.  */
-
-	/* Detailed SLIP statistics. */
-	int                 mtu;		/* Our mtu (to spot changes!)   */
-	int                 buffsize;		/* Max buffers sizes            */
-
-
-	unsigned long   flags;		/* Flag values/ mode etc	*/
-					/* long req'd: used by set_bit --RR */
-#define AXF_INUSE	0		/* Channel in use               */
-#define AXF_ESCAPE	1               /* ESC received                 */
-#define AXF_ERROR	2               /* Parity, etc. error           */
-#define AXF_KEEPTEST	3		/* Keepalive test flag		*/
-#define AXF_OUTWAIT	4		/* is outpacket was flag	*/
-
-	int                 mode;
-        int                 crcmode;    /* MW: for FlexNet, SMACK etc.  */ 
-#define CRC_MODE_NONE   0
-#define CRC_MODE_FLEX   1
-#define CRC_MODE_SMACK  2
-	spinlock_t          buflock;	/* lock for rbuf and xbuf */
-};
-
-#define AX25_MAGIC		0x5316
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index cf0ac6f..b71fab6 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2517,10 +2517,8 @@
 	do {
 		if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
 			break;
-		if (!in_interrupt()) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
-		}
+		if (!in_interrupt())
+			schedule_timeout_interruptible(1);
 	} while (time_after(time, jiffies));
 
 	if (time_after_eq(jiffies, time))	/* no signal->no logout */
@@ -2536,10 +2534,8 @@
 	do {
 		if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
 			break;
-		if (!in_interrupt()) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
-		}
+		if (!in_interrupt())
+			schedule_timeout_interruptible(1);
 	} while (time_after(time, jiffies));
 
 #ifdef HP100_DEBUG
@@ -2577,10 +2573,8 @@
 		do {
 			if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST))
 				break;
-			if (!in_interrupt()) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(1);
-			}
+			if (!in_interrupt())
+				schedule_timeout_interruptible(1);
 		} while (time_after(time, jiffies));
 
 		hp100_orb(HP100_AUTO_MODE, MAC_CFG_3);	/* Autosel back on */
@@ -2591,10 +2585,8 @@
 	do {
 		if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0)
 			break;
-		if (!in_interrupt()) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
-		}
+		if (!in_interrupt())
+			schedule_timeout_interruptible(1);
 	} while (time_after(time, jiffies));
 
 	if (time_before_eq(time, jiffies)) {
@@ -2606,10 +2598,8 @@
 
 	time = jiffies + (2 * HZ);	/* This seems to take a while.... */
 	do {
-		if (!in_interrupt()) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
-		}
+		if (!in_interrupt())
+			schedule_timeout_interruptible(1);
 	} while (time_after(time, jiffies));
 
 	return 0;
@@ -2659,10 +2649,8 @@
 		do {
 			if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST))
 				break;
-			if (!in_interrupt()) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(1);
-			}
+			if (!in_interrupt())
+				schedule_timeout_interruptible(1);
 		} while (time_after(time, jiffies));
 
 		/* Start an addressed training and optionally request promiscuous port */
@@ -2697,10 +2685,8 @@
 		do {
 			if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST)
 				break;
-			if (!in_interrupt()) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(1);
-			}
+			if (!in_interrupt())
+				schedule_timeout_interruptible(1);
 		} while (time_before(jiffies, time));
 
 		if (time_after_eq(jiffies, time)) {
@@ -2723,10 +2709,8 @@
 #endif
 					break;
 				}
-				if (!in_interrupt()) {
-					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(1);
-				}
+				if (!in_interrupt())
+					schedule_timeout_interruptible(1);
 			} while (time_after(time, jiffies));
 		}
 
diff --git a/drivers/net/ibm_emac/Makefile b/drivers/net/ibm_emac/Makefile
index 7f583a3..f98ddf0 100644
--- a/drivers/net/ibm_emac/Makefile
+++ b/drivers/net/ibm_emac/Makefile
@@ -1,12 +1,11 @@
 #
-# Makefile for the IBM PPC4xx EMAC controllers
+# Makefile for the PowerPC 4xx on-chip ethernet driver
 #
 
 obj-$(CONFIG_IBM_EMAC) += ibm_emac.o
 
-ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o
-
-# Only need this if you want to see additional debug messages
-ifeq ($(CONFIG_IBM_EMAC_ERRMSG), y)
-ibm_emac-objs += ibm_emac_debug.o
-endif
+ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o 
+ibm_emac-$(CONFIG_IBM_EMAC_ZMII) += ibm_emac_zmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_RGMII) += ibm_emac_rgmii.o
+ibm_emac-$(CONFIG_IBM_EMAC_TAH) += ibm_emac_tah.o
+ibm_emac-$(CONFIG_IBM_EMAC_DEBUG) += ibm_emac_debug.o
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 15d5a0e..28c476f 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -1,110 +1,142 @@
 /*
- * ibm_emac.h
+ * drivers/net/ibm_emac/ibm_emac.h
  *
+ * Register definitions for PowerPC 4xx on-chip ethernet contoller
  *
- *      Armin Kuster akuster@mvista.com
- *      June, 2002
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  *
- * Copyright 2002 MontaVista Softare Inc.
+ * Based on original work by
+ *      Matt Porter <mporter@kernel.crashing.org>
+ *      Armin Kuster <akuster@mvista.com>
+ * 	Copyright 2002-2004 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 as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
+ *
  */
+#ifndef __IBM_EMAC_H_
+#define __IBM_EMAC_H_
 
-#ifndef _IBM_EMAC_H_
-#define _IBM_EMAC_H_
-/* General defines needed for the driver */
+#include <linux/config.h>
+#include <linux/types.h>
 
-/* Emac */
-typedef struct emac_regs {
-	u32 em0mr0;
-	u32 em0mr1;
-	u32 em0tmr0;
-	u32 em0tmr1;
-	u32 em0rmr;
-	u32 em0isr;
-	u32 em0iser;
-	u32 em0iahr;
-	u32 em0ialr;
-	u32 em0vtpid;
-	u32 em0vtci;
-	u32 em0ptr;
-	u32 em0iaht1;
-	u32 em0iaht2;
-	u32 em0iaht3;
-	u32 em0iaht4;
-	u32 em0gaht1;
-	u32 em0gaht2;
-	u32 em0gaht3;
-	u32 em0gaht4;
-	u32 em0lsah;
-	u32 em0lsal;
-	u32 em0ipgvr;
-	u32 em0stacr;
-	u32 em0trtr;
-	u32 em0rwmr;
-} emac_t;
+/* This is a simple check to prevent use of this driver on non-tested SoCs */
+#if !defined(CONFIG_405GP) && !defined(CONFIG_405GPR) && !defined(CONFIG_405EP) && \
+    !defined(CONFIG_440GP) && !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && \
+    !defined(CONFIG_440EP) && !defined(CONFIG_NP405H)
+#error	"Unknown SoC. Please, check chip user manual and make sure EMAC defines are OK"
+#endif
 
-/* MODE REG 0 */
-#define EMAC_M0_RXI			0x80000000
-#define EMAC_M0_TXI			0x40000000
-#define EMAC_M0_SRST			0x20000000
-#define EMAC_M0_TXE			0x10000000
-#define EMAC_M0_RXE			0x08000000
-#define EMAC_M0_WKE			0x04000000
+/* EMAC registers 		Write Access rules */
+struct emac_regs {
+	u32 mr0;		/* special 	*/
+	u32 mr1;		/* Reset 	*/
+	u32 tmr0;		/* special 	*/
+	u32 tmr1;		/* special 	*/
+	u32 rmr;		/* Reset 	*/
+	u32 isr;		/* Always 	*/
+	u32 iser;		/* Reset 	*/
+	u32 iahr;		/* Reset, R, T 	*/
+	u32 ialr;		/* Reset, R, T 	*/
+	u32 vtpid;		/* Reset, R, T 	*/
+	u32 vtci;		/* Reset, R, T 	*/
+	u32 ptr;		/* Reset,    T 	*/
+	u32 iaht1;		/* Reset, R	*/
+	u32 iaht2;		/* Reset, R	*/
+	u32 iaht3;		/* Reset, R	*/
+	u32 iaht4;		/* Reset, R	*/
+	u32 gaht1;		/* Reset, R	*/
+	u32 gaht2;		/* Reset, R	*/
+	u32 gaht3;		/* Reset, R	*/
+	u32 gaht4;		/* Reset, R	*/
+	u32 lsah;
+	u32 lsal;
+	u32 ipgvr;		/* Reset,    T 	*/
+	u32 stacr;		/* special 	*/
+	u32 trtr;		/* special 	*/
+	u32 rwmr;		/* Reset 	*/
+	u32 octx;
+	u32 ocrx;
+	u32 ipcr;
+};
 
-/* MODE Reg 1 */
-#define EMAC_M1_FDE			0x80000000
-#define EMAC_M1_ILE			0x40000000
-#define EMAC_M1_VLE			0x20000000
-#define EMAC_M1_EIFC			0x10000000
-#define EMAC_M1_APP			0x08000000
-#define EMAC_M1_AEMI			0x02000000
-#define EMAC_M1_IST			0x01000000
-#define EMAC_M1_MF_1000GPCS		0x00c00000	/* Internal GPCS */
-#define EMAC_M1_MF_1000MBPS		0x00800000	/* External GPCS */
-#define EMAC_M1_MF_100MBPS		0x00400000
-#define EMAC_M1_RFS_16K                 0x00280000	/* 000 for 512 byte */
-#define EMAC_M1_TR			0x00008000
-#ifdef CONFIG_IBM_EMAC4
-#define EMAC_M1_RFS_8K                  0x00200000
-#define EMAC_M1_RFS_4K                  0x00180000
-#define EMAC_M1_RFS_2K                  0x00100000
-#define EMAC_M1_RFS_1K                  0x00080000
-#define EMAC_M1_TX_FIFO_16K             0x00050000	/* 0's for 512 byte */
-#define EMAC_M1_TX_FIFO_8K              0x00040000
-#define EMAC_M1_TX_FIFO_4K              0x00030000
-#define EMAC_M1_TX_FIFO_2K              0x00020000
-#define EMAC_M1_TX_FIFO_1K              0x00010000
-#define EMAC_M1_TX_TR                   0x00008000
-#define EMAC_M1_TX_MWSW                 0x00001000	/* 0 wait for status */
-#define EMAC_M1_JUMBO_ENABLE            0x00000800	/* Upt to 9Kr status */
-#define EMAC_M1_OPB_CLK_66              0x00000008	/* 66Mhz */
-#define EMAC_M1_OPB_CLK_83              0x00000010	/* 83Mhz */
-#define EMAC_M1_OPB_CLK_100             0x00000018	/* 100Mhz */
-#define EMAC_M1_OPB_CLK_100P            0x00000020	/* 100Mhz+ */
-#else				/* CONFIG_IBM_EMAC4 */
-#define EMAC_M1_RFS_4K			0x00300000	/* ~4k for 512 byte */
-#define EMAC_M1_RFS_2K			0x00200000
-#define EMAC_M1_RFS_1K			0x00100000
-#define EMAC_M1_TX_FIFO_2K		0x00080000	/* 0's for 512 byte */
-#define EMAC_M1_TX_FIFO_1K		0x00040000
-#define EMAC_M1_TR0_DEPEND		0x00010000	/* 0'x for single packet */
-#define EMAC_M1_TR1_DEPEND		0x00004000
-#define EMAC_M1_TR1_MULTI		0x00002000
-#define EMAC_M1_JUMBO_ENABLE		0x00001000
-#endif				/* CONFIG_IBM_EMAC4 */
-#define EMAC_M1_BASE			(EMAC_M1_TX_FIFO_2K | \
-					EMAC_M1_APP | \
-					EMAC_M1_TR | EMAC_M1_VLE)
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_ETHTOOL_REGS_VER		0
+#define EMAC_ETHTOOL_REGS_SIZE		(sizeof(struct emac_regs) - sizeof(u32))
+#else
+#define EMAC_ETHTOOL_REGS_VER		1
+#define EMAC_ETHTOOL_REGS_SIZE		sizeof(struct emac_regs)
+#endif
 
-/* Transmit Mode Register 0 */
-#define EMAC_TMR0_GNP0			0x80000000
-#define EMAC_TMR0_GNP1			0x40000000
-#define EMAC_TMR0_GNPD			0x20000000
-#define EMAC_TMR0_FC			0x10000000
+/* EMACx_MR0 */
+#define EMAC_MR0_RXI			0x80000000
+#define EMAC_MR0_TXI			0x40000000
+#define EMAC_MR0_SRST			0x20000000
+#define EMAC_MR0_TXE			0x10000000
+#define EMAC_MR0_RXE			0x08000000
+#define EMAC_MR0_WKE			0x04000000
+
+/* EMACx_MR1 */
+#define EMAC_MR1_FDE			0x80000000
+#define EMAC_MR1_ILE			0x40000000
+#define EMAC_MR1_VLE			0x20000000
+#define EMAC_MR1_EIFC			0x10000000
+#define EMAC_MR1_APP			0x08000000
+#define EMAC_MR1_IST			0x01000000
+
+#define EMAC_MR1_MF_MASK		0x00c00000
+#define EMAC_MR1_MF_10			0x00000000
+#define EMAC_MR1_MF_100			0x00400000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_MR1_MF_1000		0x00000000
+#define EMAC_MR1_MF_1000GPCS		0x00000000
+#define EMAC_MR1_MF_IPPA(id)		0x00000000
+#else
+#define EMAC_MR1_MF_1000		0x00800000
+#define EMAC_MR1_MF_1000GPCS		0x00c00000
+#define EMAC_MR1_MF_IPPA(id)		(((id) & 0x1f) << 6)
+#endif
+
+#define EMAC_TX_FIFO_SIZE		2048
+
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_MR1_RFS_4K			0x00300000
+#define EMAC_MR1_RFS_16K		0x00000000
+#define EMAC_RX_FIFO_SIZE(gige)		4096
+#define EMAC_MR1_TFS_2K			0x00080000
+#define EMAC_MR1_TR0_MULT		0x00008000
+#define EMAC_MR1_JPSM			0x00000000
+#define EMAC_MR1_BASE(opb)		(EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT)
+#else
+#define EMAC_MR1_RFS_4K			0x00180000
+#define EMAC_MR1_RFS_16K		0x00280000
+#define EMAC_RX_FIFO_SIZE(gige)		((gige) ? 16384 : 4096)
+#define EMAC_MR1_TFS_2K			0x00020000
+#define EMAC_MR1_TR			0x00008000
+#define EMAC_MR1_MWSW_001		0x00001000
+#define EMAC_MR1_JPSM			0x00000800
+#define EMAC_MR1_OBCI_MASK		0x00000038
+#define EMAC_MR1_OBCI_50		0x00000000
+#define EMAC_MR1_OBCI_66		0x00000008
+#define EMAC_MR1_OBCI_83		0x00000010
+#define EMAC_MR1_OBCI_100		0x00000018
+#define EMAC_MR1_OBCI_100P		0x00000020
+#define EMAC_MR1_OBCI(freq)		((freq) <= 50  ? EMAC_MR1_OBCI_50 : \
+					 (freq) <= 66  ? EMAC_MR1_OBCI_66 : \
+					 (freq) <= 83  ? EMAC_MR1_OBCI_83 : \
+					 (freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P)
+#define EMAC_MR1_BASE(opb)		(EMAC_MR1_TFS_2K | EMAC_MR1_TR | \
+					 EMAC_MR1_MWSW_001 | EMAC_MR1_OBCI(opb))
+#endif
+
+/* EMACx_TMR0 */
+#define EMAC_TMR0_GNP			0x80000000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_TMR0_DEFAULT		0x00000000	
+#else
 #define EMAC_TMR0_TFAE_2_32		0x00000001
 #define EMAC_TMR0_TFAE_4_64		0x00000002
 #define EMAC_TMR0_TFAE_8_128		0x00000003
@@ -112,14 +144,36 @@
 #define EMAC_TMR0_TFAE_32_512		0x00000005
 #define EMAC_TMR0_TFAE_64_1024		0x00000006
 #define EMAC_TMR0_TFAE_128_2048		0x00000007
+#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_2_32
+#endif
+#define EMAC_TMR0_XMIT			(EMAC_TMR0_GNP | EMAC_TMR0_DEFAULT)
 
-/* Receive Mode Register */
+/* EMACx_TMR1 */
+
+/* IBM manuals are not very clear here. 
+ * This is my interpretation of how things are. --ebs
+ */
+#if defined(CONFIG_40x)
+#define EMAC_FIFO_ENTRY_SIZE		8
+#define EMAC_MAL_BURST_SIZE		(16 * 4)
+#else
+#define EMAC_FIFO_ENTRY_SIZE		16
+#define EMAC_MAL_BURST_SIZE		(64 * 4)
+#endif
+
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_TMR1(l,h)			(((l) << 27) | (((h) & 0xff) << 16))
+#else
+#define EMAC_TMR1(l,h)			(((l) << 27) | (((h) & 0x3ff) << 14))
+#endif
+
+/* EMACx_RMR */
 #define EMAC_RMR_SP			0x80000000
 #define EMAC_RMR_SFCS			0x40000000
-#define EMAC_RMR_ARRP			0x20000000
-#define EMAC_RMR_ARP			0x10000000
-#define EMAC_RMR_AROP			0x08000000
-#define EMAC_RMR_ARPI			0x04000000
+#define EMAC_RMR_RRP			0x20000000
+#define EMAC_RMR_RFP			0x10000000
+#define EMAC_RMR_ROP			0x08000000
+#define EMAC_RMR_RPIR			0x04000000
 #define EMAC_RMR_PPP			0x02000000
 #define EMAC_RMR_PME			0x01000000
 #define EMAC_RMR_PMME			0x00800000
@@ -127,6 +181,9 @@
 #define EMAC_RMR_MIAE			0x00200000
 #define EMAC_RMR_BAE			0x00100000
 #define EMAC_RMR_MAE			0x00080000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_RMR_BASE			0x00000000
+#else
 #define EMAC_RMR_RFAF_2_32		0x00000001
 #define EMAC_RMR_RFAF_4_64		0x00000002
 #define EMAC_RMR_RFAF_8_128		0x00000003
@@ -134,9 +191,21 @@
 #define EMAC_RMR_RFAF_32_512		0x00000005
 #define EMAC_RMR_RFAF_64_1024		0x00000006
 #define EMAC_RMR_RFAF_128_2048		0x00000007
-#define EMAC_RMR_BASE			(EMAC_RMR_IAE | EMAC_RMR_BAE)
+#define EMAC_RMR_BASE			EMAC_RMR_RFAF_128_2048
+#endif
 
-/* Interrupt Status & enable Regs */
+/* EMACx_ISR & EMACx_ISER */
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_ISR_TXPE			0x00000000
+#define EMAC_ISR_RXPE			0x00000000
+#define EMAC_ISR_TXUE			0x00000000
+#define EMAC_ISR_RXOE			0x00000000
+#else
+#define EMAC_ISR_TXPE			0x20000000
+#define EMAC_ISR_RXPE			0x10000000
+#define EMAC_ISR_TXUE			0x08000000
+#define EMAC_ISR_RXOE			0x04000000
+#endif
 #define EMAC_ISR_OVR			0x02000000
 #define EMAC_ISR_PP			0x01000000
 #define EMAC_ISR_BP			0x00800000
@@ -147,53 +216,62 @@
 #define EMAC_ISR_PTLE			0x00040000
 #define EMAC_ISR_ORE			0x00020000
 #define EMAC_ISR_IRE			0x00010000
-#define EMAC_ISR_DBDM			0x00000200
-#define EMAC_ISR_DB0			0x00000100
-#define EMAC_ISR_SE0			0x00000080
-#define EMAC_ISR_TE0			0x00000040
-#define EMAC_ISR_DB1			0x00000020
-#define EMAC_ISR_SE1			0x00000010
-#define EMAC_ISR_TE1			0x00000008
+#define EMAC_ISR_SQE			0x00000080
+#define EMAC_ISR_TE			0x00000040
 #define EMAC_ISR_MOS			0x00000002
 #define EMAC_ISR_MOF			0x00000001
 
-/* STA CONTROL REG */
+/* EMACx_STACR */
+#define EMAC_STACR_PHYD_MASK		0xffff
+#define EMAC_STACR_PHYD_SHIFT		16
 #define EMAC_STACR_OC			0x00008000
 #define EMAC_STACR_PHYE			0x00004000
-#define EMAC_STACR_WRITE		0x00002000
-#define EMAC_STACR_READ			0x00001000
-#define EMAC_STACR_CLK_83MHZ		0x00000800	/* 0's for 50Mhz */
-#define EMAC_STACR_CLK_66MHZ		0x00000400
-#define EMAC_STACR_CLK_100MHZ		0x00000C00
+#define EMAC_STACR_STAC_MASK		0x00003000
+#define EMAC_STACR_STAC_READ		0x00001000
+#define EMAC_STACR_STAC_WRITE		0x00002000
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_STACR_OPBC_MASK		0x00000C00
+#define EMAC_STACR_OPBC_50		0x00000000
+#define EMAC_STACR_OPBC_66		0x00000400
+#define EMAC_STACR_OPBC_83		0x00000800
+#define EMAC_STACR_OPBC_100		0x00000C00
+#define EMAC_STACR_OPBC(freq)		((freq) <= 50 ? EMAC_STACR_OPBC_50 : \
+					 (freq) <= 66 ? EMAC_STACR_OPBC_66 : \
+					 (freq) <= 83 ? EMAC_STACR_OPBC_83 : EMAC_STACR_OPBC_100)
+#define EMAC_STACR_BASE(opb)		EMAC_STACR_OPBC(opb)
+#else
+#define EMAC_STACR_BASE(opb)		0x00000000
+#endif
+#define EMAC_STACR_PCDA_MASK		0x1f
+#define EMAC_STACR_PCDA_SHIFT		5
+#define EMAC_STACR_PRA_MASK		0x1f
 
-/* Transmit Request Threshold Register */
-#define EMAC_TRTR_1600			0x18000000	/* 0's for 64 Bytes */
-#define EMAC_TRTR_1024			0x0f000000
-#define EMAC_TRTR_512			0x07000000
-#define EMAC_TRTR_256			0x03000000
-#define EMAC_TRTR_192			0x10000000
-#define EMAC_TRTR_128			0x01000000
+/* EMACx_TRTR */
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_TRTR_SHIFT			27
+#else
+#define EMAC_TRTR_SHIFT			24
+#endif
+#define EMAC_TRTR(size)			((((size) >> 6) - 1) << EMAC_TRTR_SHIFT)
 
+/* EMACx_RWMR */
+#if !defined(CONFIG_IBM_EMAC4)
+#define EMAC_RWMR(l,h)			(((l) << 23) | ( ((h) & 0x1ff) << 7))	
+#else
+#define EMAC_RWMR(l,h)			(((l) << 22) | ( ((h) & 0x3ff) << 6))	
+#endif
+
+/* EMAC specific TX descriptor control fields (write access) */
 #define EMAC_TX_CTRL_GFCS		0x0200
 #define EMAC_TX_CTRL_GP			0x0100
 #define EMAC_TX_CTRL_ISA		0x0080
 #define EMAC_TX_CTRL_RSA		0x0040
 #define EMAC_TX_CTRL_IVT		0x0020
 #define EMAC_TX_CTRL_RVT		0x0010
-#define EMAC_TX_CTRL_TAH_CSUM		0x000e	/* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG4		0x000a	/* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG3		0x0008	/* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG2		0x0006	/* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG1		0x0004	/* TAH only */
-#define EMAC_TX_CTRL_TAH_SEG0		0x0002	/* TAH only */
-#define EMAC_TX_CTRL_TAH_DIS		0x0000	/* TAH only */
+#define EMAC_TX_CTRL_TAH_CSUM		0x000e
 
-#define EMAC_TX_CTRL_DFLT ( \
-	MAL_TX_CTRL_INTR | EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP )
-
-/* madmal transmit status / Control bits */
+/* EMAC specific TX descriptor status fields (read access) */
 #define EMAC_TX_ST_BFCS			0x0200
-#define EMAC_TX_ST_BPP			0x0100
 #define EMAC_TX_ST_LCS			0x0080
 #define EMAC_TX_ST_ED			0x0040
 #define EMAC_TX_ST_EC			0x0020
@@ -202,8 +280,16 @@
 #define EMAC_TX_ST_SC			0x0004
 #define EMAC_TX_ST_UR			0x0002
 #define EMAC_TX_ST_SQE			0x0001
+#if !defined(CONFIG_IBM_EMAC_TAH)
+#define EMAC_IS_BAD_TX(v)		((v) & (EMAC_TX_ST_LCS | EMAC_TX_ST_ED | \
+					 EMAC_TX_ST_EC | EMAC_TX_ST_LC | \
+					 EMAC_TX_ST_MC | EMAC_TX_ST_UR))
+#else
+#define EMAC_IS_BAD_TX(v)		((v) & (EMAC_TX_ST_LCS | EMAC_TX_ST_ED | \
+					 EMAC_TX_ST_EC | EMAC_TX_ST_LC))
+#endif					 
 
-/* madmal receive status / Control bits */
+/* EMAC specific RX descriptor status fields (read access) */
 #define EMAC_RX_ST_OE			0x0200
 #define EMAC_RX_ST_PP			0x0100
 #define EMAC_RX_ST_BP			0x0080
@@ -214,54 +300,10 @@
 #define EMAC_RX_ST_PTL			0x0004
 #define EMAC_RX_ST_ORE			0x0002
 #define EMAC_RX_ST_IRE			0x0001
-#define EMAC_BAD_RX_PACKET		0x02ff
-#define EMAC_CSUM_VER_ERROR		0x0003
-
-/* identify a bad rx packet dependent on emac features */
-#ifdef CONFIG_IBM_EMAC4
-#define EMAC_IS_BAD_RX_PACKET(desc) \
-	(((desc & (EMAC_BAD_RX_PACKET & ~EMAC_CSUM_VER_ERROR)) || \
-	((desc & EMAC_CSUM_VER_ERROR) == EMAC_RX_ST_ORE) || \
-	((desc & EMAC_CSUM_VER_ERROR) == EMAC_RX_ST_IRE)))
-#else
-#define EMAC_IS_BAD_RX_PACKET(desc) \
-	 (desc & EMAC_BAD_RX_PACKET)
-#endif
-
-/* SoC implementation specific EMAC register defaults */
-#if defined(CONFIG_440GP)
-#define EMAC_RWMR_DEFAULT		0x80009000
-#define EMAC_TMR0_DEFAULT		0x00000000
-#define EMAC_TMR1_DEFAULT		0xf8640000
-#elif defined(CONFIG_440GX)
-#define EMAC_RWMR_DEFAULT		0x1000a200
-#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_2_32
-#define EMAC_TMR1_DEFAULT		0xa00f0000
-#elif defined(CONFIG_440SP)
-#define EMAC_RWMR_DEFAULT		0x08002000
-#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_128_2048
-#define EMAC_TMR1_DEFAULT		0xf8200000
-#else
-#define EMAC_RWMR_DEFAULT		0x0f002000
-#define EMAC_TMR0_DEFAULT		0x00000000
-#define EMAC_TMR1_DEFAULT		0x380f0000
-#endif				/* CONFIG_440GP */
-
-/* Revision specific EMAC register defaults */
-#ifdef CONFIG_IBM_EMAC4
-#define EMAC_M1_DEFAULT			(EMAC_M1_BASE | \
-					EMAC_M1_OPB_CLK_83 | \
-					EMAC_M1_TX_MWSW)
-#define EMAC_RMR_DEFAULT		(EMAC_RMR_BASE | \
-					EMAC_RMR_RFAF_128_2048)
-#define EMAC_TMR0_XMIT			(EMAC_TMR0_GNP0 | \
-					EMAC_TMR0_DEFAULT)
-#define EMAC_TRTR_DEFAULT		EMAC_TRTR_1024
-#else				/* !CONFIG_IBM_EMAC4 */
-#define EMAC_M1_DEFAULT			EMAC_M1_BASE
-#define EMAC_RMR_DEFAULT		EMAC_RMR_BASE
-#define EMAC_TMR0_XMIT			EMAC_TMR0_GNP0
-#define EMAC_TRTR_DEFAULT		EMAC_TRTR_1600
-#endif				/* CONFIG_IBM_EMAC4 */
-
-#endif
+#define EMAC_RX_TAH_BAD_CSUM		0x0003
+#define EMAC_BAD_RX_MASK		(EMAC_RX_ST_OE | EMAC_RX_ST_BP | \
+					 EMAC_RX_ST_RP | EMAC_RX_ST_SE | \
+					 EMAC_RX_ST_AE | EMAC_RX_ST_BFCS | \
+					 EMAC_RX_ST_PTL | EMAC_RX_ST_ORE | \
+					 EMAC_RX_ST_IRE )
+#endif /* __IBM_EMAC_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 14e9b631..943fbd1 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1,13 +1,14 @@
 /*
- * ibm_emac_core.c
+ * drivers/net/ibm_emac/ibm_emac_core.c
  *
- * Ethernet driver for the built in ethernet on the IBM 4xx PowerPC
- * processors.
- * 
- * (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Driver for PowerPC 4xx on-chip ethernet controller.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  *
  * Based on original work by
- *
+ * 	Matt Porter <mporter@kernel.crashing.org>
+ *	(c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
  *      Armin Kuster <akuster@mvista.com>
  * 	Johnnie Peters <jpeters@mvista.com>
  *
@@ -15,29 +16,24 @@
  * 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.
- * TODO
- *       - Check for races in the "remove" code path
- *       - Add some Power Management to the MAC and the PHY
- *       - Audit remaining of non-rewritten code (--BenH)
- *       - Cleanup message display using msglevel mecanism
- *       - Address all errata
- *       - Audit all register update paths to ensure they
- *         are being written post soft reset if required.
+ *
  */
+
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/bitops.h>
@@ -45,1691 +41,1893 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/ocp.h>
 
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/crc32.h>
-
 #include "ibm_emac_core.h"
-
-//#define MDIO_DEBUG(fmt) printk fmt
-#define MDIO_DEBUG(fmt)
-
-//#define LINK_DEBUG(fmt) printk fmt
-#define LINK_DEBUG(fmt)
-
-//#define PKT_DEBUG(fmt) printk fmt
-#define PKT_DEBUG(fmt)
-
-#define DRV_NAME        "emac"
-#define DRV_VERSION     "2.0"
-#define DRV_AUTHOR      "Benjamin Herrenschmidt <benh@kernel.crashing.org>"
-#define DRV_DESC        "IBM EMAC Ethernet driver"
+#include "ibm_emac_debug.h"
 
 /*
- * When mdio_idx >= 0, contains a list of emac ocp_devs
- * that have had their initialization deferred until the
- * common MDIO controller has been initialized.
+ * Lack of dma_unmap_???? calls is intentional.
+ *
+ * API-correct usage requires additional support state information to be 
+ * maintained for every RX and TX buffer descriptor (BD). Unfortunately, due to
+ * EMAC design (e.g. TX buffer passed from network stack can be split into
+ * several BDs, dma_map_single/dma_map_page can be used to map particular BD),
+ * maintaining such information will add additional overhead.
+ * Current DMA API implementation for 4xx processors only ensures cache coherency
+ * and dma_unmap_???? routines are empty and are likely to stay this way.
+ * I decided to omit dma_unmap_??? calls because I don't want to add additional
+ * complexity just for the sake of following some abstract API, when it doesn't
+ * add any real benefit to the driver. I understand that this decision maybe 
+ * controversial, but I really tried to make code API-correct and efficient 
+ * at the same time and didn't come up with code I liked :(.                --ebs
  */
-LIST_HEAD(emac_init_list);
 
-MODULE_AUTHOR(DRV_AUTHOR);
+#define DRV_NAME        "emac"
+#define DRV_VERSION     "3.53"
+#define DRV_DESC        "PPC 4xx OCP EMAC driver"
+
 MODULE_DESCRIPTION(DRV_DESC);
+MODULE_AUTHOR
+    ("Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>");
 MODULE_LICENSE("GPL");
 
-static int skb_res = SKB_RES;
-module_param(skb_res, int, 0444);
-MODULE_PARM_DESC(skb_res, "Amount of data to reserve on skb buffs\n"
-		 "The 405 handles a misaligned IP header fine but\n"
-		 "this can help if you are routing to a tunnel or a\n"
-		 "device that needs aligned data. 0..2");
+/* minimum number of free TX descriptors required to wake up TX process */
+#define EMAC_TX_WAKEUP_THRESH		(NUM_TX_BUFF / 4)
 
-#define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev))
-
-static unsigned int rgmii_enable[] = {
-	RGMII_RTBI,
-	RGMII_RGMII,
-	RGMII_TBI,
-	RGMII_GMII
-};
-
-static unsigned int rgmii_speed_mask[] = {
-	RGMII_MII2_SPDMASK,
-	RGMII_MII3_SPDMASK
-};
-
-static unsigned int rgmii_speed100[] = {
-	RGMII_MII2_100MB,
-	RGMII_MII3_100MB
-};
-
-static unsigned int rgmii_speed1000[] = {
-	RGMII_MII2_1000MB,
-	RGMII_MII3_1000MB
-};
-
-#define ZMII_PRIV(ocpdev) ((struct ibm_ocp_zmii*)ocp_get_drvdata(ocpdev))
-
-static unsigned int zmii_enable[][4] = {
-	{ZMII_SMII0, ZMII_RMII0, ZMII_MII0,
-	 ~(ZMII_MDI1 | ZMII_MDI2 | ZMII_MDI3)},
-	{ZMII_SMII1, ZMII_RMII1, ZMII_MII1,
-	 ~(ZMII_MDI0 | ZMII_MDI2 | ZMII_MDI3)},
-	{ZMII_SMII2, ZMII_RMII2, ZMII_MII2,
-	 ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)},
-	{ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)}
-};
-
-static unsigned int mdi_enable[] = {
-	ZMII_MDI0,
-	ZMII_MDI1,
-	ZMII_MDI2,
-	ZMII_MDI3
-};
-
-static unsigned int zmii_speed = 0x0;
-static unsigned int zmii_speed100[] = {
-	ZMII_MII0_100MB,
-	ZMII_MII1_100MB,
-	ZMII_MII2_100MB,
-	ZMII_MII3_100MB
-};
+/* If packet size is less than this number, we allocate small skb and copy packet 
+ * contents into it instead of just sending original big skb up
+ */
+#define EMAC_RX_COPY_THRESH		CONFIG_IBM_EMAC_RX_COPY_THRESHOLD
 
 /* Since multiple EMACs share MDIO lines in various ways, we need
  * to avoid re-using the same PHY ID in cases where the arch didn't
  * setup precise phy_map entries
  */
-static u32 busy_phy_map = 0;
+static u32 busy_phy_map;
 
-/* If EMACs share a common MDIO device, this points to it */
-static struct net_device *mdio_ndev = NULL;
-
-struct emac_def_dev {
-	struct list_head link;
-	struct ocp_device *ocpdev;
-	struct ibm_ocp_mal *mal;
-};
-
-static struct net_device_stats *emac_stats(struct net_device *dev)
-{
-	struct ocp_enet_private *fep = dev->priv;
-	return &fep->stats;
-};
-
-static int
-emac_init_rgmii(struct ocp_device *rgmii_dev, int input, int phy_mode)
-{
-	struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(rgmii_dev);
-	const char *mode_name[] = { "RTBI", "RGMII", "TBI", "GMII" };
-	int mode = -1;
-
-	if (!rgmii) {
-		rgmii = kmalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
-
-		if (rgmii == NULL) {
-			printk(KERN_ERR
-			       "rgmii%d: Out of memory allocating RGMII structure!\n",
-			       rgmii_dev->def->index);
-			return -ENOMEM;
-		}
-
-		memset(rgmii, 0, sizeof(*rgmii));
-
-		rgmii->base =
-		    (struct rgmii_regs *)ioremap(rgmii_dev->def->paddr,
-						 sizeof(*rgmii->base));
-		if (rgmii->base == NULL) {
-			printk(KERN_ERR
-			       "rgmii%d: Cannot ioremap bridge registers!\n",
-			       rgmii_dev->def->index);
-
-			kfree(rgmii);
-			return -ENOMEM;
-		}
-		ocp_set_drvdata(rgmii_dev, rgmii);
-	}
-
-	if (phy_mode) {
-		switch (phy_mode) {
-		case PHY_MODE_GMII:
-			mode = GMII;
-			break;
-		case PHY_MODE_TBI:
-			mode = TBI;
-			break;
-		case PHY_MODE_RTBI:
-			mode = RTBI;
-			break;
-		case PHY_MODE_RGMII:
-		default:
-			mode = RGMII;
-		}
-		rgmii->base->fer &= ~RGMII_FER_MASK(input);
-		rgmii->base->fer |= rgmii_enable[mode] << (4 * input);
-	} else {
-		switch ((rgmii->base->fer & RGMII_FER_MASK(input)) >> (4 *
-								       input)) {
-		case RGMII_RTBI:
-			mode = RTBI;
-			break;
-		case RGMII_RGMII:
-			mode = RGMII;
-			break;
-		case RGMII_TBI:
-			mode = TBI;
-			break;
-		case RGMII_GMII:
-			mode = GMII;
-		}
-	}
-
-	/* Set mode to RGMII if nothing valid is detected */
-	if (mode < 0)
-		mode = RGMII;
-
-	printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
-	       rgmii_dev->def->index, input, mode_name[mode]);
-
-	rgmii->mode[input] = mode;
-	rgmii->users++;
-
-	return 0;
-}
-
-static void
-emac_rgmii_port_speed(struct ocp_device *ocpdev, int input, int speed)
-{
-	struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev);
-	unsigned int rgmii_speed;
-
-	rgmii_speed = in_be32(&rgmii->base->ssr);
-
-	rgmii_speed &= ~rgmii_speed_mask[input];
-
-	if (speed == 1000)
-		rgmii_speed |= rgmii_speed1000[input];
-	else if (speed == 100)
-		rgmii_speed |= rgmii_speed100[input];
-
-	out_be32(&rgmii->base->ssr, rgmii_speed);
-}
-
-static void emac_close_rgmii(struct ocp_device *ocpdev)
-{
-	struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev);
-	BUG_ON(!rgmii || rgmii->users == 0);
-
-	if (!--rgmii->users) {
-		ocp_set_drvdata(ocpdev, NULL);
-		iounmap((void *)rgmii->base);
-		kfree(rgmii);
-	}
-}
-
-static int emac_init_zmii(struct ocp_device *zmii_dev, int input, int phy_mode)
-{
-	struct ibm_ocp_zmii *zmii = ZMII_PRIV(zmii_dev);
-	const char *mode_name[] = { "SMII", "RMII", "MII" };
-	int mode = -1;
-
-	if (!zmii) {
-		zmii = kmalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL);
-		if (zmii == NULL) {
-			printk(KERN_ERR
-			       "zmii%d: Out of memory allocating ZMII structure!\n",
-			       zmii_dev->def->index);
-			return -ENOMEM;
-		}
-		memset(zmii, 0, sizeof(*zmii));
-
-		zmii->base =
-		    (struct zmii_regs *)ioremap(zmii_dev->def->paddr,
-						sizeof(*zmii->base));
-		if (zmii->base == NULL) {
-			printk(KERN_ERR
-			       "zmii%d: Cannot ioremap bridge registers!\n",
-			       zmii_dev->def->index);
-
-			kfree(zmii);
-			return -ENOMEM;
-		}
-		ocp_set_drvdata(zmii_dev, zmii);
-	}
-
-	if (phy_mode) {
-		switch (phy_mode) {
-		case PHY_MODE_MII:
-			mode = MII;
-			break;
-		case PHY_MODE_RMII:
-			mode = RMII;
-			break;
-		case PHY_MODE_SMII:
-		default:
-			mode = SMII;
-		}
-		zmii->base->fer &= ~ZMII_FER_MASK(input);
-		zmii->base->fer |= zmii_enable[input][mode];
-	} else {
-		switch ((zmii->base->fer & ZMII_FER_MASK(input)) << (4 * input)) {
-		case ZMII_MII0:
-			mode = MII;
-			break;
-		case ZMII_RMII0:
-			mode = RMII;
-			break;
-		case ZMII_SMII0:
-			mode = SMII;
-		}
-	}
-
-	/* Set mode to SMII if nothing valid is detected */
-	if (mode < 0)
-		mode = SMII;
-
-	printk(KERN_NOTICE "zmii%d: input %d in %s mode\n",
-	       zmii_dev->def->index, input, mode_name[mode]);
-
-	zmii->mode[input] = mode;
-	zmii->users++;
-
-	return 0;
-}
-
-static void emac_enable_zmii_port(struct ocp_device *ocpdev, int input)
-{
-	u32 mask;
-	struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
-
-	mask = in_be32(&zmii->base->fer);
-	mask &= zmii_enable[input][MDI];	/* turn all non enabled MDI's off */
-	mask |= zmii_enable[input][zmii->mode[input]] | mdi_enable[input];
-	out_be32(&zmii->base->fer, mask);
-}
-
-static void
-emac_zmii_port_speed(struct ocp_device *ocpdev, int input, int speed)
-{
-	struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
-
-	if (speed == 100)
-		zmii_speed |= zmii_speed100[input];
-	else
-		zmii_speed &= ~zmii_speed100[input];
-
-	out_be32(&zmii->base->ssr, zmii_speed);
-}
-
-static void emac_close_zmii(struct ocp_device *ocpdev)
-{
-	struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev);
-	BUG_ON(!zmii || zmii->users == 0);
-
-	if (!--zmii->users) {
-		ocp_set_drvdata(ocpdev, NULL);
-		iounmap((void *)zmii->base);
-		kfree(zmii);
-	}
-}
-
-int emac_phy_read(struct net_device *dev, int mii_id, int reg)
-{
-	int count;
-	uint32_t stacr;
-	struct ocp_enet_private *fep = dev->priv;
-	emac_t *emacp = fep->emacp;
-
-	MDIO_DEBUG(("%s: phy_read, id: 0x%x, reg: 0x%x\n", dev->name, mii_id,
-		    reg));
-
-	/* Enable proper ZMII port */
-	if (fep->zmii_dev)
-		emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input);
-
-	/* Use the EMAC that has the MDIO port */
-	if (fep->mdio_dev) {
-		dev = fep->mdio_dev;
-		fep = dev->priv;
-		emacp = fep->emacp;
-	}
-
-	count = 0;
-	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
-					&& (count++ < MDIO_DELAY))
-		udelay(1);
-	MDIO_DEBUG((" (count was %d)\n", count));
-
-	if ((stacr & EMAC_STACR_OC) == 0) {
-		printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name);
-		return -1;
-	}
-
-	/* Clear the speed bits and make a read request to the PHY */
-	stacr = ((EMAC_STACR_READ | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ);
-	stacr |= ((mii_id & 0x1F) << 5);
-
-	out_be32(&emacp->em0stacr, stacr);
-
-	count = 0;
-	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
-					&& (count++ < MDIO_DELAY))
-		udelay(1);
-	MDIO_DEBUG((" (count was %d)\n", count));
-
-	if ((stacr & EMAC_STACR_OC) == 0) {
-		printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name);
-		return -1;
-	}
-
-	/* Check for a read error */
-	if (stacr & EMAC_STACR_PHYE) {
-		MDIO_DEBUG(("EMAC MDIO PHY error !\n"));
-		return -1;
-	}
-
-	MDIO_DEBUG((" -> 0x%x\n", stacr >> 16));
-
-	return (stacr >> 16);
-}
-
-void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
-{
-	int count;
-	uint32_t stacr;
-	struct ocp_enet_private *fep = dev->priv;
-	emac_t *emacp = fep->emacp;
-
-	MDIO_DEBUG(("%s phy_write, id: 0x%x, reg: 0x%x, data: 0x%x\n",
-		    dev->name, mii_id, reg, data));
-
-	/* Enable proper ZMII port */
-	if (fep->zmii_dev)
-		emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input);
-
-	/* Use the EMAC that has the MDIO port */
-	if (fep->mdio_dev) {
-		dev = fep->mdio_dev;
-		fep = dev->priv;
-		emacp = fep->emacp;
-	}
-
-	count = 0;
-	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
-					&& (count++ < MDIO_DELAY))
-		udelay(1);
-	MDIO_DEBUG((" (count was %d)\n", count));
-
-	if ((stacr & EMAC_STACR_OC) == 0) {
-		printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
-		return;
-	}
-
-	/* Clear the speed bits and make a read request to the PHY */
-
-	stacr = ((EMAC_STACR_WRITE | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ);
-	stacr |= ((mii_id & 0x1f) << 5) | ((data & 0xffff) << 16);
-
-	out_be32(&emacp->em0stacr, stacr);
-
-	count = 0;
-	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
-					&& (count++ < MDIO_DELAY))
-		udelay(1);
-	MDIO_DEBUG((" (count was %d)\n", count));
-
-	if ((stacr & EMAC_STACR_OC) == 0)
-		printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
-
-	/* Check for a write error */
-	if ((stacr & EMAC_STACR_PHYE) != 0) {
-		MDIO_DEBUG(("EMAC MDIO PHY error !\n"));
-	}
-}
-
-static void emac_txeob_dev(void *param, u32 chanmask)
-{
-	struct net_device *dev = param;
-	struct ocp_enet_private *fep = dev->priv;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fep->lock, flags);
-
-	PKT_DEBUG(("emac_txeob_dev() entry, tx_cnt: %d\n", fep->tx_cnt));
-
-	while (fep->tx_cnt &&
-	       !(fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_READY)) {
-
-		if (fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_LAST) {
-			/* Tell the system the transmit completed. */
-			dma_unmap_single(&fep->ocpdev->dev,
-					 fep->tx_desc[fep->ack_slot].data_ptr,
-					 fep->tx_desc[fep->ack_slot].data_len,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb_irq(fep->tx_skb[fep->ack_slot]);
-
-			if (fep->tx_desc[fep->ack_slot].ctrl &
-			    (EMAC_TX_ST_EC | EMAC_TX_ST_MC | EMAC_TX_ST_SC))
-				fep->stats.collisions++;
-		}
-
-		fep->tx_skb[fep->ack_slot] = (struct sk_buff *)NULL;
-		if (++fep->ack_slot == NUM_TX_BUFF)
-			fep->ack_slot = 0;
-
-		fep->tx_cnt--;
-	}
-	if (fep->tx_cnt < NUM_TX_BUFF)
-		netif_wake_queue(dev);
-
-	PKT_DEBUG(("emac_txeob_dev() exit, tx_cnt: %d\n", fep->tx_cnt));
-
-	spin_unlock_irqrestore(&fep->lock, flags);
-}
-
-/*
-  Fill/Re-fill the rx chain with valid ctrl/ptrs.
-  This function will fill from rx_slot up to the parm end.
-  So to completely fill the chain pre-set rx_slot to 0 and
-  pass in an end of 0.
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX) && (defined(CONFIG_405EP) || defined(CONFIG_440EP))
+/* 405EP has "EMAC to PHY Control Register" (CPC0_EPCTL) which can help us
+ * with PHY RX clock problem.
+ * 440EP has more sane SDR0_MFR register implementation than 440GX, which
+ * also allows controlling each EMAC clock
  */
-static void emac_rx_fill(struct net_device *dev, int end)
+static inline void EMAC_RX_CLK_TX(int idx)
 {
-	int i;
-	struct ocp_enet_private *fep = dev->priv;
-
-	i = fep->rx_slot;
-	do {
-		/* We don't want the 16 bytes skb_reserve done by dev_alloc_skb,
-		 * it breaks our cache line alignement. However, we still allocate
-		 * +16 so that we end up allocating the exact same size as
-		 * dev_alloc_skb() would do.
-		 * Also, because of the skb_res, the max DMA size we give to EMAC
-		 * is slighly wrong, causing it to potentially DMA 2 more bytes
-		 * from a broken/oversized packet. These 16 bytes will take care
-		 * that we don't walk on somebody else toes with that.
-		 */
-		fep->rx_skb[i] =
-		    alloc_skb(fep->rx_buffer_size + 16, GFP_ATOMIC);
-
-		if (fep->rx_skb[i] == NULL) {
-			/* Keep rx_slot here, the next time clean/fill is called
-			 * we will try again before the MAL wraps back here
-			 * If the MAL tries to use this descriptor with
-			 * the EMPTY bit off it will cause the
-			 * rxde interrupt.  That is where we will
-			 * try again to allocate an sk_buff.
-			 */
-			break;
-
-		}
-
-		if (skb_res)
-			skb_reserve(fep->rx_skb[i], skb_res);
-
-		/* We must NOT dma_map_single the cache line right after the
-		 * buffer, so we must crop our sync size to account for the
-		 * reserved space
-		 */
-		fep->rx_desc[i].data_ptr =
-		    (unsigned char *)dma_map_single(&fep->ocpdev->dev,
-						    (void *)fep->rx_skb[i]->
-						    data,
-						    fep->rx_buffer_size -
-						    skb_res, DMA_FROM_DEVICE);
-
-		/*
-		 * Some 4xx implementations use the previously
-		 * reserved bits in data_len to encode the MS
-		 * 4-bits of a 36-bit physical address (ERPN)
-		 * This must be initialized.
-		 */
-		fep->rx_desc[i].data_len = 0;
-		fep->rx_desc[i].ctrl = MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR |
-		    (i == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
-
-	} while ((i = (i + 1) % NUM_RX_BUFF) != end);
-
-	fep->rx_slot = i;
-}
-
-static void
-emac_rx_csum(struct net_device *dev, unsigned short ctrl, struct sk_buff *skb)
-{
-	struct ocp_enet_private *fep = dev->priv;
-
-	/* Exit if interface has no TAH engine */
-	if (!fep->tah_dev) {
-		skb->ip_summed = CHECKSUM_NONE;
-		return;
-	}
-
-	/* Check for TCP/UDP/IP csum error */
-	if (ctrl & EMAC_CSUM_VER_ERROR) {
-		/* Let the stack verify checksum errors */
-		skb->ip_summed = CHECKSUM_NONE;
-/*		adapter->hw_csum_err++; */
-	} else {
-		/* Csum is good */
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-/*		adapter->hw_csum_good++; */
-	}
-}
-
-static int emac_rx_clean(struct net_device *dev)
-{
-	int i, b, bnum = 0, buf[6];
-	int error, frame_length;
-	struct ocp_enet_private *fep = dev->priv;
-	unsigned short ctrl;
-
-	i = fep->rx_slot;
-
-	PKT_DEBUG(("emac_rx_clean() entry, rx_slot: %d\n", fep->rx_slot));
-
-	do {
-		if (fep->rx_skb[i] == NULL)
-			continue;	/*we have already handled the packet but haved failed to alloc */
-		/* 
-		   since rx_desc is in uncached mem we don't keep reading it directly 
-		   we pull out a local copy of ctrl and do the checks on the copy.
-		 */
-		ctrl = fep->rx_desc[i].ctrl;
-		if (ctrl & MAL_RX_CTRL_EMPTY)
-			break;	/*we don't have any more ready packets */
-
-		if (EMAC_IS_BAD_RX_PACKET(ctrl)) {
-			fep->stats.rx_errors++;
-			fep->stats.rx_dropped++;
-
-			if (ctrl & EMAC_RX_ST_OE)
-				fep->stats.rx_fifo_errors++;
-			if (ctrl & EMAC_RX_ST_AE)
-				fep->stats.rx_frame_errors++;
-			if (ctrl & EMAC_RX_ST_BFCS)
-				fep->stats.rx_crc_errors++;
-			if (ctrl & (EMAC_RX_ST_RP | EMAC_RX_ST_PTL |
-				    EMAC_RX_ST_ORE | EMAC_RX_ST_IRE))
-				fep->stats.rx_length_errors++;
-		} else {
-			if ((ctrl & (MAL_RX_CTRL_FIRST | MAL_RX_CTRL_LAST)) ==
-			    (MAL_RX_CTRL_FIRST | MAL_RX_CTRL_LAST)) {
-				/* Single descriptor packet */
-				emac_rx_csum(dev, ctrl, fep->rx_skb[i]);
-				/* Send the skb up the chain. */
-				frame_length = fep->rx_desc[i].data_len - 4;
-				skb_put(fep->rx_skb[i], frame_length);
-				fep->rx_skb[i]->dev = dev;
-				fep->rx_skb[i]->protocol =
-				    eth_type_trans(fep->rx_skb[i], dev);
-				error = netif_rx(fep->rx_skb[i]);
-
-				if ((error == NET_RX_DROP) ||
-				    (error == NET_RX_BAD)) {
-					fep->stats.rx_dropped++;
-				} else {
-					fep->stats.rx_packets++;
-					fep->stats.rx_bytes += frame_length;
-				}
-				fep->rx_skb[i] = NULL;
-			} else {
-				/* Multiple descriptor packet */
-				if (ctrl & MAL_RX_CTRL_FIRST) {
-					if (fep->rx_desc[(i + 1) % NUM_RX_BUFF].
-					    ctrl & MAL_RX_CTRL_EMPTY)
-						break;
-					bnum = 0;
-					buf[bnum] = i;
-					++bnum;
-					continue;
-				}
-				if (((ctrl & MAL_RX_CTRL_FIRST) !=
-				     MAL_RX_CTRL_FIRST) &&
-				    ((ctrl & MAL_RX_CTRL_LAST) !=
-				     MAL_RX_CTRL_LAST)) {
-					if (fep->rx_desc[(i + 1) %
-							 NUM_RX_BUFF].ctrl &
-					    MAL_RX_CTRL_EMPTY) {
-						i = buf[0];
-						break;
-					}
-					buf[bnum] = i;
-					++bnum;
-					continue;
-				}
-				if (ctrl & MAL_RX_CTRL_LAST) {
-					buf[bnum] = i;
-					++bnum;
-					skb_put(fep->rx_skb[buf[0]],
-						fep->rx_desc[buf[0]].data_len);
-					for (b = 1; b < bnum; b++) {
-						/*
-						 * MAL is braindead, we need
-						 * to copy the remainder
-						 * of the packet from the
-						 * latter descriptor buffers
-						 * to the first skb. Then
-						 * dispose of the source
-						 * skbs.
-						 *
-						 * Once the stack is fixed
-						 * to handle frags on most
-						 * protocols we can generate
-						 * a fragmented skb with
-						 * no copies.
-						 */
-						memcpy(fep->rx_skb[buf[0]]->
-						       data +
-						       fep->rx_skb[buf[0]]->len,
-						       fep->rx_skb[buf[b]]->
-						       data,
-						       fep->rx_desc[buf[b]].
-						       data_len);
-						skb_put(fep->rx_skb[buf[0]],
-							fep->rx_desc[buf[b]].
-							data_len);
-						dma_unmap_single(&fep->ocpdev->
-								 dev,
-								 fep->
-								 rx_desc[buf
-									 [b]].
-								 data_ptr,
-								 fep->
-								 rx_desc[buf
-									 [b]].
-								 data_len,
-								 DMA_FROM_DEVICE);
-						dev_kfree_skb(fep->
-							      rx_skb[buf[b]]);
-					}
-					emac_rx_csum(dev, ctrl,
-						     fep->rx_skb[buf[0]]);
-
-					fep->rx_skb[buf[0]]->dev = dev;
-					fep->rx_skb[buf[0]]->protocol =
-					    eth_type_trans(fep->rx_skb[buf[0]],
-							   dev);
-					error = netif_rx(fep->rx_skb[buf[0]]);
-
-					if ((error == NET_RX_DROP)
-					    || (error == NET_RX_BAD)) {
-						fep->stats.rx_dropped++;
-					} else {
-						fep->stats.rx_packets++;
-						fep->stats.rx_bytes +=
-						    fep->rx_skb[buf[0]]->len;
-					}
-					for (b = 0; b < bnum; b++)
-						fep->rx_skb[buf[b]] = NULL;
-				}
-			}
-		}
-	} while ((i = (i + 1) % NUM_RX_BUFF) != fep->rx_slot);
-
-	PKT_DEBUG(("emac_rx_clean() exit, rx_slot: %d\n", fep->rx_slot));
-
-	return i;
-}
-
-static void emac_rxeob_dev(void *param, u32 chanmask)
-{
-	struct net_device *dev = param;
-	struct ocp_enet_private *fep = dev->priv;
 	unsigned long flags;
+	local_irq_save(flags);
+
+#if defined(CONFIG_405EP)
+	mtdcr(0xf3, mfdcr(0xf3) | (1 << idx));
+#else /* CONFIG_440EP */
+	SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) | (0x08000000 >> idx));
+#endif
+
+	local_irq_restore(flags);
+}
+
+static inline void EMAC_RX_CLK_DEFAULT(int idx)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+
+#if defined(CONFIG_405EP)
+	mtdcr(0xf3, mfdcr(0xf3) & ~(1 << idx));
+#else /* CONFIG_440EP */
+	SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) & ~(0x08000000 >> idx));
+#endif
+
+	local_irq_restore(flags);
+}
+#else
+#define EMAC_RX_CLK_TX(idx)		((void)0)
+#define EMAC_RX_CLK_DEFAULT(idx)	((void)0)
+#endif
+
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX) && defined(CONFIG_440GX)
+/* We can switch Ethernet clock to the internal source through SDR0_MFR[ECS],
+ * unfortunately this is less flexible than 440EP case, because it's a global 
+ * setting for all EMACs, therefore we do this clock trick only during probe.
+ */
+#define EMAC_CLK_INTERNAL		SDR_WRITE(DCRN_SDR_MFR, \
+					    SDR_READ(DCRN_SDR_MFR) | 0x08000000)
+#define EMAC_CLK_EXTERNAL		SDR_WRITE(DCRN_SDR_MFR, \
+					    SDR_READ(DCRN_SDR_MFR) & ~0x08000000)
+#else
+#define EMAC_CLK_INTERNAL		((void)0)
+#define EMAC_CLK_EXTERNAL		((void)0)
+#endif
+
+/* I don't want to litter system log with timeout errors 
+ * when we have brain-damaged PHY.
+ */
+static inline void emac_report_timeout_error(struct ocp_enet_private *dev,
+					     const char *error)
+{
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX)
+	DBG("%d: %s" NL, dev->def->index, error);
+#else
+	if (net_ratelimit())
+		printk(KERN_ERR "emac%d: %s\n", dev->def->index, error);
+#endif
+}
+
+/* PHY polling intervals */
+#define PHY_POLL_LINK_ON	HZ
+#define PHY_POLL_LINK_OFF	(HZ / 5)
+
+/* Please, keep in sync with struct ibm_emac_stats/ibm_emac_error_stats */
+static const char emac_stats_keys[EMAC_ETHTOOL_STATS_COUNT][ETH_GSTRING_LEN] = {
+	"rx_packets", "rx_bytes", "tx_packets", "tx_bytes", "rx_packets_csum",
+	"tx_packets_csum", "tx_undo", "rx_dropped_stack", "rx_dropped_oom",
+	"rx_dropped_error", "rx_dropped_resize", "rx_dropped_mtu",
+	"rx_stopped", "rx_bd_errors", "rx_bd_overrun", "rx_bd_bad_packet",
+	"rx_bd_runt_packet", "rx_bd_short_event", "rx_bd_alignment_error",
+	"rx_bd_bad_fcs", "rx_bd_packet_too_long", "rx_bd_out_of_range",
+	"rx_bd_in_range", "rx_parity", "rx_fifo_overrun", "rx_overrun",
+	"rx_bad_packet", "rx_runt_packet", "rx_short_event",
+	"rx_alignment_error", "rx_bad_fcs", "rx_packet_too_long",
+	"rx_out_of_range", "rx_in_range", "tx_dropped", "tx_bd_errors",
+	"tx_bd_bad_fcs", "tx_bd_carrier_loss", "tx_bd_excessive_deferral",
+	"tx_bd_excessive_collisions", "tx_bd_late_collision",
+	"tx_bd_multple_collisions", "tx_bd_single_collision",
+	"tx_bd_underrun", "tx_bd_sqe", "tx_parity", "tx_underrun", "tx_sqe",
+	"tx_errors"
+};
+
+static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs);
+static void emac_clean_tx_ring(struct ocp_enet_private *dev);
+
+static inline int emac_phy_supports_gige(int phy_mode)
+{
+	return  phy_mode == PHY_MODE_GMII ||
+		phy_mode == PHY_MODE_RGMII ||
+		phy_mode == PHY_MODE_TBI ||
+		phy_mode == PHY_MODE_RTBI;
+}
+
+static inline int emac_phy_gpcs(int phy_mode)
+{
+	return  phy_mode == PHY_MODE_TBI ||
+		phy_mode == PHY_MODE_RTBI;
+}
+
+static inline void emac_tx_enable(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	unsigned long flags;
+	u32 r;
+
+	local_irq_save(flags);
+
+	DBG("%d: tx_enable" NL, dev->def->index);
+
+	r = in_be32(&p->mr0);
+	if (!(r & EMAC_MR0_TXE))
+		out_be32(&p->mr0, r | EMAC_MR0_TXE);
+	local_irq_restore(flags);
+}
+
+static void emac_tx_disable(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	unsigned long flags;
+	u32 r;
+
+	local_irq_save(flags);
+
+	DBG("%d: tx_disable" NL, dev->def->index);
+
+	r = in_be32(&p->mr0);
+	if (r & EMAC_MR0_TXE) {
+		int n = 300;
+		out_be32(&p->mr0, r & ~EMAC_MR0_TXE);
+		while (!(in_be32(&p->mr0) & EMAC_MR0_TXI) && n)
+			--n;
+		if (unlikely(!n))
+			emac_report_timeout_error(dev, "TX disable timeout");
+	}
+	local_irq_restore(flags);
+}
+
+static void emac_rx_enable(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	unsigned long flags;
+	u32 r;
+
+	local_irq_save(flags);
+	if (unlikely(dev->commac.rx_stopped))
+		goto out;
+
+	DBG("%d: rx_enable" NL, dev->def->index);
+
+	r = in_be32(&p->mr0);
+	if (!(r & EMAC_MR0_RXE)) {
+		if (unlikely(!(r & EMAC_MR0_RXI))) {
+			/* Wait if previous async disable is still in progress */
+			int n = 100;
+			while (!(r = in_be32(&p->mr0) & EMAC_MR0_RXI) && n)
+				--n;
+			if (unlikely(!n))
+				emac_report_timeout_error(dev,
+							  "RX disable timeout");
+		}
+		out_be32(&p->mr0, r | EMAC_MR0_RXE);
+	}
+      out:
+	local_irq_restore(flags);
+}
+
+static void emac_rx_disable(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	unsigned long flags;
+	u32 r;
+
+	local_irq_save(flags);
+
+	DBG("%d: rx_disable" NL, dev->def->index);
+
+	r = in_be32(&p->mr0);
+	if (r & EMAC_MR0_RXE) {
+		int n = 300;
+		out_be32(&p->mr0, r & ~EMAC_MR0_RXE);
+		while (!(in_be32(&p->mr0) & EMAC_MR0_RXI) && n)
+			--n;
+		if (unlikely(!n))
+			emac_report_timeout_error(dev, "RX disable timeout");
+	}
+	local_irq_restore(flags);
+}
+
+static inline void emac_rx_disable_async(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	unsigned long flags;
+	u32 r;
+
+	local_irq_save(flags);
+
+	DBG("%d: rx_disable_async" NL, dev->def->index);
+
+	r = in_be32(&p->mr0);
+	if (r & EMAC_MR0_RXE)
+		out_be32(&p->mr0, r & ~EMAC_MR0_RXE);
+	local_irq_restore(flags);
+}
+
+static int emac_reset(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	unsigned long flags;
+	int n = 20;
+
+	DBG("%d: reset" NL, dev->def->index);
+
+	local_irq_save(flags);
+
+	if (!dev->reset_failed) {
+		/* 40x erratum suggests stopping RX channel before reset,
+		 * we stop TX as well
+		 */
+		emac_rx_disable(dev);
+		emac_tx_disable(dev);
+	}
+
+	out_be32(&p->mr0, EMAC_MR0_SRST);
+	while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
+		--n;
+	local_irq_restore(flags);
+
+	if (n) {
+		dev->reset_failed = 0;
+		return 0;
+	} else {
+		emac_report_timeout_error(dev, "reset timeout");
+		dev->reset_failed = 1;
+		return -ETIMEDOUT;
+	}
+}
+
+static void emac_hash_mc(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	u16 gaht[4] = { 0 };
+	struct dev_mc_list *dmi;
+
+	DBG("%d: hash_mc %d" NL, dev->def->index, dev->ndev->mc_count);
+
+	for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
+		int bit;
+		DBG2("%d: mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
+		     dev->def->index,
+		     dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
+		     dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
+
+		bit = 63 - (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 26);
+		gaht[bit >> 4] |= 0x8000 >> (bit & 0x0f);
+	}
+	out_be32(&p->gaht1, gaht[0]);
+	out_be32(&p->gaht2, gaht[1]);
+	out_be32(&p->gaht3, gaht[2]);
+	out_be32(&p->gaht4, gaht[3]);
+}
+
+static inline u32 emac_iff2rmr(struct net_device *ndev)
+{
+	u32 r = EMAC_RMR_SP | EMAC_RMR_SFCS | EMAC_RMR_IAE | EMAC_RMR_BAE |
+	    EMAC_RMR_BASE;
+
+	if (ndev->flags & IFF_PROMISC)
+		r |= EMAC_RMR_PME;
+	else if (ndev->flags & IFF_ALLMULTI || ndev->mc_count > 32)
+		r |= EMAC_RMR_PMME;
+	else if (ndev->mc_count > 0)
+		r |= EMAC_RMR_MAE;
+
+	return r;
+}
+
+static inline int emac_opb_mhz(void)
+{
+	return (ocp_sys_info.opb_bus_freq + 500000) / 1000000;
+}
+
+/* BHs disabled */
+static int emac_configure(struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+	struct net_device *ndev = dev->ndev;
+	int gige;
+	u32 r;
+
+	DBG("%d: configure" NL, dev->def->index);
+
+	if (emac_reset(dev) < 0)
+		return -ETIMEDOUT;
+
+	tah_reset(dev->tah_dev);
+
+	/* Mode register */
+	r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST;
+	if (dev->phy.duplex == DUPLEX_FULL)
+		r |= EMAC_MR1_FDE;
+	switch (dev->phy.speed) {
+	case SPEED_1000:
+		if (emac_phy_gpcs(dev->phy.mode)) {
+			r |= EMAC_MR1_MF_1000GPCS |
+			    EMAC_MR1_MF_IPPA(dev->phy.address);
+
+			/* Put some arbitrary OUI, Manuf & Rev IDs so we can
+			 * identify this GPCS PHY later.
+			 */
+			out_be32(&p->ipcr, 0xdeadbeef);
+		} else
+			r |= EMAC_MR1_MF_1000;
+		r |= EMAC_MR1_RFS_16K;
+		gige = 1;
+		
+		if (dev->ndev->mtu > ETH_DATA_LEN)
+			r |= EMAC_MR1_JPSM;
+		break;
+	case SPEED_100:
+		r |= EMAC_MR1_MF_100;
+		/* Fall through */
+	default:
+		r |= EMAC_MR1_RFS_4K;
+		gige = 0;
+		break;
+	}
+
+	if (dev->rgmii_dev)
+		rgmii_set_speed(dev->rgmii_dev, dev->rgmii_input,
+				dev->phy.speed);
+	else
+		zmii_set_speed(dev->zmii_dev, dev->zmii_input, dev->phy.speed);
+
+#if !defined(CONFIG_40x)
+	/* on 40x erratum forces us to NOT use integrated flow control, 
+	 * let's hope it works on 44x ;)
+	 */
+	if (dev->phy.duplex == DUPLEX_FULL) {
+		if (dev->phy.pause)
+			r |= EMAC_MR1_EIFC | EMAC_MR1_APP;
+		else if (dev->phy.asym_pause)
+			r |= EMAC_MR1_APP;
+	}
+#endif
+	out_be32(&p->mr1, r);
+
+	/* Set individual MAC address */
+	out_be32(&p->iahr, (ndev->dev_addr[0] << 8) | ndev->dev_addr[1]);
+	out_be32(&p->ialr, (ndev->dev_addr[2] << 24) |
+		 (ndev->dev_addr[3] << 16) | (ndev->dev_addr[4] << 8) |
+		 ndev->dev_addr[5]);
+
+	/* VLAN Tag Protocol ID */
+	out_be32(&p->vtpid, 0x8100);
+
+	/* Receive mode register */
+	r = emac_iff2rmr(ndev);
+	if (r & EMAC_RMR_MAE)
+		emac_hash_mc(dev);
+	out_be32(&p->rmr, r);
+
+	/* FIFOs thresholds */
+	r = EMAC_TMR1((EMAC_MAL_BURST_SIZE / EMAC_FIFO_ENTRY_SIZE) + 1,
+		      EMAC_TX_FIFO_SIZE / 2 / EMAC_FIFO_ENTRY_SIZE);
+	out_be32(&p->tmr1, r);
+	out_be32(&p->trtr, EMAC_TRTR(EMAC_TX_FIFO_SIZE / 2));
+
+	/* PAUSE frame is sent when RX FIFO reaches its high-water mark,
+	   there should be still enough space in FIFO to allow the our link
+	   partner time to process this frame and also time to send PAUSE 
+	   frame itself.
+
+	   Here is the worst case scenario for the RX FIFO "headroom"
+	   (from "The Switch Book") (100Mbps, without preamble, inter-frame gap):
+
+	   1) One maximum-length frame on TX                    1522 bytes
+	   2) One PAUSE frame time                                64 bytes
+	   3) PAUSE frame decode time allowance                   64 bytes
+	   4) One maximum-length frame on RX                    1522 bytes
+	   5) Round-trip propagation delay of the link (100Mb)    15 bytes
+	   ----------       
+	   3187 bytes
+
+	   I chose to set high-water mark to RX_FIFO_SIZE / 4 (1024 bytes)
+	   low-water mark  to RX_FIFO_SIZE / 8 (512 bytes)
+	 */
+	r = EMAC_RWMR(EMAC_RX_FIFO_SIZE(gige) / 8 / EMAC_FIFO_ENTRY_SIZE,
+		      EMAC_RX_FIFO_SIZE(gige) / 4 / EMAC_FIFO_ENTRY_SIZE);
+	out_be32(&p->rwmr, r);
+
+	/* Set PAUSE timer to the maximum */
+	out_be32(&p->ptr, 0xffff);
+
+	/* IRQ sources */
+	out_be32(&p->iser, EMAC_ISR_TXPE | EMAC_ISR_RXPE | /* EMAC_ISR_TXUE |
+		 EMAC_ISR_RXOE | */ EMAC_ISR_OVR | EMAC_ISR_BP | EMAC_ISR_SE |
+		 EMAC_ISR_ALE | EMAC_ISR_BFCS | EMAC_ISR_PTLE | EMAC_ISR_ORE |
+		 EMAC_ISR_IRE | EMAC_ISR_TE);
+		 
+	/* We need to take GPCS PHY out of isolate mode after EMAC reset */
+	if (emac_phy_gpcs(dev->phy.mode)) 
+		mii_reset_phy(&dev->phy);
+		 
+	return 0;
+}
+
+/* BHs disabled */
+static void emac_reinitialize(struct ocp_enet_private *dev)
+{
+	DBG("%d: reinitialize" NL, dev->def->index);
+
+	if (!emac_configure(dev)) {
+		emac_tx_enable(dev);
+		emac_rx_enable(dev);
+	}
+}
+
+/* BHs disabled */
+static void emac_full_tx_reset(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+	DBG("%d: full_tx_reset" NL, dev->def->index);
+
+	emac_tx_disable(dev);
+	mal_disable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+	emac_clean_tx_ring(dev);
+	dev->tx_cnt = dev->tx_slot = dev->ack_slot = 0;
+
+	emac_configure(dev);
+
+	mal_enable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+	emac_tx_enable(dev);
+	emac_rx_enable(dev);
+
+	netif_wake_queue(ndev);
+}
+
+static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg)
+{
+	struct emac_regs *p = dev->emacp;
+	u32 r;
 	int n;
 
-	spin_lock_irqsave(&fep->lock, flags);
-	if ((n = emac_rx_clean(dev)) != fep->rx_slot)
-		emac_rx_fill(dev, n);
-	spin_unlock_irqrestore(&fep->lock, flags);
-}
+	DBG2("%d: mdio_read(%02x,%02x)" NL, dev->def->index, id, reg);
 
-/*
- * This interrupt should never occurr, we don't program
- * the MAL for contiunous mode.
- */
-static void emac_txde_dev(void *param, u32 chanmask)
-{
-	struct net_device *dev = param;
-	struct ocp_enet_private *fep = dev->priv;
+	/* Enable proper MDIO port */
+	zmii_enable_mdio(dev->zmii_dev, dev->zmii_input);
 
-	printk(KERN_WARNING "%s: transmit descriptor error\n", dev->name);
-
-	emac_mac_dump(dev);
-	emac_mal_dump(dev);
-
-	/* Reenable the transmit channel */
-	mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
-}
-
-/*
- * This interrupt should be very rare at best.  This occurs when
- * the hardware has a problem with the receive descriptors.  The manual
- * states that it occurs when the hardware cannot the receive descriptor
- * empty bit is not set.  The recovery mechanism will be to
- * traverse through the descriptors, handle any that are marked to be
- * handled and reinitialize each along the way.  At that point the driver
- * will be restarted.
- */
-static void emac_rxde_dev(void *param, u32 chanmask)
-{
-	struct net_device *dev = param;
-	struct ocp_enet_private *fep = dev->priv;
-	unsigned long flags;
-
-	if (net_ratelimit()) {
-		printk(KERN_WARNING "%s: receive descriptor error\n",
-		       fep->ndev->name);
-
-		emac_mac_dump(dev);
-		emac_mal_dump(dev);
-		emac_desc_dump(dev);
+	/* Wait for management interface to become idle */
+	n = 10;
+	while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
+		udelay(1);
+		if (!--n)
+			goto to;
 	}
 
-	/* Disable RX channel */
-	spin_lock_irqsave(&fep->lock, flags);
-	mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
+	/* Issue read command */
+	out_be32(&p->stacr,
+		 EMAC_STACR_BASE(emac_opb_mhz()) | EMAC_STACR_STAC_READ |
+		 (reg & EMAC_STACR_PRA_MASK)
+		 | ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT));
 
-	/* For now, charge the error against all emacs */
-	fep->stats.rx_errors++;
+	/* Wait for read to complete */
+	n = 100;
+	while (!((r = in_be32(&p->stacr)) & EMAC_STACR_OC)) {
+		udelay(1);
+		if (!--n)
+			goto to;
+	}
 
-	/* so do we have any good packets still? */
-	emac_rx_clean(dev);
+	if (unlikely(r & EMAC_STACR_PHYE)) {
+		DBG("%d: mdio_read(%02x, %02x) failed" NL, dev->def->index,
+		    id, reg);
+		return -EREMOTEIO;
+	}
 
-	/* When the interface is restarted it resets processing to the
-	 *  first descriptor in the table.
+	r = ((r >> EMAC_STACR_PHYD_SHIFT) & EMAC_STACR_PHYD_MASK);
+	DBG2("%d: mdio_read -> %04x" NL, dev->def->index, r);
+	return r;
+      to:
+	DBG("%d: MII management interface timeout (read)" NL, dev->def->index);
+	return -ETIMEDOUT;
+}
+
+static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg,
+			      u16 val)
+{
+	struct emac_regs *p = dev->emacp;
+	int n;
+
+	DBG2("%d: mdio_write(%02x,%02x,%04x)" NL, dev->def->index, id, reg,
+	     val);
+
+	/* Enable proper MDIO port */
+	zmii_enable_mdio(dev->zmii_dev, dev->zmii_input);
+
+	/* Wait for management interface to be idle */
+	n = 10;
+	while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
+		udelay(1);
+		if (!--n)
+			goto to;
+	}
+
+	/* Issue write command */
+	out_be32(&p->stacr,
+		 EMAC_STACR_BASE(emac_opb_mhz()) | EMAC_STACR_STAC_WRITE |
+		 (reg & EMAC_STACR_PRA_MASK) |
+		 ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT) |
+		 (val << EMAC_STACR_PHYD_SHIFT));
+
+	/* Wait for write to complete */
+	n = 100;
+	while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) {
+		udelay(1);
+		if (!--n)
+			goto to;
+	}
+	return;
+      to:
+	DBG("%d: MII management interface timeout (write)" NL, dev->def->index);
+}
+
+static int emac_mdio_read(struct net_device *ndev, int id, int reg)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	int res;
+
+	local_bh_disable();
+	res = __emac_mdio_read(dev->mdio_dev ? dev->mdio_dev : dev, (u8) id,
+			       (u8) reg);
+	local_bh_enable();
+	return res;
+}
+
+static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+
+	local_bh_disable();
+	__emac_mdio_write(dev->mdio_dev ? dev->mdio_dev : dev, (u8) id,
+			  (u8) reg, (u16) val);
+	local_bh_enable();
+}
+
+/* BHs disabled */
+static void emac_set_multicast_list(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	struct emac_regs *p = dev->emacp;
+	u32 rmr = emac_iff2rmr(ndev);
+
+	DBG("%d: multicast %08x" NL, dev->def->index, rmr);
+	BUG_ON(!netif_running(dev->ndev));
+
+	/* I decided to relax register access rules here to avoid
+	 * full EMAC reset.
+	 *
+	 * There is a real problem with EMAC4 core if we use MWSW_001 bit 
+	 * in MR1 register and do a full EMAC reset.
+	 * One TX BD status update is delayed and, after EMAC reset, it 
+	 * never happens, resulting in TX hung (it'll be recovered by TX 
+	 * timeout handler eventually, but this is just gross).
+	 * So we either have to do full TX reset or try to cheat here :)
+	 *
+	 * The only required change is to RX mode register, so I *think* all
+	 * we need is just to stop RX channel. This seems to work on all
+	 * tested SoCs.                                                --ebs
 	 */
-
-	fep->rx_slot = 0;
-	emac_rx_fill(dev, 0);
-
-	set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, fep->commac.rx_chan_mask);
-	set_mal_dcrn(fep->mal, DCRN_MALRXDEIR, fep->commac.rx_chan_mask);
-
-	/* Reenable the receive channels */
-	mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-	spin_unlock_irqrestore(&fep->lock, flags);
+	emac_rx_disable(dev);
+	if (rmr & EMAC_RMR_MAE)
+		emac_hash_mc(dev);
+	out_be32(&p->rmr, rmr);
+	emac_rx_enable(dev);
 }
 
-static irqreturn_t
-emac_mac_irq(int irq, void *dev_instance, struct pt_regs *regs)
+/* BHs disabled */
+static int emac_resize_rx_ring(struct ocp_enet_private *dev, int new_mtu)
 {
-	struct net_device *dev = dev_instance;
-	struct ocp_enet_private *fep = dev->priv;
-	emac_t *emacp = fep->emacp;
-	unsigned long tmp_em0isr;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+	int rx_sync_size = emac_rx_sync_size(new_mtu);
+	int rx_skb_size = emac_rx_skb_size(new_mtu);
+	int i, ret = 0;
 
-	/* EMAC interrupt */
-	tmp_em0isr = in_be32(&emacp->em0isr);
-	if (tmp_em0isr & (EMAC_ISR_TE0 | EMAC_ISR_TE1)) {
-		/* This error is a hard transmit error - could retransmit */
-		fep->stats.tx_errors++;
+	emac_rx_disable(dev);
+	mal_disable_rx_channel(dev->mal, emacdata->mal_rx_chan);
 
-		/* Reenable the transmit channel */
-		mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
-
-	} else {
-		fep->stats.rx_errors++;
+	if (dev->rx_sg_skb) {
+		++dev->estats.rx_dropped_resize;
+		dev_kfree_skb(dev->rx_sg_skb);
+		dev->rx_sg_skb = NULL;
 	}
 
-	if (tmp_em0isr & EMAC_ISR_RP)
-		fep->stats.rx_length_errors++;
-	if (tmp_em0isr & EMAC_ISR_ALE)
-		fep->stats.rx_frame_errors++;
-	if (tmp_em0isr & EMAC_ISR_BFCS)
-		fep->stats.rx_crc_errors++;
-	if (tmp_em0isr & EMAC_ISR_PTLE)
-		fep->stats.rx_length_errors++;
-	if (tmp_em0isr & EMAC_ISR_ORE)
-		fep->stats.rx_length_errors++;
-	if (tmp_em0isr & EMAC_ISR_TE0)
-		fep->stats.tx_aborted_errors++;
+	/* Make a first pass over RX ring and mark BDs ready, dropping 
+	 * non-processed packets on the way. We need this as a separate pass
+	 * to simplify error recovery in the case of allocation failure later.
+	 */
+	for (i = 0; i < NUM_RX_BUFF; ++i) {
+		if (dev->rx_desc[i].ctrl & MAL_RX_CTRL_FIRST)
+			++dev->estats.rx_dropped_resize;
 
-	emac_err_dump(dev, tmp_em0isr);
+		dev->rx_desc[i].data_len = 0;
+		dev->rx_desc[i].ctrl = MAL_RX_CTRL_EMPTY |
+		    (i == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
+	}
 
-	out_be32(&emacp->em0isr, tmp_em0isr);
+	/* Reallocate RX ring only if bigger skb buffers are required */
+	if (rx_skb_size <= dev->rx_skb_size)
+		goto skip;
+
+	/* Second pass, allocate new skbs */
+	for (i = 0; i < NUM_RX_BUFF; ++i) {
+		struct sk_buff *skb = alloc_skb(rx_skb_size, GFP_ATOMIC);
+		if (!skb) {
+			ret = -ENOMEM;
+			goto oom;
+		}
+
+		BUG_ON(!dev->rx_skb[i]);
+		dev_kfree_skb(dev->rx_skb[i]);
+
+		skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
+		dev->rx_desc[i].data_ptr =
+		    dma_map_single(dev->ldev, skb->data - 2, rx_sync_size,
+				   DMA_FROM_DEVICE) + 2;
+		dev->rx_skb[i] = skb;
+	}
+      skip:
+	/* Check if we need to change "Jumbo" bit in MR1 */
+	if ((new_mtu > ETH_DATA_LEN) ^ (dev->ndev->mtu > ETH_DATA_LEN)) {
+		/* This is to prevent starting RX channel in emac_rx_enable() */
+		dev->commac.rx_stopped = 1;
+
+		dev->ndev->mtu = new_mtu;
+		emac_full_tx_reset(dev->ndev);
+	}
+
+	mal_set_rcbs(dev->mal, emacdata->mal_rx_chan, emac_rx_size(new_mtu));
+      oom:
+	/* Restart RX */
+	dev->commac.rx_stopped = dev->rx_slot = 0;
+	mal_enable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+	emac_rx_enable(dev);
+
+	return ret;
+}
+
+/* Process ctx, rtnl_lock semaphore */
+static int emac_change_mtu(struct net_device *ndev, int new_mtu)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	int ret = 0;
+
+	if (new_mtu < EMAC_MIN_MTU || new_mtu > EMAC_MAX_MTU)
+		return -EINVAL;
+
+	DBG("%d: change_mtu(%d)" NL, dev->def->index, new_mtu);
+
+	local_bh_disable();
+	if (netif_running(ndev)) {
+		/* Check if we really need to reinitalize RX ring */
+		if (emac_rx_skb_size(ndev->mtu) != emac_rx_skb_size(new_mtu))
+			ret = emac_resize_rx_ring(dev, new_mtu);
+	}
+
+	if (!ret) {
+		ndev->mtu = new_mtu;
+		dev->rx_skb_size = emac_rx_skb_size(new_mtu);
+		dev->rx_sync_size = emac_rx_sync_size(new_mtu);
+	}	
+	local_bh_enable();
+
+	return ret;
+}
+
+static void emac_clean_tx_ring(struct ocp_enet_private *dev)
+{
+	int i;
+	for (i = 0; i < NUM_TX_BUFF; ++i) {
+		if (dev->tx_skb[i]) {
+			dev_kfree_skb(dev->tx_skb[i]);
+			dev->tx_skb[i] = NULL;
+			if (dev->tx_desc[i].ctrl & MAL_TX_CTRL_READY)
+				++dev->estats.tx_dropped;
+		}
+		dev->tx_desc[i].ctrl = 0;
+		dev->tx_desc[i].data_ptr = 0;
+	}
+}
+
+static void emac_clean_rx_ring(struct ocp_enet_private *dev)
+{
+	int i;
+	for (i = 0; i < NUM_RX_BUFF; ++i)
+		if (dev->rx_skb[i]) {
+			dev->rx_desc[i].ctrl = 0;
+			dev_kfree_skb(dev->rx_skb[i]);
+			dev->rx_skb[i] = NULL;
+			dev->rx_desc[i].data_ptr = 0;
+		}
+
+	if (dev->rx_sg_skb) {
+		dev_kfree_skb(dev->rx_sg_skb);
+		dev->rx_sg_skb = NULL;
+	}
+}
+
+static inline int emac_alloc_rx_skb(struct ocp_enet_private *dev, int slot,
+				    int flags)
+{
+	struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags);
+	if (unlikely(!skb))
+		return -ENOMEM;
+
+	dev->rx_skb[slot] = skb;
+	dev->rx_desc[slot].data_len = 0;
+
+	skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
+	dev->rx_desc[slot].data_ptr = 
+	    dma_map_single(dev->ldev, skb->data - 2, dev->rx_sync_size, 
+			   DMA_FROM_DEVICE) + 2;
+	barrier();
+	dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY |
+	    (slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
+
+	return 0;
+}
+
+static void emac_print_link_status(struct ocp_enet_private *dev)
+{
+	if (netif_carrier_ok(dev->ndev))
+		printk(KERN_INFO "%s: link is up, %d %s%s\n",
+		       dev->ndev->name, dev->phy.speed,
+		       dev->phy.duplex == DUPLEX_FULL ? "FDX" : "HDX",
+		       dev->phy.pause ? ", pause enabled" :
+		       dev->phy.asym_pause ? ", assymetric pause enabled" : "");
+	else
+		printk(KERN_INFO "%s: link is down\n", dev->ndev->name);
+}
+
+/* Process ctx, rtnl_lock semaphore */
+static int emac_open(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+	int err, i;
+
+	DBG("%d: open" NL, dev->def->index);
+
+	/* Setup error IRQ handler */
+	err = request_irq(dev->def->irq, emac_irq, 0, "EMAC", dev);
+	if (err) {
+		printk(KERN_ERR "%s: failed to request IRQ %d\n",
+		       ndev->name, dev->def->irq);
+		return err;
+	}
+
+	/* Allocate RX ring */
+	for (i = 0; i < NUM_RX_BUFF; ++i)
+		if (emac_alloc_rx_skb(dev, i, GFP_KERNEL)) {
+			printk(KERN_ERR "%s: failed to allocate RX ring\n",
+			       ndev->name);
+			goto oom;
+		}
+
+	local_bh_disable();
+	dev->tx_cnt = dev->tx_slot = dev->ack_slot = dev->rx_slot =
+	    dev->commac.rx_stopped = 0;
+	dev->rx_sg_skb = NULL;
+
+	if (dev->phy.address >= 0) {
+		int link_poll_interval;
+		if (dev->phy.def->ops->poll_link(&dev->phy)) {
+			dev->phy.def->ops->read_link(&dev->phy);
+			EMAC_RX_CLK_DEFAULT(dev->def->index);
+			netif_carrier_on(dev->ndev);
+			link_poll_interval = PHY_POLL_LINK_ON;
+		} else {
+			EMAC_RX_CLK_TX(dev->def->index);
+			netif_carrier_off(dev->ndev);
+			link_poll_interval = PHY_POLL_LINK_OFF;
+		}
+		mod_timer(&dev->link_timer, jiffies + link_poll_interval);
+		emac_print_link_status(dev);
+	} else
+		netif_carrier_on(dev->ndev);
+
+	emac_configure(dev);
+	mal_poll_add(dev->mal, &dev->commac);
+	mal_enable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+	mal_set_rcbs(dev->mal, emacdata->mal_rx_chan, emac_rx_size(ndev->mtu));
+	mal_enable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+	emac_tx_enable(dev);
+	emac_rx_enable(dev);
+	netif_start_queue(ndev);
+	local_bh_enable();
+
+	return 0;
+      oom:
+	emac_clean_rx_ring(dev);
+	free_irq(dev->def->irq, dev);
+	return -ENOMEM;
+}
+
+/* BHs disabled */
+static int emac_link_differs(struct ocp_enet_private *dev)
+{
+	u32 r = in_be32(&dev->emacp->mr1);
+
+	int duplex = r & EMAC_MR1_FDE ? DUPLEX_FULL : DUPLEX_HALF;
+	int speed, pause, asym_pause;
+
+	if (r & (EMAC_MR1_MF_1000 | EMAC_MR1_MF_1000GPCS))
+		speed = SPEED_1000;
+	else if (r & EMAC_MR1_MF_100)
+		speed = SPEED_100;
+	else
+		speed = SPEED_10;
+
+	switch (r & (EMAC_MR1_EIFC | EMAC_MR1_APP)) {
+	case (EMAC_MR1_EIFC | EMAC_MR1_APP):
+		pause = 1;
+		asym_pause = 0;
+		break;
+	case EMAC_MR1_APP:
+		pause = 0;
+		asym_pause = 1;
+		break;
+	default:
+		pause = asym_pause = 0;
+	}
+	return speed != dev->phy.speed || duplex != dev->phy.duplex ||
+	    pause != dev->phy.pause || asym_pause != dev->phy.asym_pause;
+}
+
+/* BHs disabled */
+static void emac_link_timer(unsigned long data)
+{
+	struct ocp_enet_private *dev = (struct ocp_enet_private *)data;
+	int link_poll_interval;
+
+	DBG2("%d: link timer" NL, dev->def->index);
+
+	if (dev->phy.def->ops->poll_link(&dev->phy)) {
+		if (!netif_carrier_ok(dev->ndev)) {
+			EMAC_RX_CLK_DEFAULT(dev->def->index);
+
+			/* Get new link parameters */
+			dev->phy.def->ops->read_link(&dev->phy);
+
+			if (dev->tah_dev || emac_link_differs(dev))
+				emac_full_tx_reset(dev->ndev);
+
+			netif_carrier_on(dev->ndev);
+			emac_print_link_status(dev);
+		}
+		link_poll_interval = PHY_POLL_LINK_ON;
+	} else {
+		if (netif_carrier_ok(dev->ndev)) {
+			EMAC_RX_CLK_TX(dev->def->index);
+#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX)
+			emac_reinitialize(dev);
+#endif
+			netif_carrier_off(dev->ndev);
+			emac_print_link_status(dev);
+		}
+
+		/* Retry reset if the previous attempt failed.
+		 * This is needed mostly for CONFIG_IBM_EMAC_PHY_RX_CLK_FIX
+		 * case, but I left it here because it shouldn't trigger for
+		 * sane PHYs anyway.
+		 */
+		if (unlikely(dev->reset_failed))
+			emac_reinitialize(dev);
+
+		link_poll_interval = PHY_POLL_LINK_OFF;
+	}
+	mod_timer(&dev->link_timer, jiffies + link_poll_interval);
+}
+
+/* BHs disabled */
+static void emac_force_link_update(struct ocp_enet_private *dev)
+{
+	netif_carrier_off(dev->ndev);
+	if (timer_pending(&dev->link_timer))
+		mod_timer(&dev->link_timer, jiffies + PHY_POLL_LINK_OFF);
+}
+
+/* Process ctx, rtnl_lock semaphore */
+static int emac_close(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+	DBG("%d: close" NL, dev->def->index);
+
+	local_bh_disable();
+
+	if (dev->phy.address >= 0)
+		del_timer_sync(&dev->link_timer);
+
+	netif_stop_queue(ndev);
+	emac_rx_disable(dev);
+	emac_tx_disable(dev);
+	mal_disable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+	mal_disable_tx_channel(dev->mal, emacdata->mal_tx_chan);
+	mal_poll_del(dev->mal, &dev->commac);
+	local_bh_enable();
+
+	emac_clean_tx_ring(dev);
+	emac_clean_rx_ring(dev);
+	free_irq(dev->def->irq, dev);
+
+	return 0;
+}
+
+static inline u16 emac_tx_csum(struct ocp_enet_private *dev,
+			       struct sk_buff *skb)
+{
+#if defined(CONFIG_IBM_EMAC_TAH)
+	if (skb->ip_summed == CHECKSUM_HW) {
+		++dev->stats.tx_packets_csum;
+		return EMAC_TX_CTRL_TAH_CSUM;
+	}
+#endif
+	return 0;
+}
+
+static inline int emac_xmit_finish(struct ocp_enet_private *dev, int len)
+{
+	struct emac_regs *p = dev->emacp;
+	struct net_device *ndev = dev->ndev;
+
+	/* Send the packet out */
+	out_be32(&p->tmr0, EMAC_TMR0_XMIT);
+
+	if (unlikely(++dev->tx_cnt == NUM_TX_BUFF)) {
+		netif_stop_queue(ndev);
+		DBG2("%d: stopped TX queue" NL, dev->def->index);
+	}
+
+	ndev->trans_start = jiffies;
+	++dev->stats.tx_packets;
+	dev->stats.tx_bytes += len;
+
+	return 0;
+}
+
+/* BHs disabled */
+static int emac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	unsigned int len = skb->len;
+	int slot;
+
+	u16 ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
+	    MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb);
+
+	slot = dev->tx_slot++;
+	if (dev->tx_slot == NUM_TX_BUFF) {
+		dev->tx_slot = 0;
+		ctrl |= MAL_TX_CTRL_WRAP;
+	}
+
+	DBG2("%d: xmit(%u) %d" NL, dev->def->index, len, slot);
+
+	dev->tx_skb[slot] = skb;
+	dev->tx_desc[slot].data_ptr = dma_map_single(dev->ldev, skb->data, len,
+						     DMA_TO_DEVICE);
+	dev->tx_desc[slot].data_len = (u16) len;
+	barrier();
+	dev->tx_desc[slot].ctrl = ctrl;
+
+	return emac_xmit_finish(dev, len);
+}
+
+#if defined(CONFIG_IBM_EMAC_TAH)
+static inline int emac_xmit_split(struct ocp_enet_private *dev, int slot,
+				  u32 pd, int len, int last, u16 base_ctrl)
+{
+	while (1) {
+		u16 ctrl = base_ctrl;
+		int chunk = min(len, MAL_MAX_TX_SIZE);
+		len -= chunk;
+
+		slot = (slot + 1) % NUM_TX_BUFF;
+
+		if (last && !len)
+			ctrl |= MAL_TX_CTRL_LAST;
+		if (slot == NUM_TX_BUFF - 1)
+			ctrl |= MAL_TX_CTRL_WRAP;
+
+		dev->tx_skb[slot] = NULL;
+		dev->tx_desc[slot].data_ptr = pd;
+		dev->tx_desc[slot].data_len = (u16) chunk;
+		dev->tx_desc[slot].ctrl = ctrl;
+		++dev->tx_cnt;
+
+		if (!len)
+			break;
+
+		pd += chunk;
+	}
+	return slot;
+}
+
+/* BHs disabled (SG version for TAH equipped EMACs) */
+static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	int len = skb->len, chunk;
+	int slot, i;
+	u16 ctrl;
+	u32 pd;
+
+	/* This is common "fast" path */
+	if (likely(!nr_frags && len <= MAL_MAX_TX_SIZE))
+		return emac_start_xmit(skb, ndev);
+
+	len -= skb->data_len;
+
+	/* Note, this is only an *estimation*, we can still run out of empty
+	 * slots because of the additional fragmentation into
+	 * MAL_MAX_TX_SIZE-sized chunks
+	 */
+	if (unlikely(dev->tx_cnt + nr_frags + mal_tx_chunks(len) > NUM_TX_BUFF))
+		goto stop_queue;
+
+	ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
+	    emac_tx_csum(dev, skb);
+	slot = dev->tx_slot;
+
+	/* skb data */
+	dev->tx_skb[slot] = NULL;
+	chunk = min(len, MAL_MAX_TX_SIZE);
+	dev->tx_desc[slot].data_ptr = pd =
+	    dma_map_single(dev->ldev, skb->data, len, DMA_TO_DEVICE);
+	dev->tx_desc[slot].data_len = (u16) chunk;
+	len -= chunk;
+	if (unlikely(len))
+		slot = emac_xmit_split(dev, slot, pd + chunk, len, !nr_frags,
+				       ctrl);
+	/* skb fragments */
+	for (i = 0; i < nr_frags; ++i) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+		len = frag->size;
+
+		if (unlikely(dev->tx_cnt + mal_tx_chunks(len) >= NUM_TX_BUFF))
+			goto undo_frame;
+
+		pd = dma_map_page(dev->ldev, frag->page, frag->page_offset, len,
+				  DMA_TO_DEVICE);
+
+		slot = emac_xmit_split(dev, slot, pd, len, i == nr_frags - 1,
+				       ctrl);
+	}
+
+	DBG2("%d: xmit_sg(%u) %d - %d" NL, dev->def->index, skb->len,
+	     dev->tx_slot, slot);
+
+	/* Attach skb to the last slot so we don't release it too early */
+	dev->tx_skb[slot] = skb;
+
+	/* Send the packet out */
+	if (dev->tx_slot == NUM_TX_BUFF - 1)
+		ctrl |= MAL_TX_CTRL_WRAP;
+	barrier();
+	dev->tx_desc[dev->tx_slot].ctrl = ctrl;
+	dev->tx_slot = (slot + 1) % NUM_TX_BUFF;
+
+	return emac_xmit_finish(dev, skb->len);
+
+      undo_frame:
+	/* Well, too bad. Our previous estimation was overly optimistic. 
+	 * Undo everything.
+	 */
+	while (slot != dev->tx_slot) {
+		dev->tx_desc[slot].ctrl = 0;
+		--dev->tx_cnt;
+		if (--slot < 0)
+			slot = NUM_TX_BUFF - 1;
+	}
+	++dev->estats.tx_undo;
+
+      stop_queue:
+	netif_stop_queue(ndev);
+	DBG2("%d: stopped TX queue" NL, dev->def->index);
+	return 1;
+}
+#else
+# define emac_start_xmit_sg	emac_start_xmit
+#endif	/* !defined(CONFIG_IBM_EMAC_TAH) */
+
+/* BHs disabled */
+static void emac_parse_tx_error(struct ocp_enet_private *dev, u16 ctrl)
+{
+	struct ibm_emac_error_stats *st = &dev->estats;
+	DBG("%d: BD TX error %04x" NL, dev->def->index, ctrl);
+
+	++st->tx_bd_errors;
+	if (ctrl & EMAC_TX_ST_BFCS)
+		++st->tx_bd_bad_fcs;
+	if (ctrl & EMAC_TX_ST_LCS)
+		++st->tx_bd_carrier_loss;
+	if (ctrl & EMAC_TX_ST_ED)
+		++st->tx_bd_excessive_deferral;
+	if (ctrl & EMAC_TX_ST_EC)
+		++st->tx_bd_excessive_collisions;
+	if (ctrl & EMAC_TX_ST_LC)
+		++st->tx_bd_late_collision;
+	if (ctrl & EMAC_TX_ST_MC)
+		++st->tx_bd_multple_collisions;
+	if (ctrl & EMAC_TX_ST_SC)
+		++st->tx_bd_single_collision;
+	if (ctrl & EMAC_TX_ST_UR)
+		++st->tx_bd_underrun;
+	if (ctrl & EMAC_TX_ST_SQE)
+		++st->tx_bd_sqe;
+}
+
+static void emac_poll_tx(void *param)
+{
+	struct ocp_enet_private *dev = param;
+	DBG2("%d: poll_tx, %d %d" NL, dev->def->index, dev->tx_cnt,
+	     dev->ack_slot);
+
+	if (dev->tx_cnt) {
+		u16 ctrl;
+		int slot = dev->ack_slot, n = 0;
+	      again:
+		ctrl = dev->tx_desc[slot].ctrl;
+		if (!(ctrl & MAL_TX_CTRL_READY)) {
+			struct sk_buff *skb = dev->tx_skb[slot];
+			++n;
+
+			if (skb) {
+				dev_kfree_skb(skb);
+				dev->tx_skb[slot] = NULL;
+			}
+			slot = (slot + 1) % NUM_TX_BUFF;
+
+			if (unlikely(EMAC_IS_BAD_TX(ctrl)))
+				emac_parse_tx_error(dev, ctrl);
+
+			if (--dev->tx_cnt)
+				goto again;
+		}
+		if (n) {
+			dev->ack_slot = slot;
+			if (netif_queue_stopped(dev->ndev) &&
+			    dev->tx_cnt < EMAC_TX_WAKEUP_THRESH)
+				netif_wake_queue(dev->ndev);
+
+			DBG2("%d: tx %d pkts" NL, dev->def->index, n);
+		}
+	}
+}
+
+static inline void emac_recycle_rx_skb(struct ocp_enet_private *dev, int slot,
+				       int len)
+{
+	struct sk_buff *skb = dev->rx_skb[slot];
+	DBG2("%d: recycle %d %d" NL, dev->def->index, slot, len);
+
+	if (len) 
+		dma_map_single(dev->ldev, skb->data - 2, 
+			       EMAC_DMA_ALIGN(len + 2), DMA_FROM_DEVICE);
+
+	dev->rx_desc[slot].data_len = 0;
+	barrier();
+	dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY |
+	    (slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0);
+}
+
+static void emac_parse_rx_error(struct ocp_enet_private *dev, u16 ctrl)
+{
+	struct ibm_emac_error_stats *st = &dev->estats;
+	DBG("%d: BD RX error %04x" NL, dev->def->index, ctrl);
+
+	++st->rx_bd_errors;
+	if (ctrl & EMAC_RX_ST_OE)
+		++st->rx_bd_overrun;
+	if (ctrl & EMAC_RX_ST_BP)
+		++st->rx_bd_bad_packet;
+	if (ctrl & EMAC_RX_ST_RP)
+		++st->rx_bd_runt_packet;
+	if (ctrl & EMAC_RX_ST_SE)
+		++st->rx_bd_short_event;
+	if (ctrl & EMAC_RX_ST_AE)
+		++st->rx_bd_alignment_error;
+	if (ctrl & EMAC_RX_ST_BFCS)
+		++st->rx_bd_bad_fcs;
+	if (ctrl & EMAC_RX_ST_PTL)
+		++st->rx_bd_packet_too_long;
+	if (ctrl & EMAC_RX_ST_ORE)
+		++st->rx_bd_out_of_range;
+	if (ctrl & EMAC_RX_ST_IRE)
+		++st->rx_bd_in_range;
+}
+
+static inline void emac_rx_csum(struct ocp_enet_private *dev,
+				struct sk_buff *skb, u16 ctrl)
+{
+#if defined(CONFIG_IBM_EMAC_TAH)
+	if (!ctrl && dev->tah_dev) {
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		++dev->stats.rx_packets_csum;
+	}
+#endif
+}
+
+static inline int emac_rx_sg_append(struct ocp_enet_private *dev, int slot)
+{
+	if (likely(dev->rx_sg_skb != NULL)) {
+		int len = dev->rx_desc[slot].data_len;
+		int tot_len = dev->rx_sg_skb->len + len;
+
+		if (unlikely(tot_len + 2 > dev->rx_skb_size)) {
+			++dev->estats.rx_dropped_mtu;
+			dev_kfree_skb(dev->rx_sg_skb);
+			dev->rx_sg_skb = NULL;
+		} else {
+			cacheable_memcpy(dev->rx_sg_skb->tail,
+					 dev->rx_skb[slot]->data, len);
+			skb_put(dev->rx_sg_skb, len);
+			emac_recycle_rx_skb(dev, slot, len);
+			return 0;
+		}
+	}
+	emac_recycle_rx_skb(dev, slot, 0);
+	return -1;
+}
+
+/* BHs disabled */
+static int emac_poll_rx(void *param, int budget)
+{
+	struct ocp_enet_private *dev = param;
+	int slot = dev->rx_slot, received = 0;
+
+	DBG2("%d: poll_rx(%d)" NL, dev->def->index, budget);
+
+      again:
+	while (budget > 0) {
+		int len;
+		struct sk_buff *skb;
+		u16 ctrl = dev->rx_desc[slot].ctrl;
+
+		if (ctrl & MAL_RX_CTRL_EMPTY)
+			break;
+
+		skb = dev->rx_skb[slot];
+		barrier();
+		len = dev->rx_desc[slot].data_len;
+
+		if (unlikely(!MAL_IS_SINGLE_RX(ctrl)))
+			goto sg;
+
+		ctrl &= EMAC_BAD_RX_MASK;
+		if (unlikely(ctrl && ctrl != EMAC_RX_TAH_BAD_CSUM)) {
+			emac_parse_rx_error(dev, ctrl);
+			++dev->estats.rx_dropped_error;
+			emac_recycle_rx_skb(dev, slot, 0);
+			len = 0;
+			goto next;
+		}
+
+		if (len && len < EMAC_RX_COPY_THRESH) {
+			struct sk_buff *copy_skb =
+			    alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC);
+			if (unlikely(!copy_skb))
+				goto oom;
+
+			skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2);
+			cacheable_memcpy(copy_skb->data - 2, skb->data - 2,
+					 len + 2);
+			emac_recycle_rx_skb(dev, slot, len);
+			skb = copy_skb;
+		} else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC)))
+			goto oom;
+
+		skb_put(skb, len);
+	      push_packet:
+		skb->dev = dev->ndev;
+		skb->protocol = eth_type_trans(skb, dev->ndev);
+		emac_rx_csum(dev, skb, ctrl);
+
+		if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+			++dev->estats.rx_dropped_stack;
+	      next:
+		++dev->stats.rx_packets;
+	      skip:
+		dev->stats.rx_bytes += len;
+		slot = (slot + 1) % NUM_RX_BUFF;
+		--budget;
+		++received;
+		continue;
+	      sg:
+		if (ctrl & MAL_RX_CTRL_FIRST) {
+			BUG_ON(dev->rx_sg_skb);
+			if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) {
+				DBG("%d: rx OOM %d" NL, dev->def->index, slot);
+				++dev->estats.rx_dropped_oom;
+				emac_recycle_rx_skb(dev, slot, 0);
+			} else {
+				dev->rx_sg_skb = skb;
+				skb_put(skb, len);
+			}
+		} else if (!emac_rx_sg_append(dev, slot) &&
+			   (ctrl & MAL_RX_CTRL_LAST)) {
+
+			skb = dev->rx_sg_skb;
+			dev->rx_sg_skb = NULL;
+
+			ctrl &= EMAC_BAD_RX_MASK;
+			if (unlikely(ctrl && ctrl != EMAC_RX_TAH_BAD_CSUM)) {
+				emac_parse_rx_error(dev, ctrl);
+				++dev->estats.rx_dropped_error;
+				dev_kfree_skb(skb);
+				len = 0;
+			} else
+				goto push_packet;
+		}
+		goto skip;
+	      oom:
+		DBG("%d: rx OOM %d" NL, dev->def->index, slot);
+		/* Drop the packet and recycle skb */
+		++dev->estats.rx_dropped_oom;
+		emac_recycle_rx_skb(dev, slot, 0);
+		goto next;
+	}
+
+	if (received) {
+		DBG2("%d: rx %d BDs" NL, dev->def->index, received);
+		dev->rx_slot = slot;
+	}
+
+	if (unlikely(budget && dev->commac.rx_stopped)) {
+		struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+		barrier();
+		if (!(dev->rx_desc[slot].ctrl & MAL_RX_CTRL_EMPTY)) {
+			DBG2("%d: rx restart" NL, dev->def->index);
+			received = 0;
+			goto again;
+		}
+
+		if (dev->rx_sg_skb) {
+			DBG2("%d: dropping partial rx packet" NL,
+			     dev->def->index);
+			++dev->estats.rx_dropped_error;
+			dev_kfree_skb(dev->rx_sg_skb);
+			dev->rx_sg_skb = NULL;
+		}
+
+		dev->commac.rx_stopped = 0;
+		mal_enable_rx_channel(dev->mal, emacdata->mal_rx_chan);
+		emac_rx_enable(dev);
+		dev->rx_slot = 0;
+	}
+	return received;
+}
+
+/* BHs disabled */
+static int emac_peek_rx(void *param)
+{
+	struct ocp_enet_private *dev = param;
+	return !(dev->rx_desc[dev->rx_slot].ctrl & MAL_RX_CTRL_EMPTY);
+}
+
+/* BHs disabled */
+static int emac_peek_rx_sg(void *param)
+{
+	struct ocp_enet_private *dev = param;
+	int slot = dev->rx_slot;
+	while (1) {
+		u16 ctrl = dev->rx_desc[slot].ctrl;
+		if (ctrl & MAL_RX_CTRL_EMPTY)
+			return 0;
+		else if (ctrl & MAL_RX_CTRL_LAST)
+			return 1;
+
+		slot = (slot + 1) % NUM_RX_BUFF;
+
+		/* I'm just being paranoid here :) */
+		if (unlikely(slot == dev->rx_slot))
+			return 0;
+	}
+}
+
+/* Hard IRQ */
+static void emac_rxde(void *param)
+{
+	struct ocp_enet_private *dev = param;
+	++dev->estats.rx_stopped;
+	emac_rx_disable_async(dev);
+}
+
+/* Hard IRQ */
+static irqreturn_t emac_irq(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ocp_enet_private *dev = dev_instance;
+	struct emac_regs *p = dev->emacp;
+	struct ibm_emac_error_stats *st = &dev->estats;
+
+	u32 isr = in_be32(&p->isr);
+	out_be32(&p->isr, isr);
+
+	DBG("%d: isr = %08x" NL, dev->def->index, isr);
+
+	if (isr & EMAC_ISR_TXPE)
+		++st->tx_parity;
+	if (isr & EMAC_ISR_RXPE)
+		++st->rx_parity;
+	if (isr & EMAC_ISR_TXUE)
+		++st->tx_underrun;
+	if (isr & EMAC_ISR_RXOE)
+		++st->rx_fifo_overrun;
+	if (isr & EMAC_ISR_OVR)
+		++st->rx_overrun;
+	if (isr & EMAC_ISR_BP)
+		++st->rx_bad_packet;
+	if (isr & EMAC_ISR_RP)
+		++st->rx_runt_packet;
+	if (isr & EMAC_ISR_SE)
+		++st->rx_short_event;
+	if (isr & EMAC_ISR_ALE)
+		++st->rx_alignment_error;
+	if (isr & EMAC_ISR_BFCS)
+		++st->rx_bad_fcs;
+	if (isr & EMAC_ISR_PTLE)
+		++st->rx_packet_too_long;
+	if (isr & EMAC_ISR_ORE)
+		++st->rx_out_of_range;
+	if (isr & EMAC_ISR_IRE)
+		++st->rx_in_range;
+	if (isr & EMAC_ISR_SQE)
+		++st->tx_sqe;
+	if (isr & EMAC_ISR_TE)
+		++st->tx_errors;
 
 	return IRQ_HANDLED;
 }
 
-static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static struct net_device_stats *emac_stats(struct net_device *ndev)
 {
-	unsigned short ctrl;
-	unsigned long flags;
-	struct ocp_enet_private *fep = dev->priv;
-	emac_t *emacp = fep->emacp;
-	int len = skb->len;
-	unsigned int offset = 0, size, f, tx_slot_first;
-	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
+	struct ocp_enet_private *dev = ndev->priv;
+	struct ibm_emac_stats *st = &dev->stats;
+	struct ibm_emac_error_stats *est = &dev->estats;
+	struct net_device_stats *nst = &dev->nstats;
 
-	spin_lock_irqsave(&fep->lock, flags);
+	DBG2("%d: stats" NL, dev->def->index);
 
-	len -= skb->data_len;
+	/* Compute "legacy" statistics */
+	local_irq_disable();
+	nst->rx_packets = (unsigned long)st->rx_packets;
+	nst->rx_bytes = (unsigned long)st->rx_bytes;
+	nst->tx_packets = (unsigned long)st->tx_packets;
+	nst->tx_bytes = (unsigned long)st->tx_bytes;
+	nst->rx_dropped = (unsigned long)(est->rx_dropped_oom +
+					  est->rx_dropped_error +
+					  est->rx_dropped_resize +
+					  est->rx_dropped_mtu);
+	nst->tx_dropped = (unsigned long)est->tx_dropped;
 
-	if ((fep->tx_cnt + nr_frags + len / DESC_BUF_SIZE + 1) > NUM_TX_BUFF) {
-		PKT_DEBUG(("emac_start_xmit() stopping queue\n"));
-		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&fep->lock, flags);
-		return -EBUSY;
-	}
+	nst->rx_errors = (unsigned long)est->rx_bd_errors;
+	nst->rx_fifo_errors = (unsigned long)(est->rx_bd_overrun +
+					      est->rx_fifo_overrun +
+					      est->rx_overrun);
+	nst->rx_frame_errors = (unsigned long)(est->rx_bd_alignment_error +
+					       est->rx_alignment_error);
+	nst->rx_crc_errors = (unsigned long)(est->rx_bd_bad_fcs +
+					     est->rx_bad_fcs);
+	nst->rx_length_errors = (unsigned long)(est->rx_bd_runt_packet +
+						est->rx_bd_short_event +
+						est->rx_bd_packet_too_long +
+						est->rx_bd_out_of_range +
+						est->rx_bd_in_range +
+						est->rx_runt_packet +
+						est->rx_short_event +
+						est->rx_packet_too_long +
+						est->rx_out_of_range +
+						est->rx_in_range);
 
-	tx_slot_first = fep->tx_slot;
-
-	while (len) {
-		size = min(len, DESC_BUF_SIZE);
-
-		fep->tx_desc[fep->tx_slot].data_len = (short)size;
-		fep->tx_desc[fep->tx_slot].data_ptr =
-		    (unsigned char *)dma_map_single(&fep->ocpdev->dev,
-						    (void *)((unsigned int)skb->
-							     data + offset),
-						    size, DMA_TO_DEVICE);
-
-		ctrl = EMAC_TX_CTRL_DFLT;
-		if (fep->tx_slot != tx_slot_first)
-			ctrl |= MAL_TX_CTRL_READY;
-		if ((NUM_TX_BUFF - 1) == fep->tx_slot)
-			ctrl |= MAL_TX_CTRL_WRAP;
-		if (!nr_frags && (len == size)) {
-			ctrl |= MAL_TX_CTRL_LAST;
-			fep->tx_skb[fep->tx_slot] = skb;
-		}
-		if (skb->ip_summed == CHECKSUM_HW)
-			ctrl |= EMAC_TX_CTRL_TAH_CSUM;
-
-		fep->tx_desc[fep->tx_slot].ctrl = ctrl;
-
-		len -= size;
-		offset += size;
-
-		/* Bump tx count */
-		if (++fep->tx_cnt == NUM_TX_BUFF)
-			netif_stop_queue(dev);
-
-		/* Next descriptor */
-		if (++fep->tx_slot == NUM_TX_BUFF)
-			fep->tx_slot = 0;
-	}
-
-	for (f = 0; f < nr_frags; f++) {
-		struct skb_frag_struct *frag;
-
-		frag = &skb_shinfo(skb)->frags[f];
-		len = frag->size;
-		offset = 0;
-
-		while (len) {
-			size = min(len, DESC_BUF_SIZE);
-
-			dma_map_page(&fep->ocpdev->dev,
-				     frag->page,
-				     frag->page_offset + offset,
-				     size, DMA_TO_DEVICE);
-
-			ctrl = EMAC_TX_CTRL_DFLT | MAL_TX_CTRL_READY;
-			if ((NUM_TX_BUFF - 1) == fep->tx_slot)
-				ctrl |= MAL_TX_CTRL_WRAP;
-			if ((f == (nr_frags - 1)) && (len == size)) {
-				ctrl |= MAL_TX_CTRL_LAST;
-				fep->tx_skb[fep->tx_slot] = skb;
-			}
-
-			if (skb->ip_summed == CHECKSUM_HW)
-				ctrl |= EMAC_TX_CTRL_TAH_CSUM;
-
-			fep->tx_desc[fep->tx_slot].data_len = (short)size;
-			fep->tx_desc[fep->tx_slot].data_ptr =
-			    (char *)((page_to_pfn(frag->page) << PAGE_SHIFT) +
-				     frag->page_offset + offset);
-			fep->tx_desc[fep->tx_slot].ctrl = ctrl;
-
-			len -= size;
-			offset += size;
-
-			/* Bump tx count */
-			if (++fep->tx_cnt == NUM_TX_BUFF)
-				netif_stop_queue(dev);
-
-			/* Next descriptor */
-			if (++fep->tx_slot == NUM_TX_BUFF)
-				fep->tx_slot = 0;
-		}
-	}
-
-	/*
-	 * Deferred set READY on first descriptor of packet to
-	 * avoid TX MAL race.
-	 */
-	fep->tx_desc[tx_slot_first].ctrl |= MAL_TX_CTRL_READY;
-
-	/* Send the packet out. */
-	out_be32(&emacp->em0tmr0, EMAC_TMR0_XMIT);
-
-	fep->stats.tx_packets++;
-	fep->stats.tx_bytes += skb->len;
-
-	PKT_DEBUG(("emac_start_xmit() exitn"));
-
-	spin_unlock_irqrestore(&fep->lock, flags);
-
-	return 0;
+	nst->tx_errors = (unsigned long)(est->tx_bd_errors + est->tx_errors);
+	nst->tx_fifo_errors = (unsigned long)(est->tx_bd_underrun +
+					      est->tx_underrun);
+	nst->tx_carrier_errors = (unsigned long)est->tx_bd_carrier_loss;
+	nst->collisions = (unsigned long)(est->tx_bd_excessive_deferral +
+					  est->tx_bd_excessive_collisions +
+					  est->tx_bd_late_collision +
+					  est->tx_bd_multple_collisions);
+	local_irq_enable();
+	return nst;
 }
 
-static int emac_adjust_to_link(struct ocp_enet_private *fep)
+static void emac_remove(struct ocp_device *ocpdev)
 {
-	emac_t *emacp = fep->emacp;
-	unsigned long mode_reg;
-	int full_duplex, speed;
+	struct ocp_enet_private *dev = ocp_get_drvdata(ocpdev);
 
-	full_duplex = 0;
-	speed = SPEED_10;
+	DBG("%d: remove" NL, dev->def->index);
 
-	/* set mode register 1 defaults */
-	mode_reg = EMAC_M1_DEFAULT;
+	ocp_set_drvdata(ocpdev, 0);
+	unregister_netdev(dev->ndev);
 
-	/* Read link mode on PHY */
-	if (fep->phy_mii.def->ops->read_link(&fep->phy_mii) == 0) {
-		/* If an error occurred, we don't deal with it yet */
-		full_duplex = (fep->phy_mii.duplex == DUPLEX_FULL);
-		speed = fep->phy_mii.speed;
-	}
+	tah_fini(dev->tah_dev);
+	rgmii_fini(dev->rgmii_dev, dev->rgmii_input);
+	zmii_fini(dev->zmii_dev, dev->zmii_input);
 
+	emac_dbg_register(dev->def->index, 0);
 
-	/* set speed (default is 10Mb) */
-	switch (speed) {
-	case SPEED_1000:
-		mode_reg |= EMAC_M1_RFS_16K;
-		if (fep->rgmii_dev) {
-			struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(fep->rgmii_dev);
-
-			if ((rgmii->mode[fep->rgmii_input] == RTBI)
-			    || (rgmii->mode[fep->rgmii_input] == TBI))
-				mode_reg |= EMAC_M1_MF_1000GPCS;
-			else
-				mode_reg |= EMAC_M1_MF_1000MBPS;
-
-			emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input,
-					      1000);
-		}
-		break;
-	case SPEED_100:
-		mode_reg |= EMAC_M1_MF_100MBPS | EMAC_M1_RFS_4K;
-		if (fep->rgmii_dev)
-			emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input,
-					      100);
-		if (fep->zmii_dev)
-			emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input,
-					     100);
-		break;
-	case SPEED_10:
-	default:
-		mode_reg = (mode_reg & ~EMAC_M1_MF_100MBPS) | EMAC_M1_RFS_4K;
-		if (fep->rgmii_dev)
-			emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input,
-					      10);
-		if (fep->zmii_dev)
-			emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input,
-					     10);
-	}
-
-	if (full_duplex)
-		mode_reg |= EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_IST;
-	else
-		mode_reg &= ~(EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_ILE);
-
-	LINK_DEBUG(("%s: adjust to link, speed: %d, duplex: %d, opened: %d\n",
-		    fep->ndev->name, speed, full_duplex, fep->opened));
-
-	printk(KERN_INFO "%s: Speed: %d, %s duplex.\n",
-	       fep->ndev->name, speed, full_duplex ? "Full" : "Half");
-	if (fep->opened)
-		out_be32(&emacp->em0mr1, mode_reg);
-
-	return 0;
+	mal_unregister_commac(dev->mal, &dev->commac);
+	iounmap((void *)dev->emacp);
+	kfree(dev->ndev);
 }
 
-static int emac_set_mac_address(struct net_device *ndev, void *p)
+static struct mal_commac_ops emac_commac_ops = {
+	.poll_tx = &emac_poll_tx,
+	.poll_rx = &emac_poll_rx,
+	.peek_rx = &emac_peek_rx,
+	.rxde = &emac_rxde,
+};
+
+static struct mal_commac_ops emac_commac_sg_ops = {
+	.poll_tx = &emac_poll_tx,
+	.poll_rx = &emac_poll_rx,
+	.peek_rx = &emac_peek_rx_sg,
+	.rxde = &emac_rxde,
+};
+
+/* Ethtool support */
+static int emac_ethtool_get_settings(struct net_device *ndev,
+				     struct ethtool_cmd *cmd)
 {
-	struct ocp_enet_private *fep = ndev->priv;
-	emac_t *emacp = fep->emacp;
-	struct sockaddr *addr = p;
+	struct ocp_enet_private *dev = ndev->priv;
 
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
-
-	/* set the high address */
-	out_be32(&emacp->em0iahr,
-		 (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);
-
-	/* set the low address */
-	out_be32(&emacp->em0ialr,
-		 (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16)
-		 | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]);
-
-	return 0;
-}
-
-static int emac_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct ocp_enet_private *fep = dev->priv;
-	int old_mtu = dev->mtu;
-	unsigned long mode_reg;
-	emac_t *emacp = fep->emacp;
-	u32 em0mr0;
-	int i, full;
-	unsigned long flags;
-
-	if ((new_mtu < EMAC_MIN_MTU) || (new_mtu > EMAC_MAX_MTU)) {
-		printk(KERN_ERR
-		       "emac: Invalid MTU setting, MTU must be between %d and %d\n",
-		       EMAC_MIN_MTU, EMAC_MAX_MTU);
-		return -EINVAL;
-	}
-
-	if (old_mtu != new_mtu && netif_running(dev)) {
-		/* Stop rx engine */
-		em0mr0 = in_be32(&emacp->em0mr0);
-		out_be32(&emacp->em0mr0, em0mr0 & ~EMAC_M0_RXE);
-
-		/* Wait for descriptors to be empty */
-		do {
-			full = 0;
-			for (i = 0; i < NUM_RX_BUFF; i++)
-				if (!(fep->rx_desc[i].ctrl & MAL_RX_CTRL_EMPTY)) {
-					printk(KERN_NOTICE
-					       "emac: RX ring is still full\n");
-					full = 1;
-				}
-		} while (full);
-
-		spin_lock_irqsave(&fep->lock, flags);
-
-		mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-
-		/* Destroy all old rx skbs */
-		for (i = 0; i < NUM_RX_BUFF; i++) {
-			dma_unmap_single(&fep->ocpdev->dev,
-					 fep->rx_desc[i].data_ptr,
-					 fep->rx_desc[i].data_len,
-					 DMA_FROM_DEVICE);
-			dev_kfree_skb(fep->rx_skb[i]);
-			fep->rx_skb[i] = NULL;
-		}
-
-		/* Set new rx_buffer_size, jumbo cap, and advertise new mtu */
-		mode_reg = in_be32(&emacp->em0mr1);
-		if (new_mtu > ENET_DEF_MTU_SIZE) {
-			mode_reg |= EMAC_M1_JUMBO_ENABLE;
-			fep->rx_buffer_size = EMAC_MAX_FRAME;
-		} else {
-			mode_reg &= ~EMAC_M1_JUMBO_ENABLE;
-			fep->rx_buffer_size = ENET_DEF_BUF_SIZE;
-		}
-		dev->mtu = new_mtu;
-		out_be32(&emacp->em0mr1, mode_reg);
-
-		/* Re-init rx skbs */
-		fep->rx_slot = 0;
-		emac_rx_fill(dev, 0);
-
-		/* Restart the rx engine */
-		mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-		out_be32(&emacp->em0mr0, em0mr0 | EMAC_M0_RXE);
-
-		spin_unlock_irqrestore(&fep->lock, flags);
-	}
-
-	return 0;
-}
-
-static void __emac_set_multicast_list(struct net_device *dev)
-{
-	struct ocp_enet_private *fep = dev->priv;
-	emac_t *emacp = fep->emacp;
-	u32 rmr = in_be32(&emacp->em0rmr);
-
-	/* First clear all special bits, they can be set later */
-	rmr &= ~(EMAC_RMR_PME | EMAC_RMR_PMME | EMAC_RMR_MAE);
-
-	if (dev->flags & IFF_PROMISC) {
-		rmr |= EMAC_RMR_PME;
-	} else if (dev->flags & IFF_ALLMULTI || 32 < dev->mc_count) {
-		/*
-		 * Must be setting up to use multicast
-		 * Now check for promiscuous multicast
-		 */
-		rmr |= EMAC_RMR_PMME;
-	} else if (dev->flags & IFF_MULTICAST && 0 < dev->mc_count) {
-		unsigned short em0gaht[4] = { 0, 0, 0, 0 };
-		struct dev_mc_list *dmi;
-
-		/* Need to hash on the multicast address. */
-		for (dmi = dev->mc_list; dmi; dmi = dmi->next) {
-			unsigned long mc_crc;
-			unsigned int bit_number;
-
-			mc_crc = ether_crc(6, (char *)dmi->dmi_addr);
-			bit_number = 63 - (mc_crc >> 26);	/* MSB: 0 LSB: 63 */
-			em0gaht[bit_number >> 4] |=
-			    0x8000 >> (bit_number & 0x0f);
-		}
-		emacp->em0gaht1 = em0gaht[0];
-		emacp->em0gaht2 = em0gaht[1];
-		emacp->em0gaht3 = em0gaht[2];
-		emacp->em0gaht4 = em0gaht[3];
-
-		/* Turn on multicast addressing */
-		rmr |= EMAC_RMR_MAE;
-	}
-	out_be32(&emacp->em0rmr, rmr);
-}
-
-static int emac_init_tah(struct ocp_enet_private *fep)
-{
-	tah_t *tahp;
-
-	/* Initialize TAH and enable checksum verification */
-	tahp = (tah_t *) ioremap(fep->tah_dev->def->paddr, sizeof(*tahp));
-
-	if (tahp == NULL) {
-		printk(KERN_ERR "tah%d: Cannot ioremap TAH registers!\n",
-		       fep->tah_dev->def->index);
-
-		return -ENOMEM;
-	}
-
-	out_be32(&tahp->tah_mr, TAH_MR_SR);
-
-	/* wait for reset to complete */
-	while (in_be32(&tahp->tah_mr) & TAH_MR_SR) ;
-
-	/* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
-	out_be32(&tahp->tah_mr,
-		 TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
-		 TAH_MR_DIG);
-
-	iounmap(tahp);
-
-	return 0;
-}
-
-static void emac_init_rings(struct net_device *dev)
-{
-	struct ocp_enet_private *ep = dev->priv;
-	int loop;
-
-	ep->tx_desc = (struct mal_descriptor *)((char *)ep->mal->tx_virt_addr +
-						(ep->mal_tx_chan *
-						 MAL_DT_ALIGN));
-	ep->rx_desc =
-	    (struct mal_descriptor *)((char *)ep->mal->rx_virt_addr +
-				      (ep->mal_rx_chan * MAL_DT_ALIGN));
-
-	/* Fill in the transmit descriptor ring. */
-	for (loop = 0; loop < NUM_TX_BUFF; loop++) {
-		if (ep->tx_skb[loop]) {
-			dma_unmap_single(&ep->ocpdev->dev,
-					 ep->tx_desc[loop].data_ptr,
-					 ep->tx_desc[loop].data_len,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb_irq(ep->tx_skb[loop]);
-		}
-		ep->tx_skb[loop] = NULL;
-		ep->tx_desc[loop].ctrl = 0;
-		ep->tx_desc[loop].data_len = 0;
-		ep->tx_desc[loop].data_ptr = NULL;
-	}
-	ep->tx_desc[loop - 1].ctrl |= MAL_TX_CTRL_WRAP;
-
-	/* Format the receive descriptor ring. */
-	ep->rx_slot = 0;
-	/* Default is MTU=1500 + Ethernet overhead */
-	ep->rx_buffer_size = dev->mtu + ENET_HEADER_SIZE + ENET_FCS_SIZE;
-	emac_rx_fill(dev, 0);
-	if (ep->rx_slot != 0) {
-		printk(KERN_ERR
-		       "%s: Not enough mem for RxChain durning Open?\n",
-		       dev->name);
-		/*We couldn't fill the ring at startup?
-		 *We could clean up and fail to open but right now we will try to
-		 *carry on. It may be a sign of a bad NUM_RX_BUFF value
-		 */
-	}
-
-	ep->tx_cnt = 0;
-	ep->tx_slot = 0;
-	ep->ack_slot = 0;
-}
-
-static void emac_reset_configure(struct ocp_enet_private *fep)
-{
-	emac_t *emacp = fep->emacp;
-	int i;
-
-	mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
-	mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-
-	/*
-	 * Check for a link, some PHYs don't provide a clock if
-	 * no link is present.  Some EMACs will not come out of
-	 * soft reset without a PHY clock present.
-	 */
-	if (fep->phy_mii.def->ops->poll_link(&fep->phy_mii)) {
-		/* Reset the EMAC */
-		out_be32(&emacp->em0mr0, EMAC_M0_SRST);
-		udelay(20);
-		for (i = 0; i < 100; i++) {
-			if ((in_be32(&emacp->em0mr0) & EMAC_M0_SRST) == 0)
-				break;
-			udelay(10);
-		}
-
-		if (i >= 100) {
-			printk(KERN_ERR "%s: Cannot reset EMAC\n",
-			       fep->ndev->name);
-			return;
-		}
-	}
-
-	/* Switch IRQs off for now */
-	out_be32(&emacp->em0iser, 0);
-
-	/* Configure MAL rx channel */
-	mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG);
-
-	/* set the high address */
-	out_be32(&emacp->em0iahr,
-		 (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]);
-
-	/* set the low address */
-	out_be32(&emacp->em0ialr,
-		 (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16)
-		 | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]);
-
-	/* Adjust to link */
-	if (netif_carrier_ok(fep->ndev))
-		emac_adjust_to_link(fep);
-
-	/* enable broadcast/individual address and RX FIFO defaults */
-	out_be32(&emacp->em0rmr, EMAC_RMR_DEFAULT);
-
-	/* set transmit request threshold register */
-	out_be32(&emacp->em0trtr, EMAC_TRTR_DEFAULT);
-
-	/* Reconfigure multicast */
-	__emac_set_multicast_list(fep->ndev);
-
-	/* Set receiver/transmitter defaults */
-	out_be32(&emacp->em0rwmr, EMAC_RWMR_DEFAULT);
-	out_be32(&emacp->em0tmr0, EMAC_TMR0_DEFAULT);
-	out_be32(&emacp->em0tmr1, EMAC_TMR1_DEFAULT);
-
-	/* set frame gap */
-	out_be32(&emacp->em0ipgvr, CONFIG_IBM_EMAC_FGAP);
-	
-	/* set VLAN Tag Protocol Identifier */
-	out_be32(&emacp->em0vtpid, 0x8100);
-
-	/* Init ring buffers */
-	emac_init_rings(fep->ndev);
-}
-
-static void emac_kick(struct ocp_enet_private *fep)
-{
-	emac_t *emacp = fep->emacp;
-	unsigned long emac_ier;
-
-	emac_ier = EMAC_ISR_PP | EMAC_ISR_BP | EMAC_ISR_RP |
-	    EMAC_ISR_SE | EMAC_ISR_PTLE | EMAC_ISR_ALE |
-	    EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE;
-
-	out_be32(&emacp->em0iser, emac_ier);
-
-	/* enable all MAL transmit and receive channels */
-	mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
-	mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-
-	/* set transmit and receive enable */
-	out_be32(&emacp->em0mr0, EMAC_M0_TXE | EMAC_M0_RXE);
-}
-
-static void
-emac_start_link(struct ocp_enet_private *fep, struct ethtool_cmd *ep)
-{
-	u32 advertise;
-	int autoneg;
-	int forced_speed;
-	int forced_duplex;
-
-	/* Default advertise */
-	advertise = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-	    ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-	    ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full;
-	autoneg = fep->want_autoneg;
-	forced_speed = fep->phy_mii.speed;
-	forced_duplex = fep->phy_mii.duplex;
-
-	/* Setup link parameters */
-	if (ep) {
-		if (ep->autoneg == AUTONEG_ENABLE) {
-			advertise = ep->advertising;
-			autoneg = 1;
-		} else {
-			autoneg = 0;
-			forced_speed = ep->speed;
-			forced_duplex = ep->duplex;
-		}
-	}
-
-	/* Configure PHY & start aneg */
-	fep->want_autoneg = autoneg;
-	if (autoneg) {
-		LINK_DEBUG(("%s: start link aneg, advertise: 0x%x\n",
-			    fep->ndev->name, advertise));
-		fep->phy_mii.def->ops->setup_aneg(&fep->phy_mii, advertise);
-	} else {
-		LINK_DEBUG(("%s: start link forced, speed: %d, duplex: %d\n",
-			    fep->ndev->name, forced_speed, forced_duplex));
-		fep->phy_mii.def->ops->setup_forced(&fep->phy_mii, forced_speed,
-						    forced_duplex);
-	}
-	fep->timer_ticks = 0;
-	mod_timer(&fep->link_timer, jiffies + HZ);
-}
-
-static void emac_link_timer(unsigned long data)
-{
-	struct ocp_enet_private *fep = (struct ocp_enet_private *)data;
-	int link;
-
-	if (fep->going_away)
-		return;
-
-	spin_lock_irq(&fep->lock);
-
-	link = fep->phy_mii.def->ops->poll_link(&fep->phy_mii);
-	LINK_DEBUG(("%s: poll_link: %d\n", fep->ndev->name, link));
-
-	if (link == netif_carrier_ok(fep->ndev)) {
-		if (!link && fep->want_autoneg && (++fep->timer_ticks) > 10)
-			emac_start_link(fep, NULL);
-		goto out;
-	}
-	printk(KERN_INFO "%s: Link is %s\n", fep->ndev->name,
-	       link ? "Up" : "Down");
-	if (link) {
-		netif_carrier_on(fep->ndev);
-		/* Chip needs a full reset on config change. That sucks, so I
-		 * should ultimately move that to some tasklet to limit
-		 * latency peaks caused by this code
-		 */
-		emac_reset_configure(fep);
-		if (fep->opened)
-			emac_kick(fep);
-	} else {
-		fep->timer_ticks = 0;
-		netif_carrier_off(fep->ndev);
-	}
-      out:
-	mod_timer(&fep->link_timer, jiffies + HZ);
-	spin_unlock_irq(&fep->lock);
-}
-
-static void emac_set_multicast_list(struct net_device *dev)
-{
-	struct ocp_enet_private *fep = dev->priv;
-
-	spin_lock_irq(&fep->lock);
-	__emac_set_multicast_list(dev);
-	spin_unlock_irq(&fep->lock);
-}
-
-static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
-{
-	struct ocp_enet_private *fep = ndev->priv;
-
-	cmd->supported = fep->phy_mii.def->features;
+	cmd->supported = dev->phy.features;
 	cmd->port = PORT_MII;
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->phy_address = fep->mii_phy_addr;
-	spin_lock_irq(&fep->lock);
-	cmd->autoneg = fep->want_autoneg;
-	cmd->speed = fep->phy_mii.speed;
-	cmd->duplex = fep->phy_mii.duplex;
-	spin_unlock_irq(&fep->lock);
+	cmd->phy_address = dev->phy.address;
+	cmd->transceiver =
+	    dev->phy.address >= 0 ? XCVR_EXTERNAL : XCVR_INTERNAL;
+
+	local_bh_disable();
+	cmd->advertising = dev->phy.advertising;
+	cmd->autoneg = dev->phy.autoneg;
+	cmd->speed = dev->phy.speed;
+	cmd->duplex = dev->phy.duplex;
+	local_bh_enable();
+
 	return 0;
 }
 
-static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+static int emac_ethtool_set_settings(struct net_device *ndev,
+				     struct ethtool_cmd *cmd)
 {
-	struct ocp_enet_private *fep = ndev->priv;
-	unsigned long features = fep->phy_mii.def->features;
+	struct ocp_enet_private *dev = ndev->priv;
+	u32 f = dev->phy.features;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
+	DBG("%d: set_settings(%d, %d, %d, 0x%08x)" NL, dev->def->index,
+	    cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising);
 
+	/* Basic sanity checks */
+	if (dev->phy.address < 0)
+		return -EOPNOTSUPP;
 	if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
 		return -EINVAL;
 	if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
 		return -EINVAL;
 	if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
 		return -EINVAL;
-	if (cmd->autoneg == AUTONEG_DISABLE)
+
+	if (cmd->autoneg == AUTONEG_DISABLE) {
 		switch (cmd->speed) {
 		case SPEED_10:
-			if (cmd->duplex == DUPLEX_HALF &&
-			    (features & SUPPORTED_10baseT_Half) == 0)
+			if (cmd->duplex == DUPLEX_HALF
+			    && !(f & SUPPORTED_10baseT_Half))
 				return -EINVAL;
-			if (cmd->duplex == DUPLEX_FULL &&
-			    (features & SUPPORTED_10baseT_Full) == 0)
+			if (cmd->duplex == DUPLEX_FULL
+			    && !(f & SUPPORTED_10baseT_Full))
 				return -EINVAL;
 			break;
 		case SPEED_100:
-			if (cmd->duplex == DUPLEX_HALF &&
-			    (features & SUPPORTED_100baseT_Half) == 0)
+			if (cmd->duplex == DUPLEX_HALF
+			    && !(f & SUPPORTED_100baseT_Half))
 				return -EINVAL;
-			if (cmd->duplex == DUPLEX_FULL &&
-			    (features & SUPPORTED_100baseT_Full) == 0)
+			if (cmd->duplex == DUPLEX_FULL
+			    && !(f & SUPPORTED_100baseT_Full))
 				return -EINVAL;
 			break;
 		case SPEED_1000:
-			if (cmd->duplex == DUPLEX_HALF &&
-			    (features & SUPPORTED_1000baseT_Half) == 0)
+			if (cmd->duplex == DUPLEX_HALF
+			    && !(f & SUPPORTED_1000baseT_Half))
 				return -EINVAL;
-			if (cmd->duplex == DUPLEX_FULL &&
-			    (features & SUPPORTED_1000baseT_Full) == 0)
+			if (cmd->duplex == DUPLEX_FULL
+			    && !(f & SUPPORTED_1000baseT_Full))
 				return -EINVAL;
 			break;
 		default:
 			return -EINVAL;
-	} else if ((features & SUPPORTED_Autoneg) == 0)
-		return -EINVAL;
-	spin_lock_irq(&fep->lock);
-	emac_start_link(fep, cmd);
-	spin_unlock_irq(&fep->lock);
+		}
+
+		local_bh_disable();
+		dev->phy.def->ops->setup_forced(&dev->phy, cmd->speed,
+						cmd->duplex);
+
+	} else {
+		if (!(f & SUPPORTED_Autoneg))
+			return -EINVAL;
+
+		local_bh_disable();
+		dev->phy.def->ops->setup_aneg(&dev->phy,
+					      (cmd->advertising & f) |
+					      (dev->phy.advertising &
+					       (ADVERTISED_Pause |
+						ADVERTISED_Asym_Pause)));
+	}
+	emac_force_link_update(dev);
+	local_bh_enable();
+
 	return 0;
 }
 
-static void
-emac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
+static void emac_ethtool_get_ringparam(struct net_device *ndev,
+				       struct ethtool_ringparam *rp)
 {
-	struct ocp_enet_private *fep = ndev->priv;
+	rp->rx_max_pending = rp->rx_pending = NUM_RX_BUFF;
+	rp->tx_max_pending = rp->tx_pending = NUM_TX_BUFF;
+}
 
-	strcpy(info->driver, DRV_NAME);
+static void emac_ethtool_get_pauseparam(struct net_device *ndev,
+					struct ethtool_pauseparam *pp)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+
+	local_bh_disable();
+	if ((dev->phy.features & SUPPORTED_Autoneg) &&
+	    (dev->phy.advertising & (ADVERTISED_Pause | ADVERTISED_Asym_Pause)))
+		pp->autoneg = 1;
+
+	if (dev->phy.duplex == DUPLEX_FULL) {
+		if (dev->phy.pause)
+			pp->rx_pause = pp->tx_pause = 1;
+		else if (dev->phy.asym_pause)
+			pp->tx_pause = 1;
+	}
+	local_bh_enable();
+}
+
+static u32 emac_ethtool_get_rx_csum(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	return dev->tah_dev != 0;
+}
+
+static int emac_get_regs_len(struct ocp_enet_private *dev)
+{
+	return sizeof(struct emac_ethtool_regs_subhdr) + EMAC_ETHTOOL_REGS_SIZE;
+}
+
+static int emac_ethtool_get_regs_len(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	return sizeof(struct emac_ethtool_regs_hdr) +
+	    emac_get_regs_len(dev) + mal_get_regs_len(dev->mal) +
+	    zmii_get_regs_len(dev->zmii_dev) +
+	    rgmii_get_regs_len(dev->rgmii_dev) +
+	    tah_get_regs_len(dev->tah_dev);
+}
+
+static void *emac_dump_regs(struct ocp_enet_private *dev, void *buf)
+{
+	struct emac_ethtool_regs_subhdr *hdr = buf;
+
+	hdr->version = EMAC_ETHTOOL_REGS_VER;
+	hdr->index = dev->def->index;
+	memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE);
+	return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE);
+}
+
+static void emac_ethtool_get_regs(struct net_device *ndev,
+				  struct ethtool_regs *regs, void *buf)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	struct emac_ethtool_regs_hdr *hdr = buf;
+
+	hdr->components = 0;
+	buf = hdr + 1;
+
+	local_irq_disable();
+	buf = mal_dump_regs(dev->mal, buf);
+	buf = emac_dump_regs(dev, buf);
+	if (dev->zmii_dev) {
+		hdr->components |= EMAC_ETHTOOL_REGS_ZMII;
+		buf = zmii_dump_regs(dev->zmii_dev, buf);
+	}
+	if (dev->rgmii_dev) {
+		hdr->components |= EMAC_ETHTOOL_REGS_RGMII;
+		buf = rgmii_dump_regs(dev->rgmii_dev, buf);
+	}
+	if (dev->tah_dev) {
+		hdr->components |= EMAC_ETHTOOL_REGS_TAH;
+		buf = tah_dump_regs(dev->tah_dev, buf);
+	}
+	local_irq_enable();
+}
+
+static int emac_ethtool_nway_reset(struct net_device *ndev)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	int res = 0;
+
+	DBG("%d: nway_reset" NL, dev->def->index);
+
+	if (dev->phy.address < 0)
+		return -EOPNOTSUPP;
+
+	local_bh_disable();
+	if (!dev->phy.autoneg) {
+		res = -EINVAL;
+		goto out;
+	}
+
+	dev->phy.def->ops->setup_aneg(&dev->phy, dev->phy.advertising);
+	emac_force_link_update(dev);
+
+      out:
+	local_bh_enable();
+	return res;
+}
+
+static int emac_ethtool_get_stats_count(struct net_device *ndev)
+{
+	return EMAC_ETHTOOL_STATS_COUNT;
+}
+
+static void emac_ethtool_get_strings(struct net_device *ndev, u32 stringset,
+				     u8 * buf)
+{
+	if (stringset == ETH_SS_STATS)
+		memcpy(buf, &emac_stats_keys, sizeof(emac_stats_keys));
+}
+
+static void emac_ethtool_get_ethtool_stats(struct net_device *ndev,
+					   struct ethtool_stats *estats,
+					   u64 * tmp_stats)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+	local_irq_disable();
+	memcpy(tmp_stats, &dev->stats, sizeof(dev->stats));
+	tmp_stats += sizeof(dev->stats) / sizeof(u64);
+	memcpy(tmp_stats, &dev->estats, sizeof(dev->estats));
+	local_irq_enable();
+}
+
+static void emac_ethtool_get_drvinfo(struct net_device *ndev,
+				     struct ethtool_drvinfo *info)
+{
+	struct ocp_enet_private *dev = ndev->priv;
+
+	strcpy(info->driver, "ibm_emac");
 	strcpy(info->version, DRV_VERSION);
 	info->fw_version[0] = '\0';
-	sprintf(info->bus_info, "IBM EMAC %d", fep->ocpdev->def->index);
-	info->regdump_len = 0;
-}
-
-static int emac_nway_reset(struct net_device *ndev)
-{
-	struct ocp_enet_private *fep = ndev->priv;
-
-	if (!fep->want_autoneg)
-		return -EINVAL;
-	spin_lock_irq(&fep->lock);
-	emac_start_link(fep, NULL);
-	spin_unlock_irq(&fep->lock);
-	return 0;
-}
-
-static u32 emac_get_link(struct net_device *ndev)
-{
-	return netif_carrier_ok(ndev);
+	sprintf(info->bus_info, "PPC 4xx EMAC %d", dev->def->index);
+	info->n_stats = emac_ethtool_get_stats_count(ndev);
+	info->regdump_len = emac_ethtool_get_regs_len(ndev);
 }
 
 static struct ethtool_ops emac_ethtool_ops = {
-	.get_settings = emac_get_settings,
-	.set_settings = emac_set_settings,
-	.get_drvinfo = emac_get_drvinfo,
-	.nway_reset = emac_nway_reset,
-	.get_link = emac_get_link
+	.get_settings = emac_ethtool_get_settings,
+	.set_settings = emac_ethtool_set_settings,
+	.get_drvinfo = emac_ethtool_get_drvinfo,
+
+	.get_regs_len = emac_ethtool_get_regs_len,
+	.get_regs = emac_ethtool_get_regs,
+
+	.nway_reset = emac_ethtool_nway_reset,
+
+	.get_ringparam = emac_ethtool_get_ringparam,
+	.get_pauseparam = emac_ethtool_get_pauseparam,
+
+	.get_rx_csum = emac_ethtool_get_rx_csum,
+
+	.get_strings = emac_ethtool_get_strings,
+	.get_stats_count = emac_ethtool_get_stats_count,
+	.get_ethtool_stats = emac_ethtool_get_ethtool_stats,
+
+	.get_link = ethtool_op_get_link,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.get_sg = ethtool_op_get_sg,
 };
 
-static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-	struct ocp_enet_private *fep = dev->priv;
+	struct ocp_enet_private *dev = ndev->priv;
 	uint16_t *data = (uint16_t *) & rq->ifr_ifru;
 
+	DBG("%d: ioctl %08x" NL, dev->def->index, cmd);
+
+	if (dev->phy.address < 0)
+		return -EOPNOTSUPP;
+
 	switch (cmd) {
 	case SIOCGMIIPHY:
-		data[0] = fep->mii_phy_addr;
+	case SIOCDEVPRIVATE:
+		data[0] = dev->phy.address;
 		/* Fall through */
 	case SIOCGMIIREG:
-		data[3] = emac_phy_read(dev, fep->mii_phy_addr, data[1]);
+	case SIOCDEVPRIVATE + 1:
+		data[3] = emac_mdio_read(ndev, dev->phy.address, data[1]);
 		return 0;
+
 	case SIOCSMIIREG:
+	case SIOCDEVPRIVATE + 2:
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-
-		emac_phy_write(dev, fep->mii_phy_addr, data[1], data[2]);
+		emac_mdio_write(ndev, dev->phy.address, data[1], data[2]);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
 	}
 }
 
-static int emac_open(struct net_device *dev)
+static int __init emac_probe(struct ocp_device *ocpdev)
 {
-	struct ocp_enet_private *fep = dev->priv;
-	int rc;
-
-	spin_lock_irq(&fep->lock);
-
-	fep->opened = 1;
-	netif_carrier_off(dev);
-
-	/* Reset & configure the chip */
-	emac_reset_configure(fep);
-
-	spin_unlock_irq(&fep->lock);
-
-	/* Request our interrupt lines */
-	rc = request_irq(dev->irq, emac_mac_irq, 0, "IBM EMAC MAC", dev);
-	if (rc != 0) {
-		printk("dev->irq %d failed\n", dev->irq);
-		goto bail;
-	}
-	/* Kick the chip rx & tx channels into life */
-	spin_lock_irq(&fep->lock);
-	emac_kick(fep);
-	spin_unlock_irq(&fep->lock);
-
-	netif_start_queue(dev);
-      bail:
-	return rc;
-}
-
-static int emac_close(struct net_device *dev)
-{
-	struct ocp_enet_private *fep = dev->priv;
-	emac_t *emacp = fep->emacp;
-
-	/* XXX Stop IRQ emitting here */
-	spin_lock_irq(&fep->lock);
-	fep->opened = 0;
-	mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask);
-	mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask);
-	netif_carrier_off(dev);
-	netif_stop_queue(dev);
-
-	/*
-	 * Check for a link, some PHYs don't provide a clock if
-	 * no link is present.  Some EMACs will not come out of
-	 * soft reset without a PHY clock present.
-	 */
-	if (fep->phy_mii.def->ops->poll_link(&fep->phy_mii)) {
-		out_be32(&emacp->em0mr0, EMAC_M0_SRST);
-		udelay(10);
-
-		if (emacp->em0mr0 & EMAC_M0_SRST) {
-			/*not sure what to do here hopefully it clears before another open */
-			printk(KERN_ERR
-			       "%s: Phy SoftReset didn't clear, no link?\n",
-			       dev->name);
-		}
-	}
-
-	/* Free the irq's */
-	free_irq(dev->irq, dev);
-
-	spin_unlock_irq(&fep->lock);
-
-	return 0;
-}
-
-static void emac_remove(struct ocp_device *ocpdev)
-{
-	struct net_device *dev = ocp_get_drvdata(ocpdev);
-	struct ocp_enet_private *ep = dev->priv;
-
-	/* FIXME: locking, races, ... */
-	ep->going_away = 1;
-	ocp_set_drvdata(ocpdev, NULL);
-	if (ep->rgmii_dev)
-		emac_close_rgmii(ep->rgmii_dev);
-	if (ep->zmii_dev)
-		emac_close_zmii(ep->zmii_dev);
-
-	unregister_netdev(dev);
-	del_timer_sync(&ep->link_timer);
-	mal_unregister_commac(ep->mal, &ep->commac);
-	iounmap((void *)ep->emacp);
-	kfree(dev);
-}
-
-struct mal_commac_ops emac_commac_ops = {
-	.txeob = &emac_txeob_dev,
-	.txde = &emac_txde_dev,
-	.rxeob = &emac_rxeob_dev,
-	.rxde = &emac_rxde_dev,
-};
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void emac_netpoll(struct net_device *ndev)
-{
-	emac_rxeob_dev((void *)ndev, 0);
-	emac_txeob_dev((void *)ndev, 0);
-}
-#endif
-
-static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
-{
-	int deferred_init = 0;
-	int rc = 0, i;
+	struct ocp_func_emac_data *emacdata = ocpdev->def->additions;
 	struct net_device *ndev;
-	struct ocp_enet_private *ep;
-	struct ocp_func_emac_data *emacdata;
-	int commac_reg = 0;
-	u32 phy_map;
+	struct ocp_device *maldev;
+	struct ocp_enet_private *dev;
+	int err, i;
 
-	emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions;
+	DBG("%d: probe" NL, ocpdev->def->index);
+
 	if (!emacdata) {
 		printk(KERN_ERR "emac%d: Missing additional data!\n",
 		       ocpdev->def->index);
@@ -1738,304 +1936,312 @@
 
 	/* Allocate our net_device structure */
 	ndev = alloc_etherdev(sizeof(struct ocp_enet_private));
-	if (ndev == NULL) {
-		printk(KERN_ERR
-		       "emac%d: Could not allocate ethernet device.\n",
+	if (!ndev) {
+		printk(KERN_ERR "emac%d: could not allocate ethernet device!\n",
 		       ocpdev->def->index);
 		return -ENOMEM;
 	}
-	ep = ndev->priv;
-	ep->ndev = ndev;
-	ep->ocpdev = ocpdev;
-	ndev->irq = ocpdev->def->irq;
-	ep->wol_irq = emacdata->wol_irq;
-	if (emacdata->mdio_idx >= 0) {
-		if (emacdata->mdio_idx == ocpdev->def->index) {
-			/* Set the common MDIO net_device */
-			mdio_ndev = ndev;
-			deferred_init = 1;
+	dev = ndev->priv;
+	dev->ndev = ndev;
+	dev->ldev = &ocpdev->dev;
+	dev->def = ocpdev->def;
+	SET_MODULE_OWNER(ndev);
+
+	/* Find MAL device we are connected to */
+	maldev =
+	    ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_MAL, emacdata->mal_idx);
+	if (!maldev) {
+		printk(KERN_ERR "emac%d: unknown mal%d device!\n",
+		       dev->def->index, emacdata->mal_idx);
+		err = -ENODEV;
+		goto out;
+	}
+	dev->mal = ocp_get_drvdata(maldev);
+	if (!dev->mal) {
+		printk(KERN_ERR "emac%d: mal%d hasn't been initialized yet!\n",
+		       dev->def->index, emacdata->mal_idx);
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* Register with MAL */
+	dev->commac.ops = &emac_commac_ops;
+	dev->commac.dev = dev;
+	dev->commac.tx_chan_mask = MAL_CHAN_MASK(emacdata->mal_tx_chan);
+	dev->commac.rx_chan_mask = MAL_CHAN_MASK(emacdata->mal_rx_chan);
+	err = mal_register_commac(dev->mal, &dev->commac);
+	if (err) {
+		printk(KERN_ERR "emac%d: failed to register with mal%d!\n",
+		       dev->def->index, emacdata->mal_idx);
+		goto out;
+	}
+	dev->rx_skb_size = emac_rx_skb_size(ndev->mtu);
+	dev->rx_sync_size = emac_rx_sync_size(ndev->mtu);
+
+	/* Get pointers to BD rings */
+	dev->tx_desc =
+	    dev->mal->bd_virt + mal_tx_bd_offset(dev->mal,
+						 emacdata->mal_tx_chan);
+	dev->rx_desc =
+	    dev->mal->bd_virt + mal_rx_bd_offset(dev->mal,
+						 emacdata->mal_rx_chan);
+
+	DBG("%d: tx_desc %p" NL, ocpdev->def->index, dev->tx_desc);
+	DBG("%d: rx_desc %p" NL, ocpdev->def->index, dev->rx_desc);
+
+	/* Clean rings */
+	memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor));
+	memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor));
+
+	/* If we depend on another EMAC for MDIO, check whether it was probed already */
+	if (emacdata->mdio_idx >= 0 && emacdata->mdio_idx != ocpdev->def->index) {
+		struct ocp_device *mdiodev =
+		    ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC,
+				    emacdata->mdio_idx);
+		if (!mdiodev) {
+			printk(KERN_ERR "emac%d: unknown emac%d device!\n",
+			       dev->def->index, emacdata->mdio_idx);
+			err = -ENODEV;
+			goto out2;
 		}
-		ep->mdio_dev = mdio_ndev;
-	} else {
-		ep->mdio_dev = ndev;
-	}
-
-	ocp_set_drvdata(ocpdev, ndev);
-
-	spin_lock_init(&ep->lock);
-
-	/* Fill out MAL informations and register commac */
-	ep->mal = mal;
-	ep->mal_tx_chan = emacdata->mal_tx_chan;
-	ep->mal_rx_chan = emacdata->mal_rx_chan;
-	ep->commac.ops = &emac_commac_ops;
-	ep->commac.dev = ndev;
-	ep->commac.tx_chan_mask = MAL_CHAN_MASK(ep->mal_tx_chan);
-	ep->commac.rx_chan_mask = MAL_CHAN_MASK(ep->mal_rx_chan);
-	rc = mal_register_commac(ep->mal, &ep->commac);
-	if (rc != 0)
-		goto bail;
-	commac_reg = 1;
-
-	/* Map our MMIOs */
-	ep->emacp = (emac_t *) ioremap(ocpdev->def->paddr, sizeof(emac_t));
-
-	/* Check if we need to attach to a ZMII */
-	if (emacdata->zmii_idx >= 0) {
-		ep->zmii_input = emacdata->zmii_mux;
-		ep->zmii_dev =
-		    ocp_find_device(OCP_ANY_ID, OCP_FUNC_ZMII,
-				    emacdata->zmii_idx);
-		if (ep->zmii_dev == NULL)
-			printk(KERN_WARNING
-			       "emac%d: ZMII %d requested but not found !\n",
-			       ocpdev->def->index, emacdata->zmii_idx);
-		else if ((rc =
-			  emac_init_zmii(ep->zmii_dev, ep->zmii_input,
-					 emacdata->phy_mode)) != 0)
-			goto bail;
-	}
-
-	/* Check if we need to attach to a RGMII */
-	if (emacdata->rgmii_idx >= 0) {
-		ep->rgmii_input = emacdata->rgmii_mux;
-		ep->rgmii_dev =
-		    ocp_find_device(OCP_ANY_ID, OCP_FUNC_RGMII,
-				    emacdata->rgmii_idx);
-		if (ep->rgmii_dev == NULL)
-			printk(KERN_WARNING
-			       "emac%d: RGMII %d requested but not found !\n",
-			       ocpdev->def->index, emacdata->rgmii_idx);
-		else if ((rc =
-			  emac_init_rgmii(ep->rgmii_dev, ep->rgmii_input,
-					  emacdata->phy_mode)) != 0)
-			goto bail;
-	}
-
-	/* Check if we need to attach to a TAH */
-	if (emacdata->tah_idx >= 0) {
-		ep->tah_dev =
-		    ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH,
-				    emacdata->tah_idx);
-		if (ep->tah_dev == NULL)
-			printk(KERN_WARNING
-			       "emac%d: TAH %d requested but not found !\n",
-			       ocpdev->def->index, emacdata->tah_idx);
-		else if ((rc = emac_init_tah(ep)) != 0)
-			goto bail;
-	}
-
-	if (deferred_init) {
-		if (!list_empty(&emac_init_list)) {
-			struct list_head *entry;
-			struct emac_def_dev *ddev;
-
-			list_for_each(entry, &emac_init_list) {
-				ddev =
-				    list_entry(entry, struct emac_def_dev,
-					       link);
-				emac_init_device(ddev->ocpdev, ddev->mal);
-			}
+		dev->mdio_dev = ocp_get_drvdata(mdiodev);
+		if (!dev->mdio_dev) {
+			printk(KERN_ERR
+			       "emac%d: emac%d hasn't been initialized yet!\n",
+			       dev->def->index, emacdata->mdio_idx);
+			err = -ENODEV;
+			goto out2;
 		}
 	}
 
-	/* Init link monitoring timer */
-	init_timer(&ep->link_timer);
-	ep->link_timer.function = emac_link_timer;
-	ep->link_timer.data = (unsigned long)ep;
-	ep->timer_ticks = 0;
+	/* Attach to ZMII, if needed */
+	if ((err = zmii_attach(dev)) != 0)
+		goto out2;
 
-	/* Fill up the mii_phy structure */
-	ep->phy_mii.dev = ndev;
-	ep->phy_mii.mdio_read = emac_phy_read;
-	ep->phy_mii.mdio_write = emac_phy_write;
-	ep->phy_mii.mode = emacdata->phy_mode;
+	/* Attach to RGMII, if needed */
+	if ((err = rgmii_attach(dev)) != 0)
+		goto out3;
 
-	/* Find PHY */
-	phy_map = emacdata->phy_map | busy_phy_map;
-	for (i = 0; i <= 0x1f; i++, phy_map >>= 1) {
-		if ((phy_map & 0x1) == 0) {
-			int val = emac_phy_read(ndev, i, MII_BMCR);
-			if (val != 0xffff && val != -1)
-				break;
-		}
-	}
-	if (i == 0x20) {
-		printk(KERN_WARNING "emac%d: Can't find PHY.\n",
-		       ocpdev->def->index);
-		rc = -ENODEV;
-		goto bail;
-	}
-	busy_phy_map |= 1 << i;
-	ep->mii_phy_addr = i;
-	rc = mii_phy_probe(&ep->phy_mii, i);
-	if (rc) {
-		printk(KERN_WARNING "emac%d: Failed to probe PHY type.\n",
-		       ocpdev->def->index);
-		rc = -ENODEV;
-		goto bail;
-	}
-	
-	/* Disable any PHY features not supported by the platform */
-	ep->phy_mii.def->features &= ~emacdata->phy_feat_exc;
+	/* Attach to TAH, if needed */
+	if ((err = tah_attach(dev)) != 0)
+		goto out4;
 
-	/* Setup initial PHY config & startup aneg */
-	if (ep->phy_mii.def->ops->init)
-		ep->phy_mii.def->ops->init(&ep->phy_mii);
-	netif_carrier_off(ndev);
-	if (ep->phy_mii.def->features & SUPPORTED_Autoneg)
-		ep->want_autoneg = 1;
-	else {
-		ep->want_autoneg = 0;
-		
-		/* Select highest supported speed/duplex */
-		if (ep->phy_mii.def->features & SUPPORTED_1000baseT_Full) {
-			ep->phy_mii.speed = SPEED_1000;
-			ep->phy_mii.duplex = DUPLEX_FULL;
-		} else if (ep->phy_mii.def->features & 
-			   SUPPORTED_1000baseT_Half) {
-			ep->phy_mii.speed = SPEED_1000;
-			ep->phy_mii.duplex = DUPLEX_HALF;
-		} else if (ep->phy_mii.def->features & 
-			   SUPPORTED_100baseT_Full) {
-			ep->phy_mii.speed = SPEED_100;
-			ep->phy_mii.duplex = DUPLEX_FULL;
-		} else if (ep->phy_mii.def->features & 
-			   SUPPORTED_100baseT_Half) {
-			ep->phy_mii.speed = SPEED_100;
-			ep->phy_mii.duplex = DUPLEX_HALF;
-		} else if (ep->phy_mii.def->features & 
-			   SUPPORTED_10baseT_Full) {
-			ep->phy_mii.speed = SPEED_10;
-			ep->phy_mii.duplex = DUPLEX_FULL;
-		} else {
-			ep->phy_mii.speed = SPEED_10;
-			ep->phy_mii.duplex = DUPLEX_HALF;
-		}
+	/* Map EMAC regs */
+	dev->emacp =
+	    (struct emac_regs *)ioremap(dev->def->paddr,
+					sizeof(struct emac_regs));
+	if (!dev->emacp) {
+		printk(KERN_ERR "emac%d: could not ioremap device registers!\n",
+		       dev->def->index);
+		err = -ENOMEM;
+		goto out5;
 	}
-	emac_start_link(ep, NULL);
 
-	/* read the MAC Address */
-	for (i = 0; i < 6; i++)
+	/* Fill in MAC address */
+	for (i = 0; i < 6; ++i)
 		ndev->dev_addr[i] = emacdata->mac_addr[i];
 
+	/* Set some link defaults before we can find out real parameters */
+	dev->phy.speed = SPEED_100;
+	dev->phy.duplex = DUPLEX_FULL;
+	dev->phy.autoneg = AUTONEG_DISABLE;
+	dev->phy.pause = dev->phy.asym_pause = 0;
+	init_timer(&dev->link_timer);
+	dev->link_timer.function = emac_link_timer;
+	dev->link_timer.data = (unsigned long)dev;
+
+	/* Find PHY if any */
+	dev->phy.dev = ndev;
+	dev->phy.mode = emacdata->phy_mode;
+	if (emacdata->phy_map != 0xffffffff) {
+		u32 phy_map = emacdata->phy_map | busy_phy_map;
+		u32 adv;
+
+		DBG("%d: PHY maps %08x %08x" NL, dev->def->index,
+		    emacdata->phy_map, busy_phy_map);
+
+		EMAC_RX_CLK_TX(dev->def->index);
+
+		dev->phy.mdio_read = emac_mdio_read;
+		dev->phy.mdio_write = emac_mdio_write;
+
+		/* Configure EMAC with defaults so we can at least use MDIO
+		 * This is needed mostly for 440GX
+		 */
+		if (emac_phy_gpcs(dev->phy.mode)) {
+			/* XXX
+			 * Make GPCS PHY address equal to EMAC index.
+			 * We probably should take into account busy_phy_map
+			 * and/or phy_map here.
+			 */
+			dev->phy.address = dev->def->index;
+		}
+		
+		emac_configure(dev);
+
+		for (i = 0; i < 0x20; phy_map >>= 1, ++i)
+			if (!(phy_map & 1)) {
+				int r;
+				busy_phy_map |= 1 << i;
+
+				/* Quick check if there is a PHY at the address */
+				r = emac_mdio_read(dev->ndev, i, MII_BMCR);
+				if (r == 0xffff || r < 0)
+					continue;
+				if (!mii_phy_probe(&dev->phy, i))
+					break;
+			}
+		if (i == 0x20) {
+			printk(KERN_WARNING "emac%d: can't find PHY!\n",
+			       dev->def->index);
+			goto out6;
+		}
+
+		/* Init PHY */
+		if (dev->phy.def->ops->init)
+			dev->phy.def->ops->init(&dev->phy);
+		
+		/* Disable any PHY features not supported by the platform */
+		dev->phy.def->features &= ~emacdata->phy_feat_exc;
+
+		/* Setup initial link parameters */
+		if (dev->phy.features & SUPPORTED_Autoneg) {
+			adv = dev->phy.features;
+#if !defined(CONFIG_40x)
+			adv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+#endif
+			/* Restart autonegotiation */
+			dev->phy.def->ops->setup_aneg(&dev->phy, adv);
+		} else {
+			u32 f = dev->phy.def->features;
+			int speed = SPEED_10, fd = DUPLEX_HALF;
+
+			/* Select highest supported speed/duplex */
+			if (f & SUPPORTED_1000baseT_Full) {
+				speed = SPEED_1000;
+				fd = DUPLEX_FULL;
+			} else if (f & SUPPORTED_1000baseT_Half)
+				speed = SPEED_1000;
+			else if (f & SUPPORTED_100baseT_Full) {
+				speed = SPEED_100;
+				fd = DUPLEX_FULL;
+			} else if (f & SUPPORTED_100baseT_Half)
+				speed = SPEED_100;
+			else if (f & SUPPORTED_10baseT_Full)
+				fd = DUPLEX_FULL;
+
+			/* Force link parameters */
+			dev->phy.def->ops->setup_forced(&dev->phy, speed, fd);
+		}
+	} else {
+		emac_reset(dev);
+
+		/* PHY-less configuration.
+		 * XXX I probably should move these settings to emacdata
+		 */
+		dev->phy.address = -1;
+		dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
+		dev->phy.pause = 1;
+	}
+
 	/* Fill in the driver function table */
 	ndev->open = &emac_open;
-	ndev->hard_start_xmit = &emac_start_xmit;
+	if (dev->tah_dev) {
+		ndev->hard_start_xmit = &emac_start_xmit_sg;
+		ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+	} else
+		ndev->hard_start_xmit = &emac_start_xmit;
+	ndev->tx_timeout = &emac_full_tx_reset;
+	ndev->watchdog_timeo = 5 * HZ;
 	ndev->stop = &emac_close;
 	ndev->get_stats = &emac_stats;
-	if (emacdata->jumbo)
-		ndev->change_mtu = &emac_change_mtu;
-	ndev->set_mac_address = &emac_set_mac_address;
 	ndev->set_multicast_list = &emac_set_multicast_list;
 	ndev->do_ioctl = &emac_ioctl;
+	if (emac_phy_supports_gige(emacdata->phy_mode)) {
+		ndev->change_mtu = &emac_change_mtu;
+		dev->commac.ops = &emac_commac_sg_ops;
+	}
 	SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
-	if (emacdata->tah_idx >= 0)
-		ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	ndev->poll_controller = emac_netpoll;
-#endif
 
-	SET_MODULE_OWNER(ndev);
+	netif_carrier_off(ndev);
+	netif_stop_queue(ndev);
 
-	rc = register_netdev(ndev);
-	if (rc != 0)
-		goto bail;
+	err = register_netdev(ndev);
+	if (err) {
+		printk(KERN_ERR "emac%d: failed to register net device (%d)!\n",
+		       dev->def->index, err);
+		goto out6;
+	}
 
-	printk("%s: IBM emac, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       ndev->name,
+	ocp_set_drvdata(ocpdev, dev);
+
+	printk("%s: emac%d, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       ndev->name, dev->def->index,
 	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
 	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
-	printk(KERN_INFO "%s: Found %s PHY (0x%02x)\n",
-	       ndev->name, ep->phy_mii.def->name, ep->mii_phy_addr);
 
-      bail:
-	if (rc && commac_reg)
-		mal_unregister_commac(ep->mal, &ep->commac);
-	if (rc && ndev)
-		kfree(ndev);
+	if (dev->phy.address >= 0)
+		printk("%s: found %s PHY (0x%02x)\n", ndev->name,
+		       dev->phy.def->name, dev->phy.address);
 
-	return rc;
-}
-
-static int emac_probe(struct ocp_device *ocpdev)
-{
-	struct ocp_device *maldev;
-	struct ibm_ocp_mal *mal;
-	struct ocp_func_emac_data *emacdata;
-
-	emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions;
-	if (emacdata == NULL) {
-		printk(KERN_ERR "emac%d: Missing additional datas !\n",
-		       ocpdev->def->index);
-		return -ENODEV;
-	}
-
-	/* Get the MAL device  */
-	maldev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_MAL, emacdata->mal_idx);
-	if (maldev == NULL) {
-		printk("No maldev\n");
-		return -ENODEV;
-	}
-	/*
-	 * Get MAL driver data, it must be here due to link order.
-	 * When the driver is modularized, symbol dependencies will
-	 * ensure the MAL driver is already present if built as a
-	 * module.
-	 */
-	mal = (struct ibm_ocp_mal *)ocp_get_drvdata(maldev);
-	if (mal == NULL) {
-		printk("No maldrv\n");
-		return -ENODEV;
-	}
-
-	/* If we depend on another EMAC for MDIO, wait for it to show up */
-	if (emacdata->mdio_idx >= 0 &&
-	    (emacdata->mdio_idx != ocpdev->def->index) && !mdio_ndev) {
-		struct emac_def_dev *ddev;
-		/* Add this index to the deferred init table */
-		ddev = kmalloc(sizeof(struct emac_def_dev), GFP_KERNEL);
-		ddev->ocpdev = ocpdev;
-		ddev->mal = mal;
-		list_add_tail(&ddev->link, &emac_init_list);
-	} else {
-		emac_init_device(ocpdev, mal);
-	}
+	emac_dbg_register(dev->def->index, dev);
 
 	return 0;
+      out6:
+	iounmap((void *)dev->emacp);
+      out5:
+	tah_fini(dev->tah_dev);
+      out4:
+	rgmii_fini(dev->rgmii_dev, dev->rgmii_input);
+      out3:
+	zmii_fini(dev->zmii_dev, dev->zmii_input);
+      out2:
+	mal_unregister_commac(dev->mal, &dev->commac);
+      out:
+	kfree(ndev);
+	return err;
 }
 
-/* Structure for a device driver */
 static struct ocp_device_id emac_ids[] = {
-	{.vendor = OCP_ANY_ID,.function = OCP_FUNC_EMAC},
-	{.vendor = OCP_VENDOR_INVALID}
+	{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_EMAC },
+	{ .vendor = OCP_VENDOR_INVALID}
 };
 
 static struct ocp_driver emac_driver = {
 	.name = "emac",
 	.id_table = emac_ids,
-
 	.probe = emac_probe,
 	.remove = emac_remove,
 };
 
 static int __init emac_init(void)
 {
-	printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n");
-	printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n");
+	printk(KERN_INFO DRV_DESC ", version " DRV_VERSION "\n");
 
-	if (skb_res > 2) {
-		printk(KERN_WARNING "Invalid skb_res: %d, cropping to 2\n",
-		       skb_res);
-		skb_res = 2;
+	DBG(": init" NL);
+
+	if (mal_init())
+		return -ENODEV;
+
+	EMAC_CLK_INTERNAL;
+	if (ocp_register_driver(&emac_driver)) {
+		EMAC_CLK_EXTERNAL;
+		ocp_unregister_driver(&emac_driver);
+		mal_exit();
+		return -ENODEV;
 	}
+	EMAC_CLK_EXTERNAL;
 
-	return ocp_register_driver(&emac_driver);
+	emac_init_debug();
+	return 0;
 }
 
 static void __exit emac_exit(void)
 {
+	DBG(": exit" NL);
 	ocp_unregister_driver(&emac_driver);
+	mal_exit();
+	emac_fini_debug();
 }
 
 module_init(emac_init);
diff --git a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h
index 97e6e1e..e9b44d0 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.h
+++ b/drivers/net/ibm_emac/ibm_emac_core.h
@@ -1,146 +1,221 @@
 /*
- * ibm_emac_core.h
+ * drivers/net/ibm_emac/ibm_emac_core.h
  *
- * Ethernet driver for the built in ethernet on the IBM 405 PowerPC
- * processor.
+ * Driver for PowerPC 4xx on-chip ethernet controller.
  *
- *      Armin Kuster akuster@mvista.com
- *      Sept, 2001
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  *
- *      Orignial driver
- *         Johnnie Peters
- *         jpeters@mvista.com
- *
- * Copyright 2000 MontaVista Softare Inc.
+ * Based on original work by
+ *      Armin Kuster <akuster@mvista.com>
+ * 	Johnnie Peters <jpeters@mvista.com>
+ *      Copyright 2000, 2001 MontaVista Softare 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.
+ *
  */
+#ifndef __IBM_EMAC_CORE_H_
+#define __IBM_EMAC_CORE_H_
 
-#ifndef _IBM_EMAC_CORE_H_
-#define _IBM_EMAC_CORE_H_
-
+#include <linux/config.h>
 #include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
 #include <asm/ocp.h>
-#include <asm/mmu.h>		/* For phys_addr_t */
 
 #include "ibm_emac.h"
 #include "ibm_emac_phy.h"
-#include "ibm_emac_rgmii.h"
 #include "ibm_emac_zmii.h"
+#include "ibm_emac_rgmii.h"
 #include "ibm_emac_mal.h"
 #include "ibm_emac_tah.h"
 
-#ifndef CONFIG_IBM_EMAC_TXB
-#define NUM_TX_BUFF		64
-#define NUM_RX_BUFF		64
-#else
-#define NUM_TX_BUFF		CONFIG_IBM_EMAC_TXB
-#define NUM_RX_BUFF		CONFIG_IBM_EMAC_RXB
+#define NUM_TX_BUFF			CONFIG_IBM_EMAC_TXB
+#define NUM_RX_BUFF			CONFIG_IBM_EMAC_RXB
+
+/* Simple sanity check */
+#if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
+#error Invalid number of buffer descriptors (greater than 256)
 #endif
 
-/* This does 16 byte alignment, exactly what we need.
- * The packet length includes FCS, but we don't want to
- * include that when passing upstream as it messes up
- * bridging applications.
+// XXX
+#define EMAC_MIN_MTU			46
+#define EMAC_MAX_MTU			9000
+
+/* Maximum L2 header length (VLAN tagged, no FCS) */
+#define EMAC_MTU_OVERHEAD		(6 * 2 + 2 + 4)
+
+/* RX BD size for the given MTU */
+static inline int emac_rx_size(int mtu)
+{
+	if (mtu > ETH_DATA_LEN)
+		return MAL_MAX_RX_SIZE;
+	else
+		return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD);
+}
+
+#define EMAC_DMA_ALIGN(x)		ALIGN((x), dma_get_cache_alignment())
+
+#define EMAC_RX_SKB_HEADROOM		\
+	EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM)
+
+/* Size of RX skb for the given MTU */
+static inline int emac_rx_skb_size(int mtu)
+{
+	int size = max(mtu + EMAC_MTU_OVERHEAD, emac_rx_size(mtu));
+	return EMAC_DMA_ALIGN(size + 2) + EMAC_RX_SKB_HEADROOM;
+}
+
+/* RX DMA sync size */
+static inline int emac_rx_sync_size(int mtu)
+{
+	return EMAC_DMA_ALIGN(emac_rx_size(mtu) + 2);
+}
+
+/* Driver statistcs is split into two parts to make it more cache friendly:
+ *   - normal statistics (packet count, etc)
+ *   - error statistics
+ *
+ * When statistics is requested by ethtool, these parts are concatenated,
+ * normal one goes first.
+ *
+ * Please, keep these structures in sync with emac_stats_keys.
  */
-#ifndef CONFIG_IBM_EMAC_SKBRES
-#define SKB_RES 2
-#else
-#define SKB_RES CONFIG_IBM_EMAC_SKBRES
-#endif
 
-/* Note about alignement. alloc_skb() returns a cache line
- * aligned buffer. However, dev_alloc_skb() will add 16 more
- * bytes and "reserve" them, so our buffer will actually end
- * on a half cache line. What we do is to use directly
- * alloc_skb, allocate 16 more bytes to match the total amount
- * allocated by dev_alloc_skb(), but we don't reserve.
- */
-#define MAX_NUM_BUF_DESC	255
-#define DESC_BUF_SIZE		4080	/* max 4096-16 */
-#define DESC_BUF_SIZE_REG	(DESC_BUF_SIZE / 16)
+/* Normal TX/RX Statistics */
+struct ibm_emac_stats {
+	u64 rx_packets;
+	u64 rx_bytes;
+	u64 tx_packets;
+	u64 tx_bytes;
+	u64 rx_packets_csum;
+	u64 tx_packets_csum;
+};
 
-/* Transmitter timeout. */
-#define TX_TIMEOUT		(2*HZ)
+/* Error statistics */
+struct ibm_emac_error_stats {
+	u64 tx_undo;
 
-/* MDIO latency delay */
-#define MDIO_DELAY		250
+	/* Software RX Errors */
+	u64 rx_dropped_stack;
+	u64 rx_dropped_oom;
+	u64 rx_dropped_error;
+	u64 rx_dropped_resize;
+	u64 rx_dropped_mtu;
+	u64 rx_stopped;
+	/* BD reported RX errors */
+	u64 rx_bd_errors;
+	u64 rx_bd_overrun;
+	u64 rx_bd_bad_packet;
+	u64 rx_bd_runt_packet;
+	u64 rx_bd_short_event;
+	u64 rx_bd_alignment_error;
+	u64 rx_bd_bad_fcs;
+	u64 rx_bd_packet_too_long;
+	u64 rx_bd_out_of_range;
+	u64 rx_bd_in_range;
+	/* EMAC IRQ reported RX errors */
+	u64 rx_parity;
+	u64 rx_fifo_overrun;
+	u64 rx_overrun;
+	u64 rx_bad_packet;
+	u64 rx_runt_packet;
+	u64 rx_short_event;
+	u64 rx_alignment_error;
+	u64 rx_bad_fcs;
+	u64 rx_packet_too_long;
+	u64 rx_out_of_range;
+	u64 rx_in_range;
 
-/* Power managment shift registers */
-#define IBM_CPM_EMMII	0	/* Shift value for MII */
-#define IBM_CPM_EMRX	1	/* Shift value for recv */
-#define IBM_CPM_EMTX	2	/* Shift value for MAC */
-#define IBM_CPM_EMAC(x)	(((x)>>IBM_CPM_EMMII) | ((x)>>IBM_CPM_EMRX) | ((x)>>IBM_CPM_EMTX))
+	/* Software TX Errors */
+	u64 tx_dropped;
+	/* BD reported TX errors */
+	u64 tx_bd_errors;
+	u64 tx_bd_bad_fcs;
+	u64 tx_bd_carrier_loss;
+	u64 tx_bd_excessive_deferral;
+	u64 tx_bd_excessive_collisions;
+	u64 tx_bd_late_collision;
+	u64 tx_bd_multple_collisions;
+	u64 tx_bd_single_collision;
+	u64 tx_bd_underrun;
+	u64 tx_bd_sqe;
+	/* EMAC IRQ reported TX errors */
+	u64 tx_parity;
+	u64 tx_underrun;
+	u64 tx_sqe;
+	u64 tx_errors;
+};
 
-#define ENET_HEADER_SIZE	14
-#define ENET_FCS_SIZE		4
-#define ENET_DEF_MTU_SIZE	1500
-#define ENET_DEF_BUF_SIZE	(ENET_DEF_MTU_SIZE + ENET_HEADER_SIZE + ENET_FCS_SIZE)
-#define EMAC_MIN_FRAME		64
-#define EMAC_MAX_FRAME		9018
-#define EMAC_MIN_MTU		(EMAC_MIN_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
-#define EMAC_MAX_MTU		(EMAC_MAX_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
-
-#ifdef CONFIG_IBM_EMAC_ERRMSG
-void emac_serr_dump_0(struct net_device *dev);
-void emac_serr_dump_1(struct net_device *dev);
-void emac_err_dump(struct net_device *dev, int em0isr);
-void emac_phy_dump(struct net_device *);
-void emac_desc_dump(struct net_device *);
-void emac_mac_dump(struct net_device *);
-void emac_mal_dump(struct net_device *);
-#else
-#define emac_serr_dump_0(dev) do { } while (0)
-#define emac_serr_dump_1(dev) do { } while (0)
-#define emac_err_dump(dev,x) do { } while (0)
-#define emac_phy_dump(dev) do { } while (0)
-#define emac_desc_dump(dev) do { } while (0)
-#define emac_mac_dump(dev) do { } while (0)
-#define emac_mal_dump(dev) do { } while (0)
-#endif
+#define EMAC_ETHTOOL_STATS_COUNT	((sizeof(struct ibm_emac_stats) + \
+					  sizeof(struct ibm_emac_error_stats)) \
+					 / sizeof(u64))
 
 struct ocp_enet_private {
-	struct sk_buff *tx_skb[NUM_TX_BUFF];
-	struct sk_buff *rx_skb[NUM_RX_BUFF];
-	struct mal_descriptor *tx_desc;
-	struct mal_descriptor *rx_desc;
-	struct mal_descriptor *rx_dirty;
-	struct net_device_stats stats;
-	int tx_cnt;
-	int rx_slot;
-	int dirty_rx;
-	int tx_slot;
-	int ack_slot;
-	int rx_buffer_size;
+	struct net_device		*ndev;		/* 0 */
+	struct emac_regs		*emacp;
+	
+	struct mal_descriptor		*tx_desc;
+	int				tx_cnt;
+	int				tx_slot;
+	int				ack_slot;
 
-	struct mii_phy phy_mii;
-	int mii_phy_addr;
-	int want_autoneg;
-	int timer_ticks;
-	struct timer_list link_timer;
-	struct net_device *mdio_dev;
+	struct mal_descriptor		*rx_desc;
+	int				rx_slot;
+	struct sk_buff			*rx_sg_skb;	/* 1 */
+	int 				rx_skb_size;
+	int				rx_sync_size;
 
-	struct ocp_device *rgmii_dev;
-	int rgmii_input;
+	struct ibm_emac_stats 		stats;
+	struct ocp_device		*tah_dev;
 
-	struct ocp_device *zmii_dev;
-	int zmii_input;
+	struct ibm_ocp_mal		*mal;
+	struct mal_commac		commac;
 
-	struct ibm_ocp_mal *mal;
-	int mal_tx_chan, mal_rx_chan;
-	struct mal_commac commac;
+	struct sk_buff			*tx_skb[NUM_TX_BUFF];
+	struct sk_buff			*rx_skb[NUM_RX_BUFF];
 
-	struct ocp_device *tah_dev;
+	struct ocp_device		*zmii_dev;
+	int				zmii_input;
+	struct ocp_enet_private		*mdio_dev;
+	struct ocp_device		*rgmii_dev;
+	int				rgmii_input;
 
-	int opened;
-	int going_away;
-	int wol_irq;
-	emac_t *emacp;
-	struct ocp_device *ocpdev;
-	struct net_device *ndev;
-	spinlock_t lock;
+	struct ocp_def			*def;
+
+	struct mii_phy			phy;
+	struct timer_list		link_timer;
+	int				reset_failed;
+
+	struct ibm_emac_error_stats	estats;
+	struct net_device_stats		nstats;
+
+	struct device*			ldev;
 };
-#endif				/* _IBM_EMAC_CORE_H_ */
+
+/* Ethtool get_regs complex data.
+ * We want to get not just EMAC registers, but also MAL, ZMII, RGMII, TAH 
+ * when available.
+ * 
+ * Returned BLOB consists of the ibm_emac_ethtool_regs_hdr, 
+ * MAL registers, EMAC registers and optional ZMII, RGMII, TAH registers.
+ * Each register component is preceded with emac_ethtool_regs_subhdr.
+ * Order of the optional headers follows their relative bit posititions 
+ * in emac_ethtool_regs_hdr.components
+ */
+#define EMAC_ETHTOOL_REGS_ZMII		0x00000001
+#define EMAC_ETHTOOL_REGS_RGMII		0x00000002
+#define EMAC_ETHTOOL_REGS_TAH		0x00000004
+
+struct emac_ethtool_regs_hdr {
+	u32 components;
+};
+
+struct emac_ethtool_regs_subhdr {
+	u32 version;
+	u32 index;
+};
+
+#endif				/* __IBM_EMAC_CORE_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_debug.c b/drivers/net/ibm_emac/ibm_emac_debug.c
index c851204..75d3b86 100644
--- a/drivers/net/ibm_emac/ibm_emac_debug.c
+++ b/drivers/net/ibm_emac/ibm_emac_debug.c
@@ -1,224 +1,213 @@
 /*
- * ibm_ocp_debug.c
+ * drivers/net/ibm_emac/ibm_emac_debug.c
  *
- * This has all the debug routines that where in *_enet.c
+ * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
  *
- *      Armin Kuster akuster@mvista.com
- *      April , 2002
- *
- * Copyright 2002 MontaVista Softare Inc.
+ * Copyright (c) 2004, 2005 Zultys Technologies
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
+ *
  */
-
 #include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/sysrq.h>
 #include <asm/io.h>
-#include "ibm_ocp_mal.h"
-#include "ibm_ocp_zmii.h"
-#include "ibm_ocp_enet.h"
 
-extern int emac_phy_read(struct net_device *dev, int mii_id, int reg);
+#include "ibm_emac_core.h"
 
-void emac_phy_dump(struct net_device *dev)
+static void emac_desc_dump(int idx, struct ocp_enet_private *p)
 {
-	struct ocp_enet_private *fep = dev->priv;
-	unsigned long i;
-	uint data;
+	int i;
+	printk("** EMAC%d TX BDs **\n"
+	       " tx_cnt = %d tx_slot = %d ack_slot = %d\n",
+	       idx, p->tx_cnt, p->tx_slot, p->ack_slot);
+	for (i = 0; i < NUM_TX_BUFF / 2; ++i)
+		printk
+		    ("bd[%2d] 0x%08x %c 0x%04x %4u - bd[%2d] 0x%08x %c 0x%04x %4u\n",
+		     i, p->tx_desc[i].data_ptr, p->tx_skb[i] ? 'V' : ' ',
+		     p->tx_desc[i].ctrl, p->tx_desc[i].data_len,
+		     NUM_TX_BUFF / 2 + i,
+		     p->tx_desc[NUM_TX_BUFF / 2 + i].data_ptr,
+		     p->tx_skb[NUM_TX_BUFF / 2 + i] ? 'V' : ' ',
+		     p->tx_desc[NUM_TX_BUFF / 2 + i].ctrl,
+		     p->tx_desc[NUM_TX_BUFF / 2 + i].data_len);
 
-	printk(KERN_DEBUG " Prepare for Phy dump....\n");
-	for (i = 0; i < 0x1A; i++) {
-		data = emac_phy_read(dev, fep->mii_phy_addr, i);
-		printk(KERN_DEBUG "Phy reg 0x%lx ==> %4x\n", i, data);
-		if (i == 0x07)
-			i = 0x0f;
+	printk("** EMAC%d RX BDs **\n"
+	       " rx_slot = %d rx_stopped = %d rx_skb_size = %d rx_sync_size = %d\n"
+	       " rx_sg_skb = 0x%p\n",
+	       idx, p->rx_slot, p->commac.rx_stopped, p->rx_skb_size,
+	       p->rx_sync_size, p->rx_sg_skb);
+	for (i = 0; i < NUM_RX_BUFF / 2; ++i)
+		printk
+		    ("bd[%2d] 0x%08x %c 0x%04x %4u - bd[%2d] 0x%08x %c 0x%04x %4u\n",
+		     i, p->rx_desc[i].data_ptr, p->rx_skb[i] ? 'V' : ' ',
+		     p->rx_desc[i].ctrl, p->rx_desc[i].data_len,
+		     NUM_RX_BUFF / 2 + i,
+		     p->rx_desc[NUM_RX_BUFF / 2 + i].data_ptr,
+		     p->rx_skb[NUM_RX_BUFF / 2 + i] ? 'V' : ' ',
+		     p->rx_desc[NUM_RX_BUFF / 2 + i].ctrl,
+		     p->rx_desc[NUM_RX_BUFF / 2 + i].data_len);
+}
+
+static void emac_mac_dump(int idx, struct ocp_enet_private *dev)
+{
+	struct emac_regs *p = dev->emacp;
+
+	printk("** EMAC%d registers **\n"
+	       "MR0 = 0x%08x MR1 = 0x%08x TMR0 = 0x%08x TMR1 = 0x%08x\n"
+	       "RMR = 0x%08x ISR = 0x%08x ISER = 0x%08x\n"
+	       "IAR = %04x%08x VTPID = 0x%04x VTCI = 0x%04x\n"
+	       "IAHT: 0x%04x 0x%04x 0x%04x 0x%04x "
+	       "GAHT: 0x%04x 0x%04x 0x%04x 0x%04x\n"
+	       "LSA = %04x%08x IPGVR = 0x%04x\n"
+	       "STACR = 0x%08x TRTR = 0x%08x RWMR = 0x%08x\n"
+	       "OCTX = 0x%08x OCRX = 0x%08x IPCR = 0x%08x\n",
+	       idx, in_be32(&p->mr0), in_be32(&p->mr1),
+	       in_be32(&p->tmr0), in_be32(&p->tmr1),
+	       in_be32(&p->rmr), in_be32(&p->isr), in_be32(&p->iser),
+	       in_be32(&p->iahr), in_be32(&p->ialr), in_be32(&p->vtpid),
+	       in_be32(&p->vtci),
+	       in_be32(&p->iaht1), in_be32(&p->iaht2), in_be32(&p->iaht3),
+	       in_be32(&p->iaht4),
+	       in_be32(&p->gaht1), in_be32(&p->gaht2), in_be32(&p->gaht3),
+	       in_be32(&p->gaht4),
+	       in_be32(&p->lsah), in_be32(&p->lsal), in_be32(&p->ipgvr),
+	       in_be32(&p->stacr), in_be32(&p->trtr), in_be32(&p->rwmr),
+	       in_be32(&p->octx), in_be32(&p->ocrx), in_be32(&p->ipcr)
+	    );
+
+	emac_desc_dump(idx, dev);
+}
+
+static void emac_mal_dump(struct ibm_ocp_mal *mal)
+{
+	struct ocp_func_mal_data *maldata = mal->def->additions;
+	int i;
+
+	printk("** MAL%d Registers **\n"
+	       "CFG = 0x%08x ESR = 0x%08x IER = 0x%08x\n"
+	       "TX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n"
+	       "RX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n",
+	       mal->def->index,
+	       get_mal_dcrn(mal, MAL_CFG), get_mal_dcrn(mal, MAL_ESR),
+	       get_mal_dcrn(mal, MAL_IER),
+	       get_mal_dcrn(mal, MAL_TXCASR), get_mal_dcrn(mal, MAL_TXCARR),
+	       get_mal_dcrn(mal, MAL_TXEOBISR), get_mal_dcrn(mal, MAL_TXDEIR),
+	       get_mal_dcrn(mal, MAL_RXCASR), get_mal_dcrn(mal, MAL_RXCARR),
+	       get_mal_dcrn(mal, MAL_RXEOBISR), get_mal_dcrn(mal, MAL_RXDEIR)
+	    );
+
+	printk("TX|");
+	for (i = 0; i < maldata->num_tx_chans; ++i) {
+		if (i && !(i % 4))
+			printk("\n   ");
+		printk("CTP%d = 0x%08x ", i, get_mal_dcrn(mal, MAL_TXCTPR(i)));
 	}
-}
-
-void emac_desc_dump(struct net_device *dev)
-{
-	struct ocp_enet_private *fep = dev->priv;
-	int curr_slot;
-
-	printk(KERN_DEBUG
-	       "dumping the receive descriptors:  current slot is %d\n",
-	       fep->rx_slot);
-	for (curr_slot = 0; curr_slot < NUM_RX_BUFF; curr_slot++) {
-		printk(KERN_DEBUG
-		       "Desc %02d: status 0x%04x, length %3d, addr 0x%x\n",
-		       curr_slot, fep->rx_desc[curr_slot].ctrl,
-		       fep->rx_desc[curr_slot].data_len,
-		       (unsigned int)fep->rx_desc[curr_slot].data_ptr);
+	printk("\nRX|");
+	for (i = 0; i < maldata->num_rx_chans; ++i) {
+		if (i && !(i % 4))
+			printk("\n   ");
+		printk("CTP%d = 0x%08x ", i, get_mal_dcrn(mal, MAL_RXCTPR(i)));
 	}
-}
-
-void emac_mac_dump(struct net_device *dev)
-{
-	struct ocp_enet_private *fep = dev->priv;
-	volatile emac_t *emacp = fep->emacp;
-
-	printk(KERN_DEBUG "EMAC DEBUG ********** \n");
-	printk(KERN_DEBUG "EMAC_M0  ==> 0x%x\n", in_be32(&emacp->em0mr0));
-	printk(KERN_DEBUG "EMAC_M1  ==> 0x%x\n", in_be32(&emacp->em0mr1));
-	printk(KERN_DEBUG "EMAC_TXM0==> 0x%x\n", in_be32(&emacp->em0tmr0));
-	printk(KERN_DEBUG "EMAC_TXM1==> 0x%x\n", in_be32(&emacp->em0tmr1));
-	printk(KERN_DEBUG "EMAC_RXM ==> 0x%x\n", in_be32(&emacp->em0rmr));
-	printk(KERN_DEBUG "EMAC_ISR ==> 0x%x\n", in_be32(&emacp->em0isr));
-	printk(KERN_DEBUG "EMAC_IER ==> 0x%x\n", in_be32(&emacp->em0iser));
-	printk(KERN_DEBUG "EMAC_IAH ==> 0x%x\n", in_be32(&emacp->em0iahr));
-	printk(KERN_DEBUG "EMAC_IAL ==> 0x%x\n", in_be32(&emacp->em0ialr));
-	printk(KERN_DEBUG "EMAC_VLAN_TPID_REG ==> 0x%x\n",
-	       in_be32(&emacp->em0vtpid));
-}
-
-void emac_mal_dump(struct net_device *dev)
-{
-	struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
-
-	printk(KERN_DEBUG " MAL DEBUG ********** \n");
-	printk(KERN_DEBUG " MCR      ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALCR));
-	printk(KERN_DEBUG " ESR      ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALESR));
-	printk(KERN_DEBUG " IER      ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALIER));
-#ifdef CONFIG_40x
-	printk(KERN_DEBUG " DBR      ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALDBR));
-#endif				/* CONFIG_40x */
-	printk(KERN_DEBUG " TXCASR   ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCASR));
-	printk(KERN_DEBUG " TXCARR   ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCARR));
-	printk(KERN_DEBUG " TXEOBISR ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXEOBISR));
-	printk(KERN_DEBUG " TXDEIR   ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXDEIR));
-	printk(KERN_DEBUG " RXCASR   ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCASR));
-	printk(KERN_DEBUG " RXCARR   ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCARR));
-	printk(KERN_DEBUG " RXEOBISR ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRXEOBISR));
-	printk(KERN_DEBUG " RXDEIR   ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRXDEIR));
-	printk(KERN_DEBUG " TXCTP0R  ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP0R));
-	printk(KERN_DEBUG " TXCTP1R  ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP1R));
-	printk(KERN_DEBUG " TXCTP2R  ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP2R));
-	printk(KERN_DEBUG " TXCTP3R  ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALTXCTP3R));
-	printk(KERN_DEBUG " RXCTP0R  ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCTP0R));
-	printk(KERN_DEBUG " RXCTP1R  ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRXCTP1R));
-	printk(KERN_DEBUG " RCBS0    ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRCBS0));
-	printk(KERN_DEBUG " RCBS1    ==> 0x%x\n",
-	       (unsigned int)get_mal_dcrn(mal, DCRN_MALRCBS1));
-}
-
-void emac_serr_dump_0(struct net_device *dev)
-{
-	struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
-	unsigned long int mal_error, plb_error, plb_addr;
-
-	mal_error = get_mal_dcrn(mal, DCRN_MALESR);
-	printk(KERN_DEBUG "ppc405_eth_serr: %s channel %ld \n",
-	       (mal_error & 0x40000000) ? "Receive" :
-	       "Transmit", (mal_error & 0x3e000000) >> 25);
-	printk(KERN_DEBUG "  -----  latched error  -----\n");
-	if (mal_error & MALESR_DE)
-		printk(KERN_DEBUG "  DE: descriptor error\n");
-	if (mal_error & MALESR_OEN)
-		printk(KERN_DEBUG "  ONE: OPB non-fullword error\n");
-	if (mal_error & MALESR_OTE)
-		printk(KERN_DEBUG "  OTE: OPB timeout error\n");
-	if (mal_error & MALESR_OSE)
-		printk(KERN_DEBUG "  OSE: OPB slave error\n");
-
-	if (mal_error & MALESR_PEIN) {
-		plb_error = mfdcr(DCRN_PLB0_BESR);
-		printk(KERN_DEBUG
-		       "  PEIN: PLB error, PLB0_BESR is 0x%x\n",
-		       (unsigned int)plb_error);
-		plb_addr = mfdcr(DCRN_PLB0_BEAR);
-		printk(KERN_DEBUG
-		       "  PEIN: PLB error, PLB0_BEAR is 0x%x\n",
-		       (unsigned int)plb_addr);
+	printk("\n   ");
+	for (i = 0; i < maldata->num_rx_chans; ++i) {
+		u32 r = get_mal_dcrn(mal, MAL_RCBS(i));
+		if (i && !(i % 3))
+			printk("\n   ");
+		printk("RCBS%d = 0x%08x (%d) ", i, r, r * 16);
 	}
+	printk("\n");
 }
 
-void emac_serr_dump_1(struct net_device *dev)
+static struct ocp_enet_private *__emacs[4];
+static struct ibm_ocp_mal *__mals[1];
+
+void emac_dbg_register(int idx, struct ocp_enet_private *dev)
 {
-	struct ibm_ocp_mal *mal = ((struct ocp_enet_private *)dev->priv)->mal;
-	int mal_error = get_mal_dcrn(mal, DCRN_MALESR);
+	unsigned long flags;
 
-	printk(KERN_DEBUG "  -----  cumulative errors  -----\n");
-	if (mal_error & MALESR_DEI)
-		printk(KERN_DEBUG "  DEI: descriptor error interrupt\n");
-	if (mal_error & MALESR_ONEI)
-		printk(KERN_DEBUG "  OPB non-fullword error interrupt\n");
-	if (mal_error & MALESR_OTEI)
-		printk(KERN_DEBUG "  OTEI: timeout error interrupt\n");
-	if (mal_error & MALESR_OSEI)
-		printk(KERN_DEBUG "  OSEI: slave error interrupt\n");
-	if (mal_error & MALESR_PBEI)
-		printk(KERN_DEBUG "  PBEI: PLB bus error interrupt\n");
+	if (idx >= sizeof(__emacs) / sizeof(__emacs[0])) {
+		printk(KERN_WARNING
+		       "invalid index %d when registering EMAC for debugging\n",
+		       idx);
+		return;
+	}
+
+	local_irq_save(flags);
+	__emacs[idx] = dev;
+	local_irq_restore(flags);
 }
 
-void emac_err_dump(struct net_device *dev, int em0isr)
+void mal_dbg_register(int idx, struct ibm_ocp_mal *mal)
 {
-	printk(KERN_DEBUG "%s: on-chip ethernet error:\n", dev->name);
+	unsigned long flags;
 
-	if (em0isr & EMAC_ISR_OVR)
-		printk(KERN_DEBUG "  OVR: overrun\n");
-	if (em0isr & EMAC_ISR_PP)
-		printk(KERN_DEBUG "  PP: control pause packet\n");
-	if (em0isr & EMAC_ISR_BP)
-		printk(KERN_DEBUG "  BP: packet error\n");
-	if (em0isr & EMAC_ISR_RP)
-		printk(KERN_DEBUG "  RP: runt packet\n");
-	if (em0isr & EMAC_ISR_SE)
-		printk(KERN_DEBUG "  SE: short event\n");
-	if (em0isr & EMAC_ISR_ALE)
-		printk(KERN_DEBUG "  ALE: odd number of nibbles in packet\n");
-	if (em0isr & EMAC_ISR_BFCS)
-		printk(KERN_DEBUG "  BFCS: bad FCS\n");
-	if (em0isr & EMAC_ISR_PTLE)
-		printk(KERN_DEBUG "  PTLE: oversized packet\n");
-	if (em0isr & EMAC_ISR_ORE)
-		printk(KERN_DEBUG
-		       "  ORE: packet length field > max allowed LLC\n");
-	if (em0isr & EMAC_ISR_IRE)
-		printk(KERN_DEBUG "  IRE: In Range error\n");
-	if (em0isr & EMAC_ISR_DBDM)
-		printk(KERN_DEBUG "  DBDM: xmit error or SQE\n");
-	if (em0isr & EMAC_ISR_DB0)
-		printk(KERN_DEBUG "  DB0: xmit error or SQE on TX channel 0\n");
-	if (em0isr & EMAC_ISR_SE0)
-		printk(KERN_DEBUG
-		       "  SE0: Signal Quality Error test failure from TX channel 0\n");
-	if (em0isr & EMAC_ISR_TE0)
-		printk(KERN_DEBUG "  TE0: xmit channel 0 aborted\n");
-	if (em0isr & EMAC_ISR_DB1)
-		printk(KERN_DEBUG "  DB1: xmit error or SQE on TX channel \n");
-	if (em0isr & EMAC_ISR_SE1)
-		printk(KERN_DEBUG
-		       "  SE1: Signal Quality Error test failure from TX channel 1\n");
-	if (em0isr & EMAC_ISR_TE1)
-		printk(KERN_DEBUG "  TE1: xmit channel 1 aborted\n");
-	if (em0isr & EMAC_ISR_MOS)
-		printk(KERN_DEBUG "  MOS\n");
-	if (em0isr & EMAC_ISR_MOF)
-		printk(KERN_DEBUG "  MOF\n");
+	if (idx >= sizeof(__mals) / sizeof(__mals[0])) {
+		printk(KERN_WARNING
+		       "invalid index %d when registering MAL for debugging\n",
+		       idx);
+		return;
+	}
 
-	emac_mac_dump(dev);
-	emac_mal_dump(dev);
+	local_irq_save(flags);
+	__mals[idx] = mal;
+	local_irq_restore(flags);
 }
+
+void emac_dbg_dump_all(void)
+{
+	unsigned int i;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	for (i = 0; i < sizeof(__mals) / sizeof(__mals[0]); ++i)
+		if (__mals[i])
+			emac_mal_dump(__mals[i]);
+
+	for (i = 0; i < sizeof(__emacs) / sizeof(__emacs[0]); ++i)
+		if (__emacs[i])
+			emac_mac_dump(i, __emacs[i]);
+
+	local_irq_restore(flags);
+}
+
+#if defined(CONFIG_MAGIC_SYSRQ)
+static void emac_sysrq_handler(int key, struct pt_regs *pt_regs,
+			       struct tty_struct *tty)
+{
+	emac_dbg_dump_all();
+}
+
+static struct sysrq_key_op emac_sysrq_op = {
+	.handler = emac_sysrq_handler,
+	.help_msg = "emaC",
+	.action_msg = "Show EMAC(s) status",
+};
+
+int __init emac_init_debug(void)
+{
+	return register_sysrq_key('c', &emac_sysrq_op);
+}
+
+void __exit emac_fini_debug(void)
+{
+	unregister_sysrq_key('c', &emac_sysrq_op);
+}
+
+#else
+int __init emac_init_debug(void)
+{
+	return 0;
+}
+void __exit emac_fini_debug(void)
+{
+}
+#endif				/* CONFIG_MAGIC_SYSRQ */
diff --git a/drivers/net/ibm_emac/ibm_emac_debug.h b/drivers/net/ibm_emac/ibm_emac_debug.h
new file mode 100644
index 0000000..e85fbe0
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_debug.h
@@ -0,0 +1,63 @@
+/*
+ * drivers/net/ibm_emac/ibm_ocp_debug.h
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * 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 __IBM_EMAC_DEBUG_H_
+#define __IBM_EMAC_DEBUG_H_
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include "ibm_emac_core.h"
+#include "ibm_emac_mal.h"
+
+#if defined(CONFIG_IBM_EMAC_DEBUG)
+void emac_dbg_register(int idx, struct ocp_enet_private *dev);
+void mal_dbg_register(int idx, struct ibm_ocp_mal *mal);
+int emac_init_debug(void) __init;
+void emac_fini_debug(void) __exit;
+void emac_dbg_dump_all(void);
+# define DBG_LEVEL		1
+#else
+# define emac_dbg_register(x,y) ((void)0)
+# define mal_dbg_register(x,y)	((void)0)
+# define emac_init_debug()	((void)0)
+# define emac_fini_debug()	((void)0)
+# define emac_dbg_dump_all()	((void)0)
+# define DBG_LEVEL		0
+#endif
+
+#if DBG_LEVEL > 0
+#  define DBG(f,x...)		printk("emac" f, ##x)
+#  define MAL_DBG(f,x...)	printk("mal" f, ##x)
+#  define ZMII_DBG(f,x...)	printk("zmii" f, ##x)
+#  define RGMII_DBG(f,x...)	printk("rgmii" f, ##x)
+#  define NL			"\n"
+#else
+#  define DBG(f,x...)		((void)0)
+#  define MAL_DBG(f,x...)	((void)0)
+#  define ZMII_DBG(f,x...)	((void)0)
+#  define RGMII_DBG(f,x...)	((void)0)
+#endif
+#if DBG_LEVEL > 1
+#  define DBG2(f,x...) 		DBG(f, ##x)
+#  define MAL_DBG2(f,x...) 	MAL_DBG(f, ##x)
+#  define ZMII_DBG2(f,x...) 	ZMII_DBG(f, ##x)
+#  define RGMII_DBG2(f,x...) 	RGMII_DBG(f, ##x)
+#else
+#  define DBG2(f,x...) 		((void)0)
+#  define MAL_DBG2(f,x...) 	((void)0)
+#  define ZMII_DBG2(f,x...) 	((void)0)
+#  define RGMII_DBG2(f,x...) 	((void)0)
+#endif
+
+#endif				/* __IBM_EMAC_DEBUG_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index e59f57f..da88d43 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -1,436 +1,565 @@
 /*
- * ibm_ocp_mal.c
+ * drivers/net/ibm_emac/ibm_emac_mal.c
  *
- *      Armin Kuster akuster@mvista.com
- *      Juen, 2002
+ * Memory Access Layer (MAL) support
+ * 
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  *
- * Copyright 2002 MontaVista Softare Inc.
+ * Based on original work by
+ *      Benjamin Herrenschmidt <benh@kernel.crashing.org>,
+ *      David Gibson <hermes@gibson.dropbear.id.au>,
+ *
+ *      Armin Kuster <akuster@mvista.com>
+ *      Copyright 2002 MontaVista Softare 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/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/ocp.h>
 
+#include "ibm_emac_core.h"
 #include "ibm_emac_mal.h"
+#include "ibm_emac_debug.h"
 
-// Locking: Should we share a lock with the client ? The client could provide
-// a lock pointer (optionally) in the commac structure... I don't think this is
-// really necessary though
-
-/* This lock protects the commac list. On today UP implementations, it's
- * really only used as IRQ protection in mal_{register,unregister}_commac()
- */
-static DEFINE_RWLOCK(mal_list_lock);
-
-int mal_register_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+int __init mal_register_commac(struct ibm_ocp_mal *mal,
+			       struct mal_commac *commac)
 {
 	unsigned long flags;
+	local_irq_save(flags);
 
-	write_lock_irqsave(&mal_list_lock, flags);
+	MAL_DBG("%d: reg(%08x, %08x)" NL, mal->def->index,
+		commac->tx_chan_mask, commac->rx_chan_mask);
 
-	/* Don't let multiple commacs claim the same channel */
+	/* Don't let multiple commacs claim the same channel(s) */
 	if ((mal->tx_chan_mask & commac->tx_chan_mask) ||
 	    (mal->rx_chan_mask & commac->rx_chan_mask)) {
-		write_unlock_irqrestore(&mal_list_lock, flags);
+		local_irq_restore(flags);
+		printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
+		       mal->def->index);
 		return -EBUSY;
 	}
 
 	mal->tx_chan_mask |= commac->tx_chan_mask;
 	mal->rx_chan_mask |= commac->rx_chan_mask;
+	list_add(&commac->list, &mal->list);
 
-	list_add(&commac->list, &mal->commac);
-
-	write_unlock_irqrestore(&mal_list_lock, flags);
-
+	local_irq_restore(flags);
 	return 0;
 }
 
-int mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+void __exit mal_unregister_commac(struct ibm_ocp_mal *mal,
+				  struct mal_commac *commac)
 {
 	unsigned long flags;
+	local_irq_save(flags);
 
-	write_lock_irqsave(&mal_list_lock, flags);
+	MAL_DBG("%d: unreg(%08x, %08x)" NL, mal->def->index,
+		commac->tx_chan_mask, commac->rx_chan_mask);
 
 	mal->tx_chan_mask &= ~commac->tx_chan_mask;
 	mal->rx_chan_mask &= ~commac->rx_chan_mask;
-
 	list_del_init(&commac->list);
 
-	write_unlock_irqrestore(&mal_list_lock, flags);
-
-	return 0;
+	local_irq_restore(flags);
 }
 
 int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel, unsigned long size)
 {
-	switch (channel) {
-	case 0:
-		set_mal_dcrn(mal, DCRN_MALRCBS0, size);
-		break;
-#ifdef DCRN_MALRCBS1
-	case 1:
-		set_mal_dcrn(mal, DCRN_MALRCBS1, size);
-		break;
-#endif
-#ifdef DCRN_MALRCBS2
-	case 2:
-		set_mal_dcrn(mal, DCRN_MALRCBS2, size);
-		break;
-#endif
-#ifdef DCRN_MALRCBS3
-	case 3:
-		set_mal_dcrn(mal, DCRN_MALRCBS3, size);
-		break;
-#endif
-	default:
+	struct ocp_func_mal_data *maldata = mal->def->additions;
+	BUG_ON(channel < 0 || channel >= maldata->num_rx_chans ||
+	       size > MAL_MAX_RX_SIZE);
+
+	MAL_DBG("%d: set_rbcs(%d, %lu)" NL, mal->def->index, channel, size);
+
+	if (size & 0xf) {
+		printk(KERN_WARNING
+		       "mal%d: incorrect RX size %lu for the channel %d\n",
+		       mal->def->index, size, channel);
 		return -EINVAL;
 	}
 
+	set_mal_dcrn(mal, MAL_RCBS(channel), size >> 4);
 	return 0;
 }
 
+int mal_tx_bd_offset(struct ibm_ocp_mal *mal, int channel)
+{
+	struct ocp_func_mal_data *maldata = mal->def->additions;
+	BUG_ON(channel < 0 || channel >= maldata->num_tx_chans);
+	return channel * NUM_TX_BUFF;
+}
+
+int mal_rx_bd_offset(struct ibm_ocp_mal *mal, int channel)
+{
+	struct ocp_func_mal_data *maldata = mal->def->additions;
+	BUG_ON(channel < 0 || channel >= maldata->num_rx_chans);
+	return maldata->num_tx_chans * NUM_TX_BUFF + channel * NUM_RX_BUFF;
+}
+
+void mal_enable_tx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+	local_bh_disable();
+	MAL_DBG("%d: enable_tx(%d)" NL, mal->def->index, channel);
+	set_mal_dcrn(mal, MAL_TXCASR,
+		     get_mal_dcrn(mal, MAL_TXCASR) | MAL_CHAN_MASK(channel));
+	local_bh_enable();
+}
+
+void mal_disable_tx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+	set_mal_dcrn(mal, MAL_TXCARR, MAL_CHAN_MASK(channel));
+	MAL_DBG("%d: disable_tx(%d)" NL, mal->def->index, channel);
+}
+
+void mal_enable_rx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+	local_bh_disable();
+	MAL_DBG("%d: enable_rx(%d)" NL, mal->def->index, channel);
+	set_mal_dcrn(mal, MAL_RXCASR,
+		     get_mal_dcrn(mal, MAL_RXCASR) | MAL_CHAN_MASK(channel));
+	local_bh_enable();
+}
+
+void mal_disable_rx_channel(struct ibm_ocp_mal *mal, int channel)
+{
+	set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));
+	MAL_DBG("%d: disable_rx(%d)" NL, mal->def->index, channel);
+}
+
+void mal_poll_add(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+{
+	local_bh_disable();
+	MAL_DBG("%d: poll_add(%p)" NL, mal->def->index, commac);
+	list_add_tail(&commac->poll_list, &mal->poll_list);
+	local_bh_enable();
+}
+
+void mal_poll_del(struct ibm_ocp_mal *mal, struct mal_commac *commac)
+{
+	local_bh_disable();
+	MAL_DBG("%d: poll_del(%p)" NL, mal->def->index, commac);
+	list_del(&commac->poll_list);
+	local_bh_enable();
+}
+
+/* synchronized by mal_poll() */
+static inline void mal_enable_eob_irq(struct ibm_ocp_mal *mal)
+{
+	MAL_DBG2("%d: enable_irq" NL, mal->def->index);
+	set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) | MAL_CFG_EOPIE);
+}
+
+/* synchronized by __LINK_STATE_RX_SCHED bit in ndev->state */
+static inline void mal_disable_eob_irq(struct ibm_ocp_mal *mal)
+{
+	set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) & ~MAL_CFG_EOPIE);
+	MAL_DBG2("%d: disable_irq" NL, mal->def->index);
+}
+
 static irqreturn_t mal_serr(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
-	unsigned long mal_error;
-
-	/*
-	 * This SERR applies to one of the devices on the MAL, here we charge
-	 * it against the first EMAC registered for the MAL.
-	 */
-
-	mal_error = get_mal_dcrn(mal, DCRN_MALESR);
-
-	printk(KERN_ERR "%s: System Error (MALESR=%lx)\n",
-	       "MAL" /* FIXME: get the name right */ , mal_error);
-
-	/* FIXME: decipher error */
-	/* DIXME: distribute to commacs, if possible */
+	u32 esr = get_mal_dcrn(mal, MAL_ESR);
 
 	/* Clear the error status register */
-	set_mal_dcrn(mal, DCRN_MALESR, mal_error);
+	set_mal_dcrn(mal, MAL_ESR, esr);
 
+	MAL_DBG("%d: SERR %08x" NL, mal->def->index, esr);
+
+	if (esr & MAL_ESR_EVB) {
+		if (esr & MAL_ESR_DE) {
+			/* We ignore Descriptor error,
+			 * TXDE or RXDE interrupt will be generated anyway.
+			 */
+			return IRQ_HANDLED;
+		}
+
+		if (esr & MAL_ESR_PEIN) {
+			/* PLB error, it's probably buggy hardware or
+			 * incorrect physical address in BD (i.e. bug)
+			 */
+			if (net_ratelimit())
+				printk(KERN_ERR
+				       "mal%d: system error, PLB (ESR = 0x%08x)\n",
+				       mal->def->index, esr);
+			return IRQ_HANDLED;
+		}
+
+		/* OPB error, it's probably buggy hardware or incorrect EBC setup */
+		if (net_ratelimit())
+			printk(KERN_ERR
+			       "mal%d: system error, OPB (ESR = 0x%08x)\n",
+			       mal->def->index, esr);
+	}
 	return IRQ_HANDLED;
 }
 
+static inline void mal_schedule_poll(struct ibm_ocp_mal *mal)
+{
+	if (likely(netif_rx_schedule_prep(&mal->poll_dev))) {
+		MAL_DBG2("%d: schedule_poll" NL, mal->def->index);
+		mal_disable_eob_irq(mal);
+		__netif_rx_schedule(&mal->poll_dev);
+	} else
+		MAL_DBG2("%d: already in poll" NL, mal->def->index);
+}
+
 static irqreturn_t mal_txeob(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
-	struct list_head *l;
-	unsigned long isr;
-
-	isr = get_mal_dcrn(mal, DCRN_MALTXEOBISR);
-	set_mal_dcrn(mal, DCRN_MALTXEOBISR, isr);
-
-	read_lock(&mal_list_lock);
-	list_for_each(l, &mal->commac) {
-		struct mal_commac *mc = list_entry(l, struct mal_commac, list);
-
-		if (isr & mc->tx_chan_mask) {
-			mc->ops->txeob(mc->dev, isr & mc->tx_chan_mask);
-		}
-	}
-	read_unlock(&mal_list_lock);
-
+	u32 r = get_mal_dcrn(mal, MAL_TXEOBISR);
+	MAL_DBG2("%d: txeob %08x" NL, mal->def->index, r);
+	mal_schedule_poll(mal);
+	set_mal_dcrn(mal, MAL_TXEOBISR, r);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t mal_rxeob(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
-	struct list_head *l;
-	unsigned long isr;
-
-	isr = get_mal_dcrn(mal, DCRN_MALRXEOBISR);
-	set_mal_dcrn(mal, DCRN_MALRXEOBISR, isr);
-
-	read_lock(&mal_list_lock);
-	list_for_each(l, &mal->commac) {
-		struct mal_commac *mc = list_entry(l, struct mal_commac, list);
-
-		if (isr & mc->rx_chan_mask) {
-			mc->ops->rxeob(mc->dev, isr & mc->rx_chan_mask);
-		}
-	}
-	read_unlock(&mal_list_lock);
-
+	u32 r = get_mal_dcrn(mal, MAL_RXEOBISR);
+	MAL_DBG2("%d: rxeob %08x" NL, mal->def->index, r);
+	mal_schedule_poll(mal);
+	set_mal_dcrn(mal, MAL_RXEOBISR, r);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t mal_txde(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
-	struct list_head *l;
-	unsigned long deir;
+	u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);
+	set_mal_dcrn(mal, MAL_TXDEIR, deir);
 
-	deir = get_mal_dcrn(mal, DCRN_MALTXDEIR);
+	MAL_DBG("%d: txde %08x" NL, mal->def->index, deir);
 
-	/* FIXME: print which MAL correctly */
-	printk(KERN_WARNING "%s: Tx descriptor error (MALTXDEIR=%lx)\n",
-	       "MAL", deir);
-
-	read_lock(&mal_list_lock);
-	list_for_each(l, &mal->commac) {
-		struct mal_commac *mc = list_entry(l, struct mal_commac, list);
-
-		if (deir & mc->tx_chan_mask) {
-			mc->ops->txde(mc->dev, deir & mc->tx_chan_mask);
-		}
-	}
-	read_unlock(&mal_list_lock);
+	if (net_ratelimit())
+		printk(KERN_ERR
+		       "mal%d: TX descriptor error (TXDEIR = 0x%08x)\n",
+		       mal->def->index, deir);
 
 	return IRQ_HANDLED;
 }
 
-/*
- * This interrupt should be very rare at best.  This occurs when
- * the hardware has a problem with the receive descriptors.  The manual
- * states that it occurs when the hardware cannot the receive descriptor
- * empty bit is not set.  The recovery mechanism will be to
- * traverse through the descriptors, handle any that are marked to be
- * handled and reinitialize each along the way.  At that point the driver
- * will be restarted.
- */
 static irqreturn_t mal_rxde(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ibm_ocp_mal *mal = dev_instance;
 	struct list_head *l;
-	unsigned long deir;
+	u32 deir = get_mal_dcrn(mal, MAL_RXDEIR);
 
-	deir = get_mal_dcrn(mal, DCRN_MALRXDEIR);
+	MAL_DBG("%d: rxde %08x" NL, mal->def->index, deir);
 
-	/*
-	 * This really is needed.  This case encountered in stress testing.
-	 */
-	if (deir == 0)
-		return IRQ_HANDLED;
-
-	/* FIXME: print which MAL correctly */
-	printk(KERN_WARNING "%s: Rx descriptor error (MALRXDEIR=%lx)\n",
-	       "MAL", deir);
-
-	read_lock(&mal_list_lock);
-	list_for_each(l, &mal->commac) {
+	list_for_each(l, &mal->list) {
 		struct mal_commac *mc = list_entry(l, struct mal_commac, list);
-
 		if (deir & mc->rx_chan_mask) {
-			mc->ops->rxde(mc->dev, deir & mc->rx_chan_mask);
+			mc->rx_stopped = 1;
+			mc->ops->rxde(mc->dev);
 		}
 	}
-	read_unlock(&mal_list_lock);
+
+	mal_schedule_poll(mal);
+	set_mal_dcrn(mal, MAL_RXDEIR, deir);
 
 	return IRQ_HANDLED;
 }
 
+static int mal_poll(struct net_device *ndev, int *budget)
+{
+	struct ibm_ocp_mal *mal = ndev->priv;
+	struct list_head *l;
+	int rx_work_limit = min(ndev->quota, *budget), received = 0, done;
+
+	MAL_DBG2("%d: poll(%d) %d ->" NL, mal->def->index, *budget,
+		 rx_work_limit);
+      again:
+	/* Process TX skbs */
+	list_for_each(l, &mal->poll_list) {
+		struct mal_commac *mc =
+		    list_entry(l, struct mal_commac, poll_list);
+		mc->ops->poll_tx(mc->dev);
+	}
+
+	/* Process RX skbs.
+	 * We _might_ need something more smart here to enforce polling fairness.
+	 */
+	list_for_each(l, &mal->poll_list) {
+		struct mal_commac *mc =
+		    list_entry(l, struct mal_commac, poll_list);
+		int n = mc->ops->poll_rx(mc->dev, rx_work_limit);
+		if (n) {
+			received += n;
+			rx_work_limit -= n;
+			if (rx_work_limit <= 0) {
+				done = 0;
+				goto more_work;	// XXX What if this is the last one ?
+			}
+		}
+	}
+
+	/* We need to disable IRQs to protect from RXDE IRQ here */
+	local_irq_disable();
+	__netif_rx_complete(ndev);
+	mal_enable_eob_irq(mal);
+	local_irq_enable();
+
+	done = 1;
+
+	/* Check for "rotting" packet(s) */
+	list_for_each(l, &mal->poll_list) {
+		struct mal_commac *mc =
+		    list_entry(l, struct mal_commac, poll_list);
+		if (unlikely(mc->ops->peek_rx(mc->dev) || mc->rx_stopped)) {
+			MAL_DBG2("%d: rotting packet" NL, mal->def->index);
+			if (netif_rx_reschedule(ndev, received))
+				mal_disable_eob_irq(mal);
+			else
+				MAL_DBG2("%d: already in poll list" NL,
+					 mal->def->index);
+
+			if (rx_work_limit > 0)
+				goto again;
+			else
+				goto more_work;
+		}
+		mc->ops->poll_tx(mc->dev);
+	}
+
+      more_work:
+	ndev->quota -= received;
+	*budget -= received;
+
+	MAL_DBG2("%d: poll() %d <- %d" NL, mal->def->index, *budget,
+		 done ? 0 : 1);
+	return done ? 0 : 1;
+}
+
+static void mal_reset(struct ibm_ocp_mal *mal)
+{
+	int n = 10;
+	MAL_DBG("%d: reset" NL, mal->def->index);
+
+	set_mal_dcrn(mal, MAL_CFG, MAL_CFG_SR);
+
+	/* Wait for reset to complete (1 system clock) */
+	while ((get_mal_dcrn(mal, MAL_CFG) & MAL_CFG_SR) && n)
+		--n;
+
+	if (unlikely(!n))
+		printk(KERN_ERR "mal%d: reset timeout\n", mal->def->index);
+}
+
+int mal_get_regs_len(struct ibm_ocp_mal *mal)
+{
+	return sizeof(struct emac_ethtool_regs_subhdr) +
+	    sizeof(struct ibm_mal_regs);
+}
+
+void *mal_dump_regs(struct ibm_ocp_mal *mal, void *buf)
+{
+	struct emac_ethtool_regs_subhdr *hdr = buf;
+	struct ibm_mal_regs *regs = (struct ibm_mal_regs *)(hdr + 1);
+	struct ocp_func_mal_data *maldata = mal->def->additions;
+	int i;
+
+	hdr->version = MAL_VERSION;
+	hdr->index = mal->def->index;
+
+	regs->tx_count = maldata->num_tx_chans;
+	regs->rx_count = maldata->num_rx_chans;
+
+	regs->cfg = get_mal_dcrn(mal, MAL_CFG);
+	regs->esr = get_mal_dcrn(mal, MAL_ESR);
+	regs->ier = get_mal_dcrn(mal, MAL_IER);
+	regs->tx_casr = get_mal_dcrn(mal, MAL_TXCASR);
+	regs->tx_carr = get_mal_dcrn(mal, MAL_TXCARR);
+	regs->tx_eobisr = get_mal_dcrn(mal, MAL_TXEOBISR);
+	regs->tx_deir = get_mal_dcrn(mal, MAL_TXDEIR);
+	regs->rx_casr = get_mal_dcrn(mal, MAL_RXCASR);
+	regs->rx_carr = get_mal_dcrn(mal, MAL_RXCARR);
+	regs->rx_eobisr = get_mal_dcrn(mal, MAL_RXEOBISR);
+	regs->rx_deir = get_mal_dcrn(mal, MAL_RXDEIR);
+
+	for (i = 0; i < regs->tx_count; ++i)
+		regs->tx_ctpr[i] = get_mal_dcrn(mal, MAL_TXCTPR(i));
+
+	for (i = 0; i < regs->rx_count; ++i) {
+		regs->rx_ctpr[i] = get_mal_dcrn(mal, MAL_RXCTPR(i));
+		regs->rcbs[i] = get_mal_dcrn(mal, MAL_RCBS(i));
+	}
+	return regs + 1;
+}
+
 static int __init mal_probe(struct ocp_device *ocpdev)
 {
-	struct ibm_ocp_mal *mal = NULL;
+	struct ibm_ocp_mal *mal;
 	struct ocp_func_mal_data *maldata;
-	int err = 0;
+	int err = 0, i, bd_size;
 
-	maldata = (struct ocp_func_mal_data *)ocpdev->def->additions;
+	MAL_DBG("%d: probe" NL, ocpdev->def->index);
+
+	maldata = ocpdev->def->additions;
 	if (maldata == NULL) {
-		printk(KERN_ERR "mal%d: Missing additional datas !\n",
+		printk(KERN_ERR "mal%d: missing additional data!\n",
 		       ocpdev->def->index);
 		return -ENODEV;
 	}
 
-	mal = kmalloc(sizeof(struct ibm_ocp_mal), GFP_KERNEL);
-	if (mal == NULL) {
+	mal = kzalloc(sizeof(struct ibm_ocp_mal), GFP_KERNEL);
+	if (!mal) {
 		printk(KERN_ERR
-		       "mal%d: Out of memory allocating MAL structure !\n",
+		       "mal%d: out of memory allocating MAL structure!\n",
 		       ocpdev->def->index);
 		return -ENOMEM;
 	}
-	memset(mal, 0, sizeof(*mal));
+	mal->dcrbase = maldata->dcr_base;
+	mal->def = ocpdev->def;
 
-	switch (ocpdev->def->index) {
-	case 0:
-		mal->dcrbase = DCRN_MAL_BASE;
-		break;
-#ifdef DCRN_MAL1_BASE
-	case 1:
-		mal->dcrbase = DCRN_MAL1_BASE;
-		break;
-#endif
-	default:
-		BUG();
-	}
+	INIT_LIST_HEAD(&mal->poll_list);
+	set_bit(__LINK_STATE_START, &mal->poll_dev.state);
+	mal->poll_dev.weight = CONFIG_IBM_EMAC_POLL_WEIGHT;
+	mal->poll_dev.poll = mal_poll;
+	mal->poll_dev.priv = mal;
+	atomic_set(&mal->poll_dev.refcnt, 1);
 
-	/**************************/
+	INIT_LIST_HEAD(&mal->list);
 
-	INIT_LIST_HEAD(&mal->commac);
-
-	set_mal_dcrn(mal, DCRN_MALRXCARR, 0xFFFFFFFF);
-	set_mal_dcrn(mal, DCRN_MALTXCARR, 0xFFFFFFFF);
-
-	set_mal_dcrn(mal, DCRN_MALCR, MALCR_MMSR);	/* 384 */
-	/* FIXME: Add delay */
+	/* Load power-on reset defaults */
+	mal_reset(mal);
 
 	/* Set the MAL configuration register */
-	set_mal_dcrn(mal, DCRN_MALCR,
-		     MALCR_PLBB | MALCR_OPBBL | MALCR_LEA |
-		     MALCR_PLBLT_DEFAULT);
+	set_mal_dcrn(mal, MAL_CFG, MAL_CFG_DEFAULT | MAL_CFG_PLBB |
+		     MAL_CFG_OPBBL | MAL_CFG_LEA);
 
-	/* It would be nice to allocate buffers separately for each
-	 * channel, but we can't because the channels share the upper
-	 * 13 bits of address lines.  Each channels buffer must also
-	 * be 4k aligned, so we allocate 4k for each channel.  This is
-	 * inefficient FIXME: do better, if possible */
-	mal->tx_virt_addr = dma_alloc_coherent(&ocpdev->dev,
-					       MAL_DT_ALIGN *
-					       maldata->num_tx_chans,
-					       &mal->tx_phys_addr, GFP_KERNEL);
-	if (mal->tx_virt_addr == NULL) {
+	mal_enable_eob_irq(mal);
+
+	/* Allocate space for BD rings */
+	BUG_ON(maldata->num_tx_chans <= 0 || maldata->num_tx_chans > 32);
+	BUG_ON(maldata->num_rx_chans <= 0 || maldata->num_rx_chans > 32);
+	bd_size = sizeof(struct mal_descriptor) *
+	    (NUM_TX_BUFF * maldata->num_tx_chans +
+	     NUM_RX_BUFF * maldata->num_rx_chans);
+	mal->bd_virt =
+	    dma_alloc_coherent(&ocpdev->dev, bd_size, &mal->bd_dma, GFP_KERNEL);
+
+	if (!mal->bd_virt) {
 		printk(KERN_ERR
-		       "mal%d: Out of memory allocating MAL descriptors !\n",
-		       ocpdev->def->index);
+		       "mal%d: out of memory allocating RX/TX descriptors!\n",
+		       mal->def->index);
 		err = -ENOMEM;
 		goto fail;
 	}
+	memset(mal->bd_virt, 0, bd_size);
 
-	/* God, oh, god, I hate DCRs */
-	set_mal_dcrn(mal, DCRN_MALTXCTP0R, mal->tx_phys_addr);
-#ifdef DCRN_MALTXCTP1R
-	if (maldata->num_tx_chans > 1)
-		set_mal_dcrn(mal, DCRN_MALTXCTP1R,
-			     mal->tx_phys_addr + MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP1R */
-#ifdef DCRN_MALTXCTP2R
-	if (maldata->num_tx_chans > 2)
-		set_mal_dcrn(mal, DCRN_MALTXCTP2R,
-			     mal->tx_phys_addr + 2 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP2R */
-#ifdef DCRN_MALTXCTP3R
-	if (maldata->num_tx_chans > 3)
-		set_mal_dcrn(mal, DCRN_MALTXCTP3R,
-			     mal->tx_phys_addr + 3 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP3R */
-#ifdef DCRN_MALTXCTP4R
-	if (maldata->num_tx_chans > 4)
-		set_mal_dcrn(mal, DCRN_MALTXCTP4R,
-			     mal->tx_phys_addr + 4 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP4R */
-#ifdef DCRN_MALTXCTP5R
-	if (maldata->num_tx_chans > 5)
-		set_mal_dcrn(mal, DCRN_MALTXCTP5R,
-			     mal->tx_phys_addr + 5 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP5R */
-#ifdef DCRN_MALTXCTP6R
-	if (maldata->num_tx_chans > 6)
-		set_mal_dcrn(mal, DCRN_MALTXCTP6R,
-			     mal->tx_phys_addr + 6 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP6R */
-#ifdef DCRN_MALTXCTP7R
-	if (maldata->num_tx_chans > 7)
-		set_mal_dcrn(mal, DCRN_MALTXCTP7R,
-			     mal->tx_phys_addr + 7 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALTXCTP7R */
+	for (i = 0; i < maldata->num_tx_chans; ++i)
+		set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma +
+			     sizeof(struct mal_descriptor) *
+			     mal_tx_bd_offset(mal, i));
 
-	mal->rx_virt_addr = dma_alloc_coherent(&ocpdev->dev,
-					       MAL_DT_ALIGN *
-					       maldata->num_rx_chans,
-					       &mal->rx_phys_addr, GFP_KERNEL);
-
-	set_mal_dcrn(mal, DCRN_MALRXCTP0R, mal->rx_phys_addr);
-#ifdef DCRN_MALRXCTP1R
-	if (maldata->num_rx_chans > 1)
-		set_mal_dcrn(mal, DCRN_MALRXCTP1R,
-			     mal->rx_phys_addr + MAL_DT_ALIGN);
-#endif				/* DCRN_MALRXCTP1R */
-#ifdef DCRN_MALRXCTP2R
-	if (maldata->num_rx_chans > 2)
-		set_mal_dcrn(mal, DCRN_MALRXCTP2R,
-			     mal->rx_phys_addr + 2 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALRXCTP2R */
-#ifdef DCRN_MALRXCTP3R
-	if (maldata->num_rx_chans > 3)
-		set_mal_dcrn(mal, DCRN_MALRXCTP3R,
-			     mal->rx_phys_addr + 3 * MAL_DT_ALIGN);
-#endif				/* DCRN_MALRXCTP3R */
+	for (i = 0; i < maldata->num_rx_chans; ++i)
+		set_mal_dcrn(mal, MAL_RXCTPR(i), mal->bd_dma +
+			     sizeof(struct mal_descriptor) *
+			     mal_rx_bd_offset(mal, i));
 
 	err = request_irq(maldata->serr_irq, mal_serr, 0, "MAL SERR", mal);
 	if (err)
-		goto fail;
-	err = request_irq(maldata->txde_irq, mal_txde, 0, "MAL TX DE ", mal);
+		goto fail2;
+	err = request_irq(maldata->txde_irq, mal_txde, 0, "MAL TX DE", mal);
 	if (err)
-		goto fail;
+		goto fail3;
 	err = request_irq(maldata->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
 	if (err)
-		goto fail;
+		goto fail4;
 	err = request_irq(maldata->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
 	if (err)
-		goto fail;
+		goto fail5;
 	err = request_irq(maldata->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
 	if (err)
-		goto fail;
+		goto fail6;
 
-	set_mal_dcrn(mal, DCRN_MALIER,
-		     MALIER_DE | MALIER_NE | MALIER_TE |
-		     MALIER_OPBE | MALIER_PLBE);
+	/* Enable all MAL SERR interrupt sources */
+	set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS);
 
-	/* Advertise me to the rest of the world */
+	/* Advertise this instance to the rest of the world */
 	ocp_set_drvdata(ocpdev, mal);
 
-	printk(KERN_INFO "mal%d: Initialized, %d tx channels, %d rx channels\n",
-	       ocpdev->def->index, maldata->num_tx_chans,
-	       maldata->num_rx_chans);
+	mal_dbg_register(mal->def->index, mal);
 
+	printk(KERN_INFO "mal%d: initialized, %d TX channels, %d RX channels\n",
+	       mal->def->index, maldata->num_tx_chans, maldata->num_rx_chans);
 	return 0;
 
+      fail6:
+	free_irq(maldata->rxde_irq, mal);
+      fail5:
+	free_irq(maldata->txeob_irq, mal);
+      fail4:
+	free_irq(maldata->txde_irq, mal);
+      fail3:
+	free_irq(maldata->serr_irq, mal);
+      fail2:
+	dma_free_coherent(&ocpdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
       fail:
-	/* FIXME: dispose requested IRQs ! */
-	if (err && mal)
-		kfree(mal);
+	kfree(mal);
 	return err;
 }
 
 static void __exit mal_remove(struct ocp_device *ocpdev)
 {
 	struct ibm_ocp_mal *mal = ocp_get_drvdata(ocpdev);
-	struct ocp_func_mal_data *maldata = ocpdev->def->additions;
+	struct ocp_func_mal_data *maldata = mal->def->additions;
 
-	BUG_ON(!maldata);
+	MAL_DBG("%d: remove" NL, mal->def->index);
+
+	/* Syncronize with scheduled polling, 
+	   stolen from net/core/dev.c:dev_close() 
+	 */
+	clear_bit(__LINK_STATE_START, &mal->poll_dev.state);
+	netif_poll_disable(&mal->poll_dev);
+
+	if (!list_empty(&mal->list)) {
+		/* This is *very* bad */
+		printk(KERN_EMERG
+		       "mal%d: commac list is not empty on remove!\n",
+		       mal->def->index);
+	}
 
 	ocp_set_drvdata(ocpdev, NULL);
 
-	/* FIXME: shut down the MAL, deal with dependency with emac */
 	free_irq(maldata->serr_irq, mal);
 	free_irq(maldata->txde_irq, mal);
 	free_irq(maldata->txeob_irq, mal);
 	free_irq(maldata->rxde_irq, mal);
 	free_irq(maldata->rxeob_irq, mal);
 
-	if (mal->tx_virt_addr)
-		dma_free_coherent(&ocpdev->dev,
-				  MAL_DT_ALIGN * maldata->num_tx_chans,
-				  mal->tx_virt_addr, mal->tx_phys_addr);
+	mal_reset(mal);
 
-	if (mal->rx_virt_addr)
-		dma_free_coherent(&ocpdev->dev,
-				  MAL_DT_ALIGN * maldata->num_rx_chans,
-				  mal->rx_virt_addr, mal->rx_phys_addr);
+	mal_dbg_register(mal->def->index, NULL);
+
+	dma_free_coherent(&ocpdev->dev,
+			  sizeof(struct mal_descriptor) *
+			  (NUM_TX_BUFF * maldata->num_tx_chans +
+			   NUM_RX_BUFF * maldata->num_rx_chans), mal->bd_virt,
+			  mal->bd_dma);
 
 	kfree(mal);
 }
 
 /* Structure for a device driver */
 static struct ocp_device_id mal_ids[] = {
-	{.vendor = OCP_ANY_ID,.function = OCP_FUNC_MAL},
-	{.vendor = OCP_VENDOR_INVALID}
+	{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_MAL },
+	{ .vendor = OCP_VENDOR_INVALID}
 };
 
 static struct ocp_driver mal_driver = {
@@ -441,23 +570,14 @@
 	.remove = mal_remove,
 };
 
-static int __init init_mals(void)
+int __init mal_init(void)
 {
-	int rc;
-
-	rc = ocp_register_driver(&mal_driver);
-	if (rc < 0) {
-		ocp_unregister_driver(&mal_driver);
-		return -ENODEV;
-	}
-
-	return 0;
+	MAL_DBG(": init" NL);
+	return ocp_register_driver(&mal_driver);
 }
 
-static void __exit exit_mals(void)
+void __exit mal_exit(void)
 {
+	MAL_DBG(": exit" NL);
 	ocp_unregister_driver(&mal_driver);
 }
-
-module_init(init_mals);
-module_exit(exit_mals);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index dd9f0da..15b0bda 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -1,131 +1,267 @@
-#ifndef _IBM_EMAC_MAL_H
-#define _IBM_EMAC_MAL_H
+/*
+ * drivers/net/ibm_emac/ibm_emac_mal.h
+ *
+ * Memory Access Layer (MAL) support
+ * 
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * Based on original work by
+ *      Armin Kuster <akuster@mvista.com>
+ *      Copyright 2002 MontaVista Softare 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.
+ *
+ */
+#ifndef __IBM_EMAC_MAL_H_
+#define __IBM_EMAC_MAL_H_
 
+#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/list.h>
+#include <linux/netdevice.h>
 
-#define MAL_DT_ALIGN	(4096)	/* Alignment for each channel's descriptor table */
+#include <asm/io.h>
 
-#define MAL_CHAN_MASK(chan)	(0x80000000 >> (chan))
+/*
+ * These MAL "versions" probably aren't the real versions IBM uses for these 
+ * MAL cores, I assigned them just to make #ifdefs in this file nicer and 
+ * reflect the fact that 40x and 44x have slightly different MALs. --ebs
+ */
+#if defined(CONFIG_405GP) || defined(CONFIG_405GPR) || defined(CONFIG_405EP) || \
+    defined(CONFIG_440EP) || defined(CONFIG_NP405H)
+#define MAL_VERSION		1
+#elif defined(CONFIG_440GP) || defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#define MAL_VERSION		2
+#else
+#error "Unknown SoC, please check chip manual and choose MAL 'version'"
+#endif
+
+/* MALx DCR registers */
+#define	MAL_CFG			0x00
+#define	  MAL_CFG_SR		0x80000000
+#define   MAL_CFG_PLBB		0x00004000
+#define   MAL_CFG_OPBBL		0x00000080
+#define   MAL_CFG_EOPIE		0x00000004
+#define   MAL_CFG_LEA		0x00000002
+#define   MAL_CFG_SD		0x00000001
+#if MAL_VERSION == 1
+#define   MAL_CFG_PLBP_MASK	0x00c00000
+#define   MAL_CFG_PLBP_10	0x00800000
+#define   MAL_CFG_GA		0x00200000
+#define   MAL_CFG_OA		0x00100000
+#define   MAL_CFG_PLBLE		0x00080000
+#define   MAL_CFG_PLBT_MASK	0x00078000
+#define   MAL_CFG_DEFAULT	(MAL_CFG_PLBP_10 | MAL_CFG_PLBT_MASK)
+#elif MAL_VERSION == 2
+#define   MAL_CFG_RPP_MASK	0x00c00000
+#define   MAL_CFG_RPP_10	0x00800000
+#define   MAL_CFG_RMBS_MASK	0x00300000
+#define   MAL_CFG_WPP_MASK	0x000c0000
+#define   MAL_CFG_WPP_10	0x00080000
+#define   MAL_CFG_WMBS_MASK	0x00030000
+#define   MAL_CFG_PLBLE		0x00008000
+#define   MAL_CFG_DEFAULT	(MAL_CFG_RMBS_MASK | MAL_CFG_WMBS_MASK | \
+				 MAL_CFG_RPP_10 | MAL_CFG_WPP_10)
+#else
+#error "Unknown MAL version"
+#endif
+
+#define MAL_ESR			0x01
+#define   MAL_ESR_EVB		0x80000000
+#define   MAL_ESR_CIDT		0x40000000
+#define   MAL_ESR_CID_MASK	0x3e000000
+#define   MAL_ESR_CID_SHIFT	25
+#define   MAL_ESR_DE		0x00100000
+#define   MAL_ESR_OTE		0x00040000
+#define   MAL_ESR_OSE		0x00020000
+#define   MAL_ESR_PEIN		0x00010000
+#define   MAL_ESR_DEI		0x00000010
+#define   MAL_ESR_OTEI		0x00000004
+#define   MAL_ESR_OSEI		0x00000002
+#define   MAL_ESR_PBEI		0x00000001
+#if MAL_VERSION == 1
+#define   MAL_ESR_ONE		0x00080000
+#define   MAL_ESR_ONEI		0x00000008
+#elif MAL_VERSION == 2
+#define   MAL_ESR_PTE		0x00800000
+#define   MAL_ESR_PRE		0x00400000
+#define   MAL_ESR_PWE		0x00200000
+#define   MAL_ESR_PTEI		0x00000080
+#define   MAL_ESR_PREI		0x00000040
+#define   MAL_ESR_PWEI		0x00000020
+#else
+#error "Unknown MAL version"
+#endif
+
+#define MAL_IER			0x02
+#define   MAL_IER_DE		0x00000010
+#define   MAL_IER_OTE		0x00000004
+#define   MAL_IER_OE		0x00000002
+#define   MAL_IER_PE		0x00000001
+#if MAL_VERSION == 1
+#define   MAL_IER_NWE		0x00000008
+#define   MAL_IER_SOC_EVENTS	MAL_IER_NWE
+#elif MAL_VERSION == 2
+#define   MAL_IER_PT		0x00000080
+#define   MAL_IER_PRE		0x00000040
+#define   MAL_IER_PWE		0x00000020
+#define   MAL_IER_SOC_EVENTS	(MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE)
+#else
+#error "Unknown MAL version"
+#endif
+#define   MAL_IER_EVENTS	(MAL_IER_SOC_EVENTS | MAL_IER_OTE | \
+				 MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
+
+#define MAL_TXCASR		0x04
+#define MAL_TXCARR		0x05
+#define MAL_TXEOBISR		0x06
+#define MAL_TXDEIR		0x07
+#define MAL_RXCASR		0x10
+#define MAL_RXCARR		0x11
+#define MAL_RXEOBISR		0x12
+#define MAL_RXDEIR		0x13
+#define MAL_TXCTPR(n)		((n) + 0x20)
+#define MAL_RXCTPR(n)		((n) + 0x40)
+#define MAL_RCBS(n)		((n) + 0x60)
+
+/* In reality MAL can handle TX buffers up to 4095 bytes long, 
+ * but this isn't a good round number :) 		 --ebs
+ */
+#define MAL_MAX_TX_SIZE		4080
+#define MAL_MAX_RX_SIZE		4080
+
+static inline int mal_rx_size(int len)
+{
+	len = (len + 0xf) & ~0xf;
+	return len > MAL_MAX_RX_SIZE ? MAL_MAX_RX_SIZE : len;
+}
+
+static inline int mal_tx_chunks(int len)
+{
+	return (len + MAL_MAX_TX_SIZE - 1) / MAL_MAX_TX_SIZE;
+}
+
+#define MAL_CHAN_MASK(n)	(0x80000000 >> (n))
 
 /* MAL Buffer Descriptor structure */
 struct mal_descriptor {
-	unsigned short ctrl;	/* MAL / Commac status control bits */
-	short data_len;		/* Max length is 4K-1 (12 bits)     */
-	unsigned char *data_ptr;	/* pointer to actual data buffer    */
-} __attribute__ ((packed));
+	u16 ctrl;		/* MAL / Commac status control bits */
+	u16 data_len;		/* Max length is 4K-1 (12 bits)     */
+	u32 data_ptr;		/* pointer to actual data buffer    */
+};
 
 /* the following defines are for the MadMAL status and control registers. */
 /* MADMAL transmit and receive status/control bits  */
-#define MAL_RX_CTRL_EMPTY		0x8000
-#define MAL_RX_CTRL_WRAP		0x4000
-#define MAL_RX_CTRL_CM			0x2000
-#define MAL_RX_CTRL_LAST		0x1000
-#define MAL_RX_CTRL_FIRST		0x0800
-#define MAL_RX_CTRL_INTR		0x0400
+#define MAL_RX_CTRL_EMPTY	0x8000
+#define MAL_RX_CTRL_WRAP	0x4000
+#define MAL_RX_CTRL_CM		0x2000
+#define MAL_RX_CTRL_LAST	0x1000
+#define MAL_RX_CTRL_FIRST	0x0800
+#define MAL_RX_CTRL_INTR	0x0400
+#define MAL_RX_CTRL_SINGLE	(MAL_RX_CTRL_LAST | MAL_RX_CTRL_FIRST)
+#define MAL_IS_SINGLE_RX(ctrl)	(((ctrl) & MAL_RX_CTRL_SINGLE) == MAL_RX_CTRL_SINGLE)
 
-#define MAL_TX_CTRL_READY		0x8000
-#define MAL_TX_CTRL_WRAP		0x4000
-#define MAL_TX_CTRL_CM			0x2000
-#define MAL_TX_CTRL_LAST		0x1000
-#define MAL_TX_CTRL_INTR		0x0400
+#define MAL_TX_CTRL_READY	0x8000
+#define MAL_TX_CTRL_WRAP	0x4000
+#define MAL_TX_CTRL_CM		0x2000
+#define MAL_TX_CTRL_LAST	0x1000
+#define MAL_TX_CTRL_INTR	0x0400
 
 struct mal_commac_ops {
-	void (*txeob) (void *dev, u32 chanmask);
-	void (*txde) (void *dev, u32 chanmask);
-	void (*rxeob) (void *dev, u32 chanmask);
-	void (*rxde) (void *dev, u32 chanmask);
+	void	(*poll_tx) (void *dev);
+	int	(*poll_rx) (void *dev, int budget);
+	int	(*peek_rx) (void *dev);
+	void	(*rxde) (void *dev);
 };
 
 struct mal_commac {
-	struct mal_commac_ops *ops;
-	void *dev;
-	u32 tx_chan_mask, rx_chan_mask;
-	struct list_head list;
+	struct mal_commac_ops	*ops;
+	void			*dev;
+	struct list_head	poll_list;
+	int			rx_stopped;
+
+	u32			tx_chan_mask;
+	u32			rx_chan_mask;
+	struct list_head	list;
 };
 
 struct ibm_ocp_mal {
-	int dcrbase;
+	int			dcrbase;
 
-	struct list_head commac;
-	u32 tx_chan_mask, rx_chan_mask;
+	struct list_head	poll_list;
+	struct net_device	poll_dev;
 
-	dma_addr_t tx_phys_addr;
-	struct mal_descriptor *tx_virt_addr;
+	struct list_head	list;
+	u32			tx_chan_mask;
+	u32			rx_chan_mask;
 
-	dma_addr_t rx_phys_addr;
-	struct mal_descriptor *rx_virt_addr;
+	dma_addr_t		bd_dma;
+	struct mal_descriptor	*bd_virt;
+
+	struct ocp_def		*def;
 };
 
-#define GET_MAL_STANZA(base,dcrn) \
-	case base: \
-		x = mfdcr(dcrn(base)); \
-		break;
-
-#define SET_MAL_STANZA(base,dcrn, val) \
-	case base: \
-		mtdcr(dcrn(base), (val)); \
-		break;
-
-#define GET_MAL0_STANZA(dcrn) GET_MAL_STANZA(DCRN_MAL_BASE,dcrn)
-#define SET_MAL0_STANZA(dcrn,val) SET_MAL_STANZA(DCRN_MAL_BASE,dcrn,val)
-
-#ifdef DCRN_MAL1_BASE
-#define GET_MAL1_STANZA(dcrn) GET_MAL_STANZA(DCRN_MAL1_BASE,dcrn)
-#define SET_MAL1_STANZA(dcrn,val) SET_MAL_STANZA(DCRN_MAL1_BASE,dcrn,val)
-#else				/* ! DCRN_MAL1_BASE */
-#define GET_MAL1_STANZA(dcrn)
-#define SET_MAL1_STANZA(dcrn,val)
-#endif
-
-#define get_mal_dcrn(mal, dcrn) ({ \
-	u32 x; \
-	switch ((mal)->dcrbase) { \
-		GET_MAL0_STANZA(dcrn) \
-		GET_MAL1_STANZA(dcrn) \
-	default: \
-		x = 0; \
-		BUG(); \
-	} \
-x; })
-
-#define set_mal_dcrn(mal, dcrn, val) do { \
-	switch ((mal)->dcrbase) { \
-		SET_MAL0_STANZA(dcrn,val) \
-		SET_MAL1_STANZA(dcrn,val) \
-	default: \
-		BUG(); \
-	} } while (0)
-
-static inline void mal_enable_tx_channels(struct ibm_ocp_mal *mal, u32 chanmask)
+static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
 {
-	set_mal_dcrn(mal, DCRN_MALTXCASR,
-		     get_mal_dcrn(mal, DCRN_MALTXCASR) | chanmask);
+	return mfdcr(mal->dcrbase + reg);
 }
 
-static inline void mal_disable_tx_channels(struct ibm_ocp_mal *mal,
-					   u32 chanmask)
+static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
 {
-	set_mal_dcrn(mal, DCRN_MALTXCARR, chanmask);
+	mtdcr(mal->dcrbase + reg, val);
 }
 
-static inline void mal_enable_rx_channels(struct ibm_ocp_mal *mal, u32 chanmask)
-{
-	set_mal_dcrn(mal, DCRN_MALRXCASR,
-		     get_mal_dcrn(mal, DCRN_MALRXCASR) | chanmask);
-}
+/* Register MAL devices */
+int mal_init(void) __init;
+void mal_exit(void) __exit;
 
-static inline void mal_disable_rx_channels(struct ibm_ocp_mal *mal,
-					   u32 chanmask)
-{
-	set_mal_dcrn(mal, DCRN_MALRXCARR, chanmask);
-}
+int mal_register_commac(struct ibm_ocp_mal *mal,
+			struct mal_commac *commac) __init;
+void mal_unregister_commac(struct ibm_ocp_mal *mal,
+			   struct mal_commac *commac) __exit;
+int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel, unsigned long size);
 
-extern int mal_register_commac(struct ibm_ocp_mal *mal,
-			       struct mal_commac *commac);
-extern int mal_unregister_commac(struct ibm_ocp_mal *mal,
-				 struct mal_commac *commac);
+/* Returns BD ring offset for a particular channel
+   (in 'struct mal_descriptor' elements)
+*/
+int mal_tx_bd_offset(struct ibm_ocp_mal *mal, int channel);
+int mal_rx_bd_offset(struct ibm_ocp_mal *mal, int channel);
 
-extern int mal_set_rcbs(struct ibm_ocp_mal *mal, int channel,
-			unsigned long size);
+void mal_enable_tx_channel(struct ibm_ocp_mal *mal, int channel);
+void mal_disable_tx_channel(struct ibm_ocp_mal *mal, int channel);
+void mal_enable_rx_channel(struct ibm_ocp_mal *mal, int channel);
+void mal_disable_rx_channel(struct ibm_ocp_mal *mal, int channel);
 
-#endif				/* _IBM_EMAC_MAL_H */
+/* Add/remove EMAC to/from MAL polling list */
+void mal_poll_add(struct ibm_ocp_mal *mal, struct mal_commac *commac);
+void mal_poll_del(struct ibm_ocp_mal *mal, struct mal_commac *commac);
+
+/* Ethtool MAL registers */
+struct ibm_mal_regs {
+	u32 tx_count;
+	u32 rx_count;
+
+	u32 cfg;
+	u32 esr;
+	u32 ier;
+	u32 tx_casr;
+	u32 tx_carr;
+	u32 tx_eobisr;
+	u32 tx_deir;
+	u32 rx_casr;
+	u32 rx_carr;
+	u32 rx_eobisr;
+	u32 rx_deir;
+	u32 tx_ctpr[32];
+	u32 rx_ctpr[32];
+	u32 rcbs[32];
+};
+
+int mal_get_regs_len(struct ibm_ocp_mal *mal);
+void *mal_dump_regs(struct ibm_ocp_mal *mal, void *buf);
+
+#endif				/* __IBM_EMAC_MAL_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c
index 14213f0..a27e49c 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.c
+++ b/drivers/net/ibm_emac/ibm_emac_phy.c
@@ -1,61 +1,256 @@
 /*
- * ibm_ocp_phy.c
+ * drivers/net/ibm_emac/ibm_emac_phy.c
  *
- * PHY drivers for the ibm ocp ethernet driver. Borrowed
- * from sungem_phy.c, though I only kept the generic MII
+ * Driver for PowerPC 4xx on-chip ethernet controller, PHY support.
+ * Borrowed from sungem_phy.c, though I only kept the generic MII
  * driver for now.
  * 
  * This file should be shared with other drivers or eventually
  * merged as the "low level" part of miilib
  * 
  * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
  *
  */
-
 #include <linux/config.h>
-
 #include <linux/module.h>
-
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 
+#include <asm/ocp.h>
+
 #include "ibm_emac_phy.h"
 
-static int reset_one_mii_phy(struct mii_phy *phy, int phy_id)
+static inline int phy_read(struct mii_phy *phy, int reg)
 {
-	u16 val;
+	return phy->mdio_read(phy->dev, phy->address, reg);
+}
+
+static inline void phy_write(struct mii_phy *phy, int reg, int val)
+{
+	phy->mdio_write(phy->dev, phy->address, reg, val);
+}
+
+int mii_reset_phy(struct mii_phy *phy)
+{
+	int val;
 	int limit = 10000;
 
-	val = __phy_read(phy, phy_id, MII_BMCR);
+	val = phy_read(phy, MII_BMCR);
 	val &= ~BMCR_ISOLATE;
 	val |= BMCR_RESET;
-	__phy_write(phy, phy_id, MII_BMCR, val);
+	phy_write(phy, MII_BMCR, val);
 
-	udelay(100);
+	udelay(300);
 
 	while (limit--) {
-		val = __phy_read(phy, phy_id, MII_BMCR);
-		if ((val & BMCR_RESET) == 0)
+		val = phy_read(phy, MII_BMCR);
+		if (val >= 0 && (val & BMCR_RESET) == 0)
 			break;
 		udelay(10);
 	}
 	if ((val & BMCR_ISOLATE) && limit > 0)
-		__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
+		phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
 
-	return (limit <= 0);
+	return limit <= 0;
 }
 
+static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
+{
+	int ctl, adv;
+
+	phy->autoneg = AUTONEG_ENABLE;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = phy->asym_pause = 0;
+	phy->advertising = advertise;
+
+	/* Setup standard advertise */
+	adv = phy_read(phy, MII_ADVERTISE);
+	if (adv < 0)
+		return adv;
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
+		 ADVERTISE_PAUSE_ASYM);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	if (advertise & ADVERTISED_Pause)
+		adv |= ADVERTISE_PAUSE_CAP;
+	if (advertise & ADVERTISED_Asym_Pause)
+		adv |= ADVERTISE_PAUSE_ASYM;
+	phy_write(phy, MII_ADVERTISE, adv);
+
+	if (phy->features &
+	    (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
+		adv = phy_read(phy, MII_CTRL1000);
+		if (adv < 0)
+			return adv;
+		adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+		if (advertise & ADVERTISED_1000baseT_Full)
+			adv |= ADVERTISE_1000FULL;
+		if (advertise & ADVERTISED_1000baseT_Half)
+			adv |= ADVERTISE_1000HALF;
+		phy_write(phy, MII_CTRL1000, adv);
+	}
+
+	/* Start/Restart aneg */
+	ctl = phy_read(phy, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
+{
+	int ctl;
+
+	phy->autoneg = AUTONEG_DISABLE;
+	phy->speed = speed;
+	phy->duplex = fd;
+	phy->pause = phy->asym_pause = 0;
+
+	ctl = phy_read(phy, MII_BMCR);
+	if (ctl < 0)
+		return ctl;
+	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
+
+	/* First reset the PHY */
+	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
+
+	/* Select speed & duplex */
+	switch (speed) {
+	case SPEED_10:
+		break;
+	case SPEED_100:
+		ctl |= BMCR_SPEED100;
+		break;
+	case SPEED_1000:
+		ctl |= BMCR_SPEED1000;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+	phy_write(phy, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int genmii_poll_link(struct mii_phy *phy)
+{
+	int status;
+
+	/* Clear latched value with dummy read */
+	phy_read(phy, MII_BMSR);
+	status = phy_read(phy, MII_BMSR);
+	if (status < 0 || (status & BMSR_LSTATUS) == 0)
+		return 0;
+	if (phy->autoneg == AUTONEG_ENABLE && !(status & BMSR_ANEGCOMPLETE))
+		return 0;
+	return 1;
+}
+
+static int genmii_read_link(struct mii_phy *phy)
+{
+	if (phy->autoneg == AUTONEG_ENABLE) {
+		int glpa = 0;
+		int lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
+		if (lpa < 0)
+			return lpa;
+
+		if (phy->features &
+		    (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
+			int adv = phy_read(phy, MII_CTRL1000);
+			glpa = phy_read(phy, MII_STAT1000);
+
+			if (glpa < 0 || adv < 0)
+				return adv;
+
+			glpa &= adv << 2;
+		}
+
+		phy->speed = SPEED_10;
+		phy->duplex = DUPLEX_HALF;
+		phy->pause = phy->asym_pause = 0;
+
+		if (glpa & (LPA_1000FULL | LPA_1000HALF)) {
+			phy->speed = SPEED_1000;
+			if (glpa & LPA_1000FULL)
+				phy->duplex = DUPLEX_FULL;
+		} else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+			phy->speed = SPEED_100;
+			if (lpa & LPA_100FULL)
+				phy->duplex = DUPLEX_FULL;
+		} else if (lpa & LPA_10FULL)
+			phy->duplex = DUPLEX_FULL;
+
+		if (phy->duplex == DUPLEX_FULL) {
+			phy->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
+			phy->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
+		}
+	} else {
+		int bmcr = phy_read(phy, MII_BMCR);
+		if (bmcr < 0)
+			return bmcr;
+
+		if (bmcr & BMCR_FULLDPLX)
+			phy->duplex = DUPLEX_FULL;
+		else
+			phy->duplex = DUPLEX_HALF;
+		if (bmcr & BMCR_SPEED1000)
+			phy->speed = SPEED_1000;
+		else if (bmcr & BMCR_SPEED100)
+			phy->speed = SPEED_100;
+		else
+			phy->speed = SPEED_10;
+
+		phy->pause = phy->asym_pause = 0;
+	}
+	return 0;
+}
+
+/* Generic implementation for most 10/100/1000 PHYs */
+static struct mii_phy_ops generic_phy_ops = {
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link
+};
+
+static struct mii_phy_def genmii_phy_def = {
+	.phy_id		= 0x00000000,
+	.phy_id_mask	= 0x00000000,
+	.name		= "Generic MII",
+	.ops		= &generic_phy_ops
+};
+
+/* CIS8201 */
+#define MII_CIS8201_EPCR	0x17
+#define  EPCR_MODE_MASK		0x3000
+#define  EPCR_GMII_MODE		0x0000
+#define  EPCR_RGMII_MODE	0x1000
+#define  EPCR_TBI_MODE		0x2000
+#define  EPCR_RTBI_MODE		0x3000
+
 static int cis8201_init(struct mii_phy *phy)
 {
-	u16 epcr;
+	int epcr;
 
 	epcr = phy_read(phy, MII_CIS8201_EPCR);
+	if (epcr < 0)
+		return epcr;
+
 	epcr &= ~EPCR_MODE_MASK;
 
 	switch (phy->mode) {
@@ -78,178 +273,19 @@
 	return 0;
 }
 
-static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
-{
-	u16 ctl, adv;
-
-	phy->autoneg = 1;
-	phy->speed = SPEED_10;
-	phy->duplex = DUPLEX_HALF;
-	phy->pause = 0;
-	phy->advertising = advertise;
-
-	/* Setup standard advertise */
-	adv = phy_read(phy, MII_ADVERTISE);
-	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	if (advertise & ADVERTISED_10baseT_Half)
-		adv |= ADVERTISE_10HALF;
-	if (advertise & ADVERTISED_10baseT_Full)
-		adv |= ADVERTISE_10FULL;
-	if (advertise & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	phy_write(phy, MII_ADVERTISE, adv);
-
-	/* Start/Restart aneg */
-	ctl = phy_read(phy, MII_BMCR);
-	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
-{
-	u16 ctl;
-
-	phy->autoneg = 0;
-	phy->speed = speed;
-	phy->duplex = fd;
-	phy->pause = 0;
-
-	ctl = phy_read(phy, MII_BMCR);
-	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
-
-	/* First reset the PHY */
-	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
-
-	/* Select speed & duplex */
-	switch (speed) {
-	case SPEED_10:
-		break;
-	case SPEED_100:
-		ctl |= BMCR_SPEED100;
-		break;
-	case SPEED_1000:
-	default:
-		return -EINVAL;
-	}
-	if (fd == DUPLEX_FULL)
-		ctl |= BMCR_FULLDPLX;
-	phy_write(phy, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int genmii_poll_link(struct mii_phy *phy)
-{
-	u16 status;
-
-	(void)phy_read(phy, MII_BMSR);
-	status = phy_read(phy, MII_BMSR);
-	if ((status & BMSR_LSTATUS) == 0)
-		return 0;
-	if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
-		return 0;
-	return 1;
-}
-
-#define	MII_CIS8201_ACSR	0x1c
-#define  ACSR_DUPLEX_STATUS	0x0020
-#define  ACSR_SPEED_1000BASET	0x0010
-#define  ACSR_SPEED_100BASET	0x0008
-
-static int cis8201_read_link(struct mii_phy *phy)
-{
-	u16 acsr;
-
-	if (phy->autoneg) {
-		acsr = phy_read(phy, MII_CIS8201_ACSR);
-
-		if (acsr & ACSR_DUPLEX_STATUS)
-			phy->duplex = DUPLEX_FULL;
-		else
-			phy->duplex = DUPLEX_HALF;
-		if (acsr & ACSR_SPEED_1000BASET) {
-			phy->speed = SPEED_1000;
-		} else if (acsr & ACSR_SPEED_100BASET)
-			phy->speed = SPEED_100;
-		else
-			phy->speed = SPEED_10;
-		phy->pause = 0;
-	}
-	/* On non-aneg, we assume what we put in BMCR is the speed,
-	 * though magic-aneg shouldn't prevent this case from occurring
-	 */
-
-	return 0;
-}
-
-static int genmii_read_link(struct mii_phy *phy)
-{
-	u16 lpa;
-
-	if (phy->autoneg) {
-		lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
-
-		phy->speed = SPEED_10;
-		phy->duplex = DUPLEX_HALF;
-		phy->pause = 0;
-
-		if (lpa & (LPA_100FULL | LPA_100HALF)) {
-			phy->speed = SPEED_100;
-			if (lpa & LPA_100FULL)
-				phy->duplex = DUPLEX_FULL;
-		} else if (lpa & LPA_10FULL)
-			phy->duplex = DUPLEX_FULL;
-	}
-	/* On non-aneg, we assume what we put in BMCR is the speed,
-	 * though magic-aneg shouldn't prevent this case from occurring
-	 */
-
-	return 0;
-}
-
-#define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
-				 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-				 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
-#define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
-				 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
-
-/* CIS8201 phy ops */
 static struct mii_phy_ops cis8201_phy_ops = {
-	init:cis8201_init,
-	setup_aneg:genmii_setup_aneg,
-	setup_forced:genmii_setup_forced,
-	poll_link:genmii_poll_link,
-	read_link:cis8201_read_link
-};
-
-/* Generic implementation for most 10/100 PHYs */
-static struct mii_phy_ops generic_phy_ops = {
-	setup_aneg:genmii_setup_aneg,
-	setup_forced:genmii_setup_forced,
-	poll_link:genmii_poll_link,
-	read_link:genmii_read_link
+	.init		= cis8201_init,
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link
 };
 
 static struct mii_phy_def cis8201_phy_def = {
-	phy_id:0x000fc410,
-	phy_id_mask:0x000ffff0,
-	name:"CIS8201 Gigabit Ethernet",
-	features:MII_GBIT_FEATURES,
-	magic_aneg:0,
-	ops:&cis8201_phy_ops
-};
-
-static struct mii_phy_def genmii_phy_def = {
-	phy_id:0x00000000,
-	phy_id_mask:0x00000000,
-	name:"Generic MII",
-	features:MII_BASIC_FEATURES,
-	magic_aneg:0,
-	ops:&generic_phy_ops
+	.phy_id		= 0x000fc410,
+	.phy_id_mask	= 0x000ffff0,
+	.name		= "CIS8201 Gigabit Ethernet",
+	.ops		= &cis8201_phy_ops
 };
 
 static struct mii_phy_def *mii_phy_table[] = {
@@ -258,39 +294,60 @@
 	NULL
 };
 
-int mii_phy_probe(struct mii_phy *phy, int mii_id)
+int mii_phy_probe(struct mii_phy *phy, int address)
 {
-	int rc;
-	u32 id;
 	struct mii_phy_def *def;
 	int i;
+	u32 id;
 
-	phy->autoneg = 0;
+	phy->autoneg = AUTONEG_DISABLE;
 	phy->advertising = 0;
-	phy->mii_id = mii_id;
-	phy->speed = 0;
-	phy->duplex = 0;
-	phy->pause = 0;
+	phy->address = address;
+	phy->speed = SPEED_10;
+	phy->duplex = DUPLEX_HALF;
+	phy->pause = phy->asym_pause = 0;
 
-	/* Take PHY out of isloate mode and reset it. */
-	rc = reset_one_mii_phy(phy, mii_id);
-	if (rc)
+	/* Take PHY out of isolate mode and reset it. */
+	if (mii_reset_phy(phy))
 		return -ENODEV;
 
 	/* Read ID and find matching entry */
-	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2))
-	    & 0xfffffff0;
+	id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2);
 	for (i = 0; (def = mii_phy_table[i]) != NULL; i++)
 		if ((id & def->phy_id_mask) == def->phy_id)
 			break;
 	/* Should never be NULL (we have a generic entry), but... */
-	if (def == NULL)
+	if (!def)
 		return -ENODEV;
 
 	phy->def = def;
 
+	/* Determine PHY features if needed */
+	phy->features = def->features;
+	if (!phy->features) {
+		u16 bmsr = phy_read(phy, MII_BMSR);
+		if (bmsr & BMSR_ANEGCAPABLE)
+			phy->features |= SUPPORTED_Autoneg;
+		if (bmsr & BMSR_10HALF)
+			phy->features |= SUPPORTED_10baseT_Half;
+		if (bmsr & BMSR_10FULL)
+			phy->features |= SUPPORTED_10baseT_Full;
+		if (bmsr & BMSR_100HALF)
+			phy->features |= SUPPORTED_100baseT_Half;
+		if (bmsr & BMSR_100FULL)
+			phy->features |= SUPPORTED_100baseT_Full;
+		if (bmsr & BMSR_ESTATEN) {
+			u16 esr = phy_read(phy, MII_ESTATUS);
+			if (esr & ESTATUS_1000_TFULL)
+				phy->features |= SUPPORTED_1000baseT_Full;
+			if (esr & ESTATUS_1000_THALF)
+				phy->features |= SUPPORTED_1000baseT_Half;
+		}
+		phy->features |= SUPPORTED_MII;
+	}
+
 	/* Setup default advertising */
-	phy->advertising = def->features;
+	phy->advertising = phy->features;
 
 	return 0;
 }
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.h b/drivers/net/ibm_emac/ibm_emac_phy.h
index 61afbea..a70e0fe 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.h
+++ b/drivers/net/ibm_emac/ibm_emac_phy.h
@@ -1,65 +1,25 @@
-
 /*
- * ibm_emac_phy.h
+ * drivers/net/ibm_emac/ibm_emac_phy.h
  *
+ * Driver for PowerPC 4xx on-chip ethernet controller, PHY support
  *
- *      Benjamin Herrenschmidt <benh@kernel.crashing.org>
- *      February 2003
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * February 2003
+ *
+ * Minor additions by Eugene Surovegin <ebs@ebshome.net>, 2004
  *
  * 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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.
- *
+ * 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 file basically duplicates sungem_phy.{c,h} with different PHYs
  * supported. I'm looking into merging that in a single mii layer more
  * flexible than mii.c 
  */
 
-#ifndef _IBM_EMAC_PHY_H_
-#define _IBM_EMAC_PHY_H_
-
-/*
- * PHY mode settings
- * Used for multi-mode capable PHYs
- */
-#define PHY_MODE_NA	0
-#define PHY_MODE_MII	1
-#define PHY_MODE_RMII	2
-#define PHY_MODE_SMII	3
-#define PHY_MODE_RGMII	4
-#define PHY_MODE_TBI	5
-#define PHY_MODE_GMII	6
-#define PHY_MODE_RTBI	7
-#define PHY_MODE_SGMII	8
-
-/*
- * PHY specific registers/values
- */
-
-/* CIS8201 */
-#define MII_CIS8201_EPCR	0x17
-#define EPCR_MODE_MASK		0x3000
-#define EPCR_GMII_MODE		0x0000
-#define EPCR_RGMII_MODE		0x1000
-#define EPCR_TBI_MODE		0x2000
-#define EPCR_RTBI_MODE		0x3000
+#ifndef _IBM_OCP_PHY_H_
+#define _IBM_OCP_PHY_H_
 
 struct mii_phy;
 
@@ -77,7 +37,8 @@
 struct mii_phy_def {
 	u32 phy_id;		/* Concatenated ID1 << 16 | ID2 */
 	u32 phy_id_mask;	/* Significant bits */
-	u32 features;		/* Ethtool SUPPORTED_* defines */
+	u32 features;		/* Ethtool SUPPORTED_* defines or 
+				   0 for autodetect */
 	int magic_aneg;		/* Autoneg does all speed test for us */
 	const char *name;
 	const struct mii_phy_ops *ops;
@@ -86,8 +47,11 @@
 /* An instance of a PHY, partially borrowed from mii_if_info */
 struct mii_phy {
 	struct mii_phy_def *def;
-	int advertising;
-	int mii_id;
+	u32 advertising;	/* Ethtool ADVERTISED_* defines */
+	u32 features;		/* Copied from mii_phy_def.features 
+				   or determined automaticaly */
+	int address;		/* PHY address */
+	int mode;		/* PHY mode */
 
 	/* 1: autoneg enabled, 0: disabled */
 	int autoneg;
@@ -98,40 +62,19 @@
 	int speed;
 	int duplex;
 	int pause;
-
-	/* PHY mode - if needed */
-	int mode;
+	int asym_pause;
 
 	/* Provided by host chip */
 	struct net_device *dev;
-	int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
-	void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
+	int (*mdio_read) (struct net_device * dev, int addr, int reg);
+	void (*mdio_write) (struct net_device * dev, int addr, int reg,
 			    int val);
 };
 
 /* Pass in a struct mii_phy with dev, mdio_read and mdio_write
  * filled, the remaining fields will be filled on return
  */
-extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
+int mii_phy_probe(struct mii_phy *phy, int address);
+int mii_reset_phy(struct mii_phy *phy);
 
-static inline int __phy_read(struct mii_phy *phy, int id, int reg)
-{
-	return phy->mdio_read(phy->dev, id, reg);
-}
-
-static inline void __phy_write(struct mii_phy *phy, int id, int reg, int val)
-{
-	phy->mdio_write(phy->dev, id, reg, val);
-}
-
-static inline int phy_read(struct mii_phy *phy, int reg)
-{
-	return phy->mdio_read(phy->dev, phy->mii_id, reg);
-}
-
-static inline void phy_write(struct mii_phy *phy, int reg, int val)
-{
-	phy->mdio_write(phy->dev, phy->mii_id, reg, val);
-}
-
-#endif				/* _IBM_EMAC_PHY_H_ */
+#endif				/* _IBM_OCP_PHY_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.c b/drivers/net/ibm_emac/ibm_emac_rgmii.c
new file mode 100644
index 0000000..f0b1ffb
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_rgmii.c
@@ -0,0 +1,201 @@
+/*
+ * drivers/net/ibm_emac/ibm_emac_rgmii.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * Based on original work by
+ * 	Matt Porter <mporter@kernel.crashing.org>
+ * 	Copyright 2004 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <asm/io.h>
+
+#include "ibm_emac_core.h"
+#include "ibm_emac_debug.h"
+
+/* RGMIIx_FER */
+#define RGMII_FER_MASK(idx)	(0x7 << ((idx) * 4))
+#define RGMII_FER_RTBI(idx)	(0x4 << ((idx) * 4))
+#define RGMII_FER_RGMII(idx)	(0x5 << ((idx) * 4))
+#define RGMII_FER_TBI(idx)	(0x6 << ((idx) * 4))
+#define RGMII_FER_GMII(idx)	(0x7 << ((idx) * 4))
+
+/* RGMIIx_SSR */
+#define RGMII_SSR_MASK(idx)	(0x7 << ((idx) * 8))
+#define RGMII_SSR_100(idx)	(0x2 << ((idx) * 8))
+#define RGMII_SSR_1000(idx)	(0x4 << ((idx) * 8))
+
+/* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
+static inline int rgmii_valid_mode(int phy_mode)
+{
+	return  phy_mode == PHY_MODE_GMII ||
+		phy_mode == PHY_MODE_RGMII ||
+		phy_mode == PHY_MODE_TBI ||
+		phy_mode == PHY_MODE_RTBI;
+}
+
+static inline const char *rgmii_mode_name(int mode)
+{
+	switch (mode) {
+	case PHY_MODE_RGMII:
+		return "RGMII";
+	case PHY_MODE_TBI:
+		return "TBI";
+	case PHY_MODE_GMII:
+		return "GMII";
+	case PHY_MODE_RTBI:
+		return "RTBI";
+	default:
+		BUG();
+	}
+}
+
+static inline u32 rgmii_mode_mask(int mode, int input)
+{
+	switch (mode) {
+	case PHY_MODE_RGMII:
+		return RGMII_FER_RGMII(input);
+	case PHY_MODE_TBI:
+		return RGMII_FER_TBI(input);
+	case PHY_MODE_GMII:
+		return RGMII_FER_GMII(input);
+	case PHY_MODE_RTBI:
+		return RGMII_FER_RTBI(input);
+	default:
+		BUG();
+	}
+}
+
+static int __init rgmii_init(struct ocp_device *ocpdev, int input, int mode)
+{
+	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+	struct rgmii_regs *p;
+
+	RGMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, mode);
+
+	if (!dev) {
+		dev = kzalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL);
+		if (!dev) {
+			printk(KERN_ERR
+			       "rgmii%d: couldn't allocate device structure!\n",
+			       ocpdev->def->index);
+			return -ENOMEM;
+		}
+
+		p = (struct rgmii_regs *)ioremap(ocpdev->def->paddr,
+						 sizeof(struct rgmii_regs));
+		if (!p) {
+			printk(KERN_ERR
+			       "rgmii%d: could not ioremap device registers!\n",
+			       ocpdev->def->index);
+			kfree(dev);
+			return -ENOMEM;
+		}
+
+		dev->base = p;
+		ocp_set_drvdata(ocpdev, dev);
+
+		/* Disable all inputs by default */
+		out_be32(&p->fer, 0);
+	} else
+		p = dev->base;
+
+	/* Enable this input */
+	out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input));
+
+	printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n",
+	       ocpdev->def->index, input, rgmii_mode_name(mode));
+
+	++dev->users;
+	return 0;
+}
+
+int __init rgmii_attach(void *emac)
+{
+	struct ocp_enet_private *dev = emac;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+	/* Check if we need to attach to a RGMII */
+	if (emacdata->rgmii_idx >= 0 && rgmii_valid_mode(emacdata->phy_mode)) {
+		dev->rgmii_input = emacdata->rgmii_mux;
+		dev->rgmii_dev =
+		    ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_RGMII,
+				    emacdata->rgmii_idx);
+		if (!dev->rgmii_dev) {
+			printk(KERN_ERR "emac%d: unknown rgmii%d!\n",
+			       dev->def->index, emacdata->rgmii_idx);
+			return -ENODEV;
+		}
+		if (rgmii_init
+		    (dev->rgmii_dev, dev->rgmii_input, emacdata->phy_mode)) {
+			printk(KERN_ERR
+			       "emac%d: rgmii%d initialization failed!\n",
+			       dev->def->index, emacdata->rgmii_idx);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
+{
+	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+	u32 ssr = in_be32(&dev->base->ssr) & ~RGMII_SSR_MASK(input);
+
+	RGMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
+
+	if (speed == SPEED_1000)
+		ssr |= RGMII_SSR_1000(input);
+	else if (speed == SPEED_100)
+		ssr |= RGMII_SSR_100(input);
+
+	out_be32(&dev->base->ssr, ssr);
+}
+
+void __exit __rgmii_fini(struct ocp_device *ocpdev, int input)
+{
+	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+	BUG_ON(!dev || dev->users == 0);
+
+	RGMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
+
+	/* Disable this input */
+	out_be32(&dev->base->fer,
+		 in_be32(&dev->base->fer) & ~RGMII_FER_MASK(input));
+
+	if (!--dev->users) {
+		/* Free everything if this is the last user */
+		ocp_set_drvdata(ocpdev, NULL);
+		iounmap((void *)dev->base);
+		kfree(dev);
+	}
+}
+
+int __rgmii_get_regs_len(struct ocp_device *ocpdev)
+{
+	return sizeof(struct emac_ethtool_regs_subhdr) +
+	    sizeof(struct rgmii_regs);
+}
+
+void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+	struct ibm_ocp_rgmii *dev = ocp_get_drvdata(ocpdev);
+	struct emac_ethtool_regs_subhdr *hdr = buf;
+	struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);
+
+	hdr->version = 0;
+	hdr->index = ocpdev->def->index;
+	memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs));
+	return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_rgmii.h b/drivers/net/ibm_emac/ibm_emac_rgmii.h
index 49f188f..a1ffb8a 100644
--- a/drivers/net/ibm_emac/ibm_emac_rgmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_rgmii.h
@@ -1,5 +1,7 @@
 /*
- * Defines for the IBM RGMII bridge
+ * drivers/net/ibm_emac/ibm_emac_rgmii.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
  *
  * Based on ocp_zmii.h/ibm_emac_zmii.h
  * Armin Kuster akuster@mvista.com
@@ -7,6 +9,9 @@
  * Copyright 2004 MontaVista Software, Inc.
  * Matt Porter <mporter@kernel.crashing.org>
  *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
  * 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
@@ -19,47 +24,42 @@
 #include <linux/config.h>
 
 /* RGMII bridge */
-typedef struct rgmii_regs {
+struct rgmii_regs {
 	u32 fer;		/* Function enable register */
 	u32 ssr;		/* Speed select register */
-} rgmii_t;
-
-#define RGMII_INPUTS			4
+};
 
 /* RGMII device */
 struct ibm_ocp_rgmii {
 	struct rgmii_regs *base;
-	int mode[RGMII_INPUTS];
 	int users;		/* number of EMACs using this RGMII bridge */
 };
 
-/* Fuctional Enable Reg */
-#define RGMII_FER_MASK(x)		(0x00000007 << (4*x))
-#define RGMII_RTBI			0x00000004
-#define RGMII_RGMII			0x00000005
-#define RGMII_TBI  			0x00000006
-#define RGMII_GMII 			0x00000007
+#ifdef CONFIG_IBM_EMAC_RGMII
+int rgmii_attach(void *emac) __init;
 
-/* Speed Selection reg */
+void __rgmii_fini(struct ocp_device *ocpdev, int input) __exit;
+static inline void rgmii_fini(struct ocp_device *ocpdev, int input)
+{
+	if (ocpdev)
+		__rgmii_fini(ocpdev, input);
+}
 
-#define RGMII_SP2_100	0x00000002
-#define RGMII_SP2_1000	0x00000004
-#define RGMII_SP3_100	0x00000200
-#define RGMII_SP3_1000	0x00000400
+void rgmii_set_speed(struct ocp_device *ocpdev, int input, int speed);
 
-#define RGMII_MII2_SPDMASK	 0x00000007
-#define RGMII_MII3_SPDMASK	 0x00000700
+int __rgmii_get_regs_len(struct ocp_device *ocpdev);
+static inline int rgmii_get_regs_len(struct ocp_device *ocpdev)
+{
+	return ocpdev ? __rgmii_get_regs_len(ocpdev) : 0;
+}
 
-#define RGMII_MII2_100MB	 RGMII_SP2_100 & ~RGMII_SP2_1000
-#define RGMII_MII2_1000MB 	 RGMII_SP2_1000 & ~RGMII_SP2_100
-#define RGMII_MII2_10MB		 ~(RGMII_SP2_100 | RGMII_SP2_1000)
-#define RGMII_MII3_100MB	 RGMII_SP3_100 & ~RGMII_SP3_1000
-#define RGMII_MII3_1000MB 	 RGMII_SP3_1000 & ~RGMII_SP3_100
-#define RGMII_MII3_10MB		 ~(RGMII_SP3_100 | RGMII_SP3_1000)
-
-#define RTBI		0
-#define RGMII		1
-#define TBI		2
-#define GMII		3
+void *rgmii_dump_regs(struct ocp_device *ocpdev, void *buf);
+#else
+# define rgmii_attach(x)	0
+# define rgmii_fini(x,y)	((void)0)
+# define rgmii_set_speed(x,y,z)	((void)0)
+# define rgmii_get_regs_len(x)	0
+# define rgmii_dump_regs(x,buf)	(buf)
+#endif				/* !CONFIG_IBM_EMAC_RGMII */
 
 #endif				/* _IBM_EMAC_RGMII_H_ */
diff --git a/drivers/net/ibm_emac/ibm_emac_tah.c b/drivers/net/ibm_emac/ibm_emac_tah.c
new file mode 100644
index 0000000..af08afc
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_tah.c
@@ -0,0 +1,111 @@
+/*
+ * drivers/net/ibm_emac/ibm_emac_tah.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
+ *
+ * Copyright 2004 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.net>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <asm/io.h>
+
+#include "ibm_emac_core.h"
+
+static int __init tah_init(struct ocp_device *ocpdev)
+{
+	struct tah_regs *p;
+
+	if (ocp_get_drvdata(ocpdev)) {
+		printk(KERN_ERR "tah%d: already in use!\n", ocpdev->def->index);
+		return -EBUSY;
+	}
+
+	/* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
+	p = (struct tah_regs *)ioremap(ocpdev->def->paddr, sizeof(*p));
+	if (!p) {
+		printk(KERN_ERR "tah%d: could not ioremap device registers!\n",
+		       ocpdev->def->index);
+		return -ENOMEM;
+	}
+	ocp_set_drvdata(ocpdev, p);
+	__tah_reset(ocpdev);
+
+	return 0;
+}
+
+int __init tah_attach(void *emac)
+{
+	struct ocp_enet_private *dev = emac;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+	/* Check if we need to attach to a TAH */
+	if (emacdata->tah_idx >= 0) {
+		dev->tah_dev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH,
+					       emacdata->tah_idx);
+		if (!dev->tah_dev) {
+			printk(KERN_ERR "emac%d: unknown tah%d!\n",
+			       dev->def->index, emacdata->tah_idx);
+			return -ENODEV;
+		}
+		if (tah_init(dev->tah_dev)) {
+			printk(KERN_ERR
+			       "emac%d: tah%d initialization failed!\n",
+			       dev->def->index, emacdata->tah_idx);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+void __exit __tah_fini(struct ocp_device *ocpdev)
+{
+	struct tah_regs *p = ocp_get_drvdata(ocpdev);
+	BUG_ON(!p);
+	ocp_set_drvdata(ocpdev, NULL);
+	iounmap((void *)p);
+}
+
+void __tah_reset(struct ocp_device *ocpdev)
+{
+	struct tah_regs *p = ocp_get_drvdata(ocpdev);
+	int n;
+
+	/* Reset TAH */
+	out_be32(&p->mr, TAH_MR_SR);
+	n = 100;
+	while ((in_be32(&p->mr) & TAH_MR_SR) && n)
+		--n;
+
+	if (unlikely(!n))
+		printk(KERN_ERR "tah%d: reset timeout\n", ocpdev->def->index);
+
+	/* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
+	out_be32(&p->mr,
+		 TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
+		 TAH_MR_DIG);
+}
+
+int __tah_get_regs_len(struct ocp_device *ocpdev)
+{
+	return sizeof(struct emac_ethtool_regs_subhdr) +
+	    sizeof(struct tah_regs);
+}
+
+void *tah_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+	struct tah_regs *dev = ocp_get_drvdata(ocpdev);
+	struct emac_ethtool_regs_subhdr *hdr = buf;
+	struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
+
+	hdr->version = 0;
+	hdr->index = ocpdev->def->index;
+	memcpy_fromio(regs, dev, sizeof(struct tah_regs));
+	return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_tah.h b/drivers/net/ibm_emac/ibm_emac_tah.h
index ecfc698..9299b5d 100644
--- a/drivers/net/ibm_emac/ibm_emac_tah.h
+++ b/drivers/net/ibm_emac/ibm_emac_tah.h
@@ -1,9 +1,13 @@
 /*
- * Defines for the IBM TAH
+ * drivers/net/ibm_emac/ibm_emac_tah.h
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
  *
  * Copyright 2004 MontaVista Software, Inc.
  * Matt Porter <mporter@kernel.crashing.org>
  *
+ * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.net>
+ *
  * 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
@@ -13,36 +17,72 @@
 #ifndef _IBM_EMAC_TAH_H
 #define _IBM_EMAC_TAH_H
 
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
+
 /* TAH */
-typedef struct tah_regs {
-	u32 tah_revid;
+struct tah_regs {
+	u32 revid;
 	u32 pad[3];
-	u32 tah_mr;
-	u32 tah_ssr0;
-	u32 tah_ssr1;
-	u32 tah_ssr2;
-	u32 tah_ssr3;
-	u32 tah_ssr4;
-	u32 tah_ssr5;
-	u32 tah_tsr;
-} tah_t;
+	u32 mr;
+	u32 ssr0;
+	u32 ssr1;
+	u32 ssr2;
+	u32 ssr3;
+	u32 ssr4;
+	u32 ssr5;
+	u32 tsr;
+};
 
 /* TAH engine */
-#define TAH_MR_CVR			0x80000000
-#define TAH_MR_SR			0x40000000
-#define TAH_MR_ST_256			0x01000000
-#define TAH_MR_ST_512			0x02000000
-#define TAH_MR_ST_768			0x03000000
-#define TAH_MR_ST_1024			0x04000000
-#define TAH_MR_ST_1280			0x05000000
-#define TAH_MR_ST_1536			0x06000000
-#define TAH_MR_TFS_16KB			0x00000000
-#define TAH_MR_TFS_2KB			0x00200000
-#define TAH_MR_TFS_4KB			0x00400000
-#define TAH_MR_TFS_6KB			0x00600000
-#define TAH_MR_TFS_8KB			0x00800000
-#define TAH_MR_TFS_10KB			0x00a00000
-#define TAH_MR_DTFP			0x00100000
-#define TAH_MR_DIG			0x00080000
+#define TAH_MR_CVR		0x80000000
+#define TAH_MR_SR		0x40000000
+#define TAH_MR_ST_256		0x01000000
+#define TAH_MR_ST_512		0x02000000
+#define TAH_MR_ST_768		0x03000000
+#define TAH_MR_ST_1024		0x04000000
+#define TAH_MR_ST_1280		0x05000000
+#define TAH_MR_ST_1536		0x06000000
+#define TAH_MR_TFS_16KB		0x00000000
+#define TAH_MR_TFS_2KB		0x00200000
+#define TAH_MR_TFS_4KB		0x00400000
+#define TAH_MR_TFS_6KB		0x00600000
+#define TAH_MR_TFS_8KB		0x00800000
+#define TAH_MR_TFS_10KB		0x00a00000
+#define TAH_MR_DTFP		0x00100000
+#define TAH_MR_DIG		0x00080000
+
+#ifdef CONFIG_IBM_EMAC_TAH
+int tah_attach(void *emac) __init;
+
+void __tah_fini(struct ocp_device *ocpdev) __exit;
+static inline void tah_fini(struct ocp_device *ocpdev)
+{
+	if (ocpdev)
+		__tah_fini(ocpdev);
+}
+
+void __tah_reset(struct ocp_device *ocpdev);
+static inline void tah_reset(struct ocp_device *ocpdev)
+{
+	if (ocpdev)
+		__tah_reset(ocpdev);
+}
+
+int __tah_get_regs_len(struct ocp_device *ocpdev);
+static inline int tah_get_regs_len(struct ocp_device *ocpdev)
+{
+	return ocpdev ? __tah_get_regs_len(ocpdev) : 0;
+}
+
+void *tah_dump_regs(struct ocp_device *ocpdev, void *buf);
+#else
+# define tah_attach(x)		0
+# define tah_fini(x)		((void)0)
+# define tah_reset(x)		((void)0)
+# define tah_get_regs_len(x)	0
+# define tah_dump_regs(x,buf)	(buf)
+#endif				/* !CONFIG_IBM_EMAC_TAH */
 
 #endif				/* _IBM_EMAC_TAH_H */
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.c b/drivers/net/ibm_emac/ibm_emac_zmii.c
new file mode 100644
index 0000000..35c1185
--- /dev/null
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.c
@@ -0,0 +1,255 @@
+/*
+ * drivers/net/ibm_emac/ibm_emac_zmii.c
+ *
+ * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
+ *
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ *
+ * Based on original work by
+ *      Armin Kuster <akuster@mvista.com>
+ * 	Copyright 2001 MontaVista Softare 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/config.h>
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <asm/io.h>
+
+#include "ibm_emac_core.h"
+#include "ibm_emac_debug.h"
+
+/* ZMIIx_FER */
+#define ZMII_FER_MDI(idx)	(0x80000000 >> ((idx) * 4))
+#define ZMII_FER_MDI_ALL	(ZMII_FER_MDI(0) | ZMII_FER_MDI(1) | \
+				 ZMII_FER_MDI(2) | ZMII_FER_MDI(3))
+
+#define ZMII_FER_SMII(idx)	(0x40000000 >> ((idx) * 4))
+#define ZMII_FER_RMII(idx)	(0x20000000 >> ((idx) * 4))
+#define ZMII_FER_MII(idx)	(0x10000000 >> ((idx) * 4))
+
+/* ZMIIx_SSR */
+#define ZMII_SSR_SCI(idx)	(0x40000000 >> ((idx) * 4))
+#define ZMII_SSR_FSS(idx)	(0x20000000 >> ((idx) * 4))
+#define ZMII_SSR_SP(idx)	(0x10000000 >> ((idx) * 4))
+
+/* ZMII only supports MII, RMII and SMII 
+ * we also support autodetection for backward compatibility
+ */
+static inline int zmii_valid_mode(int mode)
+{
+	return  mode == PHY_MODE_MII ||
+		mode == PHY_MODE_RMII ||
+		mode == PHY_MODE_SMII ||
+		mode == PHY_MODE_NA;
+}
+
+static inline const char *zmii_mode_name(int mode)
+{
+	switch (mode) {
+	case PHY_MODE_MII:
+		return "MII";
+	case PHY_MODE_RMII:
+		return "RMII";
+	case PHY_MODE_SMII:
+		return "SMII";
+	default:
+		BUG();
+	}
+}
+
+static inline u32 zmii_mode_mask(int mode, int input)
+{
+	switch (mode) {
+	case PHY_MODE_MII:
+		return ZMII_FER_MII(input);
+	case PHY_MODE_RMII:
+		return ZMII_FER_RMII(input);
+	case PHY_MODE_SMII:
+		return ZMII_FER_SMII(input);
+	default:
+		return 0;
+	}
+}
+
+static int __init zmii_init(struct ocp_device *ocpdev, int input, int *mode)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	struct zmii_regs *p;
+
+	ZMII_DBG("%d: init(%d, %d)" NL, ocpdev->def->index, input, *mode);
+
+	if (!dev) {
+		dev = kzalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL);
+		if (!dev) {
+			printk(KERN_ERR
+			       "zmii%d: couldn't allocate device structure!\n",
+			       ocpdev->def->index);
+			return -ENOMEM;
+		}
+		dev->mode = PHY_MODE_NA;
+
+		p = (struct zmii_regs *)ioremap(ocpdev->def->paddr,
+						sizeof(struct zmii_regs));
+		if (!p) {
+			printk(KERN_ERR
+			       "zmii%d: could not ioremap device registers!\n",
+			       ocpdev->def->index);
+			kfree(dev);
+			return -ENOMEM;
+		}
+		dev->base = p;
+		ocp_set_drvdata(ocpdev, dev);
+		
+		/* We may need FER value for autodetection later */
+		dev->fer_save = in_be32(&p->fer);
+
+		/* Disable all inputs by default */
+		out_be32(&p->fer, 0);
+	} else
+		p = dev->base;
+
+	if (!zmii_valid_mode(*mode)) {
+		/* Probably an EMAC connected to RGMII, 
+		 * but it still may need ZMII for MDIO 
+		 */
+		goto out;
+	}
+
+	/* Autodetect ZMII mode if not specified.
+	 * This is only for backward compatibility with the old driver.
+	 * Please, always specify PHY mode in your board port to avoid
+	 * any surprises.
+	 */
+	if (dev->mode == PHY_MODE_NA) {
+		if (*mode == PHY_MODE_NA) {
+			u32 r = dev->fer_save;
+
+			ZMII_DBG("%d: autodetecting mode, FER = 0x%08x" NL,
+				 ocpdev->def->index, r);
+			
+			if (r & (ZMII_FER_MII(0) | ZMII_FER_MII(1)))
+				dev->mode = PHY_MODE_MII;
+			else if (r & (ZMII_FER_RMII(0) | ZMII_FER_RMII(1)))
+				dev->mode = PHY_MODE_RMII;
+			else
+				dev->mode = PHY_MODE_SMII;
+		} else
+			dev->mode = *mode;
+
+		printk(KERN_NOTICE "zmii%d: bridge in %s mode\n",
+		       ocpdev->def->index, zmii_mode_name(dev->mode));
+	} else {
+		/* All inputs must use the same mode */
+		if (*mode != PHY_MODE_NA && *mode != dev->mode) {
+			printk(KERN_ERR
+			       "zmii%d: invalid mode %d specified for input %d\n",
+			       ocpdev->def->index, *mode, input);
+			return -EINVAL;
+		}
+	}
+
+	/* Report back correct PHY mode, 
+	 * it may be used during PHY initialization.
+	 */
+	*mode = dev->mode;
+
+	/* Enable this input */
+	out_be32(&p->fer, in_be32(&p->fer) | zmii_mode_mask(dev->mode, input));
+      out:
+	++dev->users;
+	return 0;
+}
+
+int __init zmii_attach(void *emac)
+{
+	struct ocp_enet_private *dev = emac;
+	struct ocp_func_emac_data *emacdata = dev->def->additions;
+
+	if (emacdata->zmii_idx >= 0) {
+		dev->zmii_input = emacdata->zmii_mux;
+		dev->zmii_dev =
+		    ocp_find_device(OCP_VENDOR_IBM, OCP_FUNC_ZMII,
+				    emacdata->zmii_idx);
+		if (!dev->zmii_dev) {
+			printk(KERN_ERR "emac%d: unknown zmii%d!\n",
+			       dev->def->index, emacdata->zmii_idx);
+			return -ENODEV;
+		}
+		if (zmii_init
+		    (dev->zmii_dev, dev->zmii_input, &emacdata->phy_mode)) {
+			printk(KERN_ERR
+			       "emac%d: zmii%d initialization failed!\n",
+			       dev->def->index, emacdata->zmii_idx);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+void __zmii_enable_mdio(struct ocp_device *ocpdev, int input)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	u32 fer = in_be32(&dev->base->fer) & ~ZMII_FER_MDI_ALL;
+
+	ZMII_DBG2("%d: mdio(%d)" NL, ocpdev->def->index, input);
+
+	out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input));
+}
+
+void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	u32 ssr = in_be32(&dev->base->ssr);
+
+	ZMII_DBG("%d: speed(%d, %d)" NL, ocpdev->def->index, input, speed);
+
+	if (speed == SPEED_100)
+		ssr |= ZMII_SSR_SP(input);
+	else
+		ssr &= ~ZMII_SSR_SP(input);
+
+	out_be32(&dev->base->ssr, ssr);
+}
+
+void __exit __zmii_fini(struct ocp_device *ocpdev, int input)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	BUG_ON(!dev || dev->users == 0);
+
+	ZMII_DBG("%d: fini(%d)" NL, ocpdev->def->index, input);
+
+	/* Disable this input */
+	out_be32(&dev->base->fer,
+		 in_be32(&dev->base->fer) & ~zmii_mode_mask(dev->mode, input));
+
+	if (!--dev->users) {
+		/* Free everything if this is the last user */
+		ocp_set_drvdata(ocpdev, NULL);
+		iounmap((void *)dev->base);
+		kfree(dev);
+	}
+}
+
+int __zmii_get_regs_len(struct ocp_device *ocpdev)
+{
+	return sizeof(struct emac_ethtool_regs_subhdr) +
+	    sizeof(struct zmii_regs);
+}
+
+void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf)
+{
+	struct ibm_ocp_zmii *dev = ocp_get_drvdata(ocpdev);
+	struct emac_ethtool_regs_subhdr *hdr = buf;
+	struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1);
+
+	hdr->version = 0;
+	hdr->index = ocpdev->def->index;
+	memcpy_fromio(regs, dev->base, sizeof(struct zmii_regs));
+	return regs + 1;
+}
diff --git a/drivers/net/ibm_emac/ibm_emac_zmii.h b/drivers/net/ibm_emac/ibm_emac_zmii.h
index 6f6cd2a..0bb2606 100644
--- a/drivers/net/ibm_emac/ibm_emac_zmii.h
+++ b/drivers/net/ibm_emac/ibm_emac_zmii.h
@@ -1,23 +1,27 @@
 /*
- * ocp_zmii.h
+ * drivers/net/ibm_emac/ibm_emac_zmii.h
  *
- * Defines for the IBM ZMII bridge
+ * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
  *
- *      Armin Kuster akuster@mvista.com
- *      Dec, 2001
+ * Copyright (c) 2004, 2005 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  *
- * Copyright 2001 MontaVista Softare Inc.
+ * Based on original work by
+ *      Armin Kuster <akuster@mvista.com>
+ * 	Copyright 2001 MontaVista Softare 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.
+ *
  */
-
 #ifndef _IBM_EMAC_ZMII_H_
 #define _IBM_EMAC_ZMII_H_
 
 #include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ocp.h>
 
 /* ZMII bridge registers */
 struct zmii_regs {
@@ -26,68 +30,54 @@
 	u32 smiirs;		/* SMII status reg */
 };
 
-#define ZMII_INPUTS	4
-
 /* ZMII device */
 struct ibm_ocp_zmii {
 	struct zmii_regs *base;
-	int mode[ZMII_INPUTS];
+	int mode;		/* subset of PHY_MODE_XXXX */
 	int users;		/* number of EMACs using this ZMII bridge */
+	u32 fer_save;		/* FER value left by firmware */
 };
 
-/* Fuctional Enable Reg */
+#ifdef CONFIG_IBM_EMAC_ZMII
+int zmii_attach(void *emac) __init;
 
-#define ZMII_FER_MASK(x)	(0xf0000000 >> (4*x))
+void __zmii_fini(struct ocp_device *ocpdev, int input) __exit;
+static inline void zmii_fini(struct ocp_device *ocpdev, int input)
+{
+	if (ocpdev)
+		__zmii_fini(ocpdev, input);
+}
 
-#define ZMII_MDI0	0x80000000
-#define ZMII_SMII0	0x40000000
-#define ZMII_RMII0	0x20000000
-#define ZMII_MII0	0x10000000
-#define ZMII_MDI1	0x08000000
-#define ZMII_SMII1	0x04000000
-#define ZMII_RMII1	0x02000000
-#define ZMII_MII1	0x01000000
-#define ZMII_MDI2	0x00800000
-#define ZMII_SMII2	0x00400000
-#define ZMII_RMII2	0x00200000
-#define ZMII_MII2	0x00100000
-#define ZMII_MDI3	0x00080000
-#define ZMII_SMII3	0x00040000
-#define ZMII_RMII3	0x00020000
-#define ZMII_MII3	0x00010000
+void __zmii_enable_mdio(struct ocp_device *ocpdev, int input);
+static inline void zmii_enable_mdio(struct ocp_device *ocpdev, int input)
+{
+	if (ocpdev)
+		__zmii_enable_mdio(ocpdev, input);
+}
 
-/* Speed Selection reg */
+void __zmii_set_speed(struct ocp_device *ocpdev, int input, int speed);
+static inline void zmii_set_speed(struct ocp_device *ocpdev, int input,
+				  int speed)
+{
+	if (ocpdev)
+		__zmii_set_speed(ocpdev, input, speed);
+}
 
-#define ZMII_SCI0	0x40000000
-#define ZMII_FSS0	0x20000000
-#define ZMII_SP0	0x10000000
-#define ZMII_SCI1	0x04000000
-#define ZMII_FSS1	0x02000000
-#define ZMII_SP1	0x01000000
-#define ZMII_SCI2	0x00400000
-#define ZMII_FSS2	0x00200000
-#define ZMII_SP2	0x00100000
-#define ZMII_SCI3	0x00040000
-#define ZMII_FSS3	0x00020000
-#define ZMII_SP3	0x00010000
+int __zmii_get_regs_len(struct ocp_device *ocpdev);
+static inline int zmii_get_regs_len(struct ocp_device *ocpdev)
+{
+	return ocpdev ? __zmii_get_regs_len(ocpdev) : 0;
+}
 
-#define ZMII_MII0_100MB	ZMII_SP0
-#define ZMII_MII0_10MB	~ZMII_SP0
-#define ZMII_MII1_100MB	ZMII_SP1
-#define ZMII_MII1_10MB	~ZMII_SP1
-#define ZMII_MII2_100MB	ZMII_SP2
-#define ZMII_MII2_10MB	~ZMII_SP2
-#define ZMII_MII3_100MB	ZMII_SP3
-#define ZMII_MII3_10MB	~ZMII_SP3
+void *zmii_dump_regs(struct ocp_device *ocpdev, void *buf);
 
-/* SMII Status reg */
-
-#define ZMII_STS0 0xFF000000	/* EMAC0 smii status mask */
-#define ZMII_STS1 0x00FF0000	/* EMAC1 smii status mask */
-
-#define SMII	0
-#define RMII	1
-#define MII	2
-#define MDI	3
+#else
+# define zmii_attach(x)		0
+# define zmii_fini(x,y)		((void)0)
+# define zmii_enable_mdio(x,y)	((void)0)
+# define zmii_set_speed(x,y,z)	((void)0)
+# define zmii_get_regs_len(x)	0
+# define zmii_dump_regs(x,buf)	(buf)
+#endif				/* !CONFIG_IBM_EMAC_ZMII */
 
 #endif				/* _IBM_EMAC_ZMII_H_ */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index cbe9368..e5246f2 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -96,7 +96,7 @@
 static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*);
+static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
 
 #ifdef CONFIG_PROC_FS
 #define IBMVETH_PROC_DIR "net/ibmveth"
@@ -181,6 +181,7 @@
 	atomic_set(&pool->available, 0);
 	pool->producer_index = 0;
 	pool->consumer_index = 0;
+	pool->active = 0;
 
 	return 0;
 }
@@ -236,7 +237,7 @@
 		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 		    
 		if(lpar_rc != H_Success) {
-			pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
+			pool->free_map[free_index] = index;
 			pool->skbuff[index] = NULL;
 			pool->consumer_index--;
 			dma_unmap_single(&adapter->vdev->dev,
@@ -255,37 +256,19 @@
 	atomic_add(buffers_added, &(pool->available));
 }
 
-/* check if replenishing is needed.  */
-static inline int ibmveth_is_replenishing_needed(struct ibmveth_adapter *adapter)
-{
-	return ((atomic_read(&adapter->rx_buff_pool[0].available) < adapter->rx_buff_pool[0].threshold) ||
-		(atomic_read(&adapter->rx_buff_pool[1].available) < adapter->rx_buff_pool[1].threshold) ||
-		(atomic_read(&adapter->rx_buff_pool[2].available) < adapter->rx_buff_pool[2].threshold));
-}
-
-/* kick the replenish tasklet if we need replenishing and it isn't already running */
-static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter *adapter)
-{
-	if(ibmveth_is_replenishing_needed(adapter) &&
-	   (atomic_dec_if_positive(&adapter->not_replenishing) == 0)) {
-		schedule_work(&adapter->replenish_task);
-	}
-}
-
-/* replenish tasklet routine */
+/* replenish routine */
 static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) 
 {
+	int i;
+
 	adapter->replenish_task_cycles++;
 
-	ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[0]);
-	ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]);
-	ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]);
+	for(i = 0; i < IbmVethNumBufferPools; i++)
+		if(adapter->rx_buff_pool[i].active)
+			ibmveth_replenish_buffer_pool(adapter, 
+						     &adapter->rx_buff_pool[i]);
 
 	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
-
-	atomic_inc(&adapter->not_replenishing);
-
-	ibmveth_schedule_replenishing(adapter);
 }
 
 /* empty and free ana buffer pool - also used to do cleanup in error paths */
@@ -293,10 +276,8 @@
 {
 	int i;
 
-	if(pool->free_map) {
-		kfree(pool->free_map);
-		pool->free_map  = NULL;
-	}
+	kfree(pool->free_map);
+	pool->free_map = NULL;
 
 	if(pool->skbuff && pool->dma_addr) {
 		for(i = 0; i < pool->size; ++i) {
@@ -321,6 +302,7 @@
 		kfree(pool->skbuff);
 		pool->skbuff = NULL;
 	}
+	pool->active = 0;
 }
 
 /* remove a buffer from a pool */
@@ -379,6 +361,12 @@
 	ibmveth_assert(pool < IbmVethNumBufferPools);
 	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
 
+	if(!adapter->rx_buff_pool[pool].active) {
+		ibmveth_rxq_harvest_buffer(adapter);
+		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
+		return;
+	}
+
 	desc.desc = 0;
 	desc.fields.valid = 1;
 	desc.fields.length = adapter->rx_buff_pool[pool].buff_size;
@@ -409,6 +397,8 @@
 
 static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
 {
+	int i;
+
 	if(adapter->buffer_list_addr != NULL) {
 		if(!dma_mapping_error(adapter->buffer_list_dma)) {
 			dma_unmap_single(&adapter->vdev->dev,
@@ -443,26 +433,24 @@
 		adapter->rx_queue.queue_addr = NULL;
 	}
 
-	ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[0]);
-	ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[1]);
-	ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[2]);
+	for(i = 0; i<IbmVethNumBufferPools; i++)
+		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
 }
 
 static int ibmveth_open(struct net_device *netdev)
 {
 	struct ibmveth_adapter *adapter = netdev->priv;
 	u64 mac_address = 0;
-	int rxq_entries;
+	int rxq_entries = 1;
 	unsigned long lpar_rc;
 	int rc;
 	union ibmveth_buf_desc rxq_desc;
+	int i;
 
 	ibmveth_debug_printk("open starting\n");
 
-	rxq_entries =
-		adapter->rx_buff_pool[0].size +
-		adapter->rx_buff_pool[1].size +
-		adapter->rx_buff_pool[2].size + 1;
+	for(i = 0; i<IbmVethNumBufferPools; i++)
+		rxq_entries += adapter->rx_buff_pool[i].size;
     
 	adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
 	adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
@@ -502,14 +490,8 @@
 	adapter->rx_queue.num_slots = rxq_entries;
 	adapter->rx_queue.toggle = 1;
 
-	if(ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) ||
-	   ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) ||
-	   ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2]))
-	{
-		ibmveth_error_printk("unable to allocate buffer pools\n");
-		ibmveth_cleanup(adapter);
-		return -ENOMEM;
-	}
+	/* call change_mtu to init the buffer pools based in initial mtu */
+	ibmveth_change_mtu(netdev, netdev->mtu);
 
 	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
 	mac_address = mac_address >> 16;
@@ -552,10 +534,10 @@
 		return rc;
 	}
 
-	netif_start_queue(netdev);
+	ibmveth_debug_printk("initial replenish cycle\n");
+	ibmveth_replenish_task(adapter);
 
-	ibmveth_debug_printk("scheduling initial replenish cycle\n");
-	ibmveth_schedule_replenishing(adapter);
+	netif_start_queue(netdev);
 
 	ibmveth_debug_printk("open complete\n");
 
@@ -573,9 +555,6 @@
 
 	free_irq(netdev->irq, netdev);
 
-	cancel_delayed_work(&adapter->replenish_task);
-	flush_scheduled_work();
-
 	do {
 		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
 	} while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
@@ -640,12 +619,18 @@
 	unsigned long lpar_rc;
 	int nfrags = 0, curfrag;
 	unsigned long correlator;
+	unsigned long flags;
 	unsigned int retry_count;
+	unsigned int tx_dropped = 0;
+	unsigned int tx_bytes = 0;
+	unsigned int tx_packets = 0;
+	unsigned int tx_send_failed = 0;
+	unsigned int tx_map_failed = 0;
+
 
 	if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) {
-		adapter->stats.tx_dropped++;
-		dev_kfree_skb(skb);
-		return 0;
+		tx_dropped++;
+		goto out;
 	}
 
 	memset(&desc, 0, sizeof(desc));
@@ -664,10 +649,9 @@
 
 	if(dma_mapping_error(desc[0].fields.address)) {
 		ibmveth_error_printk("tx: unable to map initial fragment\n");
-		adapter->tx_map_failed++;
-		adapter->stats.tx_dropped++;
-		dev_kfree_skb(skb);
-		return 0;
+		tx_map_failed++;
+		tx_dropped++;
+		goto out;
 	}
 
 	curfrag = nfrags;
@@ -684,8 +668,8 @@
 
 		if(dma_mapping_error(desc[curfrag+1].fields.address)) {
 			ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag);
-			adapter->tx_map_failed++;
-			adapter->stats.tx_dropped++;
+			tx_map_failed++;
+			tx_dropped++;
 			/* Free all the mappings we just created */
 			while(curfrag < nfrags) {
 				dma_unmap_single(&adapter->vdev->dev,
@@ -694,8 +678,7 @@
 						 DMA_TO_DEVICE);
 				curfrag++;
 			}
-			dev_kfree_skb(skb);
-			return 0;
+			goto out;
 		}
 	}
 
@@ -720,11 +703,12 @@
 			ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i,
 					     desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address);
 		}
-		adapter->tx_send_failed++;
-		adapter->stats.tx_dropped++;
+		tx_send_failed++;
+		tx_dropped++;
 	} else {
-		adapter->stats.tx_packets++;
-		adapter->stats.tx_bytes += skb->len;
+		tx_packets++;
+		tx_bytes += skb->len;
+		netdev->trans_start = jiffies;
 	}
 
 	do {
@@ -733,6 +717,14 @@
 				desc[nfrags].fields.length, DMA_TO_DEVICE);
 	} while(--nfrags >= 0);
 
+out:	spin_lock_irqsave(&adapter->stats_lock, flags);
+	adapter->stats.tx_dropped += tx_dropped;
+	adapter->stats.tx_bytes += tx_bytes;
+	adapter->stats.tx_packets += tx_packets;
+	adapter->tx_send_failed += tx_send_failed;
+	adapter->tx_map_failed += tx_map_failed;
+	spin_unlock_irqrestore(&adapter->stats_lock, flags);
+
 	dev_kfree_skb(skb);
 	return 0;
 }
@@ -776,13 +768,14 @@
 				adapter->stats.rx_packets++;
 				adapter->stats.rx_bytes += length;
 				frames_processed++;
+				netdev->last_rx = jiffies;
 			}
 		} else {
 			more_work = 0;
 		}
 	} while(more_work && (frames_processed < max_frames_to_process));
 
-	ibmveth_schedule_replenishing(adapter);
+	ibmveth_replenish_task(adapter);
 
 	if(more_work) {
 		/* more work to do - return that we are not done yet */
@@ -883,17 +876,54 @@
 
 static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 {
-	if ((new_mtu < 68) || (new_mtu > (1<<20)))
+	struct ibmveth_adapter *adapter = dev->priv;
+	int i;
+	int prev_smaller = 1;
+
+	if ((new_mtu < 68) || 
+	    (new_mtu > (pool_size[IbmVethNumBufferPools-1]) - IBMVETH_BUFF_OH))
 		return -EINVAL;
+
+	for(i = 0; i<IbmVethNumBufferPools; i++) {
+		int activate = 0;
+		if (new_mtu > (pool_size[i]  - IBMVETH_BUFF_OH)) { 
+			activate = 1;
+			prev_smaller= 1;
+		} else {
+			if (prev_smaller)
+				activate = 1;
+			prev_smaller= 0;
+		}
+
+		if (activate && !adapter->rx_buff_pool[i].active) {
+			struct ibmveth_buff_pool *pool = 
+						&adapter->rx_buff_pool[i];
+			if(ibmveth_alloc_buffer_pool(pool)) {
+				ibmveth_error_printk("unable to alloc pool\n");
+				return -ENOMEM;
+			}
+			adapter->rx_buff_pool[i].active = 1;
+		} else if (!activate && adapter->rx_buff_pool[i].active) {
+			adapter->rx_buff_pool[i].active = 0;
+			h_free_logical_lan_buffer(adapter->vdev->unit_address,
+					  (u64)pool_size[i]);
+		}
+
+	}
+
+	/* kick the interrupt handler so that the new buffer pools get
+	   replenished or deallocated */
+	ibmveth_interrupt(dev->irq, dev, NULL);
+
 	dev->mtu = new_mtu;
 	return 0;	
 }
 
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
-	int rc;
+	int rc, i;
 	struct net_device *netdev;
-	struct ibmveth_adapter *adapter;
+	struct ibmveth_adapter *adapter = NULL;
 
 	unsigned char *mac_addr_p;
 	unsigned int *mcastFilterSize_p;
@@ -960,23 +990,21 @@
 	netdev->ethtool_ops           = &netdev_ethtool_ops;
 	netdev->change_mtu         = ibmveth_change_mtu;
 	SET_NETDEV_DEV(netdev, &dev->dev);
+ 	netdev->features |= NETIF_F_LLTX; 
+	spin_lock_init(&adapter->stats_lock);
 
 	memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
 
-	ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, IbmVethPool0DftCnt, IbmVethPool0DftSize);
-	ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, IbmVethPool1DftCnt, IbmVethPool1DftSize);
-	ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, IbmVethPool2DftCnt, IbmVethPool2DftSize);
+	for(i = 0; i<IbmVethNumBufferPools; i++)
+		ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 
+					 pool_count[i], pool_size[i]);
 
 	ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
 
-	INIT_WORK(&adapter->replenish_task, (void*)ibmveth_replenish_task, (void*)adapter);
-
 	adapter->buffer_list_dma = DMA_ERROR_CODE;
 	adapter->filter_list_dma = DMA_ERROR_CODE;
 	adapter->rx_queue.queue_dma = DMA_ERROR_CODE;
 
-	atomic_set(&adapter->not_replenishing, 1);
-
 	ibmveth_debug_printk("registering netdev...\n");
 
 	rc = register_netdev(netdev);
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index 51a470d..46919a8 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -49,6 +49,7 @@
 #define H_SEND_LOGICAL_LAN       0x120
 #define H_MULTICAST_CTRL         0x130
 #define H_CHANGE_LOGICAL_LAN_MAC 0x14C
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
 
 /* hcall macros */
 #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
@@ -69,13 +70,15 @@
 #define h_change_logical_lan_mac(ua, mac) \
   plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
 
-#define IbmVethNumBufferPools 3
-#define IbmVethPool0DftSize (1024 * 2)
-#define IbmVethPool1DftSize (1024 * 4)
-#define IbmVethPool2DftSize (1024 * 10)
-#define IbmVethPool0DftCnt  256
-#define IbmVethPool1DftCnt  256
-#define IbmVethPool2DftCnt  256
+#define h_free_logical_lan_buffer(ua, bufsize) \
+  plpar_hcall_norets(H_FREE_LOGICAL_LAN_BUFFER, ua, bufsize)
+
+#define IbmVethNumBufferPools 5
+#define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
+
+/* pool_size should be sorted */
+static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
+static int pool_count[] = { 256, 768, 256, 256, 256 };
 
 #define IBM_VETH_INVALID_MAP ((u16)0xffff)
 
@@ -90,6 +93,7 @@
     u16 *free_map;
     dma_addr_t *dma_addr;
     struct sk_buff **skbuff;
+    int active;
 };
 
 struct ibmveth_rx_q {
@@ -114,10 +118,6 @@
     dma_addr_t filter_list_dma;
     struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
     struct ibmveth_rx_q rx_queue;
-    atomic_t not_replenishing;
-
-    /* helper tasks */
-    struct work_struct replenish_task;
 
     /* adapter specific stats */
     u64 replenish_task_cycles;
@@ -131,6 +131,7 @@
     u64 tx_linearize_failed;
     u64 tx_map_failed;
     u64 tx_send_failed;
+    spinlock_t stats_lock;
 };
 
 struct ibmveth_buf_desc_fields {	
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index ca59140..d54156f 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -400,5 +400,15 @@
 	  To compile it as a module, choose M here: the module will be called
 	  via-ircc.
 
+config PXA_FICP
+	tristate "Intel PXA2xx Internal FICP"
+	depends on ARCH_PXA && IRDA
+	help
+	  Say Y or M here if you want to build support for the PXA2xx
+	  built-in IRDA interface which can support both SIR and FIR.
+	  This driver relies on platform specific helper routines so
+	  available capabilities may vary from one PXA2xx target to
+	  another.
+
 endmenu
 
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 29a8bd8..e7a8b7f 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -18,6 +18,7 @@
 obj-$(CONFIG_ALI_FIR)		+= ali-ircc.o
 obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
 obj-$(CONFIG_VIA_FIR)		+= via-ircc.o
+obj-$(CONFIG_PXA_FICP)	        += pxaficp_ir.o
 # Old dongle drivers for old SIR drivers
 obj-$(CONFIG_ESI_DONGLE_OLD)		+= esi.o
 obj-$(CONFIG_TEKRAM_DONGLE_OLD)	+= tekram.o
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 0a08c53..0282771 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1695,11 +1695,9 @@
 
 freebufs:
   for (i = 0; i < TX_SLOTS; ++i)
-    if (self->tx_bufs[i])
-      kfree (self->tx_bufs[i]);
+    kfree (self->tx_bufs[i]);
   for (i = 0; i < RX_SLOTS; ++i)
-    if (self->rx_bufs[i])
-      kfree (self->rx_bufs[i]);
+    kfree (self->rx_bufs[i]);
   kfree(self->ringbuf);
 
 freeregion:
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6c766fd..c22c051 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1168,10 +1168,8 @@
 	unregister_netdev(self->netdev);
 
 	/* Remove the speed buffer */
-	if (self->speed_buff != NULL) {
-		kfree(self->speed_buff);
-		self->speed_buff = NULL;
-	}
+	kfree(self->speed_buff);
+	self->speed_buff = NULL;
 }
 
 /********************** USB CONFIG SUBROUTINES **********************/
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 5971315..3d016a4 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -235,8 +235,7 @@
 		   __FUNCTION__, self->io.sir_base);
 	release_region(self->io.sir_base, self->io.sir_ext);
 
-	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
+	kfree(self->tx_buff.head);
 	
 	if (self->rx_buff.skb)
 		kfree_skb(self->rx_buff.skb);
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
new file mode 100644
index 0000000..b886b07
--- /dev/null
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -0,0 +1,865 @@
+/*
+ * linux/drivers/net/irda/pxaficp_ir.c
+ *
+ * Based on sa1100_ir.c by Russell King
+ *
+ * Changes copyright (C) 2003-2005 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.
+ *
+ * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/delay.h>
+#include <asm/hardware.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/pxa-regs.h>
+
+#ifdef CONFIG_MACH_MAINSTONE
+#include <asm/arch/mainstone.h>
+#endif
+
+#define IrSR_RXPL_NEG_IS_ZERO (1<<4)
+#define IrSR_RXPL_POS_IS_ZERO 0x0
+#define IrSR_TXPL_NEG_IS_ZERO (1<<3)
+#define IrSR_TXPL_POS_IS_ZERO 0x0
+#define IrSR_XMODE_PULSE_1_6  (1<<2)
+#define IrSR_XMODE_PULSE_3_16 0x0
+#define IrSR_RCVEIR_IR_MODE   (1<<1)
+#define IrSR_RCVEIR_UART_MODE 0x0
+#define IrSR_XMITIR_IR_MODE   (1<<0)
+#define IrSR_XMITIR_UART_MODE 0x0
+
+#define IrSR_IR_RECEIVE_ON (\
+                IrSR_RXPL_NEG_IS_ZERO | \
+                IrSR_TXPL_POS_IS_ZERO | \
+                IrSR_XMODE_PULSE_3_16 | \
+                IrSR_RCVEIR_IR_MODE   | \
+                IrSR_XMITIR_UART_MODE)
+
+#define IrSR_IR_TRANSMIT_ON (\
+                IrSR_RXPL_NEG_IS_ZERO | \
+                IrSR_TXPL_POS_IS_ZERO | \
+                IrSR_XMODE_PULSE_3_16 | \
+                IrSR_RCVEIR_UART_MODE | \
+                IrSR_XMITIR_IR_MODE)
+
+struct pxa_irda {
+	int			speed;
+	int			newspeed;
+	unsigned long		last_oscr;
+
+	unsigned char		*dma_rx_buff;
+	unsigned char		*dma_tx_buff;
+	dma_addr_t		dma_rx_buff_phy;
+	dma_addr_t		dma_tx_buff_phy;
+	unsigned int		dma_tx_buff_len;
+	int			txdma;
+	int			rxdma;
+
+	struct net_device_stats	stats;
+	struct irlap_cb		*irlap;
+	struct qos_info		qos;
+
+	iobuff_t		tx_buff;
+	iobuff_t		rx_buff;
+
+	struct device		*dev;
+	struct pxaficp_platform_data *pdata;
+};
+
+
+#define IS_FIR(si)		((si)->speed >= 4000000)
+#define IRDA_FRAME_SIZE_LIMIT	2047
+
+inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si)
+{
+	DCSR(si->rxdma)  = DCSR_NODESC;
+	DSADR(si->rxdma) = __PREG(ICDR);
+	DTADR(si->rxdma) = si->dma_rx_buff_phy;
+	DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC |  DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT;
+	DCSR(si->rxdma) |= DCSR_RUN;
+}
+
+inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si)
+{
+	DCSR(si->txdma)  = DCSR_NODESC;
+	DSADR(si->txdma) = si->dma_tx_buff_phy;
+	DTADR(si->txdma) = __PREG(ICDR);
+	DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG |  DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len;
+	DCSR(si->txdma) |= DCSR_RUN;
+}
+
+/*
+ * Set the IrDA communications speed.
+ */
+static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
+{
+	unsigned long flags;
+	unsigned int divisor;
+
+	switch (speed) {
+	case 9600:	case 19200:	case 38400:
+	case 57600:	case 115200:
+
+		/* refer to PXA250/210 Developer's Manual 10-7 */
+		/*  BaudRate = 14.7456 MHz / (16*Divisor) */
+		divisor = 14745600 / (16 * speed);
+
+		local_irq_save(flags);
+
+		if (IS_FIR(si)) {
+			/* stop RX DMA */
+			DCSR(si->rxdma) &= ~DCSR_RUN;
+			/* disable FICP */
+			ICCR0 = 0;
+			pxa_set_cken(CKEN13_FICP, 0);
+
+			/* set board transceiver to SIR mode */
+			si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
+
+			/* configure GPIO46/47 */
+			pxa_gpio_mode(GPIO46_STRXD_MD);
+			pxa_gpio_mode(GPIO47_STTXD_MD);
+
+			/* enable the STUART clock */
+			pxa_set_cken(CKEN5_STUART, 1);
+		}
+
+		/* disable STUART first */
+		STIER = 0;
+
+		/* access DLL & DLH */
+		STLCR |= LCR_DLAB;
+		STDLL = divisor & 0xff;
+		STDLH = divisor >> 8;
+		STLCR &= ~LCR_DLAB;
+
+		si->speed = speed;
+		STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+		STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+
+		local_irq_restore(flags);
+		break;
+
+	case 4000000:
+		local_irq_save(flags);
+
+		/* disable STUART */
+		STIER = 0;
+		STISR = 0;
+		pxa_set_cken(CKEN5_STUART, 0);
+
+		/* disable FICP first */
+		ICCR0 = 0;
+
+		/* set board transceiver to FIR mode */
+		si->pdata->transceiver_mode(si->dev, IR_FIRMODE);
+
+		/* configure GPIO46/47 */
+		pxa_gpio_mode(GPIO46_ICPRXD_MD);
+		pxa_gpio_mode(GPIO47_ICPTXD_MD);
+
+		/* enable the FICP clock */
+		pxa_set_cken(CKEN13_FICP, 1);
+
+		si->speed = speed;
+		pxa_irda_fir_dma_rx_start(si);
+		ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+		local_irq_restore(flags);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* SIR interrupt service routine. */
+static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct pxa_irda *si = netdev_priv(dev);
+	int iir, lsr, data;
+
+	iir = STIIR;
+
+	switch  (iir & 0x0F) {
+	case 0x06: /* Receiver Line Status */
+	  	lsr = STLSR;
+		while (lsr & LSR_FIFOE) {
+			data = STRBR;
+			if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
+				printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
+				si->stats.rx_errors++;
+				if (lsr & LSR_FE)
+					si->stats.rx_frame_errors++;
+				if (lsr & LSR_OE)
+					si->stats.rx_fifo_errors++;
+			} else {
+				si->stats.rx_bytes++;
+				async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+			}
+			lsr = STLSR;
+		}
+		dev->last_rx = jiffies;
+		si->last_oscr = OSCR;
+		break;
+
+	case 0x04: /* Received Data Available */
+	  	   /* forth through */
+
+	case 0x0C: /* Character Timeout Indication */
+	  	do  {
+		    si->stats.rx_bytes++;
+	            async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
+	  	} while (STLSR & LSR_DR);
+	  	dev->last_rx = jiffies;
+		si->last_oscr = OSCR;
+	  	break;
+
+	case 0x02: /* Transmit FIFO Data Request */
+	    	while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
+	    		STTHR = *si->tx_buff.data++;
+			si->tx_buff.len -= 1;
+	    	}
+
+		if (si->tx_buff.len == 0) {
+			si->stats.tx_packets++;
+			si->stats.tx_bytes += si->tx_buff.data -
+					      si->tx_buff.head;
+
+                        /* We need to ensure that the transmitter has finished. */
+			while ((STLSR & LSR_TEMT) == 0)
+				cpu_relax();
+			si->last_oscr = OSCR;
+
+			/*
+		 	* Ok, we've finished transmitting.  Now enable
+		 	* the receiver.  Sometimes we get a receive IRQ
+		 	* immediately after a transmit...
+		 	*/
+			if (si->newspeed) {
+				pxa_irda_set_speed(si, si->newspeed);
+				si->newspeed = 0;
+			} else {
+				/* enable IR Receiver, disable IR Transmitter */
+				STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+				/* enable STUART and receive interrupts */
+				STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+			}
+			/* I'm hungry! */
+			netif_wake_queue(dev);
+		}
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* FIR Receive DMA interrupt handler */
+static void pxa_irda_fir_dma_rx_irq(int channel, void *data, struct pt_regs *regs)
+{
+	int dcsr = DCSR(channel);
+
+	DCSR(channel) = dcsr & ~DCSR_RUN;
+
+	printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr);
+}
+
+/* FIR Transmit DMA interrupt handler */
+static void pxa_irda_fir_dma_tx_irq(int channel, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = data;
+	struct pxa_irda *si = netdev_priv(dev);
+	int dcsr;
+
+	dcsr = DCSR(channel);
+	DCSR(channel) = dcsr & ~DCSR_RUN;
+
+	if (dcsr & DCSR_ENDINTR)  {
+		si->stats.tx_packets++;
+		si->stats.tx_bytes += si->dma_tx_buff_len;
+	} else {
+		si->stats.tx_errors++;
+	}
+
+	while (ICSR1 & ICSR1_TBY)
+		cpu_relax();
+	si->last_oscr = OSCR;
+
+	/*
+	 * HACK: It looks like the TBY bit is dropped too soon.
+	 * Without this delay things break.
+	 */
+	udelay(120);
+
+	if (si->newspeed) {
+		pxa_irda_set_speed(si, si->newspeed);
+		si->newspeed = 0;
+	} else {
+		ICCR0 = 0;
+		pxa_irda_fir_dma_rx_start(si);
+		ICCR0 = ICCR0_ITR | ICCR0_RXE;
+	}
+	netif_wake_queue(dev);
+}
+
+/* EIF(Error in FIFO/End in Frame) handler for FIR */
+static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
+{
+	unsigned int len, stat, data;
+
+	/* Get the current data position. */
+	len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
+
+	do {
+		/* Read Status, and then Data. 	 */
+		stat = ICSR1;
+		rmb();
+		data = ICDR;
+
+		if (stat & (ICSR1_CRE | ICSR1_ROR)) {
+			si->stats.rx_errors++;
+			if (stat & ICSR1_CRE) {
+				printk(KERN_DEBUG "pxa_ir: fir receive CRC error\n");
+				si->stats.rx_crc_errors++;
+			}
+			if (stat & ICSR1_ROR) {
+				printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
+				si->stats.rx_frame_errors++;
+			}
+		} else	{
+			si->dma_rx_buff[len++] = data;
+		}
+		/* If we hit the end of frame, there's no point in continuing. */
+		if (stat & ICSR1_EOF)
+			break;
+	} while (ICSR0 & ICSR0_EIF);
+
+	if (stat & ICSR1_EOF) {
+		/* end of frame. */
+		struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC);
+		if (!skb)  {
+			printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
+			si->stats.rx_dropped++;
+			return;
+		}
+
+		/* Align IP header to 20 bytes  */
+		skb_reserve(skb, 1);
+		memcpy(skb->data, si->dma_rx_buff, len);
+		skb_put(skb, len);
+
+		/* Feed it to IrLAP  */
+		skb->dev = dev;
+		skb->mac.raw  = skb->data;
+		skb->protocol = htons(ETH_P_IRDA);
+		netif_rx(skb);
+
+		si->stats.rx_packets++;
+		si->stats.rx_bytes += len;
+
+		dev->last_rx = jiffies;
+	}
+}
+
+/* FIR interrupt handler */
+static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct pxa_irda *si = netdev_priv(dev);
+	int icsr0;
+
+	/* stop RX DMA */
+	DCSR(si->rxdma) &= ~DCSR_RUN;
+	si->last_oscr = OSCR;
+	icsr0 = ICSR0;
+
+	if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
+		if (icsr0 & ICSR0_FRE) {
+		        printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
+			si->stats.rx_frame_errors++;
+		} else {
+			printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
+			si->stats.rx_errors++;
+		}
+		ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
+	}
+
+	if (icsr0 & ICSR0_EIF) {
+		/* An error in FIFO occured, or there is a end of frame */
+		pxa_irda_fir_irq_eif(si, dev);
+	}
+
+	ICCR0 = 0;
+	pxa_irda_fir_dma_rx_start(si);
+	ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+	return IRQ_HANDLED;
+}
+
+/* hard_xmit interface of irda device */
+static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+	int speed = irda_get_next_speed(skb);
+
+	/*
+	 * Does this packet contain a request to change the interface
+	 * speed?  If so, remember it until we complete the transmission
+	 * of this frame.
+	 */
+	if (speed != si->speed && speed != -1)
+		si->newspeed = speed;
+
+	/*
+	 * If this is an empty frame, we can bypass a lot.
+	 */
+	if (skb->len == 0) {
+		if (si->newspeed) {
+			si->newspeed = 0;
+			pxa_irda_set_speed(si, speed);
+		}
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	netif_stop_queue(dev);
+
+	if (!IS_FIR(si)) {
+		si->tx_buff.data = si->tx_buff.head;
+		si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
+
+		/* Disable STUART interrupts and switch to transmit mode. */
+		STIER = 0;
+		STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;
+
+		/* enable STUART and transmit interrupts */
+		STIER = IER_UUE | IER_TIE;
+	} else {
+		unsigned long mtt = irda_get_mtt(skb);
+
+		si->dma_tx_buff_len = skb->len;
+		memcpy(si->dma_tx_buff, skb->data, skb->len);
+
+		if (mtt)
+			while ((unsigned)(OSCR - si->last_oscr)/4 < mtt)
+				cpu_relax();
+
+		/* stop RX DMA,  disable FICP */
+		DCSR(si->rxdma) &= ~DCSR_RUN;
+		ICCR0 = 0;
+
+		pxa_irda_fir_dma_tx_start(si);
+		ICCR0 = ICCR0_ITR | ICCR0_TXE;
+	}
+
+	dev_kfree_skb(skb);
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+	struct pxa_irda *si = netdev_priv(dev);
+	int ret;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			/*
+			 * We are unable to set the speed if the
+			 * device is not running.
+			 */
+			if (netif_running(dev)) {
+				ret = pxa_irda_set_speed(si,
+						rq->ifr_baudrate);
+			} else {
+				printk(KERN_INFO "pxa_ir: SIOCSBANDWIDTH: !netif_running\n");
+				ret = 0;
+			}
+		}
+		break;
+
+	case SIOCSMEDIABUSY:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			irda_device_set_media_busy(dev, TRUE);
+			ret = 0;
+		}
+		break;
+
+	case SIOCGRECEIVING:
+		ret = 0;
+		rq->ifr_receiving = IS_FIR(si) ? 0
+					: si->rx_buff.state != OUTSIDE_FRAME;
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static struct net_device_stats *pxa_irda_stats(struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+	return &si->stats;
+}
+
+static void pxa_irda_startup(struct pxa_irda *si)
+{
+	/* Disable STUART interrupts */
+	STIER = 0;
+	/* enable STUART interrupt to the processor */
+	STMCR = MCR_OUT2;
+	/* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */
+	STLCR = LCR_WLS0 | LCR_WLS1;
+	/* enable FIFO, we use FIFO to improve performance */
+	STFCR = FCR_TRFIFOE | FCR_ITL_32;
+
+	/* disable FICP */
+	ICCR0 = 0;
+	/* configure FICP ICCR2 */
+	ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
+
+	/* configure DMAC */
+	DRCMR17 = si->rxdma | DRCMR_MAPVLD;
+	DRCMR18 = si->txdma | DRCMR_MAPVLD;
+
+	/* force SIR reinitialization */
+	si->speed = 4000000;
+	pxa_irda_set_speed(si, 9600);
+
+	printk(KERN_DEBUG "pxa_ir: irda startup\n");
+}
+
+static void pxa_irda_shutdown(struct pxa_irda *si)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* disable STUART and interrupt */
+	STIER = 0;
+	/* disable STUART SIR mode */
+	STISR = 0;
+	/* disable the STUART clock */
+	pxa_set_cken(CKEN5_STUART, 0);
+
+	/* disable DMA */
+	DCSR(si->txdma) &= ~DCSR_RUN;
+	DCSR(si->rxdma) &= ~DCSR_RUN;
+	/* disable FICP */
+	ICCR0 = 0;
+	/* disable the FICP clock */
+	pxa_set_cken(CKEN13_FICP, 0);
+
+	DRCMR17 = 0;
+	DRCMR18 = 0;
+
+	local_irq_restore(flags);
+
+	/* power off board transceiver */
+	si->pdata->transceiver_mode(si->dev, IR_OFF);
+
+	printk(KERN_DEBUG "pxa_ir: irda shutdown\n");
+}
+
+static int pxa_irda_start(struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+	int err;
+
+	si->speed = 9600;
+
+	err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev);
+	if (err)
+		goto err_irq1;
+
+	err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev);
+	if (err)
+		goto err_irq2;
+
+	/*
+	 * The interrupt must remain disabled for now.
+	 */
+	disable_irq(IRQ_STUART);
+	disable_irq(IRQ_ICP);
+
+	err = -EBUSY;
+	si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
+	if (si->rxdma < 0)
+		goto err_rx_dma;
+
+	si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
+	if (si->txdma < 0)
+		goto err_tx_dma;
+
+	err = -ENOMEM;
+	si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+					     &si->dma_rx_buff_phy, GFP_KERNEL );
+	if (!si->dma_rx_buff)
+		goto err_dma_rx_buff;
+
+	si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
+					     &si->dma_tx_buff_phy, GFP_KERNEL );
+	if (!si->dma_tx_buff)
+		goto err_dma_tx_buff;
+
+	/* Setup the serial port for the initial speed. */
+	pxa_irda_startup(si);
+
+	/*
+	 * Open a new IrLAP layer instance.
+	 */
+	si->irlap = irlap_open(dev, &si->qos, "pxa");
+	err = -ENOMEM;
+	if (!si->irlap)
+		goto err_irlap;
+
+	/*
+	 * Now enable the interrupt and start the queue
+	 */
+	enable_irq(IRQ_STUART);
+	enable_irq(IRQ_ICP);
+	netif_start_queue(dev);
+
+	printk(KERN_DEBUG "pxa_ir: irda driver opened\n");
+
+	return 0;
+
+err_irlap:
+	pxa_irda_shutdown(si);
+	dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+err_dma_tx_buff:
+	dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+err_dma_rx_buff:
+	pxa_free_dma(si->txdma);
+err_tx_dma:
+	pxa_free_dma(si->rxdma);
+err_rx_dma:
+	free_irq(IRQ_ICP, dev);
+err_irq2:
+	free_irq(IRQ_STUART, dev);
+err_irq1:
+
+	return err;
+}
+
+static int pxa_irda_stop(struct net_device *dev)
+{
+	struct pxa_irda *si = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+
+	pxa_irda_shutdown(si);
+
+	/* Stop IrLAP */
+	if (si->irlap) {
+		irlap_close(si->irlap);
+		si->irlap = NULL;
+	}
+
+	free_irq(IRQ_STUART, dev);
+	free_irq(IRQ_ICP, dev);
+
+	pxa_free_dma(si->rxdma);
+	pxa_free_dma(si->txdma);
+
+	if (si->dma_rx_buff)
+		dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
+	if (si->dma_tx_buff)
+		dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
+
+	printk(KERN_DEBUG "pxa_ir: irda driver closed\n");
+	return 0;
+}
+
+static int pxa_irda_suspend(struct device *_dev, pm_message_t state)
+{
+	struct net_device *dev = dev_get_drvdata(_dev);
+	struct pxa_irda *si;
+
+	if (dev && netif_running(dev)) {
+		si = netdev_priv(dev);
+		netif_device_detach(dev);
+		pxa_irda_shutdown(si);
+	}
+
+	return 0;
+}
+
+static int pxa_irda_resume(struct device *_dev)
+{
+	struct net_device *dev = dev_get_drvdata(_dev);
+	struct pxa_irda *si;
+
+	if (dev && netif_running(dev)) {
+		si = netdev_priv(dev);
+		pxa_irda_startup(si);
+		netif_device_attach(dev);
+		netif_wake_queue(dev);
+	}
+
+	return 0;
+}
+
+
+static int pxa_irda_init_iobuf(iobuff_t *io, int size)
+{
+	io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
+	if (io->head != NULL) {
+		io->truesize = size;
+		io->in_frame = FALSE;
+		io->state    = OUTSIDE_FRAME;
+		io->data     = io->head;
+	}
+	return io->head ? 0 : -ENOMEM;
+}
+
+static int pxa_irda_probe(struct device *_dev)
+{
+	struct platform_device *pdev = to_platform_device(_dev);
+	struct net_device *dev;
+	struct pxa_irda *si;
+	unsigned int baudrate_mask;
+	int err;
+
+	if (!pdev->dev.platform_data)
+		return -ENODEV;
+
+	err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY;
+	if (err)
+		goto err_mem_1;
+
+	err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY;
+	if (err)
+		goto err_mem_2;
+
+	dev = alloc_irdadev(sizeof(struct pxa_irda));
+	if (!dev)
+		goto err_mem_3;
+
+	si = netdev_priv(dev);
+	si->dev = &pdev->dev;
+	si->pdata = pdev->dev.platform_data;
+
+	/*
+	 * Initialise the SIR buffers
+	 */
+	err = pxa_irda_init_iobuf(&si->rx_buff, 14384);
+	if (err)
+		goto err_mem_4;
+	err = pxa_irda_init_iobuf(&si->tx_buff, 4000);
+	if (err)
+		goto err_mem_5;
+
+	dev->hard_start_xmit	= pxa_irda_hard_xmit;
+	dev->open		= pxa_irda_start;
+	dev->stop		= pxa_irda_stop;
+	dev->do_ioctl		= pxa_irda_ioctl;
+	dev->get_stats		= pxa_irda_stats;
+
+	irda_init_max_qos_capabilies(&si->qos);
+
+	baudrate_mask = 0;
+	if (si->pdata->transceiver_cap & IR_SIRMODE)
+		baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	if (si->pdata->transceiver_cap & IR_FIRMODE)
+		baudrate_mask |= IR_4000000 << 8;
+
+	si->qos.baud_rate.bits &= baudrate_mask;
+	si->qos.min_turn_time.bits = 7;  /* 1ms or more */
+
+	irda_qos_bits_to_value(&si->qos);
+
+	err = register_netdev(dev);
+
+	if (err == 0)
+		dev_set_drvdata(&pdev->dev, dev);
+
+	if (err) {
+		kfree(si->tx_buff.head);
+err_mem_5:
+		kfree(si->rx_buff.head);
+err_mem_4:
+		free_netdev(dev);
+err_mem_3:
+		release_mem_region(__PREG(FICP), 0x1c);
+err_mem_2:
+		release_mem_region(__PREG(STUART), 0x24);
+	}
+err_mem_1:
+	return err;
+}
+
+static int pxa_irda_remove(struct device *_dev)
+{
+	struct net_device *dev = dev_get_drvdata(_dev);
+
+	if (dev) {
+		struct pxa_irda *si = netdev_priv(dev);
+		unregister_netdev(dev);
+		kfree(si->tx_buff.head);
+		kfree(si->rx_buff.head);
+		free_netdev(dev);
+	}
+
+	release_mem_region(__PREG(STUART), 0x24);
+	release_mem_region(__PREG(FICP), 0x1c);
+
+	return 0;
+}
+
+static struct device_driver pxa_ir_driver = {
+	.name		= "pxa2xx-ir",
+	.bus		= &platform_bus_type,
+	.probe		= pxa_irda_probe,
+	.remove		= pxa_irda_remove,
+	.suspend	= pxa_irda_suspend,
+	.resume		= pxa_irda_resume,
+};
+
+static int __init pxa_irda_init(void)
+{
+	return driver_register(&pxa_ir_driver);
+}
+
+static void __exit pxa_irda_exit(void)
+{
+	driver_unregister(&pxa_ir_driver);
+}
+
+module_init(pxa_irda_init);
+module_exit(pxa_irda_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 8d34ac6..0688330 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -291,12 +291,12 @@
 /*
  * Suspend the IrDA interface.
  */
-static int sa1100_irda_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int sa1100_irda_suspend(struct device *_dev, pm_message_t state)
 {
 	struct net_device *dev = dev_get_drvdata(_dev);
 	struct sa1100_irda *si;
 
-	if (!dev || level != SUSPEND_DISABLE)
+	if (!dev)
 		return 0;
 
 	si = dev->priv;
@@ -316,12 +316,12 @@
 /*
  * Resume the IrDA interface.
  */
-static int sa1100_irda_resume(struct device *_dev, u32 level)
+static int sa1100_irda_resume(struct device *_dev)
 {
 	struct net_device *dev = dev_get_drvdata(_dev);
 	struct sa1100_irda *si;
 
-	if (!dev || level != RESUME_ENABLE)
+	if (!dev)
 		return 0;
 
 	si = dev->priv;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index efc5a88..df22b8b 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -490,8 +490,7 @@
 {
 	if (dev->rx_buff.skb)
 		kfree_skb(dev->rx_buff.skb);
-	if (dev->tx_buff.head)
-		kfree(dev->tx_buff.head);
+	kfree(dev->tx_buff.head);
 	dev->rx_buff.head = dev->tx_buff.head = NULL;
 	dev->rx_buff.skb = NULL;
 }
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index dd89bda..140b7cd 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -213,8 +213,8 @@
 
 /* Power Management */
 
-static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level);
-static int smsc_ircc_resume(struct device *dev, u32 level);
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state);
+static int smsc_ircc_resume(struct device *dev);
 
 static struct device_driver smsc_ircc_driver = {
 	.name		= SMSC_IRCC2_DRIVER_NAME,
@@ -638,21 +638,14 @@
  */
 static void smsc_ircc_init_chip(struct smsc_ircc_cb *self)
 {
-	int iobase, ir_mode, ctrl, fast;
-
-	IRDA_ASSERT(self != NULL, return;);
-
-	iobase = self->io.fir_base;
-	ir_mode = IRCC_CFGA_IRDA_SIR_A;
-	ctrl = 0;
-	fast = 0;
+	int iobase = self->io.fir_base;
 
 	register_bank(iobase, 0);
 	outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
 	outb(0x00, iobase + IRCC_MASTER);
 
 	register_bank(iobase, 1);
-	outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode),
+	outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | IRCC_CFGA_IRDA_SIR_A),
 	     iobase + IRCC_SCE_CFGA);
 
 #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */
@@ -666,10 +659,10 @@
 	outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD);
 
 	register_bank(iobase, 4);
-	outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL);
+	outb((inb(iobase + IRCC_CONTROL) & 0x30), iobase + IRCC_CONTROL);
 
 	register_bank(iobase, 0);
-	outb(fast, iobase + IRCC_LCR_A);
+	outb(0, iobase + IRCC_LCR_A);
 
 	smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
 
@@ -1556,6 +1549,46 @@
 }
 #endif /* unused */
 
+static int smsc_ircc_request_irq(struct smsc_ircc_cb *self)
+{
+	int error;
+
+	error = request_irq(self->io.irq, smsc_ircc_interrupt, 0,
+			    self->netdev->name, self->netdev);
+	if (error)
+		IRDA_DEBUG(0, "%s(), unable to allocate irq=%d, err=%d\n",
+			   __FUNCTION__, self->io.irq, error);
+
+	return error;
+}
+
+static void smsc_ircc_start_interrupts(struct smsc_ircc_cb *self)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&self->lock, flags);
+
+	self->io.speed = 0;
+	smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+}
+
+static void smsc_ircc_stop_interrupts(struct smsc_ircc_cb *self)
+{
+	int iobase = self->io.fir_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&self->lock, flags);
+
+	register_bank(iobase, 0);
+	outb(0, iobase + IRCC_IER);
+	outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
+	outb(0x00, iobase + IRCC_MASTER);
+
+	spin_unlock_irqrestore(&self->lock, flags);
+}
+
 
 /*
  * Function smsc_ircc_net_open (dev)
@@ -1567,7 +1600,6 @@
 {
 	struct smsc_ircc_cb *self;
 	char hwname[16];
-	unsigned long flags;
 
 	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
@@ -1575,6 +1607,11 @@
 	self = netdev_priv(dev);
 	IRDA_ASSERT(self != NULL, return 0;);
 
+	if (self->io.suspended) {
+		IRDA_DEBUG(0, "%s(), device is suspended\n", __FUNCTION__);
+		return -EAGAIN;
+	}
+
 	if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name,
 			(void *) dev)) {
 		IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
@@ -1582,11 +1619,7 @@
 		return -EAGAIN;
 	}
 
-	spin_lock_irqsave(&self->lock, flags);
-	/*smsc_ircc_sir_start(self);*/
-	self->io.speed = 0;
-	smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
-	spin_unlock_irqrestore(&self->lock, flags);
+	smsc_ircc_start_interrupts(self);
 
 	/* Give self a hardware name */
 	/* It would be cool to offer the chip revision here - Jean II */
@@ -1639,37 +1672,63 @@
 		irlap_close(self->irlap);
 	self->irlap = NULL;
 
-	free_irq(self->io.irq, dev);
+	smsc_ircc_stop_interrupts(self);
+
+	/* if we are called from smsc_ircc_resume we don't have IRQ reserved */
+	if (!self->io.suspended)
+		free_irq(self->io.irq, dev);
+
 	disable_dma(self->io.dma);
 	free_dma(self->io.dma);
 
 	return 0;
 }
 
-static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int smsc_ircc_suspend(struct device *dev, pm_message_t state)
 {
 	struct smsc_ircc_cb *self = dev_get_drvdata(dev);
 
-	IRDA_MESSAGE("%s, Suspending\n", driver_name);
+	if (!self->io.suspended) {
+		IRDA_DEBUG(1, "%s, Suspending\n", driver_name);
 
-	if (level == SUSPEND_DISABLE && !self->io.suspended) {
-		smsc_ircc_net_close(self->netdev);
+		rtnl_lock();
+		if (netif_running(self->netdev)) {
+			netif_device_detach(self->netdev);
+			smsc_ircc_stop_interrupts(self);
+			free_irq(self->io.irq, self->netdev);
+			disable_dma(self->io.dma);
+		}
 		self->io.suspended = 1;
+		rtnl_unlock();
 	}
 
 	return 0;
 }
 
-static int smsc_ircc_resume(struct device *dev, u32 level)
+static int smsc_ircc_resume(struct device *dev)
 {
 	struct smsc_ircc_cb *self = dev_get_drvdata(dev);
 
-	if (level == RESUME_ENABLE && self->io.suspended) {
+	if (self->io.suspended) {
+		IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
 
-		smsc_ircc_net_open(self->netdev);
+		rtnl_lock();
+		smsc_ircc_init_chip(self);
+		if (netif_running(self->netdev)) {
+			if (smsc_ircc_request_irq(self)) {
+				/*
+				 * Don't fail resume process, just kill this
+				 * network interface
+				 */
+				unregister_netdevice(self->netdev);
+			} else {
+				enable_dma(self->io.dma);
+				smsc_ircc_start_interrupts(self);
+				netif_device_attach(self->netdev);
+			}
+		}
 		self->io.suspended = 0;
-
-		IRDA_MESSAGE("%s, Waking up\n", driver_name);
+		rtnl_unlock();
 	}
 	return 0;
 }
@@ -1682,9 +1741,6 @@
  */
 static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
 {
-	int iobase;
-	unsigned long flags;
-
 	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
 
 	IRDA_ASSERT(self != NULL, return -1;);
@@ -1694,22 +1750,7 @@
 	/* Remove netdevice */
 	unregister_netdev(self->netdev);
 
-	/* Make sure the irq handler is not exectuting */
-	spin_lock_irqsave(&self->lock, flags);
-
-	/* Stop interrupts */
-	iobase = self->io.fir_base;
-	register_bank(iobase, 0);
-	outb(0, iobase + IRCC_IER);
-	outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
-	outb(0x00, iobase + IRCC_MASTER);
-#if 0
-	/* Reset to SIR mode */
-	register_bank(iobase, 1);
-        outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase + IRCC_SCE_CFGA);
-        outb(IRCC_CFGB_IR, iobase + IRCC_SCE_CFGB);
-#endif
-	spin_unlock_irqrestore(&self->lock, flags);
+	smsc_ircc_stop_interrupts(self);
 
 	/* Release the PORTS that this driver is using */
 	IRDA_DEBUG(0, "%s(), releasing 0x%03x\n",  __FUNCTION__,
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 15f2073..3961a75 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -678,10 +678,9 @@
 		return;
 
 	ticks = us / (1000000 / HZ);
-	if (ticks > 0) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1 + ticks);
-	} else
+	if (ticks > 0)
+		schedule_timeout_interruptible(1 + ticks);
+	else
 		udelay(us);
 }
 
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 651c5a6..a9f49f0 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -473,8 +473,7 @@
 		rd_set_addr_status(rd, 0, 0);
 		if (busaddr)
 			pci_unmap_single(r->pdev, busaddr, r->len, r->dir);
-		if (rd->buf)
-			kfree(rd->buf);
+		kfree(rd->buf);
 	}
 	kfree(r);
 	return 0;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 9d026ed..04e4718 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -645,11 +645,10 @@
 
 	mod_timer(&adapter->blink_timer, jiffies);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	if(data)
-		schedule_timeout(data * HZ);
+	if (data)
+		schedule_timeout_interruptible(data * HZ);
 	else
-		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
 
 	del_timer_sync(&adapter->blink_timer);
 	ixgb_led_off(&adapter->hw);
@@ -723,6 +722,7 @@
 	.phys_id = ixgb_phys_id,
 	.get_stats_count = ixgb_get_stats_count,
 	.get_ethtool_stats = ixgb_get_ethtool_stats,
+	.get_perm_addr = ethtool_op_get_perm_addr,
 };
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 89d6d69..176680c 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -460,8 +460,9 @@
 	}
 
 	ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+	memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
 
-	if(!is_valid_ether_addr(netdev->dev_addr)) {
+	if(!is_valid_ether_addr(netdev->perm_addr)) {
 		err = -EIO;
 		goto err_eeprom;
 	}
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index b4929be..1d75ca0 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -298,7 +298,7 @@
 static unsigned char lance_need_isa_bounce_buffers = 1;
 
 static int lance_open(struct net_device *dev);
-static void lance_init_ring(struct net_device *dev, int mode);
+static void lance_init_ring(struct net_device *dev, gfp_t mode);
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int lance_rx(struct net_device *dev);
 static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -846,7 +846,7 @@
 
 /* Initialize the LANCE Rx and Tx rings. */
 static void
-lance_init_ring(struct net_device *dev, int gfp)
+lance_init_ring(struct net_device *dev, gfp_t gfp)
 {
 	struct lance_private *lp = dev->priv;
 	int i;
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 41bad07..f7b7238 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -415,6 +415,10 @@
 static int ticks_limit = 100;
 static int max_cmd_backlog = TX_RING_SIZE-1;
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
 
 static inline void CA(struct net_device *dev)
 {
@@ -636,11 +640,11 @@
 
 	disable_irq(dev->irq);	/* disable IRQs from LAN */
 	DEB(DEB_INIT,
-		printk("RESET 82596 port: %p (with IRQ %d disabled)\n",
-		       (void*)(dev->base_addr + PA_I82596_RESET),
+		printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
+		       (dev->base_addr + PA_I82596_RESET),
 		       dev->irq));
 	
-	gsc_writel(0, (void*)(dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
+	gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
 	udelay(100);			/* Wait 100us - seems to help */
 
 	/* change the scp address */
@@ -1209,6 +1213,9 @@
 	dev->set_multicast_list = set_multicast_list;
 	dev->tx_timeout = i596_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = i596_poll_controller;
+#endif
 
 	dev->priv = (void *)(dev->mem_start);
 
@@ -1242,6 +1249,14 @@
 	return 0;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	i596_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 static irqreturn_t i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1528,17 +1543,18 @@
 	
 	if (!dev->irq) {
 		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
-			__FILE__, dev->hpa);
+			__FILE__, dev->hpa.start);
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa, dev->irq);
+	printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
+			dev->irq);
 
 	netdevice = alloc_etherdev(0);
 	if (!netdevice)
 		return -ENOMEM;
 
-	netdevice->base_addr = dev->hpa;
+	netdevice->base_addr = dev->hpa.start;
 	netdevice->irq = dev->irq;
 
 	retval = i82596_probe(netdevice, &dev->dev);
@@ -1566,7 +1582,7 @@
 MODULE_DEVICE_TABLE(parisc, lan_tbl);
 
 static struct parisc_driver lan_driver = {
-	.name		= "Apricot",
+	.name		= "lasi_82596",
 	.id_table	= lan_tbl,
 	.probe		= lan_init_chip,
 };
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 27f0d8a..309d254 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -298,7 +298,7 @@
 	return 0;
 unmap:
 	if (ei_status.reg0)
-		iounmap((void *)dev->mem_start);
+		iounmap(ei_status.mem);
 cleanup:
 	free_irq(dev->irq, dev);
 	return ret;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index f2fc1f2..2a5add2 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -1036,10 +1036,8 @@
 {
 	macio_unregister_driver(&mace_driver);
 
-	if (dummy_buf) {
-		kfree(dummy_buf);
-		dummy_buf = NULL;
-	}
+	kfree(dummy_buf);
+	dummy_buf = NULL;
 }
 
 MODULE_AUTHOR("Paul Mackerras");
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
index c33cb3d..e42aa79 100644
--- a/drivers/net/mii.c
+++ b/drivers/net/mii.c
@@ -207,6 +207,20 @@
 	return 0;
 }
 
+int mii_check_gmii_support(struct mii_if_info *mii)
+{
+	int reg;
+
+	reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
+	if (reg & BMSR_ESTATEN) {
+		reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
+		if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
+			return 1;
+	}
+
+	return 0;
+}
+
 int mii_link_ok (struct mii_if_info *mii)
 {
 	/* first, a dummy read, needed to latch some MII phys */
@@ -394,5 +408,6 @@
 EXPORT_SYMBOL(mii_ethtool_sset);
 EXPORT_SYMBOL(mii_check_link);
 EXPORT_SYMBOL(mii_check_media);
+EXPORT_SYMBOL(mii_check_gmii_support);
 EXPORT_SYMBOL(generic_mii_ioctl);
 
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
new file mode 100644
index 0000000..f79f7ee
--- /dev/null
+++ b/drivers/net/mipsnet.c
@@ -0,0 +1,371 @@
+/*
+ * 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.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include <asm/mips-boards/simint.h>
+
+#include "mipsnet.h"		/* actual device IO mapping */
+
+#define MIPSNET_VERSION "2005-06-20"
+
+#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
+
+struct mipsnet_priv {
+	struct net_device_stats stats;
+};
+
+static struct platform_device *mips_plat_dev;
+
+static char mipsnet_string[] = "mipsnet";
+
+/*
+ * Copy data from the MIPSNET rx data port
+ */
+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));
+	}
+
+	return inl(mipsnet_reg_address(dev, rxDataCount));
+}
+
+static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
+	struct sk_buff *skb)
+{
+	int count_to_go = skb->len;
+	char *buf_ptr = skb->data;
+	struct mipsnet_priv *mp = netdev_priv(dev);
+
+	pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
+	         dev->name, __FUNCTION__, skb->len);
+
+	outl(skb->len, mipsnet_reg_address(dev, txDataCount));
+
+	pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
+	         dev->name, __FUNCTION__, skb->len);
+
+	for (; count_to_go; buf_ptr++, count_to_go--) {
+		outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
+	}
+
+	mp->stats.tx_packets++;
+	mp->stats.tx_bytes += skb->len;
+
+	return skb->len;
+}
+
+static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	pr_debug("%s:%s(): transmitting %d bytes\n",
+	         dev->name, __FUNCTION__, skb->len);
+
+	/* Only one packet at a time. Once TXDONE interrupt is serviced, the
+	 * queue will be restarted.
+	 */
+	netif_stop_queue(dev);
+	mipsnet_put_todevice(dev, skb);
+
+	return 0;
+}
+
+static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
+{
+	struct sk_buff *skb;
+	size_t len = count;
+	struct mipsnet_priv *mp = netdev_priv(dev);
+
+	if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+		mp->stats.rx_dropped++;
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, 2);
+	if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
+		return -EFAULT;
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	pr_debug("%s:%s(): pushing RXed data to kernel\n",
+	         dev->name, __FUNCTION__);
+	netif_rx(skb);
+
+	mp->stats.rx_packets++;
+	mp->stats.rx_bytes += len;
+
+	return count;
+}
+
+static irqreturn_t
+mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+
+	irqreturn_t retval = IRQ_NONE;
+	uint64_t interruptFlags;
+
+	if (irq == dev->irq) {
+		pr_debug("%s:%s(): irq %d for device\n",
+		         dev->name, __FUNCTION__, irq);
+
+		retval = IRQ_HANDLED;
+
+		interruptFlags =
+		    inl(mipsnet_reg_address(dev, interruptControl));
+		pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
+		         __FUNCTION__, interruptFlags);
+
+		if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
+			pr_debug("%s:%s(): got TXDone\n",
+			         dev->name, __FUNCTION__);
+			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) {
+			pr_debug("%s:%s(): got RX data\n",
+			         dev->name, __FUNCTION__);
+			mipsnet_get_fromdev(dev,
+			            inl(mipsnet_reg_address(dev, rxDataCount)));
+			pr_debug("%s:%s(): clearing RX int\n",
+			         dev->name, __FUNCTION__);
+			outl(MIPSNET_INTCTL_RXDONE,
+			     mipsnet_reg_address(dev, interruptControl));
+
+		} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
+			pr_debug("%s:%s(): got test interrupt\n",
+			         dev->name, __FUNCTION__);
+			// TESTBIT is cleared on read.
+			//    And takes effect after a write with 0
+			outl(0, mipsnet_reg_address(dev, interruptControl));
+		} else {
+			pr_debug("%s:%s(): no valid fags 0x%016llx\n",
+			         dev->name, __FUNCTION__, interruptFlags);
+			// 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;
+	}
+	return retval;
+}				//mipsnet_interrupt()
+
+static int mipsnet_open(struct net_device *dev)
+{
+	int err;
+	pr_debug("%s: mipsnet_open\n", dev->name);
+
+	err = request_irq(dev->irq, &mipsnet_interrupt,
+			  SA_SHIRQ, dev->name, (void *) dev);
+
+	if (err) {
+		pr_debug("%s: %s(): can't get irq %d\n",
+		         dev->name, __FUNCTION__, dev->irq);
+		release_region(dev->base_addr, MIPSNET_IO_EXTENT);
+		return err;
+	}
+
+	pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
+	         dev->name, __FUNCTION__, dev->base_addr, dev->irq);
+
+
+	netif_start_queue(dev);
+
+	// test interrupt handler
+	outl(MIPSNET_INTCTL_TESTBIT,
+	     mipsnet_reg_address(dev, interruptControl));
+
+
+	return 0;
+}
+
+static int mipsnet_close(struct net_device *dev)
+{
+	pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
+{
+	struct mipsnet_priv *mp = netdev_priv(dev);
+
+	return &mp->stats;
+}
+
+static void mipsnet_set_mclist(struct net_device *dev)
+{
+	// we don't do anything
+	return;
+}
+
+static int __init mipsnet_probe(struct device *dev)
+{
+	struct net_device *netdev;
+	int err;
+
+	netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dev_set_drvdata(dev, netdev);
+
+	netdev->open			= mipsnet_open;
+	netdev->stop			= mipsnet_close;
+	netdev->hard_start_xmit		= mipsnet_xmit;
+	netdev->get_stats		= mipsnet_get_stats;
+	netdev->set_multicast_list	= mipsnet_set_mclist;
+
+	/*
+	 * TODO: probe for these or load them from PARAM
+	 */
+	netdev->base_addr = 0x4200;
+	netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+	              inl(mipsnet_reg_address(netdev, interruptInfo));
+
+	// Get the io region now, get irq on open()
+	if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
+		pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
+		         "for dev is not availble.\n", netdev->name,
+		         __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
+		err = -EBUSY;
+		goto out_free_netdev;
+	}
+
+	/*
+	 * Lacking any better mechanism to allocate a MAC address we use a
+	 * random one ...
+	 */
+	random_ether_addr(netdev->dev_addr);
+
+	err = register_netdev(netdev);
+	if (err) {
+		printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
+		goto out_free_region;
+	}
+
+	return 0;
+
+out_free_region:
+	release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
+
+out_free_netdev:
+	free_netdev(netdev);
+
+out:
+	return err;
+}
+
+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);
+	free_netdev(dev);
+	dev_set_drvdata(device, NULL);
+
+	return 0;
+}
+
+static struct device_driver mipsnet_driver = {
+	.name	= mipsnet_string,
+	.bus	= &platform_bus_type,
+	.probe	= mipsnet_probe,
+	.remove	= __devexit_p(mipsnet_device_remove),
+};
+
+static void mipsnet_platform_release(struct device *device)
+{
+	struct platform_device *pldev;
+
+	/* free device */
+	pldev = to_platform_device(device);
+	kfree(pldev);
+}
+
+static int __init mipsnet_init_module(void)
+{
+	struct platform_device *pldev;
+	int err;
+
+	printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
+	       "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
+
+	if (driver_register(&mipsnet_driver)) {
+		printk(KERN_ERR "Driver registration failed\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+        if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto out_unregister_driver;
+	}
+
+	memset (pldev, 0, sizeof (*pldev));
+	pldev->name		= mipsnet_string;
+	pldev->id		= 0;
+	pldev->dev.release	= mipsnet_platform_release;
+
+	if (platform_device_register(pldev)) {
+		err = -ENODEV;
+		goto out_free_pldev;
+	}
+
+        if (!pldev->dev.driver) {
+		/*
+		 * The driver was not bound to this device, there was
+                 * no hardware at this address. Unregister it, as the
+		 * release fuction will take care of freeing the
+		 * allocated structure
+		 */
+		platform_device_unregister (pldev);
+	}
+
+	mips_plat_dev		= pldev;
+
+	return 0;
+
+out_free_pldev:
+	kfree(pldev);
+
+out_unregister_driver:
+	driver_unregister(&mipsnet_driver);
+out:
+	return err;
+}
+
+static void __exit mipsnet_exit_module(void)
+{
+	pr_debug("MIPSNet Ethernet driver exiting\n");
+
+	driver_unregister(&mipsnet_driver);
+}
+
+module_init(mipsnet_init_module);
+module_exit(mipsnet_exit_module);
diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
new file mode 100644
index 0000000..8785359
--- /dev/null
+++ b/drivers/net/mipsnet.h
@@ -0,0 +1,127 @@
+//
+// <COPYRIGHT CLASS="1B" YEAR="2005">
+// Unpublished work (c) MIPS Technologies, Inc.  All rights reserved.
+// Unpublished rights reserved under the copyright laws of the U.S.A. and
+//  other countries.
+//
+// PROPRIETARY / SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES, INC.
+// FOR INTERNAL USE ONLY.
+//
+// Under no circumstances (contract or otherwise) may this information be
+// disclosed to, or copied, modified or used by anyone other than employees
+// or contractors of MIPS Technologies having a need to know.
+// </COPYRIGHT>
+//
+//++
+// File: MIPS_Net.h
+//
+// Description:
+//   The definition of the emulated MIPSNET device's interface.
+//
+// Notes: This include file needs to work from a Linux device drivers.
+//
+//--
+//
+
+#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.)
+ */
+typedef 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 */
+} MIPS_T_NetControl;
+
+#define MIPSNET_IO_EXTENT 0x40	/* being generous */
+
+#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field)
+
+#endif /* __MIPSNET_H */
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index f0996ce..6c86dca 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -277,7 +277,7 @@
 	struct recvq __iomem *rq = mp->rq;
 	struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
 	struct net_device *dev = mp->dev;
-	int gfp_flags = GFP_KERNEL;
+	gfp_t gfp_flags = GFP_KERNEL;
 	int i;
 
 	if (from_irq || in_interrupt())
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
index 9391e55..47722f7 100644
--- a/drivers/net/myri_sbus.h
+++ b/drivers/net/myri_sbus.h
@@ -296,7 +296,7 @@
 /* We use this to acquire receive skb's that we can DMA directly into. */
 #define ALIGNED_RX_SKB_ADDR(addr) \
         ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
 {
 	struct sk_buff *skb;
 
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index d209a15..0de8fdd 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -54,6 +54,10 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+#include <asm/tx4938/rbtx4938.h>
+#endif
+
 #include "8390.h"
 
 #define DRV_NAME "ne"
@@ -111,6 +115,9 @@
     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
     {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
     {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+    {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
+#endif
     {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
     {NULL,}
 };
@@ -226,6 +233,10 @@
 	sprintf(dev->name, "eth%d", unit);
 	netdev_boot_setup_check(dev);
 
+#ifdef CONFIG_TOSHIBA_RBTX4938
+	dev->base_addr = 0x07f20280;
+	dev->irq = RBTX4938_RTL_8019_IRQ;
+#endif
 	err = do_ne_probe(dev);
 	if (err)
 		goto out;
@@ -506,6 +517,10 @@
 	ei_status.name = name;
 	ei_status.tx_start_page = start_page;
 	ei_status.stop_page = stop_page;
+#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
+	wordlength = 1;
+#endif
+
 #ifdef CONFIG_PLAT_OAKS32R
 	ei_status.word16 = 0;
 #else
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index f1c01ac..d11821d 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -372,6 +372,7 @@
 		printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
 		dev->dev_addr[i] = SA_prom[i];
 	}
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	return 0;
 
@@ -637,6 +638,7 @@
 	.get_drvinfo		= ne2k_pci_get_drvinfo,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
 	.get_sg			= ethtool_op_get_sg,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
@@ -673,7 +675,6 @@
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
 	pci_enable_device(pdev);
-	pci_set_master(pdev);
 	NS8390_init(dev, 1);
 	netif_device_attach(dev);
 
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 925d1df..bb42ff2 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -696,8 +696,7 @@
 		return;
 
 	for(i=0;i<TMDNUM;i++) {
-		if(p->tmdbounce[i])
-			kfree(p->tmdbounce[i]);
+		kfree(p->tmdbounce[i]);
 #ifdef XMT_VIA_SKB
 		if(p->tmd_skb[i])
 			dev_kfree_skb(p->tmd_skb[i]);
@@ -710,12 +709,10 @@
 		if(p->recv_skb[i])
 			dev_kfree_skb(p->recv_skb[i]);
 #else
-		if(p->recvbounce[i])
-			kfree(p->recvbounce[i]);
+		kfree(p->recvbounce[i]);
 #endif
 	}
-	if(p->self)
-		kfree(p->self);
+	kfree(p->self);
 }
 
 
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index e4811b4..a3c3fc9 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1632,8 +1632,7 @@
 			timed_out = 1;
 			break;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
+		schedule_timeout_uninterruptible(1);
 	}
 
 	if (status & fail)
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 9f22d138..818c185 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1020,6 +1020,12 @@
 	} else {
 	    outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
 	}
+    } else if (info->flags & IS_DL10019) {
+	/* Advertise 100F, 100H, 10F, 10H */
+	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
+	/* Restart MII autonegotiation */
+	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
     }
 }
 
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 113b680..70fe81a 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -22,8 +22,8 @@
  *************************************************************************/
 
 #define DRV_NAME	"pcnet32"
-#define DRV_VERSION	"1.30j"
-#define DRV_RELDATE	"29.04.2005"
+#define DRV_VERSION	"1.31a"
+#define DRV_RELDATE	"12.Sep.2005"
 #define PFX		DRV_NAME ": "
 
 static const char *version =
@@ -257,6 +257,9 @@
  * v1.30h  24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
  * v1.30i  28 Jun 2004 Don Fry change to use module_param.
  * v1.30j  29 Apr 2005 Don Fry fix skb/map leak with loopback test.
+ * v1.31   02 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> added set_ringparam().
+ * v1.31a  12 Sep 2005 Hubert WS Lin <wslin@tw.ibm.c0m> set min ring size to 4
+ *	   to allow loopback test to work unchanged.
  */
 
 
@@ -266,17 +269,17 @@
  * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
  */
 #ifndef PCNET32_LOG_TX_BUFFERS
-#define PCNET32_LOG_TX_BUFFERS 4
-#define PCNET32_LOG_RX_BUFFERS 5
+#define PCNET32_LOG_TX_BUFFERS		4
+#define PCNET32_LOG_RX_BUFFERS		5
+#define PCNET32_LOG_MAX_TX_BUFFERS	9	/* 2^9 == 512 */
+#define PCNET32_LOG_MAX_RX_BUFFERS	9
 #endif
 
 #define TX_RING_SIZE		(1 << (PCNET32_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS	((PCNET32_LOG_TX_BUFFERS) << 12)
+#define TX_MAX_RING_SIZE	(1 << (PCNET32_LOG_MAX_TX_BUFFERS))
 
 #define RX_RING_SIZE		(1 << (PCNET32_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)
-#define RX_RING_LEN_BITS	((PCNET32_LOG_RX_BUFFERS) << 4)
+#define RX_MAX_RING_SIZE	(1 << (PCNET32_LOG_MAX_RX_BUFFERS))
 
 #define PKT_BUF_SZ		1544
 
@@ -334,14 +337,14 @@
 };
 
 /*
- * The first three fields of pcnet32_private are read by the ethernet device
- * so we allocate the structure should be allocated by pci_alloc_consistent().
+ * The first field of pcnet32_private is read by the ethernet device
+ * so the structure should be allocated using pci_alloc_consistent().
  */
 struct pcnet32_private {
-    /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
-    struct pcnet32_rx_head    rx_ring[RX_RING_SIZE];
-    struct pcnet32_tx_head    tx_ring[TX_RING_SIZE];
     struct pcnet32_init_block init_block;
+    /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
+    struct pcnet32_rx_head    *rx_ring;
+    struct pcnet32_tx_head    *tx_ring;
     dma_addr_t		dma_addr;	/* DMA address of beginning of this
 					   object, returned by
 					   pci_alloc_consistent */
@@ -349,13 +352,21 @@
 					   structure */
     const char		*name;
     /* The saved address of a sent-in-place packet/buffer, for skfree(). */
-    struct sk_buff	*tx_skbuff[TX_RING_SIZE];
-    struct sk_buff	*rx_skbuff[RX_RING_SIZE];
-    dma_addr_t		tx_dma_addr[TX_RING_SIZE];
-    dma_addr_t		rx_dma_addr[RX_RING_SIZE];
+    struct sk_buff	**tx_skbuff;
+    struct sk_buff	**rx_skbuff;
+    dma_addr_t		*tx_dma_addr;
+    dma_addr_t		*rx_dma_addr;
     struct pcnet32_access	a;
     spinlock_t		lock;		/* Guard lock */
     unsigned int	cur_rx, cur_tx;	/* The next free ring entry */
+    unsigned int	rx_ring_size;	/* current rx ring size */
+    unsigned int	tx_ring_size;	/* current tx ring size */
+    unsigned int	rx_mod_mask;	/* rx ring modular mask */
+    unsigned int	tx_mod_mask;	/* tx ring modular mask */
+    unsigned short	rx_len_bits;
+    unsigned short	tx_len_bits;
+    dma_addr_t		rx_ring_dma_addr;
+    dma_addr_t		tx_ring_dma_addr;
     unsigned int	dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
     struct net_device_stats stats;
     char		tx_full;
@@ -397,6 +408,9 @@
 static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 	void *ptr);
 static void pcnet32_purge_tx_ring(struct net_device *dev);
+static int pcnet32_alloc_ring(struct net_device *dev);
+static void pcnet32_free_ring(struct net_device *dev);
+
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -613,10 +627,62 @@
 {
     struct pcnet32_private *lp = dev->priv;
 
-    ering->tx_max_pending = TX_RING_SIZE - 1;
-    ering->tx_pending = lp->cur_tx - lp->dirty_tx;
-    ering->rx_max_pending = RX_RING_SIZE - 1;
-    ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+    ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
+    ering->tx_pending = lp->tx_ring_size - 1;
+    ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
+    ering->rx_pending = lp->rx_ring_size - 1;
+}
+
+static int pcnet32_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int i;
+
+    if (ering->rx_mini_pending || ering->rx_jumbo_pending)
+	return -EINVAL;
+
+    if (netif_running(dev))
+	pcnet32_close(dev);
+
+    spin_lock_irqsave(&lp->lock, flags);
+    pcnet32_free_ring(dev);
+    lp->tx_ring_size = min(ering->tx_pending, (unsigned int) TX_MAX_RING_SIZE);
+    lp->rx_ring_size = min(ering->rx_pending, (unsigned int) RX_MAX_RING_SIZE);
+
+    /* set the minimum ring size to 4, to allow the loopback test to work
+     * unchanged.
+     */
+    for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
+	if (lp->tx_ring_size <= (1 << i))
+	    break;
+    }
+    lp->tx_ring_size = (1 << i);
+    lp->tx_mod_mask = lp->tx_ring_size - 1;
+    lp->tx_len_bits = (i << 12);
+
+    for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
+	if (lp->rx_ring_size <= (1 << i))
+	    break;
+    }
+    lp->rx_ring_size = (1 << i);
+    lp->rx_mod_mask = lp->rx_ring_size - 1;
+    lp->rx_len_bits = (i << 4);
+
+    if (pcnet32_alloc_ring(dev)) {
+	pcnet32_free_ring(dev);
+	return -ENOMEM;
+    }
+
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    if (pcnet32_debug & NETIF_MSG_DRV)
+	printk(KERN_INFO PFX "Ring Param Settings: RX: %d, TX: %d\n", lp->rx_ring_size, lp->tx_ring_size);
+
+    if (netif_running(dev))
+	pcnet32_open(dev);
+
+    return 0;
 }
 
 static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -948,6 +1014,7 @@
     .nway_reset		= pcnet32_nway_reset,
     .get_link		= pcnet32_get_link,
     .get_ringparam	= pcnet32_get_ringparam,
+    .set_ringparam	= pcnet32_set_ringparam,
     .get_tx_csum	= ethtool_op_get_tx_csum,
     .get_sg		= ethtool_op_get_sg,
     .get_tso		= ethtool_op_get_tso,
@@ -957,6 +1024,7 @@
     .phys_id		= pcnet32_phys_id,
     .get_regs_len	= pcnet32_get_regs_len,
     .get_regs		= pcnet32_get_regs,
+    .get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
 /* only probes for non-PCI devices, the rest are handled by
@@ -1185,9 +1253,10 @@
 	    memcpy(dev->dev_addr, promaddr, 6);
 	}
     }
+    memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
     /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
-    if (!is_valid_ether_addr(dev->dev_addr))
+    if (!is_valid_ether_addr(dev->perm_addr))
 	memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
 
     if (pcnet32_debug & NETIF_MSG_PROBE) {
@@ -1239,6 +1308,12 @@
     dev->priv = lp;
     lp->name = chipname;
     lp->shared_irq = shared;
+    lp->tx_ring_size = TX_RING_SIZE;		/* default tx ring size */
+    lp->rx_ring_size = RX_RING_SIZE;		/* default rx ring size */
+    lp->tx_mod_mask = lp->tx_ring_size - 1;
+    lp->rx_mod_mask = lp->rx_ring_size - 1;
+    lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
+    lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
     lp->mii_if.full_duplex = fdx;
     lp->mii_if.phy_id_mask = 0x1f;
     lp->mii_if.reg_num_mask = 0x1f;
@@ -1265,21 +1340,23 @@
     }
     lp->a = *a;
 
+    if (pcnet32_alloc_ring(dev)) {
+	ret = -ENOMEM;
+	goto err_free_ring;
+    }
     /* detect special T1/E1 WAN card by checking for MAC address */
     if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
 	    && dev->dev_addr[2] == 0x75)
 	lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
 
     lp->init_block.mode = le16_to_cpu(0x0003);	/* Disable Rx and Tx. */
-    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+    lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
     for (i = 0; i < 6; i++)
 	lp->init_block.phys_addr[i] = dev->dev_addr[i];
     lp->init_block.filter[0] = 0x00000000;
     lp->init_block.filter[1] = 0x00000000;
-    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
-	    offsetof(struct pcnet32_private, rx_ring));
-    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
-	    offsetof(struct pcnet32_private, tx_ring));
+    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
 
     /* switch pcnet32 to 32bit mode */
     a->write_bcr(ioaddr, 20, 2);
@@ -1310,7 +1387,7 @@
 	    if (pcnet32_debug & NETIF_MSG_PROBE)
 		printk(", failed to detect IRQ line.\n");
 	    ret = -ENODEV;
-	    goto err_free_consistent;
+	    goto err_free_ring;
 	}
 	if (pcnet32_debug & NETIF_MSG_PROBE)
 	    printk(", probed IRQ %d.\n", dev->irq);
@@ -1341,7 +1418,7 @@
 
     /* Fill in the generic fields of the device structure. */
     if (register_netdev(dev))
-	goto err_free_consistent;
+	goto err_free_ring;
 
     if (pdev) {
 	pci_set_drvdata(pdev, dev);
@@ -1359,6 +1436,8 @@
 
     return 0;
 
+err_free_ring:
+    pcnet32_free_ring(dev);
 err_free_consistent:
     pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
 err_free_netdev:
@@ -1369,6 +1448,86 @@
 }
 
 
+static int pcnet32_alloc_ring(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+
+    if ((lp->tx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+	&lp->tx_ring_dma_addr)) == NULL) {
+	if (pcnet32_debug & NETIF_MSG_DRV)
+	    printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+	return -ENOMEM;
+    }
+
+    if ((lp->rx_ring = pci_alloc_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+	&lp->rx_ring_dma_addr)) == NULL) {
+	if (pcnet32_debug & NETIF_MSG_DRV)
+	    printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+	return -ENOMEM;
+    }
+
+    if (!(lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size, GFP_ATOMIC))) {
+	if (pcnet32_debug & NETIF_MSG_DRV)
+	    printk(KERN_ERR PFX "Memory allocation failed.\n");
+	return -ENOMEM;
+    }
+    memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
+
+    if (!(lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size, GFP_ATOMIC))) {
+	if (pcnet32_debug & NETIF_MSG_DRV)
+	    printk(KERN_ERR PFX "Memory allocation failed.\n");
+	return -ENOMEM;
+    }
+    memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
+
+    if (!(lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size, GFP_ATOMIC))) {
+	if (pcnet32_debug & NETIF_MSG_DRV)
+	    printk(KERN_ERR PFX "Memory allocation failed.\n");
+	return -ENOMEM;
+    }
+    memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
+
+    if (!(lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size, GFP_ATOMIC))) {
+	if (pcnet32_debug & NETIF_MSG_DRV)
+	    printk(KERN_ERR PFX "Memory allocation failed.\n");
+	return -ENOMEM;
+    }
+    memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
+
+    return 0;
+}
+
+
+static void pcnet32_free_ring(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+
+    kfree(lp->tx_skbuff);
+    lp->tx_skbuff = NULL;
+
+    kfree(lp->rx_skbuff);
+    lp->rx_skbuff = NULL;
+
+    kfree(lp->tx_dma_addr);
+    lp->tx_dma_addr = NULL;
+
+    kfree(lp->rx_dma_addr);
+    lp->rx_dma_addr = NULL;
+
+    if (lp->tx_ring) {
+	pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+		lp->tx_ring, lp->tx_ring_dma_addr);
+	lp->tx_ring = NULL;
+    }
+
+    if (lp->rx_ring) {
+	pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * lp->rx_ring_size,
+		lp->rx_ring, lp->rx_ring_dma_addr);
+	lp->rx_ring = NULL;
+    }
+}
+
+
 static int
 pcnet32_open(struct net_device *dev)
 {
@@ -1400,8 +1559,8 @@
     if (netif_msg_ifup(lp))
 	printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
 	       dev->name, dev->irq,
-	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
-	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
+	       (u32) (lp->tx_ring_dma_addr),
+	       (u32) (lp->rx_ring_dma_addr),
 	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
 
     /* set/reset autoselect bit */
@@ -1521,7 +1680,7 @@
 
 err_free_ring:
     /* free any allocated skbuffs */
-    for (i = 0; i < RX_RING_SIZE; i++) {
+    for (i = 0; i < lp->rx_ring_size; i++) {
 	lp->rx_ring[i].status = 0;
 	if (lp->rx_skbuff[i]) {
 	    pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
@@ -1531,6 +1690,9 @@
 	lp->rx_skbuff[i] = NULL;
 	lp->rx_dma_addr[i] = 0;
     }
+
+    pcnet32_free_ring(dev);
+
     /*
      * Switch back to 16bit mode to avoid problems with dumb
      * DOS packet driver after a warm reboot
@@ -1562,7 +1724,7 @@
     struct pcnet32_private *lp = dev->priv;
     int i;
 
-    for (i = 0; i < TX_RING_SIZE; i++) {
+    for (i = 0; i < lp->tx_ring_size; i++) {
 	lp->tx_ring[i].status = 0;	/* CPU owns buffer */
 	wmb();	/* Make sure adapter sees owner change */
 	if (lp->tx_skbuff[i]) {
@@ -1587,7 +1749,7 @@
     lp->cur_rx = lp->cur_tx = 0;
     lp->dirty_rx = lp->dirty_tx = 0;
 
-    for (i = 0; i < RX_RING_SIZE; i++) {
+    for (i = 0; i < lp->rx_ring_size; i++) {
 	struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
 	if (rx_skbuff == NULL) {
 	    if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
@@ -1611,20 +1773,18 @@
     }
     /* The Tx buffer address is filled in as needed, but we do need to clear
      * the upper ownership bit. */
-    for (i = 0; i < TX_RING_SIZE; i++) {
+    for (i = 0; i < lp->tx_ring_size; i++) {
 	lp->tx_ring[i].status = 0;	/* CPU owns buffer */
 	wmb();	/* Make sure adapter sees owner change */
 	lp->tx_ring[i].base = 0;
 	lp->tx_dma_addr[i] = 0;
     }
 
-    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
+    lp->init_block.tlen_rlen = le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
     for (i = 0; i < 6; i++)
 	lp->init_block.phys_addr[i] = dev->dev_addr[i];
-    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
-	    offsetof(struct pcnet32_private, rx_ring));
-    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
-	    offsetof(struct pcnet32_private, tx_ring));
+    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->rx_ring_dma_addr);
+    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->tx_ring_dma_addr);
     wmb();	/* Make sure all changes are visible */
     return 0;
 }
@@ -1682,13 +1842,13 @@
 	printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
 	   lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
 	   lp->cur_rx);
-	for (i = 0 ; i < RX_RING_SIZE; i++)
+	for (i = 0 ; i < lp->rx_ring_size; i++)
 	printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
 	       le32_to_cpu(lp->rx_ring[i].base),
 	       (-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
 	       le32_to_cpu(lp->rx_ring[i].msg_length),
 	       le16_to_cpu(lp->rx_ring[i].status));
-	for (i = 0 ; i < TX_RING_SIZE; i++)
+	for (i = 0 ; i < lp->tx_ring_size; i++)
 	printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
 	       le32_to_cpu(lp->tx_ring[i].base),
 	       (-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
@@ -1729,7 +1889,7 @@
     /* Fill in a Tx ring entry */
 
     /* Mask to ring buffer boundary. */
-    entry = lp->cur_tx & TX_RING_MOD_MASK;
+    entry = lp->cur_tx & lp->tx_mod_mask;
 
     /* Caution: the write order is important here, set the status
      * with the "ownership" bits last. */
@@ -1753,7 +1913,7 @@
 
     dev->trans_start = jiffies;
 
-    if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
+    if (lp->tx_ring[(entry+1) & lp->tx_mod_mask].base != 0) {
 	lp->tx_full = 1;
 	netif_stop_queue(dev);
     }
@@ -1806,7 +1966,7 @@
 	    int delta;
 
 	    while (dirty_tx != lp->cur_tx) {
-		int entry = dirty_tx & TX_RING_MOD_MASK;
+		int entry = dirty_tx & lp->tx_mod_mask;
 		int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
 
 		if (status < 0)
@@ -1864,18 +2024,18 @@
 		dirty_tx++;
 	    }
 
-	    delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
-	    if (delta > TX_RING_SIZE) {
+	    delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
+	    if (delta > lp->tx_ring_size) {
 		if (netif_msg_drv(lp))
 		    printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
 			    dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
-		dirty_tx += TX_RING_SIZE;
-		delta -= TX_RING_SIZE;
+		dirty_tx += lp->tx_ring_size;
+		delta -= lp->tx_ring_size;
 	    }
 
 	    if (lp->tx_full &&
 		netif_queue_stopped(dev) &&
-		delta < TX_RING_SIZE - 2) {
+		delta < lp->tx_ring_size - 2) {
 		/* The ring is no longer full, clear tbusy. */
 		lp->tx_full = 0;
 		netif_wake_queue (dev);
@@ -1932,8 +2092,8 @@
 pcnet32_rx(struct net_device *dev)
 {
     struct pcnet32_private *lp = dev->priv;
-    int entry = lp->cur_rx & RX_RING_MOD_MASK;
-    int boguscnt = RX_RING_SIZE / 2;
+    int entry = lp->cur_rx & lp->rx_mod_mask;
+    int boguscnt = lp->rx_ring_size / 2;
 
     /* If we own the next entry, it's a new packet. Send it up. */
     while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
@@ -1998,12 +2158,12 @@
 		    if (netif_msg_drv(lp))
 			printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
 				dev->name);
-		    for (i = 0; i < RX_RING_SIZE; i++)
+		    for (i = 0; i < lp->rx_ring_size; i++)
 			if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
-				    & RX_RING_MOD_MASK].status) < 0)
+				    & lp->rx_mod_mask].status) < 0)
 			    break;
 
-		    if (i > RX_RING_SIZE -2) {
+		    if (i > lp->rx_ring_size -2) {
 			lp->stats.rx_dropped++;
 			lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
 			wmb();	/* Make sure adapter sees owner change */
@@ -2041,7 +2201,7 @@
 	lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
 	wmb(); /* Make sure owner changes after all others are visible */
 	lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
-	entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+	entry = (++lp->cur_rx) & lp->rx_mod_mask;
 	if (--boguscnt <= 0) break;	/* don't stay in loop forever */
     }
 
@@ -2084,7 +2244,7 @@
     spin_lock_irqsave(&lp->lock, flags);
 
     /* free all allocated skbuffs */
-    for (i = 0; i < RX_RING_SIZE; i++) {
+    for (i = 0; i < lp->rx_ring_size; i++) {
 	lp->rx_ring[i].status = 0;
 	wmb();		/* Make sure adapter sees owner change */
 	if (lp->rx_skbuff[i]) {
@@ -2096,7 +2256,7 @@
 	lp->rx_dma_addr[i] = 0;
     }
 
-    for (i = 0; i < TX_RING_SIZE; i++) {
+    for (i = 0; i < lp->tx_ring_size; i++) {
 	lp->tx_ring[i].status = 0;	/* CPU owns buffer */
 	wmb();		/* Make sure adapter sees owner change */
 	if (lp->tx_skbuff[i]) {
@@ -2265,6 +2425,7 @@
 	struct pcnet32_private *lp = dev->priv;
 
 	unregister_netdev(dev);
+	pcnet32_free_ring(dev);
 	release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
 	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
 	free_netdev(dev);
@@ -2340,6 +2501,7 @@
 	struct pcnet32_private *lp = pcnet32_dev->priv;
 	next_dev = lp->next;
 	unregister_netdev(pcnet32_dev);
+	pcnet32_free_ring(pcnet32_dev);
 	release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
 	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
 	free_netdev(pcnet32_dev);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 14f4de1..c782a63 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -12,14 +12,6 @@
 	  devices.  This option provides infrastructure for
 	  managing PHY devices.
 
-config PHYCONTROL
-	bool "  Support for automatically handling PHY state changes"
-	depends on PHYLIB
-	help
-	  Adds code to perform all the work for keeping PHY link
-	  state (speed/duplex/etc) up-to-date.  Also handles
-	  interrupts.
-
 comment "MII PHY device drivers"
 	depends on PHYLIB
 
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 9063067..ad93b0d 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -133,13 +133,9 @@
 	int ret = 0;
 	struct device_driver *drv = dev->driver;
 
-	if (drv && drv->suspend) {
-		ret = drv->suspend(dev, state, SUSPEND_DISABLE);
-		if (ret == 0)
-			ret = drv->suspend(dev, state, SUSPEND_SAVE_STATE);
-		if (ret == 0)
-			ret = drv->suspend(dev, state, SUSPEND_POWER_DOWN);
-	}
+	if (drv && drv->suspend)
+		ret = drv->suspend(dev, state);
+
 	return ret;
 }
 
@@ -148,13 +144,9 @@
 	int ret = 0;
 	struct device_driver *drv = dev->driver;
 
-	if (drv && drv->resume) {
-		ret = drv->resume(dev, RESUME_POWER_ON);
-		if (ret == 0)
-			ret = drv->resume(dev, RESUME_RESTORE_STATE);
-		if (ret == 0)
-			ret = drv->resume(dev, RESUME_ENABLE);
-	}
+	if (drv && drv->resume)
+		ret = drv->resume(dev);
+
 	return ret;
 }
 
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d9e11f9..9209da9 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -242,10 +242,6 @@
  *   choose the next best ones from the ones selected, so we don't
  *   care if ethtool tries to give us bad values
  *
- * A note about the PHYCONTROL Layer.  If you turn off
- * CONFIG_PHYCONTROL, you will need to read the PHY status
- * registers after this function completes, and update your
- * controller manually.
  */
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
 {
@@ -380,7 +376,6 @@
 
 	err = phydev->drv->config_aneg(phydev);
 
-#ifdef CONFIG_PHYCONTROL
 	if (err < 0)
 		goto out_unlock;
 
@@ -395,14 +390,12 @@
 	}
 
 out_unlock:
-#endif
 	spin_unlock(&phydev->lock);
 	return err;
 }
 EXPORT_SYMBOL(phy_start_aneg);
 
 
-#ifdef CONFIG_PHYCONTROL
 static void phy_change(void *data);
 static void phy_timer(unsigned long data);
 
@@ -868,4 +861,3 @@
 	mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
 }
 
-#endif /* CONFIG_PHYCONTROL */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 33f7bdb..6da1aa0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -101,7 +101,6 @@
 	return dev;
 }
 
-#ifdef CONFIG_PHYCONTROL
 /* phy_prepare_link:
  *
  * description: Tells the PHY infrastructure to handle the
@@ -160,8 +159,6 @@
 }
 EXPORT_SYMBOL(phy_disconnect);
 
-#endif /* CONFIG_PHYCONTROL */
-
 /* phy_attach:
  *
  *   description: Called by drivers to attach to a particular PHY
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0df7e92..d3c9958 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -863,7 +863,7 @@
 			err = PTR_ERR(ppp_class);
 			goto out_chrdev;
 		}
-		class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+		class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
 		err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
 				S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
 		if (err)
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index afb3f18..159b56a 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1027,6 +1027,7 @@
 	.get_strings		= rtl8169_get_strings,
 	.get_stats_count	= rtl8169_get_stats_count,
 	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1511,6 +1512,7 @@
 	/* Get MAC address.  FIXME: read EEPROM */
 	for (i = 0; i < MAC_ADDR_LEN; i++)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	dev->open = rtl8169_open;
 	dev->hard_start_xmit = rtl8169_start_xmit;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
new file mode 100644
index 0000000..12cde06
--- /dev/null
+++ b/drivers/net/rionet.c
@@ -0,0 +1,574 @@
+/*
+ * rionet - Ethernet driver over RapidIO messaging services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME        "rionet"
+#define DRV_VERSION     "0.2"
+#define DRV_AUTHOR      "Matt Porter <mporter@kernel.crashing.org>"
+#define DRV_DESC        "Ethernet over RapidIO"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
+#define RIONET_DEFAULT_MSGLEVEL \
+			(NETIF_MSG_DRV          | \
+			 NETIF_MSG_LINK         | \
+			 NETIF_MSG_RX_ERR       | \
+			 NETIF_MSG_TX_ERR)
+
+#define RIONET_DOORBELL_JOIN	0x1000
+#define RIONET_DOORBELL_LEAVE	0x1001
+
+#define RIONET_MAILBOX		0
+
+#define RIONET_TX_RING_SIZE	CONFIG_RIONET_TX_SIZE
+#define RIONET_RX_RING_SIZE	CONFIG_RIONET_RX_SIZE
+
+static LIST_HEAD(rionet_peers);
+
+struct rionet_private {
+	struct rio_mport *mport;
+	struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
+	struct sk_buff *tx_skb[RIONET_TX_RING_SIZE];
+	struct net_device_stats stats;
+	int rx_slot;
+	int tx_slot;
+	int tx_cnt;
+	int ack_slot;
+	spinlock_t lock;
+	spinlock_t tx_lock;
+	u32 msg_enable;
+};
+
+struct rionet_peer {
+	struct list_head node;
+	struct rio_dev *rdev;
+	struct resource *res;
+};
+
+static int rionet_check = 0;
+static int rionet_capable = 1;
+
+/*
+ * This is a fast lookup table for for translating TX
+ * Ethernet packets into a destination RIO device. It
+ * could be made into a hash table to save memory depending
+ * on system trade-offs.
+ */
+static struct rio_dev *rionet_active[RIO_MAX_ROUTE_ENTRIES];
+
+#define is_rionet_capable(pef, src_ops, dst_ops)		\
+			((pef & RIO_PEF_INB_MBOX) &&		\
+			 (pef & RIO_PEF_INB_DOORBELL) &&	\
+			 (src_ops & RIO_SRC_OPS_DOORBELL) &&	\
+			 (dst_ops & RIO_DST_OPS_DOORBELL))
+#define dev_rionet_capable(dev) \
+	is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops)
+
+#define RIONET_MAC_MATCH(x)	(*(u32 *)x == 0x00010001)
+#define RIONET_GET_DESTID(x)	(*(u16 *)(x + 4))
+
+static struct net_device_stats *rionet_stats(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+	return &rnet->stats;
+}
+
+static int rionet_rx_clean(struct net_device *ndev)
+{
+	int i;
+	int error = 0;
+	struct rionet_private *rnet = ndev->priv;
+	void *data;
+
+	i = rnet->rx_slot;
+
+	do {
+		if (!rnet->rx_skb[i])
+			continue;
+
+		if (!(data = rio_get_inb_message(rnet->mport, RIONET_MAILBOX)))
+			break;
+
+		rnet->rx_skb[i]->data = data;
+		skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
+		rnet->rx_skb[i]->dev = ndev;
+		rnet->rx_skb[i]->protocol =
+		    eth_type_trans(rnet->rx_skb[i], ndev);
+		error = netif_rx(rnet->rx_skb[i]);
+
+		if (error == NET_RX_DROP) {
+			rnet->stats.rx_dropped++;
+		} else if (error == NET_RX_BAD) {
+			if (netif_msg_rx_err(rnet))
+				printk(KERN_WARNING "%s: bad rx packet\n",
+				       DRV_NAME);
+			rnet->stats.rx_errors++;
+		} else {
+			rnet->stats.rx_packets++;
+			rnet->stats.rx_bytes += RIO_MAX_MSG_SIZE;
+		}
+
+	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != rnet->rx_slot);
+
+	return i;
+}
+
+static void rionet_rx_fill(struct net_device *ndev, int end)
+{
+	int i;
+	struct rionet_private *rnet = ndev->priv;
+
+	i = rnet->rx_slot;
+	do {
+		rnet->rx_skb[i] = dev_alloc_skb(RIO_MAX_MSG_SIZE);
+
+		if (!rnet->rx_skb[i])
+			break;
+
+		rio_add_inb_buffer(rnet->mport, RIONET_MAILBOX,
+				   rnet->rx_skb[i]->data);
+	} while ((i = (i + 1) % RIONET_RX_RING_SIZE) != end);
+
+	rnet->rx_slot = i;
+}
+
+static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
+			       struct rio_dev *rdev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
+	rnet->tx_skb[rnet->tx_slot] = skb;
+
+	rnet->stats.tx_packets++;
+	rnet->stats.tx_bytes += skb->len;
+
+	if (++rnet->tx_cnt == RIONET_TX_RING_SIZE)
+		netif_stop_queue(ndev);
+
+	++rnet->tx_slot;
+	rnet->tx_slot &= (RIONET_TX_RING_SIZE - 1);
+
+	if (netif_msg_tx_queued(rnet))
+		printk(KERN_INFO "%s: queued skb %8.8x len %8.8x\n", DRV_NAME,
+		       (u32) skb, skb->len);
+
+	return 0;
+}
+
+static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int i;
+	struct rionet_private *rnet = ndev->priv;
+	struct ethhdr *eth = (struct ethhdr *)skb->data;
+	u16 destid;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (!spin_trylock(&rnet->tx_lock)) {
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
+
+	if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+		netif_stop_queue(ndev);
+		spin_unlock_irqrestore(&rnet->tx_lock, flags);
+		printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+		       ndev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (eth->h_dest[0] & 0x01) {
+		for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++)
+			if (rionet_active[i])
+				rionet_queue_tx_msg(skb, ndev,
+						    rionet_active[i]);
+	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
+		destid = RIONET_GET_DESTID(eth->h_dest);
+		if (rionet_active[destid])
+			rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+	}
+
+	spin_unlock_irqrestore(&rnet->tx_lock, flags);
+
+	return 0;
+}
+
+static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u16 tid,
+			       u16 info)
+{
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = ndev->priv;
+	struct rionet_peer *peer;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
+		       DRV_NAME, sid, tid, info);
+	if (info == RIONET_DOORBELL_JOIN) {
+		if (!rionet_active[sid]) {
+			list_for_each_entry(peer, &rionet_peers, node) {
+				if (peer->rdev->destid == sid)
+					rionet_active[sid] = peer->rdev;
+			}
+			rio_mport_send_doorbell(mport, sid,
+						RIONET_DOORBELL_JOIN);
+		}
+	} else if (info == RIONET_DOORBELL_LEAVE) {
+		rionet_active[sid] = NULL;
+	} else {
+		if (netif_msg_intr(rnet))
+			printk(KERN_WARNING "%s: unhandled doorbell\n",
+			       DRV_NAME);
+	}
+}
+
+static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+	int n;
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
+		       DRV_NAME, mbox, slot);
+
+	spin_lock(&rnet->lock);
+	if ((n = rionet_rx_clean(ndev)) != rnet->rx_slot)
+		rionet_rx_fill(ndev, n);
+	spin_unlock(&rnet->lock);
+}
+
+static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
+{
+	struct net_device *ndev = dev_id;
+	struct rionet_private *rnet = ndev->priv;
+
+	spin_lock(&rnet->lock);
+
+	if (netif_msg_intr(rnet))
+		printk(KERN_INFO
+		       "%s: outbound message event, mbox %d slot %d\n",
+		       DRV_NAME, mbox, slot);
+
+	while (rnet->tx_cnt && (rnet->ack_slot != slot)) {
+		/* dma unmap single */
+		dev_kfree_skb_irq(rnet->tx_skb[rnet->ack_slot]);
+		rnet->tx_skb[rnet->ack_slot] = NULL;
+		++rnet->ack_slot;
+		rnet->ack_slot &= (RIONET_TX_RING_SIZE - 1);
+		rnet->tx_cnt--;
+	}
+
+	if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+		netif_wake_queue(ndev);
+
+	spin_unlock(&rnet->lock);
+}
+
+static int rionet_open(struct net_device *ndev)
+{
+	int i, rc = 0;
+	struct rionet_peer *peer, *tmp;
+	u32 pwdcsr;
+	struct rionet_private *rnet = ndev->priv;
+
+	if (netif_msg_ifup(rnet))
+		printk(KERN_INFO "%s: open\n", DRV_NAME);
+
+	if ((rc = rio_request_inb_dbell(rnet->mport,
+					(void *)ndev,
+					RIONET_DOORBELL_JOIN,
+					RIONET_DOORBELL_LEAVE,
+					rionet_dbell_event)) < 0)
+		goto out;
+
+	if ((rc = rio_request_inb_mbox(rnet->mport,
+				       (void *)ndev,
+				       RIONET_MAILBOX,
+				       RIONET_RX_RING_SIZE,
+				       rionet_inb_msg_event)) < 0)
+		goto out;
+
+	if ((rc = rio_request_outb_mbox(rnet->mport,
+					(void *)ndev,
+					RIONET_MAILBOX,
+					RIONET_TX_RING_SIZE,
+					rionet_outb_msg_event)) < 0)
+		goto out;
+
+	/* Initialize inbound message ring */
+	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+		rnet->rx_skb[i] = NULL;
+	rnet->rx_slot = 0;
+	rionet_rx_fill(ndev, 0);
+
+	rnet->tx_slot = 0;
+	rnet->tx_cnt = 0;
+	rnet->ack_slot = 0;
+
+	netif_carrier_on(ndev);
+	netif_start_queue(ndev);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		if (!(peer->res = rio_request_outb_dbell(peer->rdev,
+							 RIONET_DOORBELL_JOIN,
+							 RIONET_DOORBELL_LEAVE)))
+		{
+			printk(KERN_ERR "%s: error requesting doorbells\n",
+			       DRV_NAME);
+			continue;
+		}
+
+		/*
+		 * If device has initialized inbound doorbells,
+		 * send a join message
+		 */
+		rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr);
+		if (pwdcsr & RIO_DOORBELL_AVAIL)
+			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
+	}
+
+      out:
+	return rc;
+}
+
+static int rionet_close(struct net_device *ndev)
+{
+	struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+	struct rionet_peer *peer, *tmp;
+	int i;
+
+	if (netif_msg_ifup(rnet))
+		printk(KERN_INFO "%s: close\n", DRV_NAME);
+
+	netif_stop_queue(ndev);
+	netif_carrier_off(ndev);
+
+	for (i = 0; i < RIONET_RX_RING_SIZE; i++)
+		if (rnet->rx_skb[i])
+			kfree_skb(rnet->rx_skb[i]);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		if (rionet_active[peer->rdev->destid]) {
+			rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
+			rionet_active[peer->rdev->destid] = NULL;
+		}
+		rio_release_outb_dbell(peer->rdev, peer->res);
+	}
+
+	rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
+			      RIONET_DOORBELL_LEAVE);
+	rio_release_inb_mbox(rnet->mport, RIONET_MAILBOX);
+	rio_release_outb_mbox(rnet->mport, RIONET_MAILBOX);
+
+	return 0;
+}
+
+static void rionet_remove(struct rio_dev *rdev)
+{
+	struct net_device *ndev = NULL;
+	struct rionet_peer *peer, *tmp;
+
+	unregister_netdev(ndev);
+	kfree(ndev);
+
+	list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+		list_del(&peer->node);
+		kfree(peer);
+	}
+}
+
+static void rionet_get_drvinfo(struct net_device *ndev,
+			       struct ethtool_drvinfo *info)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "n/a");
+	strcpy(info->bus_info, rnet->mport->name);
+}
+
+static u32 rionet_get_msglevel(struct net_device *ndev)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	return rnet->msg_enable;
+}
+
+static void rionet_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct rionet_private *rnet = ndev->priv;
+
+	rnet->msg_enable = value;
+}
+
+static struct ethtool_ops rionet_ethtool_ops = {
+	.get_drvinfo = rionet_get_drvinfo,
+	.get_msglevel = rionet_get_msglevel,
+	.set_msglevel = rionet_set_msglevel,
+	.get_link = ethtool_op_get_link,
+};
+
+static int rionet_setup_netdev(struct rio_mport *mport)
+{
+	int rc = 0;
+	struct net_device *ndev = NULL;
+	struct rionet_private *rnet;
+	u16 device_id;
+
+	/* Allocate our net_device structure */
+	ndev = alloc_etherdev(sizeof(struct rionet_private));
+	if (ndev == NULL) {
+		printk(KERN_INFO "%s: could not allocate ethernet device.\n",
+		       DRV_NAME);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Set up private area */
+	rnet = (struct rionet_private *)ndev->priv;
+	rnet->mport = mport;
+
+	/* Set the default MAC address */
+	device_id = rio_local_get_device_id(mport);
+	ndev->dev_addr[0] = 0x00;
+	ndev->dev_addr[1] = 0x01;
+	ndev->dev_addr[2] = 0x00;
+	ndev->dev_addr[3] = 0x01;
+	ndev->dev_addr[4] = device_id >> 8;
+	ndev->dev_addr[5] = device_id & 0xff;
+
+	/* Fill in the driver function table */
+	ndev->open = &rionet_open;
+	ndev->hard_start_xmit = &rionet_start_xmit;
+	ndev->stop = &rionet_close;
+	ndev->get_stats = &rionet_stats;
+	ndev->mtu = RIO_MAX_MSG_SIZE - 14;
+	ndev->features = NETIF_F_LLTX;
+	SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
+
+	SET_MODULE_OWNER(ndev);
+
+	spin_lock_init(&rnet->lock);
+	spin_lock_init(&rnet->tx_lock);
+
+	rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
+
+	rc = register_netdev(ndev);
+	if (rc != 0)
+		goto out;
+
+	printk("%s: %s %s Version %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       ndev->name,
+	       DRV_NAME,
+	       DRV_DESC,
+	       DRV_VERSION,
+	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
+	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+
+      out:
+	return rc;
+}
+
+/*
+ * XXX Make multi-net safe
+ */
+static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
+{
+	int rc = -ENODEV;
+	u32 lpef, lsrc_ops, ldst_ops;
+	struct rionet_peer *peer;
+
+	/* If local device is not rionet capable, give up quickly */
+	if (!rionet_capable)
+		goto out;
+
+	/*
+	 * First time through, make sure local device is rionet
+	 * capable, setup netdev,  and set flags so this is skipped
+	 * on later probes
+	 */
+	if (!rionet_check) {
+		rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef);
+		rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
+					 &lsrc_ops);
+		rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
+					 &ldst_ops);
+		if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) {
+			printk(KERN_ERR
+			       "%s: local device is not network capable\n",
+			       DRV_NAME);
+			rionet_check = 1;
+			rionet_capable = 0;
+			goto out;
+		}
+
+		rc = rionet_setup_netdev(rdev->net->hport);
+		rionet_check = 1;
+	}
+
+	/*
+	 * If the remote device has mailbox/doorbell capabilities,
+	 * add it to the peer list.
+	 */
+	if (dev_rionet_capable(rdev)) {
+		if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		peer->rdev = rdev;
+		list_add_tail(&peer->node, &rionet_peers);
+	}
+
+      out:
+	return rc;
+}
+
+static struct rio_device_id rionet_id_table[] = {
+	{RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}
+};
+
+static struct rio_driver rionet_driver = {
+	.name = "rionet",
+	.id_table = rionet_id_table,
+	.probe = rionet_probe,
+	.remove = rionet_remove,
+};
+
+static int __init rionet_init(void)
+{
+	return rio_register_driver(&rionet_driver);
+}
+
+static void __exit rionet_exit(void)
+{
+	rio_unregister_driver(&rionet_driver);
+}
+
+module_init(rionet_init);
+module_exit(rionet_exit);
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index ec1a18d..19c2df9 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1710,10 +1710,8 @@
 			error = -EFAULT;
 		}
 	wf_out:
-		if (oldimage)
-			kfree(oldimage);
-		if (image)
-			kfree(image);
+		kfree(oldimage);
+		kfree(image);
 		return error;
 		
 	case SIOCRRID:
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index 7cefe55..00179bc 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -814,6 +814,17 @@
 	u64 rxgxs_ber_0;	/* CHANGED */
 	u64 rxgxs_ber_1;	/* CHANGED */
 
+	u64 spi_control;
+#define SPI_CONTROL_KEY(key)		vBIT(key,0,4)
+#define SPI_CONTROL_BYTECNT(cnt)	vBIT(cnt,29,3)
+#define SPI_CONTROL_CMD(cmd)		vBIT(cmd,32,8)
+#define SPI_CONTROL_ADDR(addr)		vBIT(addr,40,24)
+#define SPI_CONTROL_SEL1		BIT(4)
+#define SPI_CONTROL_REQ			BIT(7)
+#define SPI_CONTROL_NACK		BIT(5)
+#define SPI_CONTROL_DONE		BIT(6)
+	u64 spi_data;
+#define SPI_DATA_WRITE(data,len)	vBIT(data,0,len)
 } XENA_dev_config_t;
 
 #define XENA_REG_SPACE	sizeof(XENA_dev_config_t)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index dd451e0..3f5e93a 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -65,9 +65,11 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
+#define DRV_VERSION "Version 2.0.9.1"
+
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = "Version 2.0.8.1";
+static char s2io_driver_version[] = DRV_VERSION;
 
 static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 {
@@ -307,6 +309,8 @@
 #endif
 /* Frequency of Rx desc syncs expressed as power of 2 */
 static unsigned int rxsync_frequency = 3;
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+static unsigned int intr_type = 0;
 
 /*
  * S2IO device table.
@@ -701,8 +705,7 @@
 			}
 			kfree(mac_control->rings[i].ba[j]);
 		}
-		if (mac_control->rings[i].ba)
-			kfree(mac_control->rings[i].ba);
+		kfree(mac_control->rings[i].ba);
 	}
 #endif
 
@@ -1396,8 +1399,13 @@
 		writeq(val64, &bar0->rti_data1_mem);
 
 		val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
-		    RTI_DATA2_MEM_RX_UFC_B(0x2) |
-		    RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80);
+		    RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+		if (nic->intr_type == MSI_X)
+		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
+				RTI_DATA2_MEM_RX_UFC_D(0x40));
+		else
+		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
+				RTI_DATA2_MEM_RX_UFC_D(0x80));
 		writeq(val64, &bar0->rti_data2_mem);
 
 		for (i = 0; i < config->rx_ring_num; i++) {
@@ -1507,17 +1515,15 @@
 #define LINK_UP_DOWN_INTERRUPT		1
 #define MAC_RMAC_ERR_TIMER		2
 
-#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
-#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
-#else
 int s2io_link_fault_indication(nic_t *nic)
 {
+	if (nic->intr_type != INTA)
+		return MAC_RMAC_ERR_TIMER;
 	if (nic->device_type == XFRAME_II_DEVICE)
 		return LINK_UP_DOWN_INTERRUPT;
 	else
 		return MAC_RMAC_ERR_TIMER;
 }
-#endif
 
 /**
  *  en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1941,11 +1947,14 @@
 	}
 
 	/*  Enable select interrupts */
-	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-	interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-	interruptible |= TX_MAC_INTR | RX_MAC_INTR;
-
-	en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+	if (nic->intr_type != INTA)
+		en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
+	else {
+		interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+		interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+		interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+		en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+	}
 
 	/*
 	 * With some switches, link might be already up at this point.
@@ -2633,11 +2642,11 @@
 			err = txdlp->Control_1 & TXD_T_CODE;
 			if ((err >> 48) == 0xA) {
 				DBG_PRINT(TX_DBG, "TxD returned due \
-						to loss of link\n");
+to loss of link\n");
 			}
 			else {
 				DBG_PRINT(ERR_DBG, "***TxD error \
-						%llx\n", err);
+%llx\n", err);
 			}
 		}
 
@@ -2854,6 +2863,9 @@
 	/* Set swapper to enable I/O register access */
 	s2io_set_swapper(sp);
 
+	/* Restore the MSIX table entries from local variables */
+	restore_xmsi_data(sp);
+
 	/* Clear certain PCI/PCI-X fields after reset */
 	if (sp->device_type == XFRAME_II_DEVICE) {
 		/* Clear parity err detect bit */
@@ -2983,8 +2995,9 @@
 		 SWAPPER_CTRL_RXD_W_FE |
 		 SWAPPER_CTRL_RXF_W_FE |
 		 SWAPPER_CTRL_XMSI_FE |
-		 SWAPPER_CTRL_XMSI_SE |
 		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+	if (sp->intr_type == INTA)
+		val64 |= SWAPPER_CTRL_XMSI_SE;
 	writeq(val64, &bar0->swapper_ctrl);
 #else
 	/*
@@ -3005,8 +3018,9 @@
 		 SWAPPER_CTRL_RXD_W_SE |
 		 SWAPPER_CTRL_RXF_W_FE |
 		 SWAPPER_CTRL_XMSI_FE |
-		 SWAPPER_CTRL_XMSI_SE |
 		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
+	if (sp->intr_type == INTA)
+		val64 |= SWAPPER_CTRL_XMSI_SE;
 	writeq(val64, &bar0->swapper_ctrl);
 #endif
 	val64 = readq(&bar0->swapper_ctrl);
@@ -3028,6 +3042,201 @@
 	return SUCCESS;
 }
 
+int wait_for_msix_trans(nic_t *nic, int i)
+{
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
+	u64 val64;
+	int ret = 0, cnt = 0;
+
+	do {
+		val64 = readq(&bar0->xmsi_access);
+		if (!(val64 & BIT(15)))
+			break;
+		mdelay(1);
+		cnt++;
+	} while(cnt < 5);
+	if (cnt == 5) {
+		DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+void restore_xmsi_data(nic_t *nic)
+{
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
+	u64 val64;
+	int i;
+
+	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+		writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
+		writeq(nic->msix_info[i].data, &bar0->xmsi_data);
+		val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
+		writeq(val64, &bar0->xmsi_access);
+		if (wait_for_msix_trans(nic, i)) {
+			DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+			continue;
+		}
+	}
+}
+
+void store_xmsi_data(nic_t *nic)
+{
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
+	u64 val64, addr, data;
+	int i;
+
+	/* Store and display */
+	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+		val64 = (BIT(15) | vBIT(i, 26, 6));
+		writeq(val64, &bar0->xmsi_access);
+		if (wait_for_msix_trans(nic, i)) {
+			DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+			continue;
+		}
+		addr = readq(&bar0->xmsi_address);
+		data = readq(&bar0->xmsi_data);
+		if (addr && data) {
+			nic->msix_info[i].addr = addr;
+			nic->msix_info[i].data = data;
+		}
+	}
+}
+
+int s2io_enable_msi(nic_t *nic)
+{
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
+	u16 msi_ctrl, msg_val;
+	struct config_param *config = &nic->config;
+	struct net_device *dev = nic->dev;
+	u64 val64, tx_mat, rx_mat;
+	int i, err;
+
+	val64 = readq(&bar0->pic_control);
+	val64 &= ~BIT(1);
+	writeq(val64, &bar0->pic_control);
+
+	err = pci_enable_msi(nic->pdev);
+	if (err) {
+		DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
+			  nic->dev->name);
+		return err;
+	}
+
+	/*
+	 * Enable MSI and use MSI-1 in stead of the standard MSI-0
+	 * for interrupt handling.
+	 */
+	pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+	msg_val ^= 0x1;
+	pci_write_config_word(nic->pdev, 0x4c, msg_val);
+	pci_read_config_word(nic->pdev, 0x4c, &msg_val);
+
+	pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
+	msi_ctrl |= 0x10;
+	pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
+
+	/* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
+	tx_mat = readq(&bar0->tx_mat0_n[0]);
+	for (i=0; i<config->tx_fifo_num; i++) {
+		tx_mat |= TX_MAT_SET(i, 1);
+	}
+	writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+	rx_mat = readq(&bar0->rx_mat);
+	for (i=0; i<config->rx_ring_num; i++) {
+		rx_mat |= RX_MAT_SET(i, 1);
+	}
+	writeq(rx_mat, &bar0->rx_mat);
+
+	dev->irq = nic->pdev->irq;
+	return 0;
+}
+
+int s2io_enable_msi_x(nic_t *nic)
+{
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
+	u64 tx_mat, rx_mat;
+	u16 msi_control; /* Temp variable */
+	int ret, i, j, msix_indx = 1;
+
+	nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
+			       GFP_KERNEL);
+	if (nic->entries == NULL) {
+		DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+
+	nic->s2io_entries =
+		kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
+				   GFP_KERNEL);
+	if (nic->s2io_entries == NULL) {
+		DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
+		kfree(nic->entries);
+		return -ENOMEM;
+	}
+	memset(nic->s2io_entries, 0,
+	       MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+
+	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+		nic->entries[i].entry = i;
+		nic->s2io_entries[i].entry = i;
+		nic->s2io_entries[i].arg = NULL;
+		nic->s2io_entries[i].in_use = 0;
+	}
+
+	tx_mat = readq(&bar0->tx_mat0_n[0]);
+	for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
+		tx_mat |= TX_MAT_SET(i, msix_indx);
+		nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
+		nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
+		nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+	}
+	writeq(tx_mat, &bar0->tx_mat0_n[0]);
+
+	if (!nic->config.bimodal) {
+		rx_mat = readq(&bar0->rx_mat);
+		for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+			rx_mat |= RX_MAT_SET(j, msix_indx);
+			nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+			nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+			nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+		}
+		writeq(rx_mat, &bar0->rx_mat);
+	} else {
+		tx_mat = readq(&bar0->tx_mat0_n[7]);
+		for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
+			tx_mat |= TX_MAT_SET(i, msix_indx);
+			nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
+			nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
+			nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
+		}
+		writeq(tx_mat, &bar0->tx_mat0_n[7]);
+	}
+
+	ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+	if (ret) {
+		DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+		kfree(nic->entries);
+		kfree(nic->s2io_entries);
+		nic->entries = NULL;
+		nic->s2io_entries = NULL;
+		return -ENOMEM;
+	}
+
+	/*
+	 * To enable MSI-X, MSI also needs to be enabled, due to a bug
+	 * in the herc NIC. (Temp change, needs to be removed later)
+	 */
+	pci_read_config_word(nic->pdev, 0x42, &msi_control);
+	msi_control |= 0x1; /* Enable MSI */
+	pci_write_config_word(nic->pdev, 0x42, msi_control);
+
+	return 0;
+}
+
 /* ********************************************************* *
  * Functions defined below concern the OS part of the driver *
  * ********************************************************* */
@@ -3048,6 +3257,8 @@
 {
 	nic_t *sp = dev->priv;
 	int err = 0;
+	int i;
+	u16 msi_control; /* Temp variable */
 
 	/*
 	 * Make sure you have link off by default every time
@@ -3064,13 +3275,55 @@
 		goto hw_init_failed;
 	}
 
+	/* Store the values of the MSIX table in the nic_t structure */
+	store_xmsi_data(sp);
+
 	/* After proper initialization of H/W, register ISR */
-	err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
-			  sp->name, dev);
-	if (err) {
-		DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
-			  dev->name);
-		goto isr_registration_failed;
+	if (sp->intr_type == MSI) {
+		err = request_irq((int) sp->pdev->irq, s2io_msi_handle, 
+			SA_SHIRQ, sp->name, dev);
+		if (err) {
+			DBG_PRINT(ERR_DBG, "%s: MSI registration \
+failed\n", dev->name);
+			goto isr_registration_failed;
+		}
+	}
+	if (sp->intr_type == MSI_X) {
+		for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+			if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+				sprintf(sp->desc1, "%s:MSI-X-%d-TX",
+					dev->name, i);
+				err = request_irq(sp->entries[i].vector,
+					  s2io_msix_fifo_handle, 0, sp->desc1,
+					  sp->s2io_entries[i].arg);
+				DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, 
+							sp->msix_info[i].addr);
+			} else {
+				sprintf(sp->desc2, "%s:MSI-X-%d-RX",
+					dev->name, i);
+				err = request_irq(sp->entries[i].vector,
+					  s2io_msix_ring_handle, 0, sp->desc2,
+					  sp->s2io_entries[i].arg);
+				DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, 
+							sp->msix_info[i].addr);
+			}
+			if (err) {
+				DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
+failed\n", dev->name, i);
+				DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+				goto isr_registration_failed;
+			}
+			sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+		}
+	}
+	if (sp->intr_type == INTA) {
+		err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+				sp->name, dev);
+		if (err) {
+			DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+				  dev->name);
+			goto isr_registration_failed;
+		}
 	}
 
 	if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
@@ -3083,11 +3336,37 @@
 	return 0;
 
 setting_mac_address_failed:
-	free_irq(sp->pdev->irq, dev);
+	if (sp->intr_type != MSI_X)
+		free_irq(sp->pdev->irq, dev);
 isr_registration_failed:
 	del_timer_sync(&sp->alarm_timer);
+	if (sp->intr_type == MSI_X) {
+		if (sp->device_type == XFRAME_II_DEVICE) {
+			for (i=1; (sp->s2io_entries[i].in_use == 
+				MSIX_REGISTERED_SUCCESS); i++) {
+				int vector = sp->entries[i].vector;
+				void *arg = sp->s2io_entries[i].arg;
+
+				free_irq(vector, arg);
+			}
+			pci_disable_msix(sp->pdev);
+
+			/* Temp */
+			pci_read_config_word(sp->pdev, 0x42, &msi_control);
+			msi_control &= 0xFFFE; /* Disable MSI */
+			pci_write_config_word(sp->pdev, 0x42, msi_control);
+		}
+	}
+	else if (sp->intr_type == MSI)
+		pci_disable_msi(sp->pdev);
 	s2io_reset(sp);
 hw_init_failed:
+	if (sp->intr_type == MSI_X) {
+		if (sp->entries)
+			kfree(sp->entries);
+		if (sp->s2io_entries)
+			kfree(sp->s2io_entries);
+	}
 	return err;
 }
 
@@ -3107,12 +3386,35 @@
 int s2io_close(struct net_device *dev)
 {
 	nic_t *sp = dev->priv;
+	int i;
+	u16 msi_control;
+
 	flush_scheduled_work();
 	netif_stop_queue(dev);
 	/* Reset card, kill tasklet and free Tx and Rx buffers. */
 	s2io_card_down(sp);
 
-	free_irq(sp->pdev->irq, dev);
+	if (sp->intr_type == MSI_X) {
+		if (sp->device_type == XFRAME_II_DEVICE) {
+			for (i=1; (sp->s2io_entries[i].in_use == 
+					MSIX_REGISTERED_SUCCESS); i++) {
+				int vector = sp->entries[i].vector;
+				void *arg = sp->s2io_entries[i].arg;
+
+				free_irq(vector, arg);
+			}
+			pci_read_config_word(sp->pdev, 0x42, &msi_control);
+			msi_control &= 0xFFFE; /* Disable MSI */
+			pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+			pci_disable_msix(sp->pdev);
+		}
+	}
+	else {
+		free_irq(sp->pdev->irq, dev);
+		if (sp->intr_type == MSI)
+			pci_disable_msi(sp->pdev);
+	}	
 	sp->device_close_flag = TRUE;	/* Device is shut down. */
 	return 0;
 }
@@ -3278,6 +3580,104 @@
 	mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
+static irqreturn_t
+s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	nic_t *sp = dev->priv;
+	int i;
+	int ret;
+	mac_info_t *mac_control;
+	struct config_param *config;
+
+	atomic_inc(&sp->isr_cnt);
+	mac_control = &sp->mac_control;
+	config = &sp->config;
+	DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
+
+	/* If Intr is because of Rx Traffic */
+	for (i = 0; i < config->rx_ring_num; i++)
+		rx_intr_handler(&mac_control->rings[i]);
+
+	/* If Intr is because of Tx Traffic */
+	for (i = 0; i < config->tx_fifo_num; i++)
+		tx_intr_handler(&mac_control->fifos[i]);
+
+	/*
+	 * If the Rx buffer count is below the panic threshold then
+	 * reallocate the buffers from the interrupt handler itself,
+	 * else schedule a tasklet to reallocate the buffers.
+	 */
+	for (i = 0; i < config->rx_ring_num; i++) {
+		int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+		int level = rx_buffer_level(sp, rxb_size, i);
+
+		if ((level == PANIC) && (!TASKLET_IN_USE)) {
+			DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+			DBG_PRINT(INTR_DBG, "PANIC levels\n");
+			if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+				DBG_PRINT(ERR_DBG, "%s:Out of memory",
+					  dev->name);
+				DBG_PRINT(ERR_DBG, " in ISR!!\n");
+				clear_bit(0, (&sp->tasklet_status));
+				atomic_dec(&sp->isr_cnt);
+				return IRQ_HANDLED;
+			}
+			clear_bit(0, (&sp->tasklet_status));
+		} else if (level == LOW) {
+			tasklet_schedule(&sp->task);
+		}
+	}
+
+	atomic_dec(&sp->isr_cnt);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ring_info_t *ring = (ring_info_t *)dev_id;
+	nic_t *sp = ring->nic;
+	int rxb_size, level, rng_n;
+
+	atomic_inc(&sp->isr_cnt);
+	rx_intr_handler(ring);
+
+	rng_n = ring->ring_no;
+	rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+	level = rx_buffer_level(sp, rxb_size, rng_n);
+
+	if ((level == PANIC) && (!TASKLET_IN_USE)) {
+		int ret;
+		DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+		DBG_PRINT(INTR_DBG, "PANIC levels\n");
+		if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+			DBG_PRINT(ERR_DBG, "Out of memory in %s",
+				  __FUNCTION__);
+			clear_bit(0, (&sp->tasklet_status));
+			return IRQ_HANDLED;
+		}
+		clear_bit(0, (&sp->tasklet_status));
+	} else if (level == LOW) {
+		tasklet_schedule(&sp->task);
+	}
+	atomic_dec(&sp->isr_cnt);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+	fifo_info_t *fifo = (fifo_info_t *)dev_id;
+	nic_t *sp = fifo->nic;
+
+	atomic_inc(&sp->isr_cnt);
+	tx_intr_handler(fifo);
+	atomic_dec(&sp->isr_cnt);
+	return IRQ_HANDLED;
+}
+
 static void s2io_txpic_intr_handle(nic_t *sp)
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3778,11 +4178,10 @@
 {
 	nic_t *sp = dev->priv;
 
-	strncpy(info->driver, s2io_driver_name, sizeof(s2io_driver_name));
-	strncpy(info->version, s2io_driver_version,
-		sizeof(s2io_driver_version));
-	strncpy(info->fw_version, "", 32);
-	strncpy(info->bus_info, pci_name(sp->pdev), 32);
+	strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
+	strncpy(info->version, s2io_driver_version, sizeof(info->version));
+	strncpy(info->fw_version, "", sizeof(info->fw_version));
+	strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
 	info->regdump_len = XENA_REG_SPACE;
 	info->eedump_len = XENA_EEPROM_SPACE;
 	info->testinfo_len = S2IO_TEST_LEN;
@@ -3978,29 +4377,53 @@
  */
 
 #define S2IO_DEV_ID		5
-static int read_eeprom(nic_t * sp, int off, u32 * data)
+static int read_eeprom(nic_t * sp, int off, u64 * data)
 {
 	int ret = -1;
 	u32 exit_cnt = 0;
 	u64 val64;
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
-	val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-	    I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
-	    I2C_CONTROL_CNTL_START;
-	SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+	if (sp->device_type == XFRAME_I_DEVICE) {
+		val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+		    I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
+		    I2C_CONTROL_CNTL_START;
+		SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
 
-	while (exit_cnt < 5) {
-		val64 = readq(&bar0->i2c_control);
-		if (I2C_CONTROL_CNTL_END(val64)) {
-			*data = I2C_CONTROL_GET_DATA(val64);
-			ret = 0;
-			break;
+		while (exit_cnt < 5) {
+			val64 = readq(&bar0->i2c_control);
+			if (I2C_CONTROL_CNTL_END(val64)) {
+				*data = I2C_CONTROL_GET_DATA(val64);
+				ret = 0;
+				break;
+			}
+			msleep(50);
+			exit_cnt++;
 		}
-		msleep(50);
-		exit_cnt++;
 	}
 
+	if (sp->device_type == XFRAME_II_DEVICE) {
+		val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+			SPI_CONTROL_BYTECNT(0x3) | 
+			SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
+		SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+		val64 |= SPI_CONTROL_REQ;
+		SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+		while (exit_cnt < 5) {
+			val64 = readq(&bar0->spi_control);
+			if (val64 & SPI_CONTROL_NACK) {
+				ret = 1;
+				break;
+			} else if (val64 & SPI_CONTROL_DONE) {
+				*data = readq(&bar0->spi_data);
+				*data &= 0xffffff;
+				ret = 0;
+				break;
+			}
+			msleep(50);
+			exit_cnt++;
+		}
+	}
 	return ret;
 }
 
@@ -4019,28 +4442,53 @@
  *  0 on success, -1 on failure.
  */
 
-static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
+static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
 {
 	int exit_cnt = 0, ret = -1;
 	u64 val64;
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
-	val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-	    I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) |
-	    I2C_CONTROL_CNTL_START;
-	SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
+	if (sp->device_type == XFRAME_I_DEVICE) {
+		val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
+		    I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
+		    I2C_CONTROL_CNTL_START;
+		SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
 
-	while (exit_cnt < 5) {
-		val64 = readq(&bar0->i2c_control);
-		if (I2C_CONTROL_CNTL_END(val64)) {
-			if (!(val64 & I2C_CONTROL_NACK))
-				ret = 0;
-			break;
+		while (exit_cnt < 5) {
+			val64 = readq(&bar0->i2c_control);
+			if (I2C_CONTROL_CNTL_END(val64)) {
+				if (!(val64 & I2C_CONTROL_NACK))
+					ret = 0;
+				break;
+			}
+			msleep(50);
+			exit_cnt++;
 		}
-		msleep(50);
-		exit_cnt++;
 	}
 
+	if (sp->device_type == XFRAME_II_DEVICE) {
+		int write_cnt = (cnt == 8) ? 0 : cnt;
+		writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
+
+		val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
+			SPI_CONTROL_BYTECNT(write_cnt) | 
+			SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
+		SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+		val64 |= SPI_CONTROL_REQ;
+		SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
+		while (exit_cnt < 5) {
+			val64 = readq(&bar0->spi_control);
+			if (val64 & SPI_CONTROL_NACK) {
+				ret = 1;
+				break;
+			} else if (val64 & SPI_CONTROL_DONE) {
+				ret = 0;
+				break;
+			}
+			msleep(50);
+			exit_cnt++;
+		}
+	}
 	return ret;
 }
 
@@ -4060,7 +4508,8 @@
 static int s2io_ethtool_geeprom(struct net_device *dev,
 			 struct ethtool_eeprom *eeprom, u8 * data_buf)
 {
-	u32 data, i, valid;
+	u32 i, valid;
+	u64 data;
 	nic_t *sp = dev->priv;
 
 	eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -4098,7 +4547,7 @@
 				u8 * data_buf)
 {
 	int len = eeprom->len, cnt = 0;
-	u32 valid = 0, data;
+	u64 valid = 0, data;
 	nic_t *sp = dev->priv;
 
 	if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
@@ -4146,7 +4595,7 @@
 static int s2io_register_test(nic_t * sp, uint64_t * data)
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
-	u64 val64 = 0;
+	u64 val64 = 0, exp_val;
 	int fail = 0;
 
 	val64 = readq(&bar0->pif_rd_swapper_fb);
@@ -4162,7 +4611,11 @@
 	}
 
 	val64 = readq(&bar0->rx_queue_cfg);
-	if (val64 != 0x0808080808080808ULL) {
+	if (sp->device_type == XFRAME_II_DEVICE)
+		exp_val = 0x0404040404040404ULL;
+	else
+		exp_val = 0x0808080808080808ULL;
+	if (val64 != exp_val) {
 		fail = 1;
 		DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
 	}
@@ -4190,7 +4643,7 @@
 	}
 
 	*data = fail;
-	return 0;
+	return fail;
 }
 
 /**
@@ -4209,58 +4662,83 @@
 static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
 {
 	int fail = 0;
-	u32 ret_data;
+	u64 ret_data, org_4F0, org_7F0;
+	u8 saved_4F0 = 0, saved_7F0 = 0;
+	struct net_device *dev = sp->dev;
 
 	/* Test Write Error at offset 0 */
-	if (!write_eeprom(sp, 0, 0, 3))
-		fail = 1;
+	/* Note that SPI interface allows write access to all areas
+	 * of EEPROM. Hence doing all negative testing only for Xframe I.
+	 */
+	if (sp->device_type == XFRAME_I_DEVICE)
+		if (!write_eeprom(sp, 0, 0, 3))
+			fail = 1;
+
+	/* Save current values at offsets 0x4F0 and 0x7F0 */
+	if (!read_eeprom(sp, 0x4F0, &org_4F0))
+		saved_4F0 = 1;
+	if (!read_eeprom(sp, 0x7F0, &org_7F0))
+		saved_7F0 = 1;
 
 	/* Test Write at offset 4f0 */
-	if (write_eeprom(sp, 0x4F0, 0x01234567, 3))
+	if (write_eeprom(sp, 0x4F0, 0x012345, 3))
 		fail = 1;
 	if (read_eeprom(sp, 0x4F0, &ret_data))
 		fail = 1;
 
-	if (ret_data != 0x01234567)
+	if (ret_data != 0x012345) {
+		DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
 		fail = 1;
+	}
 
 	/* Reset the EEPROM data go FFFF */
-	write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3);
+	write_eeprom(sp, 0x4F0, 0xFFFFFF, 3);
 
 	/* Test Write Request Error at offset 0x7c */
-	if (!write_eeprom(sp, 0x07C, 0, 3))
+	if (sp->device_type == XFRAME_I_DEVICE)
+		if (!write_eeprom(sp, 0x07C, 0, 3))
+			fail = 1;
+
+	/* Test Write Request at offset 0x7f0 */
+	if (write_eeprom(sp, 0x7F0, 0x012345, 3))
+		fail = 1;
+	if (read_eeprom(sp, 0x7F0, &ret_data))
 		fail = 1;
 
-	/* Test Write Request at offset 0x7fc */
-	if (write_eeprom(sp, 0x7FC, 0x01234567, 3))
+	if (ret_data != 0x012345) {
+		DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
 		fail = 1;
-	if (read_eeprom(sp, 0x7FC, &ret_data))
-		fail = 1;
-
-	if (ret_data != 0x01234567)
-		fail = 1;
+	}
 
 	/* Reset the EEPROM data go FFFF */
-	write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3);
+	write_eeprom(sp, 0x7F0, 0xFFFFFF, 3);
 
-	/* Test Write Error at offset 0x80 */
-	if (!write_eeprom(sp, 0x080, 0, 3))
-		fail = 1;
+	if (sp->device_type == XFRAME_I_DEVICE) {
+		/* Test Write Error at offset 0x80 */
+		if (!write_eeprom(sp, 0x080, 0, 3))
+			fail = 1;
 
-	/* Test Write Error at offset 0xfc */
-	if (!write_eeprom(sp, 0x0FC, 0, 3))
-		fail = 1;
+		/* Test Write Error at offset 0xfc */
+		if (!write_eeprom(sp, 0x0FC, 0, 3))
+			fail = 1;
 
-	/* Test Write Error at offset 0x100 */
-	if (!write_eeprom(sp, 0x100, 0, 3))
-		fail = 1;
+		/* Test Write Error at offset 0x100 */
+		if (!write_eeprom(sp, 0x100, 0, 3))
+			fail = 1;
 
-	/* Test Write Error at offset 4ec */
-	if (!write_eeprom(sp, 0x4EC, 0, 3))
-		fail = 1;
+		/* Test Write Error at offset 4ec */
+		if (!write_eeprom(sp, 0x4EC, 0, 3))
+			fail = 1;
+	}
+
+	/* Restore values at offsets 0x4F0 and 0x7F0 */
+	if (saved_4F0)
+		write_eeprom(sp, 0x4F0, org_4F0, 3);
+	if (saved_7F0)
+		write_eeprom(sp, 0x7F0, org_7F0, 3);
 
 	*data = fail;
-	return 0;
+	return fail;
 }
 
 /**
@@ -4342,7 +4820,7 @@
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	u64 val64;
-	int cnt, iteration = 0, test_pass = 0;
+	int cnt, iteration = 0, test_fail = 0;
 
 	val64 = readq(&bar0->adapter_control);
 	val64 &= ~ADAPTER_ECC_EN;
@@ -4350,7 +4828,7 @@
 
 	val64 = readq(&bar0->mc_rldram_test_ctrl);
 	val64 |= MC_RLDRAM_TEST_MODE;
-	writeq(val64, &bar0->mc_rldram_test_ctrl);
+	SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
 	val64 = readq(&bar0->mc_rldram_mrs);
 	val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE;
@@ -4378,17 +4856,12 @@
 		}
 		writeq(val64, &bar0->mc_rldram_test_d2);
 
-		val64 = (u64) (0x0000003fffff0000ULL);
+		val64 = (u64) (0x0000003ffffe0100ULL);
 		writeq(val64, &bar0->mc_rldram_test_add);
 
-
-		val64 = MC_RLDRAM_TEST_MODE;
-		writeq(val64, &bar0->mc_rldram_test_ctrl);
-
-		val64 |=
-		    MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
-		    MC_RLDRAM_TEST_GO;
-		writeq(val64, &bar0->mc_rldram_test_ctrl);
+		val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
+		    	MC_RLDRAM_TEST_GO;
+		SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
 		for (cnt = 0; cnt < 5; cnt++) {
 			val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4400,11 +4873,8 @@
 		if (cnt == 5)
 			break;
 
-		val64 = MC_RLDRAM_TEST_MODE;
-		writeq(val64, &bar0->mc_rldram_test_ctrl);
-
-		val64 |= MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
-		writeq(val64, &bar0->mc_rldram_test_ctrl);
+		val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_GO;
+		SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
 		for (cnt = 0; cnt < 5; cnt++) {
 			val64 = readq(&bar0->mc_rldram_test_ctrl);
@@ -4417,18 +4887,18 @@
 			break;
 
 		val64 = readq(&bar0->mc_rldram_test_ctrl);
-		if (val64 & MC_RLDRAM_TEST_PASS)
-			test_pass = 1;
+		if (!(val64 & MC_RLDRAM_TEST_PASS))
+			test_fail = 1;
 
 		iteration++;
 	}
 
-	if (!test_pass)
-		*data = 1;
-	else
-		*data = 0;
+	*data = test_fail;
 
-	return 0;
+	/* Bring the adapter out of test mode */
+	SPECIAL_REG_WRITE(0, &bar0->mc_rldram_test_ctrl, LF);
+
+	return test_fail;
 }
 
 /**
@@ -4932,7 +5402,7 @@
 
 static int s2io_card_up(nic_t * sp)
 {
-	int i, ret;
+	int i, ret = 0;
 	mac_info_t *mac_control;
 	struct config_param *config;
 	struct net_device *dev = (struct net_device *) sp->dev;
@@ -4944,6 +5414,15 @@
 		return -ENODEV;
 	}
 
+	if (sp->intr_type == MSI)
+		ret = s2io_enable_msi(sp);
+	else if (sp->intr_type == MSI_X)
+		ret = s2io_enable_msi_x(sp);
+	if (ret) {
+		DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+		sp->intr_type = INTA;
+	}
+
 	/*
 	 * Initializing the Rx buffers. For now we are considering only 1
 	 * Rx ring and initializing buffers into 30 Rx blocks
@@ -5228,6 +5707,8 @@
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
 module_param(tx_fifo_num, int, 0);
 module_param(rx_ring_num, int, 0);
 module_param_array(tx_fifo_len, uint, NULL, 0);
@@ -5245,6 +5726,7 @@
 module_param(indicate_max_pkts, int, 0);
 #endif
 module_param(rxsync_frequency, int, 0);
+module_param(intr_type, int, 0);
 
 /**
  *  s2io_init_nic - Initialization of the adapter .
@@ -5274,9 +5756,16 @@
 	mac_info_t *mac_control;
 	struct config_param *config;
 	int mode;
+	u8 dev_intr_type = intr_type;
 
 #ifdef CONFIG_S2IO_NAPI
-	DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+	if (dev_intr_type != INTA) {
+		DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
+is enabled. Defaulting to INTA\n");
+		dev_intr_type = INTA;
+	}
+	else
+		DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
 #endif
 
 	if ((ret = pci_enable_device(pdev))) {
@@ -5303,10 +5792,35 @@
 		return -ENOMEM;
 	}
 
-	if (pci_request_regions(pdev, s2io_driver_name)) {
-		DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
-		    pci_disable_device(pdev);
-		return -ENODEV;
+	if ((dev_intr_type == MSI_X) && 
+			((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+			(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+		DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
+Defaulting to INTA\n");
+		dev_intr_type = INTA;
+	}
+	if (dev_intr_type != MSI_X) {
+		if (pci_request_regions(pdev, s2io_driver_name)) {
+			DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+			    pci_disable_device(pdev);
+			return -ENODEV;
+		}
+	}
+	else {
+		if (!(request_mem_region(pci_resource_start(pdev, 0),
+               	         pci_resource_len(pdev, 0), s2io_driver_name))) {
+			DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
+			pci_disable_device(pdev);
+			return -ENODEV;
+		}
+        	if (!(request_mem_region(pci_resource_start(pdev, 2),
+               	         pci_resource_len(pdev, 2), s2io_driver_name))) {
+			DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
+                	release_mem_region(pci_resource_start(pdev, 0),
+                                   pci_resource_len(pdev, 0));
+			pci_disable_device(pdev);
+			return -ENODEV;
+		}
 	}
 
 	dev = alloc_etherdev(sizeof(nic_t));
@@ -5329,6 +5843,7 @@
 	sp->pdev = pdev;
 	sp->high_dma_flag = dma_flag;
 	sp->device_enabled_once = FALSE;
+	sp->intr_type = dev_intr_type;
 
 	if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
 		(pdev->device == PCI_DEVICE_ID_HERC_UNI))
@@ -5336,6 +5851,7 @@
 	else
 		sp->device_type = XFRAME_I_DEVICE;
 
+		
 	/* Initialize some PCI/PCI-X fields of the NIC. */
 	s2io_init_pci(sp);
 
@@ -5571,12 +6087,23 @@
 	if (sp->device_type & XFRAME_II_DEVICE) {
 		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
 			  dev->name);
-		DBG_PRINT(ERR_DBG, "(rev %d), %s",
+		DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
 				get_xena_rev_id(sp->pdev),
 				s2io_driver_version);
 #ifdef CONFIG_2BUFF_MODE
 		DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
 #endif
+		switch(sp->intr_type) {
+			case INTA:
+				DBG_PRINT(ERR_DBG, ", Intr type INTA");
+				break;
+			case MSI:
+				DBG_PRINT(ERR_DBG, ", Intr type MSI");
+				break;
+			case MSI_X:
+				DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+				break;
+		}
 
 		DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
 		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -5595,12 +6122,23 @@
 	} else {
 		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
 			  dev->name);
-		DBG_PRINT(ERR_DBG, "(rev %d), %s",
+		DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
 					get_xena_rev_id(sp->pdev),
 					s2io_driver_version);
 #ifdef CONFIG_2BUFF_MODE
 		DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
 #endif
+		switch(sp->intr_type) {
+			case INTA:
+				DBG_PRINT(ERR_DBG, ", Intr type INTA");
+				break;
+			case MSI:
+				DBG_PRINT(ERR_DBG, ", Intr type MSI");
+				break;
+			case MSI_X:
+				DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+				break;
+		}
 		DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
 		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
 			  sp->def_mac_addr[0].mac_addr[0],
@@ -5644,7 +6182,14 @@
       mem_alloc_failed:
 	free_shared_mem(sp);
 	pci_disable_device(pdev);
-	pci_release_regions(pdev);
+	if (dev_intr_type != MSI_X)
+		pci_release_regions(pdev);
+	else {
+		release_mem_region(pci_resource_start(pdev, 0),
+			pci_resource_len(pdev, 0));
+		release_mem_region(pci_resource_start(pdev, 2),
+			pci_resource_len(pdev, 2));
+	}
 	pci_set_drvdata(pdev, NULL);
 	free_netdev(dev);
 
@@ -5678,7 +6223,14 @@
 	iounmap(sp->bar0);
 	iounmap(sp->bar1);
 	pci_disable_device(pdev);
-	pci_release_regions(pdev);
+	if (sp->intr_type != MSI_X)
+		pci_release_regions(pdev);
+	else {
+		release_mem_region(pci_resource_start(pdev, 0),
+			pci_resource_len(pdev, 0));
+		release_mem_region(pci_resource_start(pdev, 2),
+			pci_resource_len(pdev, 2));
+	}
 	pci_set_drvdata(pdev, NULL);
 	free_netdev(dev);
 }
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 89151cb..1cc24b5 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -652,6 +652,30 @@
 #define SMALL_BLK_CNT	30
 #define LARGE_BLK_CNT	100
 
+/*
+ * Structure to keep track of the MSI-X vectors and the corresponding
+ * argument registered against each vector
+ */
+#define MAX_REQUESTED_MSI_X	17
+struct s2io_msix_entry
+{
+	u16 vector;
+	u16 entry;
+	void *arg;
+
+	u8 type;
+#define	MSIX_FIFO_TYPE	1
+#define	MSIX_RING_TYPE	2
+
+	u8 in_use;
+#define MSIX_REGISTERED_SUCCESS	0xAA
+};
+
+struct msix_info_st {
+	u64 addr;
+	u64 data;
+};
+
 /* Structure representing one instance of the NIC */
 struct s2io_nic {
 #ifdef CONFIG_S2IO_NAPI
@@ -719,13 +743,8 @@
 	 *  a schedule task that will set the correct Link state once the
 	 *  NIC's PHY has stabilized after a state change.
 	 */
-#ifdef INIT_TQUEUE
-	struct tq_struct rst_timer_task;
-	struct tq_struct set_link_task;
-#else
 	struct work_struct rst_timer_task;
 	struct work_struct set_link_task;
-#endif
 
 	/* Flag that can be used to turn on or turn off the Rx checksum
 	 * offload feature.
@@ -748,10 +767,23 @@
 	atomic_t card_state;
 	volatile unsigned long link_state;
 	struct vlan_group *vlgrp;
+#define MSIX_FLG                0xA5
+	struct msix_entry *entries;
+	struct s2io_msix_entry *s2io_entries;
+	char desc1[35];
+	char desc2[35];
+
+	struct msix_info_st msix_info[0x3f];
+
 #define XFRAME_I_DEVICE		1
 #define XFRAME_II_DEVICE	2
 	u8 device_type;
 
+#define INTA	0
+#define MSI	1
+#define MSI_X	2
+	u8 intr_type;
+
 	spinlock_t	rx_lock;
 	atomic_t	isr_cnt;
 };
@@ -886,6 +918,13 @@
 static void s2io_init_pci(nic_t * sp);
 int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
 static void s2io_alarm_handle(unsigned long data);
+static int s2io_enable_msi(nic_t *nic);
+static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t
+s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
+int s2io_enable_msi_x(nic_t *nic);
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
 static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static struct ethtool_ops netdev_ethtool_ops;
@@ -894,4 +933,5 @@
 static void s2io_card_down(nic_t *nic);
 static int s2io_card_up(nic_t *nic);
 int get_xena_rev_id(struct pci_dev *pdev);
+void restore_xmsi_data(nic_t *nic);
 #endif				/* _S2IO_H */
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index fd01670..110e777 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -997,10 +997,7 @@
 
         if (dev) {
                 unregister_netdev(dev);
-
-		if (dev->priv)
-			kfree(dev->priv);
-
+		kfree(dev->priv);
                 free_netdev(dev);
                 pci_release_regions(pdev);
                 pci_disable_device(pdev);
@@ -1096,8 +1093,7 @@
 	return 0;
 
  out:
-	if (dev->priv)
-		kfree(dev->priv);
+	kfree(dev->priv);
 	return ret;
 }
 
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 7abd55a..aa4ca18 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -10,7 +10,7 @@
  * 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.
@@ -118,8 +118,6 @@
  ********************************************************************* */
 
 
-typedef unsigned long sbmac_port_t;
-
 typedef enum { sbmac_speed_auto, sbmac_speed_10,
 	       sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
 
@@ -129,7 +127,7 @@
 typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
 	       sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
 
-typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on, 
+typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
 	       sbmac_state_broken } sbmac_state_t;
 
 
@@ -144,17 +142,13 @@
 
 #define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
 
-#define SBMAC_READCSR(t)	__raw_readq((unsigned long)t)
-#define SBMAC_WRITECSR(t,v)	__raw_writeq(v, (unsigned long)t)
- 
-
 #define SBMAC_MAX_TXDESCR	32
 #define SBMAC_MAX_RXDESCR	32
 
 #define ETHER_ALIGN	2
 #define ETHER_ADDR_LEN	6
-#define ENET_PACKET_SIZE	1518 
-/*#define ENET_PACKET_SIZE	9216 */ 
+#define ENET_PACKET_SIZE	1518
+/*#define ENET_PACKET_SIZE	9216 */
 
 /**********************************************************************
  *  DMA Descriptor structure
@@ -172,12 +166,12 @@
  ********************************************************************* */
 
 typedef struct sbmacdma_s {
-	
-	/* 
+
+	/*
 	 * This stuff is used to identify the channel and the registers
 	 * associated with it.
 	 */
-	
+
 	struct sbmac_softc *sbdma_eth;	        /* back pointer to associated MAC */
 	int              sbdma_channel;	/* channel number */
 	int		 sbdma_txdir;       /* direction (1=transmit) */
@@ -187,21 +181,21 @@
 	int		 sbdma_int_timeout; /* # usec rx/tx interrupt */
 #endif
 
-	sbmac_port_t     sbdma_config0;	/* DMA config register 0 */
-	sbmac_port_t     sbdma_config1;	/* DMA config register 1 */
-	sbmac_port_t     sbdma_dscrbase;	/* Descriptor base address */
-	sbmac_port_t     sbdma_dscrcnt;     /* Descriptor count register */
-	sbmac_port_t     sbdma_curdscr;	/* current descriptor address */
-	
+	volatile void __iomem *sbdma_config0;	/* DMA config register 0 */
+	volatile void __iomem *sbdma_config1;	/* DMA config register 1 */
+	volatile void __iomem *sbdma_dscrbase;	/* Descriptor base address */
+	volatile void __iomem *sbdma_dscrcnt;     /* Descriptor count register */
+	volatile void __iomem *sbdma_curdscr;	/* current descriptor address */
+
 	/*
 	 * This stuff is for maintenance of the ring
 	 */
-	
+
 	sbdmadscr_t     *sbdma_dscrtable;	/* base of descriptor table */
 	sbdmadscr_t     *sbdma_dscrtable_end; /* end of descriptor table */
-	
+
 	struct sk_buff **sbdma_ctxtable;    /* context table, one per descr */
-	
+
 	paddr_t          sbdma_dscrtable_phys; /* and also the phys addr */
 	sbdmadscr_t     *sbdma_addptr;	/* next dscr for sw to add */
 	sbdmadscr_t     *sbdma_remptr;	/* next dscr for sw to remove */
@@ -213,15 +207,15 @@
  ********************************************************************* */
 
 struct sbmac_softc {
-	
+
 	/*
 	 * Linux-specific things
 	 */
-	
+
 	struct net_device *sbm_dev;		/* pointer to linux device */
 	spinlock_t sbm_lock;		/* spin lock */
 	struct timer_list sbm_timer;     	/* for monitoring MII */
-	struct net_device_stats sbm_stats; 
+	struct net_device_stats sbm_stats;
 	int sbm_devflags;			/* current device flags */
 
 	int	     sbm_phy_oldbmsr;
@@ -229,31 +223,31 @@
 	int	     sbm_phy_oldk1stsr;
 	int	     sbm_phy_oldlinkstat;
 	int sbm_buffersize;
-	
+
 	unsigned char sbm_phys[2];
-	
+
 	/*
 	 * Controller-specific things
 	 */
-	
-	unsigned long	sbm_base;          /* MAC's base address */
+
+	volatile void __iomem *sbm_base;          /* MAC's base address */
 	sbmac_state_t    sbm_state;         /* current state */
-	
-	sbmac_port_t     sbm_macenable;	/* MAC Enable Register */
-	sbmac_port_t     sbm_maccfg;	/* MAC Configuration Register */
-	sbmac_port_t     sbm_fifocfg;	/* FIFO configuration register */
-	sbmac_port_t     sbm_framecfg;	/* Frame configuration register */
-	sbmac_port_t     sbm_rxfilter;	/* receive filter register */
-	sbmac_port_t     sbm_isr;		/* Interrupt status register */
-	sbmac_port_t     sbm_imr;		/* Interrupt mask register */
-	sbmac_port_t     sbm_mdio;		/* MDIO register */
-	
+
+	volatile void __iomem	*sbm_macenable;	/* MAC Enable Register */
+	volatile void __iomem	*sbm_maccfg;	/* MAC Configuration Register */
+	volatile void __iomem	*sbm_fifocfg;	/* FIFO configuration register */
+	volatile void __iomem	*sbm_framecfg;	/* Frame configuration register */
+	volatile void __iomem	*sbm_rxfilter;	/* receive filter register */
+	volatile void __iomem	*sbm_isr;	/* Interrupt status register */
+	volatile void __iomem	*sbm_imr;	/* Interrupt mask register */
+	volatile void __iomem	*sbm_mdio;	/* MDIO register */
+
 	sbmac_speed_t    sbm_speed;		/* current speed */
 	sbmac_duplex_t   sbm_duplex;	/* current duplex */
 	sbmac_fc_t       sbm_fc;		/* current flow control setting */
-	
+
 	unsigned char    sbm_hwaddr[ETHER_ADDR_LEN];
-	
+
 	sbmacdma_t       sbm_txdma;		/* for now, only use channel 0 */
 	sbmacdma_t       sbm_rxdma;
 	int              rx_hw_checksum;
@@ -302,6 +296,7 @@
 static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int sbmac_close(struct net_device *dev);
 static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
+static int sbmac_mii_probe(struct net_device *dev);
 
 static void sbmac_mii_sync(struct sbmac_softc *s);
 static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);
@@ -439,6 +434,9 @@
 
 #define	MII_BMCR	0x00 	/* Basic mode control register (rw) */
 #define	MII_BMSR	0x01	/* Basic mode status register (ro) */
+#define	MII_PHYIDR1	0x02
+#define	MII_PHYIDR2	0x03
+
 #define MII_K1STSR	0x0A	/* 1K Status Register (ro) */
 #define	MII_ANLPAR	0x05	/* Autonegotiation lnk partner abilities (rw) */
 
@@ -450,13 +448,13 @@
 
 /**********************************************************************
  *  SBMAC_MII_SYNC(s)
- *  
+ *
  *  Synchronize with the MII - send a pattern of bits to the MII
  *  that will guarantee that it is ready to accept a command.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -467,25 +465,25 @@
 	uint64_t bits;
 	int mac_mdio_genc;
 
-	mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-	
+	mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
 	bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
-	
-	SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-	
+
+	__raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
 	for (cnt = 0; cnt < 32; cnt++) {
-		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
-		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+		__raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+		__raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
 	}
 }
 
 /**********************************************************************
  *  SBMAC_MII_SENDDATA(s,data,bitcnt)
- *  
+ *
  *  Send some bits to the MII.  The bits to be sent are right-
  *  justified in the 'data' parameter.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
  *  	   data - data to send
  *  	   bitcnt - number of bits to send
@@ -498,20 +496,20 @@
 	unsigned int curmask;
 	int mac_mdio_genc;
 
-	mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-	
+	mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
 	bits = M_MAC_MDIO_DIR_OUTPUT;
-	SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-	
+	__raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+
 	curmask = 1 << (bitcnt - 1);
-	
+
 	for (i = 0; i < bitcnt; i++) {
 		if (data & curmask)
 			bits |= M_MAC_MDIO_OUT;
 		else bits &= ~M_MAC_MDIO_OUT;
-		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
-		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc);
-		SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc);
+		__raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
+		__raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+		__raw_writeq(bits | mac_mdio_genc, s->sbm_mdio);
 		curmask >>= 1;
 	}
 }
@@ -520,14 +518,14 @@
 
 /**********************************************************************
  *  SBMAC_MII_READ(s,phyaddr,regidx)
- *  
+ *
  *  Read a PHY register.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
  *  	   phyaddr - PHY's address
  *  	   regidx = index of register to read
- *  	   
+ *
  *  Return value:
  *  	   value read, or 0 if an error occurred.
  ********************************************************************* */
@@ -543,9 +541,9 @@
 	 * Synchronize ourselves so that the PHY knows the next
 	 * thing coming down is a command
 	 */
-	
+
 	sbmac_mii_sync(s);
-	
+
 	/*
 	 * Send the data to the PHY.  The sequence is
 	 * a "start" command (2 bits)
@@ -553,59 +551,55 @@
 	 * the PHY addr (5 bits)
 	 * the register index (5 bits)
 	 */
-	
+
 	sbmac_mii_senddata(s,MII_COMMAND_START, 2);
 	sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
 	sbmac_mii_senddata(s,phyaddr, 5);
 	sbmac_mii_senddata(s,regidx, 5);
-	
-	mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
-	
-	/* 
+
+	mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
+
+	/*
 	 * Switch the port around without a clock transition.
 	 */
-	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-	
+	__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
 	/*
 	 * Send out a clock pulse to signal we want the status
 	 */
-	
-	SBMAC_WRITECSR(s->sbm_mdio,
-		       M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
-	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-	
-	/* 
+
+	__raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+	__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
+	/*
 	 * If an error occurred, the PHY will signal '1' back
 	 */
-	error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN;
-	
-	/* 
+	error = __raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN;
+
+	/*
 	 * Issue an 'idle' clock pulse, but keep the direction
 	 * the same.
 	 */
-	SBMAC_WRITECSR(s->sbm_mdio,
-		       M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
-	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
-	
+	__raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+	__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
+
 	regval = 0;
-	
+
 	for (idx = 0; idx < 16; idx++) {
 		regval <<= 1;
-		
+
 		if (error == 0) {
-			if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
+			if (__raw_readq(s->sbm_mdio) & M_MAC_MDIO_IN)
 				regval |= 1;
 		}
-		
-		SBMAC_WRITECSR(s->sbm_mdio,
-			       M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc);
-		SBMAC_WRITECSR(s->sbm_mdio,
-			       M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
+
+		__raw_writeq(M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc, s->sbm_mdio);
+		__raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, s->sbm_mdio);
 	}
-	
+
 	/* Switch back to output */
-	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
-	
+	__raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
+
 	if (error == 0)
 		return regval;
 	return 0;
@@ -614,15 +608,15 @@
 
 /**********************************************************************
  *  SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
- *  
+ *
  *  Write a value to a PHY register.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
  *  	   phyaddr - PHY to use
  *  	   regidx - register within the PHY
  *  	   regval - data to write to register
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -633,7 +627,7 @@
 	int mac_mdio_genc;
 
 	sbmac_mii_sync(s);
-	
+
 	sbmac_mii_senddata(s,MII_COMMAND_START,2);
 	sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
 	sbmac_mii_senddata(s,phyaddr, 5);
@@ -641,27 +635,27 @@
 	sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
 	sbmac_mii_senddata(s,regval,16);
 
-	mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC;
+	mac_mdio_genc = __raw_readq(s->sbm_mdio) & M_MAC_GENC;
 
-	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
+	__raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, s->sbm_mdio);
 }
 
 
 
 /**********************************************************************
  *  SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
- *  
+ *
  *  Initialize a DMA channel context.  Since there are potentially
  *  eight DMA channels per MAC, it's nice to do this in a standard
- *  way.  
- *  
- *  Input parameters: 
+ *  way.
+ *
+ *  Input parameters:
  *  	   d - sbmacdma_t structure (DMA channel context)
  *  	   s - sbmac_softc structure (pointer to a MAC)
  *  	   chan - channel number (0..1 right now)
  *  	   txrx - Identifies DMA_TX or DMA_RX for channel direction
  *      maxdescr - number of descriptors
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -672,101 +666,87 @@
 			  int txrx,
 			  int maxdescr)
 {
-	/* 
-	 * Save away interesting stuff in the structure 
+	/*
+	 * Save away interesting stuff in the structure
 	 */
-	
+
 	d->sbdma_eth       = s;
 	d->sbdma_channel   = chan;
 	d->sbdma_txdir     = txrx;
-	
+
 #if 0
 	/* RMON clearing */
 	s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
 #endif
 
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
-	SBMAC_WRITECSR(IOADDR(
-	A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)));
+	__raw_writeq(0, IOADDR(A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)));
 
-	/* 
-	 * initialize register pointers 
+	/*
+	 * initialize register pointers
 	 */
-	
-	d->sbdma_config0 = 
+
+	d->sbdma_config0 =
 		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
-	d->sbdma_config1 = 
+	d->sbdma_config1 =
 		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
-	d->sbdma_dscrbase = 
+	d->sbdma_dscrbase =
 		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
-	d->sbdma_dscrcnt = 
+	d->sbdma_dscrcnt =
 		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
-	d->sbdma_curdscr = 	
+	d->sbdma_curdscr =
 		s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
-	
+
 	/*
 	 * Allocate memory for the ring
 	 */
-	
+
 	d->sbdma_maxdescr = maxdescr;
-	
-	d->sbdma_dscrtable = (sbdmadscr_t *) 
-		kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
-	
+
+	d->sbdma_dscrtable = (sbdmadscr_t *)
+		kmalloc((d->sbdma_maxdescr+1)*sizeof(sbdmadscr_t), GFP_KERNEL);
+
+	/*
+	 * The descriptor table must be aligned to at least 16 bytes or the
+	 * MAC will corrupt it.
+	 */
+	d->sbdma_dscrtable = (sbdmadscr_t *)
+		ALIGN((unsigned long)d->sbdma_dscrtable, sizeof(sbdmadscr_t));
+
 	memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
-	
+
 	d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
-	
+
 	d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
-	
+
 	/*
 	 * And context table
 	 */
-	
-	d->sbdma_ctxtable = (struct sk_buff **) 
+
+	d->sbdma_ctxtable = (struct sk_buff **)
 		kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
-	
+
 	memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
-	
+
 #ifdef CONFIG_SBMAC_COALESCE
 	/*
 	 * Setup Rx/Tx DMA coalescing defaults
@@ -777,7 +757,7 @@
 	} else {
 		d->sbdma_int_pktcnt = 1;
 	}
-	
+
 	if ( int_timeout ) {
 		d->sbdma_int_timeout = int_timeout;
 	} else {
@@ -789,13 +769,13 @@
 
 /**********************************************************************
  *  SBDMA_CHANNEL_START(d)
- *  
+ *
  *  Initialize the hardware registers for a DMA channel.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   d - DMA channel to init (context must be previously init'd
  *         rxtx - DMA_RX or DMA_TX depending on what type of channel
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -805,24 +785,21 @@
 	/*
 	 * Turn on the DMA channel
 	 */
-	
+
 #ifdef CONFIG_SBMAC_COALESCE
-	SBMAC_WRITECSR(d->sbdma_config1,
-		       V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
-		       0);
-	SBMAC_WRITECSR(d->sbdma_config0,
-		       M_DMA_EOP_INT_EN |
+	__raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
+		       0, d->sbdma_config1);
+	__raw_writeq(M_DMA_EOP_INT_EN |
 		       V_DMA_RINGSZ(d->sbdma_maxdescr) |
 		       V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
-		       0);
+		       0, d->sbdma_config0);
 #else
-	SBMAC_WRITECSR(d->sbdma_config1,0);
-	SBMAC_WRITECSR(d->sbdma_config0,
-		       V_DMA_RINGSZ(d->sbdma_maxdescr) |
-		       0);
+	__raw_writeq(0, d->sbdma_config1);
+	__raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
+		       0, d->sbdma_config0);
 #endif
 
-	SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
+	__raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
 
 	/*
 	 * Initialize ring pointers
@@ -834,12 +811,12 @@
 
 /**********************************************************************
  *  SBDMA_CHANNEL_STOP(d)
- *  
+ *
  *  Initialize the hardware registers for a DMA channel.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   d - DMA channel to init (context must be previously init'd
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -849,44 +826,44 @@
 	/*
 	 * Turn off the DMA channel
 	 */
-	
-	SBMAC_WRITECSR(d->sbdma_config1,0);
-	
-	SBMAC_WRITECSR(d->sbdma_dscrbase,0);
-	
-	SBMAC_WRITECSR(d->sbdma_config0,0);
-	
+
+	__raw_writeq(0, d->sbdma_config1);
+
+	__raw_writeq(0, d->sbdma_dscrbase);
+
+	__raw_writeq(0, d->sbdma_config0);
+
 	/*
 	 * Zero ring pointers
 	 */
-	
-	d->sbdma_addptr = 0;
-	d->sbdma_remptr = 0;
+
+	d->sbdma_addptr = NULL;
+	d->sbdma_remptr = NULL;
 }
 
 static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
 {
 	unsigned long addr;
 	unsigned long newaddr;
-	
+
 	addr = (unsigned long) skb->data;
-	
+
 	newaddr = (addr + power2 - 1) & ~(power2 - 1);
-	
+
 	skb_reserve(skb,newaddr-addr+offset);
 }
 
 
 /**********************************************************************
  *  SBDMA_ADD_RCVBUFFER(d,sb)
- *  
+ *
  *  Add a buffer to the specified DMA channel.   For receive channels,
  *  this queues a buffer for inbound packets.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   d - DMA channel descriptor
  * 	   sb - sk_buff to add, or NULL if we should allocate one
- *  	   
+ *
  *  Return value:
  *  	   0 if buffer could not be added (ring is full)
  *  	   1 if buffer added successfully
@@ -899,24 +876,24 @@
 	sbdmadscr_t *nextdsc;
 	struct sk_buff *sb_new = NULL;
 	int pktsize = ENET_PACKET_SIZE;
-	
+
 	/* get pointer to our current place in the ring */
-	
+
 	dsc = d->sbdma_addptr;
 	nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-	
+
 	/*
 	 * figure out if the ring is full - if the next descriptor
 	 * is the same as the one that we're going to remove from
 	 * the ring, the ring is full
 	 */
-	
+
 	if (nextdsc == d->sbdma_remptr) {
 		return -ENOSPC;
 	}
 
-	/* 
-	 * Allocate a sk_buff if we don't already have one.  
+	/*
+	 * Allocate a sk_buff if we don't already have one.
 	 * If we do have an sk_buff, reset it so that it's empty.
 	 *
 	 * Note: sk_buffs don't seem to be guaranteed to have any sort
@@ -925,7 +902,7 @@
 	 *
 	 *    1. the data does not start in the middle of a cache line.
 	 *    2. The data does not end in the middle of a cache line
-	 *    3. The buffer can be aligned such that the IP addresses are 
+	 *    3. The buffer can be aligned such that the IP addresses are
 	 *       naturally aligned.
 	 *
 	 *  Remember, the SOCs MAC writes whole cache lines at a time,
@@ -933,7 +910,7 @@
 	 *  data portion starts in the middle of a cache line, the SOC
 	 *  DMA will trash the beginning (and ending) portions.
 	 */
-	
+
 	if (sb == NULL) {
 		sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
 		if (sb_new == NULL) {
@@ -949,23 +926,22 @@
 	}
 	else {
 		sb_new = sb;
-		/* 
+		/*
 		 * nothing special to reinit buffer, it's already aligned
 		 * and sb->data already points to a good place.
 		 */
 	}
-	
+
 	/*
-	 * fill in the descriptor 
+	 * fill in the descriptor
 	 */
-	
+
 #ifdef CONFIG_SBMAC_COALESCE
 	/*
 	 * Do not interrupt per DMA transfer.
 	 */
 	dsc->dscr_a = virt_to_phys(sb_new->data) |
-		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
-		0;
+		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0;
 #else
 	dsc->dscr_a = virt_to_phys(sb_new->data) |
 		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
@@ -974,38 +950,38 @@
 
 	/* receiving: no options */
 	dsc->dscr_b = 0;
-	
+
 	/*
-	 * fill in the context 
+	 * fill in the context
 	 */
-	
+
 	d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
-	
-	/* 
-	 * point at next packet 
+
+	/*
+	 * point at next packet
 	 */
-	
+
 	d->sbdma_addptr = nextdsc;
-	
-	/* 
+
+	/*
 	 * Give the buffer to the DMA engine.
 	 */
-	
-	SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-	
+
+	__raw_writeq(1, d->sbdma_dscrcnt);
+
 	return 0;					/* we did it */
 }
 
 /**********************************************************************
  *  SBDMA_ADD_TXBUFFER(d,sb)
- *  
+ *
  *  Add a transmit buffer to the specified DMA channel, causing a
  *  transmit to start.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   d - DMA channel descriptor
  * 	   sb - sk_buff to add
- *  	   
+ *
  *  Return value:
  *  	   0 transmit queued successfully
  *  	   otherwise error code
@@ -1019,70 +995,70 @@
 	uint64_t phys;
 	uint64_t ncb;
 	int length;
-	
+
 	/* get pointer to our current place in the ring */
-	
+
 	dsc = d->sbdma_addptr;
 	nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
-	
+
 	/*
 	 * figure out if the ring is full - if the next descriptor
 	 * is the same as the one that we're going to remove from
 	 * the ring, the ring is full
 	 */
-	
+
 	if (nextdsc == d->sbdma_remptr) {
 		return -ENOSPC;
 	}
-	
+
 	/*
 	 * Under Linux, it's not necessary to copy/coalesce buffers
 	 * like it is on NetBSD.  We think they're all contiguous,
 	 * but that may not be true for GBE.
 	 */
-	
+
 	length = sb->len;
-	
+
 	/*
 	 * fill in the descriptor.  Note that the number of cache
 	 * blocks in the descriptor is the number of blocks
 	 * *spanned*, so we need to add in the offset (if any)
 	 * while doing the calculation.
 	 */
-	
+
 	phys = virt_to_phys(sb->data);
 	ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
 
-	dsc->dscr_a = phys | 
+	dsc->dscr_a = phys |
 		V_DMA_DSCRA_A_SIZE(ncb) |
 #ifndef CONFIG_SBMAC_COALESCE
 		M_DMA_DSCRA_INTERRUPT |
 #endif
 		M_DMA_ETHTX_SOP;
-	
+
 	/* transmitting: set outbound options and length */
 
 	dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
 		V_DMA_DSCRB_PKT_SIZE(length);
-	
+
 	/*
-	 * fill in the context 
+	 * fill in the context
 	 */
-	
+
 	d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
-	
-	/* 
-	 * point at next packet 
+
+	/*
+	 * point at next packet
 	 */
-	
+
 	d->sbdma_addptr = nextdsc;
-	
-	/* 
+
+	/*
 	 * Give the buffer to the DMA engine.
 	 */
-	
-	SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
-	
+
+	__raw_writeq(1, d->sbdma_dscrcnt);
+
 	return 0;					/* we did it */
 }
 
@@ -1091,12 +1067,12 @@
 
 /**********************************************************************
  *  SBDMA_EMPTYRING(d)
- *  
+ *
  *  Free all allocated sk_buffs on the specified DMA channel;
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   d  - DMA channel
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1105,7 +1081,7 @@
 {
 	int idx;
 	struct sk_buff *sb;
-	
+
 	for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
 		sb = d->sbdma_ctxtable[idx];
 		if (sb) {
@@ -1118,13 +1094,13 @@
 
 /**********************************************************************
  *  SBDMA_FILLRING(d)
- *  
+ *
  *  Fill the specified DMA channel (must be receive channel)
  *  with sk_buffs
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   d - DMA channel
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1132,7 +1108,7 @@
 static void sbdma_fillring(sbmacdma_t *d)
 {
 	int idx;
-	
+
 	for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
 		if (sbdma_add_rcvbuffer(d,NULL) != 0)
 			break;
@@ -1142,16 +1118,16 @@
 
 /**********************************************************************
  *  SBDMA_RX_PROCESS(sc,d)
- *  
- *  Process "completed" receive buffers on the specified DMA channel.  
- *  Note that this isn't really ideal for priority channels, since
- *  it processes all of the packets on a given channel before 
- *  returning. 
  *
- *  Input parameters: 
+ *  Process "completed" receive buffers on the specified DMA channel.
+ *  Note that this isn't really ideal for priority channels, since
+ *  it processes all of the packets on a given channel before
+ *  returning.
+ *
+ *  Input parameters:
  *	   sc - softc structure
  *  	   d - DMA channel context
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1163,56 +1139,56 @@
 	sbdmadscr_t *dsc;
 	struct sk_buff *sb;
 	int len;
-	
+
 	for (;;) {
-		/* 
+		/*
 		 * figure out where we are (as an index) and where
 		 * the hardware is (also as an index)
 		 *
-		 * This could be done faster if (for example) the 
+		 * This could be done faster if (for example) the
 		 * descriptor table was page-aligned and contiguous in
 		 * both virtual and physical memory -- you could then
 		 * just compare the low-order bits of the virtual address
 		 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
 		 */
-		
+
 		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
-		hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+		hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
 				d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
-		
+
 		/*
 		 * If they're the same, that means we've processed all
 		 * of the descriptors up to (but not including) the one that
 		 * the hardware is working on right now.
 		 */
-		
+
 		if (curidx == hwidx)
 			break;
-		
+
 		/*
 		 * Otherwise, get the packet's sk_buff ptr back
 		 */
-		
+
 		dsc = &(d->sbdma_dscrtable[curidx]);
 		sb = d->sbdma_ctxtable[curidx];
 		d->sbdma_ctxtable[curidx] = NULL;
-		
+
 		len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
-		
+
 		/*
 		 * Check packet status.  If good, process it.
 		 * If not, silently drop it and put it back on the
 		 * receive ring.
 		 */
-		
+
 		if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
-			
+
 			/*
 			 * Add a new buffer to replace the old one.  If we fail
 			 * to allocate a buffer, we're going to drop this
 			 * packet and put it right back on the receive ring.
 			 */
-			
+
 			if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
 				sc->sbm_stats.rx_dropped++;
 				sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
@@ -1221,7 +1197,7 @@
 				 * Set length into the packet
 				 */
 				skb_put(sb,len);
-				
+
 				/*
 				 * Buffer has been replaced on the
 				 * receive ring.  Pass the buffer to
@@ -1240,7 +1216,7 @@
 						sb->ip_summed = CHECKSUM_NONE;
 					}
 				}
-				
+
 				netif_rx(sb);
 			}
 		} else {
@@ -1251,14 +1227,14 @@
 			sc->sbm_stats.rx_errors++;
 			sbdma_add_rcvbuffer(d,sb);
 		}
-		
-		
-		/* 
+
+
+		/*
 		 * .. and advance to the next buffer.
 		 */
-		
+
 		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-		
+
 	}
 }
 
@@ -1266,17 +1242,17 @@
 
 /**********************************************************************
  *  SBDMA_TX_PROCESS(sc,d)
- *  
- *  Process "completed" transmit buffers on the specified DMA channel.  
+ *
+ *  Process "completed" transmit buffers on the specified DMA channel.
  *  This is normally called within the interrupt service routine.
  *  Note that this isn't really ideal for priority channels, since
- *  it processes all of the packets on a given channel before 
- *  returning. 
+ *  it processes all of the packets on a given channel before
+ *  returning.
  *
- *  Input parameters: 
+ *  Input parameters:
  *      sc - softc structure
  *  	   d - DMA channel context
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1290,21 +1266,21 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&(sc->sbm_lock), flags);
-	
+
 	for (;;) {
-		/* 
+		/*
 		 * figure out where we are (as an index) and where
 		 * the hardware is (also as an index)
 		 *
-		 * This could be done faster if (for example) the 
+		 * This could be done faster if (for example) the
 		 * descriptor table was page-aligned and contiguous in
 		 * both virtual and physical memory -- you could then
 		 * just compare the low-order bits of the virtual address
 		 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
 		 */
-		
+
 		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
-		hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+		hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
 				d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
 
 		/*
@@ -1312,75 +1288,75 @@
 		 * of the descriptors up to (but not including) the one that
 		 * the hardware is working on right now.
 		 */
-		
+
 		if (curidx == hwidx)
 			break;
-		
+
 		/*
 		 * Otherwise, get the packet's sk_buff ptr back
 		 */
-		
+
 		dsc = &(d->sbdma_dscrtable[curidx]);
 		sb = d->sbdma_ctxtable[curidx];
 		d->sbdma_ctxtable[curidx] = NULL;
-		
+
 		/*
 		 * Stats
 		 */
-		
+
 		sc->sbm_stats.tx_bytes += sb->len;
 		sc->sbm_stats.tx_packets++;
-		
+
 		/*
 		 * for transmits, we just free buffers.
 		 */
-		
+
 		dev_kfree_skb_irq(sb);
-		
-		/* 
+
+		/*
 		 * .. and advance to the next buffer.
 		 */
 
 		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-		
+
 	}
-	
+
 	/*
 	 * Decide if we should wake up the protocol or not.
 	 * Other drivers seem to do this when we reach a low
 	 * watermark on the transmit queue.
 	 */
-	
+
 	netif_wake_queue(d->sbdma_eth->sbm_dev);
-	
+
 	spin_unlock_irqrestore(&(sc->sbm_lock), flags);
-	
+
 }
 
 
 
 /**********************************************************************
  *  SBMAC_INITCTX(s)
- *  
+ *
  *  Initialize an Ethernet context structure - this is called
  *  once per MAC on the 1250.  Memory is allocated here, so don't
  *  call it again from inside the ioctl routines that bring the
  *  interface up/down
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac context structure
- *  	   
+ *
  *  Return value:
  *  	   0
  ********************************************************************* */
 
 static int sbmac_initctx(struct sbmac_softc *s)
 {
-	
-	/* 
-	 * figure out the addresses of some ports 
+
+	/*
+	 * figure out the addresses of some ports
 	 */
-	
+
 	s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
 	s->sbm_maccfg    = s->sbm_base + R_MAC_CFG;
 	s->sbm_fifocfg   = s->sbm_base + R_MAC_THRSH_CFG;
@@ -1397,29 +1373,29 @@
 	s->sbm_phy_oldanlpar = 0;
 	s->sbm_phy_oldk1stsr = 0;
 	s->sbm_phy_oldlinkstat = 0;
-	
+
 	/*
 	 * Initialize the DMA channels.  Right now, only one per MAC is used
 	 * Note: Only do this _once_, as it allocates memory from the kernel!
 	 */
-	
+
 	sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
 	sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
-	
+
 	/*
 	 * initial state is OFF
 	 */
-	
+
 	s->sbm_state = sbmac_state_off;
-	
+
 	/*
 	 * Initial speed is (XXX TEMP) 10MBit/s HDX no FC
 	 */
-	
+
 	s->sbm_speed = sbmac_speed_10;
 	s->sbm_duplex = sbmac_duplex_half;
 	s->sbm_fc = sbmac_fc_disabled;
-	
+
 	return 0;
 }
 
@@ -1430,7 +1406,7 @@
 		kfree(d->sbdma_dscrtable);
 		d->sbdma_dscrtable = NULL;
 	}
-	
+
 	if (d->sbdma_ctxtable) {
 		kfree(d->sbdma_ctxtable);
 		d->sbdma_ctxtable = NULL;
@@ -1447,12 +1423,12 @@
 
 /**********************************************************************
  *  SBMAC_CHANNEL_START(s)
- *  
+ *
  *  Start packet processing on this MAC.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1460,49 +1436,49 @@
 static void sbmac_channel_start(struct sbmac_softc *s)
 {
 	uint64_t reg;
-	sbmac_port_t port;
+	volatile void __iomem *port;
 	uint64_t cfg,fifo,framecfg;
 	int idx, th_value;
-	
+
 	/*
 	 * Don't do this if running
 	 */
 
 	if (s->sbm_state == sbmac_state_on)
 		return;
-	
+
 	/*
 	 * Bring the controller out of reset, but leave it off.
 	 */
-	
-	SBMAC_WRITECSR(s->sbm_macenable,0);
-	
+
+	__raw_writeq(0, s->sbm_macenable);
+
 	/*
 	 * Ignore all received packets
 	 */
-	
-	SBMAC_WRITECSR(s->sbm_rxfilter,0);
-	
-	/* 
+
+	__raw_writeq(0, s->sbm_rxfilter);
+
+	/*
 	 * Calculate values for various control registers.
 	 */
-	
+
 	cfg = M_MAC_RETRY_EN |
-		M_MAC_TX_HOLD_SOP_EN | 
+		M_MAC_TX_HOLD_SOP_EN |
 		V_MAC_TX_PAUSE_CNT_16K |
 		M_MAC_AP_STAT_EN |
 		M_MAC_FAST_SYNC |
 		M_MAC_SS_EN |
 		0;
-	
-	/* 
+
+	/*
 	 * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
 	 * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
 	 * Use a larger RD_THRSH for gigabit
 	 */
-	if (periph_rev >= 2) 
+	if (periph_rev >= 2)
 		th_value = 64;
-	else 
+	else
 		th_value = 28;
 
 	fifo = V_MAC_TX_WR_THRSH(4) |	/* Must be '4' or '8' */
@@ -1520,51 +1496,51 @@
 		V_MAC_BACKOFF_SEL(1);
 
 	/*
-	 * Clear out the hash address map 
+	 * Clear out the hash address map
 	 */
-	
+
 	port = s->sbm_base + R_MAC_HASH_BASE;
 	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
-		SBMAC_WRITECSR(port,0);
+		__raw_writeq(0, port);
 		port += sizeof(uint64_t);
 	}
-	
+
 	/*
 	 * Clear out the exact-match table
 	 */
-	
+
 	port = s->sbm_base + R_MAC_ADDR_BASE;
 	for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
-		SBMAC_WRITECSR(port,0);
+		__raw_writeq(0, port);
 		port += sizeof(uint64_t);
 	}
-	
+
 	/*
 	 * Clear out the DMA Channel mapping table registers
 	 */
-	
+
 	port = s->sbm_base + R_MAC_CHUP0_BASE;
 	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
-		SBMAC_WRITECSR(port,0);
+		__raw_writeq(0, port);
 		port += sizeof(uint64_t);
 	}
 
 
 	port = s->sbm_base + R_MAC_CHLO0_BASE;
 	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
-		SBMAC_WRITECSR(port,0);
+		__raw_writeq(0, port);
 		port += sizeof(uint64_t);
 	}
-	
+
 	/*
 	 * Program the hardware address.  It goes into the hardware-address
 	 * register as well as the first filter register.
 	 */
-	
+
 	reg = sbmac_addr2reg(s->sbm_hwaddr);
-	
+
 	port = s->sbm_base + R_MAC_ADDR_BASE;
-	SBMAC_WRITECSR(port,reg);
+	__raw_writeq(reg, port);
 	port = s->sbm_base + R_MAC_ETHERNET_ADDR;
 
 #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
@@ -1573,108 +1549,105 @@
 	 * destination address in the R_MAC_ETHERNET_ADDR register.
 	 * Set the value to zero.
 	 */
-	SBMAC_WRITECSR(port,0);
+	__raw_writeq(0, port);
 #else
-	SBMAC_WRITECSR(port,reg);
+	__raw_writeq(reg, port);
 #endif
-	
+
 	/*
 	 * Set the receive filter for no packets, and write values
 	 * to the various config registers
 	 */
-	
-	SBMAC_WRITECSR(s->sbm_rxfilter,0);
-	SBMAC_WRITECSR(s->sbm_imr,0);
-	SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
-	SBMAC_WRITECSR(s->sbm_fifocfg,fifo);
-	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-	
+
+	__raw_writeq(0, s->sbm_rxfilter);
+	__raw_writeq(0, s->sbm_imr);
+	__raw_writeq(framecfg, s->sbm_framecfg);
+	__raw_writeq(fifo, s->sbm_fifocfg);
+	__raw_writeq(cfg, s->sbm_maccfg);
+
 	/*
 	 * Initialize DMA channels (rings should be ok now)
 	 */
-	
+
 	sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
 	sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
-	
+
 	/*
 	 * Configure the speed, duplex, and flow control
 	 */
 
 	sbmac_set_speed(s,s->sbm_speed);
 	sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
-	
+
 	/*
 	 * Fill the receive ring
 	 */
-	
+
 	sbdma_fillring(&(s->sbm_rxdma));
-	
-	/* 
+
+	/*
 	 * Turn on the rest of the bits in the enable register
-	 */      
-	
-	SBMAC_WRITECSR(s->sbm_macenable,
-		       M_MAC_RXDMA_EN0 |
+	 */
+
+	__raw_writeq(M_MAC_RXDMA_EN0 |
 		       M_MAC_TXDMA_EN0 |
 		       M_MAC_RX_ENABLE |
-		       M_MAC_TX_ENABLE);
-	
-	
+		       M_MAC_TX_ENABLE, s->sbm_macenable);
+
+
 
 
 #ifdef CONFIG_SBMAC_COALESCE
 	/*
 	 * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
 	 */
-	SBMAC_WRITECSR(s->sbm_imr,
-		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
-		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+	__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
 #else
 	/*
 	 * Accept any kind of interrupt on TX and RX DMA channel 0
 	 */
-	SBMAC_WRITECSR(s->sbm_imr,
-		       (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
-		       (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
+	__raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
+		       (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
 #endif
-	
-	/* 
-	 * Enable receiving unicasts and broadcasts 
-	 */
-	
-	SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
-	
+
 	/*
-	 * we're running now. 
+	 * Enable receiving unicasts and broadcasts
 	 */
-	
+
+	__raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
+
+	/*
+	 * we're running now.
+	 */
+
 	s->sbm_state = sbmac_state_on;
-	
-	/* 
-	 * Program multicast addresses 
+
+	/*
+	 * Program multicast addresses
 	 */
-	
+
 	sbmac_setmulti(s);
-	
-	/* 
-	 * If channel was in promiscuous mode before, turn that on 
+
+	/*
+	 * If channel was in promiscuous mode before, turn that on
 	 */
-	
+
 	if (s->sbm_devflags & IFF_PROMISC) {
 		sbmac_promiscuous_mode(s,1);
 	}
-	
+
 }
 
 
 /**********************************************************************
  *  SBMAC_CHANNEL_STOP(s)
- *  
+ *
  *  Stop packet processing on this MAC.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1682,49 +1655,49 @@
 static void sbmac_channel_stop(struct sbmac_softc *s)
 {
 	/* don't do this if already stopped */
-	
+
 	if (s->sbm_state == sbmac_state_off)
 		return;
-	
+
 	/* don't accept any packets, disable all interrupts */
-	
-	SBMAC_WRITECSR(s->sbm_rxfilter,0);
-	SBMAC_WRITECSR(s->sbm_imr,0);
-	
+
+	__raw_writeq(0, s->sbm_rxfilter);
+	__raw_writeq(0, s->sbm_imr);
+
 	/* Turn off ticker */
-	
+
 	/* XXX */
-	
+
 	/* turn off receiver and transmitter */
-	
-	SBMAC_WRITECSR(s->sbm_macenable,0);
-	
+
+	__raw_writeq(0, s->sbm_macenable);
+
 	/* We're stopped now. */
-	
+
 	s->sbm_state = sbmac_state_off;
-	
+
 	/*
 	 * Stop DMA channels (rings should be ok now)
 	 */
-	
+
 	sbdma_channel_stop(&(s->sbm_rxdma));
 	sbdma_channel_stop(&(s->sbm_txdma));
-	
+
 	/* Empty the receive and transmit rings */
-	
+
 	sbdma_emptyring(&(s->sbm_rxdma));
 	sbdma_emptyring(&(s->sbm_txdma));
-	
+
 }
 
 /**********************************************************************
  *  SBMAC_SET_CHANNEL_STATE(state)
- *  
+ *
  *  Set the channel's state ON or OFF
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   state - new state
- *  	   
+ *
  *  Return value:
  *  	   old state
  ********************************************************************* */
@@ -1732,43 +1705,43 @@
 					     sbmac_state_t state)
 {
 	sbmac_state_t oldstate = sc->sbm_state;
-	
+
 	/*
 	 * If same as previous state, return
 	 */
-	
+
 	if (state == oldstate) {
 		return oldstate;
 	}
-	
+
 	/*
-	 * If new state is ON, turn channel on 
+	 * If new state is ON, turn channel on
 	 */
-	
+
 	if (state == sbmac_state_on) {
 		sbmac_channel_start(sc);
 	}
 	else {
 		sbmac_channel_stop(sc);
 	}
-	
+
 	/*
 	 * Return previous state
 	 */
-	
+
 	return oldstate;
 }
 
 
 /**********************************************************************
  *  SBMAC_PROMISCUOUS_MODE(sc,onoff)
- *  
+ *
  *  Turn on or off promiscuous mode
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   sc - softc
  *      onoff - 1 to turn on, 0 to turn off
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1776,30 +1749,30 @@
 static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
 {
 	uint64_t reg;
-	
+
 	if (sc->sbm_state != sbmac_state_on)
 		return;
-	
+
 	if (onoff) {
-		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg = __raw_readq(sc->sbm_rxfilter);
 		reg |= M_MAC_ALLPKT_EN;
-		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-	}	
+		__raw_writeq(reg, sc->sbm_rxfilter);
+	}
 	else {
-		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg = __raw_readq(sc->sbm_rxfilter);
 		reg &= ~M_MAC_ALLPKT_EN;
-		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+		__raw_writeq(reg, sc->sbm_rxfilter);
 	}
 }
 
 /**********************************************************************
  *  SBMAC_SETIPHDR_OFFSET(sc,onoff)
- *  
+ *
  *  Set the iphdr offset as 15 assuming ethernet encapsulation
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   sc - softc
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -1807,12 +1780,12 @@
 static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
 {
 	uint64_t reg;
-	
+
 	/* Hard code the off set to 15 for now */
-	reg = SBMAC_READCSR(sc->sbm_rxfilter);
+	reg = __raw_readq(sc->sbm_rxfilter);
 	reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
-	SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-	
+	__raw_writeq(reg, sc->sbm_rxfilter);
+
 	/* read system identification to determine revision */
 	if (periph_rev >= 2) {
 		sc->rx_hw_checksum = ENABLE;
@@ -1824,13 +1797,13 @@
 
 /**********************************************************************
  *  SBMAC_ADDR2REG(ptr)
- *  
+ *
  *  Convert six bytes into the 64-bit register value that
  *  we typically write into the SBMAC's address/mcast registers
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   ptr - pointer to 6 bytes
- *  	   
+ *
  *  Return value:
  *  	   register value
  ********************************************************************* */
@@ -1838,35 +1811,35 @@
 static uint64_t sbmac_addr2reg(unsigned char *ptr)
 {
 	uint64_t reg = 0;
-	
+
 	ptr += 6;
-	
-	reg |= (uint64_t) *(--ptr); 
+
+	reg |= (uint64_t) *(--ptr);
 	reg <<= 8;
-	reg |= (uint64_t) *(--ptr); 
+	reg |= (uint64_t) *(--ptr);
 	reg <<= 8;
-	reg |= (uint64_t) *(--ptr); 
+	reg |= (uint64_t) *(--ptr);
 	reg <<= 8;
-	reg |= (uint64_t) *(--ptr); 
+	reg |= (uint64_t) *(--ptr);
 	reg <<= 8;
-	reg |= (uint64_t) *(--ptr); 
+	reg |= (uint64_t) *(--ptr);
 	reg <<= 8;
-	reg |= (uint64_t) *(--ptr); 
-	
+	reg |= (uint64_t) *(--ptr);
+
 	return reg;
 }
 
 
 /**********************************************************************
  *  SBMAC_SET_SPEED(s,speed)
- *  
+ *
  *  Configure LAN speed for the specified MAC.
  *  Warning: must be called when MAC is off!
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
  *  	   speed - speed to set MAC to (see sbmac_speed_t enum)
- *  	   
+ *
  *  Return value:
  *  	   1 if successful
  *      0 indicates invalid parameters
@@ -1880,31 +1853,31 @@
 	/*
 	 * Save new current values
 	 */
-	
+
 	s->sbm_speed = speed;
-	
+
 	if (s->sbm_state == sbmac_state_on)
 		return 0;	/* save for next restart */
 
 	/*
-	 * Read current register values 
+	 * Read current register values
 	 */
-	
-	cfg = SBMAC_READCSR(s->sbm_maccfg);
-	framecfg = SBMAC_READCSR(s->sbm_framecfg);
-	
+
+	cfg = __raw_readq(s->sbm_maccfg);
+	framecfg = __raw_readq(s->sbm_framecfg);
+
 	/*
 	 * Mask out the stuff we want to change
 	 */
-	
+
 	cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
 	framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
 		      M_MAC_SLOT_SIZE);
-	
+
 	/*
 	 * Now add in the new bits
 	 */
-	
+
 	switch (speed) {
 	case sbmac_speed_10:
 		framecfg |= V_MAC_IFG_RX_10 |
@@ -1913,7 +1886,7 @@
 			V_MAC_SLOT_SIZE_10;
 		cfg |= V_MAC_SPEED_SEL_10MBPS;
 		break;
-		
+
 	case sbmac_speed_100:
 		framecfg |= V_MAC_IFG_RX_100 |
 			V_MAC_IFG_TX_100 |
@@ -1921,7 +1894,7 @@
 			V_MAC_SLOT_SIZE_100;
 		cfg |= V_MAC_SPEED_SEL_100MBPS ;
 		break;
-		
+
 	case sbmac_speed_1000:
 		framecfg |= V_MAC_IFG_RX_1000 |
 			V_MAC_IFG_TX_1000 |
@@ -1929,34 +1902,34 @@
 			V_MAC_SLOT_SIZE_1000;
 		cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
 		break;
-		
+
 	case sbmac_speed_auto:		/* XXX not implemented */
 		/* fall through */
 	default:
 		return 0;
 	}
-	
+
 	/*
-	 * Send the bits back to the hardware 
+	 * Send the bits back to the hardware
 	 */
-	
-	SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
-	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-	
+
+	__raw_writeq(framecfg, s->sbm_framecfg);
+	__raw_writeq(cfg, s->sbm_maccfg);
+
 	return 1;
 }
 
 /**********************************************************************
  *  SBMAC_SET_DUPLEX(s,duplex,fc)
- *  
+ *
  *  Set Ethernet duplex and flow control options for this MAC
  *  Warning: must be called when MAC is off!
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   s - sbmac structure
  *  	   duplex - duplex setting (see sbmac_duplex_t)
  *  	   fc - flow control setting (see sbmac_fc_t)
- *  	   
+ *
  *  Return value:
  *  	   1 if ok
  *  	   0 if an invalid parameter combination was specified
@@ -1965,67 +1938,67 @@
 static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc)
 {
 	uint64_t cfg;
-	
+
 	/*
 	 * Save new current values
 	 */
-	
+
 	s->sbm_duplex = duplex;
 	s->sbm_fc = fc;
-	
+
 	if (s->sbm_state == sbmac_state_on)
 		return 0;	/* save for next restart */
-	
+
 	/*
-	 * Read current register values 
+	 * Read current register values
 	 */
-	
-	cfg = SBMAC_READCSR(s->sbm_maccfg);
-	
+
+	cfg = __raw_readq(s->sbm_maccfg);
+
 	/*
 	 * Mask off the stuff we're about to change
 	 */
-	
+
 	cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
-	
-	
+
+
 	switch (duplex) {
 	case sbmac_duplex_half:
 		switch (fc) {
 		case sbmac_fc_disabled:
 			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
 			break;
-			
+
 		case sbmac_fc_collision:
 			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
 			break;
-			
+
 		case sbmac_fc_carrier:
 			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
 			break;
-			
+
 		case sbmac_fc_auto:		/* XXX not implemented */
-			/* fall through */					   
+			/* fall through */
 		case sbmac_fc_frame:		/* not valid in half duplex */
 		default:			/* invalid selection */
 			return 0;
 		}
 		break;
-		
+
 	case sbmac_duplex_full:
 		switch (fc) {
 		case sbmac_fc_disabled:
 			cfg |= V_MAC_FC_CMD_DISABLED;
 			break;
-			
+
 		case sbmac_fc_frame:
 			cfg |= V_MAC_FC_CMD_ENABLED;
 			break;
-			
+
 		case sbmac_fc_collision:	/* not valid in full duplex */
 		case sbmac_fc_carrier:		/* not valid in full duplex */
 		case sbmac_fc_auto:		/* XXX not implemented */
-			/* fall through */					   
+			/* fall through */
 		default:
 			return 0;
 		}
@@ -2034,13 +2007,13 @@
 		/* XXX not implemented */
 		break;
 	}
-	
+
 	/*
-	 * Send the bits back to the hardware 
+	 * Send the bits back to the hardware
 	 */
-	
-	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
-	
+
+	__raw_writeq(cfg, s->sbm_maccfg);
+
 	return 1;
 }
 
@@ -2049,12 +2022,12 @@
 
 /**********************************************************************
  *  SBMAC_INTR()
- *  
+ *
  *  Interrupt handler for MAC interrupts
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   MAC structure
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -2066,27 +2039,27 @@
 	int handled = 0;
 
 	for (;;) {
-		
+
 		/*
 		 * Read the ISR (this clears the bits in the real
 		 * register, except for counter addr)
 		 */
-		
-		isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
-		
+
+		isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
+
 		if (isr == 0)
 			break;
 
 		handled = 1;
-		
+
 		/*
 		 * Transmits on channel 0
 		 */
-		
+
 		if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
 			sbdma_tx_process(sc,&(sc->sbm_txdma));
 		}
-		
+
 		/*
 		 * Receives on channel 0
 		 */
@@ -2106,8 +2079,8 @@
 		 * EOP_SEEN here takes care of this case.
 		 * (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
 		 */
-		 
-		
+
+
 		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
 			sbdma_rx_process(sc,&(sc->sbm_rxdma));
 		}
@@ -2118,29 +2091,29 @@
 
 /**********************************************************************
  *  SBMAC_START_TX(skb,dev)
- *  
- *  Start output on the specified interface.  Basically, we 
+ *
+ *  Start output on the specified interface.  Basically, we
  *  queue as many buffers as we can until the ring fills up, or
  *  we run off the end of the queue, whichever comes first.
- *  
- *  Input parameters: 
- *  	   
- *  	   
+ *
+ *  Input parameters:
+ *
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
 static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sbmac_softc *sc = netdev_priv(dev);
-	
+
 	/* lock eth irq */
 	spin_lock_irq (&sc->sbm_lock);
-	
+
 	/*
-	 * Put the buffer on the transmit ring.  If we 
+	 * Put the buffer on the transmit ring.  If we
 	 * don't have room, stop the queue.
 	 */
-	
+
 	if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
 		/* XXX save skb that we could not send */
 		netif_stop_queue(dev);
@@ -2148,24 +2121,24 @@
 
 		return 1;
 	}
-	
+
 	dev->trans_start = jiffies;
-	
+
 	spin_unlock_irq (&sc->sbm_lock);
-	
+
 	return 0;
 }
 
 /**********************************************************************
  *  SBMAC_SETMULTI(sc)
- *  
+ *
  *  Reprogram the multicast table into the hardware, given
  *  the list of multicasts associated with the interface
  *  structure.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   sc - softc
- *  	   
+ *
  *  Return value:
  *  	   nothing
  ********************************************************************* */
@@ -2173,75 +2146,75 @@
 static void sbmac_setmulti(struct sbmac_softc *sc)
 {
 	uint64_t reg;
-	sbmac_port_t port;
+	volatile void __iomem *port;
 	int idx;
 	struct dev_mc_list *mclist;
 	struct net_device *dev = sc->sbm_dev;
-	
-	/* 
+
+	/*
 	 * Clear out entire multicast table.  We do this by nuking
 	 * the entire hash table and all the direct matches except
-	 * the first one, which is used for our station address 
+	 * the first one, which is used for our station address
 	 */
-	
+
 	for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
 		port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
-		SBMAC_WRITECSR(port,0);	
+		__raw_writeq(0, port);
 	}
-	
+
 	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
 		port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
-		SBMAC_WRITECSR(port,0);	
+		__raw_writeq(0, port);
 	}
-	
+
 	/*
 	 * Clear the filter to say we don't want any multicasts.
 	 */
-	
-	reg = SBMAC_READCSR(sc->sbm_rxfilter);
+
+	reg = __raw_readq(sc->sbm_rxfilter);
 	reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
-	SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
-	
+	__raw_writeq(reg, sc->sbm_rxfilter);
+
 	if (dev->flags & IFF_ALLMULTI) {
-		/* 
-		 * Enable ALL multicasts.  Do this by inverting the 
-		 * multicast enable bit. 
+		/*
+		 * Enable ALL multicasts.  Do this by inverting the
+		 * multicast enable bit.
 		 */
-		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg = __raw_readq(sc->sbm_rxfilter);
 		reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
-		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+		__raw_writeq(reg, sc->sbm_rxfilter);
 		return;
 	}
-	
 
-	/* 
+
+	/*
 	 * Progam new multicast entries.  For now, only use the
 	 * perfect filter.  In the future we'll need to use the
 	 * hash filter if the perfect filter overflows
 	 */
-	
+
 	/* XXX only using perfect filter for now, need to use hash
 	 * XXX if the table overflows */
-	
+
 	idx = 1;		/* skip station address */
 	mclist = dev->mc_list;
 	while (mclist && (idx < MAC_ADDR_COUNT)) {
 		reg = sbmac_addr2reg(mclist->dmi_addr);
 		port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
-		SBMAC_WRITECSR(port,reg);
+		__raw_writeq(reg, port);
 		idx++;
 		mclist = mclist->next;
 	}
-	
-	/*	
+
+	/*
 	 * Enable the "accept multicast bits" if we programmed at least one
-	 * multicast. 
+	 * multicast.
 	 */
-	
+
 	if (idx > 1) {
-		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg = __raw_readq(sc->sbm_rxfilter);
 		reg |= M_MAC_MCAST_EN;
-		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+		__raw_writeq(reg, sc->sbm_rxfilter);
 	}
 }
 
@@ -2250,12 +2223,12 @@
 #if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
 /**********************************************************************
  *  SBMAC_PARSE_XDIGIT(str)
- *  
+ *
  *  Parse a hex digit, returning its value
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   str - character
- *  	   
+ *
  *  Return value:
  *  	   hex value, or -1 if invalid
  ********************************************************************* */
@@ -2263,7 +2236,7 @@
 static int sbmac_parse_xdigit(char str)
 {
 	int digit;
-	
+
 	if ((str >= '0') && (str <= '9'))
 		digit = str - '0';
 	else if ((str >= 'a') && (str <= 'f'))
@@ -2272,20 +2245,20 @@
 		digit = str - 'A' + 10;
 	else
 		return -1;
-	
+
 	return digit;
 }
 
 /**********************************************************************
  *  SBMAC_PARSE_HWADDR(str,hwaddr)
- *  
+ *
  *  Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
  *  Ethernet address.
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   str - string
  *  	   hwaddr - pointer to hardware address
- *  	   
+ *
  *  Return value:
  *  	   0 if ok, else -1
  ********************************************************************* */
@@ -2294,7 +2267,7 @@
 {
 	int digit1,digit2;
 	int idx = 6;
-	
+
 	while (*str && (idx > 0)) {
 		digit1 = sbmac_parse_xdigit(*str);
 		if (digit1 < 0)
@@ -2302,7 +2275,7 @@
 		str++;
 		if (!*str)
 			return -1;
-		
+
 		if ((*str == ':') || (*str == '-')) {
 			digit2 = digit1;
 			digit1 = 0;
@@ -2313,10 +2286,10 @@
 				return -1;
 			str++;
 		}
-		
+
 		*hwaddr++ = (digit1 << 4) | digit2;
 		idx--;
-		
+
 		if (*str == '-')
 			str++;
 		if (*str == ':')
@@ -2337,12 +2310,12 @@
 
 /**********************************************************************
  *  SBMAC_INIT(dev)
- *  
+ *
  *  Attach routine - init hardware and hook ourselves into linux
- *  
- *  Input parameters: 
+ *
+ *  Input parameters:
  *  	   dev - net_device structure
- *  	   
+ *
  *  Return value:
  *  	   status
  ********************************************************************* */
@@ -2354,53 +2327,53 @@
 	uint64_t ea_reg;
 	int i;
 	int err;
-	
+
 	sc = netdev_priv(dev);
-	
+
 	/* Determine controller base address */
-	
+
 	sc->sbm_base = IOADDR(dev->base_addr);
 	sc->sbm_dev = dev;
 	sc->sbe_idx = idx;
-	
+
 	eaddr = sc->sbm_hwaddr;
-	
-	/* 
+
+	/*
 	 * Read the ethernet address.  The firwmare left this programmed
 	 * for us in the ethernet address register for each mac.
 	 */
-	
-	ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
-	SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
+
+	ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
+	__raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
 	for (i = 0; i < 6; i++) {
 		eaddr[i] = (uint8_t) (ea_reg & 0xFF);
 		ea_reg >>= 8;
 	}
-	
+
 	for (i = 0; i < 6; i++) {
 		dev->dev_addr[i] = eaddr[i];
 	}
-	
-	
+
+
 	/*
-	 * Init packet size 
+	 * Init packet size
 	 */
-	
+
 	sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
 
-	/* 
+	/*
 	 * Initialize context (get pointers to registers and stuff), then
 	 * allocate the memory for the descriptor tables.
 	 */
-	
+
 	sbmac_initctx(sc);
-	
+
 	/*
 	 * Set up Linux device callins
 	 */
-	
+
 	spin_lock_init(&(sc->sbm_lock));
-	
+
 	dev->open               = sbmac_open;
 	dev->hard_start_xmit    = sbmac_start_tx;
 	dev->stop               = sbmac_close;
@@ -2419,7 +2392,7 @@
 	if (err)
 		goto out_uninit;
 
-	if (periph_rev >= 2) {
+	if (sc->rx_hw_checksum == ENABLE) {
 		printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
 			sc->sbm_dev->name);
 	}
@@ -2430,10 +2403,10 @@
 	 * was being displayed)
 	 */
 	printk(KERN_INFO
-	       "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
+	       "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n",
 	       dev->name, dev->base_addr,
 	       eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
-	
+
 
 	return 0;
 
@@ -2447,54 +2420,86 @@
 static int sbmac_open(struct net_device *dev)
 {
 	struct sbmac_softc *sc = netdev_priv(dev);
-	
+
 	if (debug > 1) {
 		printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
 	}
-	
-	/* 
+
+	/*
 	 * map/route interrupt (clear status first, in case something
 	 * weird is pending; we haven't initialized the mac registers
 	 * yet)
 	 */
 
-	SBMAC_READCSR(sc->sbm_isr);
+	__raw_readq(sc->sbm_isr);
 	if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev))
 		return -EBUSY;
 
 	/*
-	 * Configure default speed 
+	 * Probe phy address
+	 */
+
+	if(sbmac_mii_probe(dev) == -1) {
+		printk("%s: failed to probe PHY.\n", dev->name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Configure default speed
 	 */
 
 	sbmac_mii_poll(sc,noisy_mii);
-	
+
 	/*
 	 * Turn on the channel
 	 */
 
 	sbmac_set_channel_state(sc,sbmac_state_on);
-	
+
 	/*
 	 * XXX Station address is in dev->dev_addr
 	 */
-	
+
 	if (dev->if_port == 0)
-		dev->if_port = 0; 
-	
+		dev->if_port = 0;
+
 	netif_start_queue(dev);
-	
+
 	sbmac_set_rx_mode(dev);
-	
+
 	/* Set the timer to check for link beat. */
 	init_timer(&sc->sbm_timer);
 	sc->sbm_timer.expires = jiffies + 2 * HZ/100;
 	sc->sbm_timer.data = (unsigned long)dev;
 	sc->sbm_timer.function = &sbmac_timer;
 	add_timer(&sc->sbm_timer);
-	
+
 	return 0;
 }
 
+static int sbmac_mii_probe(struct net_device *dev)
+{
+	int i;
+	struct sbmac_softc *s = netdev_priv(dev);
+	u16 bmsr, id1, id2;
+	u32 vendor, device;
+
+	for (i=1; i<31; i++) {
+	bmsr = sbmac_mii_read(s, i, MII_BMSR);
+		if (bmsr != 0) {
+			s->sbm_phys[0] = i;
+			id1 = sbmac_mii_read(s, i, MII_PHYIDR1);
+			id2 = sbmac_mii_read(s, i, MII_PHYIDR2);
+			vendor = ((u32)id1 << 6) | ((id2 >> 10) & 0x3f);
+			device = (id2 >> 4) & 0x3f;
+
+			printk(KERN_INFO "%s: found phy %d, vendor %06x part %02x\n",
+				dev->name, i, vendor, device);
+			return i;
+		}
+	}
+	return -1;
+}
 
 
 static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
@@ -2609,20 +2614,20 @@
 	int mii_status;
 
 	spin_lock_irq (&sc->sbm_lock);
-	
+
 	/* make IFF_RUNNING follow the MII status bit "Link established" */
 	mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
-	
+
 	if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
     	        sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
 		if (mii_status & BMSR_LINKSTAT) {
 			netif_carrier_on(dev);
 		}
 		else {
-			netif_carrier_off(dev);	
+			netif_carrier_off(dev);
 		}
 	}
-	
+
 	/*
 	 * Poll the PHY to see what speed we should be running at
 	 */
@@ -2640,9 +2645,9 @@
 			sbmac_channel_start(sc);
 		}
 	}
-	
+
 	spin_unlock_irq (&sc->sbm_lock);
-	
+
 	sc->sbm_timer.expires = jiffies + next_tick;
 	add_timer(&sc->sbm_timer);
 }
@@ -2651,13 +2656,13 @@
 static void sbmac_tx_timeout (struct net_device *dev)
 {
 	struct sbmac_softc *sc = netdev_priv(dev);
-	
+
 	spin_lock_irq (&sc->sbm_lock);
-	
-	
+
+
 	dev->trans_start = jiffies;
 	sc->sbm_stats.tx_errors++;
-	
+
 	spin_unlock_irq (&sc->sbm_lock);
 
 	printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
@@ -2670,13 +2675,13 @@
 {
 	struct sbmac_softc *sc = netdev_priv(dev);
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&sc->sbm_lock, flags);
-	
+
 	/* XXX update other stats here */
-	
+
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
-	
+
 	return &sc->sbm_stats;
 }
 
@@ -2693,8 +2698,8 @@
 		/*
 		 * Promiscuous changed.
 		 */
-		
-		if (dev->flags & IFF_PROMISC) {	
+
+		if (dev->flags & IFF_PROMISC) {
 			/* Unconditionally log net taps. */
 			msg_flag = 1;
 			sbmac_promiscuous_mode(sc,1);
@@ -2705,18 +2710,18 @@
 		}
 	}
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
-	
+
 	if (msg_flag) {
 		printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
 		       dev->name,(msg_flag==1)?"en":"dis");
 	}
-	
+
 	/*
 	 * Program the multicasts.  Do this every time.
 	 */
-	
+
 	sbmac_setmulti(sc);
-	
+
 }
 
 static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2725,10 +2730,10 @@
 	u16 *data = (u16 *)&rq->ifr_ifru;
 	unsigned long flags;
 	int retval;
-	
+
 	spin_lock_irqsave(&sc->sbm_lock, flags);
 	retval = 0;
-	
+
 	switch(cmd) {
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
 		data[0] = sc->sbm_phys[0] & 0x1f;
@@ -2750,7 +2755,7 @@
 	default:
 		retval = -EOPNOTSUPP;
 	}
-	
+
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
 	return retval;
 }
@@ -2781,7 +2786,7 @@
 
 	sbdma_emptyring(&(sc->sbm_txdma));
 	sbdma_emptyring(&(sc->sbm_rxdma));
-	
+
 	return 0;
 }
 
@@ -2793,13 +2798,13 @@
 {
 	uint8_t eaddr[6];
 	uint64_t val;
-	sbmac_port_t port;
+	unsigned long port;
 
 	port = A_MAC_CHANNEL_BASE(chan);
 	sbmac_parse_hwaddr(addr,eaddr);
 	val = sbmac_addr2reg(eaddr);
-	SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),val);
-	val = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+	__raw_writeq(val, IOADDR(port+R_MAC_ETHERNET_ADDR));
+	val = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
 }
 #endif
 
@@ -2810,9 +2815,9 @@
 {
 	int idx;
 	struct net_device *dev;
-	sbmac_port_t port;
+	unsigned long port;
 	int chip_max_units;
-	
+
 	/*
 	 * For bringup when not using the firmware, we can pre-fill
 	 * the MAC addresses using the environment variables
@@ -2858,13 +2863,13 @@
 
 	        port = A_MAC_CHANNEL_BASE(idx);
 
-		/*	
+		/*
 		 * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
 		 * value for us by the firmware if we're going to use this MAC.
 		 * If we find a zero, skip this MAC.
 		 */
 
-		sbmac_orig_hwaddr[idx] = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR));
+		sbmac_orig_hwaddr[idx] = __raw_readq(IOADDR(port+R_MAC_ETHERNET_ADDR));
 		if (sbmac_orig_hwaddr[idx] == 0) {
 			printk(KERN_DEBUG "sbmac: not configuring MAC at "
 			       "%lx\n", port);
@@ -2876,7 +2881,7 @@
 		 */
 
 		dev = alloc_etherdev(sizeof(struct sbmac_softc));
-		if (!dev) 
+		if (!dev)
 			return -ENOMEM;	/* return ENOMEM */
 
 		printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
@@ -2886,8 +2891,7 @@
 		dev->mem_end = 0;
 		if (sbmac_init(dev, idx)) {
 			port = A_MAC_CHANNEL_BASE(idx);
-			SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
-				       sbmac_orig_hwaddr[idx]);
+			__raw_writeq(sbmac_orig_hwaddr[idx], IOADDR(port+R_MAC_ETHERNET_ADDR));
 			free_netdev(dev);
 			continue;
 		}
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 9bc3b1c..a4614df 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -32,8 +32,6 @@
 
 #include "sgiseeq.h"
 
-static char *version = "sgiseeq.c: David S. Miller (dm@engr.sgi.com)\n";
-
 static char *sgiseeqstr = "SGI Seeq8003";
 
 /*
@@ -113,9 +111,9 @@
 
 static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
 {
-	hregs->rx_reset = HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ;
+	hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
 	udelay(20);
-	hregs->rx_reset = 0;
+	hregs->reset = 0;
 }
 
 static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
@@ -252,7 +250,6 @@
 
 #define TSTAT_INIT_SEEQ (SEEQ_TCMD_IPT|SEEQ_TCMD_I16|SEEQ_TCMD_IC|SEEQ_TCMD_IUF)
 #define TSTAT_INIT_EDLC ((TSTAT_INIT_SEEQ) | SEEQ_TCMD_RB2)
-#define RDMACFG_INIT    (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
 
 static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
 		     struct sgiseeq_regs *sregs)
@@ -274,8 +271,6 @@
 		sregs->tstat = TSTAT_INIT_SEEQ;
 	}
 
-	hregs->rx_dconfig |= RDMACFG_INIT;
-
 	hregs->rx_ndptr = CPHYSADDR(sp->rx_desc);
 	hregs->tx_ndptr = CPHYSADDR(sp->tx_desc);
 
@@ -446,7 +441,7 @@
 	spin_lock(&sp->tx_lock);
 
 	/* Ack the IRQ and set software state. */
-	hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
+	hregs->reset = HPC3_ERST_CLRIRQ;
 
 	/* Always check for received packets. */
 	sgiseeq_rx(dev, sp, hregs, sregs);
@@ -493,11 +488,13 @@
 {
 	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct sgiseeq_regs *sregs = sp->sregs;
+	unsigned int irq = dev->irq;
 
 	netif_stop_queue(dev);
 
 	/* Shutdown the Seeq. */
 	reset_hpc3_and_seeq(sp->hregs, sregs);
+	free_irq(irq, dev);
 
 	return 0;
 }
@@ -644,7 +641,7 @@
 
 #define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
 
-static int sgiseeq_init(struct hpc3_regs* regs, int irq)
+static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq)
 {
 	struct sgiseeq_init_block *sr;
 	struct sgiseeq_private *sp;
@@ -680,8 +677,8 @@
 	gpriv = sp;
 	gdev = dev;
 #endif
-	sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
-	sp->hregs = &hpc3c0->ethregs;
+	sp->sregs = (struct sgiseeq_regs *) &hpcregs->eth_ext[0];
+	sp->hregs = &hpcregs->ethregs;
 	sp->name = sgiseeqstr;
 	sp->mode = SEEQ_RCMD_RBCAST;
 
@@ -698,6 +695,11 @@
 	setup_rx_ring(sp->rx_desc, SEEQ_RX_BUFFERS);
 	setup_tx_ring(sp->tx_desc, SEEQ_TX_BUFFERS);
 
+	/* Setup PIO and DMA transfer timing */
+	sp->hregs->pconfig = 0x161;
+	sp->hregs->dconfig = HPC3_EDCFG_FIRQ | HPC3_EDCFG_FEOP |
+			     HPC3_EDCFG_FRXDC | HPC3_EDCFG_PTO | 0x026;
+
 	/* Reset the chip. */
 	hpc3_eth_reset(sp->hregs);
 
@@ -724,7 +726,7 @@
 		goto err_out_free_page;
 	}
 
-	printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
+	printk(KERN_INFO "%s: %s ", dev->name, sgiseeqstr);
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
 
@@ -734,7 +736,7 @@
 	return 0;
 
 err_out_free_page:
-	free_page((unsigned long) sp);
+	free_page((unsigned long) sp->srings);
 err_out_free_dev:
 	kfree(dev);
 
@@ -744,8 +746,6 @@
 
 static int __init sgiseeq_probe(void)
 {
-	printk(version);
-
 	/* On board adapter on 1st HPC is always present */
 	return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
 }
@@ -754,15 +754,12 @@
 {
 	struct net_device *next, *dev;
 	struct sgiseeq_private *sp;
-	int irq;
 
 	for (dev = root_sgiseeq_dev; dev; dev = next) {
 		sp = (struct sgiseeq_private *) netdev_priv(dev);
 		next = sp->next_module;
-		irq = dev->irq;
 		unregister_netdev(dev);
-		free_irq(irq, dev);
-		free_page((unsigned long) sp);
+		free_page((unsigned long) sp->srings);
 		free_netdev(dev);
 	}
 }
@@ -770,4 +767,6 @@
 module_init(sgiseeq_probe);
 module_exit(sgiseeq_exit);
 
+MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 92f7552..478791e 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -842,7 +842,7 @@
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
 		     i++, mclist = mclist->next) {
 			int bit_nr =
-				ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+				ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f;
 			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
 			rx_mode |= AcceptMulticast;
 		}
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 23b713c..1d4d886 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1696,15 +1696,20 @@
 	long ioaddr = net_dev->base_addr;
 	unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
 	u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
+	int rx_work_limit;
 
 	if (netif_msg_rx_status(sis_priv))
 		printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
 		       "status:0x%8.8x\n",
 		       sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
+	rx_work_limit = sis_priv->dirty_rx + NUM_RX_DESC - sis_priv->cur_rx;
 
 	while (rx_status & OWN) {
 		unsigned int rx_size;
 
+		if (--rx_work_limit < 0)
+			break;
+
 		rx_size = (rx_status & DSIZE) - CRC_SIZE;
 
 		if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
@@ -1732,9 +1737,11 @@
 			   we are working on NULL sk_buff :-( */
 			if (sis_priv->rx_skbuff[entry] == NULL) {
 				if (netif_msg_rx_err(sis_priv))
-					printk(KERN_INFO "%s: NULL pointer " 
-						"encountered in Rx ring, skipping\n",
-						net_dev->name);
+					printk(KERN_WARNING "%s: NULL pointer " 
+					      "encountered in Rx ring\n"
+					      "cur_rx:%4.4d, dirty_rx:%4.4d\n",
+					      net_dev->name, sis_priv->cur_rx,
+					      sis_priv->dirty_rx);
 				break;
 			}
 
@@ -1770,6 +1777,7 @@
 				sis_priv->rx_ring[entry].cmdsts = 0;
 				sis_priv->rx_ring[entry].bufptr = 0;
 				sis_priv->stats.rx_dropped++;
+				sis_priv->cur_rx++;
 				break;
 			}
 			skb->dev = net_dev;
@@ -1787,7 +1795,7 @@
 
 	/* refill the Rx buffer, what if the rate of refilling is slower
 	 * than consuming ?? */
-	for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) {
+	for (; sis_priv->cur_rx != sis_priv->dirty_rx; sis_priv->dirty_rx++) {
 		struct sk_buff *skb;
 
 		entry = sis_priv->dirty_rx % NUM_RX_DESC;
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index f17c05c..99a776a 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -1896,7 +1896,7 @@
 
 static void smt_string_swap(char *data, const char *format, int len)
 {
-	const char	*open_paren = 0 ;
+	const char	*open_paren = NULL ;
 	int	x ;
 
 	while (len > 0  && *format) {
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index c2e6484..572f121 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -730,6 +730,7 @@
 	.phys_id	= skge_phys_id,
 	.get_stats_count = skge_get_stats_count,
 	.get_ethtool_stats = skge_get_ethtool_stats,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
 /*
@@ -3096,6 +3097,7 @@
 
 	/* read the mac address */
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	/* device is off until link detection */
 	netif_carrier_off(dev);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 1438fdd..c573bb3 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1983,6 +1983,10 @@
 	if (lp->version >= (CHIP_91100 << 4))
 		smc_phy_detect(dev);
 
+	/* then shut everything down to save power */
+	smc_shutdown(dev);
+	smc_phy_powerdown(dev);
+
 	/* Set default parameters */
 	lp->msg_enable = NETIF_MSG_LINK;
 	lp->ctl_rfduplx = 0;
@@ -2291,11 +2295,11 @@
 	return 0;
 }
 
-static int smc_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+static int smc_drv_suspend(struct device *dev, pm_message_t state)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 
-	if (ndev && level == SUSPEND_DISABLE) {
+	if (ndev) {
 		if (netif_running(ndev)) {
 			netif_device_detach(ndev);
 			smc_shutdown(ndev);
@@ -2305,12 +2309,12 @@
 	return 0;
 }
 
-static int smc_drv_resume(struct device *dev, u32 level)
+static int smc_drv_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct net_device *ndev = dev_get_drvdata(dev);
 
-	if (ndev && level == RESUME_ENABLE) {
+	if (ndev) {
 		struct smc_local *lp = netdev_priv(ndev);
 		smc_enable_device(pdev);
 		if (netif_running(ndev)) {
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index ac9ce65..817f200 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -230,12 +230,12 @@
 #define SMC_CAN_USE_16BIT	1
 #define SMC_CAN_USE_32BIT	0
 
-#define SMC_inb(a, r)		inb((a) + (r) - 0xa0000000)
-#define SMC_inw(a, r)		inw((a) + (r) - 0xa0000000)
-#define SMC_outb(v, a, r)	outb(v, (a) + (r) - 0xa0000000)
-#define SMC_outw(v, a, r)	outw(v, (a) + (r) - 0xa0000000)
-#define SMC_insw(a, r, p, l)	insw((a) + (r) - 0xa0000000, p, l)
-#define SMC_outsw(a, r, p, l)	outsw((a) + (r) - 0xa0000000, p, l)
+#define SMC_inb(a, r)		inb((u32)a) + (r))
+#define SMC_inw(a, r)		inw(((u32)a) + (r))
+#define SMC_outb(v, a, r)	outb(v, ((u32)a) + (r))
+#define SMC_outw(v, a, r)	outw(v, ((u32)a) + (r))
+#define SMC_insw(a, r, p, l)	insw(((u32)a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	outsw(((u32)a) + (r), p, l)
 
 #define set_irq_type(irq, type)	do {} while(0)
 
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index efdb179..38b2b0a 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1091,8 +1091,10 @@
 		rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
 		np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
 		np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
-		if (np->queue_mem == 0)
+		if (np->queue_mem == NULL) {
+			free_irq(dev->irq, dev);
 			return -ENOMEM;
+		}
 
 		np->tx_done_q     = np->queue_mem;
 		np->tx_done_q_dma = np->queue_mem_dma;
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index f88f5e3..cfaf47c 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -214,7 +214,8 @@
 {
 	struct bmac_init_block *bb = bp->bmac_block;
 	struct net_device *dev = bp->dev;
-	int i, gfp_flags = GFP_KERNEL;
+	int i;
+	gfp_t gfp_flags = GFP_KERNEL;
 
 	if (from_irq || in_interrupt())
 		gfp_flags = GFP_ATOMIC;
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
index 5674003..b0dbc51 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/sunbmac.h
@@ -339,7 +339,7 @@
 #define ALIGNED_RX_SKB_ADDR(addr) \
         ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
 
-static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, int gfp_flags)
+static inline struct sk_buff *big_mac_alloc_skb(unsigned int length, gfp_t gfp_flags)
 {
 	struct sk_buff *skb;
 
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index d500a57..0ab9c38 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -80,7 +80,7 @@
 	  I/O access could affect performance in ARM-based system
 	- Add Linux software VLAN support
 	
-	Version LK1.08 (D-Link):
+	Version LK1.08 (Philippe De Muyter phdm@macqel.be):
 	- Fix bug of custom mac address 
 	(StationAddr register only accept word write) 
 
@@ -91,11 +91,14 @@
 	Version LK1.09a (ICPlus):
 	- Add the delay time in reading the contents of EEPROM
 
+	Version LK1.10 (Philippe De Muyter phdm@macqel.be):
+	- Make 'unblock interface after Tx underrun' work
+
 */
 
 #define DRV_NAME	"sundance"
-#define DRV_VERSION	"1.01+LK1.09a"
-#define DRV_RELDATE	"10-Jul-2003"
+#define DRV_VERSION	"1.01+LK1.10"
+#define DRV_RELDATE	"28-Oct-2005"
 
 
 /* The user-configurable values.
@@ -263,8 +266,10 @@
 IVb. References
 
 The Sundance ST201 datasheet, preliminary version.
-http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+The Kendin KS8723 datasheet, preliminary version.
+The ICplus IP100 datasheet, preliminary version.
+http://www.scyld.com/expert/100mbps.html
+http://www.scyld.com/expert/NWay.html
 
 IVc. Errata
 
@@ -500,6 +505,25 @@
 static int  netdev_close(struct net_device *dev);
 static struct ethtool_ops ethtool_ops;
 
+static void sundance_reset(struct net_device *dev, unsigned long reset_cmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->base + ASICCtrl;
+	int countdown;
+
+	/* ST201 documentation states ASICCtrl is a 32bit register */
+	iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr);
+	/* ST201 documentation states reset can take up to 1 ms */
+	countdown = 10 + 1;
+	while (ioread32 (ioaddr) & (ResetBusy << 16)) {
+		if (--countdown == 0) {
+			printk(KERN_WARNING "%s : reset not completed !!\n", dev->name);
+			break;
+		}
+		udelay(100);
+	}
+}
+
 static int __devinit sundance_probe1 (struct pci_dev *pdev,
 				      const struct pci_device_id *ent)
 {
@@ -518,6 +542,7 @@
 #else
 	int bar = 1;
 #endif
+	int phy, phy_idx = 0;
 
 
 /* when built into the kernel, we only print version if device is found */
@@ -549,6 +574,7 @@
 	for (i = 0; i < 3; i++)
 		((u16 *)dev->dev_addr)[i] =
 			le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	dev->base_addr = (unsigned long)ioaddr;
 	dev->irq = irq;
@@ -605,32 +631,30 @@
 			printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
-	if (1) {
-		int phy, phy_idx = 0;
-		np->phys[0] = 1;		/* Default setting */
-		np->mii_preamble_required++;
-		for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
-			int mii_status = mdio_read(dev, phy, MII_BMSR);
-			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
-				np->phys[phy_idx++] = phy;
-				np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
-				if ((mii_status & 0x0040) == 0)
-					np->mii_preamble_required++;
-				printk(KERN_INFO "%s: MII PHY found at address %d, status "
-					   "0x%4.4x advertising %4.4x.\n",
-					   dev->name, phy, mii_status, np->mii_if.advertising);
-			}
+	np->phys[0] = 1;		/* Default setting */
+	np->mii_preamble_required++;
+	for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) {
+		int mii_status = mdio_read(dev, phy, MII_BMSR);
+		int phyx = phy & 0x1f;
+		if (mii_status != 0xffff  &&  mii_status != 0x0000) {
+			np->phys[phy_idx++] = phyx;
+			np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE);
+			if ((mii_status & 0x0040) == 0)
+				np->mii_preamble_required++;
+			printk(KERN_INFO "%s: MII PHY found at address %d, status "
+				   "0x%4.4x advertising %4.4x.\n",
+				   dev->name, phyx, mii_status, np->mii_if.advertising);
 		}
-		np->mii_preamble_required--;
-
-		if (phy_idx == 0) {
-			printk(KERN_INFO "%s: No MII transceiver found, aborting.  ASIC status %x\n",
-				   dev->name, ioread32(ioaddr + ASICCtrl));
-			goto err_out_unregister;
-		}
-
-		np->mii_if.phy_id = np->phys[0];
 	}
+	np->mii_preamble_required--;
+
+	if (phy_idx == 0) {
+		printk(KERN_INFO "%s: No MII transceiver found, aborting.  ASIC status %x\n",
+			   dev->name, ioread32(ioaddr + ASICCtrl));
+		goto err_out_unregister;
+	}
+
+	np->mii_if.phy_id = np->phys[0];
 
 	/* Parse override configuration */
 	np->an_enable = 1;
@@ -692,7 +716,7 @@
 	/* Reset the chip to erase previous misconfiguration. */
 	if (netif_msg_hw(np))
 		printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
-	iowrite16(0x007f, ioaddr + ASICCtrl + 2);
+	iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
 	if (netif_msg_hw(np))
 		printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
 
@@ -1190,23 +1214,33 @@
 					    ("%s: Transmit status is %2.2x.\n",
 				     	dev->name, tx_status);
 				if (tx_status & 0x1e) {
+					if (netif_msg_tx_err(np))
+						printk("%s: Transmit error status %4.4x.\n",
+							   dev->name, tx_status);
 					np->stats.tx_errors++;
 					if (tx_status & 0x10)
 						np->stats.tx_fifo_errors++;
 					if (tx_status & 0x08)
 						np->stats.collisions++;
+					if (tx_status & 0x04)
+						np->stats.tx_fifo_errors++;
 					if (tx_status & 0x02)
 						np->stats.tx_window_errors++;
-					/* This reset has not been verified!. */
-					if (tx_status & 0x10) {	/* Reset the Tx. */
-						np->stats.tx_fifo_errors++;
-						spin_lock(&np->lock);
-						reset_tx(dev);
-						spin_unlock(&np->lock);
+					/*
+					** This reset has been verified on
+					** DFE-580TX boards ! phdm@macqel.be.
+					*/
+					if (tx_status & 0x10) {	/* TxUnderrun */
+						unsigned short txthreshold;
+
+						txthreshold = ioread16 (ioaddr + TxStartThresh);
+						/* Restart Tx FIFO and transmitter */
+						sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
+						iowrite16 (txthreshold, ioaddr + TxStartThresh);
+						/* No need to reset the Tx pointer here */
 					}
-					if (tx_status & 0x1e)	/* Restart the Tx. */
-						iowrite16 (TxEnable,
-							ioaddr + MACCtrl1);
+					/* Restart the Tx. */
+					iowrite16 (TxEnable, ioaddr + MACCtrl1);
 				}
 				/* Yup, this is a documentation bug.  It cost me *hours*. */
 				iowrite16 (0, ioaddr + TxStatus);
@@ -1619,6 +1653,7 @@
 	.get_link = get_link,
 	.get_msglevel = get_msglevel,
 	.set_msglevel = set_msglevel,
+	.get_perm_addr = ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 1802c3b..1828a6b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -37,6 +37,7 @@
 #include <linux/tcp.h>
 #include <linux/workqueue.h>
 #include <linux/prefetch.h>
+#include <linux/dma-mapping.h>
 
 #include <net/checksum.h>
 
@@ -67,8 +68,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.42"
-#define DRV_MODULE_RELDATE	"Oct 3, 2005"
+#define DRV_MODULE_VERSION	"3.43"
+#define DRV_MODULE_RELDATE	"Oct 24, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -219,6 +220,10 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S,
@@ -466,6 +471,15 @@
 	spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
+static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
+{
+	/* If no workaround is needed, write to mem space directly */
+	if (tp->write32 != tg3_write_indirect_reg32)
+		tw32(NIC_SRAM_WIN_BASE + off, val);
+	else
+		tg3_write_mem(tp, off, val);
+}
+
 static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 {
 	unsigned long flags;
@@ -570,7 +584,7 @@
 	u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
 	u32 orig_clock_ctrl;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+	if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
 		return;
 
 	orig_clock_ctrl = clock_ctrl;
@@ -1210,7 +1224,7 @@
 		     CLOCK_CTRL_ALTCLK |
 		     CLOCK_CTRL_PWRDOWN_PLL133);
 		udelay(40);
-	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+	} else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
 		/* do nothing */
 	} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
 		     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
@@ -3712,14 +3726,14 @@
 	dev->mtu = new_mtu;
 
 	if (new_mtu > ETH_DATA_LEN) {
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+		if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
 			tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
 			ethtool_op_set_tso(dev, 0);
 		}
 		else
 			tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
 	} else {
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+		if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
 			tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
 		tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE;
 	}
@@ -3850,7 +3864,7 @@
 	memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
 
 	tp->rx_pkt_buf_sz = RX_PKT_BUF_SZ;
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) &&
+	if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
 	    (tp->dev->mtu > ETH_DATA_LEN))
 		tp->rx_pkt_buf_sz = RX_JUMBO_PKT_BUF_SZ;
 
@@ -3905,10 +3919,8 @@
  */
 static void tg3_free_consistent(struct tg3 *tp)
 {
-	if (tp->rx_std_buffers) {
-		kfree(tp->rx_std_buffers);
-		tp->rx_std_buffers = NULL;
-	}
+	kfree(tp->rx_std_buffers);
+	tp->rx_std_buffers = NULL;
 	if (tp->rx_std) {
 		pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
 				    tp->rx_std, tp->rx_std_mapping);
@@ -4347,7 +4359,7 @@
 	val &= ~PCIX_CAPS_RELAXED_ORDERING;
 	pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+	if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
 		u32 val;
 
 		/* Chip reset on 5780 will reset MSI enable bit,
@@ -6003,7 +6015,7 @@
 	tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
 
 	if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780))
+	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		limit = 8;
 	else
 		limit = 16;
@@ -6191,14 +6203,16 @@
 		tp->timer_counter = tp->timer_multiplier;
 	}
 
-	/* Heartbeat is only sent once every 120 seconds.  */
+	/* Heartbeat is only sent once every 2 seconds.  */
 	if (!--tp->asf_counter) {
 		if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
 			u32 val;
 
-			tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_ALIVE);
-			tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
-			tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 3);
+			tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
+					   FWCMD_NICDRV_ALIVE2);
+			tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+			/* 5 seconds timeout */
+			tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
 			val = tr32(GRC_RX_CPU_EVENT);
 			val |= (1 << 14);
 			tw32(GRC_RX_CPU_EVENT, val);
@@ -6409,7 +6423,7 @@
 		tp->timer_counter = tp->timer_multiplier =
 			(HZ / tp->timer_offset);
 		tp->asf_counter = tp->asf_multiplier =
-			((HZ / tp->timer_offset) * 120);
+			((HZ / tp->timer_offset) * 2);
 
 		init_timer(&tp->timer);
 		tp->timer.expires = jiffies + tp->timer_offset;
@@ -7237,7 +7251,7 @@
 		cmd->supported |= (SUPPORTED_1000baseT_Half |
 				   SUPPORTED_1000baseT_Full);
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
+	if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
 		cmd->supported |= (SUPPORTED_100baseT_Half |
 				  SUPPORTED_100baseT_Full |
 				  SUPPORTED_10baseT_Half |
@@ -7264,7 +7278,7 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
   
-	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { 
 		/* These are the only valid advertisement bits allowed.  */
 		if (cmd->autoneg == AUTONEG_ENABLE &&
 		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
@@ -7272,7 +7286,17 @@
 					  ADVERTISED_Autoneg |
 					  ADVERTISED_FIBRE)))
 			return -EINVAL;
-	}
+		/* Fiber can only do SPEED_1000.  */
+		else if ((cmd->autoneg != AUTONEG_ENABLE) &&
+			 (cmd->speed != SPEED_1000))
+			return -EINVAL;
+	/* Copper cannot force SPEED_1000.  */
+	} else if ((cmd->autoneg != AUTONEG_ENABLE) &&
+		   (cmd->speed == SPEED_1000))
+		return -EINVAL;
+	else if ((cmd->speed == SPEED_1000) &&
+		 (tp->tg3_flags2 & TG3_FLAG_10_100_ONLY))
+		return -EINVAL;
 
 	tg3_full_lock(tp, 0);
 
@@ -8380,7 +8404,7 @@
 	}
 
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)) {
+	    (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
 		switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
 			case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
 				tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -8980,7 +9004,7 @@
 
 		tp->phy_id = eeprom_phy_id;
 		if (eeprom_phy_serdes) {
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+			if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
 				tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
 			else
 				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
@@ -9393,8 +9417,11 @@
 	}
 
 	/* Find msi capability. */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+		tp->tg3_flags2 |= TG3_FLG2_5780_CLASS;
 		tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
+	}
 
 	/* Initialize misc host control in PCI block. */
 	tp->misc_host_ctrl |= (misc_ctrl_reg &
@@ -9412,7 +9439,7 @@
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+	    (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
@@ -9607,7 +9634,7 @@
 	 * ether_setup() via the alloc_etherdev() call
 	 */
 	if (tp->dev->mtu > ETH_DATA_LEN &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780)
+	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
 
 	/* Determine WakeOnLan speed to use. */
@@ -9830,7 +9857,7 @@
 	mac_offset = 0x7c;
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
 	     !(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+	    (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
 		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
 			mac_offset = 0xcc;
 		if (tg3_nvram_lock(tp))
@@ -10148,6 +10175,9 @@
 		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
 			/* 5780 always in PCIX mode */
 			tp->dma_rwctrl |= 0x00144000;
+		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+			/* 5714 always in PCIX mode */
+			tp->dma_rwctrl |= 0x00148000;
 		} else {
 			tp->dma_rwctrl |= 0x001b000f;
 		}
@@ -10347,6 +10377,7 @@
 	case PHY_ID_BCM5705:	return "5705";
 	case PHY_ID_BCM5750:	return "5750";
 	case PHY_ID_BCM5752:	return "5752";
+	case PHY_ID_BCM5714:	return "5714";
 	case PHY_ID_BCM5780:	return "5780";
 	case PHY_ID_BCM8002:	return "8002/serdes";
 	case 0:			return "serdes";
@@ -10492,17 +10523,17 @@
 	}
 
 	/* Configure DMA attributes. */
-	err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+	err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
 	if (!err) {
 		pci_using_dac = 1;
-		err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+		err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
 		if (err < 0) {
 			printk(KERN_ERR PFX "Unable to obtain 64 bit DMA "
 			       "for consistent allocations\n");
 			goto err_out_free_res;
 		}
 	} else {
-		err = pci_set_dma_mask(pdev, 0xffffffffULL);
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (err) {
 			printk(KERN_ERR PFX "No usable DMA configuration, "
 			       "aborting.\n");
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 2e733c6..fb7e2a5 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -137,6 +137,7 @@
 #define   ASIC_REV_5750			 0x04
 #define   ASIC_REV_5752			 0x06
 #define   ASIC_REV_5780			 0x08
+#define   ASIC_REV_5714			 0x09
 #define  GET_CHIP_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX		 0x70
 #define   CHIPREV_5700_BX		 0x71
@@ -531,6 +532,8 @@
 #define  MAC_SERDES_CFG_EDGE_SELECT	 0x00001000
 #define MAC_SERDES_STAT			0x00000594
 /* 0x598 --> 0x5b0 unused */
+#define SERDES_RX_CTRL			0x000005b0	/* 5780/5714 only */
+#define  SERDES_RX_SIG_DETECT		 0x00000400
 #define SG_DIG_CTRL			0x000005b0
 #define  SG_DIG_USING_HW_AUTONEG	 0x80000000
 #define  SG_DIG_SOFT_RESET		 0x40000000
@@ -1329,6 +1332,8 @@
 #define  GRC_LCLCTRL_CLEARINT		0x00000002
 #define  GRC_LCLCTRL_SETINT		0x00000004
 #define  GRC_LCLCTRL_INT_ON_ATTN	0x00000008
+#define  GRC_LCLCTRL_USE_SIG_DETECT	0x00000010	/* 5714/5780 only */
+#define  GRC_LCLCTRL_USE_EXT_SIG_DETECT	0x00000020	/* 5714/5780 only */
 #define  GRC_LCLCTRL_GPIO_INPUT3	0x00000020
 #define  GRC_LCLCTRL_GPIO_OE3		0x00000040
 #define  GRC_LCLCTRL_GPIO_OUTPUT3	0x00000080
@@ -1507,6 +1512,7 @@
 #define  FWCMD_NICDRV_IPV6ADDR_CHG	 0x00000004
 #define  FWCMD_NICDRV_FIX_DMAR		 0x00000005
 #define  FWCMD_NICDRV_FIX_DMAW		 0x00000006
+#define  FWCMD_NICDRV_ALIVE2		 0x0000000d
 #define NIC_SRAM_FW_CMD_LEN_MBOX	0x00000b7c
 #define NIC_SRAM_FW_CMD_DATA_MBOX	0x00000b80
 #define NIC_SRAM_FW_ASF_STATUS_MBOX	0x00000c00
@@ -2175,6 +2181,7 @@
 					TG3_FLG2_MII_SERDES)
 #define TG3_FLG2_PARALLEL_DETECT	0x01000000
 #define TG3_FLG2_ICH_WORKAROUND		0x02000000
+#define TG3_FLG2_5780_CLASS		0x04000000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -2222,6 +2229,7 @@
 #define PHY_ID_BCM5705			0x600081a0
 #define PHY_ID_BCM5750			0x60008180
 #define PHY_ID_BCM5752			0x60008100
+#define PHY_ID_BCM5714			0x60008340
 #define PHY_ID_BCM5780			0x60008350
 #define PHY_ID_BCM8002			0x60010140
 #define PHY_ID_INVALID			0xffffffff
@@ -2246,8 +2254,8 @@
 	 (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
 	 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
 	 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
-	 (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5780 || \
-	 (X) == PHY_ID_BCM8002)
+	 (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \
+	 (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM8002)
 
 	struct tg3_hw_stats		*hw_stats;
 	dma_addr_t			stats_mapping;
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 32057e6..9f49156 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -318,7 +318,7 @@
 	if (dev->base_addr) {
 		outb(0,dev->base_addr+ADAPTRESET);
 		
-		schedule_timeout(TR_RST_TIME); /* wait 50ms */
+		schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
 
 		outb(0,dev->base_addr+ADAPTRESETREL);
 	}
@@ -854,8 +854,7 @@
 	writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
 	outb(0, PIOaddr + ADAPTRESET);
 
-	current->state=TASK_UNINTERRUPTIBLE;
-	schedule_timeout(TR_RST_TIME); /* wait 50ms */
+	schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */
 
 	outb(0, PIOaddr + ADAPTRESETREL);
 #ifdef ENABLE_PAGING
@@ -903,8 +902,8 @@
 			DPRINTK("Adapter is up and running\n");
 			return 0;
 		}
-		current->state=TASK_INTERRUPTIBLE;
-		i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
+		i=schedule_timeout_interruptible(TR_RETRY_INTERVAL);
+							/* wait 30 seconds */
 		if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
 	}
 	outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 9e79231..05477d2 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -1101,7 +1101,7 @@
 
 	while(olympic_priv->srb_queued) {
 
-		t = schedule_timeout(60*HZ); 
+		t = schedule_timeout_interruptible(60*HZ);
 
         	if(signal_pending(current))	{            
 			printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 2e39bf1..c192559 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -1243,8 +1243,7 @@
 	
 	tmp = jiffies + time/(1000000/HZ);
 	do {
-  		current->state 		= TASK_INTERRUPTIBLE;
-		tmp = schedule_timeout(tmp);
+		tmp = schedule_timeout_interruptible(tmp);
 	} while(time_after(tmp, jiffies));
 #else
 	udelay(time);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index a22d001..d7fb3ff 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1787,10 +1787,15 @@
 	/* DEC now has a specification but early board makers
 	   just put the address in the first EEPROM locations. */
 	/* This does  memcmp(eedata, eedata+16, 8) */
+
+#ifndef CONFIG_MIPS_COBALT
+
 	for (i = 0; i < 8; i ++)
 		if (ee_data[i] != ee_data[16+i])
 			sa_offset = 20;
 
+#endif
+
 	/* store MAC address */
 	for (i = 0; i < 6; i ++)
 		de->dev->dev_addr[i] = ee_data[i + sa_offset];
@@ -2071,8 +2076,7 @@
 	return 0;
 
 err_out_iomap:
-	if (de->ee_data)
-		kfree(de->ee_data);
+	kfree(de->ee_data);
 	iounmap(regs);
 err_out_res:
 	pci_release_regions(pdev);
@@ -2091,8 +2095,7 @@
 	if (!dev)
 		BUG();
 	unregister_netdev(dev);
-	if (de->ee_data)
-		kfree(de->ee_data);
+	kfree(de->ee_data);
 	iounmap(de->regs);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 6266a9a..125ed00 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1727,8 +1727,7 @@
 			     tp->rx_ring, tp->rx_ring_dma);
 
 err_out_mtable:
-	if (tp->mtable)
-		kfree (tp->mtable);
+	kfree (tp->mtable);
 	pci_iounmap(pdev, ioaddr);
 
 err_out_free_res:
@@ -1806,8 +1805,7 @@
 			     sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
 			     sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
 			     tp->rx_ring, tp->rx_ring_dma);
-	if (tp->mtable)
-		kfree (tp->mtable);
+	kfree (tp->mtable);
 	pci_iounmap(pdev, tp->base_addr);
 	free_netdev (dev);
 	pci_release_regions (pdev);
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index ecfa6f8..4c76cb7 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -419,10 +419,9 @@
 			   TYPHOON_STATUS_WAITING_FOR_HOST)
 				goto out;
 
-			if(wait_type == WaitSleep) {
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout(1);
-			} else
+			if(wait_type == WaitSleep)
+				schedule_timeout_uninterruptible(1);
+			else
 				udelay(TYPHOON_UDELAY);
 		}
 
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index fc7738f..241871589 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -490,6 +490,8 @@
 	u8 tx_thresh, rx_thresh;
 
 	struct mii_if_info mii_if;
+	struct work_struct tx_timeout_task;
+	struct work_struct check_media_task;
 	void __iomem *base;
 };
 
@@ -497,6 +499,8 @@
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
 static void rhine_tx_timeout(struct net_device *dev);
+static void rhine_tx_timeout_task(struct net_device *dev);
+static void rhine_check_media_task(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static void rhine_tx(struct net_device *dev);
@@ -814,8 +818,9 @@
 
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	if (!is_valid_ether_addr(dev->dev_addr)) {
+	if (!is_valid_ether_addr(dev->perm_addr)) {
 		rc = -EIO;
 		printk(KERN_ERR "Invalid MAC address\n");
 		goto err_out_unmap;
@@ -850,6 +855,12 @@
 	if (rp->quirks & rqRhineI)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
+	INIT_WORK(&rp->tx_timeout_task,
+		  (void (*)(void *))rhine_tx_timeout_task, dev);
+
+	INIT_WORK(&rp->check_media_task,
+		  (void (*)(void *))rhine_check_media_task, dev);
+
 	/* dev->name not defined before register_netdev()! */
 	rc = register_netdev(dev);
 	if (rc)
@@ -1076,6 +1087,11 @@
 		   ioaddr + ChipCmd1);
 }
 
+static void rhine_check_media_task(struct net_device *dev)
+{
+	rhine_check_media(dev, 0);
+}
+
 static void init_registers(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -1129,8 +1145,8 @@
 	if (quirks & rqRhineI) {
 		iowrite8(0x01, ioaddr + MIIRegAddr);	// MII_BMSR
 
-		/* Can be called from ISR. Evil. */
-		mdelay(1);
+		/* Do not call from ISR! */
+		msleep(1);
 
 		/* 0x80 must be set immediately before turning it off */
 		iowrite8(0x80, ioaddr + MIICmd);
@@ -1220,6 +1236,16 @@
 static void rhine_tx_timeout(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
+
+	/*
+	 * Move bulk of work outside of interrupt context
+	 */
+	schedule_work(&rp->tx_timeout_task);
+}
+
+static void rhine_tx_timeout_task(struct net_device *dev)
+{
+	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 
 	printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
@@ -1625,7 +1651,7 @@
 	spin_lock(&rp->lock);
 
 	if (intr_status & IntrLinkChange)
-		rhine_check_media(dev, 0);
+		schedule_work(&rp->check_media_task);
 	if (intr_status & IntrStatsMax) {
 		rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
 		rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1829,6 +1855,7 @@
 	.set_wol		= rhine_set_wol,
 	.get_sg			= ethtool_op_get_sg,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1872,6 +1899,9 @@
 	spin_unlock_irq(&rp->lock);
 
 	free_irq(rp->pdev->irq, dev);
+
+	flush_scheduled_work();
+
 	free_rbufs(dev);
 	free_tbufs(dev);
 	free_ring(dev);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index abc5cee..a368d08 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1212,10 +1212,8 @@
 			velocity_free_td_ring_entry(vptr, j, i);
 
 		}
-		if (vptr->td_infos[j]) {
-			kfree(vptr->td_infos[j]);
-			vptr->td_infos[j] = NULL;
-		}
+		kfree(vptr->td_infos[j]);
+		vptr->td_infos[j] = NULL;
 	}
 }
 
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7ff814f..e392ee8 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -400,7 +400,7 @@
 		goto out_chrdev;
 	}
 	for (i=0; i<nr_cards; i++) {
-		class_device_create(cosa_class, MKDEV(cosa_major, i),
+		class_device_create(cosa_class, NULL, MKDEV(cosa_major, i),
 				NULL, "cosa%d", i);
 		err = devfs_mk_cdev(MKDEV(cosa_major, i),
 				S_IFCHR|S_IRUSR|S_IWUSR,
@@ -1617,8 +1617,7 @@
 			return r;
 		}
 		/* sleep if not ready to read */
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(1);
+		schedule_timeout_interruptible(1);
 	}
 	printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
 		cosa_getstatus(cosa));
@@ -1644,8 +1643,7 @@
 		}
 #if 0
 		/* sleep if not ready to read */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
+		schedule_timeout_interruptible(1);
 #endif
 	}
 	printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index 9e56fc3..e6d0057 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -109,7 +109,7 @@
  *		< 0	error.
  * Context:	process */
 
-int __init cycx_drv_init(void)
+static int __init cycx_drv_init(void)
 {
 	printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
 			 copyright);
@@ -119,7 +119,7 @@
 
 /* Module 'remove' entry point.
  * o release all remaining system resources */
-void cycx_drv_cleanup(void)
+static void cycx_drv_cleanup(void)
 {
 }
 
@@ -184,8 +184,7 @@
 }
 
 /* Enable interrupt generation.  */
-EXPORT_SYMBOL(cycx_inten);
-void cycx_inten(struct cycx_hw *hw)
+static void cycx_inten(struct cycx_hw *hw)
 {
 	writeb(0, hw->dpmbase);
 }
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 7b48064..430b1f6 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -103,7 +103,7 @@
  *		< 0	error.
  * Context:	process
  */
-int __init cycx_init(void)
+static int __init cycx_init(void)
 {
 	int cnt, err = -ENOMEM;
 
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index 02d57c0..a631d1c 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -78,6 +78,7 @@
 
 #define CYCLOMX_X25_DEBUG 1
 
+#include <linux/ctype.h>	/* isdigit() */
 #include <linux/errno.h>	/* return codes */
 #include <linux/if_arp.h>       /* ARPHRD_HWX25 */
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
@@ -418,7 +419,7 @@
 
 		/* Set channel timeouts (default if not specified) */
 		chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
-	} else if (is_digit(conf->addr[0])) {	/* PVC */
+	} else if (isdigit(conf->addr[0])) {	/* PVC */
 		s16 lcn = dec_to_uint(conf->addr, 0);
 
 		if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
@@ -1531,7 +1532,7 @@
 	if (!len)
 		len = strlen(str);
 
-	for (; len && is_digit(*str); ++str, --len)
+	for (; len && isdigit(*str); ++str, --len)
 		val = (val * 10) + (*str - (unsigned) '0');
 
 	return val;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 520a77a..2f61a47 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -446,8 +446,8 @@
 	return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda;
 }
 
-int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev,
-		const char *msg)
+static int state_check(u32 state, struct dscc4_dev_priv *dpriv,
+		       struct net_device *dev, const char *msg)
 {
 	int ret = 0;
 
@@ -466,8 +466,9 @@
 	return ret;
 }
 
-void dscc4_tx_print(struct net_device *dev, struct dscc4_dev_priv *dpriv,
-		    char *msg)
+static void dscc4_tx_print(struct net_device *dev,
+			   struct dscc4_dev_priv *dpriv,
+			   char *msg)
 {
 	printk(KERN_DEBUG "%s: tx_current=%02d tx_dirty=%02d (%s)\n",
 	       dev->name, dpriv->tx_current, dpriv->tx_dirty, msg);
@@ -507,7 +508,8 @@
 	}
 }
 
-inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv,
+				 struct net_device *dev)
 {
 	unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE;
 	struct RxFD *rx_fd = dpriv->rx_fd + dirty;
@@ -542,8 +544,7 @@
 			       msg, i);
 			goto done;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(10);
+		schedule_timeout_uninterruptible(10);
 		rmb();
 	} while (++i > 0);
 	printk(KERN_ERR "%s: %s timeout\n", dev->name, msg);
@@ -588,8 +589,7 @@
 		    (dpriv->iqtx[cur] & Xpr))
 			break;
 		smp_rmb();
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(10);
+		schedule_timeout_uninterruptible(10);
 	} while (++i > 0);
 
 	return (i >= 0 ) ? i : -EAGAIN;
@@ -1035,8 +1035,7 @@
 	/* Flush posted writes */
 	readl(ioaddr + GSTAR);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(10);
+	schedule_timeout_uninterruptible(10);
 
 	for (i = 0; i < 16; i++)
 		pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
@@ -1894,7 +1893,7 @@
  * It failed and locked solid. Thus the introduction of a dummy skb.
  * Problem is acknowledged in errata sheet DS5. Joy :o/
  */
-struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
+static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv)
 {
 	struct sk_buff *skb;
 
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 2c83cca..7981a2c 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -74,11 +74,11 @@
 /*
  * Modules parameters and associated varaibles
  */
-int fst_txq_low = FST_LOW_WATER_MARK;
-int fst_txq_high = FST_HIGH_WATER_MARK;
-int fst_max_reads = 7;
-int fst_excluded_cards = 0;
-int fst_excluded_list[FST_MAX_CARDS];
+static int fst_txq_low = FST_LOW_WATER_MARK;
+static int fst_txq_high = FST_HIGH_WATER_MARK;
+static int fst_max_reads = 7;
+static int fst_excluded_cards = 0;
+static int fst_excluded_list[FST_MAX_CARDS];
 
 module_param(fst_txq_low, int, 0);
 module_param(fst_txq_high, int, 0);
@@ -572,13 +572,13 @@
 static void fst_process_tx_work_q(unsigned long work_q);
 static void fst_process_int_work_q(unsigned long work_q);
 
-DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
-DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
+static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
 
-struct fst_card_info *fst_card_array[FST_MAX_CARDS];
-spinlock_t fst_work_q_lock;
-u64 fst_work_txq;
-u64 fst_work_intq;
+static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
+static spinlock_t fst_work_q_lock;
+static u64 fst_work_txq;
+static u64 fst_work_intq;
 
 static void
 fst_q_work_item(u64 * queue, int card_index)
@@ -980,8 +980,7 @@
 	/* Wait for any previous command to complete */
 	while (mbval > NAK) {
 		spin_unlock_irqrestore(&card->card_lock, flags);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
+		schedule_timeout_uninterruptible(1);
 		spin_lock_irqsave(&card->card_lock, flags);
 
 		if (++safety > 2000) {
@@ -1498,7 +1497,7 @@
  *      The interrupt service routine
  *      Dev_id is our fst_card_info pointer
  */
-irqreturn_t
+static irqreturn_t
 fst_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct fst_card_info *card;
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index a5d6891..e1601d3 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -330,7 +330,7 @@
 
 
 
-int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	pvc_device *pvc = dev_to_pvc(dev);
 	fr_proto_pvc_info info;
diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c
index 9dccd95..3b94352 100644
--- a/drivers/net/wan/lmc/lmc_debug.c
+++ b/drivers/net/wan/lmc/lmc_debug.c
@@ -8,10 +8,10 @@
 /*
  * Prints out len, max to 80 octets using printk, 20 per line
  */
-void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
-{
 #ifdef DEBUG
 #ifdef LMC_PACKET_LOG
+void lmcConsoleLog(char *type, unsigned char *ucData, int iLen)
+{
   int iNewLine = 1;
   char str[80], *pstr;
   
@@ -43,26 +43,24 @@
     }
   sprintf(pstr, "\n");
   printk(str);
-#endif
-#endif
 }
+#endif
+#endif
 
 #ifdef DEBUG
 u_int32_t lmcEventLogIndex = 0;
 u_int32_t lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS];
-#endif
 
 void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
 {
-#ifdef DEBUG
   lmcEventLogBuf[lmcEventLogIndex++] = EventNum;
   lmcEventLogBuf[lmcEventLogIndex++] = arg2;
   lmcEventLogBuf[lmcEventLogIndex++] = arg3;
   lmcEventLogBuf[lmcEventLogIndex++] = jiffies;
 
   lmcEventLogIndex &= (LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS) - 1;
-#endif
 }
+#endif  /*  DEBUG  */
 
 void lmc_trace(struct net_device *dev, char *msg){
 #ifdef LMC_TRACE
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c
index f55ce76..af8b55f 100644
--- a/drivers/net/wan/lmc/lmc_media.c
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -48,14 +48,6 @@
   */
 
 /*
- * For lack of a better place, put the SSI cable stuff here.
- */
-char *lmc_t1_cables[] = {
-  "V.10/RS423", "EIA530A", "reserved", "X.21", "V.35",
-  "EIA449/EIA530/V.36", "V.28/EIA232", "none", NULL
-};
-
-/*
  * protocol independent method.
  */
 static void lmc_set_protocol (lmc_softc_t * const, lmc_ctl_t *);
diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h
index 73401b0..2024b26 100644
--- a/drivers/net/wan/pc300.h
+++ b/drivers/net/wan/pc300.h
@@ -472,24 +472,8 @@
 
 #ifdef __KERNEL__
 /* Function Prototypes */
-int dma_buf_write(pc300_t *, int, ucchar *, int);
-int dma_buf_read(pc300_t *, int, struct sk_buff *);
 void tx_dma_start(pc300_t *, int);
-void rx_dma_start(pc300_t *, int);
-void tx_dma_stop(pc300_t *, int);
-void rx_dma_stop(pc300_t *, int);
-int cpc_queue_xmit(struct sk_buff *, struct net_device *);
-void cpc_net_rx(struct net_device *);
-void cpc_sca_status(pc300_t *, int);
-int cpc_change_mtu(struct net_device *, int);
-int cpc_ioctl(struct net_device *, struct ifreq *, int);
-int ch_config(pc300dev_t *);
-int rx_config(pc300dev_t *);
-int tx_config(pc300dev_t *);
-void cpc_opench(pc300dev_t *);
-void cpc_closech(pc300dev_t *);
 int cpc_open(struct net_device *dev);
-int cpc_close(struct net_device *dev);
 int cpc_set_media(hdlc_device *, int);
 #endif /* __KERNEL__ */
 
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 3e7753b..a3e65d1 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -291,6 +291,7 @@
 static void plx_init(pc300_t *);
 static void cpc_trace(struct net_device *, struct sk_buff *, char);
 static int cpc_attach(struct net_device *, unsigned short, unsigned short);
+static int cpc_close(struct net_device *dev);
 
 #ifdef CONFIG_PC300_MLPPP
 void cpc_tty_init(pc300dev_t * dev);
@@ -437,7 +438,7 @@
 	printk("\n");
 }
 
-int dma_get_rx_frame_size(pc300_t * card, int ch)
+static int dma_get_rx_frame_size(pc300_t * card, int ch)
 {
 	volatile pcsca_bd_t __iomem *ptdescr;
 	ucshort first_bd = card->chan[ch].rx_first_bd;
@@ -462,7 +463,7 @@
  * dma_buf_write: writes a frame to the Tx DMA buffers
  * NOTE: this function writes one frame at a time.
  */
-int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
+static int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
 {
 	int i, nchar;
 	volatile pcsca_bd_t __iomem *ptdescr;
@@ -503,7 +504,7 @@
  * dma_buf_read: reads a frame from the Rx DMA buffers
  * NOTE: this function reads one frame at a time.
  */
-int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
+static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 {
 	int nchar;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -560,7 +561,7 @@
 	return (rcvd);
 }
 
-void tx_dma_stop(pc300_t * card, int ch)
+static void tx_dma_stop(pc300_t * card, int ch)
 {
 	void __iomem *scabase = card->hw.scabase;
 	ucchar drr_ena_bit = 1 << (5 + 2 * ch);
@@ -571,7 +572,7 @@
 	cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
 }
 
-void rx_dma_stop(pc300_t * card, int ch)
+static void rx_dma_stop(pc300_t * card, int ch)
 {
 	void __iomem *scabase = card->hw.scabase;
 	ucchar drr_ena_bit = 1 << (4 + 2 * ch);
@@ -582,7 +583,7 @@
 	cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
 }
 
-void rx_dma_start(pc300_t * card, int ch)
+static void rx_dma_start(pc300_t * card, int ch)
 {
 	void __iomem *scabase = card->hw.scabase;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -607,7 +608,7 @@
 /*************************/
 /***   FALC Routines   ***/
 /*************************/
-void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
+static void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
 {
 	void __iomem *falcbase = card->hw.falcbase;
 	unsigned long i = 0;
@@ -622,7 +623,7 @@
 	cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
 }
 
-void falc_intr_enable(pc300_t * card, int ch)
+static void falc_intr_enable(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -672,7 +673,7 @@
 	}
 }
 
-void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 {
 	void __iomem *falcbase = card->hw.falcbase;
 	ucchar tshf = card->chan[ch].falc.offset;
@@ -688,7 +689,7 @@
 			(0x80 >> (timeslot & 0x07)));
 }
 
-void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
+static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
 {
 	void __iomem *falcbase = card->hw.falcbase;
 	ucchar tshf = card->chan[ch].falc.offset;
@@ -704,7 +705,7 @@
 		   ~(0x80 >> (timeslot & 0x07)));
 }
 
-void falc_close_all_timeslots(pc300_t * card, int ch)
+static void falc_close_all_timeslots(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -726,7 +727,7 @@
 	}
 }
 
-void falc_open_all_timeslots(pc300_t * card, int ch)
+static void falc_open_all_timeslots(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -758,7 +759,7 @@
 	}
 }
 
-void falc_init_timeslot(pc300_t * card, int ch)
+static void falc_init_timeslot(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -776,7 +777,7 @@
 	}
 }
 
-void falc_enable_comm(pc300_t * card, int ch)
+static void falc_enable_comm(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
@@ -792,7 +793,7 @@
 		   ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
 }
 
-void falc_disable_comm(pc300_t * card, int ch)
+static void falc_disable_comm(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
@@ -806,7 +807,7 @@
 		   ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
 }
 
-void falc_init_t1(pc300_t * card, int ch)
+static void falc_init_t1(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -975,7 +976,7 @@
 	falc_close_all_timeslots(card, ch);
 }
 
-void falc_init_e1(pc300_t * card, int ch)
+static void falc_init_e1(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1155,7 +1156,7 @@
 	falc_close_all_timeslots(card, ch);
 }
 
-void falc_init_hdlc(pc300_t * card, int ch)
+static void falc_init_hdlc(pc300_t * card, int ch)
 {
 	void __iomem *falcbase = card->hw.falcbase;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
@@ -1181,7 +1182,7 @@
 	falc_intr_enable(card, ch);
 }
 
-void te_config(pc300_t * card, int ch)
+static void te_config(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1241,7 +1242,7 @@
 	CPC_UNLOCK(card, flags);
 }
 
-void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
+static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1397,7 +1398,7 @@
 	}
 }
 
-void falc_update_stats(pc300_t * card, int ch)
+static void falc_update_stats(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1450,7 +1451,7 @@
  *		the synchronizer and then sent to the system interface.
  *----------------------------------------------------------------------------
  */
-void falc_remote_loop(pc300_t * card, int ch, int loop_on)
+static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1495,7 +1496,7 @@
  *		coding must be identical.
  *----------------------------------------------------------------------------
  */
-void falc_local_loop(pc300_t * card, int ch, int loop_on)
+static void falc_local_loop(pc300_t * card, int ch, int loop_on)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1522,7 +1523,7 @@
  *		looped. They are originated by the FALC-LH transmitter.
  *----------------------------------------------------------------------------
  */
-void falc_payload_loop(pc300_t * card, int ch, int loop_on)
+static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1576,7 +1577,7 @@
  * Description:	Turns XLU bit off in the proper register
  *----------------------------------------------------------------------------
  */
-void turn_off_xlu(pc300_t * card, int ch)
+static void turn_off_xlu(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1597,7 +1598,7 @@
  * Description: Turns XLD bit off in the proper register
  *----------------------------------------------------------------------------
  */
-void turn_off_xld(pc300_t * card, int ch)
+static void turn_off_xld(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1619,7 +1620,7 @@
  *		to generate a LOOP activation code over a T1/E1 line.
  *----------------------------------------------------------------------------
  */
-void falc_generate_loop_up_code(pc300_t * card, int ch)
+static void falc_generate_loop_up_code(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1652,7 +1653,7 @@
  *		to generate a LOOP deactivation code over a T1/E1 line.
  *----------------------------------------------------------------------------
  */
-void falc_generate_loop_down_code(pc300_t * card, int ch)
+static void falc_generate_loop_down_code(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1682,7 +1683,7 @@
  *		it on the reception side.
  *----------------------------------------------------------------------------
  */
-void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
+static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -1729,7 +1730,7 @@
  * Description:	This routine returns the bit error counter value
  *----------------------------------------------------------------------------
  */
-ucshort falc_pattern_test_error(pc300_t * card, int ch)
+static ucshort falc_pattern_test_error(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
@@ -1769,7 +1770,7 @@
 	netif_rx(skb);
 }
 
-void cpc_tx_timeout(struct net_device *dev)
+static void cpc_tx_timeout(struct net_device *dev)
 {
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1797,7 +1798,7 @@
 	netif_wake_queue(dev);
 }
 
-int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -1880,7 +1881,7 @@
 	return 0;
 }
 
-void cpc_net_rx(struct net_device *dev)
+static void cpc_net_rx(struct net_device *dev)
 {
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
@@ -2403,7 +2404,7 @@
 	return IRQ_HANDLED;
 }
 
-void cpc_sca_status(pc300_t * card, int ch)
+static void cpc_sca_status(pc300_t * card, int ch)
 {
 	ucchar ilar;
 	void __iomem *scabase = card->hw.scabase;
@@ -2495,7 +2496,7 @@
 	}
 }
 
-void cpc_falc_status(pc300_t * card, int ch)
+static void cpc_falc_status(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = &card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
@@ -2523,7 +2524,7 @@
 	CPC_UNLOCK(card, flags);
 }
 
-int cpc_change_mtu(struct net_device *dev, int new_mtu)
+static int cpc_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
 		return -EINVAL;
@@ -2531,7 +2532,7 @@
 	return 0;
 }
 
-int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
@@ -2856,7 +2857,7 @@
 	}
 }
 
-int ch_config(pc300dev_t * d)
+static int ch_config(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
@@ -3004,7 +3005,7 @@
 	return 0;
 }
 
-int rx_config(pc300dev_t * d)
+static int rx_config(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
@@ -3035,7 +3036,7 @@
 	return 0;
 }
 
-int tx_config(pc300dev_t * d)
+static int tx_config(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
@@ -3098,7 +3099,7 @@
 	return 0;
 }
 
-void cpc_opench(pc300dev_t * d)
+static void cpc_opench(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
@@ -3116,7 +3117,7 @@
 		   cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
 }
 
-void cpc_closech(pc300dev_t * d)
+static void cpc_closech(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
@@ -3173,7 +3174,7 @@
 	return 0;
 }
 
-int cpc_close(struct net_device *dev)
+static int cpc_close(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	pc300dev_t *d = (pc300dev_t *) dev->priv;
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 8454bf6..52f26b9 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -112,10 +112,10 @@
 static struct tty_driver serial_drv;
 
 /* local variables */
-st_cpc_tty_area	cpc_tty_area[CPC_TTY_NPORTS];
+static st_cpc_tty_area	cpc_tty_area[CPC_TTY_NPORTS];
 
-int cpc_tty_cnt=0;	/* number of intrfaces configured with MLPPP */
-int cpc_tty_unreg_flag = 0;
+static int cpc_tty_cnt = 0;	/* number of intrfaces configured with MLPPP */
+static int cpc_tty_unreg_flag = 0;
 
 /* TTY functions prototype */
 static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
@@ -132,9 +132,9 @@
 static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
 static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
 
-int pc300_tiocmset(struct tty_struct *, struct file *,
-			unsigned int, unsigned int);
-int pc300_tiocmget(struct tty_struct *, struct file *);
+static int pc300_tiocmset(struct tty_struct *, struct file *,
+			  unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *, struct file *);
 
 /* functions called by PC300 driver */
 void cpc_tty_init(pc300dev_t *dev);
@@ -538,8 +538,8 @@
 	return(0); 
 } 
 
-int pc300_tiocmset(struct tty_struct *tty, struct file *file,
-			unsigned int set, unsigned int clear)
+static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+			  unsigned int set, unsigned int clear)
 {
 	st_cpc_tty_area    *cpc_tty; 
 
@@ -565,7 +565,7 @@
 	return 0;
 }
 
-int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	unsigned int result;
 	unsigned char status;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 3ac9a45..036adc4 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -182,7 +182,7 @@
 	return(byte);
 }
 
-void sdla_stop(struct net_device *dev)
+static void sdla_stop(struct net_device *dev)
 {
 	struct frad_local *flp;
 
@@ -209,7 +209,7 @@
 	}
 }
 
-void sdla_start(struct net_device *dev)
+static void sdla_start(struct net_device *dev)
 {
 	struct frad_local *flp;
 
@@ -247,7 +247,7 @@
  *
  ***************************************************/
 
-int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
+static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
 {
 	unsigned long start, done, now;
 	char          resp, *temp;
@@ -505,7 +505,7 @@
 
 static int sdla_reconfig(struct net_device *dev);
 
-int sdla_activate(struct net_device *slave, struct net_device *master)
+static int sdla_activate(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int i;
@@ -527,7 +527,7 @@
 	return(0);
 }
 
-int sdla_deactivate(struct net_device *slave, struct net_device *master)
+static int sdla_deactivate(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int               i;
@@ -549,7 +549,7 @@
 	return(0);
 }
 
-int sdla_assoc(struct net_device *slave, struct net_device *master)
+static int sdla_assoc(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int               i;
@@ -585,7 +585,7 @@
 	return(0);
 }
 
-int sdla_deassoc(struct net_device *slave, struct net_device *master)
+static int sdla_deassoc(struct net_device *slave, struct net_device *master)
 {
 	struct frad_local *flp;
 	int               i;
@@ -613,7 +613,7 @@
 	return(0);
 }
 
-int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
+static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
 {
 	struct frad_local *flp;
 	struct dlci_local *dlp;
@@ -1324,7 +1324,7 @@
 	return(0);
 }
 
-int sdla_change_mtu(struct net_device *dev, int new_mtu)
+static int sdla_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct frad_local *flp;
 
@@ -1337,7 +1337,7 @@
 	return(-EOPNOTSUPP);
 }
 
-int sdla_set_config(struct net_device *dev, struct ifmap *map)
+static int sdla_set_config(struct net_device *dev, struct ifmap *map)
 {
 	struct frad_local *flp;
 	int               i;
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index 0497dbd..7f1ce9d 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -822,7 +822,7 @@
 	chan->card = card;
 
 	/* verify media address */
-	if (is_digit(conf->addr[0])) {
+	if (isdigit(conf->addr[0])) {
 
 		dlci = dec_to_uint(conf->addr, 0);
 
@@ -3456,7 +3456,7 @@
 	if (!len) 
 		len = strlen(str);
 
-	for (val = 0; len && is_digit(*str); ++str, --len)
+	for (val = 0; len && isdigit(*str); ++str, --len)
 		val = (val * 10) + (*str - (unsigned)'0');
 
 	return val;
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
index 8a95d61..63f846d 100644
--- a/drivers/net/wan/sdla_x25.c
+++ b/drivers/net/wan/sdla_x25.c
@@ -957,7 +957,7 @@
 		chan->hold_timeout = (conf->hold_timeout) ? 
 					conf->hold_timeout : 10;
 
-	}else if (is_digit(conf->addr[0])){	/* PVC */
+	}else if (isdigit(conf->addr[0])){	/* PVC */
 		int lcn = dec_to_uint(conf->addr, 0);
 
 		if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
@@ -3875,7 +3875,7 @@
 	if (!len) 
 		len = strlen(str);
 
-	for (val = 0; len && is_digit(*str); ++str, --len)
+	for (val = 0; len && isdigit(*str); ++str, --len)
 		val = (val * 10) + (*str - (unsigned)'0');
 	
 	return val;
@@ -3896,9 +3896,9 @@
 	for (val = 0; len; ++str, --len)
 	{
 		ch = *str;
-		if (is_digit(ch))
+		if (isdigit(ch))
 			val = (val << 4) + (ch - (unsigned)'0');
-		else if (is_hex_digit(ch))
+		else if (isxdigit(ch))
 			val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
 		else break;
 	}
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
index c8bc6da..7c2cf2e 100644
--- a/drivers/net/wan/sdladrv.c
+++ b/drivers/net/wan/sdladrv.c
@@ -642,9 +642,7 @@
  * Enable interrupt generation.
  */
 
-EXPORT_SYMBOL(sdla_inten);
-
-int sdla_inten (sdlahw_t* hw)
+static int sdla_inten (sdlahw_t* hw)
 {
 	unsigned port = hw->port;
 	int tmp, i;
@@ -698,8 +696,7 @@
  * Disable interrupt generation.
  */
 
-EXPORT_SYMBOL(sdla_intde);
-
+#if 0
 int sdla_intde (sdlahw_t* hw)
 {
 	unsigned port = hw->port;
@@ -748,14 +745,13 @@
 	}
 	return 0;
 }
+#endif  /*  0  */
 
 /*============================================================================
  * Acknowledge SDLA hardware interrupt.
  */
 
-EXPORT_SYMBOL(sdla_intack);
-
-int sdla_intack (sdlahw_t* hw)
+static int sdla_intack (sdlahw_t* hw)
 {
 	unsigned port = hw->port;
 	int tmp;
@@ -827,8 +823,7 @@
  * Generate an interrupt to adapter's CPU.
  */
 
-EXPORT_SYMBOL(sdla_intr);
-
+#if 0
 int sdla_intr (sdlahw_t* hw)
 {
 	unsigned port = hw->port;
@@ -863,6 +858,7 @@
 	}
 	return 0;
 }
+#endif  /*  0  */
 
 /*============================================================================
  * Execute Adapter Command.
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index a6d3b55..2d1bba0 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -221,7 +221,7 @@
  *	here.
  */
  
-void sppp_input (struct net_device *dev, struct sk_buff *skb)
+static void sppp_input (struct net_device *dev, struct sk_buff *skb)
 {
 	struct ppp_header *h;
 	struct sppp *sp = (struct sppp *)sppp_of(dev);
@@ -355,8 +355,6 @@
 	return;
 }
 
-EXPORT_SYMBOL(sppp_input);
-
 /*
  *	Handle transmit packets.
  */
@@ -990,7 +988,7 @@
  *	the mtu is out of range.
  */
  
-int sppp_change_mtu(struct net_device *dev, int new_mtu)
+static int sppp_change_mtu(struct net_device *dev, int new_mtu)
 {
 	if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
 		return -EINVAL;
@@ -998,8 +996,6 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(sppp_change_mtu);
-
 /**
  *	sppp_do_ioctl - Ioctl handler for ppp/hdlc
  *	@dev: Device subject to ioctl
@@ -1456,7 +1452,7 @@
 	return 0;
 }
 
-struct packet_type sppp_packet_type = {
+static struct packet_type sppp_packet_type = {
 	.type	= __constant_htons(ETH_P_WAN_PPP),
 	.func	= sppp_rcv,
 };
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 06998c2..750c016 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -35,6 +35,7 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/bitops.h>
+#include <linux/scatterlist.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -1046,7 +1047,6 @@
 	}
 };
 
-#ifdef WIRELESS_EXT
 // Frequency list (map channels to frequencies)
 static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
 				2447, 2452, 2457, 2462, 2467, 2472, 2484 };
@@ -1067,7 +1067,6 @@
 
 /* List of Wireless Handlers (new API) */
 static const struct iw_handler_def	airo_handler_def;
-#endif /* WIRELESS_EXT */
 
 static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
 
@@ -1110,10 +1109,8 @@
 static int airo_thread(void *data);
 static void timer_func( struct net_device *dev );
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#ifdef WIRELESS_EXT
 static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
 static void airo_read_wireless_stats (struct airo_info *local);
-#endif /* WIRELESS_EXT */
 #ifdef CISCO_EXT
 static int readrids(struct net_device *dev, aironet_ioctl *comp);
 static int writerids(struct net_device *dev, aironet_ioctl *comp);
@@ -1187,12 +1184,10 @@
 		int fid;
 	} xmit, xmit11;
 	struct net_device *wifidev;
-#ifdef WIRELESS_EXT
 	struct iw_statistics	wstats;		// wireless stats
 	unsigned long		scan_timestamp;	/* Time started to scan */
 	struct iw_spy_data	spy_data;
 	struct iw_public_data	wireless_data;
-#endif /* WIRELESS_EXT */
 #ifdef MICSUPPORT
 	/* MIC stuff */
 	struct crypto_tfm	*tfm;
@@ -1596,11 +1591,9 @@
 		aes_counter[12] = (u8)(counter >> 24);
 		counter++;
 		memcpy (plain, aes_counter, 16);
-		sg[0].page = virt_to_page(plain);
-		sg[0].offset = ((long) plain & ~PAGE_MASK);
-		sg[0].length = 16;
+		sg_set_buf(sg, plain, 16);
 		crypto_cipher_encrypt(tfm, sg, sg, 16);
-		cipher = kmap(sg[0].page) + sg[0].offset;
+		cipher = kmap(sg->page) + sg->offset;
 		for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
 			context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
 			j += 4;
@@ -2387,14 +2380,10 @@
 			dev_kfree_skb(skb);
 	}
 
-	if (ai->flash)
-		kfree(ai->flash);
-	if (ai->rssi)
-		kfree(ai->rssi);
-	if (ai->APList)
-		kfree(ai->APList);
-	if (ai->SSID)
-		kfree(ai->SSID);
+	kfree(ai->flash);
+	kfree(ai->rssi);
+	kfree(ai->APList);
+	kfree(ai->SSID);
 	if (freeres) {
 		/* PCMCIA frees this stuff, so only for PCI and ISA */
 	        release_region( dev->base_addr, 64 );
@@ -2527,7 +2516,8 @@
 	unsigned long mem_start, mem_len, aux_start, aux_len;
 	int rc = -1;
 	int i;
-	unsigned char *busaddroff,*vpackoff;
+	dma_addr_t busaddroff;
+	unsigned char *vpackoff;
 	unsigned char __iomem *pciaddroff;
 
 	mem_start = pci_resource_start(pci, 1);
@@ -2570,7 +2560,7 @@
 	/*
 	 * Setup descriptor RX, TX, CONFIG
 	 */
-	busaddroff = (unsigned char *)ai->shared_dma;
+	busaddroff = ai->shared_dma;
 	pciaddroff = ai->pciaux + AUX_OFFSET;
 	vpackoff   = ai->shared;
 
@@ -2579,7 +2569,7 @@
 		ai->rxfids[i].pending = 0;
 		ai->rxfids[i].card_ram_off = pciaddroff;
 		ai->rxfids[i].virtual_host_addr = vpackoff;
-		ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
+		ai->rxfids[i].rx_desc.host_addr = busaddroff;
 		ai->rxfids[i].rx_desc.valid = 1;
 		ai->rxfids[i].rx_desc.len = PKTSIZE;
 		ai->rxfids[i].rx_desc.rdy = 0;
@@ -2594,7 +2584,7 @@
 		ai->txfids[i].card_ram_off = pciaddroff;
 		ai->txfids[i].virtual_host_addr = vpackoff;
 		ai->txfids[i].tx_desc.valid = 1;
-		ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
+		ai->txfids[i].tx_desc.host_addr = busaddroff;
 		memcpy(ai->txfids[i].virtual_host_addr,
 			&wifictlhdr8023, sizeof(wifictlhdr8023));
 
@@ -2607,8 +2597,8 @@
 	/* Rid descriptor setup */
 	ai->config_desc.card_ram_off = pciaddroff;
 	ai->config_desc.virtual_host_addr = vpackoff;
-	ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
-	ai->ridbus = (dma_addr_t)busaddroff;
+	ai->config_desc.rid_desc.host_addr = busaddroff;
+	ai->ridbus = busaddroff;
 	ai->config_desc.rid_desc.rid = 0;
 	ai->config_desc.rid_desc.len = RIDSIZE;
 	ai->config_desc.rid_desc.valid = 1;
@@ -2647,9 +2637,7 @@
 	dev->get_stats = &airo_get_stats;
 	dev->set_mac_address = &airo_set_mac_address;
 	dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
 	dev->wireless_handlers = &airo_handler_def;
-#endif /* WIRELESS_EXT */
 	dev->change_mtu = &airo_change_mtu;
 	dev->open = &airo_open;
 	dev->stop = &airo_close;
@@ -2675,9 +2663,7 @@
 	dev->priv = ethdev->priv;
 	dev->irq = ethdev->irq;
 	dev->base_addr = ethdev->base_addr;
-#ifdef WIRELESS_EXT
 	dev->wireless_data = ethdev->wireless_data;
-#endif /* WIRELESS_EXT */
 	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
 	err = register_netdev(dev);
 	if (err<0) {
@@ -2755,11 +2741,9 @@
 	dev->set_multicast_list = &airo_set_multicast_list;
 	dev->set_mac_address = &airo_set_mac_address;
 	dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
 	dev->wireless_handlers = &airo_handler_def;
 	ai->wireless_data.spy_data = &ai->spy_data;
 	dev->wireless_data = &ai->wireless_data;
-#endif /* WIRELESS_EXT */
 	dev->change_mtu = &airo_change_mtu;
 	dev->open = &airo_open;
 	dev->stop = &airo_close;
@@ -3637,10 +3621,8 @@
 	int rc;
 
 	memset( &mySsid, 0, sizeof( mySsid ) );
-	if (ai->flash) {
-		kfree (ai->flash);
-		ai->flash = NULL;
-	}
+	kfree (ai->flash);
+	ai->flash = NULL;
 
 	/* The NOP is the first step in getting the card going */
 	cmd.cmd = NOP;
@@ -3677,14 +3659,10 @@
 		tdsRssiRid rssi_rid;
 		CapabilityRid cap_rid;
 
-		if (ai->APList) {
-			kfree(ai->APList);
-			ai->APList = NULL;
-		}
-		if (ai->SSID) {
-			kfree(ai->SSID);
-			ai->SSID = NULL;
-		}
+		kfree(ai->APList);
+		ai->APList = NULL;
+		kfree(ai->SSID);
+		ai->SSID = NULL;
 		// general configuration (read/modify/write)
 		status = readConfigRid(ai, lock);
 		if ( status != SUCCESS ) return ERROR;
@@ -3698,10 +3676,8 @@
 				memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
 		}
 		else {
-			if (ai->rssi) {
-				kfree(ai->rssi);
-				ai->rssi = NULL;
-			}
+			kfree(ai->rssi);
+			ai->rssi = NULL;
 			if (cap_rid.softCap & 8)
 				ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
 			else
@@ -5380,11 +5356,13 @@
 
 static int proc_close( struct inode *inode, struct file *file )
 {
-	struct proc_data *data = (struct proc_data *)file->private_data;
-	if ( data->on_close != NULL ) data->on_close( inode, file );
-	if ( data->rbuffer ) kfree( data->rbuffer );
-	if ( data->wbuffer ) kfree( data->wbuffer );
-	kfree( data );
+	struct proc_data *data = file->private_data;
+
+	if (data->on_close != NULL)
+		data->on_close(inode, file);
+	kfree(data->rbuffer);
+	kfree(data->wbuffer);
+	kfree(data);
 	return 0;
 }
 
@@ -5515,12 +5493,13 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct airo_info *ai = dev->priv;
 	Resp rsp;
+	pci_power_t prev_state = pdev->current_state;
 
-	pci_set_power_state(pdev, 0);
+	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
+	pci_enable_wake(pdev, PCI_D0, 0);
 
-	if (ai->power.event > 1) {
+	if (prev_state != PCI_D1) {
 		reset_card(dev, 0);
 		mpi_init_descriptors(ai);
 		setup_card(ai, dev->dev_addr, 0);
@@ -5598,7 +5577,6 @@
 	remove_proc_entry("aironet", proc_root_driver);
 }
 
-#ifdef WIRELESS_EXT
 /*
  * Initial Wireless Extension code for Aironet driver by :
  *	Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
@@ -7107,8 +7085,6 @@
 	.get_wireless_stats = airo_get_wireless_stats,
 };
 
-#endif /* WIRELESS_EXT */
-
 /*
  * This defines the configuration part of the Wireless Extensions
  * Note : irq and spinlock protection will occur in the subroutines
@@ -7187,7 +7163,6 @@
 	return rc;
 }
 
-#ifdef WIRELESS_EXT
 /*
  * Get the Wireless stats out of the driver
  * Note : irq and spinlock protection will occur in the subroutines
@@ -7260,7 +7235,6 @@
 
 	return &local->wstats;
 }
-#endif /* WIRELESS_EXT */
 
 #ifdef CISCO_EXT
 /*
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index bf25584..784de91 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -258,9 +258,7 @@
 	
 	/* Unlink device structure, free pieces */
 	*linkp = link->next;
-	if (link->priv) {
-		kfree(link->priv);
-	}
+	kfree(link->priv);
 	kfree(link);
 	
 } /* airo_detach */
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 9d49670..7b321f7 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -15,28 +15,11 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/current.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
+#include <linux/delay.h>
 #include <asm/pmac_feature.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
 
 #include "orinoco.h"
 
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 587869d..1fbe027 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -618,12 +618,12 @@
 static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
 static void atmel_command_irq(struct atmel_private *priv);
 static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
 				   u16 frame_len, u8 rssi);
 static void atmel_management_timer(u_long a);
 static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
 static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
 					    u8 *body, int body_len);
 
 static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -827,7 +827,7 @@
 static int start_tx (struct sk_buff *skb, struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-	struct ieee80211_hdr header;
+	struct ieee80211_hdr_4addr header;
 	unsigned long flags;
 	u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 	u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
@@ -902,7 +902,7 @@
 }
 
 static void atmel_transmit_management_frame(struct atmel_private *priv, 
-					    struct ieee80211_hdr *header,
+					    struct ieee80211_hdr_4addr *header,
 					    u8 *body, int body_len)
 {
 	u16 buff;
@@ -917,7 +917,7 @@
 	tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
 }
 	
-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
 			 u16 msdu_size, u16 rx_packet_loc, u32 crc)
 {
 	/* fast path: unfragmented packet copy directly into skbuf */
@@ -990,7 +990,7 @@
 	return (crc ^ 0xffffffff) == netcrc;
 }
 
-static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
 			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
 {
 	u8 mac4[6]; 
@@ -1082,7 +1082,7 @@
 static void rx_done_irq(struct atmel_private *priv)
 {
 	int i;
-	struct ieee80211_hdr header;
+	struct ieee80211_hdr_4addr header;
 	
 	for (i = 0; 
 	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -1653,8 +1653,7 @@
 	unregister_netdev(dev);
 	remove_proc_entry("driver/atmel", NULL);
 	free_irq(dev->irq, dev);
-	if (priv->firmware)
-		kfree(priv->firmware);
+	kfree(priv->firmware);
 	if (freeres) {
 		/* PCMCIA frees this stuff, so only for PCI */
 	        release_region(dev->base_addr, 64);
@@ -2450,8 +2449,7 @@
 			break;
 		}
 
-		if (priv->firmware)
-			kfree(priv->firmware);
+		kfree(priv->firmware);
 		
 		priv->firmware = new_firmware;
 		priv->firmware_length = com.len;
@@ -2650,7 +2648,7 @@
  
 static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
 {
-	struct ieee80211_hdr header;
+	struct ieee80211_hdr_4addr header;
 	struct auth_body auth;
 	
 	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); 
@@ -2688,7 +2686,7 @@
 {
 	u8 *ssid_el_p;
 	int bodysize;
-	struct ieee80211_hdr header;
+	struct ieee80211_hdr_4addr header;
 	struct ass_req_format {
 		u16 capability;
 		u16 listen_interval; 
@@ -2738,7 +2736,7 @@
 	atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
 }
 
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
 {
 	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
 		return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
@@ -2788,7 +2786,7 @@
 }
 
 
-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr *header,
+static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
 			   u16 capability, u16 beacon_period, u8 channel, u8 rssi, 
 			   u8 ssid_len, u8 *ssid, int is_beacon)
 {
@@ -3072,7 +3070,7 @@
 }
 
 /* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr *header, 
+static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
 		      u16 frame_len, u8 rssi)
 {
 	u16 subtype;
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index ff031a3..195cb36 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -259,8 +259,7 @@
 
 	/* Unlink device structure, free pieces */
 	*linkp = link->next;
-	if (link->priv)
-		kfree(link->priv);
+	kfree(link->priv);
 	kfree(link);
 }
 
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 21c3d0d..579480d 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -39,17 +39,10 @@
  */
 
 #include <linux/config.h>
-
 #include <linux/module.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/net.h>
-#include <asm/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
 
 #include "hermes.h"
 
@@ -451,6 +444,43 @@
 	return err;
 }
 
+/* Write a block of data to the chip's buffer with padding if
+ * neccessary, via the BAP. Synchronization/serialization is the
+ * caller's problem. len must be even.
+ *
+ * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
+ */
+int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, unsigned len,
+		      u16 id, u16 offset)
+{
+	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
+	int err = 0;
+
+	if (len < 0 || len % 2 || data_len > len)
+		return -EINVAL;
+
+	err = hermes_bap_seek(hw, bap, id, offset);
+	if (err)
+		goto out;
+
+	/* Transfer all the complete words of data */
+	hermes_write_words(hw, dreg, buf, data_len/2);
+	/* If there is an odd byte left over pad and transfer it */
+	if (data_len & 1) {
+		u8 end[2];
+		end[1] = 0;
+		end[0] = ((unsigned char *)buf)[data_len - 1];
+		hermes_write_words(hw, dreg, end, 1);
+		data_len ++;
+	}
+	/* Now send zeros for the padding */
+	if (data_len < len)
+		hermes_clear_words(hw, dreg, (len - data_len) / 2);
+	/* Complete */
+ out:
+	return err;
+}
+
 /* Read a Length-Type-Value record from the card.
  *
  * If length is NULL, we ignore the length read from the card, and
@@ -538,6 +568,7 @@
 
 EXPORT_SYMBOL(hermes_bap_pread);
 EXPORT_SYMBOL(hermes_bap_pwrite);
+EXPORT_SYMBOL(hermes_bap_pwrite_pad);
 EXPORT_SYMBOL(hermes_read_ltv);
 EXPORT_SYMBOL(hermes_write_ltv);
 
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 8c9e874..a6bd472 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -30,9 +30,8 @@
  * access to the hermes_t structure, and to the hardware
 */
 
-#include <linux/delay.h>
 #include <linux/if_ether.h>
-#include <asm/byteorder.h>
+#include <asm/io.h>
 
 /*
  * Limits and constants
@@ -192,13 +191,13 @@
 #define	HERMES_RXSTAT_WMP		(0x6000)	/* Wavelan-II Management Protocol frame */
 
 struct hermes_tx_descriptor {
-	u16 status;
-	u16 reserved1;
-	u16 reserved2;
-	u32 sw_support;
+	__le16 status;
+	__le16 reserved1;
+	__le16 reserved2;
+	__le32 sw_support;
 	u8 retry_count;
 	u8 tx_rate;
-	u16 tx_control;	
+	__le16 tx_control;	
 } __attribute__ ((packed));
 
 #define HERMES_TXSTAT_RETRYERR		(0x0001)
@@ -222,60 +221,60 @@
 #define HERMES_INQ_SEC_STAT_AGERE	(0xF202)
 
 struct hermes_tallies_frame {
-	u16 TxUnicastFrames;
-	u16 TxMulticastFrames;
-	u16 TxFragments;
-	u16 TxUnicastOctets;
-	u16 TxMulticastOctets;
-	u16 TxDeferredTransmissions;
-	u16 TxSingleRetryFrames;
-	u16 TxMultipleRetryFrames;
-	u16 TxRetryLimitExceeded;
-	u16 TxDiscards;
-	u16 RxUnicastFrames;
-	u16 RxMulticastFrames;
-	u16 RxFragments;
-	u16 RxUnicastOctets;
-	u16 RxMulticastOctets;
-	u16 RxFCSErrors;
-	u16 RxDiscards_NoBuffer;
-	u16 TxDiscardsWrongSA;
-	u16 RxWEPUndecryptable;
-	u16 RxMsgInMsgFragments;
-	u16 RxMsgInBadMsgFragments;
+	__le16 TxUnicastFrames;
+	__le16 TxMulticastFrames;
+	__le16 TxFragments;
+	__le16 TxUnicastOctets;
+	__le16 TxMulticastOctets;
+	__le16 TxDeferredTransmissions;
+	__le16 TxSingleRetryFrames;
+	__le16 TxMultipleRetryFrames;
+	__le16 TxRetryLimitExceeded;
+	__le16 TxDiscards;
+	__le16 RxUnicastFrames;
+	__le16 RxMulticastFrames;
+	__le16 RxFragments;
+	__le16 RxUnicastOctets;
+	__le16 RxMulticastOctets;
+	__le16 RxFCSErrors;
+	__le16 RxDiscards_NoBuffer;
+	__le16 TxDiscardsWrongSA;
+	__le16 RxWEPUndecryptable;
+	__le16 RxMsgInMsgFragments;
+	__le16 RxMsgInBadMsgFragments;
 	/* Those last are probably not available in very old firmwares */
-	u16 RxDiscards_WEPICVError;
-	u16 RxDiscards_WEPExcluded;
+	__le16 RxDiscards_WEPICVError;
+	__le16 RxDiscards_WEPExcluded;
 } __attribute__ ((packed));
 
 /* Grabbed from wlan-ng - Thanks Mark... - Jean II
  * This is the result of a scan inquiry command */
 /* Structure describing info about an Access Point */
 struct prism2_scan_apinfo {
-	u16 channel;		/* Channel where the AP sits */
-	u16 noise;		/* Noise level */
-	u16 level;		/* Signal level */
+	__le16 channel;		/* Channel where the AP sits */
+	__le16 noise;		/* Noise level */
+	__le16 level;		/* Signal level */
 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
-	u16 beacon_interv;	/* Beacon interval */
-	u16 capabilities;	/* Capabilities */
-	u16 essid_len;		/* ESSID length */
+	__le16 beacon_interv;	/* Beacon interval */
+	__le16 capabilities;	/* Capabilities */
+	__le16 essid_len;	/* ESSID length */
 	u8 essid[32];		/* ESSID of the network */
 	u8 rates[10];		/* Bit rate supported */
-	u16 proberesp_rate;	/* Data rate of the response frame */
-	u16 atim;		/* ATIM window time, Kus (hostscan only) */
+	__le16 proberesp_rate;	/* Data rate of the response frame */
+	__le16 atim;		/* ATIM window time, Kus (hostscan only) */
 } __attribute__ ((packed));
 
 /* Same stuff for the Lucent/Agere card.
  * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
 struct agere_scan_apinfo {
-	u16 channel;		/* Channel where the AP sits */
-	u16 noise;		/* Noise level */
-	u16 level;		/* Signal level */
+	__le16 channel;		/* Channel where the AP sits */
+	__le16 noise;		/* Noise level */
+	__le16 level;		/* Signal level */
 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
-	u16 beacon_interv;	/* Beacon interval */
-	u16 capabilities;	/* Capabilities */
+	__le16 beacon_interv;	/* Beacon interval */
+	__le16 capabilities;	/* Capabilities */
 	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
-	u16 essid_len;		/* ESSID length */
+	__le16 essid_len;	/* ESSID length */
 	u8 essid[32];		/* ESSID of the network */
 } __attribute__ ((packed));
 
@@ -283,16 +282,16 @@
 struct symbol_scan_apinfo {
 	u8 channel;		/* Channel where the AP sits */
 	u8 unknown1;		/* 8 in 2.9x and 3.9x f/w, 0 otherwise */
-	u16 noise;		/* Noise level */
-	u16 level;		/* Signal level */
+	__le16 noise;		/* Noise level */
+	__le16 level;		/* Signal level */
 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
-	u16 beacon_interv;	/* Beacon interval */
-	u16 capabilities;	/* Capabilities */
+	__le16 beacon_interv;	/* Beacon interval */
+	__le16 capabilities;	/* Capabilities */
 	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
-	u16 essid_len;		/* ESSID length */
+	__le16 essid_len;	/* ESSID length */
 	u8 essid[32];		/* ESSID of the network */
-    	u16 rates[5];		/* Bit rate supported */
-	u16 basic_rates;	/* Basic rates bitmask */
+    	__le16 rates[5];	/* Bit rate supported */
+	__le16 basic_rates;	/* Basic rates bitmask */
 	u8 unknown2[6];		/* Always FF:FF:FF:FF:00:00 */
 	u8 unknown3[8];		/* Always 0, appeared in f/w 3.91-68 */
 } __attribute__ ((packed));
@@ -312,7 +311,7 @@
 #define HERMES_LINKSTATUS_ASSOC_FAILED    (0x0006)
   
 struct hermes_linkstatus {
-	u16 linkstatus;         /* Link status */
+	__le16 linkstatus;         /* Link status */
 } __attribute__ ((packed));
 
 struct hermes_response {
@@ -321,8 +320,8 @@
 
 /* "ID" structure - used for ESSID and station nickname */
 struct hermes_idstring {
-	u16 len;
-	u16 val[16];
+	__le16 len;
+	__le16 val[16];
 } __attribute__ ((packed));
 
 struct hermes_multicast {
@@ -377,6 +376,8 @@
 		       u16 id, u16 offset);
 int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, unsigned len,
 			u16 id, u16 offset);
+int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf,
+			unsigned data_len, unsigned len, u16 id, u16 offset);
 int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
 		    u16 *length, void *buf);
 int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
@@ -447,7 +448,7 @@
 
 static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 {
-	u16 rec;
+	__le16 rec;
 	int err;
 
 	err = HERMES_READ_RECORD(hw, bap, rid, &rec);
@@ -457,7 +458,7 @@
 
 static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
 {
-	u16 rec = cpu_to_le16(word);
+	__le16 rec = cpu_to_le16(word);
 	return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
 }
 
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c
index e7f5821..6a96cd9 100644
--- a/drivers/net/wireless/hostap/hostap.c
+++ b/drivers/net/wireless/hostap/hostap.c
@@ -716,9 +716,6 @@
 		hostap_deauth_all_stas(dev, local->ap, 1);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-	if (local->func->dev_close && local->func->dev_close(local))
-		return 0;
-
 	if (dev == local->dev) {
 		local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL);
 	}
@@ -766,9 +763,6 @@
 	    local->hw_downloading)
 		return -ENODEV;
 
-	if (local->func->dev_open && local->func->dev_open(local))
-		return 1;
-
 	if (!try_module_get(local->hw_module))
 		return -ENODEV;
 	local->num_dev_open++;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index b050124..ffac508 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -6,10 +6,10 @@
 void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
 			  struct hostap_80211_rx_status *rx_stats)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
 	printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
 	       "jiffies=%ld\n",
@@ -51,7 +51,7 @@
 	int hdrlen, phdrlen, head_need, tail_need;
 	u16 fc;
 	int prism_header, ret;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
@@ -70,7 +70,7 @@
 		phdrlen = 0;
 	}
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
@@ -215,7 +215,7 @@
 
 /* Called only as a tasklet (software IRQ) */
 static struct sk_buff *
-prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr)
+prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
 {
 	struct sk_buff *skb = NULL;
 	u16 sc;
@@ -229,7 +229,7 @@
 	if (frag == 0) {
 		/* Reserve enough space to fit maximum frame length */
 		skb = dev_alloc_skb(local->dev->mtu +
-				    sizeof(struct ieee80211_hdr) +
+				    sizeof(struct ieee80211_hdr_4addr) +
 				    8 /* LLC */ +
 				    2 /* alignment */ +
 				    8 /* WEP */ + ETH_ALEN /* WDS */);
@@ -267,7 +267,7 @@
 
 /* Called only as a tasklet (software IRQ) */
 static int prism2_frag_cache_invalidate(local_info_t *local,
-					struct ieee80211_hdr *hdr)
+					struct ieee80211_hdr_4addr *hdr)
 {
 	u16 sc;
 	unsigned int seq;
@@ -441,7 +441,7 @@
 		     u16 stype)
 {
 	if (local->iw_mode == IW_MODE_MASTER) {
-		hostap_update_sta_ps(local, (struct ieee80211_hdr *)
+		hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)
 				     skb->data);
 	}
 
@@ -520,7 +520,7 @@
 
 
 static inline int
-hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr,
+hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
 		    u16 fc, struct net_device **wds)
 {
 	/* FIX: is this really supposed to accept WDS frames only in Master
@@ -579,13 +579,13 @@
 {
 	struct net_device *dev = local->dev;
 	u16 fc, ethertype;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u8 *pos;
 
 	if (skb->len < 24)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	/* check that the frame is unicast frame to us */
@@ -619,13 +619,13 @@
 hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
 			struct ieee80211_crypt_data *crypt)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	int res, hdrlen;
 
 	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
 	if (local->tkip_countermeasures &&
@@ -658,13 +658,13 @@
 hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
 			     int keyidx, struct ieee80211_crypt_data *crypt)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	int res, hdrlen;
 
 	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
 	atomic_inc(&crypt->refcnt);
@@ -689,7 +689,7 @@
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	size_t hdrlen;
 	u16 fc, type, stype, sc;
 	struct net_device *wds = NULL;
@@ -716,7 +716,7 @@
 	dev = local->ddev;
 	iface = netdev_priv(dev);
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	stats = hostap_get_stats(dev);
 
 	if (skb->len < 10)
@@ -737,7 +737,8 @@
 		struct iw_quality wstats;
 		wstats.level = rx_stats->signal;
 		wstats.noise = rx_stats->noise;
-		wstats.updated = 6;	/* No qual value */
+		wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED
+			| IW_QUAL_QUAL_INVALID | IW_QUAL_DBM;
 		/* Update spy records */
 		wireless_spy_update(dev, hdr->addr2, &wstats);
 	}
@@ -889,7 +890,7 @@
 	if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
 	    (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
 		goto rx_dropped;
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
 	/* skb: hdr + (possibly fragmented) plaintext payload */
 
@@ -941,7 +942,7 @@
 		/* this was the last fragment and the frame will be
 		 * delivered, so remove skb from fragment cache */
 		skb = frag_skb;
-		hdr = (struct ieee80211_hdr *) skb->data;
+		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		prism2_frag_cache_invalidate(local, hdr);
 	}
 
@@ -952,7 +953,7 @@
 	    hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt))
 		goto rx_dropped;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) {
 		if (local->ieee_802_1x &&
 		    hostap_is_eapol_frame(local, skb)) {
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 6358015..9d24f8a 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,9 +1,9 @@
 void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
 	printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n",
 	       name, skb->len, jiffies);
@@ -41,7 +41,7 @@
 	struct hostap_interface *iface;
 	local_info_t *local;
 	int need_headroom, need_tailroom = 0;
-	struct ieee80211_hdr hdr;
+	struct ieee80211_hdr_4addr hdr;
 	u16 fc, ethertype = 0;
 	enum {
 		WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
@@ -244,7 +244,7 @@
 	struct hostap_interface *iface;
 	local_info_t *local;
 	struct hostap_skb_tx_data *meta;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
 
 	iface = netdev_priv(dev);
@@ -266,7 +266,7 @@
 	meta->iface = iface;
 
 	if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) {
-		hdr = (struct ieee80211_hdr *) skb->data;
+		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		fc = le16_to_cpu(hdr->frame_ctl);
 		if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA &&
 		    WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) {
@@ -289,7 +289,7 @@
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
 	int hdr_len, res;
 
@@ -303,7 +303,7 @@
 
 	if (local->tkip_countermeasures &&
 	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
-		hdr = (struct ieee80211_hdr *) skb->data;
+		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
 			       "TX packet to " MACSTR "\n",
@@ -317,15 +317,15 @@
 	if (skb == NULL)
 		return NULL;
 
-	if ((skb_headroom(skb) < crypt->ops->extra_prefix_len ||
-	     skb_tailroom(skb) < crypt->ops->extra_postfix_len) &&
-	    pskb_expand_head(skb, crypt->ops->extra_prefix_len,
-			     crypt->ops->extra_postfix_len, GFP_ATOMIC)) {
+	if ((skb_headroom(skb) < crypt->ops->extra_mpdu_prefix_len ||
+	     skb_tailroom(skb) < crypt->ops->extra_mpdu_postfix_len) &&
+	    pskb_expand_head(skb, crypt->ops->extra_mpdu_prefix_len,
+			     crypt->ops->extra_mpdu_postfix_len, GFP_ATOMIC)) {
 		kfree_skb(skb);
 		return NULL;
 	}
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
  	fc = le16_to_cpu(hdr->frame_ctl);
 	hdr_len = hostap_80211_get_hdrlen(fc);
 
@@ -360,7 +360,7 @@
 	ap_tx_ret tx_ret;
 	struct hostap_skb_tx_data *meta;
 	int no_encrypt = 0;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
@@ -403,7 +403,7 @@
 	tx_ret = hostap_handle_sta_tx(local, &tx);
 	skb = tx.skb;
 	meta = (struct hostap_skb_tx_data *) skb->cb;
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
  	fc = le16_to_cpu(hdr->frame_ctl);
 	switch (tx_ret) {
 	case AP_TX_CONTINUE:
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 930cef8..9da94ab 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -591,14 +591,14 @@
 {
 	struct ap_data *ap = data;
 	u16 fc;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 
 	if (!ap->local->hostapd || !ap->local->apdev) {
 		dev_kfree_skb(skb);
 		return;
 	}
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	/* Pass the TX callback frame to the hostapd; use 802.11 header version
@@ -623,7 +623,7 @@
 {
 	struct ap_data *ap = data;
 	struct net_device *dev = ap->local->dev;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc, *pos, auth_alg, auth_transaction, status;
 	struct sta_info *sta = NULL;
 	char *txt = NULL;
@@ -633,7 +633,7 @@
 		return;
 	}
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
 	    WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||
@@ -692,7 +692,7 @@
 {
 	struct ap_data *ap = data;
 	struct net_device *dev = ap->local->dev;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc, *pos, status;
 	struct sta_info *sta = NULL;
 	char *txt = NULL;
@@ -702,7 +702,7 @@
 		return;
 	}
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||
 	    (WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&
@@ -757,12 +757,12 @@
 static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
 {
 	struct ap_data *ap = data;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	struct sta_info *sta;
 
 	if (skb->len < 24)
 		goto fail;
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	if (ok) {
 		spin_lock(&ap->sta_table_lock);
 		sta = ap_get_sta(ap, hdr->addr1);
@@ -918,7 +918,7 @@
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u16 fc;
 	struct sk_buff *skb;
 	struct hostap_skb_tx_data *meta;
@@ -944,7 +944,7 @@
 
 	fc = type_subtype;
 	hdrlen = hostap_80211_get_hdrlen(fc);
-	hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen);
+	hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);
 	if (body)
 		memcpy(skb_put(skb, body_len), body, body_len);
 
@@ -1256,14 +1256,14 @@
 	}
 
 	skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +
-			    ap->crypt->extra_prefix_len +
-			    ap->crypt->extra_postfix_len);
+			    ap->crypt->extra_mpdu_prefix_len +
+			    ap->crypt->extra_mpdu_postfix_len);
 	if (skb == NULL) {
 		kfree(tmpbuf);
 		return NULL;
 	}
 
-	skb_reserve(skb, ap->crypt->extra_prefix_len);
+	skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);
 	memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,
 	       WLAN_AUTH_CHALLENGE_LEN);
 	if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {
@@ -1272,7 +1272,7 @@
 		return NULL;
 	}
 
-	memcpy(tmpbuf, skb->data + ap->crypt->extra_prefix_len,
+	memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,
 	       WLAN_AUTH_CHALLENGE_LEN);
 	dev_kfree_skb(skb);
 
@@ -1285,7 +1285,7 @@
 			  struct hostap_80211_rx_status *rx_stats)
 {
 	struct net_device *dev = local->dev;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	size_t hdrlen;
 	struct ap_data *ap = local->ap;
 	char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
@@ -1498,7 +1498,7 @@
 			 struct hostap_80211_rx_status *rx_stats, int reassoc)
 {
 	struct net_device *dev = local->dev;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	char body[12], *p, *lpos;
 	int len, left;
 	u16 *pos;
@@ -1705,7 +1705,7 @@
 			  struct hostap_80211_rx_status *rx_stats)
 {
 	struct net_device *dev = local->dev;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
 	int len;
 	u16 reason_code, *pos;
@@ -1746,7 +1746,7 @@
 			    struct hostap_80211_rx_status *rx_stats)
 {
 	struct net_device *dev = local->dev;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
 	int len;
 	u16 reason_code, *pos;
@@ -1784,7 +1784,7 @@
 
 /* Called only as a scheduled task for pending AP frames. */
 static void ap_handle_data_nullfunc(local_info_t *local,
-				    struct ieee80211_hdr *hdr)
+				    struct ieee80211_hdr_4addr *hdr)
 {
 	struct net_device *dev = local->dev;
 
@@ -1801,7 +1801,7 @@
 
 /* Called only as a scheduled task for pending AP frames. */
 static void ap_handle_dropped_data(local_info_t *local,
-				   struct ieee80211_hdr *hdr)
+				   struct ieee80211_hdr_4addr *hdr)
 {
 	struct net_device *dev = local->dev;
 	struct sta_info *sta;
@@ -1860,7 +1860,7 @@
 
 /* Called only as a scheduled task for pending AP frames. */
 static void handle_pspoll(local_info_t *local,
-			  struct ieee80211_hdr *hdr,
+			  struct ieee80211_hdr_4addr *hdr,
 			  struct hostap_80211_rx_status *rx_stats)
 {
 	struct net_device *dev = local->dev;
@@ -1979,7 +1979,7 @@
 static void handle_beacon(local_info_t *local, struct sk_buff *skb,
 			  struct hostap_80211_rx_status *rx_stats)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
 	int len, left;
 	u16 *pos, beacon_int, capability;
@@ -2137,11 +2137,11 @@
 	struct net_device *dev = local->dev;
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 	u16 fc, type, stype;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 
 	/* FIX: should give skb->len to handler functions and check that the
 	 * buffer is long enough */
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 	type = WLAN_FC_GET_TYPE(fc);
 	stype = WLAN_FC_GET_STYPE(fc);
@@ -2258,7 +2258,7 @@
 	struct hostap_interface *iface;
 	local_info_t *local;
 	u16 fc;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
@@ -2268,7 +2268,7 @@
 
 	local->stats.rx_packets++;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL &&
@@ -2289,7 +2289,7 @@
 static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
 {
 	struct sk_buff *skb;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	struct hostap_80211_rx_status rx_stats;
 
 	if (skb_queue_empty(&sta->tx_buf))
@@ -2302,7 +2302,7 @@
 		return;
 	}
 
-	hdr = (struct ieee80211_hdr *) skb_put(skb, 16);
+	hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, 16);
 
 	/* Generate a fake pspoll frame to start packet delivery */
 	hdr->frame_ctl = __constant_cpu_to_le16(
@@ -2349,7 +2349,7 @@
 		qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
 		qual[count].updated = sta->last_rx_updated;
 
-		sta->last_rx_updated = 0;
+		sta->last_rx_updated = IW_QUAL_DBM;
 
 		count++;
 		if (count >= buf_size)
@@ -2467,7 +2467,7 @@
 		}
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-		sta->last_rx_updated = 0;
+		sta->last_rx_updated = IW_QUAL_DBM;
 
 		/* To be continued, we should make good use of IWEVCUSTOM */
 	}
@@ -2685,7 +2685,7 @@
 	struct sta_info *sta = NULL;
 	struct sk_buff *skb = tx->skb;
 	int set_tim, ret;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	struct hostap_skb_tx_data *meta;
 
 	meta = (struct hostap_skb_tx_data *) skb->cb;
@@ -2694,7 +2694,7 @@
 	    meta->iface->type == HOSTAP_INTERFACE_STA)
 		goto out;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
 	if (hdr->addr1[0] & 0x01) {
 		/* broadcast/multicast frame - no AP related processing */
@@ -2821,10 +2821,10 @@
 void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
 {
 	struct sta_info *sta;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	struct hostap_skb_tx_data *meta;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	meta = (struct hostap_skb_tx_data *) skb->cb;
 
 	spin_lock(&local->ap->sta_table_lock);
@@ -2892,7 +2892,7 @@
 
 /* Called only as a tasklet (software IRQ). Called for each RX frame to update
  * STA power saving state. pwrmgt is a flag from 802.11 frame_ctl field. */
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr)
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr)
 {
 	struct sta_info *sta;
 	u16 fc;
@@ -2925,12 +2925,12 @@
 	int ret;
 	struct sta_info *sta;
 	u16 fc, type, stype;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 
 	if (local->ap == NULL)
 		return AP_RX_CONTINUE;
 
-	hdr = (struct ieee80211_hdr *) skb->data;
+	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
 	fc = le16_to_cpu(hdr->frame_ctl);
 	type = WLAN_FC_GET_TYPE(fc);
@@ -3058,7 +3058,7 @@
 
 /* Called only as a tasklet (software IRQ) */
 int hostap_handle_sta_crypto(local_info_t *local,
-			     struct ieee80211_hdr *hdr,
+			     struct ieee80211_hdr_4addr *hdr,
 			     struct ieee80211_crypt_data **crypt,
 			     void **sta_ptr)
 {
@@ -3160,7 +3160,7 @@
 
 /* Called only as a tasklet (software IRQ) */
 int hostap_update_rx_stats(struct ap_data *ap,
-			   struct ieee80211_hdr *hdr,
+			   struct ieee80211_hdr_4addr *hdr,
 			   struct hostap_80211_rx_status *rx_stats)
 {
 	struct sta_info *sta;
@@ -3174,7 +3174,7 @@
 		sta->last_rx_silence = rx_stats->noise;
 		sta->last_rx_signal = rx_stats->signal;
 		sta->last_rx_rate = rx_stats->rate;
-		sta->last_rx_updated = 7;
+		sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 		if (rx_stats->rate == 10)
 			sta->rx_count[0]++;
 		else if (rx_stats->rate == 20)
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 816a52b..6d00df6 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -233,7 +233,7 @@
 ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
 void hostap_handle_sta_release(void *ptr);
 void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb);
-int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr);
+int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr_4addr *hdr);
 typedef enum {
 	AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED
 } ap_rx_ret;
@@ -241,13 +241,13 @@
 			       struct sk_buff *skb,
 			       struct hostap_80211_rx_status *rx_stats,
 			       int wds);
-int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr,
+int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
 			     struct ieee80211_crypt_data **crypt,
 			     void **sta_ptr);
 int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
 int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
 int hostap_add_sta(struct ap_data *ap, u8 *sta_addr);
-int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr,
+int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr_4addr *hdr,
 			   struct hostap_80211_rx_status *rx_stats);
 void hostap_update_rates(local_info_t *local);
 void hostap_add_wds_links(local_info_t *local);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index faa83ba..2643976 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -492,42 +492,10 @@
 }
 
 
-static int prism2_pccard_dev_open(local_info_t *local)
-{
-	struct hostap_cs_priv *hw_priv = local->hw_priv;
-	hw_priv->link->open++;
-	return 0;
-}
-
-
-static int prism2_pccard_dev_close(local_info_t *local)
-{
-	struct hostap_cs_priv *hw_priv;
-
-	if (local == NULL || local->hw_priv == NULL)
-		return 1;
-	hw_priv = local->hw_priv;
-	if (hw_priv->link == NULL)
-		return 1;
-
-	if (!hw_priv->link->open) {
-		printk(KERN_WARNING "%s: prism2_pccard_dev_close(): "
-		       "link not open?!\n", local->dev->name);
-		return 1;
-	}
-
-	hw_priv->link->open--;
-
-	return 0;
-}
-
-
 static struct prism2_helper_functions prism2_pccard_funcs =
 {
 	.card_present	= prism2_pccard_card_present,
 	.cor_sreset	= prism2_pccard_cor_sreset,
-	.dev_open	= prism2_pccard_dev_open,
-	.dev_close	= prism2_pccard_dev_close,
 	.genesis_reset	= prism2_pccard_genesis_reset,
 	.hw_type	= HOSTAP_HW_PCCARD,
 };
@@ -597,13 +565,14 @@
 	*linkp = link->next;
 	/* release net devices */
 	if (link->priv) {
+		struct hostap_cs_priv *hw_priv;
 		struct net_device *dev;
 		struct hostap_interface *iface;
 		dev = link->priv;
 		iface = netdev_priv(dev);
-		kfree(iface->local->hw_priv);
-		iface->local->hw_priv = NULL;
+		hw_priv = iface->local->hw_priv;
 		prism2_free_local_data(dev);
+		kfree(hw_priv);
 	}
 	kfree(link);
 }
@@ -883,6 +852,13 @@
 {
 	dev_link_t *link = args->client_data;
 	struct net_device *dev = (struct net_device *) link->priv;
+	int dev_open = 0;
+
+	if (link->state & DEV_CONFIG) {
+		struct hostap_interface *iface = netdev_priv(dev);
+		if (iface && iface->local)
+			dev_open = iface->local->num_dev_open > 0;
+	}
 
 	switch (event) {
 	case CS_EVENT_CARD_INSERTION:
@@ -911,7 +887,7 @@
 	case CS_EVENT_RESET_PHYSICAL:
 		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
 		if (link->state & DEV_CONFIG) {
-			if (link->open) {
+			if (dev_open) {
 				netif_stop_queue(dev);
 				netif_device_detach(dev);
 			}
@@ -931,8 +907,8 @@
 			pcmcia_request_configuration(link->handle,
 						     &link->conf);
 			prism2_hw_shutdown(dev, 1);
-			prism2_hw_config(dev, link->open ? 0 : 1);
-			if (link->open) {
+			prism2_hw_config(dev, dev_open ? 0 : 1);
+			if (dev_open) {
 				netif_device_attach(dev);
 				netif_start_queue(dev);
 			}
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index e533a66..59fc155 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3322,6 +3322,18 @@
 	iface = netdev_priv(dev);
 	local = iface->local;
 
+	/* Unregister all netdevs before freeing local data. */
+	list_for_each_safe(ptr, n, &local->hostap_interfaces) {
+		iface = list_entry(ptr, struct hostap_interface, list);
+		if (iface->type == HOSTAP_INTERFACE_MASTER) {
+			/* special handling for this interface below */
+			continue;
+		}
+		hostap_remove_interface(iface->dev, 0, 1);
+	}
+
+	unregister_netdev(local->dev);
+
 	flush_scheduled_work();
 
 	if (timer_pending(&local->crypt_deinit_timer))
@@ -3382,15 +3394,6 @@
 	prism2_download_free_data(local->dl_sec);
 #endif /* PRISM2_DOWNLOAD_SUPPORT */
 
-	list_for_each_safe(ptr, n, &local->hostap_interfaces) {
-		iface = list_entry(ptr, struct hostap_interface, list);
-		if (iface->type == HOSTAP_INTERFACE_MASTER) {
-			/* special handling for this interface below */
-			continue;
-		}
-		hostap_remove_interface(iface->dev, 0, 1);
-	}
-
 	prism2_clear_set_tim_queue(local);
 
 	list_for_each_safe(ptr, n, &local->bss_list) {
@@ -3403,7 +3406,6 @@
 	kfree(local->last_scan_results);
 	kfree(local->generic_elem);
 
-	unregister_netdev(local->dev);
 	free_netdev(local->dev);
 }
 
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index e720369..2617d70 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -50,7 +50,8 @@
 #endif /* in_atomic */
 
 		if (update && prism2_update_comms_qual(dev) == 0)
-			wstats->qual.updated = 7;
+			wstats->qual.updated = IW_QUAL_ALL_UPDATED |
+				IW_QUAL_DBM;
 
 		wstats->qual.qual = local->comms_qual;
 		wstats->qual.level = local->avg_signal;
@@ -59,7 +60,7 @@
 		wstats->qual.qual = 0;
 		wstats->qual.level = 0;
 		wstats->qual.noise = 0;
-		wstats->qual.updated = 0;
+		wstats->qual.updated = IW_QUAL_ALL_INVALID;
 	}
 
 	return wstats;
@@ -551,7 +552,6 @@
 
 	kfree(addr);
 	kfree(qual);
-
 	return 0;
 }
 
@@ -1827,13 +1827,6 @@
 	iwe.cmd = SIOCGIWAP;
 	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 	memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
-	/* FIX:
-	 * I do not know how this is possible, but iwe_stream_add_event
-	 * seems to re-order memcpy execution so that len is set only
-	 * after copying.. Pre-setting len here "fixes" this, but real
-	 * problems should be solved (after which these iwe.len
-	 * settings could be removed from this function). */
-	iwe.len = IW_EV_ADDR_LEN;
 	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
 					  IW_EV_ADDR_LEN);
 
@@ -1843,7 +1836,6 @@
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.length = ssid_len;
 	iwe.u.data.flags = 1;
-	iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
 	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid);
 
 	memset(&iwe, 0, sizeof(iwe));
@@ -1859,7 +1851,6 @@
 			iwe.u.mode = IW_MODE_MASTER;
 		else
 			iwe.u.mode = IW_MODE_ADHOC;
-		iwe.len = IW_EV_UINT_LEN;
 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
 						  IW_EV_UINT_LEN);
 	}
@@ -1877,7 +1868,6 @@
 	if (chan > 0) {
 		iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
 		iwe.u.freq.e = 1;
-		iwe.len = IW_EV_FREQ_LEN;
 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
 						  IW_EV_FREQ_LEN);
 	}
@@ -1894,7 +1884,10 @@
 			iwe.u.qual.noise =
 				HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
 		}
-		iwe.len = IW_EV_QUAL_LEN;
+		iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
+			| IW_QUAL_NOISE_UPDATED
+			| IW_QUAL_QUAL_INVALID
+			| IW_QUAL_DBM;
 		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
 						  IW_EV_QUAL_LEN);
 	}
@@ -1906,7 +1899,6 @@
 	else
 		iwe.u.data.flags = IW_ENCODE_DISABLED;
 	iwe.u.data.length = 0;
-	iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
 	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
 
 	/* TODO: add SuppRates into BSS table */
@@ -1930,7 +1922,7 @@
 	}
 
 	/* TODO: add BeaconInt,resp_rate,atim into BSS table */
-	buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_KERNEL);
+	buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
 	if (buf && scan) {
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVCUSTOM;
@@ -3088,9 +3080,7 @@
 	ret = local->func->download(local, param);
 
  out:
-	if (param != NULL)
-		kfree(param);
-
+	kfree(param);
 	return ret;
 }
 #endif /* PRISM2_DOWNLOAD_SUPPORT */
@@ -3897,9 +3887,7 @@
 	}
 
  out:
-	if (param != NULL)
-		kfree(param);
-
+	kfree(param);
 	return ret;
 }
 
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 025f8cd..da0c80f 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -59,11 +59,13 @@
 static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
 {
 	struct hostap_interface *iface;
+	struct hostap_pci_priv *hw_priv;
 	local_info_t *local;
 	unsigned long flags;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
+	hw_priv = local->hw_priv;
 
 	spin_lock_irqsave(&local->lock, flags);
 	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
@@ -74,12 +76,14 @@
 static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
 {
 	struct hostap_interface *iface;
+	struct hostap_pci_priv *hw_priv;
 	local_info_t *local;
 	unsigned long flags;
 	u8 v;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
+	hw_priv = local->hw_priv;
 
 	spin_lock_irqsave(&local->lock, flags);
 	v = readb(hw_priv->mem_start + a);
@@ -91,11 +95,13 @@
 static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
 {
 	struct hostap_interface *iface;
+	struct hostap_pci_priv *hw_priv;
 	local_info_t *local;
 	unsigned long flags;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
+	hw_priv = local->hw_priv;
 
 	spin_lock_irqsave(&local->lock, flags);
 	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
@@ -106,12 +112,14 @@
 static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
 {
 	struct hostap_interface *iface;
+	struct hostap_pci_priv *hw_priv;
 	local_info_t *local;
 	unsigned long flags;
 	u16 v;
 
 	iface = netdev_priv(dev);
 	local = iface->local;
+	hw_priv = local->hw_priv;
 
 	spin_lock_irqsave(&local->lock, flags);
 	v = readw(hw_priv->mem_start + a);
@@ -277,8 +285,6 @@
 {
 	.card_present	= NULL,
 	.cor_sreset	= prism2_pci_cor_sreset,
-	.dev_open	= NULL,
-	.dev_close	= NULL,
 	.genesis_reset	= prism2_pci_genesis_reset,
 	.hw_type	= HOSTAP_HW_PCI,
 };
@@ -352,8 +358,6 @@
 	return hostap_hw_ready(dev);
 
  fail:
-	kfree(hw_priv);
-
 	if (irq_registered && dev)
 		free_irq(dev->irq, dev);
 
@@ -364,10 +368,8 @@
 
  err_out_disable:
 	pci_disable_device(pdev);
-	kfree(hw_priv);
-	if (local)
-		local->hw_priv = NULL;
 	prism2_free_local_data(dev);
+	kfree(hw_priv);
 
 	return -ENODEV;
 }
@@ -392,9 +394,8 @@
 		free_irq(dev->irq, dev);
 
 	mem_start = hw_priv->mem_start;
-	kfree(hw_priv);
-	iface->local->hw_priv = NULL;
 	prism2_free_local_data(dev);
+	kfree(hw_priv);
 
 	iounmap(mem_start);
 
@@ -441,7 +442,7 @@
 MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
 
 static struct pci_driver prism2_pci_drv_id = {
-	.name		= "prism2_pci",
+	.name		= "hostap_pci",
 	.id_table	= prism2_pci_id_table,
 	.probe		= prism2_pci_probe,
 	.remove		= prism2_pci_remove,
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index 474ef83..78d67b408 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -328,8 +328,6 @@
 {
 	.card_present	= NULL,
 	.cor_sreset	= prism2_plx_cor_sreset,
-	.dev_open	= NULL,
-	.dev_close	= NULL,
 	.genesis_reset	= prism2_plx_genesis_reset,
 	.hw_type	= HOSTAP_HW_PLX,
 };
@@ -570,10 +568,8 @@
 	return hostap_hw_ready(dev);
 
  fail:
-	kfree(hw_priv);
-	if (local)
-		local->hw_priv = NULL;
 	prism2_free_local_data(dev);
+	kfree(hw_priv);
 
 	if (irq_registered && dev)
 		free_irq(dev->irq, dev);
@@ -606,9 +602,8 @@
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 
-	kfree(iface->local->hw_priv);
-	iface->local->hw_priv = NULL;
 	prism2_free_local_data(dev);
+	kfree(hw_priv);
 	pci_disable_device(pdev);
 }
 
@@ -616,7 +611,7 @@
 MODULE_DEVICE_TABLE(pci, prism2_plx_id_table);
 
 static struct pci_driver prism2_plx_drv_id = {
-	.name		= "prism2_plx",
+	.name		= "hostap_plx",
 	.id_table	= prism2_plx_id_table,
 	.probe		= prism2_plx_probe,
 	.remove		= prism2_plx_remove,
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index cc061e1..cfd8015 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -552,8 +552,6 @@
 	 * (hostap_{cs,plx,pci}.c */
 	int (*card_present)(local_info_t *local);
 	void (*cor_sreset)(local_info_t *local);
-	int (*dev_open)(local_info_t *local);
-	int (*dev_close)(local_info_t *local);
 	void (*genesis_reset)(local_info_t *local, int hcr);
 
 	/* the following functions are from hostap_hw.c, but they may have some
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 2414e64..ad7f8cd 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -800,8 +800,7 @@
 	 * doesn't seem to have as many firmware restart cycles...
 	 *
 	 * As a test, we're sticking in a 1/100s delay here */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 100);
+	schedule_timeout_uninterruptible(msecs_to_jiffies(10));
 
 	return 0;
 
@@ -1256,8 +1255,7 @@
 	IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");
 	i = 5000;
 	do {
-  		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(40 * HZ / 1000);
+		schedule_timeout_uninterruptible(msecs_to_jiffies(40));
 		/* Todo... wait for sync command ... */
 
 		read_register(priv->net_dev, IPW_REG_INTA, &inta);
@@ -1411,8 +1409,7 @@
 		    (val2 & IPW2100_COMMAND_PHY_OFF))
 			return 0;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HW_PHY_OFF_LOOP_DELAY);
+		schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);
 	}
 
 	return -EIO;
@@ -1466,7 +1463,7 @@
 
 static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
 {
-#define HW_POWER_DOWN_DELAY (HZ / 10)
+#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100))
 
 	struct host_command cmd = {
 		.host_command = HOST_PRE_POWER_DOWN,
@@ -1520,10 +1517,8 @@
 			printk(KERN_WARNING DRV_NAME ": "
 			       "%s: Power down command failed: Error %d\n",
 			       priv->net_dev->name, err);
-		else {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HW_POWER_DOWN_DELAY);
-		}
+		else
+			schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY);
 	}
 
 	priv->status &= ~STATUS_ENABLED;
@@ -2953,7 +2948,7 @@
 	int next = txq->next;
         int i = 0;
 	struct ipw2100_data_header *ipw_hdr;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 
 	while (!list_empty(&priv->tx_pend_list)) {
 		/* if there isn't enough space in TBD queue, then
@@ -2989,7 +2984,7 @@
 		packet->index = txq->next;
 
 		ipw_hdr = packet->info.d_struct.data;
-		hdr = (struct ieee80211_hdr *)packet->info.d_struct.txb->
+		hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
 			fragments[0]->data;
 
 		if (priv->ieee->iw_mode == IW_MODE_INFRA) {
@@ -3274,7 +3269,8 @@
 	return IRQ_NONE;
 }
 
-static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev)
+static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
+		      int pri)
 {
 	struct ipw2100_priv *priv = ieee80211_priv(dev);
 	struct list_head *element;
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index 2a3cdbd..c9e99ce 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -808,7 +808,7 @@
 struct ipw2100_rx {
 	union {
 		unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
-		struct ieee80211_hdr header;
+		struct ieee80211_hdr_4addr header;
 		u32 status;
 		struct ipw2100_notification notification;
 		struct ipw2100_cmd_header command;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index b7f275c..3db0c32 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4030,6 +4030,10 @@
 	int i;
 
 	rxq = (struct ipw_rx_queue *)kmalloc(sizeof(*rxq), GFP_KERNEL);
+	if (unlikely(!rxq)) {
+		IPW_ERROR("memory allocation failed\n");
+		return NULL;
+	}
 	memset(rxq, 0, sizeof(*rxq));
 	spin_lock_init(&rxq->lock);
 	INIT_LIST_HEAD(&rxq->rx_free);
@@ -4904,7 +4908,7 @@
 {
 	struct ipw_rx_mem_buffer *rxb;
 	struct ipw_rx_packet *pkt;
-	struct ieee80211_hdr *header;
+	struct ieee80211_hdr_4addr *header;
 	u32 r, w, i;
 	u8 network_packet;
 
@@ -4967,8 +4971,9 @@
 #endif
 
 				header =
-				    (struct ieee80211_hdr *)(rxb->skb->data +
-							     IPW_RX_FRAME_SIZE);
+				    (struct ieee80211_hdr_4addr *)(rxb->skb->
+								   data +
+								   IPW_RX_FRAME_SIZE);
 				/* TODO: Check Ad-Hoc dest/source and make sure
 				 * that we are actually parsing these packets
 				 * correctly -- we should probably use the
@@ -5317,8 +5322,6 @@
 
 	IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
 	return ipw_set_channel(priv, (u8) fwrq->m);
-
-	return 0;
 }
 
 static int ipw_wx_get_freq(struct net_device *dev,
@@ -6010,12 +6013,12 @@
 	}
 
 	if (priv->adapter == IPW_2915ABG) {
-		priv->ieee->abg_ture = 1;
+		priv->ieee->abg_true = 1;
 		if (mode & IEEE_A) {
 			band |= IEEE80211_52GHZ_BAND;
 			modulation |= IEEE80211_OFDM_MODULATION;
 		} else
-			priv->ieee->abg_ture = 0;
+			priv->ieee->abg_true = 0;
 	} else {
 		if (mode & IEEE_A) {
 			IPW_WARNING("Attempt to set 2200BG into "
@@ -6023,20 +6026,20 @@
 			return -EINVAL;
 		}
 
-		priv->ieee->abg_ture = 0;
+		priv->ieee->abg_true = 0;
 	}
 
 	if (mode & IEEE_B) {
 		band |= IEEE80211_24GHZ_BAND;
 		modulation |= IEEE80211_CCK_MODULATION;
 	} else
-		priv->ieee->abg_ture = 0;
+		priv->ieee->abg_true = 0;
 
 	if (mode & IEEE_G) {
 		band |= IEEE80211_24GHZ_BAND;
 		modulation |= IEEE80211_OFDM_MODULATION;
 	} else
-		priv->ieee->abg_ture = 0;
+		priv->ieee->abg_true = 0;
 
 	priv->ieee->mode = mode;
 	priv->ieee->freq_band = band;
@@ -6325,7 +6328,7 @@
 
 static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)
+	struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
 	    txb->fragments[0]->data;
 	int i = 0;
 	struct tfd_frame *tfd;
@@ -6448,7 +6451,7 @@
 }
 
 static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
-				   struct net_device *dev)
+				   struct net_device *dev, int pri)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	unsigned long flags;
@@ -7108,7 +7111,7 @@
 		printk(KERN_INFO DRV_NAME
 		       ": Detected Intel PRO/Wireless 2915ABG Network "
 		       "Connection\n");
-		priv->ieee->abg_ture = 1;
+		priv->ieee->abg_true = 1;
 		band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND;
 		modulation = IEEE80211_OFDM_MODULATION |
 		    IEEE80211_CCK_MODULATION;
@@ -7124,7 +7127,7 @@
 			       ": Detected Intel PRO/Wireless 2200BG Network "
 			       "Connection\n");
 
-		priv->ieee->abg_ture = 0;
+		priv->ieee->abg_true = 0;
 		band = IEEE80211_24GHZ_BAND;
 		modulation = IEEE80211_OFDM_MODULATION |
 		    IEEE80211_CCK_MODULATION;
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 5b00882..e9cf32b 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1654,12 +1654,12 @@
 
 #define IPW_MAX_CONFIG_RETRIES 10
 
-static inline u32 frame_hdr_len(struct ieee80211_hdr *hdr)
+static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
 {
 	u32 retval;
 	u16 fc;
 
-	retval = sizeof(struct ieee80211_hdr);
+	retval = sizeof(struct ieee80211_hdr_3addr);
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	/*
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index ca6c03c..92793b9 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -57,9 +57,7 @@
 #include <linux/bitops.h>
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>
-#if WIRELESS_EXT > 12
 #include <net/iw_handler.h>
-#endif	/* WIRELESS_EXT > 12 */
 #endif
 
 #include <pcmcia/cs_types.h>
@@ -225,10 +223,7 @@
 static struct net_device_stats *netwave_get_stats(struct net_device *dev);
 
 /* Wireless extensions */
-#ifdef WIRELESS_EXT
 static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
-#endif
-static int netwave_ioctl(struct net_device *, struct ifreq *, int);
 
 static void set_multicast_list(struct net_device *dev);
 
@@ -260,26 +255,7 @@
    because they generally can't be allocated dynamically.
 */
 
-#if WIRELESS_EXT <= 12
-/* Wireless extensions backward compatibility */
-
-/* Part of iw_handler prototype we need */
-struct iw_request_info
-{
-	__u16		cmd;		/* Wireless Extension command */
-	__u16		flags;		/* More to come ;-) */
-};
-
-/* Wireless Extension Backward compatibility - Jean II
- * If the new wireless device private ioctl range is not defined,
- * default to standard device private ioctl range */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV	SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
-#else	/* WIRELESS_EXT <= 12 */
 static const struct iw_handler_def	netwave_handler_def;
-#endif	/* WIRELESS_EXT <= 12 */
 
 #define SIOCGIPSNAP	SIOCIWFIRSTPRIV	+ 1	/* Site Survey Snapshot */
 
@@ -319,9 +295,7 @@
     struct timer_list      watchdog;	/* To avoid blocking state */
     struct site_survey     nss;
     struct net_device_stats stats;
-#ifdef WIRELESS_EXT
     struct iw_statistics   iw_stats;    /* Wireless stats */
-#endif
 } netwave_private;
 
 #ifdef NETWAVE_STATS
@@ -353,7 +327,6 @@
     while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ; 
 }
 
-#ifdef WIRELESS_EXT
 static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase, 
 			     kio_addr_t iobase) {
     u_short resultBuffer;
@@ -376,9 +349,7 @@
 		      sizeof(struct site_survey)); 
     } 
 }
-#endif
 
-#ifdef WIRELESS_EXT
 /*
  * Function netwave_get_wireless_stats (dev)
  *
@@ -411,7 +382,6 @@
     
     return &priv->iw_stats;
 }
-#endif
 
 /*
  * Function netwave_attach (void)
@@ -471,13 +441,7 @@
     dev->get_stats  = &netwave_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     /* wireless extensions */
-#if WIRELESS_EXT <= 16
-    dev->get_wireless_stats = &netwave_get_wireless_stats;
-#endif /* WIRELESS_EXT <= 16 */
-#if WIRELESS_EXT > 12
     dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
-#endif /* WIRELESS_EXT > 12 */
-    dev->do_ioctl = &netwave_ioctl;
 
     dev->tx_timeout = &netwave_watchdog;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -576,13 +540,8 @@
 	/* Disable interrupts & save flags */
 	spin_lock_irqsave(&priv->spinlock, flags);
 
-#if WIRELESS_EXT > 8
 	if(!wrqu->nwid.disabled) {
 	    domain = wrqu->nwid.value;
-#else	/* WIRELESS_EXT > 8 */
-	if(wrqu->nwid.on) {
-	    domain = wrqu->nwid.nwid;
-#endif	/* WIRELESS_EXT > 8 */
 	    printk( KERN_DEBUG "Setting domain to 0x%x%02x\n", 
 		    (domain >> 8) & 0x01, domain & 0xff);
 	    wait_WOC(iobase);
@@ -606,15 +565,9 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-#if WIRELESS_EXT > 8
 	wrqu->nwid.value = domain;
 	wrqu->nwid.disabled = 0;
 	wrqu->nwid.fixed = 1;
-#else	/* WIRELESS_EXT > 8 */
-	wrqu->nwid.nwid = domain;
-	wrqu->nwid.on = 1;
-#endif	/* WIRELESS_EXT > 8 */
-
 	return 0;
 }
 
@@ -657,17 +610,11 @@
 {
 	key[1] = scramble_key & 0xff;
 	key[0] = (scramble_key>>8) & 0xff;
-#if WIRELESS_EXT > 8
 	wrqu->encoding.flags = IW_ENCODE_ENABLED;
 	wrqu->encoding.length = 2;
-#else /* WIRELESS_EXT > 8 */
-	wrqu->encoding.method = 1;
-#endif	/* WIRELESS_EXT > 8 */
-
 	return 0;
 }
 
-#if WIRELESS_EXT > 8
 /*
  * Wireless Handler : get mode
  */
@@ -683,7 +630,6 @@
 
 	return 0;
 }
-#endif	/* WIRELESS_EXT > 8 */
 
 /*
  * Wireless Handler : get range info
@@ -702,11 +648,9 @@
 	/* Set all the info we don't care or don't know about to zero */
 	memset(range, 0, sizeof(struct iw_range));
 
-#if WIRELESS_EXT > 10
 	/* Set the Wireless Extension versions */
 	range->we_version_compiled = WIRELESS_EXT;
 	range->we_version_source = 9;	/* Nothing for us in v10 and v11 */
-#endif /* WIRELESS_EXT > 10 */
 		   
 	/* Set information in the range struct */
 	range->throughput = 450 * 1000;	/* don't argue on this ! */
@@ -720,16 +664,12 @@
 	range->max_qual.level = 255;
 	range->max_qual.noise = 0;
 		   
-#if WIRELESS_EXT > 7
 	range->num_bitrates = 1;
 	range->bitrate[0] = 1000000;	/* 1 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
 
-#if WIRELESS_EXT > 8
 	range->encoding_size[0] = 2;		/* 16 bits scrambling */
 	range->num_encoding_sizes = 1;
 	range->max_encoding_tokens = 1;	/* Only one key possible */
-#endif /* WIRELESS_EXT > 8 */
 
 	return ret;
 }
@@ -775,8 +715,6 @@
     "getsitesurvey" },
 };
 
-#if WIRELESS_EXT > 12
-
 static const iw_handler		netwave_handler[] =
 {
 	NULL,				/* SIOCSIWNAME */
@@ -839,131 +777,8 @@
 	.standard	= (iw_handler *) netwave_handler,
 	.private	= (iw_handler *) netwave_private_handler,
 	.private_args	= (struct iw_priv_args *) netwave_private_args,
-#if WIRELESS_EXT > 16
 	.get_wireless_stats = netwave_get_wireless_stats,
-#endif /* WIRELESS_EXT > 16 */
 };
-#endif /* WIRELESS_EXT > 12 */
-
-/*
- * Function netwave_ioctl (dev, rq, cmd)
- *
- *     Perform ioctl : config & info stuff
- *     This is the stuff that are treated the wireless extensions (iwconfig)
- *
- */
-static int netwave_ioctl(struct net_device *dev, /* ioctl device */
-			 struct ifreq *rq,	 /* Data passed */
-			 int	cmd)	     /* Ioctl number */
-{
-    int			ret = 0;
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
-    struct iwreq *wrq = (struct iwreq *) rq;
-#endif
-#endif
-	
-    DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
-	
-    /* Look what is the request */
-    switch(cmd) {
-	/* --------------- WIRELESS EXTENSIONS --------------- */
-#ifdef WIRELESS_EXT
-#if WIRELESS_EXT <= 12
-    case SIOCGIWNAME:
-	netwave_get_name(dev, NULL, &(wrq->u), NULL);
-	break;
-    case SIOCSIWNWID:
-	ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
-	break;
-    case SIOCGIWNWID:
-	ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
-	break;
-#if WIRELESS_EXT > 8	/* Note : The API did change... */
-    case SIOCGIWENCODE:
-	/* Get scramble key */
-	if(wrq->u.encoding.pointer != (caddr_t) 0)
-	  {
-	    char	key[2];
-	    ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
-	    if(copy_to_user(wrq->u.encoding.pointer, key, 2))
-	      ret = -EFAULT;
-	  }
-	break;
-    case SIOCSIWENCODE:
-	/* Set  scramble key */
-	if(wrq->u.encoding.pointer != (caddr_t) 0)
-	  {
-	    char	key[2];
-	    if(copy_from_user(key, wrq->u.encoding.pointer, 2))
-	      {
-		ret = -EFAULT;
-		break;
-	      }
-	    ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
-	  }
-	break;
-    case SIOCGIWMODE:
-	/* Mode of operation */
-	ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
-	break;
-#else /* WIRELESS_EXT > 8 */
-    case SIOCGIWENCODE:
-	/* Get scramble key */
-	ret = netwave_get_scramble(dev, NULL, &(wrq->u),
-				   (char *) &wrq->u.encoding.code);
-	break;
-    case SIOCSIWENCODE:
-	/* Set  scramble key */
-	ret = netwave_set_scramble(dev, NULL, &(wrq->u),
-				   (char *) &wrq->u.encoding.code);
-	break;
-#endif /* WIRELESS_EXT > 8 */
-   case SIOCGIWRANGE:
-       /* Basic checking... */
-       if(wrq->u.data.pointer != (caddr_t) 0) {
-           struct iw_range range;
-	   ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
-	   if (copy_to_user(wrq->u.data.pointer, &range,
-			    sizeof(struct iw_range)))
-	       ret = -EFAULT;
-       }
-       break;
-    case SIOCGIWPRIV:
-	/* Basic checking... */
-	if(wrq->u.data.pointer != (caddr_t) 0) {
-	    /* Set the number of ioctl available */
-	    wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
-			
-	    /* Copy structure to the user buffer */
-	    if(copy_to_user(wrq->u.data.pointer,
-			    (u_char *) netwave_private_args,
-			    sizeof(netwave_private_args)))
-	      ret = -EFAULT;
-	} 
-	break;
-    case SIOCGIPSNAP:
-	if(wrq->u.data.pointer != (caddr_t) 0) {
-	    char buffer[sizeof( struct site_survey)];
-	    ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
-	    /* Copy structure to the user buffer */
-	    if(copy_to_user(wrq->u.data.pointer, 
-			    buffer,
-			    sizeof( struct site_survey)))
-	      {
-		printk(KERN_DEBUG "Bad buffer!\n");
-		break;
-	      }
-	}
-	break;
-#endif /* WIRELESS_EXT <= 12 */
-#endif /* WIRELESS_EXT */
-    default:
-	ret = -EOPNOTSUPP;
-    }
-	
-    return ret;
-}
 
 /*
  * Function netwave_pcmcia_config (link)
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 15ceaf6..488ab06 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -77,30 +77,16 @@
 #define DRIVER_NAME "orinoco"
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
 #include <linux/netdevice.h>
-#include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211.h>
 
-#include <net/ieee80211.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "hermes.h"
 #include "hermes_rid.h"
 #include "orinoco.h"
 
@@ -137,7 +123,7 @@
 
 /* We do this this way to avoid ifdefs in the actual code */
 #ifdef WIRELESS_SPY
-#define SPY_NUMBER(priv)	(priv->spy_number)
+#define SPY_NUMBER(priv)	(priv->spy_data.spy_number)
 #else
 #define SPY_NUMBER(priv)	0
 #endif /* WIRELESS_SPY */
@@ -216,31 +202,32 @@
 /********************************************************************/
 
 /* Used in Event handling.
- * We avoid nested structres as they break on ARM -- Moustafa */
+ * We avoid nested structures as they break on ARM -- Moustafa */
 struct hermes_tx_descriptor_802_11 {
 	/* hermes_tx_descriptor */
-	u16 status;
-	u16 reserved1;
-	u16 reserved2;
-	u32 sw_support;
+	__le16 status;
+	__le16 reserved1;
+	__le16 reserved2;
+	__le32 sw_support;
 	u8 retry_count;
 	u8 tx_rate;
-	u16 tx_control;
+	__le16 tx_control;
 
-	/* ieee802_11_hdr */
-	u16 frame_ctl;
-	u16 duration_id;
+	/* ieee80211_hdr */
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
+	__le16 seq_ctl;
 	u8 addr4[ETH_ALEN];
-	u16 data_len;
+
+	__le16 data_len;
 
 	/* ethhdr */
-	unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
-	unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
-	unsigned short  h_proto;                /* packet type ID field */
+	u8 h_dest[ETH_ALEN];	/* destination eth addr */
+	u8 h_source[ETH_ALEN];	/* source ether addr    */
+	__be16 h_proto;		/* packet type ID field */
 
 	/* p8022_hdr */
 	u8 dsap;
@@ -248,31 +235,31 @@
 	u8 ctrl;
 	u8 oui[3];
 
-	u16 ethertype;
+	__be16 ethertype;
 } __attribute__ ((packed));
 
 /* Rx frame header except compatibility 802.3 header */
 struct hermes_rx_descriptor {
 	/* Control */
-	u16 status;
-	u32 time;
+	__le16 status;
+	__le32 time;
 	u8 silence;
 	u8 signal;
 	u8 rate;
 	u8 rxflow;
-	u32 reserved;
+	__le32 reserved;
 
 	/* 802.11 header */
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
-	u16 seq_ctl;
+	__le16 seq_ctl;
 	u8 addr4[ETH_ALEN];
 
 	/* Data length */
-	u16 data_len;
+	__le16 data_len;
 } __attribute__ ((packed));
 
 /********************************************************************/
@@ -396,14 +383,14 @@
 		/* If a spy address is defined, we report stats of the
 		 * first spy address - Jean II */
 		if (SPY_NUMBER(priv)) {
-			wstats->qual.qual = priv->spy_stat[0].qual;
-			wstats->qual.level = priv->spy_stat[0].level;
-			wstats->qual.noise = priv->spy_stat[0].noise;
-			wstats->qual.updated = priv->spy_stat[0].updated;
+			wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
+			wstats->qual.level = priv->spy_data.spy_stat[0].level;
+			wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
+			wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
 		}
 	} else {
 		struct {
-			u16 qual, signal, noise;
+			__le16 qual, signal, noise;
 		} __attribute__ ((packed)) cq;
 
 		err = HERMES_READ_RECORD(hw, USER_BAP,
@@ -503,13 +490,12 @@
 		return 0;
 	}
 
-	/* Check packet length, pad short packets, round up odd length */
+	/* Length of the packet body */
+	/* FIXME: what if the skb is smaller than this? */
 	len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
-	if (skb->len < len) {
-		skb = skb_padto(skb, len);
-		if (skb == NULL)
-			goto fail;
-	}
+	skb = skb_padto(skb, len);
+	if (skb == NULL)
+		goto fail;
 	len -= ETH_HLEN;
 
 	eh = (struct ethhdr *)skb->data;
@@ -556,13 +542,21 @@
 			stats->tx_errors++;
 			goto fail;
 		}
+		/* Actual xfer length - allow for padding */
+		len = ALIGN(data_len, 2);
+		if (len < ETH_ZLEN - ETH_HLEN)
+			len = ETH_ZLEN - ETH_HLEN;
 	} else { /* IEEE 802.3 frame */
 		data_len = len + ETH_HLEN;
 		data_off = HERMES_802_3_OFFSET;
 		p = skb->data;
+		/* Actual xfer length - round up for odd length packets */
+		len = ALIGN(data_len, 2);
+		if (len < ETH_ZLEN)
+			len = ETH_ZLEN;
 	}
 
-	err = hermes_bap_pwrite(hw, USER_BAP, p, data_len,
+	err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len,
 				txfid, data_off);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
@@ -634,16 +628,17 @@
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
 	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+	u16 status;
 	struct hermes_tx_descriptor_802_11 hdr;
 	int err = 0;
 
 	if (fid == DUMMY_FID)
 		return; /* Nothing's really happened */
 
-	/* Read the frame header */
+	/* Read part of the frame header - we need status and addr1 */
 	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
-			       sizeof(struct hermes_tx_descriptor) +
-			       sizeof(struct ieee80211_hdr),
+			       offsetof(struct hermes_tx_descriptor_802_11,
+					addr2),
 			       fid, 0);
 
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -663,8 +658,8 @@
 	 * exceeded, because that's the only status that really mean
 	 * that this particular node went away.
 	 * Other errors means that *we* screwed up. - Jean II */
-	hdr.status = le16_to_cpu(hdr.status);
-	if (hdr.status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+	status = le16_to_cpu(hdr.status);
+	if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
 		union iwreq_data	wrqu;
 
 		/* Copy 802.11 dest address.
@@ -723,18 +718,13 @@
 static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
 				      int level, int noise)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	int i;
-
-	/* Gather wireless spy statistics: for each packet, compare the
-	 * source address with out list, and if match, get the stats... */
-	for (i = 0; i < priv->spy_number; i++)
-		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
-			priv->spy_stat[i].level = level - 0x95;
-			priv->spy_stat[i].noise = noise - 0x95;
-			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
-			priv->spy_stat[i].updated = 7;
-		}
+	struct iw_quality wstats;
+	wstats.level = level - 0x95;
+	wstats.noise = noise - 0x95;
+	wstats.qual = (level > noise) ? (level - noise) : 0;
+	wstats.updated = 7;
+	/* Update spy records */
+	wireless_spy_update(dev, mac, &wstats);
 }
 
 static void orinoco_stat_gather(struct net_device *dev,
@@ -1055,7 +1045,7 @@
 	unsigned long flags;
 	struct join_req {
 		u8 bssid[ETH_ALEN];
-		u16 channel;
+		__le16 channel;
 	} __attribute__ ((packed)) req;
 	const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
 	struct prism2_scan_apinfo *atom = NULL;
@@ -1070,7 +1060,7 @@
 		return;
 
 	if (orinoco_lock(priv, &flags) != 0)
-		goto out;
+		goto fail_lock;
 
 	/* Sanity checks in case user changed something in the meantime */
 	if (! priv->bssid_fixed)
@@ -1115,8 +1105,10 @@
 		printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
 
  out:
-	kfree(buf);
 	orinoco_unlock(priv, &flags);
+
+ fail_lock:
+	kfree(buf);
 }
 
 /* Send new BSSID to userspace */
@@ -1134,12 +1126,14 @@
 	err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
 			      ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
 	if (err != 0)
-		return;
+		goto out;
 
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 
 	/* Send event to user space */
 	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+
+ out:
 	orinoco_unlock(priv, &flags);
 }
 
@@ -1148,8 +1142,8 @@
 	struct orinoco_private *priv = netdev_priv(dev);
 	u16 infofid;
 	struct {
-		u16 len;
-		u16 type;
+		__le16 len;
+		__le16 type;
 	} __attribute__ ((packed)) info;
 	int len, type;
 	int err;
@@ -2464,6 +2458,10 @@
 	dev->get_stats = orinoco_get_stats;
 	dev->ethtool_ops = &orinoco_ethtool_ops;
 	dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+#ifdef WIRELESS_SPY
+	priv->wireless_data.spy_data = &priv->spy_data;
+	dev->wireless_data = &priv->wireless_data;
+#endif
 	dev->change_mtu = orinoco_change_mtu;
 	dev->set_multicast_list = orinoco_set_multicast_list;
 	/* we use the default eth_mac_addr for setting the MAC addr */
@@ -2835,7 +2833,7 @@
 		}
 	}
 
-	if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
+	if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
 		/* Quality stats meaningless in ad-hoc mode */
 	} else {
 		range->max_qual.qual = 0x8b - 0x2f;
@@ -2882,6 +2880,14 @@
 	range->min_r_time = 0;
 	range->max_r_time = 65535 * 1000;	/* ??? */
 
+	/* Event capability (kernel) */
+	IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+	/* Event capability (driver) */
+	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+	IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+
 	TRACE_EXIT(dev->name);
 
 	return 0;
@@ -3841,92 +3847,6 @@
 	return err;
 }
 
-/* Spy is used for link quality/strength measurements in Ad-Hoc mode
- * Jean II */
-static int orinoco_ioctl_setspy(struct net_device *dev,
-				struct iw_request_info *info,
-				struct iw_point *srq,
-				char *extra)
-
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct sockaddr *address = (struct sockaddr *) extra;
-	int number = srq->length;
-	int i;
-	unsigned long flags;
-
-	/* Make sure nobody mess with the structure while we do */
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	/* orinoco_lock() doesn't disable interrupts, so make sure the
-	 * interrupt rx path don't get confused while we copy */
-	priv->spy_number = 0;
-
-	if (number > 0) {
-		/* Extract the addresses */
-		for (i = 0; i < number; i++)
-			memcpy(priv->spy_address[i], address[i].sa_data,
-			       ETH_ALEN);
-		/* Reset stats */
-		memset(priv->spy_stat, 0,
-		       sizeof(struct iw_quality) * IW_MAX_SPY);
-		/* Set number of addresses */
-		priv->spy_number = number;
-	}
-
-	/* Now, let the others play */
-	orinoco_unlock(priv, &flags);
-
-	/* Do NOT call commit handler */
-	return 0;
-}
-
-static int orinoco_ioctl_getspy(struct net_device *dev,
-				struct iw_request_info *info,
-				struct iw_point *srq,
-				char *extra)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct sockaddr *address = (struct sockaddr *) extra;
-	int number;
-	int i;
-	unsigned long flags;
-
-	if (orinoco_lock(priv, &flags) != 0)
-		return -EBUSY;
-
-	number = priv->spy_number;
-	/* Create address struct */
-	for (i = 0; i < number; i++) {
-		memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
-		address[i].sa_family = AF_UNIX;
-	}
-	if (number > 0) {
-		/* Create address struct */
-		for (i = 0; i < number; i++) {
-			memcpy(address[i].sa_data, priv->spy_address[i],
-			       ETH_ALEN);
-			address[i].sa_family = AF_UNIX;
-		}
-		/* Copy stats */
-		/* In theory, we should disable irqs while copying the stats
-		 * because the rx path might update it in the middle...
-		 * Bah, who care ? - Jean II */
-		memcpy(extra  + (sizeof(struct sockaddr) * number),
-		       priv->spy_stat, sizeof(struct iw_quality) * number);
-	}
-	/* Reset updated flags. */
-	for (i = 0; i < number; i++)
-		priv->spy_stat[i].updated = 0;
-
-	orinoco_unlock(priv, &flags);
-
-	srq->length = number;
-
-	return 0;
-}
-
 /* Trigger a scan (look for other cells in the vicinity */
 static int orinoco_ioctl_setscan(struct net_device *dev,
 				 struct iw_request_info *info,
@@ -3999,7 +3919,7 @@
 						   HERMES_HOSTSCAN_SYMBOL_BCAST);
 			break;
 		case FIRMWARE_TYPE_INTERSIL: {
-			u16 req[3];
+			__le16 req[3];
 
 			req[0] = cpu_to_le16(0x3fff);	/* All channels */
 			req[1] = cpu_to_le16(0x0001);	/* rate 1 Mbps */
@@ -4073,7 +3993,7 @@
 	case FIRMWARE_TYPE_INTERSIL:
 		offset = 4;
 		if (priv->has_hostscan) {
-			atom_len = le16_to_cpup((u16 *)scan);
+			atom_len = le16_to_cpup((__le16 *)scan);
 			/* Sanity check for atom_len */
 			if (atom_len < sizeof(struct prism2_scan_apinfo)) {
 				printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
@@ -4357,8 +4277,10 @@
 	[SIOCSIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
 	[SIOCGIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
 	[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
-	[SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setspy,
-	[SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getspy,
+	[SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
+	[SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
+	[SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
+	[SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
 	[SIOCSIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
 	[SIOCGIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
 	[SIOCSIWSCAN  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 2f213a7..7a17bb3 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -7,12 +7,11 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
-#define DRIVER_VERSION "0.15rc2"
+#define DRIVER_VERSION "0.15rc3"
 
-#include <linux/types.h>
-#include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
+#include <net/iw_handler.h>
 #include <linux/version.h>
 
 #include "hermes.h"
@@ -28,7 +27,7 @@
 #define ORINOCO_MAX_KEYS	4
 
 struct orinoco_key {
-	u16 len;	/* always stored as little-endian */
+	__le16 len;	/* always stored as little-endian */
 	char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
@@ -36,14 +35,14 @@
 	/* 802.3 */
 	u8 dest[ETH_ALEN];
 	u8 src[ETH_ALEN];
-	u16 len;
+	__be16 len;
 	/* 802.2 */
 	u8 dsap;
 	u8 ssap;
 	u8 ctrl;
 	/* SNAP */
 	u8 oui[3];
-	u16 ethertype;
+	unsigned short ethertype;
 } __attribute__ ((packed));
 
 typedef enum {
@@ -112,9 +111,8 @@
 	u16 pm_on, pm_mcast, pm_period, pm_timeout;
 	u16 preamble;
 #ifdef WIRELESS_SPY
-	int			spy_number;
-	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
-	struct iw_quality	spy_stat[IW_MAX_SPY];
+ 	struct iw_spy_data spy_data; /* iwspy support */
+	struct iw_public_data	wireless_data;
 #endif
 
 	/* Configuration dependent variables */
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index bedd7f9..dc1128a 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -14,33 +14,16 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-#ifdef  __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
 #include "orinoco.h"
 
 /********************************************************************/
@@ -97,17 +80,8 @@
 /* Function prototypes						    */
 /********************************************************************/
 
-/* device methods */
-static int orinoco_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void orinoco_cs_config(dev_link_t * link);
-static void orinoco_cs_release(dev_link_t * link);
-static int orinoco_cs_event(event_t event, int priority,
-			    event_callback_args_t * args);
-
-static dev_link_t *orinoco_cs_attach(void);
-static void orinoco_cs_detach(dev_link_t *);
+static void orinoco_cs_release(dev_link_t *link);
+static void orinoco_cs_detach(dev_link_t *link);
 
 /********************************************************************/
 /* Device methods     						    */
@@ -603,49 +577,85 @@
 	"Pavel Roskin <proski@gnu.org>, et al)";
 
 static struct pcmcia_device_id orinoco_cs_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
-	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
-	PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001),
-	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305),
-	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613),
-	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673),
-	PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001),
-	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300),
-	PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021),
-	PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
-	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
+	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
+	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
+	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
+	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
+	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
+	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
+	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
+	PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
+	PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
+	PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
+	PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
+	PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
+	PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
+	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
+	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
+	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
+	PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
+	PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
+	PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
+	PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
+	PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
+	PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
+	PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
+	PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
+	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
+	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
+	PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
 	PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
-	PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
 	PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
+	PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
+	PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
+	PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
+	PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
+	PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
 	PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
+	PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
 	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
+	PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
 	PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
+	PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
+	PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
 	PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
 	PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
 	PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
+	PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
+	PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
 	PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
 	PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
+	PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
+	PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
 	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
+	PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
+	PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
+	PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
+	PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
+	PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
 	PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
 	PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
 	PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
 	PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
 	PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
+	PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
 	PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
+	PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
+	PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
+	PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
+	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
 	PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
+	PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
 	PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
 	PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
-	PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6),
+	PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
+	PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
+	PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
+	PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
@@ -656,8 +666,8 @@
 		.name	= DRIVER_NAME,
 	},
 	.attach		= orinoco_cs_attach,
-	.event		= orinoco_cs_event,
 	.detach		= orinoco_cs_detach,
+	.event		= orinoco_cs_event,
 	.id_table       = orinoco_cs_ids,
 };
 
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 86fa58e..d8afd51 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -40,29 +40,13 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
 #include <pcmcia/cisreg.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 #define COR_OFFSET    (0xe0)	/* COR attribute offset of Prism2 PC card */
@@ -108,7 +92,7 @@
 	return 0;
 }
 
-int nortel_pci_hw_init(struct nortel_pci_card *card)
+static int nortel_pci_hw_init(struct nortel_pci_card *card)
 {
 	int i;
 	u32 reg;
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 42e0343..5362c21 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -93,28 +93,12 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "hermes.h"
 #include "orinoco.h"
 
 /* All the magic there is from wlan-ng */
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 7ab05b8..210e737 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -117,29 +117,13 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
 #include <pcmcia/cisreg.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 #define COR_OFFSET	(0x3e0)	/* COR attribute offset of Prism2 PC card */
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 85893f4..5e68b70 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -53,29 +53,13 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/fcntl.h>
-
 #include <pcmcia/cisreg.h>
 
-#include "hermes.h"
 #include "orinoco.h"
 
 #define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 9a8790e..5c1a1ad 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -462,14 +462,12 @@
 	/* txpower is supported in dBm's */
 	range->txpower_capa = IW_TXPOW_DBM;
 
-#if WIRELESS_EXT > 16
 	/* Event capability (kernel + driver) */
 	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
 	IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
 	IW_EVENT_CAPA_MASK(SIOCGIWAP));
 	range->event_capa[1] = IW_EVENT_CAPA_K_1;
 	range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
-#endif /* WIRELESS_EXT > 16 */
 
 	if (islpci_get_state(priv) < PRV_STATE_INIT)
 		return 0;
@@ -693,14 +691,13 @@
 						   extra + dwrq->length,
 						   &(bsslist->bsslist[i]),
 						   noise);
-#if WIRELESS_EXT > 16
+
 		/* Check if there is space for one more entry */
 		if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
 			/* Ask user space to try again with a bigger buffer */
 			rvalue = -E2BIG;
 			break;
 		}
-#endif /* WIRELESS_EXT > 16 */
 	}
 
 	kfree(bsslist);
@@ -2727,12 +2724,7 @@
 	.standard = (iw_handler *) prism54_handler,
 	.private = (iw_handler *) prism54_private_handler,
 	.private_args = (struct iw_priv_args *) prism54_private_args,
-#if WIRELESS_EXT > 16
 	.get_wireless_stats = prism54_get_wireless_stats,
-#endif /* WIRELESS_EXT > 16 */
-#if WIRELESS_EXT == 16
-	.spy_offset = offsetof(islpci_private, spy_data),
-#endif /* WIRELESS_EXT == 16 */
 };
 
 /* For wpa_supplicant */
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index 6f13d4a..78bdb35 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -439,8 +439,7 @@
 	wmb();
 
 	/* wait a while for the device to reset */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(50*HZ/1000);
+	schedule_timeout_uninterruptible(msecs_to_jiffies(50));
 
 	return 0;
 }
@@ -491,8 +490,7 @@
 		/* The software reset acknowledge needs about 220 msec here.
 		 * Be conservative and wait for up to one second. */
 	
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		remaining = schedule_timeout(HZ);
+		remaining = schedule_timeout_uninterruptible(HZ);
 
 		if(remaining > 0) {
 			result = 0;
@@ -756,8 +754,7 @@
 			pci_unmap_single(priv->pdev, buf->pci_addr,
 					 buf->size, PCI_DMA_FROMDEVICE);
 		buf->pci_addr = 0;
-		if (buf->mem)
-			kfree(buf->mem);
+		kfree(buf->mem);
 		buf->size = 0;
 		buf->mem = NULL;
         }
@@ -839,13 +836,9 @@
 	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
 		priv->monitor_type : ARPHRD_ETHER;
 
-#if WIRELESS_EXT > 16
 	/* Add pointers to enable iwspy support. */
 	priv->wireless_data.spy_data = &priv->spy_data;
 	ndev->wireless_data = &priv->wireless_data;
-#else  /* WIRELESS_EXT > 16 */
-	ndev->get_wireless_stats = &prism54_get_wireless_stats;
-#endif /* WIRELESS_EXT > 16 */
 
 	/* save the start and end address of the PCI memory area */
 	ndev->mem_start = (unsigned long) priv->device_base;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 32a1019..efbed43 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -100,9 +100,7 @@
 
 	struct iw_spy_data spy_data; /* iwspy support */
 
-#if WIRELESS_EXT > 16
 	struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT > 16 */
 
 	int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
 
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 5952e99..3b49efa 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -97,12 +97,6 @@
 	/* lock the driver code */
 	spin_lock_irqsave(&priv->slock, flags);
 
-	/* determine the amount of fragments needed to store the frame */
-
-	frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
-	if (init_wds)
-		frame_size += 6;
-
 	/* check whether the destination queue has enough fragments for the frame */
 	curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]);
 	if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) {
@@ -213,6 +207,7 @@
 	/* store the skb address for future freeing  */
 	priv->data_low_tx[index] = skb;
 	/* set the proper fragment start address and size information */
+	frame_size = skb->len;
 	fragment->size = cpu_to_le16(frame_size);
 	fragment->flags = cpu_to_le16(0);	/* set to 1 if more fragments */
 	fragment->address = cpu_to_le32(pci_map_address);
@@ -246,12 +241,10 @@
 	return 0;
 
       drop_free:
-	/* free the skbuf structure before aborting */
-	dev_kfree_skb(skb);
-	skb = NULL;
-
 	priv->statistics.tx_dropped++;
 	spin_unlock_irqrestore(&priv->slock, flags);
+	dev_kfree_skb(skb);
+	skb = NULL;
 	return err;
 }
 
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
index b6f2e5a..6a60c59 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/prism54/islpci_mgt.c
@@ -137,7 +137,7 @@
 						       PCI_DMA_FROMDEVICE);
 			if (!buf->pci_addr) {
 				printk(KERN_WARNING
-				       "Failed to make memory DMA'able\n.");
+				       "Failed to make memory DMA'able.\n");
 				return -ENOMEM;
 			}
 		}
@@ -455,7 +455,7 @@
 		       struct islpci_mgmtframe **recvframe)
 {
 	islpci_private *priv = netdev_priv(ndev);
-	const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
+	const long wait_cycle_jiffies = msecs_to_jiffies(ISL38XX_WAIT_CYCLE * 10);
 	long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
 	int err;
 	DEFINE_WAIT(wait);
@@ -475,8 +475,7 @@
 		int timeleft;
 		struct islpci_mgmtframe *frame;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		timeleft = schedule_timeout(wait_cycle_jiffies);
+		timeleft = schedule_timeout_uninterruptible(wait_cycle_jiffies);
 		frame = xchg(&priv->mgmt_received, NULL);
 		if (frame) {
 			if (frame->header->oid == oid) {
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index 12123e2..eea2f04 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -268,11 +268,10 @@
 
 	if (!priv->mib)
 		return;
-	for (i = 0; i < OID_NUM_LAST; i++)
-		if (priv->mib[i]) {
-			kfree(priv->mib[i]);
-			priv->mib[i] = NULL;
-		}
+	for (i = 0; i < OID_NUM_LAST; i++) {
+		kfree(priv->mib[i]);
+		priv->mib[i] = NULL;
+	}
 	kfree(priv->mib);
 	priv->mib = NULL;
 }
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index e9c5ea0..70fd6fd 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1649,28 +1649,28 @@
  */
 
 static const iw_handler	ray_handler[] = {
-	[SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) ray_commit,
-	[SIOCGIWNAME  -SIOCIWFIRST] (iw_handler) ray_get_name,
-	[SIOCSIWFREQ  -SIOCIWFIRST] (iw_handler) ray_set_freq,
-	[SIOCGIWFREQ  -SIOCIWFIRST] (iw_handler) ray_get_freq,
-	[SIOCSIWMODE  -SIOCIWFIRST] (iw_handler) ray_set_mode,
-	[SIOCGIWMODE  -SIOCIWFIRST] (iw_handler) ray_get_mode,
-	[SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) ray_get_range,
+	[SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit,
+	[SIOCGIWNAME  -SIOCIWFIRST] = (iw_handler) ray_get_name,
+	[SIOCSIWFREQ  -SIOCIWFIRST] = (iw_handler) ray_set_freq,
+	[SIOCGIWFREQ  -SIOCIWFIRST] = (iw_handler) ray_get_freq,
+	[SIOCSIWMODE  -SIOCIWFIRST] = (iw_handler) ray_set_mode,
+	[SIOCGIWMODE  -SIOCIWFIRST] = (iw_handler) ray_get_mode,
+	[SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range,
 #ifdef WIRELESS_SPY
- 	[SIOCSIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_set_spy,
-	[SIOCGIWSPY   -SIOCIWFIRST] (iw_handler) iw_handler_get_spy,
-	[SIOCSIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_set_thrspy,
-	[SIOCGIWTHRSPY-SIOCIWFIRST] (iw_handler) iw_handler_get_thrspy,
+ 	[SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
+	[SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
+	[SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
+	[SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
 #endif	/* WIRELESS_SPY */
-	[SIOCGIWAP    -SIOCIWFIRST] (iw_handler) ray_get_wap,
-	[SIOCSIWESSID -SIOCIWFIRST] (iw_handler) ray_set_essid,
-	[SIOCGIWESSID -SIOCIWFIRST] (iw_handler) ray_get_essid,
-	[SIOCSIWRATE  -SIOCIWFIRST] (iw_handler) ray_set_rate,
-	[SIOCGIWRATE  -SIOCIWFIRST] (iw_handler) ray_get_rate,
-	[SIOCSIWRTS   -SIOCIWFIRST] (iw_handler) ray_set_rts,
-	[SIOCGIWRTS   -SIOCIWFIRST] (iw_handler) ray_get_rts,
-	[SIOCSIWFRAG  -SIOCIWFIRST] (iw_handler) ray_set_frag,
-	[SIOCGIWFRAG  -SIOCIWFIRST] (iw_handler) ray_get_frag,
+	[SIOCGIWAP    -SIOCIWFIRST] = (iw_handler) ray_get_wap,
+	[SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid,
+	[SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid,
+	[SIOCSIWRATE  -SIOCIWFIRST] = (iw_handler) ray_set_rate,
+	[SIOCGIWRATE  -SIOCIWFIRST] = (iw_handler) ray_get_rate,
+	[SIOCSIWRTS   -SIOCIWFIRST] = (iw_handler) ray_set_rts,
+	[SIOCGIWRTS   -SIOCIWFIRST] = (iw_handler) ray_get_rts,
+	[SIOCSIWFRAG  -SIOCIWFIRST] = (iw_handler) ray_set_frag,
+	[SIOCGIWFRAG  -SIOCIWFIRST] = (iw_handler) ray_get_frag,
 };
 
 #define SIOCSIPFRAMING	SIOCIWFIRSTPRIV		/* Set framing mode */
@@ -1678,9 +1678,9 @@
 #define SIOCGIPCOUNTRY	SIOCIWFIRSTPRIV + 3	/* Get country code */
 
 static const iw_handler	ray_private_handler[] = {
-	[0] (iw_handler) ray_set_framing,
-	[1] (iw_handler) ray_get_framing,
-	[3] (iw_handler) ray_get_country,
+	[0] = (iw_handler) ray_set_framing,
+	[1] = (iw_handler) ray_get_framing,
+	[3] = (iw_handler) ray_get_country,
 };
 
 static const struct iw_priv_args	ray_private_args[] = {
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 39c6cdf..b1bbc8e 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -22,58 +22,23 @@
 #define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
-#ifdef  __IN_PCMCIA_PACKAGE__
-#include <pcmcia/k_compat.h>
-#endif /* __IN_PCMCIA_PACKAGE__ */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
+#include <linux/delay.h>
+#include <linux/firmware.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
 #include "orinoco.h"
 
-/*
- * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
- * the driver.  Use get_symbol_fw script to generate spectrum_fw.h and
- * copy it to the same directory as spectrum_cs.c.
- *
- * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
- * runtime using hotplug.  Use the same get_symbol_fw script to generate
- * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
- * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
- * make sure that you have hotplug installed and enabled in the kernel.
- */
-/* #define SPECTRUM_FW_INCLUDED 1 */
-
-#ifdef SPECTRUM_FW_INCLUDED
-/* Header with the firmware */
-#include "spectrum_fw.h"
-#else	/* !SPECTRUM_FW_INCLUDED */
-#include <linux/firmware.h>
 static unsigned char *primsym;
 static unsigned char *secsym;
 static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
 static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
-#endif	/* !SPECTRUM_FW_INCLUDED */
 
 /********************************************************************/
 /* Module stuff							    */
@@ -124,17 +89,8 @@
 /* Function prototypes						    */
 /********************************************************************/
 
-/* device methods */
-static int spectrum_cs_hard_reset(struct orinoco_private *priv);
-
-/* PCMCIA gumpf */
-static void spectrum_cs_config(dev_link_t * link);
-static void spectrum_cs_release(dev_link_t * link);
-static int spectrum_cs_event(event_t event, int priority,
-			    event_callback_args_t * args);
-
-static dev_link_t *spectrum_cs_attach(void);
-static void spectrum_cs_detach(dev_link_t *);
+static void spectrum_cs_release(dev_link_t *link);
+static void spectrum_cs_detach(dev_link_t *link);
 
 /********************************************************************/
 /* Firmware downloader						    */
@@ -182,8 +138,8 @@
  * Each block has the following structure.
  */
 struct dblock {
-	u32 _addr;		/* adapter address where to write the block */
-	u16 _len;		/* length of the data only, in bytes */
+	__le32 _addr;		/* adapter address where to write the block */
+	__le16 _len;		/* length of the data only, in bytes */
 	char data[0];		/* data to be written */
 } __attribute__ ((packed));
 
@@ -193,9 +149,9 @@
  * items with matching ID should be written.
  */
 struct pdr {
-	u32 _id;		/* record ID */
-	u32 _addr;		/* adapter address where to write the data */
-	u32 _len;		/* expected length of the data, in bytes */
+	__le32 _id;		/* record ID */
+	__le32 _addr;		/* adapter address where to write the data */
+	__le32 _len;		/* expected length of the data, in bytes */
 	char next[0];		/* next PDR starts here */
 } __attribute__ ((packed));
 
@@ -206,8 +162,8 @@
  * be plugged into the secondary firmware.
  */
 struct pdi {
-	u16 _len;		/* length of ID and data, in words */
-	u16 _id;		/* record ID */
+	__le16 _len;		/* length of ID and data, in words */
+	__le16 _id;		/* record ID */
 	char data[0];		/* plug data */
 } __attribute__ ((packed));;
 
@@ -414,7 +370,7 @@
 
 /* Read PDA from the adapter */
 static int
-spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
 {
 	int ret;
 	int pda_size;
@@ -445,7 +401,7 @@
 /* Parse PDA and write the records into the adapter */
 static int
 spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
-		   u16 *pda)
+		   __le16 *pda)
 {
 	int ret;
 	struct pdi *pdi;
@@ -511,7 +467,7 @@
 	const struct dblock *first_block;
 
 	/* Plug Data Area (PDA) */
-	u16 pda[PDA_WORDS];
+	__le16 pda[PDA_WORDS];
 
 	/* Binary block begins after the 0x1A marker */
 	ptr = image;
@@ -571,8 +527,6 @@
 {
 	int ret;
 	client_handle_t handle = link->handle;
-
-#ifndef SPECTRUM_FW_INCLUDED
 	const struct firmware *fw_entry;
 
 	if (request_firmware(&fw_entry, primary_fw_name,
@@ -592,7 +546,6 @@
 		       secondary_fw_name);
 		return -ENOENT;
 	}
-#endif
 
 	/* Load primary firmware */
 	ret = spectrum_dl_image(hw, link, primsym);
@@ -1085,7 +1038,7 @@
 static struct pcmcia_device_id spectrum_cs_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
 	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
-	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+	PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
@@ -1096,8 +1049,8 @@
 		.name	= DRIVER_NAME,
 	},
 	.attach		= spectrum_cs_attach,
-	.event		= spectrum_cs_event,
 	.detach		= spectrum_cs_detach,
+	.event		= spectrum_cs_event,
 	.id_table       = spectrum_cs_ids,
 };
 
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 7bc7fc8..d25264b 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -860,12 +860,9 @@
 		strip_info->mtu = dev->mtu = mtu;
 		return (1);
 	}
-	if (r)
-		kfree(r);
-	if (s)
-		kfree(s);
-	if (t)
-		kfree(t);
+	kfree(r);
+	kfree(s);
+	kfree(t);
 	return (0);
 }
 
@@ -922,13 +919,9 @@
 	printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n",
 	       strip_info->dev->name, old_mtu, strip_info->mtu);
 
-	if (orbuff)
-		kfree(orbuff);
-	if (osbuff)
-		kfree(osbuff);
-	if (otbuff)
-		kfree(otbuff);
-
+	kfree(orbuff);
+	kfree(osbuff);
+	kfree(otbuff);
 	return 0;
 }
 
@@ -2498,18 +2491,13 @@
 	/*
 	 * Free all STRIP frame buffers.
 	 */
-	if (strip_info->rx_buff) {
-		kfree(strip_info->rx_buff);
-		strip_info->rx_buff = NULL;
-	}
-	if (strip_info->sx_buff) {
-		kfree(strip_info->sx_buff);
-		strip_info->sx_buff = NULL;
-	}
-	if (strip_info->tx_buff) {
-		kfree(strip_info->tx_buff);
-		strip_info->tx_buff = NULL;
-	}
+	kfree(strip_info->rx_buff);
+	strip_info->rx_buff = NULL;
+	kfree(strip_info->sx_buff);
+	strip_info->sx_buff = NULL;
+	kfree(strip_info->tx_buff);
+	strip_info->tx_buff = NULL;
+
 	del_timer(&strip_info->idle_timer);
 	return 0;
 }
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 7a5e20a..b0d8b5b 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -430,7 +430,6 @@
 	}
 }
 
-#ifdef WIRELESS_EXT		/* if the wireless extension exists in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -514,7 +513,6 @@
 	fee_wait(ioaddr, 10, 100);
 #endif				/* EEPROM_IS_PROTECTED */
 }
-#endif				/* WIRELESS_EXT */
 
 /************************ I82586 SUBROUTINES *************************/
 /*
@@ -973,11 +971,9 @@
 	mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
 	mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
 
-#ifdef WIRELESS_EXT		/* if wireless extension exists in the kernel */
 	/* Don't forget to update statistics */
 	lp->wstats.discard.nwid +=
 	    (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif				/* WIRELESS_EXT */
 
 	printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
 #ifdef DEBUG_SHOW_UNUSED
@@ -1499,7 +1495,6 @@
 }
 #endif				/* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT		/* if wireless extensions exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2473,7 +2468,6 @@
 #endif
 	return &lp->wstats;
 }
-#endif				/* WIRELESS_EXT */
 
 /************************* PACKET RECEPTION *************************/
 /*
@@ -4194,11 +4188,9 @@
 	dev->set_mac_address = &wavelan_set_mac_address;
 #endif				/* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT		/* if wireless extension exists in the kernel */
 	dev->wireless_handlers = &wavelan_handler_def;
 	lp->wireless_data.spy_data = &lp->spy_data;
 	dev->wireless_data = &lp->wireless_data;
-#endif
 
 	dev->mtu = WAVELAN_MTU;
 
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 509ff22..166e28b 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -409,11 +409,9 @@
 #define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical). */
 #undef SET_MAC_ADDRESS		/* Experimental */
 
-#ifdef WIRELESS_EXT	/* If wireless extensions exist in the kernel */
 /* Warning:  this stuff will slow down the driver. */
 #define WIRELESS_SPY		/* Enable spying addresses. */
 #undef HISTOGRAM		/* Enable histogram of signal level. */
-#endif
 
 /****************************** DEBUG ******************************/
 
@@ -506,12 +504,10 @@
   u_short	tx_first_free;
   u_short	tx_first_in_use;
 
-#ifdef WIRELESS_EXT
   iw_stats	wstats;		/* Wireless-specific statistics */
 
   struct iw_spy_data	spy_data;
   struct iw_public_data	wireless_data;
-#endif
 
 #ifdef HISTOGRAM
   int		his_number;		/* number of intervals */
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 183c473..4b3c98f 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -415,7 +415,6 @@
     }
 }
 
-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -500,7 +499,6 @@
   fee_wait(base, 10, 100);
 #endif	/* EEPROM_IS_PROTECTED */
 }
-#endif	/* WIRELESS_EXT */
 
 /******************* WaveLAN Roaming routines... ********************/
 
@@ -1161,10 +1159,8 @@
   mmc_read(base, 0, (u_char *)&m, sizeof(m));
   mmc_out(base, mmwoff(0, mmw_freeze), 0);
 
-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
   /* Don't forget to update statistics */
   lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif	/* WIRELESS_EXT */
 
   spin_unlock_irqrestore(&lp->spinlock, flags);
 
@@ -1550,7 +1546,6 @@
 }
 #endif	/* SET_MAC_ADDRESS */
 
-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2793,7 +2788,6 @@
 #endif
   return &lp->wstats;
 }
-#endif	/* WIRELESS_EXT */
 
 /************************* PACKET RECEPTION *************************/
 /*
@@ -4679,11 +4673,9 @@
   dev->watchdog_timeo	= WATCHDOG_JIFFIES;
   SET_ETHTOOL_OPS(dev, &ops);
 
-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
   dev->wireless_handlers = &wavelan_handler_def;
   lp->wireless_data.spy_data = &lp->spy_data;
   dev->wireless_data = &lp->wireless_data;
-#endif
 
   /* Other specific data */
   dev->mtu = WAVELAN_MTU;
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 01d882b..724a715 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -472,11 +472,9 @@
 #define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical) */
 #undef SET_MAC_ADDRESS		/* Experimental */
 
-#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
 /* Warning : these stuff will slow down the driver... */
 #define WIRELESS_SPY		/* Enable spying addresses */
 #undef HISTOGRAM		/* Enable histogram of sig level... */
-#endif
 
 /****************************** DEBUG ******************************/
 
@@ -624,12 +622,10 @@
   int   	rfp;		/* Last DMA machine receive pointer */
   int		overrunning;	/* Receiver overrun flag */
 
-#ifdef WIRELESS_EXT
   iw_stats	wstats;		/* Wireless specific stats */
 
   struct iw_spy_data	spy_data;
   struct iw_public_data	wireless_data;
-#endif
 
 #ifdef HISTOGRAM
   int		his_number;		/* Number of intervals */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 7fcbe58..4303c50 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -548,7 +548,7 @@
 
 struct wl3501_80211_tx_hdr {
 	struct wl3501_80211_tx_plcp_hdr	pclp_hdr;
-	struct ieee80211_hdr		mac_hdr;
+	struct ieee80211_hdr_4addr		mac_hdr;
 } __attribute__ ((packed));
 
 /*
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
index 3886099..558420b 100644
--- a/drivers/parisc/asp.c
+++ b/drivers/parisc/asp.c
@@ -77,12 +77,12 @@
 	struct gsc_irq gsc_irq;
 	int ret;
 
-	asp.version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
+	asp.version = gsc_readb(dev->hpa.start + ASP_VER_OFFSET) & 0xf;
 	asp.name = (asp.version == 1) ? "Asp" : "Cutoff";
 	asp.hpa = ASP_INTERRUPT_ADDR;
 
 	printk(KERN_INFO "%s version %d at 0x%lx found.\n", 
-		asp.name, asp.version, dev->hpa);
+		asp.name, asp.version, dev->hpa.start);
 
 	/* the IRQ ASP should use */
 	ret = -EBUSY;
@@ -126,7 +126,7 @@
 };
 
 struct parisc_driver asp_driver = {
-	.name =		"Asp",
+	.name =		"asp",
 	.id_table =	asp_tbl,
 	.probe =	asp_init_chip,
 };
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 0e98a9d..9e0229f 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -100,9 +100,9 @@
 #define DBG_RUN_SG(x...)
 #endif
 
-#define CCIO_INLINE	/* inline */
-#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr))
-#define READ_U32(addr) gsc_readl((u32 *)(addr))
+#define CCIO_INLINE	inline
+#define WRITE_U32(value, addr) __raw_writel(value, addr)
+#define READ_U32(addr) __raw_readl(addr)
 
 #define U2_IOA_RUNWAY 0x580
 #define U2_BC_GSC     0x501
@@ -115,28 +115,28 @@
 
 struct ioa_registers {
         /* Runway Supervisory Set */
-        volatile int32_t    unused1[12];
-        volatile uint32_t   io_command;             /* Offset 12 */
-        volatile uint32_t   io_status;              /* Offset 13 */
-        volatile uint32_t   io_control;             /* Offset 14 */
-        volatile int32_t    unused2[1];
+        int32_t    unused1[12];
+        uint32_t   io_command;             /* Offset 12 */
+        uint32_t   io_status;              /* Offset 13 */
+        uint32_t   io_control;             /* Offset 14 */
+        int32_t    unused2[1];
 
         /* Runway Auxiliary Register Set */
-        volatile uint32_t   io_err_resp;            /* Offset  0 */
-        volatile uint32_t   io_err_info;            /* Offset  1 */
-        volatile uint32_t   io_err_req;             /* Offset  2 */
-        volatile uint32_t   io_err_resp_hi;         /* Offset  3 */
-        volatile uint32_t   io_tlb_entry_m;         /* Offset  4 */
-        volatile uint32_t   io_tlb_entry_l;         /* Offset  5 */
-        volatile uint32_t   unused3[1];
-        volatile uint32_t   io_pdir_base;           /* Offset  7 */
-        volatile uint32_t   io_io_low_hv;           /* Offset  8 */
-        volatile uint32_t   io_io_high_hv;          /* Offset  9 */
-        volatile uint32_t   unused4[1];
-        volatile uint32_t   io_chain_id_mask;       /* Offset 11 */
-        volatile uint32_t   unused5[2];
-        volatile uint32_t   io_io_low;              /* Offset 14 */
-        volatile uint32_t   io_io_high;             /* Offset 15 */
+        uint32_t   io_err_resp;            /* Offset  0 */
+        uint32_t   io_err_info;            /* Offset  1 */
+        uint32_t   io_err_req;             /* Offset  2 */
+        uint32_t   io_err_resp_hi;         /* Offset  3 */
+        uint32_t   io_tlb_entry_m;         /* Offset  4 */
+        uint32_t   io_tlb_entry_l;         /* Offset  5 */
+        uint32_t   unused3[1];
+        uint32_t   io_pdir_base;           /* Offset  7 */
+        uint32_t   io_io_low_hv;           /* Offset  8 */
+        uint32_t   io_io_high_hv;          /* Offset  9 */
+        uint32_t   unused4[1];
+        uint32_t   io_chain_id_mask;       /* Offset 11 */
+        uint32_t   unused5[2];
+        uint32_t   io_io_low;              /* Offset 14 */
+        uint32_t   io_io_high;             /* Offset 15 */
 };
 
 /*
@@ -226,7 +226,7 @@
 */
 
 struct ioc {
-	struct ioa_registers *ioc_hpa;  /* I/O MMU base address */
+	struct ioa_registers __iomem *ioc_regs;  /* I/O MMU base address */
 	u8  *res_map;	                /* resource map, bit == pdir entry */
 	u64 *pdir_base;	                /* physical base address */
 	u32 pdir_size; 			/* bytes, function of IOV Space size */
@@ -595,7 +595,7 @@
 	** Grab virtual index [0:11]
 	** Deposit virt_idx bits into I/O PDIR word
 	*/
-	asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+	asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
 	asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
 	asm volatile ("depw  %1,15,12,%0" : "+r" (pa) : "r" (ci));
 
@@ -613,7 +613,7 @@
 	** the real mode coherence index generation of U2, the PDIR entry
 	** must be flushed to memory to retain coherence."
 	*/
-	asm volatile("fdc 0(%0)" : : "r" (pdir_ptr));
+	asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
 	asm volatile("sync");
 }
 
@@ -636,7 +636,7 @@
 	byte_cnt += chain_size;
 
 	while(byte_cnt > chain_size) {
-		WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command);
+		WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_regs->io_command);
 		iovp += chain_size;
 		byte_cnt -= chain_size;
 	}
@@ -684,7 +684,7 @@
 		** Hopefully someone figures out how to patch (NOP) the
 		** FDC/SYNC out at boot time.
 		*/
-		asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7]));
+		asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr[7]));
 
 		iovp     += IOVP_SIZE;
 		byte_cnt -= IOVP_SIZE;
@@ -836,7 +836,7 @@
  * This function implements the pci_alloc_consistent function.
  */
 static void * 
-ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag)
+ccio_alloc_consistent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)
 {
       void *ret;
 #if 0
@@ -1251,7 +1251,7 @@
 static int ccio_probe(struct parisc_device *dev);
 
 static struct parisc_driver ccio_driver = {
-	.name =		"U2:Uturn",
+	.name =		"ccio",
 	.id_table =	ccio_tbl,
 	.probe =	ccio_probe,
 };
@@ -1314,14 +1314,13 @@
 
 	ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
 
-	BUG_ON(ioc->pdir_size >= 4 * 1024 * 1024);   /* max pdir size < 4MB */
+	BUG_ON(ioc->pdir_size > 8 * 1024 * 1024);   /* max pdir size <= 8MB */
 
 	/* Verify it's a power of two */
 	BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
 
-	DBG_INIT("%s() hpa 0x%lx mem %luMB IOV %dMB (%d bits)\n",
-			__FUNCTION__,
-			ioc->ioc_hpa,
+	DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
+			__FUNCTION__, ioc->ioc_regs,
 			(unsigned long) num_physpages >> (20 - PAGE_SHIFT),
 			iova_space_size>>20,
 			iov_order + PAGE_SHIFT);
@@ -1329,13 +1328,12 @@
 	ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, 
 						 get_order(ioc->pdir_size));
 	if(NULL == ioc->pdir_base) {
-		panic("%s:%s() could not allocate I/O Page Table\n", __FILE__,
-		      __FUNCTION__);
+		panic("%s() could not allocate I/O Page Table\n", __FUNCTION__);
 	}
 	memset(ioc->pdir_base, 0, ioc->pdir_size);
 
 	BUG_ON((((unsigned long)ioc->pdir_base) & PAGE_MASK) != (unsigned long)ioc->pdir_base);
-	DBG_INIT(" base %p", ioc->pdir_base);
+	DBG_INIT(" base %p\n", ioc->pdir_base);
 
 	/* resource map size dictated by pdir_size */
  	ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
@@ -1344,8 +1342,7 @@
 	ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, 
 					      get_order(ioc->res_size));
 	if(NULL == ioc->res_map) {
-		panic("%s:%s() could not allocate resource map\n", __FILE__,
-		      __FUNCTION__);
+		panic("%s() could not allocate resource map\n", __FUNCTION__);
 	}
 	memset(ioc->res_map, 0, ioc->res_size);
 
@@ -1366,44 +1363,58 @@
 	** Initialize IOA hardware
 	*/
 	WRITE_U32(CCIO_CHAINID_MASK << ioc->chainid_shift, 
-		  &ioc->ioc_hpa->io_chain_id_mask);
+		  &ioc->ioc_regs->io_chain_id_mask);
 
 	WRITE_U32(virt_to_phys(ioc->pdir_base), 
-		  &ioc->ioc_hpa->io_pdir_base);
+		  &ioc->ioc_regs->io_pdir_base);
 
 	/*
 	** Go to "Virtual Mode"
 	*/
-	WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_hpa->io_control);
+	WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_regs->io_control);
 
 	/*
 	** Initialize all I/O TLB entries to 0 (Valid bit off).
 	*/
-	WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_m);
-	WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_l);
+	WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_m);
+	WRITE_U32(0, &ioc->ioc_regs->io_tlb_entry_l);
 
 	for(i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
 		WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioc->chainid_shift)),
-			  &ioc->ioc_hpa->io_command);
+			  &ioc->ioc_regs->io_command);
 	}
 }
 
 static void
-ccio_init_resource(struct resource *res, char *name, unsigned long ioaddr)
+ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
 {
 	int result;
 
 	res->parent = NULL;
 	res->flags = IORESOURCE_MEM;
-	res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16;
-	res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1;
+	/*
+	 * bracing ((signed) ...) are required for 64bit kernel because
+	 * we only want to sign extend the lower 16 bits of the register.
+	 * The upper 16-bits of range registers are hardcoded to 0xffff.
+	 */
+	res->start = (unsigned long)((signed) READ_U32(ioaddr) << 16);
+	res->end = (unsigned long)((signed) (READ_U32(ioaddr + 4) << 16) - 1);
 	res->name = name;
+	/*
+	 * Check if this MMIO range is disable
+	 */
 	if (res->end + 1 == res->start)
 		return;
-	result = request_resource(&iomem_resource, res);
+
+	/* On some platforms (e.g. K-Class), we have already registered
+	 * resources for devices reported by firmware. Some are children
+	 * of ccio.
+	 * "insert" ccio ranges in the mmio hierarchy (/proc/iomem).
+	 */
+	result = insert_resource(&iomem_resource, res);
 	if (result < 0) {
-		printk(KERN_ERR "%s: failed to claim CCIO bus address space (%08lx,%08lx)\n", 
-		       __FILE__, res->start, res->end);
+		printk(KERN_ERR "%s() failed to claim CCIO bus address space (%08lx,%08lx)\n", 
+	 		__FUNCTION__, res->start, res->end);
 	}
 }
 
@@ -1414,9 +1425,8 @@
 
 	sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
 
-	ccio_init_resource(res, name, (unsigned long)&ioc->ioc_hpa->io_io_low);
-	ccio_init_resource(res + 1, name,
-			(unsigned long)&ioc->ioc_hpa->io_io_low_hv);
+	ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
+	ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
 }
 
 static int new_ioc_area(struct resource *res, unsigned long size,
@@ -1427,7 +1437,12 @@
 
 	res->start = (max - size + 1) &~ (align - 1);
 	res->end = res->start + size;
-	if (!request_resource(&iomem_resource, res))
+	
+	/* We might be trying to expand the MMIO range to include
+	 * a child device that has already registered it's MMIO space.
+	 * Use "insert" instead of request_resource().
+	 */
+	if (!insert_resource(&iomem_resource, res))
 		return 0;
 
 	return new_ioc_area(res, size, min, max - size, align);
@@ -1486,15 +1501,15 @@
 
 	if (!expand_ioc_area(parent, size, min, max, align)) {
 		__raw_writel(((parent->start)>>16) | 0xffff0000,
-			     (unsigned long)&(ioc->ioc_hpa->io_io_low));
+			     &ioc->ioc_regs->io_io_low);
 		__raw_writel(((parent->end)>>16) | 0xffff0000,
-			     (unsigned long)&(ioc->ioc_hpa->io_io_high));
+			     &ioc->ioc_regs->io_io_high);
 	} else if (!expand_ioc_area(parent + 1, size, min, max, align)) {
 		parent++;
 		__raw_writel(((parent->start)>>16) | 0xffff0000,
-			     (unsigned long)&(ioc->ioc_hpa->io_io_low_hv));
+			     &ioc->ioc_regs->io_io_low_hv);
 		__raw_writel(((parent->end)>>16) | 0xffff0000,
-			     (unsigned long)&(ioc->ioc_hpa->io_io_high_hv));
+			     &ioc->ioc_regs->io_io_high_hv);
 	} else {
 		return -EBUSY;
 	}
@@ -1521,7 +1536,12 @@
 		return -EBUSY;
 	}
 
-	return request_resource(parent, res);
+	/* "transparent" bus bridges need to register MMIO resources
+	 * firmware assigned them. e.g. children of hppb.c (e.g. K-class)
+	 * registered their resources in the PDC "bus walk" (See
+	 * arch/parisc/kernel/inventory.c).
+	 */
+	return insert_resource(parent, res);
 }
 
 /**
@@ -1546,7 +1566,7 @@
 
 	ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
 
-	printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa);
+	printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa.start);
 
 	for (i = 0; i < ioc_count; i++) {
 		ioc_p = &(*ioc_p)->next;
@@ -1554,7 +1574,7 @@
 	*ioc_p = ioc;
 
 	ioc->hw_path = dev->hw_path;
-	ioc->ioc_hpa = (struct ioa_registers *)dev->hpa;
+	ioc->ioc_regs = ioremap(dev->hpa.start, 4096);
 	ccio_ioc_init(ioc);
 	ccio_init_resources(ioc);
 	hppa_dma_ops = &ccio_ops;
diff --git a/drivers/parisc/ccio-rm-dma.c b/drivers/parisc/ccio-rm-dma.c
index 57e6385..356b835 100644
--- a/drivers/parisc/ccio-rm-dma.c
+++ b/drivers/parisc/ccio-rm-dma.c
@@ -167,7 +167,7 @@
 {
 	printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME,
 			dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn",
-			dev->hpa);
+			dev->hpa.start);
 
 /*
 ** FIXME - should check U2 registers to verify it's really running
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 2f2dbef..5ab7533 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -178,6 +178,8 @@
 	void __iomem *base_addr = d->hba.base_addr;
 	unsigned long flags;
 
+	DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where,
+									size);
 	spin_lock_irqsave(&d->dinosaur_pen, flags);
 
 	/* tell HW which CFG address */
@@ -211,6 +213,8 @@
 	void __iomem *base_addr = d->hba.base_addr;
 	unsigned long flags;
 
+	DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where,
+									size);
 	spin_lock_irqsave(&d->dinosaur_pen, flags);
 
 	/* avoid address stepping feature */
@@ -295,7 +299,7 @@
 	struct dino_device *dino_dev = irq_desc[irq].handler_data;
 	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
 
-	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
+	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
 
 	/* Clear the matching bit in the IMR register */
 	dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
@@ -308,7 +312,7 @@
 	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
 	u32 tmp;
 
-	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
+	DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
 
 	/*
 	** clear pending IRQ bits
@@ -490,7 +494,7 @@
 		if (res->start == F_EXTEND(0xf0000000UL | (i * _8MB)))
 			break;
 	}
-	DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %lx\n",
+	DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %p\n",
 	    i, res->start, base_addr + DINO_IO_ADDR_EN);
 	__raw_writel(1 << i, base_addr + DINO_IO_ADDR_EN);
 }
@@ -683,6 +687,14 @@
 dino_card_init(struct dino_device *dino_dev)
 {
 	u32 brdg_feat = 0x00784e05;
+	unsigned long status;
+
+	status = __raw_readl(dino_dev->hba.base_addr+DINO_IO_STATUS);
+	if (status & 0x0000ff80) {
+		__raw_writel(0x00000005,
+				dino_dev->hba.base_addr+DINO_IO_COMMAND);
+		udelay(1);
+	}
 
 	__raw_writel(0x00000000, dino_dev->hba.base_addr+DINO_GMASK);
 	__raw_writel(0x00000001, dino_dev->hba.base_addr+DINO_IO_FBB_EN);
@@ -902,15 +914,15 @@
 ** If so, initialize the chip appropriately (card-mode vs bridge mode).
 ** Much of the initialization is common though.
 */
-static int __init
-dino_driver_callback(struct parisc_device *dev)
+static int __init dino_probe(struct parisc_device *dev)
 {
 	struct dino_device *dino_dev;	// Dino specific control struct
 	const char *version = "unknown";
 	char *name;
 	int is_cujo = 0;
 	struct pci_bus *bus;
-	
+	unsigned long hpa = dev->hpa.start;
+
 	name = "Dino";
 	if (is_card_dino(&dev->id)) {
 		version = "3.x (card mode)";
@@ -928,11 +940,11 @@
 		}
 	}
 
-	printk("%s version %s found at 0x%lx\n", name, version, dev->hpa);
+	printk("%s version %s found at 0x%lx\n", name, version, hpa);
 
-	if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) {
+	if (!request_mem_region(hpa, PAGE_SIZE, name)) {
 		printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n",
-			dev->hpa);
+			hpa);
 		return 1;
 	}
 
@@ -940,12 +952,12 @@
 	if (is_cujo && dev->id.hversion_rev == 1) {
 #ifdef CONFIG_IOMMU_CCIO
 		printk(KERN_WARNING "Enabling Cujo 2.0 bug workaround\n");
-		if (dev->hpa == (unsigned long)CUJO_RAVEN_ADDR) {
+		if (hpa == (unsigned long)CUJO_RAVEN_ADDR) {
 			ccio_cujo20_fixup(dev, CUJO_RAVEN_BADPAGE);
-		} else if (dev->hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
+		} else if (hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
 			ccio_cujo20_fixup(dev, CUJO_FIREHAWK_BADPAGE);
 		} else {
-			printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", dev->hpa);
+			printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", hpa);
 		}
 #endif
 	} else if (!is_cujo && !is_card_dino(&dev->id) &&
@@ -970,7 +982,7 @@
 	memset(dino_dev, 0, sizeof(struct dino_device));
 
 	dino_dev->hba.dev = dev;
-	dino_dev->hba.base_addr = ioremap(dev->hpa, 4096); /* faster access */
+	dino_dev->hba.base_addr = ioremap(hpa, 4096);
 	dino_dev->hba.lmmio_space_offset = 0;	/* CPU addrs == bus addrs */
 	spin_lock_init(&dino_dev->dinosaur_pen);
 	dino_dev->hba.iommu = ccio_get_iommu(dev);
@@ -1027,9 +1039,9 @@
 };
 
 static struct parisc_driver dino_driver = {
-	.name =		"Dino",
+	.name =		"dino",
 	.id_table =	dino_tbl,
-	.probe =	dino_driver_callback,
+	.probe =	dino_probe,
 };
 
 /*
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 043d47a..6362bf9 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -315,7 +315,7 @@
 	char *name = is_mongoose(dev) ? "Mongoose" : "Wax";
 
 	printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n", 
-		name, dev->hpa);
+		name, dev->hpa.start);
 
 	eisa_dev.hba.dev = dev;
 	eisa_dev.hba.iommu = ccio_get_iommu(dev);
@@ -397,7 +397,7 @@
 MODULE_DEVICE_TABLE(parisc, eisa_tbl);
 
 static struct parisc_driver eisa_driver = {
-	.name =		"EISA Bus Adapter",
+	.name =		"eisa_ba",
 	.id_table =	eisa_tbl,
 	.probe =	eisa_probe,
 };
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index af5e025..16d40f9 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -183,12 +183,20 @@
 	*irqp = irq;
 }
 
+static struct device *next_device(struct klist_iter *i)
+{
+	struct klist_node * n = klist_next(i);
+	return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
 void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
 			void (*choose_irq)(struct parisc_device *, void *))
 {
 	struct device *dev;
+	struct klist_iter i;
 
-	list_for_each_entry(dev, &parent->dev.children, node) {
+	klist_iter_init(&parent->dev.klist_children, &i);
+	while ((dev = next_device(&i))) {
 		struct parisc_device *padev = to_parisc_device(dev);
 
 		/* work-around for 715/64 and others which have parent 
@@ -197,6 +205,7 @@
 			return gsc_fixup_irqs(padev, ctrl, choose_irq);
 		choose_irq(padev, ctrl);
 	}
+	klist_iter_exit(&i);
 }
 
 int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index e869c60..5edf93f 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -68,14 +68,14 @@
 		memset(card->next, '\0', sizeof(struct hppb_card));
 		card = card->next;
 	}
-        printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa);
+        printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa.start);
 
-	card->hpa = dev->hpa;
+	card->hpa = dev->hpa.start;
 	card->mmio_region.name = "HP-PB Bus";
 	card->mmio_region.flags = IORESOURCE_MEM;
 
-	card->mmio_region.start = __raw_readl(dev->hpa + IO_IO_LOW);
-	card->mmio_region.end = __raw_readl(dev->hpa + IO_IO_HIGH) - 1;
+	card->mmio_region.start = gsc_readl(dev->hpa.start + IO_IO_LOW);
+	card->mmio_region.end = gsc_readl(dev->hpa.start + IO_IO_HIGH) - 1;
 
 	status = ccio_request_resource(dev, &card->mmio_region);
 	if(status < 0) {
@@ -93,7 +93,7 @@
 };
 
 static struct parisc_driver hppb_driver = {
-        .name =         "Gecko Boa",
+        .name =         "gecko_boa",
         .id_table =     hppb_tbl,
 	.probe =        hppb_probe,
 };
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 7a57c1b..a39fbfe 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -244,7 +244,7 @@
 	 * 4-byte alignment on 32-bit kernels
 	 */
 	a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
-	a = (a + 7) & ~7;
+	a = (a + 7UL) & ~7UL;
 	return (struct irt_entry *)a;
 }
 
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index cb84a4e..a8c2039 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -175,7 +175,7 @@
 		return -ENOMEM;
 
 	lasi->name = "Lasi";
-	lasi->hpa = dev->hpa;
+	lasi->hpa = dev->hpa.start;
 
 	/* Check the 4-bit (yes, only 4) version register */
 	lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf;
@@ -233,7 +233,7 @@
 };
 
 struct parisc_driver lasi_driver = {
-	.name =		"Lasi",
+	.name =		"lasi",
 	.id_table =	lasi_tbl,
 	.probe =	lasi_init_chip,
 };
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 7fdd80b..5e495dc 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -1288,7 +1288,7 @@
 		** Adjust "window" for this rope.
 		*/
 		rsize /= ROPES_PER_IOC;
-		r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa);
+		r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa.start);
 		r->end = r->start + rsize;
 	} else {
 		r->end = r->start = 0;	/* Not enabled. */
@@ -1458,7 +1458,7 @@
 	u32 func_class;
 	void *tmp_obj;
 	char *version;
-	void __iomem *addr = ioremap(dev->hpa, 4096);
+	void __iomem *addr = ioremap(dev->hpa.start, 4096);
 
 	/* Read HW Rev First */
 	func_class = READ_REG32(addr + LBA_FCLASS);
@@ -1476,7 +1476,7 @@
 		}
 
 		printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
-			MODULE_NAME, version, func_class & 0xf, dev->hpa);
+			MODULE_NAME, version, func_class & 0xf, dev->hpa.start);
 
 		if (func_class < 2) {
 			printk(KERN_WARNING "Can't support LBA older than "
@@ -1503,17 +1503,17 @@
                  * but for the mask for func_class.
                  */ 
 		printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
-			MODULE_NAME, version, func_class & 0xff, dev->hpa);
+		       MODULE_NAME, version, func_class & 0xff, dev->hpa.start);
 		cfg_ops = &mercury_cfg_ops;
 	} else {
-		printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa);
+		printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa.start);
 		return -ENODEV;
 	}
 
 	/*
 	** Tell I/O SAPIC driver we have a IRQ handler/region.
 	*/
-	tmp_obj = iosapic_register(dev->hpa + LBA_IOSAPIC_BASE);
+	tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE);
 
 	/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
 	**	have an IRT entry will get NULL back from iosapic code.
@@ -1635,7 +1635,7 @@
 */
 void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
 {
-	void __iomem * base_addr = ioremap(lba->hpa, 4096);
+	void __iomem * base_addr = ioremap(lba->hpa.start, 4096);
 
 	imask <<= 2;	/* adjust for hints - 2 more bits */
 
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 2869022..95bd07b 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -18,6 +18,9 @@
  * Changes:
  *      - Audit copy_from_user in led_proc_write.
  *                                Daniele Bellucci <bellucda@tiscali.it>
+ *	- Switch from using a tasklet to a work queue, so the led_LCD_driver
+ *	  	can sleep.
+ *	  			  David Pye <dmp@davidmpye.dyndns.org>
  */
 
 #include <linux/config.h>
@@ -37,6 +40,7 @@
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
 #include <linux/blkdev.h>
+#include <linux/workqueue.h>
 #include <linux/rcupdate.h>
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -47,25 +51,30 @@
 #include <asm/uaccess.h>
 
 /* The control of the LEDs and LCDs on PARISC-machines have to be done 
-   completely in software. The necessary calculations are done in a tasklet
-   which is scheduled at every timer interrupt and since the calculations 
-   may consume relatively much CPU-time some of the calculations can be 
+   completely in software. The necessary calculations are done in a work queue
+   task which is scheduled regularly, and since the calculations may consume a 
+   relatively large amount of CPU time, some of the calculations can be 
    turned off with the following variables (controlled via procfs) */
 
 static int led_type = -1;
-static int led_heartbeat = 1;
-static int led_diskio = 1;
-static int led_lanrxtx = 1;
+static unsigned char lastleds;	/* LED state from most recent update */
+static unsigned int led_heartbeat = 1;
+static unsigned int led_diskio = 1;
+static unsigned int led_lanrxtx = 1;
 static char lcd_text[32];
 static char lcd_text_default[32];
 
+
+static struct workqueue_struct *led_wq;
+static void led_work_func(void *);
+static DECLARE_WORK(led_task, led_work_func, NULL);
+
 #if 0
 #define DPRINTK(x)	printk x
 #else
 #define DPRINTK(x)
 #endif
 
-
 struct lcd_block {
 	unsigned char command;	/* stores the command byte      */
 	unsigned char on;	/* value for turning LED on     */
@@ -116,12 +125,27 @@
 #define LCD_DATA_REG	lcd_info.lcd_data_reg_addr	 
 #define LED_DATA_REG	lcd_info.lcd_cmd_reg_addr	/* LASI & ASP only */
 
+#define LED_HASLCD 1
+#define LED_NOLCD  0
+
+/* The workqueue must be created at init-time */
+static int start_task(void) 
+{	
+	/* Display the default text now */
+	if (led_type == LED_HASLCD) lcd_print( lcd_text_default );
+
+	/* Create the work queue and queue the LED task */
+	led_wq = create_singlethread_workqueue("led_wq");	
+	queue_work(led_wq, &led_task);
+
+	return 0;
+}
+
+device_initcall(start_task);
 
 /* ptr to LCD/LED-specific function */
 static void (*led_func_ptr) (unsigned char);
 
-#define LED_HASLCD 1
-#define LED_NOLCD  0
 #ifdef CONFIG_PROC_FS
 static int led_proc_read(char *page, char **start, off_t off, int count, 
 	int *eof, void *data)
@@ -286,52 +310,35 @@
 /*
    ** 
    ** led_LCD_driver()
-   ** 
-   ** The logic of the LCD driver is, that we write at every scheduled call
-   ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers.
-   ** That way we don't need to let this tasklet busywait for min_cmd_delay
-   ** milliseconds.
-   **
-   ** TODO: check the value of "min_cmd_delay" against the value of HZ.
    **   
  */
 static void led_LCD_driver(unsigned char leds)
 {
-	static int last_index;	/* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */
-	static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */
-	struct lcd_block *block_ptr;
-	int value;
-
-	switch (last_index) {
-	    case 0:	block_ptr = &lcd_info.heartbeat;
-			value = leds & LED_HEARTBEAT;
-			break;
-	    case 1:	block_ptr = &lcd_info.disk_io;
-			value = leds & LED_DISK_IO;
-			break;					
-	    case 2:	block_ptr = &lcd_info.lan_rcv;
-			value = leds & LED_LAN_RCV;
-			break;					
-	    case 3:	block_ptr = &lcd_info.lan_tx;
-			value = leds & LED_LAN_TX;
-			break;
-	    default:	/* should never happen: */
-			return;
-	}
-
-	if (last_was_cmd) {
-	    /* write the value to the LCD data port */
-    	    gsc_writeb( value ? block_ptr->on : block_ptr->off, LCD_DATA_REG );
-	} else {
-	    /* write the command-byte to the LCD command register */
-    	    gsc_writeb( block_ptr->command, LCD_CMD_REG );
-	}    
+	static int i;
+	static unsigned char mask[4] = { LED_HEARTBEAT, LED_DISK_IO,
+		LED_LAN_RCV, LED_LAN_TX };
 	
-	/* now update the vars for the next interrupt iteration */ 
-	if (++last_was_cmd == 2) { /* switch between cmd & data */
-	    last_was_cmd = 0;
-	    if (++last_index == 4) 
-		last_index = 0;	 /* switch back to heartbeat index */
+	static struct lcd_block * blockp[4] = {
+		&lcd_info.heartbeat,
+		&lcd_info.disk_io,
+		&lcd_info.lan_rcv,
+		&lcd_info.lan_tx
+	};
+
+	/* Convert min_cmd_delay to milliseconds */
+	unsigned int msec_cmd_delay = 1 + (lcd_info.min_cmd_delay / 1000);
+	
+	for (i=0; i<4; ++i) 
+	{
+		if ((leds & mask[i]) != (lastleds & mask[i])) 
+		{
+			gsc_writeb( blockp[i]->command, LCD_CMD_REG );
+			msleep(msec_cmd_delay);
+			
+			gsc_writeb( leds & mask[i] ? blockp[i]->on : 
+					blockp[i]->off, LCD_DATA_REG );
+			msleep(msec_cmd_delay);
+		}
 	}
 }
 
@@ -356,7 +363,7 @@
 
 	rx_total = tx_total = 0;
 	
-	/* we are running as tasklet, so locking dev_base 
+	/* we are running as a workqueue task, so locking dev_base 
 	 * for reading should be OK */
 	read_lock(&dev_base_lock);
 	rcu_read_lock();
@@ -405,7 +412,7 @@
 	static unsigned long last_pgpgin, last_pgpgout;
 	struct page_state pgstat;
 	int changed;
-	
+
 	get_full_page_state(&pgstat); /* get no of sectors in & out */
 
 	/* Just use a very simple calculation here. Do not care about overflow,
@@ -413,87 +420,71 @@
 	changed = (pgstat.pgpgin != last_pgpgin) || (pgstat.pgpgout != last_pgpgout);
 	last_pgpgin  = pgstat.pgpgin;
 	last_pgpgout = pgstat.pgpgout;
-	
+
 	return (changed ? LED_DISK_IO : 0);
 }
 
 
 
 /*
-   ** led_tasklet_func()
+   ** led_work_func()
    ** 
-   ** is scheduled at every timer interrupt from time.c and
-   ** updates the chassis LCD/LED 
+   ** manages when and which chassis LCD/LED gets updated
 
     TODO:
     - display load average (older machines like 715/64 have 4 "free" LED's for that)
     - optimizations
  */
 
-#define HEARTBEAT_LEN (HZ*6/100)
-#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
+#define HEARTBEAT_LEN (HZ*10/100)
+#define HEARTBEAT_2ND_RANGE_START (HZ*28/100)
 #define HEARTBEAT_2ND_RANGE_END   (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
 
-#define NORMALIZED_COUNT(count) (count/(HZ/100))
+#define LED_UPDATE_INTERVAL (1 + (HZ*19/1000))
 
-static void led_tasklet_func(unsigned long unused)
+static void led_work_func (void *unused)
 {
-	static unsigned char lastleds;
-	unsigned char currentleds; /* stores current value of the LEDs */
-	static unsigned long count; /* static incremented value, not wrapped */
+	static unsigned long last_jiffies;
 	static unsigned long count_HZ; /* counter in range 0..HZ */
+	unsigned char currentleds = 0; /* stores current value of the LEDs */
 
 	/* exit if not initialized */
 	if (!led_func_ptr)
 	    return;
 
-	/* increment the local counters */
-	++count;
-	if (++count_HZ == HZ)
+	/* increment the heartbeat timekeeper */
+	count_HZ += jiffies - last_jiffies;
+	last_jiffies = jiffies;
+	if (count_HZ >= HZ)
 	    count_HZ = 0;
 
-	currentleds = lastleds;
-
-	if (led_heartbeat)
+	if (likely(led_heartbeat))
 	{
-		/* flash heartbeat-LED like a real heart (2 x short then a long delay) */
-		if (count_HZ<HEARTBEAT_LEN || 
-		    (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END)) 
-		    currentleds |= LED_HEARTBEAT;
-		else
-		    currentleds &= ~LED_HEARTBEAT;
+		/* flash heartbeat-LED like a real heart
+		 * (2 x short then a long delay)
+		 */
+		if (count_HZ < HEARTBEAT_LEN || 
+				(count_HZ >= HEARTBEAT_2ND_RANGE_START &&
+				count_HZ < HEARTBEAT_2ND_RANGE_END)) 
+			currentleds |= LED_HEARTBEAT;
 	}
 
-	/* look for network activity and flash LEDs respectively */
-	if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
-	{
-		currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
-		currentleds |= led_get_net_activity();
-	}
-
-	/* avoid to calculate diskio-stats at same irq  as netio-stats */
-	if (led_diskio && (NORMALIZED_COUNT(count) & 7) == 0)
-	{
-		currentleds &= ~LED_DISK_IO;
-		currentleds |= led_get_diskio_activity();
-	}
+	if (likely(led_lanrxtx))  currentleds |= led_get_net_activity();
+	if (likely(led_diskio))   currentleds |= led_get_diskio_activity();
 
 	/* blink all LEDs twice a second if we got an Oops (HPMC) */
-	if (oops_in_progress) {
+	if (unlikely(oops_in_progress)) 
 		currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff;
+
+	if (currentleds != lastleds)
+	{
+		led_func_ptr(currentleds);	/* Update the LCD/LEDs */
+		lastleds = currentleds;
 	}
-	
-	/* update the LCD/LEDs */
-	if (currentleds != lastleds) {
-	    led_func_ptr(currentleds);
-	    lastleds = currentleds;
-	}
+
+	queue_delayed_work(led_wq, &led_task, LED_UPDATE_INTERVAL);
 }
 
-/* main led tasklet struct (scheduled from time.c) */
-DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0);
-
-
 /*
    ** led_halt()
    ** 
@@ -522,9 +513,13 @@
 	default:		return NOTIFY_DONE;
 	}
 	
-	/* completely stop the LED/LCD tasklet */
-	tasklet_disable(&led_tasklet);
-
+	/* Cancel the work item and delete the queue */
+	if (led_wq) {
+		cancel_rearming_delayed_workqueue(led_wq, &led_task);
+		destroy_workqueue(led_wq);
+		led_wq = NULL;
+	}
+ 
 	if (lcd_info.model == DISPLAY_MODEL_LCD)
 		lcd_print(txt);
 	else
@@ -559,7 +554,6 @@
 		printk(KERN_INFO "LCD display at %lx,%lx registered\n", 
 			LCD_CMD_REG , LCD_DATA_REG);
 		led_func_ptr = led_LCD_driver;
-		lcd_print( lcd_text_default );
 		led_type = LED_HASLCD;
 		break;
 
@@ -589,9 +583,11 @@
 	initialized++;
 	register_reboot_notifier(&led_notifier);
 
-	/* start the led tasklet for the first time */
-	tasklet_enable(&led_tasklet);
-	
+	/* Ensure the work is queued */
+	if (led_wq) {
+		queue_work(led_wq, &led_task);
+	}
+
 	return 0;
 }
 
@@ -626,8 +622,8 @@
    ** lcd_print()
    ** 
    ** Displays the given string on the LCD-Display of newer machines.
-   ** lcd_print() disables the timer-based led tasklet during its 
-   ** execution and enables it afterwards again.
+   ** lcd_print() disables/enables the timer-based led work queue to
+   ** avoid a race condition while writing the CMD/DATA register pair.
    **
  */
 int lcd_print( char *str )
@@ -637,12 +633,13 @@
 	if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD)
 	    return 0;
 	
-	/* temporarily disable the led tasklet */
-	tasklet_disable(&led_tasklet);
+	/* temporarily disable the led work task */
+	if (led_wq)
+		cancel_rearming_delayed_workqueue(led_wq, &led_task);
 
 	/* copy display string to buffer for procfs */
 	strlcpy(lcd_text, str, sizeof(lcd_text));
-	
+
 	/* Set LCD Cursor to 1st character */
 	gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);
 	udelay(lcd_info.min_cmd_delay);
@@ -656,8 +653,10 @@
 	    udelay(lcd_info.min_cmd_delay);
 	}
 	
-	/* re-enable the led tasklet */
-	tasklet_enable(&led_tasklet);
+	/* re-queue the work */
+	if (led_wq) {
+		queue_work(led_wq, &led_task);
+	}
 
 	return lcd_info.lcd_width;
 }
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 67c8f3b..273a741 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -536,7 +536,7 @@
 
 	out += sprintf(out, "Memory tested: ");
 	if ((result & 0x0F) < 0x0E)
-		out += sprintf(out, "%.3f MB", 0.256*(1<<(result & 0x0F)));
+		out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256);
 	else
 		out += sprintf(out, "All");
 	out += sprintf(out, "\n");
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 82ea68b..c85653f 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -91,8 +91,8 @@
 #define DBG_RES(x...)
 #endif
 
-#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
-/* "low end" PA8800 machines use ZX1 chipset */
+#if defined(CONFIG_64BIT)
+/* "low end" PA8800 machines use ZX1 chipset: PAT PDC and only run 64-bit */
 #define ZX1_SUPPORT
 #endif
 
@@ -231,7 +231,7 @@
 	spinlock_t	res_lock;
 	unsigned int	res_bitshift;	/* from the LEFT! */
 	unsigned int	res_size;	/* size of resource map in bytes */
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
 /* FIXME : DMA HINTs not used */
 	unsigned long	hint_mask_pdir;	/* bits used for DMA hints */
 	unsigned int	hint_shift_pdir;
@@ -294,7 +294,7 @@
 /* Looks nice and keeps the compiler happy */
 #define SBA_DEV(d) ((struct sba_device *) (d))
 
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
 static int reserve_sba_gart = 1;
 #endif
 
@@ -314,7 +314,7 @@
 #define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr)
 #define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr)
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 #define READ_REG(addr)		READ_REG64(addr)
 #define WRITE_REG(value, addr)	WRITE_REG64(value, addr)
 #else
@@ -324,7 +324,7 @@
 
 #ifdef DEBUG_SBA_INIT
 
-/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
+/* NOTE: When CONFIG_64BIT isn't defined, READ_REG64() is two 32-bit reads */
 
 /**
  * sba_dump_ranges - debugging only - print ranges assigned to this IOA
@@ -364,7 +364,7 @@
 #else
 #define sba_dump_ranges(x)
 #define sba_dump_tlb(x)
-#endif
+#endif	/* DEBUG_SBA_INIT */
 
 
 #ifdef ASSERT_PDIR_SANITY
@@ -674,7 +674,7 @@
 *
 ***************************************************************/
 
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
 #define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
 #endif
 
@@ -743,9 +743,8 @@
 	 * (bit #61, big endian), we have to flush and sync every time
 	 * IO-PDIR is changed in Ike/Astro.
 	 */
-	if (ioc_needs_fdc) {
-		asm volatile("fdc 0(%%sr1,%0)\n\tsync" : : "r" (pdir_ptr));
-	}
+	if (ioc_needs_fdc)
+		asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
 }
 
 
@@ -769,42 +768,57 @@
 sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 {
 	u32 iovp = (u32) SBA_IOVP(ioc,iova);
-
-	/* Even though this is a big-endian machine, the entries
-	** in the iopdir are little endian. That's why we clear the byte
-	** at +7 instead of at +0.
-	*/
-	int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
+	u64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
 
 #ifdef ASSERT_PDIR_SANITY
-	/* Assert first pdir entry is set */
-	if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
+	/* Assert first pdir entry is set.
+	**
+	** Even though this is a big-endian machine, the entries
+	** in the iopdir are little endian. That's why we look at
+	** the byte at +7 instead of at +0.
+	*/
+	if (0x80 != (((u8 *) pdir_ptr)[7])) {
 		sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
 	}
 #endif
 
-	if (byte_cnt <= IOVP_SIZE)
+	if (byte_cnt > IOVP_SIZE)
 	{
-		iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
+#if 0
+		unsigned long entries_per_cacheline = ioc_needs_fdc ?
+				L1_CACHE_ALIGN(((unsigned long) pdir_ptr))
+					- (unsigned long) pdir_ptr;
+				: 262144;
+#endif
 
-		/*
-		** clear I/O PDIR entry "valid" bit
-		** Do NOT clear the rest - save it for debugging.
-		** We should only clear bits that have previously
-		** been enabled.
-		*/
-		((u8 *)(ioc->pdir_base))[off] = 0;
-	} else {
-		u32 t = get_order(byte_cnt) + PAGE_SHIFT;
+		/* set "size" field for PCOM */
+		iovp |= get_order(byte_cnt) + PAGE_SHIFT;
 
-		iovp |= t;
 		do {
 			/* clear I/O Pdir entry "valid" bit first */
-			((u8 *)(ioc->pdir_base))[off] = 0;
-			off += sizeof(u64);
+			((u8 *) pdir_ptr)[7] = 0;
+			if (ioc_needs_fdc) {
+				asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
+#if 0
+				entries_per_cacheline = L1_CACHE_SHIFT - 3;
+#endif
+			}
+			pdir_ptr++;
 			byte_cnt -= IOVP_SIZE;
-		} while (byte_cnt > 0);
-	}
+		} while (byte_cnt > IOVP_SIZE);
+	} else
+		iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
+
+	/*
+	** clear I/O PDIR entry "valid" bit.
+	** We have to R/M/W the cacheline regardless how much of the
+	** pdir entry that we clobber.
+	** The rest of the entry would be useful for debugging if we
+	** could dump core on HPMC.
+	*/
+	((u8 *) pdir_ptr)[7] = 0;
+	if (ioc_needs_fdc)
+		asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr));
 
 	WRITE_REG( SBA_IOVA(ioc, iovp, 0, 0), ioc->ioc_hpa+IOC_PCOM);
 }
@@ -819,18 +833,29 @@
 static int sba_dma_supported( struct device *dev, u64 mask)
 {
 	struct ioc *ioc;
+
 	if (dev == NULL) {
 		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
 		BUG();
 		return(0);
 	}
 
+	/* Documentation/DMA-mapping.txt tells drivers to try 64-bit first,
+	 * then fall back to 32-bit if that fails.
+	 * We are just "encouraging" 32-bit DMA masks here since we can
+	 * never allow IOMMU bypass unless we add special support for ZX1.
+	 */
+	if (mask > ~0U)
+		return 0;
+
 	ioc = GET_IOC(dev);
 
-	/* check if mask is > than the largest IO Virt Address */
-
-	return((int) (mask >= (ioc->ibase +
-				(ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
+	/*
+	 * check if mask is >= than the current max IO Virt Address
+	 * The max IO Virt address will *always* < 30 bits.
+	 */
+	return((int)(mask >= (ioc->ibase - 1 +
+			(ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
 }
 
 
@@ -898,11 +923,17 @@
 		size -= IOVP_SIZE;
 		pdir_start++;
 	}
-	/* form complete address */
+
+	/* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+	if (ioc_needs_fdc)
+		asm volatile("sync" : : );
+
 #ifdef ASSERT_PDIR_SANITY
 	sba_check_pdir(ioc,"Check after sba_map_single()");
 #endif
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+	/* form complete address */
 	return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
 }
 
@@ -958,12 +989,19 @@
 			d--;
 		}
 		ioc->saved_cnt = 0;
+
 		READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 	}
 #else /* DELAYED_RESOURCE_CNT == 0 */
 	sba_free_range(ioc, iova, size);
+
+	/* If fdc's were issued, force fdc's to be visible now */
+	if (ioc_needs_fdc)
+		asm volatile("sync" : : );
+
 	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 #endif /* DELAYED_RESOURCE_CNT == 0 */
+
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 
 	/* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
@@ -986,7 +1024,7 @@
  * See Documentation/DMA-mapping.txt
  */
 static void *sba_alloc_consistent(struct device *hwdev, size_t size,
-					dma_addr_t *dma_handle, int gfp)
+					dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret;
 
@@ -1106,6 +1144,10 @@
 	*/
 	filled = iommu_fill_pdir(ioc, sglist, nents, 0, sba_io_pdir_entry);
 
+	/* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+	if (ioc_needs_fdc)
+		asm volatile("sync" : : );
+
 #ifdef ASSERT_PDIR_SANITY
 	if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
 	{
@@ -1234,8 +1276,10 @@
 	unsigned long pdir_order = get_order(pdir_size);
 
 	pdir_base = __get_free_pages(GFP_KERNEL, pdir_order);
-	if (NULL == (void *) pdir_base)
-		panic("sba_ioc_init() could not allocate I/O Page Table\n");
+	if (NULL == (void *) pdir_base)	{
+		panic("%s() could not allocate I/O Page Table\n",
+			__FUNCTION__);
+	}
 
 	/* If this is not PA8700 (PCX-W2)
 	**	OR newer than ver 2.2
@@ -1322,19 +1366,29 @@
 	return (void *) pdir_base;
 }
 
-/* setup Mercury or Elroy IBASE/IMASK registers. */
-static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+static struct device *next_device(struct klist_iter *i)
 {
-        /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
+        struct klist_node * n = klist_next(i);
+        return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
+/* setup Mercury or Elroy IBASE/IMASK registers. */
+static void 
+setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+{
+	/* lba_set_iregs() is in drivers/parisc/lba_pci.c */
         extern void lba_set_iregs(struct parisc_device *, u32, u32);
 	struct device *dev;
+	struct klist_iter i;
 
-	list_for_each_entry(dev, &sba->dev.children, node) {
+	klist_iter_init(&sba->dev.klist_children, &i);
+	while ((dev = next_device(&i))) {
 		struct parisc_device *lba = to_parisc_device(dev);
-		int rope_num = (lba->hpa >> 13) & 0xf;
+		int rope_num = (lba->hpa.start >> 13) & 0xf;
 		if (rope_num >> 3 == ioc_num)
 			lba_set_iregs(lba, ioc->ibase, ioc->imask);
 	}
+	klist_iter_exit(&i);
 }
 
 static void
@@ -1343,7 +1397,7 @@
 	u32 iova_space_mask;
 	u32 iova_space_size;
 	int iov_order, tcnfg;
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
 	int agp_found = 0;
 #endif
 	/*
@@ -1380,7 +1434,7 @@
 	DBG_INIT("%s() pdir %p size %x\n",
 			__FUNCTION__, ioc->pdir_base, ioc->pdir_size);
 
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
 	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
 	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
 
@@ -1404,7 +1458,7 @@
 
 	WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	/*
 	** Setting the upper bits makes checking for bypass addresses
 	** a little faster later on.
@@ -1437,7 +1491,7 @@
 	*/
 	WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
 
-#if SBA_AGP_SUPPORT
+#ifdef SBA_AGP_SUPPORT
 	/*
 	** If an AGP device is present, only use half of the IOV space
 	** for PCI DMA.  Unfortunately we can't know ahead of time
@@ -1489,11 +1543,9 @@
 	if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
 		iova_space_size = 1 << (20 - PAGE_SHIFT);
 	}
-#ifdef __LP64__
 	else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
 		iova_space_size = 1 << (30 - PAGE_SHIFT);
 	}
-#endif
 
 	/*
 	** iova space must be log2() in size.
@@ -1519,7 +1571,7 @@
 	DBG_INIT("%s() pdir %p size %x\n",
 			__FUNCTION__, ioc->pdir_base, pdir_size);
 
-#if SBA_HINT_SUPPORT
+#ifdef SBA_HINT_SUPPORT
 	/* FIXME : DMA HINTs not used */
 	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
 	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
@@ -1590,7 +1642,7 @@
 
 static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
 {
-	return ioremap(sba_dev->dev->hpa + offset, SBA_FUNC_SIZE);
+	return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE);
 }
 
 static void sba_hw_init(struct sba_device *sba_dev)
@@ -1968,7 +2020,7 @@
 	u32 func_class;
 	int i;
 	char *version;
-	void __iomem *sba_addr = ioremap(dev->hpa, SBA_FUNC_SIZE);
+	void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
 
 	sba_dump_ranges(sba_addr);
 
@@ -2010,7 +2062,7 @@
 	}
 
 	printk(KERN_INFO "%s found %s at 0x%lx\n",
-		MODULE_NAME, version, dev->hpa);
+		MODULE_NAME, version, dev->hpa.start);
 
 	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
 	if (!sba_dev) {
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index e0efed7..bab3bca 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -11,6 +11,7 @@
  * 	(C) Copyright 2000 Alex deVries <alex@onefishtwo.ca>
  *      (C) Copyright 2001 John Marvin <jsm fc hp com>
  *      (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
+ *	(C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License as
@@ -405,6 +406,7 @@
         
 	serial[0].iobase = sio_dev.sp1_base;
 	serial[0].irq = SP1_IRQ;
+	spin_lock_init(&serial[0].lock);
 
 	retval = early_serial_setup(&serial[0]);
 	if (retval < 0) {
@@ -414,6 +416,7 @@
 
 	serial[1].iobase = sio_dev.sp2_base;
 	serial[1].irq = SP2_IRQ;
+	spin_lock_init(&serial[1].lock);
 	retval = early_serial_setup(&serial[1]);
 
 	if (retval < 0)
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index e547d7d..17dce2a 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -81,7 +81,7 @@
 		return -ENOMEM;
 
 	wax->name = "wax";
-	wax->hpa = dev->hpa;
+	wax->hpa = dev->hpa.start;
 
 	wax->version = 0;   /* gsc_readb(wax->hpa+WAX_VER); */
 	printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa);
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 02d72ac..fde29a7 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -359,11 +359,12 @@
 	unsigned long port;
 
 	if (!dev->irq) {
-		printk("IRQ not found for parallel device at 0x%lx\n", dev->hpa);
+		printk(KERN_WARNING "IRQ not found for parallel device at 0x%lx\n",
+			dev->hpa.start);
 		return -ENODEV;
 	}
 
-	port = dev->hpa + PARPORT_GSC_OFFSET;
+	port = dev->hpa.start + PARPORT_GSC_OFFSET;
 	
 	/* some older machines with ASP-chip don't support
 	 * the enhanced parport modes.
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 24a76de..2a42add 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -60,3 +60,92 @@
 EXPORT_SYMBOL(pci_bus_write_config_byte);
 EXPORT_SYMBOL(pci_bus_write_config_word);
 EXPORT_SYMBOL(pci_bus_write_config_dword);
+
+static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
+{
+	u32 data;
+
+	data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
+	data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
+	return data;
+}
+
+#define PCI_USER_READ_CONFIG(size,type)					\
+int pci_user_read_config_##size						\
+	(struct pci_dev *dev, int pos, type *val)			\
+{									\
+	unsigned long flags;						\
+	int ret = 0;							\
+	u32 data = -1;							\
+	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
+	spin_lock_irqsave(&pci_lock, flags);				\
+	if (likely(!dev->block_ucfg_access))				\
+		ret = dev->bus->ops->read(dev->bus, dev->devfn,		\
+					pos, sizeof(type), &data);	\
+	else if (pos < sizeof(dev->saved_config_space))			\
+		data = pci_user_cached_config(dev, pos); 		\
+	spin_unlock_irqrestore(&pci_lock, flags);			\
+	*val = (type)data;						\
+	return ret;							\
+}
+
+#define PCI_USER_WRITE_CONFIG(size,type)				\
+int pci_user_write_config_##size					\
+	(struct pci_dev *dev, int pos, type val)			\
+{									\
+	unsigned long flags;						\
+	int ret = -EIO;							\
+	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
+	spin_lock_irqsave(&pci_lock, flags);				\
+	if (likely(!dev->block_ucfg_access))				\
+		ret = dev->bus->ops->write(dev->bus, dev->devfn,	\
+					pos, sizeof(type), val);	\
+	spin_unlock_irqrestore(&pci_lock, flags);			\
+	return ret;							\
+}
+
+PCI_USER_READ_CONFIG(byte, u8)
+PCI_USER_READ_CONFIG(word, u16)
+PCI_USER_READ_CONFIG(dword, u32)
+PCI_USER_WRITE_CONFIG(byte, u8)
+PCI_USER_WRITE_CONFIG(word, u16)
+PCI_USER_WRITE_CONFIG(dword, u32)
+
+/**
+ * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * @dev:	pci device struct
+ *
+ * This function blocks any userspace PCI config accesses from occurring.
+ * When blocked, any writes will be bit bucketed and reads will return the
+ * data saved using pci_save_state for the first 64 bytes of config
+ * space and return 0xff for all other config reads.
+ **/
+void pci_block_user_cfg_access(struct pci_dev *dev)
+{
+	unsigned long flags;
+
+	pci_save_state(dev);
+
+	/* spinlock to synchronize with anyone reading config space now */
+	spin_lock_irqsave(&pci_lock, flags);
+	dev->block_ucfg_access = 1;
+	spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
+
+/**
+ * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
+ * @dev:	pci device struct
+ *
+ * This function allows userspace PCI config accesses to resume.
+ **/
+void pci_unblock_user_cfg_access(struct pci_dev *dev)
+{
+	unsigned long flags;
+
+	/* spinlock to synchronize with anyone reading saved config space */
+	spin_lock_irqsave(&pci_lock, flags);
+	dev->block_ucfg_access = 0;
+	spin_unlock_irqrestore(&pci_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 424e7de..8e21f6a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,6 +58,9 @@
 
 static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
 static void handle_hotplug_event_func (acpi_handle, u32, void *);
+static void acpiphp_sanitize_bus(struct pci_bus *bus);
+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
+
 
 /*
  * initialization & terminatation routines
@@ -796,8 +799,13 @@
 		}
 	}
 
+	pci_bus_size_bridges(bus);
 	pci_bus_assign_resources(bus);
+	acpiphp_sanitize_bus(bus);
+	pci_enable_bridges(bus);
 	pci_bus_add_devices(bus);
+	acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
+	acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));
 
 	/* associate pci_dev to our representation */
 	list_for_each (l, &slot->funcs) {
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
index a62a434..2d4639d6 100644
--- a/drivers/pci/hotplug/cpcihp_generic.c
+++ b/drivers/pci/hotplug/cpcihp_generic.c
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
+#include <linux/string.h>
 #include "cpci_hotplug.h"
 
 #define DRIVER_VERSION	"0.1"
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index e992802..f7cb00d 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -36,6 +36,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
+#include <linux/signal.h>	/* SA_SHIRQ */
 #include "cpci_hotplug.h"
 #include "cpcihp_zt5550.h"
 
@@ -78,11 +79,20 @@
 
 static int zt5550_hc_config(struct pci_dev *pdev)
 {
+	int ret;
+
 	/* Since we know that no boards exist with two HC chips, treat it as an error */
 	if(hc_dev) {
 		err("too many host controller devices?");
 		return -EBUSY;
 	}
+
+	ret = pci_enable_device(pdev);
+	if(ret) {
+		err("cannot enable %s\n", pci_name(pdev));
+		return ret;
+	}
+
 	hc_dev = pdev;
 	dbg("hc_dev = %p", hc_dev);
 	dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
@@ -91,7 +101,8 @@
 	if(!request_mem_region(pci_resource_start(hc_dev, 1),
 				pci_resource_len(hc_dev, 1), MY_NAME)) {
 		err("cannot reserve MMIO region");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto exit_disable_device;
 	}
 
 	hc_registers =
@@ -99,9 +110,8 @@
 	if(!hc_registers) {
 		err("cannot remap MMIO region %lx @ %lx",
 		    pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
-		release_mem_region(pci_resource_start(hc_dev, 1),
-				   pci_resource_len(hc_dev, 1));
-		return -ENODEV;
+		ret = -ENODEV;
+		goto exit_release_region;
 	}
 
 	csr_hc_index = hc_registers + CSR_HCINDEX;
@@ -124,6 +134,13 @@
 	writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
 	dbg("disabled timer0, timer1 and ENUM interrupts");
 	return 0;
+
+exit_release_region:
+	release_mem_region(pci_resource_start(hc_dev, 1),
+			   pci_resource_len(hc_dev, 1));
+exit_disable_device:
+	pci_disable_device(hc_dev);
+	return ret;
 }
 
 static int zt5550_hc_cleanup(void)
@@ -134,6 +151,7 @@
 	iounmap(hc_registers);
 	release_mem_region(pci_resource_start(hc_dev, 1),
 			   pci_resource_len(hc_dev, 1));
+	pci_disable_device(hc_dev);
 	return 0;
 }
 
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 8c6d398..9aed8ef 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -794,12 +794,21 @@
 	u32 rc;
 	struct controller *ctrl;
 	struct pci_func *func;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
+			pci_name(pdev), err);
+		return err;
+	}
 
 	// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
 	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
 	if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
 		err(msg_HPC_non_compaq_or_intel);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err_disable_device;
 	}
 	dbg("Vendor ID: %x\n", vendor_id);
 
@@ -807,7 +816,8 @@
 	dbg("revision: %d\n", rev);
 	if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
 		err(msg_HPC_rev_error);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err_disable_device;
 	}
 
 	/* Check for the proper subsytem ID's
@@ -820,18 +830,20 @@
 		rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
 		if (rc) {
 			err("%s : pci_read_config_word failed\n", __FUNCTION__);
-			return rc;
+			goto err_disable_device;
 		}
 		dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
 		if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
 			err(msg_HPC_non_compaq_or_intel);
-			return -ENODEV;
+			rc = -ENODEV;
+			goto err_disable_device;
 		}
 
 		ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
 		if (!ctrl) {
 			err("%s : out of memory\n", __FUNCTION__);
-			return -ENOMEM;
+			rc = -ENOMEM;
+			goto err_disable_device;
 		}
 		memset(ctrl, 0, sizeof(struct controller));
 
@@ -1264,6 +1276,8 @@
 	kfree(ctrl->pci_bus);
 err_free_ctrl:
 	kfree(ctrl);
+err_disable_device:
+	pci_disable_device(pdev);
 	return rc;
 }
 
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 8e47fa6..060d747 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -37,6 +37,8 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include "pci_hotplug.h"
 #include "../pci.h"
 
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 0392e00..aabf1e7 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -1077,7 +1077,7 @@
 	if (rc) {
 		err("Adding this card exceeds the limitations of this bus.\n");
 		err("(i.e., >1 133MHz cards running on same bus, or "
-		     ">2 66 PCI cards running on same bus\n.");
+		     ">2 66 PCI cards running on same bus.\n");
 		err("Try hot-adding into another bus\n");
 		rc = -EINVAL;
 		goto error_nopower;
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 33b539b..ff17d8e 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -113,7 +113,7 @@
  */
 int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
 {
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC)
 	int rc;
 	u16 temp_word;
 	struct pci_dev fakedev;
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c
index 3622965..33b2c69 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.c
@@ -33,10 +33,13 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/slab.h>
+
 #include <asm/uaccess.h>
 #ifdef CONFIG_IA64
 #include <asm/iosapic.h>
 #endif
+
 #include "pciehp.h"
 #include "pciehprm.h"
 #include "pciehprm_nonacpi.h"
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index ad1017d..fcb66b9 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -16,10 +16,13 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/string.h>
+
 #include <asm/pci-bridge.h>
 #include <asm/semaphore.h>
 #include <asm/rtas.h>
 #include <asm/vio.h>
+
 #include "../pci.h"
 #include "rpaphp.h"
 #include "rpadlpar.h"
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 61d94d1..71ea5f9 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -92,9 +92,10 @@
 extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
 extern int rpaphp_enable_pci_slot(struct slot *slot);
 extern int register_pci_slot(struct slot *slot);
-extern int rpaphp_unconfig_pci_adapter(struct slot *slot);
 extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
+
 extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
+extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
 
 /* rpaphp_core.c */
 extern int rpaphp_add_slot(struct device_node *dn);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index c830ff0..cf075c3 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -426,8 +426,11 @@
 
 	dbg("DISABLING SLOT %s\n", slot->name);
 	down(&rpaphp_sem);
-	retval = rpaphp_unconfig_pci_adapter(slot);
+	retval = rpaphp_unconfig_pci_adapter(slot->bus);
 	up(&rpaphp_sem);
+	slot->state = NOT_CONFIGURED;
+	info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
+	     slot->name);
 exit:
 	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
 	return retval;
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 49e4d10..f7c12d7 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -23,11 +23,13 @@
  *
  */
 #include <linux/pci.h>
+#include <linux/string.h>
+
 #include <asm/pci-bridge.h>
 #include <asm/rtas.h>
 #include <asm/machdep.h>
-#include "../pci.h"		/* for pci_add_new_bus */
 
+#include "../pci.h"		/* for pci_add_new_bus */
 #include "rpaphp.h"
 
 static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
@@ -319,20 +321,15 @@
 	return;
 }
 
-int rpaphp_unconfig_pci_adapter(struct slot *slot)
+int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
 {
 	struct pci_dev *dev, *tmp;
-	int retval = 0;
 
-	list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
+	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
 		rpaphp_eeh_remove_bus_device(dev);
 		pci_remove_bus_device(dev);
 	}
-
-	slot->state = NOT_CONFIGURED;
-	info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
-	     slot->name);
-	return retval;
+	return 0;
 }
 
 static int setup_pci_hotplug_slot_info(struct slot *slot)
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 0e88154..daa89ae 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -27,6 +27,9 @@
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
 #include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
 #include <asm/rtas.h>
 #include "rpaphp.h"
 
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index b7d1c61..08ad26a 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -32,8 +32,8 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>		
+#include <linux/sched.h>	/* signal_pending(), struct timer_list */
+
 #include "pci_hotplug.h"
 
 #if !defined(MODULE)
@@ -52,42 +52,18 @@
 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
-struct pci_func {
-	struct pci_func *next;
-	u8 bus;
-	u8 device;
-	u8 function;
-	u8 is_a_board;
-	u16 status;
-	u8 configured;
-	u8 switch_save;
-	u8 presence_save;
-	u8 pwr_save;
-	u32 base_length[0x06];
-	u8 base_type[0x06];
-	u16 reserved2;
-	u32 config_space[0x20];
-	struct pci_resource *mem_head;
-	struct pci_resource *p_mem_head;
-	struct pci_resource *io_head;
-	struct pci_resource *bus_head;
-	struct pci_dev* pci_dev;
-};
-
 #define SLOT_MAGIC	0x67267321
 struct slot {
 	u32 magic;
 	struct slot *next;
 	u8 bus;
 	u8 device;
+	u16 status;
 	u32 number;
 	u8 is_a_board;
-	u8 configured;
 	u8 state;
-	u8 switch_save;
 	u8 presence_save;
-	u32 capabilities;
-	u16 reserved2;
+	u8 pwr_save;
 	struct timer_list task_event;
 	u8 hp_slot;
 	struct controller *ctrl;
@@ -96,12 +72,6 @@
 	struct list_head	slot_list;
 };
 
-struct pci_resource {
-	struct pci_resource * next;
-	u32 base;
-	u32 length;
-};
-
 struct event_info {
 	u32 event_type;
 	u8 hp_slot;
@@ -110,13 +80,9 @@
 struct controller {
 	struct controller *next;
 	struct semaphore crit_sect;	/* critical section semaphore */
-	void * hpc_ctlr_handle;		/* HPC controller handle */
+	struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
 	int num_slots;			/* Number of slots on ctlr */
 	int slot_num_inc;		/* 1 or -1 */
-	struct pci_resource *mem_head;
-	struct pci_resource *p_mem_head;
-	struct pci_resource *io_head;
-	struct pci_resource *bus_head;
 	struct pci_dev *pci_dev;
 	struct pci_bus *pci_bus;
 	struct event_info event_queue[10];
@@ -124,33 +90,21 @@
 	struct hpc_ops *hpc_ops;
 	wait_queue_head_t queue;	/* sleep & wake process */
 	u8 next_event;
-	u8 seg;
 	u8 bus;
 	u8 device;
 	u8 function;
-	u8 rev;
 	u8 slot_device_offset;
 	u8 add_support;
 	enum pci_bus_speed speed;
 	u32 first_slot;		/* First physical slot number */
 	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
-	u8 push_flag;
-	u16 ctlrcap;
-	u16 vendor_id;
 };
 
-struct irq_mapping {
-	u8 barber_pole;
-	u8 valid_INT;
-	u8 interrupt[4];
-};
-
-struct resource_lists {
-	struct pci_resource *mem_head;
-	struct pci_resource *p_mem_head;
-	struct pci_resource *io_head;
-	struct pci_resource *bus_head;
-	struct irq_mapping *irqs;
+struct hotplug_params {
+	u8	cache_line_size;
+	u8	latency_timer;
+	u8	enable_serr;
+	u8	enable_perr;
 };
 
 /* Define AMD SHPC ID  */
@@ -194,24 +148,16 @@
  * error Messages
  */
 #define msg_initialization_err	"Initialization failure, error=%d\n"
-#define msg_HPC_rev_error	"Unsupported revision of the PCI hot plug controller found.\n"
-#define msg_HPC_non_shpc	"The PCI hot plug controller is not supported by this driver.\n"
-#define msg_HPC_not_supported	"This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n"
-#define msg_unable_to_save	"Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
 #define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
 #define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
 #define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
-#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"
 
 /* sysfs functions for the hotplug controller info */
 extern void shpchp_create_ctrl_files	(struct controller *ctrl);
 
 /* controller functions */
-extern int	shpchprm_find_available_resources(struct controller *ctrl);
 extern int	shpchp_event_start_thread(void);
 extern void	shpchp_event_stop_thread(void);
-extern struct 	pci_func *shpchp_slot_create(unsigned char busnumber);
-extern struct 	pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
 extern int	shpchp_enable_slot(struct slot *slot);
 extern int	shpchp_disable_slot(struct slot *slot);
 
@@ -220,29 +166,20 @@
 extern u8	shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
 extern u8	shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
 
-/* resource functions */
-extern int	shpchp_resource_sort_and_combine(struct pci_resource **head);
-
 /* pci functions */
-extern int	shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-/*extern int	shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
 extern int	shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
-extern int	shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
-extern int	shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
-extern void	shpchp_destroy_board_resources(struct pci_func * func);
-extern int	shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
-extern void	shpchp_destroy_resource_list(struct resource_lists * resources);
-extern int	shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
-extern int	shpchp_unconfigure_device(struct pci_func* func);
+extern int	shpchp_configure_device(struct slot *p_slot);
+extern int	shpchp_unconfigure_device(struct slot *p_slot);
+extern void	get_hp_hw_control_from_firmware(struct pci_dev *dev);
+extern void	get_hp_params_from_firmware(struct pci_dev *dev,
+		struct hotplug_params *hpp);
+extern int	shpchprm_get_physical_slot_number(struct controller *ctrl,
+		u32 *sun, u8 busnum, u8 devnum);
+extern void	shpchp_remove_ctrl_files(struct controller *ctrl);
 
 
 /* Global variables */
 extern struct controller *shpchp_ctrl_list;
-extern struct pci_func *shpchp_slot_list[256];
-
-/* These are added to support AMD shpc */
-extern u8 shpchp_nic_irq;
-extern u8 shpchp_disk_irq;
 
 struct ctrl_reg {
 	volatile u32 base_offset;
@@ -298,7 +235,7 @@
 	SLOT11 =	offsetof(struct ctrl_reg, slot11),
 	SLOT12 =	offsetof(struct ctrl_reg, slot12),
 };
-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
+typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
 struct php_ctlr_state_s {
 	struct php_ctlr_state_s *pnext;
 	struct pci_dev *pci_dev;
@@ -359,12 +296,9 @@
 
 	p_slot = ctrl->slot;
 
-	dbg("p_slot = %p\n", p_slot);
-
 	while (p_slot && (p_slot->device != device)) {
 		tmp_slot = p_slot;
 		p_slot = p_slot->next;
-		dbg("In while loop, p_slot = %p\n", p_slot);
 	}
 	if (p_slot == NULL) {
 		err("ERROR: shpchp_find_slot device=0x%x\n", device);
@@ -379,8 +313,6 @@
     DECLARE_WAITQUEUE(wait, current);
 	int retval = 0;
 
-	dbg("%s : start\n",__FUNCTION__);
-
 	add_wait_queue(&ctrl->queue, &wait);
 
 	if (!shpchp_poll_mode) {
@@ -394,19 +326,9 @@
 	if (signal_pending(current))
 		retval =  -EINTR;
 
-	dbg("%s : end\n", __FUNCTION__);
 	return retval;
 }
 
-/* Puts node back in the resource list pointed to by head */
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
-{
-	if (!node || !head)
-		return;
-	node->next = *head;
-	*head = node;
-}
-
 #define SLOT_NAME_SIZE 10
 
 static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
@@ -420,11 +342,7 @@
 	ACPI
 };
 
-int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
-		php_intr_callback_t attention_button_callback,
-		php_intr_callback_t switch_change_callback,
-		php_intr_callback_t presence_change_callback,
-		php_intr_callback_t power_fault_callback);
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
 
 int shpc_get_ctlr_slot_config( struct controller *ctrl,
 		int *num_ctlr_slots,
@@ -437,8 +355,6 @@
 	int	(*power_on_slot )		(struct slot *slot);
 	int	(*slot_enable )			(struct slot *slot);
 	int	(*slot_disable )		(struct slot *slot);
-	int	(*enable_all_slots)		(struct slot *slot);
-	int	(*pwr_on_all_slots)		(struct slot *slot);
 	int	(*set_bus_speed_mode)	(struct slot *slot, enum pci_bus_speed speed);
 	int	(*get_power_status)		(struct slot *slot, u8 *status);
 	int	(*get_attention_status)	(struct slot *slot, u8 *status);
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 6f7d8a2..63628e0 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -27,26 +27,18 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
 #include "shpchp.h"
-#include "shpchprm.h"
 
 /* Global variables */
 int shpchp_debug;
 int shpchp_poll_mode;
 int shpchp_poll_time;
 struct controller *shpchp_ctrl_list;	/* = NULL */
-struct pci_func *shpchp_slot_list[256];
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -113,8 +105,6 @@
 	u32 slot_number, sun;
 	int result = -ENOMEM;
 
-	dbg("%s\n",__FUNCTION__);
-
 	number_of_slots = ctrl->num_slots;
 	slot_device = ctrl->slot_device_offset;
 	slot_number = ctrl->first_slot;
@@ -352,6 +342,17 @@
 	return 0;
 }
 
+static int is_shpc_capable(struct pci_dev *dev)
+{
+       if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
+                               PCI_DEVICE_ID_AMD_GOLAM_7450))
+               return 1;
+       if (pci_find_capability(dev, PCI_CAP_ID_SHPC))
+               return 1;
+
+       return 0;
+}
+
 static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int rc;
@@ -360,6 +361,9 @@
 	int first_device_num;	/* first PCI device number supported by this SHPC */
 	int num_ctlr_slots;	/* number of slots supported by this SHPC */
 
+	if (!is_shpc_capable(pdev))
+		return -ENODEV;
+
 	ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
 	if (!ctrl) {
 		err("%s : out of memory\n", __FUNCTION__);
@@ -367,19 +371,12 @@
 	}
 	memset(ctrl, 0, sizeof(struct controller));
 
-	dbg("DRV_thread pid = %d\n", current->pid);
-
-	rc = shpc_init(ctrl, pdev,
-			(php_intr_callback_t) shpchp_handle_attention_button,
-			(php_intr_callback_t) shpchp_handle_switch_change,
-			(php_intr_callback_t) shpchp_handle_presence_change,
-			(php_intr_callback_t) shpchp_handle_power_fault);
+	rc = shpc_init(ctrl, pdev);
 	if (rc) {
 		dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
 		goto err_out_free_ctrl;
 	}
 
-	dbg("%s: controller initialization success\n", __FUNCTION__);
 	ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
 
 	pci_set_drvdata(pdev, ctrl);
@@ -411,23 +408,8 @@
 	first_device_num = ctrl->slot_device_offset;
 	num_ctlr_slots = ctrl->num_slots;
 
-	/* Store PCI Config Space for all devices on this bus */
-	rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
-	if (rc) {
-		err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
-		goto err_out_free_ctrl_bus;
-	}
-
-	/* Get IO, memory, and IRQ resources for new devices */
-	rc = shpchprm_find_available_resources(ctrl);
-	ctrl->add_support = !rc;
+	ctrl->add_support = 1;
 	
-	if (rc) {
-		dbg("shpchprm_find_available_resources = %#x\n", rc);
-		err("unable to locate PCI configuration resources for hot plug add.\n");
-		goto err_out_free_ctrl_bus;
-	}
-
 	/* Setup the slot information structures */
 	rc = init_slots(ctrl);
 	if (rc) {
@@ -477,7 +459,6 @@
 
 static int shpc_start_thread(void)
 {
-	int loop;
 	int retval = 0;
 	
 	dbg("Initialize + Start the notification/polling mechanism \n");
@@ -488,48 +469,21 @@
 		return retval;
 	}
 
-	dbg("Initialize slot lists\n");
-	/* One slot list for each bus in the system */
-	for (loop = 0; loop < 256; loop++) {
-		shpchp_slot_list[loop] = NULL;
-	}
-
 	return retval;
 }
 
-static inline void __exit
-free_shpchp_res(struct pci_resource *res)
-{
-	struct pci_resource *tres;
-
-	while (res) {
-		tres = res;
-		res = res->next;
-		kfree(tres);
-	}
-}
-
 static void __exit unload_shpchpd(void)
 {
-	struct pci_func *next;
-	struct pci_func *TempSlot;
-	int loop;
 	struct controller *ctrl;
 	struct controller *tctrl;
 
 	ctrl = shpchp_ctrl_list;
 
 	while (ctrl) {
+		shpchp_remove_ctrl_files(ctrl);
 		cleanup_slots(ctrl);
 
-		free_shpchp_res(ctrl->io_head);
-		free_shpchp_res(ctrl->mem_head);
-		free_shpchp_res(ctrl->p_mem_head);
-		free_shpchp_res(ctrl->bus_head);
-
 		kfree (ctrl->pci_bus);
-
-		dbg("%s: calling release_ctlr\n", __FUNCTION__);
 		ctrl->hpc_ops->release_ctlr(ctrl);
 
 		tctrl = ctrl;
@@ -538,20 +492,6 @@
 		kfree(tctrl);
 	}
 
-	for (loop = 0; loop < 256; loop++) {
-		next = shpchp_slot_list[loop];
-		while (next != NULL) {
-			free_shpchp_res(next->io_head);
-			free_shpchp_res(next->mem_head);
-			free_shpchp_res(next->p_mem_head);
-			free_shpchp_res(next->bus_head);
-
-			TempSlot = next;
-			next = next->next;
-			kfree(TempSlot);
-		}
-	}
-
 	/* Stop the notification mechanism */
 	shpchp_event_stop_thread();
 
@@ -596,20 +536,14 @@
 	if (retval)
 		goto error_hpc_init;
 
-	retval = shpchprm_init(PCI);
-	if (!retval) {
-		retval = pci_register_driver(&shpc_driver);
-		dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
-		info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	}
+	retval = pci_register_driver(&shpc_driver);
+	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
+	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
 error_hpc_init:
 	if (retval) {
-		shpchprm_cleanup();
 		shpchp_event_stop_thread();
-	} else
-		shpchprm_print_pirt();
-
+	}
 	return retval;
 }
 
@@ -618,9 +552,6 @@
 	dbg("unload_shpchpd()\n");
 	unload_shpchpd();
 
-	shpchprm_cleanup();
-
-	dbg("pci_unregister_driver\n");
 	pci_unregister_driver(&shpc_driver);
 
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 91c9903..5861935 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -27,24 +27,14 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include "../pci.h"
 #include "shpchp.h"
-#include "shpchprm.h"
 
-static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
-	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
-static int configure_new_function( struct controller *ctrl, struct pci_func *func,
-	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
 static void interrupt_event_handler(struct controller *ctrl);
 
 static struct semaphore event_semaphore;	/* mutex for process loop (up if something to process) */
@@ -52,28 +42,22 @@
 static int event_finished;
 static unsigned long pushbutton_pending;	/* = 0 */
 
-u8 shpchp_disk_irq;
-u8 shpchp_nic_irq;
-
 u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
 {
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct slot *p_slot;
 	u8 rc = 0;
 	u8 getstatus;
-	struct pci_func *func;
 	struct event_info *taskInfo;
 
 	/* Attention Button Change */
 	dbg("shpchp:  Attention button interrupt received.\n");
 	
-	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
 	/* This is the structure that tells the worker thread what to do */
 	taskInfo = &(ctrl->event_queue[ctrl->next_event]);
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
-	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	
 	ctrl->next_event = (ctrl->next_event + 1) % 10;
@@ -118,14 +102,11 @@
 	struct slot *p_slot;
 	u8 rc = 0;
 	u8 getstatus;
-	struct pci_func *func;
 	struct event_info *taskInfo;
 
 	/* Switch Change */
 	dbg("shpchp:  Switch interrupt received.\n");
 
-	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
 	/* This is the structure that tells the worker thread
 	 * what to do
 	 */
@@ -135,19 +116,18 @@
 
 	rc++;
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
-		func->presence_save, func->pwr_save);
+		p_slot->presence_save, p_slot->pwr_save);
 
 	if (getstatus) {
 		/*
 		 * Switch opened
 		 */
 		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		func->switch_save = 0;
 		taskInfo->event_type = INT_SWITCH_OPEN;
-		if (func->pwr_save && func->presence_save) {
+		if (p_slot->pwr_save && p_slot->presence_save) {
 			taskInfo->event_type = INT_POWER_FAULT;
 			err("Surprise Removal of card\n");
 		}
@@ -156,7 +136,6 @@
 		 *  Switch closed
 		 */
 		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		func->switch_save = 0x10;
 		taskInfo->event_type = INT_SWITCH_CLOSE;
 	}
 
@@ -172,14 +151,11 @@
 	struct slot *p_slot;
 	u8 rc = 0;
 	/*u8 temp_byte;*/
-	struct pci_func *func;
 	struct event_info *taskInfo;
 
 	/* Presence Change */
 	dbg("shpchp:  Presence/Notify input change.\n");
 
-	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
 	/* This is the structure that tells the worker thread
 	 * what to do
 	 */
@@ -193,8 +169,8 @@
 	/* 
 	 * Save the presence state
 	 */
-	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
-	if (func->presence_save) {
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+	if (p_slot->presence_save) {
 		/*
 		 * Card Present
 		 */
@@ -219,14 +195,11 @@
 	struct controller *ctrl = (struct controller *) inst_id;
 	struct slot *p_slot;
 	u8 rc = 0;
-	struct pci_func *func;
 	struct event_info *taskInfo;
 
 	/* Power fault */
 	dbg("shpchp:  Power fault interrupt received.\n");
 
-	func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
 	/* This is the structure that tells the worker thread
 	 * what to do
 	 */
@@ -242,7 +215,7 @@
 		 * Power fault Cleared
 		 */
 		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
-		func->status = 0x00;
+		p_slot->status = 0x00;
 		taskInfo->event_type = INT_POWER_FAULT_CLEAR;
 	} else {
 		/*
@@ -251,7 +224,7 @@
 		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		taskInfo->event_type = INT_POWER_FAULT;
 		/* set power fault status for this board */
-		func->status = 0xFF;
+		p_slot->status = 0xFF;
 		info("power fault bit %x set\n", hp_slot);
 	}
 	if (rc)
@@ -260,799 +233,13 @@
 	return rc;
 }
 
-
-/*
- * sort_by_size
- *
- * Sorts nodes on the list by their length.
- * Smallest first.
- *
- */
-static int sort_by_size(struct pci_resource **head)
-{
-	struct pci_resource *current_res;
-	struct pci_resource *next_res;
-	int out_of_order = 1;
-
-	if (!(*head))
-		return(1);
-
-	if (!((*head)->next))
-		return(0);
-
-	while (out_of_order) {
-		out_of_order = 0;
-
-		/* Special case for swapping list head */
-		if (((*head)->next) &&
-		    ((*head)->length > (*head)->next->length)) {
-			out_of_order++;
-			current_res = *head;
-			*head = (*head)->next;
-			current_res->next = (*head)->next;
-			(*head)->next = current_res;
-		}
-
-		current_res = *head;
-
-		while (current_res->next && current_res->next->next) {
-			if (current_res->next->length > current_res->next->next->length) {
-				out_of_order++;
-				next_res = current_res->next;
-				current_res->next = current_res->next->next;
-				current_res = current_res->next;
-				next_res->next = current_res->next;
-				current_res->next = next_res;
-			} else
-				current_res = current_res->next;
-		}
-	}  /* End of out_of_order loop */
-
-	return(0);
-}
-
-
-/*
- * sort_by_max_size
- *
- * Sorts nodes on the list by their length.
- * Largest first.
- *
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
-	struct pci_resource *current_res;
-	struct pci_resource *next_res;
-	int out_of_order = 1;
-
-	if (!(*head))
-		return(1);
-
-	if (!((*head)->next))
-		return(0);
-
-	while (out_of_order) {
-		out_of_order = 0;
-
-		/* Special case for swapping list head */
-		if (((*head)->next) &&
-		    ((*head)->length < (*head)->next->length)) {
-			out_of_order++;
-			current_res = *head;
-			*head = (*head)->next;
-			current_res->next = (*head)->next;
-			(*head)->next = current_res;
-		}
-
-		current_res = *head;
-
-		while (current_res->next && current_res->next->next) {
-			if (current_res->next->length < current_res->next->next->length) {
-				out_of_order++;
-				next_res = current_res->next;
-				current_res->next = current_res->next->next;
-				current_res = current_res->next;
-				next_res->next = current_res->next;
-				current_res->next = next_res;
-			} else
-				current_res = current_res->next;
-		}
-	}  /* End of out_of_order loop */
-
-	return(0);
-}
-
-
-/*
- * do_pre_bridge_resource_split
- *
- *	Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment)
-{
-	struct pci_resource *prevnode = NULL;
-	struct pci_resource *node;
-	struct pci_resource *split_node;
-	u32 rc;
-	u32 temp_dword;
-	dbg("do_pre_bridge_resource_split\n");
-
-	if (!(*head) || !(*orig_head))
-		return(NULL);
-
-	rc = shpchp_resource_sort_and_combine(head);
-
-	if (rc)
-		return(NULL);
-
-	if ((*head)->base != (*orig_head)->base)
-		return(NULL);
-
-	if ((*head)->length == (*orig_head)->length)
-		return(NULL);
-
-
-	/* If we got here, there the bridge requires some of the resource, but
-	 *  we may be able to split some off of the front
-	 */	
-	node = *head;
-
-	if (node->length & (alignment -1)) {
-		/* This one isn't an aligned length, so we'll make a new entry
-		 * and split it up.
-		 */
-		split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-		if (!split_node)
-			return(NULL);
-
-		temp_dword = (node->length | (alignment-1)) + 1 - alignment;
-
-		split_node->base = node->base;
-		split_node->length = temp_dword;
-
-		node->length -= temp_dword;
-		node->base += split_node->length;
-
-		/* Put it in the list */
-		*head = split_node;
-		split_node->next = node;
-	}
-
-	if (node->length < alignment) {
-		return(NULL);
-	}
-
-	/* Now unlink it */
-	if (*head == node) {
-		*head = node->next;
-		node->next = NULL;
-	} else {
-		prevnode = *head;
-		while (prevnode->next != node)
-			prevnode = prevnode->next;
-
-		prevnode->next = node->next;
-		node->next = NULL;
-	}
-
-	return(node);
-}
-
-
-/*
- * do_bridge_resource_split
- *
- *	Returns zero or one node of resources that aren't in use
- *
- */
-static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment)
-{
-	struct pci_resource *prevnode = NULL;
-	struct pci_resource *node;
-	u32 rc;
-	u32 temp_dword;
-
-	if (!(*head))
-		return(NULL);
-
-	rc = shpchp_resource_sort_and_combine(head);
-
-	if (rc)
-		return(NULL);
-
-	node = *head;
-
-	while (node->next) {
-		prevnode = node;
-		node = node->next;
-		kfree(prevnode);
-	}
-
-	if (node->length < alignment) {
-		kfree(node);
-		return(NULL);
-	}
-
-	if (node->base & (alignment - 1)) {
-		/* Short circuit if adjusted size is too small */
-		temp_dword = (node->base | (alignment-1)) + 1;
-		if ((node->length - (temp_dword - node->base)) < alignment) {
-			kfree(node);
-			return(NULL);
-		}
-
-		node->length -= (temp_dword - node->base);
-		node->base = temp_dword;
-	}
-
-	if (node->length & (alignment - 1)) {
-		/* There's stuff in use after this node */
-		kfree(node);
-		return(NULL);
-	}
-
-	return(node);
-}
-
-
-/*
- * get_io_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window.  If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size)
-{
-	struct pci_resource *prevnode;
-	struct pci_resource *node;
-	struct pci_resource *split_node = NULL;
-	u32 temp_dword;
-
-	if (!(*head))
-		return(NULL);
-
-	if ( shpchp_resource_sort_and_combine(head) )
-		return(NULL);
-
-	if ( sort_by_size(head) )
-		return(NULL);
-
-	for (node = *head; node; node = node->next) {
-		if (node->length < size)
-			continue;
-
-		if (node->base & (size - 1)) {
-			/* This one isn't base aligned properly
-			   so we'll make a new entry and split it up */
-			temp_dword = (node->base | (size-1)) + 1;
-
-			/*/ Short circuit if adjusted size is too small */
-			if ((node->length - (temp_dword - node->base)) < size)
-				continue;
-
-			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-			if (!split_node)
-				return(NULL);
-
-			split_node->base = node->base;
-			split_node->length = temp_dword - node->base;
-			node->base = temp_dword;
-			node->length -= split_node->length;
-
-			/* Put it in the list */
-			split_node->next = node->next;
-			node->next = split_node;
-		} /* End of non-aligned base */
-
-		/* Don't need to check if too small since we already did */
-		if (node->length > size) {
-			/* This one is longer than we need
-			   so we'll make a new entry and split it up */
-			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-			if (!split_node)
-				return(NULL);
-
-			split_node->base = node->base + size;
-			split_node->length = node->length - size;
-			node->length = size;
-
-			/* Put it in the list */
-			split_node->next = node->next;
-			node->next = split_node;
-		}  /* End of too big on top end */
-
-		/* For IO make sure it's not in the ISA aliasing space */
-		if (node->base & 0x300L)
-			continue;
-
-		/* If we got here, then it is the right size 
-		   Now take it out of the list */
-		if (*head == node) {
-			*head = node->next;
-		} else {
-			prevnode = *head;
-			while (prevnode->next != node)
-				prevnode = prevnode->next;
-
-			prevnode->next = node->next;
-		}
-		node->next = NULL;
-		/* Stop looping */
-		break;
-	}
-
-	return(node);
-}
-
-
-/*
- * get_max_resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head.  It aligns the node on top and bottom
- * to "size" alignment before returning it.
- * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
- *  This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
- */
-static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size)
-{
-	struct pci_resource *max;
-	struct pci_resource *temp;
-	struct pci_resource *split_node;
-	u32 temp_dword;
-	u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
-	int i;
-
-	if (!(*head))
-		return(NULL);
-
-	if (shpchp_resource_sort_and_combine(head))
-		return(NULL);
-
-	if (sort_by_max_size(head))
-		return(NULL);
-
-	for (max = *head;max; max = max->next) {
-
-		/* If not big enough we could probably just bail, 
-		   instead we'll continue to the next. */
-		if (max->length < size)
-			continue;
-
-		if (max->base & (size - 1)) {
-			/* This one isn't base aligned properly
-			   so we'll make a new entry and split it up */
-			temp_dword = (max->base | (size-1)) + 1;
-
-			/* Short circuit if adjusted size is too small */
-			if ((max->length - (temp_dword - max->base)) < size)
-				continue;
-
-			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-			if (!split_node)
-				return(NULL);
-
-			split_node->base = max->base;
-			split_node->length = temp_dword - max->base;
-			max->base = temp_dword;
-			max->length -= split_node->length;
-
-			/* Put it next in the list */
-			split_node->next = max->next;
-			max->next = split_node;
-		}
-
-		if ((max->base + max->length) & (size - 1)) {
-			/* This one isn't end aligned properly at the top
-			   so we'll make a new entry and split it up */
-			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-			if (!split_node)
-				return(NULL);
-			temp_dword = ((max->base + max->length) & ~(size - 1));
-			split_node->base = temp_dword;
-			split_node->length = max->length + max->base
-					     - split_node->base;
-			max->length -= split_node->length;
-
-			/* Put it in the list */
-			split_node->next = max->next;
-			max->next = split_node;
-		}
-
-		/* Make sure it didn't shrink too much when we aligned it */
-		if (max->length < size)
-			continue;
-
-		for ( i = 0; max_size[i] > size; i++) {
-			if (max->length > max_size[i]) {
-				split_node = kmalloc(sizeof(*split_node),
-							GFP_KERNEL);
-				if (!split_node)
-					break;	/* return (NULL); */
-				split_node->base = max->base + max_size[i];
-				split_node->length = max->length - max_size[i];
-				max->length = max_size[i];
-				/* Put it next in the list */
-				split_node->next = max->next;
-				max->next = split_node;
-				break;
-			}
-		}
-
-		/* Now take it out of the list */
-		temp = (struct pci_resource*) *head;
-		if (temp == max) {
-			*head = max->next;
-		} else {
-			while (temp && temp->next != max) {
-				temp = temp->next;
-			}
-
-			temp->next = max->next;
-		}
-
-		max->next = NULL;
-		return(max);
-	}
-
-	/* If we get here, we couldn't find one */
-	return(NULL);
-}
-
-
-/*
- * get_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length.  If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_resource (struct pci_resource **head, u32 size)
-{
-	struct pci_resource *prevnode;
-	struct pci_resource *node;
-	struct pci_resource *split_node;
-	u32 temp_dword;
-
-	if (!(*head))
-		return(NULL);
-
-	if ( shpchp_resource_sort_and_combine(head) )
-		return(NULL);
-
-	if ( sort_by_size(head) )
-		return(NULL);
-
-	for (node = *head; node; node = node->next) {
-		dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
-		    __FUNCTION__, size, node, node->base, node->length);
-		if (node->length < size)
-			continue;
-
-		if (node->base & (size - 1)) {
-			dbg("%s: not aligned\n", __FUNCTION__);
-			/* this one isn't base aligned properly
-			   so we'll make a new entry and split it up */
-			temp_dword = (node->base | (size-1)) + 1;
-
-			/* Short circuit if adjusted size is too small */
-			if ((node->length - (temp_dword - node->base)) < size)
-				continue;
-
-			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-			if (!split_node)
-				return(NULL);
-
-			split_node->base = node->base;
-			split_node->length = temp_dword - node->base;
-			node->base = temp_dword;
-			node->length -= split_node->length;
-
-			/* Put it in the list */
-			split_node->next = node->next;
-			node->next = split_node;
-		} /* End of non-aligned base */
-
-		/* Don't need to check if too small since we already did */
-		if (node->length > size) {
-			dbg("%s: too big\n", __FUNCTION__);
-			/* this one is longer than we need
-			   so we'll make a new entry and split it up */
-			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
-
-			if (!split_node)
-				return(NULL);
-
-			split_node->base = node->base + size;
-			split_node->length = node->length - size;
-			node->length = size;
-
-			/* Put it in the list */
-			split_node->next = node->next;
-			node->next = split_node;
-		}  /* End of too big on top end */
-
-		dbg("%s: got one!!!\n", __FUNCTION__);
-		/* If we got here, then it is the right size
-		   Now take it out of the list */
-		if (*head == node) {
-			*head = node->next;
-		} else {
-			prevnode = *head;
-			while (prevnode->next != node)
-				prevnode = prevnode->next;
-
-			prevnode->next = node->next;
-		}
-		node->next = NULL;
-		/* Stop looping */
-		break;
-	}
-	return(node);
-}
-
-
-/*
- * shpchp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses.  Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int shpchp_resource_sort_and_combine(struct pci_resource **head)
-{
-	struct pci_resource *node1;
-	struct pci_resource *node2;
-	int out_of_order = 1;
-
-	dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
-
-	if (!(*head))
-		return(1);
-
-	dbg("*head->next = %p\n",(*head)->next);
-
-	if (!(*head)->next)
-		return(0);	/* only one item on the list, already sorted! */
-
-	dbg("*head->base = 0x%x\n",(*head)->base);
-	dbg("*head->next->base = 0x%x\n",(*head)->next->base);
-	while (out_of_order) {
-		out_of_order = 0;
-
-		/* Special case for swapping list head */
-		if (((*head)->next) &&
-		    ((*head)->base > (*head)->next->base)) {
-			node1 = *head;
-			(*head) = (*head)->next;
-			node1->next = (*head)->next;
-			(*head)->next = node1;
-			out_of_order++;
-		}
-
-		node1 = (*head);
-
-		while (node1->next && node1->next->next) {
-			if (node1->next->base > node1->next->next->base) {
-				out_of_order++;
-				node2 = node1->next;
-				node1->next = node1->next->next;
-				node1 = node1->next;
-				node2->next = node1->next;
-				node1->next = node2;
-			} else
-				node1 = node1->next;
-		}
-	}  /* End of out_of_order loop */
-
-	node1 = *head;
-
-	while (node1 && node1->next) {
-		if ((node1->base + node1->length) == node1->next->base) {
-			/* Combine */
-			dbg("8..\n");
-			node1->length += node1->next->length;
-			node2 = node1->next;
-			node1->next = node1->next->next;
-			kfree(node2);
-		} else
-			node1 = node1->next;
-	}
-
-	return(0);
-}
-
-
-/**
- * shpchp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
- *
- * Returns pointer to the new node or NULL if unsuccessful
- */
-struct pci_func *shpchp_slot_create(u8 busnumber)
-{
-	struct pci_func *new_slot;
-	struct pci_func *next;
-
-	new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
-
-	if (new_slot == NULL) {
-		return(new_slot);
-	}
-
-	memset(new_slot, 0, sizeof(struct pci_func));
-
-	new_slot->next = NULL;
-	new_slot->configured = 1;
-
-	if (shpchp_slot_list[busnumber] == NULL) {
-		shpchp_slot_list[busnumber] = new_slot;
-	} else {
-		next = shpchp_slot_list[busnumber];
-		while (next->next != NULL)
-			next = next->next;
-		next->next = new_slot;
-	}
-	return(new_slot);
-}
-
-
-/*
- * slot_remove - Removes a node from the linked list of slots.
- * @old_slot: slot to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int slot_remove(struct pci_func * old_slot)
-{
-	struct pci_func *next;
-
-	if (old_slot == NULL)
-		return(1);
-
-	next = shpchp_slot_list[old_slot->bus];
-
-	if (next == NULL) {
-		return(1);
-	}
-
-	if (next == old_slot) {
-		shpchp_slot_list[old_slot->bus] = old_slot->next;
-		shpchp_destroy_board_resources(old_slot);
-		kfree(old_slot);
-		return(0);
-	}
-
-	while ((next->next != old_slot) && (next->next != NULL)) {
-		next = next->next;
-	}
-
-	if (next->next == old_slot) {
-		next->next = old_slot->next;
-		shpchp_destroy_board_resources(old_slot);
-		kfree(old_slot);
-		return(0);
-	} else
-		return(2);
-}
-
-
-/**
- * bridge_slot_remove - Removes a node from the linked list of slots.
- * @bridge: bridge to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int bridge_slot_remove(struct pci_func *bridge)
-{
-	u8 subordinateBus, secondaryBus;
-	u8 tempBus;
-	struct pci_func *next;
-
-	if (bridge == NULL)
-		return(1);
-
-	secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
-	subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
-
-	for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
-		next = shpchp_slot_list[tempBus];
-
-		while (!slot_remove(next)) {
-			next = shpchp_slot_list[tempBus];
-		}
-	}
-
-	next = shpchp_slot_list[bridge->bus];
-
-	if (next == NULL) {
-		return(1);
-	}
-
-	if (next == bridge) {
-		shpchp_slot_list[bridge->bus] = bridge->next;
-		kfree(bridge);
-		return(0);
-	}
-
-	while ((next->next != bridge) && (next->next != NULL)) {
-		next = next->next;
-	}
-
-	if (next->next == bridge) {
-		next->next = bridge->next;
-		kfree(bridge);
-		return(0);
-	} else
-		return(2);
-}
-
-
-/**
- * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed
- * @bus: bus to find
- * @device: device to find
- * @index: is 0 for first function found, 1 for the second...
- *
- * Returns pointer to the node if successful, %NULL otherwise.
- */
-struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
-{
-	int found = -1;
-	struct pci_func *func;
-
-	func = shpchp_slot_list[bus];
-
-	if ((func == NULL) || ((func->device == device) && (index == 0)))
-		return(func);
-
-	if (func->device == device)
-		found++;
-
-	while (func->next != NULL) {
-		func = func->next;
-
-		if (func->device == device)
-			found++;
-
-		if (found == index)
-			return(func);
-	}
-
-	return(NULL);
-}
-
-static int is_bridge(struct pci_func * func)
-{
-	/* Check the header type */
-	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
-		return 1;
-	else
-		return 0;
-}
-
-
 /* The following routines constitute the bulk of the 
    hotplug controller logic
  */
-static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed)
+static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
+		enum pci_bus_speed speed)
 { 
-	u32 rc = 0;
+	int rc = 0;
 
 	dbg("%s: change to speed %d\n", __FUNCTION__, speed);
 	down(&ctrl->crit_sect);
@@ -1074,10 +261,11 @@
 	return rc;
 }
 
-static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag, 
-enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp)
+static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
+		u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
+		enum pci_bus_speed msp)
 { 
-	u32 rc = 0;
+	int rc = 0;
 	
 	if (flag != 0) { /* Other slots on the same bus are occupied */
 		if ( asp < bsp ) {
@@ -1116,23 +304,20 @@
  * Configures board
  *
  */
-static u32 board_added(struct pci_func * func, struct controller * ctrl)
+static int board_added(struct slot *p_slot)
 {
 	u8 hp_slot;
 	u8 slots_not_empty = 0;
-	int index;
-	u32 temp_register = 0xFFFFFFFF;
-	u32 retval, rc = 0;
-	struct pci_func *new_func = NULL;
-	struct slot *p_slot;
-	struct resource_lists res_lists;
+	int rc = 0;
 	enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed;
 	u8 pi, mode;
+	struct controller *ctrl = p_slot->ctrl;
 
-	p_slot = shpchp_find_slot(ctrl, func->device);
-	hp_slot = func->device - ctrl->slot_device_offset;
+	hp_slot = p_slot->device - ctrl->slot_device_offset;
 
-	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+	dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+			__FUNCTION__, p_slot->device,
+			ctrl->slot_device_offset, hp_slot);
 
 	/* Wait for exclusive access to hardware */
 	down(&ctrl->crit_sect);
@@ -1320,143 +505,68 @@
 	up(&ctrl->crit_sect);
 
 	/* Wait for ~1 second */
-	dbg("%s: before long_delay\n", __FUNCTION__);
 	wait_for_ctrl_irq (ctrl);
-	dbg("%s: after long_delay\n", __FUNCTION__);
 
-	dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+	dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
 	/* Check for a power fault */
-	if (func->status == 0xFF) {
+	if (p_slot->status == 0xFF) {
 		/* power fault occurred, but it was benign */
-		temp_register = 0xFFFFFFFF;
-		dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
+		dbg("%s: power fault\n", __FUNCTION__);
 		rc = POWER_FAILURE;
-		func->status = 0;
-	} else {
-		/* Get vendor/device ID u32 */
-		rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), 
-			PCI_VENDOR_ID, &temp_register);
-		dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
-		dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
-
-		if (rc != 0) {
-			/* Something's wrong here */
-			temp_register = 0xFFFFFFFF;
-			dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
-		}
-		/* Preset return code.  It will be changed later if things go okay. */
-		rc = NO_ADAPTER_PRESENT;
+		p_slot->status = 0;
+		goto err_exit;
 	}
 
-	/* All F's is an empty slot or an invalid board */
-	if (temp_register != 0xFFFFFFFF) {	  /* Check for a board in the slot */
-		res_lists.io_head = ctrl->io_head;
-		res_lists.mem_head = ctrl->mem_head;
-		res_lists.p_mem_head = ctrl->p_mem_head;
-		res_lists.bus_head = ctrl->bus_head;
-		res_lists.irqs = NULL;
-
-		rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
-		dbg("%s: back from configure_new_device\n", __FUNCTION__);
-
-		ctrl->io_head = res_lists.io_head;
-		ctrl->mem_head = res_lists.mem_head;
-		ctrl->p_mem_head = res_lists.p_mem_head;
-		ctrl->bus_head = res_lists.bus_head;
-
-		shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-		shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-		shpchp_resource_sort_and_combine(&(ctrl->io_head));
-		shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-		if (rc) {
-			/* Wait for exclusive access to hardware */
-			down(&ctrl->crit_sect);
-
-			/* turn off slot, turn on Amber LED, turn off Green LED */
-			retval = p_slot->hpc_ops->slot_disable(p_slot);
-			if (retval) {
-				err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
-				/* Done with exclusive hardware access */
-				up(&ctrl->crit_sect);
-				return retval;
-			}
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq (ctrl);
-
-			retval = p_slot->hpc_ops->check_cmd_status(ctrl);
-			if (retval) {
-				err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, retval);
-				/* Done with exclusive hardware access */
-				up(&ctrl->crit_sect);
-				return retval;  
-			}
-
-			/* Done with exclusive hardware access */
-			up(&ctrl->crit_sect);
-
-			return(rc);
-		}
-		shpchp_save_slot_config(ctrl, func);
-
-		func->status = 0;
-		func->switch_save = 0x10;
-		func->is_a_board = 0x01;
-		func->pwr_save = 1;
-
-		/* Next, we will instantiate the linux pci_dev structures 
-		 * (with appropriate driver notification, if already present) 
-		 */
-		index = 0;
-		do {
-			new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++);
-			if (new_func && !new_func->pci_dev) {
-				dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__);
-				shpchp_configure_device(ctrl, new_func);
-			}
-		} while (new_func);
-
-		/* Wait for exclusive access to hardware */
-		down(&ctrl->crit_sect);
-
-		p_slot->hpc_ops->green_led_on(p_slot);
-
-		/* Wait for the command to complete */
-		wait_for_ctrl_irq (ctrl);
-
-
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
-
-	} else {
-		/* Wait for exclusive access to hardware */
-		down(&ctrl->crit_sect);
-
-		/* turn off slot, turn on Amber LED, turn off Green LED */
-		rc = p_slot->hpc_ops->slot_disable(p_slot);
-		if (rc) {
-			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
-			/* Done with exclusive hardware access */
-			up(&ctrl->crit_sect);
-			return rc;
-		}
-		/* Wait for the command to complete */
-		wait_for_ctrl_irq (ctrl);
-
-		rc = p_slot->hpc_ops->check_cmd_status(ctrl);
-		if (rc) {
-			err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
-			/* Done with exclusive hardware access */
-			up(&ctrl->crit_sect);
-			return rc;  
-		}
-
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
-
-		return(rc);
+	if (shpchp_configure_device(p_slot)) {
+		err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,
+				p_slot->device);
+		goto err_exit;
 	}
+
+	p_slot->status = 0;
+	p_slot->is_a_board = 0x01;
+	p_slot->pwr_save = 1;
+
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	p_slot->hpc_ops->green_led_on(p_slot);
+
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
 	return 0;
+
+err_exit:
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* turn off slot, turn on Amber LED, turn off Green LED */
+	rc = p_slot->hpc_ops->slot_disable(p_slot);
+	if (rc) {
+		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;
+	}
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq (ctrl);
+
+	rc = p_slot->hpc_ops->check_cmd_status(ctrl);
+	if (rc) {
+		err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc);
+		/* Done with exclusive hardware access */
+		up(&ctrl->crit_sect);
+		return rc;
+	}
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+
+	return(rc);
 }
 
 
@@ -1464,55 +574,23 @@
  * remove_board - Turns off slot and LED's
  *
  */
-static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+static int remove_board(struct slot *p_slot)
 {
-	int index;
-	u8 skip = 0;
-	u8 device;
+	struct controller *ctrl = p_slot->ctrl;
 	u8 hp_slot;
-	u32 rc;
-	struct resource_lists res_lists;
-	struct pci_func *temp_func;
-	struct slot *p_slot;
+	int rc;
 
-	if (func == NULL)
+	if (shpchp_unconfigure_device(p_slot))
 		return(1);
 
-	if (shpchp_unconfigure_device(func))
-		return(1);
-
-	device = func->device;
-
-	hp_slot = func->device - ctrl->slot_device_offset;
+	hp_slot = p_slot->device - ctrl->slot_device_offset;
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
 
-	if ((ctrl->add_support) &&
-		!(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
-		/* Here we check to see if we've saved any of the board's
-		 * resources already.  If so, we'll skip the attempt to
-		 * determine what's being used.
-		 */
-		index = 0;
-
-		temp_func = func;
-
-		while ((temp_func = shpchp_slot_find(temp_func->bus, temp_func->device, index++))) {
-			if (temp_func->bus_head || temp_func->mem_head
-			    || temp_func->p_mem_head || temp_func->io_head) {
-				skip = 1;
-				break;
-			}
-		}
-
-		if (!skip)
-			rc = shpchp_save_used_resources(ctrl, func, DISABLE_CARD);
-	}
 	/* Change status to shutdown */
-	if (func->is_a_board)
-		func->status = 0x01;
-	func->configured = 0;
+	if (p_slot->is_a_board)
+		p_slot->status = 0x01;
 
 	/* Wait for exclusive access to hardware */
 	down(&ctrl->crit_sect);
@@ -1549,55 +627,8 @@
 	/* Done with exclusive hardware access */
 	up(&ctrl->crit_sect);
 
-	if (ctrl->add_support) {
-		while (func) {
-			res_lists.io_head = ctrl->io_head;
-			res_lists.mem_head = ctrl->mem_head;
-			res_lists.p_mem_head = ctrl->p_mem_head;
-			res_lists.bus_head = ctrl->bus_head;
-
-			dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus, 
-				func->device, func->function);
-
-			shpchp_return_board_resources(func, &res_lists);
-
-			ctrl->io_head = res_lists.io_head;
-			ctrl->mem_head = res_lists.mem_head;
-			ctrl->p_mem_head = res_lists.p_mem_head;
-			ctrl->bus_head = res_lists.bus_head;
-
-			shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-			shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-			shpchp_resource_sort_and_combine(&(ctrl->io_head));
-			shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-			if (is_bridge(func)) {
-				dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
-					func->device, func->function);
-				bridge_slot_remove(func);
-			} else
-				dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 
-					func->device, func->function);
-				slot_remove(func);
-
-			func = shpchp_slot_find(ctrl->slot_bus, device, 0);
-		}
-
-		/* Setup slot structure with entry for empty slot */
-		func = shpchp_slot_create(ctrl->slot_bus);
-
-		if (func == NULL) {
-			return(1);
-		}
-
-		func->bus = ctrl->slot_bus;
-		func->device = device;
-		func->function = 0;
-		func->configured = 0;
-		func->switch_save = 0x10;
-		func->pwr_save = 0;
-		func->is_a_board = 0;
-	}
+	p_slot->pwr_save = 0;
+	p_slot->is_a_board = 0;
 
 	return 0;
 }
@@ -1633,13 +664,11 @@
 	p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (getstatus) {
 		p_slot->state = POWEROFF_STATE;
-		dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
 		shpchp_disable_slot(p_slot);
 		p_slot->state = STATIC_STATE;
 	} else {
 		p_slot->state = POWERON_STATE;
-		dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
 		if (shpchp_enable_slot(p_slot)) {
 			/* Wait for exclusive access to hardware */
@@ -1701,7 +730,6 @@
 		err ("Can't start up our event thread\n");
 		return -1;
 	}
-	dbg("Our event thread pid = %d\n", pid);
 	return 0;
 }
 
@@ -1709,9 +737,7 @@
 void shpchp_event_stop_thread (void)
 {
 	event_finished = 1;
-	dbg("event_thread finish command given\n");
 	up(&event_semaphore);
-	dbg("wait for event_thread to exit\n");
 	down(&event_exit);
 }
 
@@ -1739,12 +765,10 @@
 {
 	int loop = 0;
 	int change = 1;
-	struct pci_func *func;
 	u8 hp_slot;
 	u8 getstatus;
 	struct slot *p_slot;
 
-	dbg("%s:\n", __FUNCTION__);
 	while (change) {
 		change = 0;
 
@@ -1754,12 +778,8 @@
 					ctrl->event_queue[loop].event_type);
 				hp_slot = ctrl->event_queue[loop].hp_slot;
 
-				func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
 				p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
-				dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot);
-
 				if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
 					dbg("%s: button cancel\n", __FUNCTION__);
 					del_timer(&p_slot->task_event);
@@ -1880,13 +900,6 @@
 {
 	u8 getstatus = 0;
 	int rc;
-	struct pci_func *func;
-
-	func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
-	if (!func) {
-		dbg("%s: Error! slot NULL\n", __FUNCTION__);
-		return -ENODEV;
-	}
 
 	/* Check to see if (latch closed, card present, power off) */
 	down(&p_slot->ctrl->crit_sect);
@@ -1910,72 +923,34 @@
 	}
 	up(&p_slot->ctrl->crit_sect);
 
-	slot_remove(func);
-
-	func = shpchp_slot_create(p_slot->bus);
-	if (func == NULL)
-		return -ENOMEM;
-
-	func->bus = p_slot->bus;
-	func->device = p_slot->device;
-	func->function = 0;
-	func->configured = 0;
-	func->is_a_board = 1;
+	p_slot->is_a_board = 1;
 
 	/* We have to save the presence info for these slots */
-	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
-	p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
-	dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
+	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+	p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
+	dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-	func->switch_save = !getstatus? 0x10:0;
 
-	rc = board_added(func, p_slot->ctrl);
+	rc = board_added(p_slot);
 	if (rc) {
-		if (is_bridge(func))
-			bridge_slot_remove(func);
-		else
-			slot_remove(func);
-
-		/* Setup slot structure with entry for empty slot */
-		func = shpchp_slot_create(p_slot->bus);
-		if (func == NULL)
-			return -ENOMEM;	/* Out of memory */
-
-		func->bus = p_slot->bus;
-		func->device = p_slot->device;
-		func->function = 0;
-		func->configured = 0;
-		func->is_a_board = 1;
-
-		/* We have to save the presence info for these slots */
-		p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+		p_slot->hpc_ops->get_adapter_status(p_slot,
+				&(p_slot->presence_save));
 		p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-		func->switch_save = !getstatus? 0x10:0;
 	}
 
-	if (p_slot)
-		update_slot_info(p_slot);
-
+	update_slot_info(p_slot);
 	return rc;
 }
 
 
 int shpchp_disable_slot (struct slot *p_slot)
 {
-	u8 class_code, header_type, BCR;
-	u8 index = 0;
 	u8 getstatus = 0;
-	u32 rc = 0;
 	int ret = 0;
-	unsigned int devfn;
-	struct pci_bus *pci_bus;
-	struct pci_func *func;
 
 	if (!p_slot->ctrl)
 		return -ENODEV;
 
-	pci_bus = p_slot->ctrl->pci_dev->subordinate;
-
 	/* Check to see if (latch closed, card present, power on) */
 	down(&p_slot->ctrl->crit_sect);
 
@@ -1999,849 +974,8 @@
 	}
 	up(&p_slot->ctrl->crit_sect);
 
-	func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
-
-	/* Make sure there are no video controllers here
-	 * for all func of p_slot
-	 */
-	while (func && !rc) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		/* Check the Class Code */
-		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-		if (rc)
-			return -ENODEV;
-
-		if (class_code == PCI_BASE_CLASS_DISPLAY) {
-			/* Display/Video adapter (not supported) */
-			rc = REMOVE_NOT_SUPPORTED;
-		} else {
-			/* See if it's a bridge */
-			rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-			if (rc)
-				return -ENODEV;
-
-			/* If it's a bridge, check the VGA Enable bit */
-			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
-				rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
-				if (rc)
-					return -ENODEV;
-
-				/* If the VGA Enable bit is set, remove isn't supported */
-				if (BCR & PCI_BRIDGE_CTL_VGA) {
-					rc = REMOVE_NOT_SUPPORTED;
-				}
-			}
-		}
-
-		func = shpchp_slot_find(p_slot->bus, p_slot->device, index++);
-	}
-
-	func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
-	if ((func != NULL) && !rc) {
-		rc = remove_board(func, p_slot->ctrl);
-	} else if (!rc)
-		rc = -ENODEV;
-
-	if (p_slot)
-		update_slot_info(p_slot);
-
-	return rc;
-}
-
-
-/**
- * configure_new_device - Configures the PCI header information of one board.
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Returns 0 if success
- *
- */
-static u32 configure_new_device (struct controller * ctrl, struct pci_func * func,
-	u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
-{
-	u8 temp_byte, function, max_functions, stop_it;
-	int rc;
-	u32 ID;
-	struct pci_func *new_slot;
-	struct pci_bus lpci_bus, *pci_bus;
-	int index;
-
-	new_slot = func;
-
-	dbg("%s\n", __FUNCTION__);
-	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-
-	/* Check for Multi-function device */
-	rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
-	if (rc) {
-		dbg("%s: rc = %d\n", __FUNCTION__, rc);
-		return rc;
-	}
-
-	if (temp_byte & 0x80)	/* Multi-function device */
-		max_functions = 8;
-	else
-		max_functions = 1;
-
-	function = 0;
-
-	do {
-		rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev);
-
-		if (rc) {
-			dbg("configure_new_function failed %d\n",rc);
-			index = 0;
-
-			while (new_slot) {
-				new_slot = shpchp_slot_find(new_slot->bus, new_slot->device, index++);
-
-				if (new_slot)
-					shpchp_return_board_resources(new_slot, resources);
-			}
-
-			return(rc);
-		}
-
-		function++;
-
-		stop_it = 0;
-
-		/*  The following loop skips to the next present function
-		 *  and creates a board structure
-		 */
-
-		while ((function < max_functions) && (!stop_it)) {
-			pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
-
-			if (ID == 0xFFFFFFFF) {	  /* There's nothing there. */
-				function++;
-			} else {  /* There's something there */
-				/* Setup slot structure. */
-				new_slot = shpchp_slot_create(func->bus);
-
-				if (new_slot == NULL) {
-					/* Out of memory */
-					return(1);
-				}
-
-				new_slot->bus = func->bus;
-				new_slot->device = func->device;
-				new_slot->function = function;
-				new_slot->is_a_board = 1;
-				new_slot->status = 0;
-
-				stop_it++;
-			}
-		}
-
-	} while (function < max_functions);
-	dbg("returning from configure_new_device\n");
-
-	return 0;
-}
-
-
-/*
- * Configuration logic that involves the hotplug data structures and 
- * their bookkeeping
- */
-
-
-/**
- * configure_new_function - Configures the PCI header information of one device
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
- */
-static int configure_new_function (struct controller * ctrl, struct pci_func * func,
-	u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev)
-{
-	int cloop;
-	u8 temp_byte;
-	u8 device;
-	u8 class_code;
-	u16 temp_word;
-	u32 rc;
-	u32 temp_register;
-	u32 base;
-	u32 ID;
-	unsigned int devfn;
-	struct pci_resource *mem_node;
-	struct pci_resource *p_mem_node;
-	struct pci_resource *io_node;
-	struct pci_resource *bus_node;
-	struct pci_resource *hold_mem_node;
-	struct pci_resource *hold_p_mem_node;
-	struct pci_resource *hold_IO_node;
-	struct pci_resource *hold_bus_node;
-	struct irq_mapping irqs;
-	struct pci_func *new_slot;
-	struct pci_bus lpci_bus, *pci_bus;
-	struct resource_lists temp_resources;
-#if defined(CONFIG_X86_64)
-	u8 IRQ=0;
-#endif
-
-	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	/* Check for Bridge */
-	rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
-	if (rc)
-		return rc;
-
-	if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
-		/* set Primary bus */
-		dbg("set Primary bus = 0x%x\n", func->bus);
-		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
-		if (rc)
-			return rc;
-
-		/* find range of busses to use */
-		bus_node = get_max_resource(&resources->bus_head, 1L);
-
-		/* If we don't have any busses to allocate, we can't continue */
-		if (!bus_node) {
-			err("Got NO bus resource to use\n");
-			return -ENOMEM;
-		}
-		dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
-
-		/* set Secondary bus */
-		temp_byte = (u8)bus_node->base;
-		dbg("set Secondary bus = 0x%x\n", temp_byte);
-		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
-		if (rc)
-			return rc;
-
-		/* set subordinate bus */
-		temp_byte = (u8)(bus_node->base + bus_node->length - 1);
-		dbg("set subordinate bus = 0x%x\n", temp_byte);
-		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-		if (rc)
-			return rc;
-
-		/* Set HP parameters (Cache Line Size, Latency Timer) */
-		rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-		if (rc)
-			return rc;
-
-		/* Setup the IO, memory, and prefetchable windows */
-
-		io_node = get_max_resource(&(resources->io_head), 0x1000L);
-		if (io_node) {
-			dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next);
-		}
-
-		mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
-		if (mem_node) {
-			dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next);
-		}
-
-		if (resources->p_mem_head)
-			p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
-		else {
-			/*
-			 * In some platform implementation, MEM and PMEM are not
-			 *  distinguished, and hence ACPI _CRS has only MEM entries
-			 *  for both MEM and PMEM.
-			 */
-			dbg("using MEM for PMEM\n");
-			p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
-		}
-		if (p_mem_node) {
-			dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next);
-		}
-
-		/* set up the IRQ info */
-		if (!resources->irqs) {
-			irqs.barber_pole = 0;
-			irqs.interrupt[0] = 0;
-			irqs.interrupt[1] = 0;
-			irqs.interrupt[2] = 0;
-			irqs.interrupt[3] = 0;
-			irqs.valid_INT = 0;
-		} else {
-			irqs.barber_pole = resources->irqs->barber_pole;
-			irqs.interrupt[0] = resources->irqs->interrupt[0];
-			irqs.interrupt[1] = resources->irqs->interrupt[1];
-			irqs.interrupt[2] = resources->irqs->interrupt[2];
-			irqs.interrupt[3] = resources->irqs->interrupt[3];
-			irqs.valid_INT = resources->irqs->valid_INT;
-		}
-
-		/* set up resource lists that are now aligned on top and bottom
-		 * for anything behind the bridge.
-		 */
-		temp_resources.bus_head = bus_node;
-		temp_resources.io_head = io_node;
-		temp_resources.mem_head = mem_node;
-		temp_resources.p_mem_head = p_mem_node;
-		temp_resources.irqs = &irqs;
-
-		/* Make copies of the nodes we are going to pass down so that
-		 * if there is a problem,we can just use these to free resources
-		 */
-		hold_bus_node = kmalloc(sizeof(*hold_bus_node), GFP_KERNEL);
-		hold_IO_node = kmalloc(sizeof(*hold_IO_node), GFP_KERNEL);
-		hold_mem_node = kmalloc(sizeof(*hold_mem_node), GFP_KERNEL);
-		hold_p_mem_node = kmalloc(sizeof(*hold_p_mem_node), GFP_KERNEL);
-
-		if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
-			kfree(hold_bus_node);
-			kfree(hold_IO_node);
-			kfree(hold_mem_node);
-			kfree(hold_p_mem_node);
-
-			return 1;
-		}
-
-		memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
-
-		bus_node->base += 1;
-		bus_node->length -= 1;
-		bus_node->next = NULL;
-
-		/* If we have IO resources copy them and fill in the bridge's
-		 * IO range registers
-		 */
-		if (io_node) {
-			memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
-			io_node->next = NULL;
-
-			/* set IO base and Limit registers */
-			RES_CHECK(io_node->base, 8);
-			temp_byte = (u8)(io_node->base >> 8);
-			rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
-			RES_CHECK(io_node->base + io_node->length - 1, 8);
-			temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
-			rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-		} else {
-			kfree(hold_IO_node);
-			hold_IO_node = NULL;
-		}
-
-		/* If we have memory resources copy them and fill in the bridge's
-		 * memory range registers.  Otherwise, fill in the range
-		 * registers with values that disable them.
-		 */
-		if (mem_node) {
-			memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
-			mem_node->next = NULL;
-
-			/* set Mem base and Limit registers */
-			RES_CHECK(mem_node->base, 16);
-			temp_word = (u32)(mem_node->base >> 16);
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-			RES_CHECK(mem_node->base + mem_node->length - 1, 16);
-			temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16);
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-		} else {
-			temp_word = 0xFFFF;
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-			temp_word = 0x0000;
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
-			kfree(hold_mem_node);
-			hold_mem_node = NULL;
-		}
-
-		/* If we have prefetchable memory resources copy them and 
-		 * fill in the bridge's memory range registers.  Otherwise,
-		 * fill in the range registers with values that disable them.
-		 */
-		if (p_mem_node) {
-			memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
-			p_mem_node->next = NULL;
-
-			/* set Pre Mem base and Limit registers */
-			RES_CHECK(p_mem_node->base, 16);
-			temp_word = (u32)(p_mem_node->base >> 16);
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-			RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16);
-			temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16);
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-		} else {
-			temp_word = 0xFFFF;
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-			temp_word = 0x0000;
-			rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
-			kfree(hold_p_mem_node);
-			hold_p_mem_node = NULL;
-		}
-
-		/* Adjust this to compensate for extra adjustment in first loop */
-		irqs.barber_pole--;
-
-		rc = 0;
-
-		/* Here we actually find the devices and configure them */
-		for (device = 0; (device <= 0x1F) && !rc; device++) {
-			irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
-
-			ID = 0xFFFFFFFF;
-			pci_bus->number = hold_bus_node->base;
-			pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
-					PCI_VENDOR_ID, &ID);
-			pci_bus->number = func->bus;
-
-			if (ID != 0xFFFFFFFF) {	  /*  device Present */
-				/* Setup slot structure. */
-				new_slot = shpchp_slot_create(hold_bus_node->base);
-
-				if (new_slot == NULL) {
-					/* Out of memory */
-					rc = -ENOMEM;
-					continue;
-				}
-
-				new_slot->bus = hold_bus_node->base;
-				new_slot->device = device;
-				new_slot->function = 0;
-				new_slot->is_a_board = 1;
-				new_slot->status = 0;
-
-				rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device);
-				dbg("configure_new_device rc=0x%x\n",rc);
-			}	/* End of IF (device in slot?) */
-		}		/* End of FOR loop */
-
-		if (rc) {
-			shpchp_destroy_resource_list(&temp_resources);
-
-			return_resource(&(resources->bus_head), hold_bus_node);
-			return_resource(&(resources->io_head), hold_IO_node);
-			return_resource(&(resources->mem_head), hold_mem_node);
-			return_resource(&(resources->p_mem_head), hold_p_mem_node);
-			return(rc);
-		}
-
-		/* save the interrupt routing information */
-		if (resources->irqs) {
-			resources->irqs->interrupt[0] = irqs.interrupt[0];
-			resources->irqs->interrupt[1] = irqs.interrupt[1];
-			resources->irqs->interrupt[2] = irqs.interrupt[2];
-			resources->irqs->interrupt[3] = irqs.interrupt[3];
-			resources->irqs->valid_INT = irqs.valid_INT;
-		} else if (!behind_bridge) {
-			/* We need to hook up the interrupts here */
-			for (cloop = 0; cloop < 4; cloop++) {
-				if (irqs.valid_INT & (0x01 << cloop)) {
-					rc = shpchp_set_irq(func->bus, func->device,
-							   0x0A + cloop, irqs.interrupt[cloop]);
-					if (rc) {
-						shpchp_destroy_resource_list (&temp_resources);
-						return_resource(&(resources->bus_head), hold_bus_node);
-						return_resource(&(resources->io_head), hold_IO_node);
-						return_resource(&(resources->mem_head), hold_mem_node);
-						return_resource(&(resources->p_mem_head), hold_p_mem_node);
-						return rc;
-					}
-				}
-			}	/* end of for loop */
-		}
-
-		/* Return unused bus resources
-		 * First use the temporary node to store information for the board
-		 */
-		if (hold_bus_node && bus_node && temp_resources.bus_head) {
-			hold_bus_node->length = bus_node->base - hold_bus_node->base;
-
-			hold_bus_node->next = func->bus_head;
-			func->bus_head = hold_bus_node;
-
-			temp_byte = (u8)(temp_resources.bus_head->base - 1);
-
-			/* set subordinate bus */
-			dbg("re-set subordinate bus = 0x%x\n", temp_byte);
-			rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-
-			if (temp_resources.bus_head->length == 0) {
-				kfree(temp_resources.bus_head);
-				temp_resources.bus_head = NULL;
-			} else {
-				dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
-					func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
-				return_resource(&(resources->bus_head), temp_resources.bus_head);
-			}
-		}
-
-		/* If we have IO space available and there is some left,
-		 * return the unused portion
-		 */
-		if (hold_IO_node && temp_resources.io_head) {
-			io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
-							       &hold_IO_node, 0x1000);
-
-			/* Check if we were able to split something off */
-			if (io_node) {
-				hold_IO_node->base = io_node->base + io_node->length;
-
-				RES_CHECK(hold_IO_node->base, 8);
-				temp_byte = (u8)((hold_IO_node->base) >> 8);
-				rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
-				return_resource(&(resources->io_head), io_node);
-			}
-
-			io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
-
-			/*  Check if we were able to split something off */
-			if (io_node) {
-				/* First use the temporary node to store information for the board */
-				hold_IO_node->length = io_node->base - hold_IO_node->base;
-
-				/* If we used any, add it to the board's list */
-				if (hold_IO_node->length) {
-					hold_IO_node->next = func->io_head;
-					func->io_head = hold_IO_node;
-
-					RES_CHECK(io_node->base - 1, 8);
-					temp_byte = (u8)((io_node->base - 1) >> 8);
-					rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
-					return_resource(&(resources->io_head), io_node);
-				} else {
-					/* it doesn't need any IO */
-					temp_byte = 0x00;
-					rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
-					return_resource(&(resources->io_head), io_node);
-					kfree(hold_IO_node);
-				}
-			} else {
-				/* it used most of the range */
-				hold_IO_node->next = func->io_head;
-				func->io_head = hold_IO_node;
-			}
-		} else if (hold_IO_node) {
-			/* it used the whole range */
-			hold_IO_node->next = func->io_head;
-			func->io_head = hold_IO_node;
-		}
-
-		/* If we have memory space available and there is some left,
-		 * return the unused portion
-		 */
-		if (hold_mem_node && temp_resources.mem_head) {
-			mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
-
-			/* Check if we were able to split something off */
-			if (mem_node) {
-				hold_mem_node->base = mem_node->base + mem_node->length;
-
-				RES_CHECK(hold_mem_node->base, 16);
-				temp_word = (u32)((hold_mem_node->base) >> 16);
-				rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
-				return_resource(&(resources->mem_head), mem_node);
-			}
-
-			mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
-
-			/* Check if we were able to split something off */
-			if (mem_node) {
-				/* First use the temporary node to store information for the board */
-				hold_mem_node->length = mem_node->base - hold_mem_node->base;
-
-				if (hold_mem_node->length) {
-					hold_mem_node->next = func->mem_head;
-					func->mem_head = hold_mem_node;
-
-					/* configure end address */
-					RES_CHECK(mem_node->base - 1, 16);
-					temp_word = (u32)((mem_node->base - 1) >> 16);
-					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
-					/* Return unused resources to the pool */
-					return_resource(&(resources->mem_head), mem_node);
-				} else {
-					/* it doesn't need any Mem */
-					temp_word = 0x0000;
-					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
-					return_resource(&(resources->mem_head), mem_node);
-					kfree(hold_mem_node);
-				}
-			} else {
-				/* it used most of the range */
-				hold_mem_node->next = func->mem_head;
-				func->mem_head = hold_mem_node;
-			}
-		} else if (hold_mem_node) {
-			/* it used the whole range */
-			hold_mem_node->next = func->mem_head;
-			func->mem_head = hold_mem_node;
-		}
-
-		/* If we have prefetchable memory space available and there is some 
-		 * left at the end, return the unused portion
-		 */
-		if (hold_p_mem_node && temp_resources.p_mem_head) {
-			p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
-								  &hold_p_mem_node, 0x100000L);
-
-			/* Check if we were able to split something off */
-			if (p_mem_node) {
-				hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
-
-				RES_CHECK(hold_p_mem_node->base, 16);
-				temp_word = (u32)((hold_p_mem_node->base) >> 16);
-				rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
-				return_resource(&(resources->p_mem_head), p_mem_node);
-			}
-
-			p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
-
-			/* Check if we were able to split something off */
-			if (p_mem_node) {
-				/* First use the temporary node to store information for the board */
-				hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
-
-				/* If we used any, add it to the board's list */
-				if (hold_p_mem_node->length) {
-					hold_p_mem_node->next = func->p_mem_head;
-					func->p_mem_head = hold_p_mem_node;
-
-					RES_CHECK(p_mem_node->base - 1, 16);
-					temp_word = (u32)((p_mem_node->base - 1) >> 16);
-					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
-					return_resource(&(resources->p_mem_head), p_mem_node);
-				} else {
-					/* it doesn't need any PMem */
-					temp_word = 0x0000;
-					rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
-					return_resource(&(resources->p_mem_head), p_mem_node);
-					kfree(hold_p_mem_node);
-				}
-			} else {
-				/* it used the most of the range */
-				hold_p_mem_node->next = func->p_mem_head;
-				func->p_mem_head = hold_p_mem_node;
-			}
-		} else if (hold_p_mem_node) {
-			/* it used the whole range */
-			hold_p_mem_node->next = func->p_mem_head;
-			func->p_mem_head = hold_p_mem_node;
-		}
-
-		/* We should be configuring an IRQ and the bridge's base address
-		 * registers if it needs them.  Although we have never seen such
-		 * a device
-		 */
-
-		shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-
-		dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
-	} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-		/* Standard device */
-		u64	base64;
-		rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
-		if (class_code == PCI_BASE_CLASS_DISPLAY)
-			return (DEVICE_TYPE_NOT_SUPPORTED);
-
-		/* Figure out IO and memory needs */
-		for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
-			temp_register = 0xFFFFFFFF;
-
-			rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
-			rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-			dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device, 
-				func->function);
-
-			if (!temp_register)
-				continue;
-
-			base64 = 0L;
-			if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
-				/* Map IO */
-
-				/* set base = amount of IO space */
-				base = temp_register & 0xFFFFFFFC;
-				base = ~base + 1;
-
-				dbg("NEED IO length(0x%x)\n", base);
-				io_node = get_io_resource(&(resources->io_head),(ulong)base);
-
-				/* allocate the resource to the board */
-				if (io_node) {
-					dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
-					base = (u32)io_node->base;
-					io_node->next = func->io_head;
-					func->io_head = io_node;
-				} else {
-					err("Got NO IO resource(length=0x%x)\n", base);
-					return -ENOMEM;
-				}
-			} else {	/* map MEM */
-				int prefetchable = 1;
-				struct pci_resource **res_node = &func->p_mem_head;
-				char *res_type_str = "PMEM";
-				u32	temp_register2;
-
-				if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
-					prefetchable = 0;
-					res_node = &func->mem_head;
-					res_type_str++;
-				}
-
-				base = temp_register & 0xFFFFFFF0;
-				base = ~base + 1;
-
-				switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-				case PCI_BASE_ADDRESS_MEM_TYPE_32:
-					dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
-
-					if (prefetchable && resources->p_mem_head)
-						mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
-					else {
-						if (prefetchable)
-							dbg("using MEM for PMEM\n");
-						mem_node=get_resource(&(resources->mem_head), (ulong)base);
-					}
-
-					/* allocate the resource to the board */
-					if (mem_node) {
-						base = (u32)mem_node->base; 
-						mem_node->next = *res_node;
-						*res_node = mem_node;
-						dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, 
-							mem_node->length);
-					} else {
-						err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
-						return -ENOMEM;
-					}
-					break;
-				case PCI_BASE_ADDRESS_MEM_TYPE_64:
-					rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
-					dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, 
-						temp_register, base);
-
-					if (prefetchable && resources->p_mem_head)
-						mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
-					else {
-						if (prefetchable)
-							dbg("using MEM for PMEM\n");
-						mem_node = get_resource(&(resources->mem_head), (ulong)base);
-					}
-
-					/* allocate the resource to the board */
-					if (mem_node) {
-						base64 = mem_node->base; 
-						mem_node->next = *res_node;
-						*res_node = mem_node;
-						dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), 
-							(u32)base64, mem_node->length);
-					} else {
-						err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
-						return -ENOMEM;
-					}
-					break;
-				default:
-					dbg("reserved BAR type=0x%x\n", temp_register);
-					break;
-				}
-
-			}
-
-			if (base64) {
-				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
-				cloop += 4;
-				base64 >>= 32;
-
-				if (base64) {
-					dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
-					base64 = 0x0L;
-				}
-
-				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
-			} else {
-				rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
-			}
-		}		/* End of base register loop */
-
-#if defined(CONFIG_X86_64)
-		/* Figure out which interrupt pin this function uses */
-		rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte);
-
-		/* If this function needs an interrupt and we are behind a bridge
-		   and the pin is tied to something that's alread mapped,
-		   set this one the same
-		 */
-		if (temp_byte && resources->irqs && 
-		    (resources->irqs->valid_INT & 
-		     (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) {
-			/* We have to share with something already set up */
-			IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03];
-		} else {
-			/* Program IRQ based on card type */
-			rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
-
-			if (class_code == PCI_BASE_CLASS_STORAGE) {
-				IRQ = shpchp_disk_irq;
-			} else {
-				IRQ = shpchp_nic_irq;
-			}
-		}
-
-		/* IRQ Line */
-		rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
-
-		if (!behind_bridge) {
-			rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
-			if (rc)
-				return(1);
-		} else {
-			/* TBD - this code may also belong in the other clause of this If statement */
-			resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ;
-			resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03;
-		}
-#endif
-		/* Disable ROM base Address */
-		rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
-
-		/* Set HP parameters (Cache Line Size, Latency Timer) */
-		rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
-		if (rc)
-			return rc;
-
-		shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
-
-		dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
-	}			/* End of Not-A-Bridge else */
-	else {
-		/* It's some strange type of PCI adapter (Cardbus?) */
-		return(DEVICE_TYPE_NOT_SUPPORTED);
-	}
-
-	func->configured = 1;
-
-	return 0;
+	ret = remove_board(p_slot);
+	update_slot_info(p_slot);
+	return ret;
 }
 
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 8d98410..40905a6 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -27,17 +27,10 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-#include <asm/system.h>
 #include "shpchp.h"
 
 #ifdef DEBUG
@@ -282,7 +275,7 @@
 
 static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u16 cmd_status;
 	int retval = 0;
 	u16 temp_word;
@@ -320,7 +313,6 @@
 	 * command. 
 	 */
 	writew(temp_word, php_ctlr->creg + CMD);
-	dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word);
 
 	DBG_LEAVE_ROUTINE 
 	return retval;
@@ -328,7 +320,7 @@
 
 static int hpc_check_cmd_status(struct controller *ctrl)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	u16 cmd_status;
 	int retval = 0;
 
@@ -368,7 +360,7 @@
 
 static int hpc_get_attention_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u32 slot_reg;
 	u16 slot_status;
 	u8 atten_led_state;
@@ -408,7 +400,7 @@
 
 static int hpc_get_power_status(struct slot * slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u32 slot_reg;
 	u16 slot_status;
 	u8 slot_state;
@@ -450,7 +442,7 @@
 
 static int hpc_get_latch_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u32 slot_reg;
 	u16 slot_status;
 
@@ -473,7 +465,7 @@
 
 static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u32 slot_reg;
 	u16 slot_status;
 	u8 card_state;
@@ -496,7 +488,7 @@
 
 static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 
 	DBG_ENTER_ROUTINE 
 	
@@ -513,7 +505,7 @@
 
 static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u32 slot_reg;
 	u16 slot_status, sec_bus_status;
 	u8 m66_cap, pcix_cap, pi;
@@ -594,7 +586,7 @@
 
 static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u16 sec_bus_status;
 	u8 pi;
 	int retval = 0;
@@ -623,7 +615,7 @@
 
 static int hpc_query_power_fault(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u32 slot_reg;
 	u16 slot_status;
 	u8 pwr_fault_state, status;
@@ -647,7 +639,7 @@
 
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
-	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd = 0;
 	int rc = 0;
 
@@ -683,7 +675,7 @@
 
 static void hpc_set_green_led_on(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd;
 
 	if (!slot->ctrl->hpc_ctlr_handle) {
@@ -705,7 +697,7 @@
 
 static void hpc_set_green_led_off(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd;
 
 	if (!slot->ctrl->hpc_ctlr_handle) {
@@ -727,7 +719,7 @@
 
 static void hpc_set_green_led_blink(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd;
 
 	if (!slot->ctrl->hpc_ctlr_handle) {
@@ -754,7 +746,7 @@
 	int *updown,		/* physical_slot_num increament: 1 or -1	*/
 	int *flags)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 
 	DBG_ENTER_ROUTINE 
 
@@ -776,7 +768,7 @@
 
 static void hpc_release_ctlr(struct controller *ctrl)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	struct php_ctlr_state_s *p, *p_prev;
 
 	DBG_ENTER_ROUTINE 
@@ -796,10 +788,8 @@
 		}
 	}
 	if (php_ctlr->pci_dev) {
-		dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
 		iounmap(php_ctlr->creg);
 		release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
-		dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__);
 		php_ctlr->pci_dev = NULL;
 	}
 
@@ -828,7 +818,7 @@
 
 static int hpc_power_on_slot(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd;
 	int retval = 0;
 
@@ -859,7 +849,7 @@
 
 static int hpc_slot_enable(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd;
 	int retval = 0;
 
@@ -890,7 +880,7 @@
 
 static int hpc_slot_disable(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd;
 	int retval = 0;
 
@@ -920,51 +910,12 @@
 	return retval;
 }
 
-static int hpc_enable_all_slots( struct slot *slot )
-{
-	int retval = 0;
-
-	DBG_ENTER_ROUTINE 
-	
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL);
-	if (retval) {
-		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
-	}
-
-	DBG_LEAVE_ROUTINE
-
-	return retval;
-}
-
-static int hpc_pwr_on_all_slots(struct slot *slot)
-{
-	int retval = 0;
-
-	DBG_ENTER_ROUTINE 
-
-	retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL);
-
-	if (retval) {
-		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
-	}
-
-	DBG_LEAVE_ROUTINE
-	return retval;
-}
-
 static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 {
 	u8 slot_cmd;
 	u8 pi;
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 
 	DBG_ENTER_ROUTINE 
 	
@@ -1089,18 +1040,13 @@
 
 	if (!intr_loc)
 		return IRQ_NONE;
-	dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
 	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
 
 	if(!shpchp_poll_mode) {
 		/* Mask Global Interrupt Mask - see implementation note on p. 139 */
 		/* of SHPC spec rev 1.0*/
 		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		dbg("%s: Before masking global interrupt, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		temp_dword |= 0x00000001;
-		dbg("%s: After masking global interrupt, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 
 		intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
@@ -1114,11 +1060,7 @@
 		 * Detect bit in Controller SERR-INT register
 		 */
 		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		dbg("%s: Before clearing CCIP, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		temp_dword &= 0xfffeffff;
-		dbg("%s: After clearing CCIP, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 		wake_up_interruptible(&ctrl->queue);
 	}
@@ -1126,11 +1068,7 @@
 	if ((intr_loc = (intr_loc >> 1)) == 0) {
 		/* Unmask Global Interrupt Mask */
 		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		temp_dword &= 0xfffffffe;
-		dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 
 		return IRQ_NONE;
@@ -1140,11 +1078,9 @@
 	/* To find out which slot has interrupt pending */
 		if ((intr_loc >> hp_slot) & 0x01) {
 			temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
-			dbg("%s: Slot %x with intr, temp_dword = %x\n",
-				__FUNCTION__, hp_slot, temp_dword); 
+			dbg("%s: Slot %x with intr, slot register = %x\n",
+				__FUNCTION__, hp_slot, temp_dword);
 			temp_byte = (temp_dword >> 16) & 0xFF;
-			dbg("%s: Slot with intr, temp_byte = %x\n",
-				__FUNCTION__, temp_byte); 
 			if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
 				schedule_flag += php_ctlr->switch_change_callback(
 					hp_slot, php_ctlr->callback_instance_id);
@@ -1160,8 +1096,6 @@
 			
 			/* Clear all slot events */
 			temp_dword = 0xe01f3fff;
-			dbg("%s: Clearing slot events, temp_dword = %x\n",
-				__FUNCTION__, temp_dword); 
 			writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
 
 			intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
@@ -1171,11 +1105,7 @@
 	if (!shpchp_poll_mode) {
 		/* Unmask Global Interrupt Mask */
 		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		temp_dword &= 0xfffffffe;
-		dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
-			__FUNCTION__, temp_dword); 
 		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 	}
 	
@@ -1184,7 +1114,7 @@
 
 static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
 	int retval = 0;
 	u8 pi;
@@ -1253,7 +1183,7 @@
 
 static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
-	struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
+	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
 	u16 sec_bus_status;
 	int retval = 0;
@@ -1367,8 +1297,6 @@
 	.power_on_slot			= hpc_power_on_slot,
 	.slot_enable			= hpc_slot_enable,
 	.slot_disable			= hpc_slot_disable,
-	.enable_all_slots		= hpc_enable_all_slots,
-	.pwr_on_all_slots		= hpc_pwr_on_all_slots,
 	.set_bus_speed_mode		= hpc_set_bus_speed_mode,	  
 	.set_attention_status	= hpc_set_attention_status,
 	.get_power_status		= hpc_get_power_status,
@@ -1391,12 +1319,7 @@
 	.check_cmd_status		= hpc_check_cmd_status,
 };
 
-int shpc_init(struct controller * ctrl,
-		struct pci_dev * pdev,
-		php_intr_callback_t attention_button_callback,
-		php_intr_callback_t switch_change_callback,
-		php_intr_callback_t presence_change_callback,
-		php_intr_callback_t power_fault_callback)
+int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 {
 	struct php_ctlr_state_s *php_ctlr, *p;
 	void *instance_id = ctrl;
@@ -1405,7 +1328,6 @@
 	static int first = 1;
 	u32 shpc_cap_offset, shpc_base_offset;
 	u32 tempdword, slot_reg;
-	u16 vendor_id, device_id;
 	u8 i;
 
 	DBG_ENTER_ROUTINE
@@ -1422,21 +1344,8 @@
 
 	php_ctlr->pci_dev = pdev;	/* save pci_dev in context */
 
-	rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
-	dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id);
-	if (rc) {
-		err("%s: unable to read PCI configuration data\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
-	dbg("%s: Device ID: %x\n",__FUNCTION__, device_id);
-	if (rc) {
-		err("%s: unable to read PCI configuration data\n", __FUNCTION__);
-		goto abort_free_ctlr;
-	}
-
-	if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+	if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
+				PCI_DEVICE_ID_AMD_GOLAM_7450)) {
 		shpc_base_offset = 0;  /* amd shpc driver doesn't use this; assume 0 */
 	} else {
 		if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
@@ -1469,7 +1378,8 @@
 				err("%s : pci_read_config_dword failed\n", __FUNCTION__);
 				goto abort_free_ctlr;
 			}
-			dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword);
+			dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
+					tempdword);
 		}
 	}
 
@@ -1478,13 +1388,6 @@
 		first = 0;
 	}
 
-	dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn), 
-		PCI_FUNC(pdev->devfn), pdev->irq);
-	for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
-		if (pci_resource_len(pdev, rc) > 0)
-			dbg("pci resource[%d] start=0x%lx(len=0x%lx), shpc_base_offset %x\n", rc,
-				pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset);
-
 	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
 		pdev->subsystem_device);
 	
@@ -1504,7 +1407,6 @@
 		goto abort_free_ctlr;
 	}
 	dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
-	dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0));
 
 	init_MUTEX(&ctrl->crit_sect);
 	/* Setup wait queue */
@@ -1512,13 +1414,10 @@
 
 	/* Find the IRQ */
 	php_ctlr->irq = pdev->irq;
-	dbg("HPC interrupt = %d\n", php_ctlr->irq);
-
-	/* Save interrupt callback info */
-	php_ctlr->attention_button_callback = attention_button_callback;
-	php_ctlr->switch_change_callback = switch_change_callback;
-	php_ctlr->presence_change_callback = presence_change_callback;
-	php_ctlr->power_fault_callback = power_fault_callback;
+	php_ctlr->attention_button_callback = shpchp_handle_attention_button,
+	php_ctlr->switch_change_callback = shpchp_handle_switch_change;
+	php_ctlr->presence_change_callback = shpchp_handle_presence_change;
+	php_ctlr->power_fault_callback = shpchp_handle_power_fault;
 	php_ctlr->callback_instance_id = instance_id;
 
 	/* Return PCI Controller Info */
@@ -1556,7 +1455,6 @@
 		if (rc) {
 			info("Can't get msi for the hotplug controller\n");
 			info("Use INTx for the hotplug controller\n");
-			dbg("%s: rc = %x\n", __FUNCTION__, rc);
 		} else
 			php_ctlr->irq = pdev->irq;
 		
@@ -1566,9 +1464,11 @@
 			err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
 			goto abort_free_ctlr;
 		}
-		/* Execute OSHP method here */
 	}
-	dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
+	dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
+			pdev->bus->number, PCI_SLOT(pdev->devfn),
+			PCI_FUNC(pdev->devfn), pdev->irq);
+	get_hp_hw_control_from_firmware(pdev);
 
 	/*  Add this HPC instance into the HPC list */
 	spin_lock(&list_lock);
@@ -1607,7 +1507,6 @@
 		dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
 	}
 
-	dbg("%s: Leaving shpc_init\n", __FUNCTION__);
 	DBG_LEAVE_ROUTINE
 	return 0;
 
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index d867099..b8e95ac 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -27,784 +27,151 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
 #include <linux/pci.h>
 #include "../pci.h"
 #include "shpchp.h"
-#ifndef CONFIG_IA64
-#include "../../../arch/i386/pci/pci.h"    /* horrible hack showing how processor dependant we are... */
-#endif
 
-int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)  
+void program_fw_provided_values(struct pci_dev *dev)
 {
-	unsigned char bus;
-	struct pci_bus *child;
-	int num;
+	u16 pci_cmd, pci_bctl;
+	struct pci_dev *cdev;
+	struct hotplug_params hpp = {0x8, 0x40, 0, 0}; /* defaults */
 
-	if (func->pci_dev == NULL)
-		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
+	/* Program hpp values for this device */
+	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+		return;
 
-	/* Still NULL ? Well then scan for it ! */
-	if (func->pci_dev == NULL) {
-		num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
-		if (num) {
-			dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate,
-				ctrl->pci_dev->subordinate->number);
-			pci_bus_add_devices(ctrl->pci_dev->subordinate);
-		}
-		
-		func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-		if (func->pci_dev == NULL) {
-			dbg("ERROR: pci_dev still null\n");
-			return 0;
+	get_hp_params_from_firmware(dev, &hpp);
+
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
+	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+	if (hpp.enable_serr)
+		pci_cmd |= PCI_COMMAND_SERR;
+	else
+		pci_cmd &= ~PCI_COMMAND_SERR;
+	if (hpp.enable_perr)
+		pci_cmd |= PCI_COMMAND_PARITY;
+	else
+		pci_cmd &= ~PCI_COMMAND_PARITY;
+	pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+	/* Program bridge control value and child devices */
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+				hpp.latency_timer);
+		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+		if (hpp.enable_serr)
+			pci_bctl |= PCI_BRIDGE_CTL_SERR;
+		else
+			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+		if (hpp.enable_perr)
+			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+		else
+			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+		pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+		if (dev->subordinate) {
+			list_for_each_entry(cdev, &dev->subordinate->devices,
+					bus_list)
+				program_fw_provided_values(cdev);
 		}
 	}
+}
 
-	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
-		child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
-		pci_do_scan_bus(child);
+int shpchp_configure_device(struct slot *p_slot)
+{
+	struct pci_dev *dev;
+	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+	int num, fn;
 
+	dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+	if (dev) {
+		err("Device %s already exists at %x:%x, cannot hot-add\n",
+				pci_name(dev), p_slot->bus, p_slot->device);
+		return -EINVAL;
 	}
 
+	num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
+	if (num == 0) {
+		err("No new device found\n");
+		return -ENODEV;
+	}
+
+	for (fn = 0; fn < 8; fn++) {
+		if (!(dev = pci_find_slot(p_slot->bus,
+					PCI_DEVFN(p_slot->device, fn))))
+			continue;
+		if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+			err("Cannot hot-add display device %s\n",
+					pci_name(dev));
+			continue;
+		}
+		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
+				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
+			/* Find an unused bus number for the new bridge */
+			struct pci_bus *child;
+			unsigned char busnr, start = parent->secondary;
+			unsigned char end = parent->subordinate;
+			for (busnr = start; busnr <= end; busnr++) {
+				if (!pci_find_bus(pci_domain_nr(parent),
+							busnr))
+					break;
+			}
+			if (busnr >= end) {
+				err("No free bus for hot-added bridge\n");
+				continue;
+			}
+			child = pci_add_new_bus(parent, dev, busnr);
+			if (!child) {
+				err("Cannot add new bus for %s\n",
+						pci_name(dev));
+				continue;
+			}
+			child->subordinate = pci_do_scan_bus(child);
+			pci_bus_size_bridges(child);
+		}
+		program_fw_provided_values(dev);
+	}
+
+	pci_bus_assign_resources(parent);
+	pci_bus_add_devices(parent);
+	pci_enable_bridges(parent);
 	return 0;
 }
 
-
-int shpchp_unconfigure_device(struct pci_func* func) 
+int shpchp_unconfigure_device(struct slot *p_slot)
 {
 	int rc = 0;
 	int j;
+	u8 bctl = 0;
 	
-	dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
-				func->device, func->function);
+	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
 
 	for (j=0; j<8 ; j++) {
-		struct pci_dev* temp = pci_find_slot(func->bus,
-				(func->device << 3) | j);
-		if (temp) {
-			pci_remove_bus_device(temp);
+		struct pci_dev* temp = pci_find_slot(p_slot->bus,
+				(p_slot->device << 3) | j);
+		if (!temp)
+			continue;
+		if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+			err("Cannot remove display device %s\n",
+					pci_name(temp));
+			continue;
 		}
+		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+			pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+			if (bctl & PCI_BRIDGE_CTL_VGA) {
+				err("Cannot remove display device %s\n",
+						pci_name(temp));
+				continue;
+			}
+		}
+		pci_remove_bus_device(temp);
 	}
 	return rc;
 }
 
-/*
- * shpchp_set_irq
- *
- * @bus_num: bus number of PCI device
- * @dev_num: device number of PCI device
- * @slot: pointer to u8 where slot number will be returned
- */
-int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
-{
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64)
-	int rc;
-	u16 temp_word;
-	struct pci_dev fakedev;
-	struct pci_bus fakebus;
-
-	fakedev.devfn = dev_num << 3;
-	fakedev.bus = &fakebus;
-	fakebus.number = bus_num;
-	dbg("%s: dev %d, bus %d, pin %d, num %d\n",
-	    __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
-	rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
-	dbg("%s: rc %d\n", __FUNCTION__, rc);
-	if (!rc)
-		return !rc;
-
-	/* set the Edge Level Control Register (ELCR) */
-	temp_word = inb(0x4d0);
-	temp_word |= inb(0x4d1) << 8;
-
-	temp_word |= 0x01 << irq_num;
-
-	/* This should only be for x86 as it sets the Edge Level Control Register */
-	outb((u8) (temp_word & 0xFF), 0x4d0);
-	outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-#endif
-	return 0;
-}
-
-/* More PCI configuration routines; this time centered around hotplug controller */
-
-
-/*
- * shpchp_save_config
- *
- * Reads configuration for all slots in a PCI bus and saves info.
- *
- * Note:  For non-hot plug busses, the slot # saved is the device #
- *
- * returns 0 if success
- */
-int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
-{
-	int rc;
-	u8 class_code;
-	u8 header_type;
-	u32 ID;
-	u8 secondary_bus;
-	struct pci_func *new_slot;
-	int sub_bus;
-	int FirstSupported;
-	int LastSupported;
-	int max_functions;
-	int function;
-	u8 DevError;
-	int device = 0;
-	int cloop = 0;
-	int stop_it;
-	int index;
-	int is_hot_plug = num_ctlr_slots || first_device_num;
-	struct pci_bus lpci_bus, *pci_bus;
-
-	dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
-				num_ctlr_slots, first_device_num);
-
-	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-
-	dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
-				num_ctlr_slots, first_device_num);
-
-	/*   Decide which slots are supported */
-	if (is_hot_plug) {
-		/*********************************
-		 *  is_hot_plug is the slot mask
-		 *********************************/
-		FirstSupported = first_device_num;
-		LastSupported = FirstSupported + num_ctlr_slots - 1;
-	} else {
-		FirstSupported = 0;
-		LastSupported = 0x1F;
-	}
-
-	dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
-					LastSupported);
-
-	/*   Save PCI configuration space for all devices in supported slots */
-	pci_bus->number = busnumber;
-	for (device = FirstSupported; device <= LastSupported; device++) {
-		ID = 0xFFFFFFFF;
-		rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
-					PCI_VENDOR_ID, &ID);
-
-		if (ID != 0xFFFFFFFF) {	  /*  device in slot */
-			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
-					0x0B, &class_code);
-			if (rc)
-				return rc;
-
-			rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
-					PCI_HEADER_TYPE, &header_type);
-			if (rc)
-				return rc;
-
-			dbg("class_code = %x, header_type = %x\n", class_code, header_type);
-
-			/* If multi-function device, set max_functions to 8 */
-			if (header_type & 0x80)
-				max_functions = 8;
-			else
-				max_functions = 1;
-
-			function = 0;
-
-			do {
-				DevError = 0;
-
-				if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {   /* P-P Bridge */
-					/* Recurse the subordinate bus
-					 * get the subordinate bus number
-					 */
-					rc = pci_bus_read_config_byte(pci_bus,
-						PCI_DEVFN(device, function), 
-						PCI_SECONDARY_BUS, &secondary_bus);
-					if (rc) {
-						return rc;
-					} else {
-						sub_bus = (int) secondary_bus;
-
-						/* Save secondary bus cfg spc with this recursive call. */
-						rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
-						if (rc)
-							return rc;
-					}
-				}
-
-				index = 0;
-				new_slot = shpchp_slot_find(busnumber, device, index++);
-
-				dbg("new_slot = %p\n", new_slot);
-
-				while (new_slot && (new_slot->function != (u8) function)) {
-					new_slot = shpchp_slot_find(busnumber, device, index++);
-					dbg("new_slot = %p\n", new_slot);
-				}
-				if (!new_slot) {
-					/* Setup slot structure. */
-					new_slot = shpchp_slot_create(busnumber);
-					dbg("new_slot = %p\n", new_slot);
-
-					if (new_slot == NULL)
-						return(1);
-				}
-
-				new_slot->bus = (u8) busnumber;
-				new_slot->device = (u8) device;
-				new_slot->function = (u8) function;
-				new_slot->is_a_board = 1;
-				new_slot->switch_save = 0x10;
-				new_slot->pwr_save = 1;
-				/* In case of unsupported board */
-				new_slot->status = DevError;
-				new_slot->pci_dev = pci_find_slot(new_slot->bus,
-					(new_slot->device << 3) | new_slot->function);
-				dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
-
-				for (cloop = 0; cloop < 0x20; cloop++) {
-					rc = pci_bus_read_config_dword(pci_bus,
-						PCI_DEVFN(device, function), 
-						cloop << 2,
-						(u32 *) &(new_slot->config_space [cloop]));
-					/* dbg("new_slot->config_space[%x] = %x\n",
-						cloop, new_slot->config_space[cloop]); */
-					if (rc)
-						return rc;
-				}
-
-				function++;
-
-				stop_it = 0;
-
-				/*  this loop skips to the next present function
-				 *  reading in Class Code and Header type.
-				 */
-
-				while ((function < max_functions)&&(!stop_it)) {
-					rc = pci_bus_read_config_dword(pci_bus,
-						PCI_DEVFN(device, function),
-						PCI_VENDOR_ID, &ID);
-
-					if (ID == 0xFFFFFFFF) {  /* nothing there. */
-						function++;
-						dbg("Nothing there\n");
-					} else {  /* Something there */
-						rc = pci_bus_read_config_byte(pci_bus,
-							PCI_DEVFN(device, function), 
-							0x0B, &class_code);
-						if (rc)
-							return rc;
-
-						rc = pci_bus_read_config_byte(pci_bus,
-							PCI_DEVFN(device, function), 
-							PCI_HEADER_TYPE, &header_type);
-						if (rc)
-							return rc;
-
-						dbg("class_code = %x, header_type = %x\n",
-							class_code, header_type);
-						stop_it++;
-					}
-				}
-
-			} while (function < max_functions);
-			/* End of IF (device in slot?) */
-		} else if (is_hot_plug) {
-			/* Setup slot structure with entry for empty slot */
-			new_slot = shpchp_slot_create(busnumber);
-
-			if (new_slot == NULL) {
-				return(1);
-			}
-			dbg("new_slot = %p\n", new_slot);
-
-			new_slot->bus = (u8) busnumber;
-			new_slot->device = (u8) device;
-			new_slot->function = 0;
-			new_slot->is_a_board = 0;
-			new_slot->presence_save = 0;
-			new_slot->switch_save = 0;
-		}
-	}			/* End of FOR loop */
-
-	return(0);
-}
-
-
-/*
- * shpchp_save_slot_config
- *
- * Saves configuration info for all PCI devices in a given slot
- * including subordinate busses.
- *
- * returns 0 if success
- */
-int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
-{
-	int rc;
-	u8 class_code;
-	u8 header_type;
-	u32 ID;
-	u8 secondary_bus;
-	int sub_bus;
-	int max_functions;
-	int function;
-	int cloop = 0;
-	int stop_it;
-	struct pci_bus lpci_bus, *pci_bus;
-	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = new_slot->bus;
-
-	ID = 0xFFFFFFFF;
-
-	pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
-					PCI_VENDOR_ID, &ID);
-
-	if (ID != 0xFFFFFFFF) {	  /*  device in slot */
-		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
-					0x0B, &class_code);
-
-		pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
-					PCI_HEADER_TYPE, &header_type);
-
-		if (header_type & 0x80)	/* Multi-function device */
-			max_functions = 8;
-		else
-			max_functions = 1;
-
-		function = 0;
-
-		do {
-			if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  /* PCI-PCI Bridge */
-				/*  Recurse the subordinate bus */
-				pci_bus_read_config_byte(pci_bus,
-					PCI_DEVFN(new_slot->device, function), 
-					PCI_SECONDARY_BUS, &secondary_bus);
-
-				sub_bus = (int) secondary_bus;
-
-				/* Save the config headers for the secondary bus. */
-				rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
-
-				if (rc)
-					return rc;
-
-			}	/* End of IF */
-
-			new_slot->status = 0;
-
-			for (cloop = 0; cloop < 0x20; cloop++) {
-				pci_bus_read_config_dword(pci_bus,
-					PCI_DEVFN(new_slot->device, function), 
-					cloop << 2,
-					(u32 *) &(new_slot->config_space [cloop]));
-			}
-
-			function++;
-
-			stop_it = 0;
-
-			/*  this loop skips to the next present function
-			 *  reading in the Class Code and the Header type.
-			 */
-
-			while ((function < max_functions) && (!stop_it)) {
-				pci_bus_read_config_dword(pci_bus,
-					PCI_DEVFN(new_slot->device, function),
-					PCI_VENDOR_ID, &ID);
-
-				if (ID == 0xFFFFFFFF) {	 /* nothing there. */
-					function++;
-				} else {  /* Something there */
-					pci_bus_read_config_byte(pci_bus,
-						PCI_DEVFN(new_slot->device, function),
-						0x0B, &class_code);
-
-					pci_bus_read_config_byte(pci_bus,
-						PCI_DEVFN(new_slot->device, function),
-						PCI_HEADER_TYPE, &header_type);
-
-					stop_it++;
-				}
-			}
-
-		} while (function < max_functions);
-	}			/* End of IF (device in slot?) */
-	else {
-		return 2;
-	}
-
-	return 0;
-}
-
-
-/*
- * shpchp_save_used_resources
- *
- * Stores used resource information for existing boards.  this is
- * for boards that were in the system when this driver was loaded.
- * this function is for hot plug ADD
- *
- * returns 0 if success
- * if disable  == 1(DISABLE_CARD),
- *  it loops for all functions of the slot and disables them.
- * else, it just get resources of the function and return.
- */
-int shpchp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
-{
-	u8 cloop;
-	u8 header_type;
-	u8 secondary_bus;
-	u8 temp_byte;
-	u16 command;
-	u16 save_command;
-	u16 w_base, w_length;
-	u32 temp_register;
-	u32 save_base;
-	u32 base, length;
-	u64 base64 = 0;
-	int index = 0;
-	unsigned int devfn;
-	struct pci_resource *mem_node = NULL;
-	struct pci_resource *p_mem_node = NULL;
-	struct pci_resource *t_mem_node;
-	struct pci_resource *io_node;
-	struct pci_resource *bus_node;
-	struct pci_bus lpci_bus, *pci_bus;
-	memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-
-	if (disable)
-		func = shpchp_slot_find(func->bus, func->device, index++);
-
-	while ((func != NULL) && func->is_a_board) {
-		pci_bus->number = func->bus;
-		devfn = PCI_DEVFN(func->device, func->function);
-
-		/* Save the command register */
-		pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
-
-		if (disable) {
-			/* disable card */
-			command = 0x00;
-			pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-		}
-
-		/* Check for Bridge */
-		pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
-		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {     /* PCI-PCI Bridge */
-			dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
-					func->bus, func->device, save_command);
-			if (disable) {
-				/* Clear Bridge Control Register */
-				command = 0x00;
-				pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
-			}
-
-			pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
-			pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
-
-			bus_node = kmalloc(sizeof(struct pci_resource),
-						GFP_KERNEL);
-			if (!bus_node)
-				return -ENOMEM;
-
-			bus_node->base = (ulong)secondary_bus;
-			bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
-
-			bus_node->next = func->bus_head;
-			func->bus_head = bus_node;
-
-			/* Save IO base and Limit registers */
-			pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
-			base = temp_byte;
-			pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
-			length = temp_byte;
-
-			if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
-				io_node = kmalloc(sizeof(struct pci_resource),
-							GFP_KERNEL);
-				if (!io_node)
-					return -ENOMEM;
-
-				io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
-				io_node->length = (ulong)(length - base + 0x10) << 8;
-
-				io_node->next = func->io_head;
-				func->io_head = io_node;
-			}
-
-			/* Save memory base and Limit registers */
-			pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
-			pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
-
-			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
-				mem_node = kmalloc(sizeof(struct pci_resource),
-						GFP_KERNEL);
-				if (!mem_node)
-					return -ENOMEM;
-
-				mem_node->base = (ulong)w_base << 16;
-				mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
-				mem_node->next = func->mem_head;
-				func->mem_head = mem_node;
-			}
-			/* Save prefetchable memory base and Limit registers */
-			pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
-			pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
-
-			if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
-				p_mem_node = kmalloc(sizeof(struct pci_resource),
-						GFP_KERNEL);
-				if (!p_mem_node)
-					return -ENOMEM;
-
-				p_mem_node->base = (ulong)w_base << 16;
-				p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
-				p_mem_node->next = func->p_mem_head;
-				func->p_mem_head = p_mem_node;
-			}
-		} else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
-			dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
-					func->bus, func->device, save_command);
-
-			/* Figure out IO and memory base lengths */
-			for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
-				pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
-
-				temp_register = 0xFFFFFFFF;
-				pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
-				pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-
-				if (!disable)
-					pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
-
-				if (!temp_register)
-					continue;
-
-				base = temp_register;
-
-				if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
-						(!disable || (save_command & PCI_COMMAND_IO))) {
-					/* IO base */
-					/* set temp_register = amount of IO space requested */
-					base = base & 0xFFFFFFFCL;
-					base = (~base) + 1;
-
-					io_node =  kmalloc(sizeof (struct pci_resource),
-								GFP_KERNEL);
-					if (!io_node)
-						return -ENOMEM;
-
-					io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
-					io_node->length = (ulong)base;
-					dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
-						io_node->base, io_node->length);
-
-					io_node->next = func->io_head;
-					func->io_head = io_node;
-				} else {  /* map Memory */
-					int prefetchable = 1;
-					/* struct pci_resources **res_node; */
-					char *res_type_str = "PMEM";
-					u32 temp_register2;
-
-					t_mem_node = kmalloc(sizeof (struct pci_resource),
-								GFP_KERNEL);
-					if (!t_mem_node)
-						return -ENOMEM;
-
-					if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
-							(!disable || (save_command & PCI_COMMAND_MEMORY))) {
-						prefetchable = 0;
-						mem_node = t_mem_node;
-						res_type_str++;
-					} else
-						p_mem_node = t_mem_node;
-
-					base = base & 0xFFFFFFF0L;
-					base = (~base) + 1;
-
-					switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-					case PCI_BASE_ADDRESS_MEM_TYPE_32:
-						if (prefetchable) {
-							p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
-							p_mem_node->length = (ulong)base;
-							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
-								res_type_str, 
-								p_mem_node->base,
-								p_mem_node->length);
-
-							p_mem_node->next = func->p_mem_head;
-							func->p_mem_head = p_mem_node;
-						} else {
-							mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
-							mem_node->length = (ulong)base;
-							dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
-								res_type_str, 
-								mem_node->base,
-								mem_node->length);
-
-							mem_node->next = func->mem_head;
-							func->mem_head = mem_node;
-						}
-						break;
-					case PCI_BASE_ADDRESS_MEM_TYPE_64:
-						pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
-						base64 = temp_register2;
-						base64 = (base64 << 32) | save_base;
-
-						if (temp_register2) {
-							dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", 
-								res_type_str, temp_register2, (u32)base64);
-							base64 &= 0x00000000FFFFFFFFL;
-						}
-
-						if (prefetchable) {
-							p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
-							p_mem_node->length = base;
-							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
-								res_type_str, 
-								p_mem_node->base,
-								p_mem_node->length);
-
-							p_mem_node->next = func->p_mem_head;
-							func->p_mem_head = p_mem_node;
-						} else {
-							mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
-							mem_node->length = base;
-							dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
-								res_type_str, 
-								mem_node->base,
-								mem_node->length);
-
-							mem_node->next = func->mem_head;
-							func->mem_head = mem_node;
-						}
-						cloop += 4;
-						break;
-					default:
-						dbg("asur: reserved BAR type=0x%x\n",
-							temp_register);
-						break;
-					}
-				} 
-			}	/* End of base register loop */
-		} else {	/* Some other unknown header type */
-			dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
-					func->bus, func->device);
-		}
-
-		/* find the next device in this slot */
-		if (!disable)
-			break;
-		func = shpchp_slot_find(func->bus, func->device, index++);
-	}
-
-	return 0;
-}
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-return_resource_list(struct pci_resource **func, struct pci_resource **res)
-{
-	struct pci_resource *node;
-	struct pci_resource *t_node;
-
-	node = *func;
-	*func = NULL;
-	while (node) {
-		t_node = node->next;
-		return_resource(res, node);
-		node = t_node;
-	}
-}
-
-/*
- * shpchp_return_board_resources
- *
- * this routine returns all resources allocated to a board to
- * the available pool.
- *
- * returns 0 if success
- */
-int shpchp_return_board_resources(struct pci_func * func,
-					struct resource_lists * resources)
-{
-	int rc;
-	dbg("%s\n", __FUNCTION__);
-
-	if (!func)
-		return 1;
-
-	return_resource_list(&(func->io_head),&(resources->io_head));
-	return_resource_list(&(func->mem_head),&(resources->mem_head));
-	return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
-	return_resource_list(&(func->bus_head),&(resources->bus_head));
-
-	rc = shpchp_resource_sort_and_combine(&(resources->mem_head));
-	rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head));
-	rc |= shpchp_resource_sort_and_combine(&(resources->io_head));
-	rc |= shpchp_resource_sort_and_combine(&(resources->bus_head));
-
-	return rc;
-}
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-kfree_resource_list(struct pci_resource **r)
-{
-	struct pci_resource *res, *tres;
-
-	res = *r;
-	*r = NULL;
-
-	while (res) {
-		tres = res;
-		res = res->next;
-		kfree(tres);
-	}
-}
-
-/**
- * shpchp_destroy_resource_list: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_resource_list(struct resource_lists *resources)
-{
-	kfree_resource_list(&(resources->io_head));
-	kfree_resource_list(&(resources->mem_head));
-	kfree_resource_list(&(resources->p_mem_head));
-	kfree_resource_list(&(resources->bus_head));
-}
-
-/**
- * shpchp_destroy_board_resources: put node back in the resource list
- * @resources: list to put nodes back
- */
-void shpchp_destroy_board_resources(struct pci_func * func)
-{
-	kfree_resource_list(&(func->io_head));
-	kfree_resource_list(&(func->mem_head));
-	kfree_resource_list(&(func->p_mem_head));
-	kfree_resource_list(&(func->bus_head));
-}
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index c9445eb..f5cfbf2 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -26,12 +26,9 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include "shpchp.h"
 
@@ -40,104 +37,60 @@
 
 static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct pci_dev *pci_dev;
-	struct controller *ctrl;
+	struct pci_dev *pdev;
 	char * out = buf;
-	int index;
-	struct pci_resource *res;
+	int index, busnr;
+	struct resource *res;
+	struct pci_bus *bus;
 
-	pci_dev = container_of (dev, struct pci_dev, dev);
-	ctrl = pci_get_drvdata(pci_dev);
+	pdev = container_of (dev, struct pci_dev, dev);
+	bus = pdev->subordinate;
 
 	out += sprintf(buf, "Free resources: memory\n");
-	index = 11;
-	res = ctrl->mem_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
+	for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+		res = bus->resource[index];
+		if (res && (res->flags & IORESOURCE_MEM) &&
+				!(res->flags & IORESOURCE_PREFETCH)) {
+			out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+					res->start, (res->end - res->start));
+		}
 	}
 	out += sprintf(out, "Free resources: prefetchable memory\n");
-	index = 11;
-	res = ctrl->p_mem_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
+	for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+		res = bus->resource[index];
+		if (res && (res->flags & IORESOURCE_MEM) &&
+			       (res->flags & IORESOURCE_PREFETCH)) {
+			out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+					res->start, (res->end - res->start));
+		}
 	}
 	out += sprintf(out, "Free resources: IO\n");
-	index = 11;
-	res = ctrl->io_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
+	for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
+		res = bus->resource[index];
+		if (res && (res->flags & IORESOURCE_IO)) {
+			out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
+					res->start, (res->end - res->start));
+		}
 	}
 	out += sprintf(out, "Free resources: bus numbers\n");
-	index = 11;
-	res = ctrl->bus_head;
-	while (res && index--) {
-		out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-		res = res->next;
+	for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
+		if (!pci_find_bus(pci_domain_nr(bus), busnr))
+			break;
 	}
+	if (busnr < bus->subordinate)
+		out += sprintf(out, "start = %8.8x, length = %8.8x\n",
+				busnr, (bus->subordinate - busnr));
 
 	return out - buf;
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pci_dev *pci_dev;
-	struct controller *ctrl;
-	char * out = buf;
-	int index;
-	struct pci_resource *res;
-	struct pci_func *new_slot;
-	struct slot *slot;
-
-	pci_dev = container_of (dev, struct pci_dev, dev);
-	ctrl = pci_get_drvdata(pci_dev);
-
-	slot=ctrl->slot;
-
-	while (slot) {
-		new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
-		if (!new_slot)
-			break;
-		out += sprintf(out, "assigned resources: memory\n");
-		index = 11;
-		res = new_slot->mem_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		out += sprintf(out, "assigned resources: prefetchable memory\n");
-		index = 11;
-		res = new_slot->p_mem_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		out += sprintf(out, "assigned resources: IO\n");
-		index = 11;
-		res = new_slot->io_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		out += sprintf(out, "assigned resources: bus numbers\n");
-		index = 11;
-		res = new_slot->bus_head;
-		while (res && index--) {
-			out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
-			res = res->next;
-		}
-		slot=slot->next;
-	}
-
-	return out - buf;
-}
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
-
 void shpchp_create_ctrl_files (struct controller *ctrl)
 {
 	device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
-	device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+}
+
+void shpchp_remove_ctrl_files(struct controller *ctrl)
+{
+	device_remove_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
 }
diff --git a/drivers/pci/hotplug/shpchprm.h b/drivers/pci/hotplug/shpchprm.h
deleted file mode 100644
index 057b192..0000000
--- a/drivers/pci/hotplug/shpchprm.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_H_
-#define _SHPCHPRM_H_
-
-#ifdef	CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-#include "shpchprm_legacy.h"
-#else
-#include "shpchprm_nonacpi.h"
-#endif
-
-int shpchprm_init(enum php_ctlr_type ct);
-void shpchprm_cleanup(void);
-int shpchprm_print_pirt(void);
-int shpchprm_find_available_resources(struct controller *ctrl);
-int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
-void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
-int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
-
-#ifdef	DEBUG
-#define RES_CHECK(this, bits)	\
-	{ if (((this) & (bits - 1))) \
-		printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
-#else
-#define RES_CHECK(this, bits)
-#endif
-
-#endif				/* _SHPCHPRM_H_ */
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index d37b316..17145e5 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -24,91 +24,19 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#ifdef	CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
 #include "shpchp.h"
-#include "shpchprm.h"
-
-#define	PCI_MAX_BUS		0x100
-#define	ACPI_STA_DEVICE_PRESENT	0x01
 
 #define	METHOD_NAME__SUN	"_SUN"
 #define	METHOD_NAME__HPP	"_HPP"
 #define	METHOD_NAME_OSHP	"OSHP"
 
-#define	PHP_RES_BUS		0xA0
-#define	PHP_RES_IO		0xA1
-#define	PHP_RES_MEM		0xA2
-#define	PHP_RES_PMEM		0xA3
-
-#define	BRIDGE_TYPE_P2P		0x00
-#define	BRIDGE_TYPE_HOST	0x01
-
-/* this should go to drivers/acpi/include/ */
-struct acpi__hpp {
-	u8	cache_line_size;
-	u8	latency_timer;
-	u8	enable_serr;
-	u8	enable_perr;
-};
-
-struct acpi_php_slot {
-	struct acpi_php_slot	*next;
-	struct acpi_bridge	*bridge;
-	acpi_handle		handle;
-	int	seg;
-	int	bus;
-	int	dev;
-	int	fun;
-	u32	sun;
-	struct pci_resource *mem_head;
-	struct pci_resource *p_mem_head;
-	struct pci_resource *io_head;
-	struct pci_resource *bus_head;
-	void	*slot_ops;	/* _STA, _EJx, etc */
-	struct slot *slot;
-};		/* per func */
-
-struct acpi_bridge {
-	struct acpi_bridge	*parent;
-	struct acpi_bridge	*next;
-	struct acpi_bridge	*child;
-	acpi_handle	handle;
-	int seg;
-	int pbus;				/* pdev->bus->number		*/
-	int pdevice;				/* PCI_SLOT(pdev->devfn)	*/
-	int pfunction;				/* PCI_DEVFN(pdev->devfn)	*/
-	int bus;				/* pdev->subordinate->number	*/
-	struct acpi__hpp		*_hpp;
-	struct acpi_php_slot	*slots;
-	struct pci_resource 	*tmem_head;	/* total from crs	*/
-	struct pci_resource 	*tp_mem_head;	/* total from crs	*/
-	struct pci_resource 	*tio_head;	/* total from crs	*/
-	struct pci_resource 	*tbus_head;	/* total from crs	*/
-	struct pci_resource 	*mem_head;	/* available	*/
-	struct pci_resource 	*p_mem_head;	/* available	*/
-	struct pci_resource 	*io_head;	/* available	*/
-	struct pci_resource 	*bus_head;	/* available	*/
-	int scanned;
-	int type;
-};
-
-static struct acpi_bridge *acpi_bridges_head;
-
 static u8 * acpi_path_name( acpi_handle	handle)
 {
 	acpi_status		status;
@@ -124,82 +52,43 @@
 		return path_name;	
 }
 
-static void acpi_get__hpp ( struct acpi_bridge	*ab);
-static void acpi_run_oshp ( struct acpi_bridge	*ab);
-
-static int acpi_add_slot_to_php_slots(
-	struct acpi_bridge	*ab,
-	int				bus_num,
-	acpi_handle		handle,
-	u32				adr,
-	u32				sun
-	)
-{
-	struct acpi_php_slot	*aps;
-	static long	samesun = -1;
-
-	aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
-	if (!aps) {
-		err ("acpi_shpchprm: alloc for aps fail\n");
-		return -1;
-	}
-	memset(aps, 0, sizeof(struct acpi_php_slot));
-
-	aps->handle = handle;
-	aps->bus = bus_num;
-	aps->dev = (adr >> 16) & 0xffff;
-	aps->fun = adr & 0xffff;
-	aps->sun = sun;
-
-	aps->next = ab->slots;	/* cling to the bridge */
-	aps->bridge = ab;
-	ab->slots = aps;
-
-	ab->scanned += 1;
-	if (!ab->_hpp)
-		acpi_get__hpp(ab);
-
-	acpi_run_oshp(ab);
-
-	if (sun != samesun) {
-		info("acpi_shpchprm:   Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg, 
-			aps->bus, aps->dev, aps->fun);
-		samesun = sun;
-	}
-	return 0;
-}
-
-static void acpi_get__hpp ( struct acpi_bridge	*ab)
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
 {
 	acpi_status		status;
 	u8			nui[4];
 	struct acpi_buffer	ret_buf = { 0, NULL};
 	union acpi_object	*ext_obj, *package;
-	u8			*path_name = acpi_path_name(ab->handle);
+	u8			*path_name = acpi_path_name(handle);
 	int			i, len = 0;
 
 	/* get _hpp */
-	status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+	status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
 	switch (status) {
 	case AE_BUFFER_OVERFLOW:
 		ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
 		if (!ret_buf.pointer) {
-			err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name);
-			return;
+			err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
+					path_name);
+			return AE_NO_MEMORY;
 		}
-		status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+		status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+				NULL, &ret_buf);
 		if (ACPI_SUCCESS(status))
 			break;
 	default:
 		if (ACPI_FAILURE(status)) {
-			err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status);
-			return;
+			dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+					path_name, status);
+			return status;
 		}
 	}
 
 	ext_obj = (union acpi_object *) ret_buf.pointer;
 	if (ext_obj->type != ACPI_TYPE_PACKAGE) {
-		err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name);
+		err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
+				path_name);
+		status = AE_ERROR;
 		goto free_and_return;
 	}
 
@@ -212,1353 +101,41 @@
 			nui[i] = (u8)ext_obj->integer.value;
 			break;
 		default:
-			err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name);
+			err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
+					path_name);
+			status = AE_ERROR;
 			goto free_and_return;
 		}
 	}
 
-	ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
-	if (!ab->_hpp) {
-		err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name);
-		goto free_and_return;
-	}
-	memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+	hpp->cache_line_size = nui[0];
+	hpp->latency_timer = nui[1];
+	hpp->enable_serr = nui[2];
+	hpp->enable_perr = nui[3];
 
-	ab->_hpp->cache_line_size	= nui[0];
-	ab->_hpp->latency_timer		= nui[1];
-	ab->_hpp->enable_serr		= nui[2];
-	ab->_hpp->enable_perr		= nui[3];
-
-	dbg("  _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
-	dbg("  _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
-	dbg("  _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
-	dbg("  _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
+	dbg("  _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+	dbg("  _HPP: latency timer  =0x%x\n", hpp->latency_timer);
+	dbg("  _HPP: enable SERR    =0x%x\n", hpp->enable_serr);
+	dbg("  _HPP: enable PERR    =0x%x\n", hpp->enable_perr);
 
 free_and_return:
 	kfree(ret_buf.pointer);
+	return status;
 }
 
-static void acpi_run_oshp ( struct acpi_bridge	*ab)
+static void acpi_run_oshp(acpi_handle handle)
 {
 	acpi_status		status;
-	u8			*path_name = acpi_path_name(ab->handle);
+	u8			*path_name = acpi_path_name(handle);
 
 	/* run OSHP */
-	status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
+	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
 	if (ACPI_FAILURE(status)) {
-		err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
-	} else
-		dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
-	return;
-}
-
-static acpi_status acpi_evaluate_crs(
-	acpi_handle		handle,
-	struct acpi_resource	**retbuf
-	)
-{
-	acpi_status		status;
-	struct acpi_buffer		crsbuf;
-	u8			*path_name = acpi_path_name(handle);
-
-	crsbuf.length  = 0;
-	crsbuf.pointer = NULL;
-
-	status = acpi_get_current_resources (handle, &crsbuf);
-
-	switch (status) {
-	case AE_BUFFER_OVERFLOW:
-		break;		/* found */
-	case AE_NOT_FOUND:
-		dbg("acpi_shpchprm:%s _CRS not found\n", path_name);
-		return status;
-	default:
-		err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status);
-		return status;
-	}
-
-	crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
-	if (!crsbuf.pointer) {
-		err ("acpi_shpchprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
-		return AE_NO_MEMORY;
-	}
-
-	status = acpi_get_current_resources (handle, &crsbuf);
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm: %s _CRS fail=0x%x.\n", path_name, status);
-		kfree(crsbuf.pointer);
-		return status;
-	}
-
-	*retbuf = crsbuf.pointer;
-
-	return status;
-}
-
-static void free_pci_resource ( struct pci_resource	*aprh)
-{
-	struct pci_resource	*res, *next;
-
-	for (res = aprh; res; res = next) {
-		next = res->next;
-		kfree(res);
-	}
-}
-
-static void print_pci_resource ( struct pci_resource	*aprh)
-{
-	struct pci_resource	*res;
-
-	for (res = aprh; res; res = res->next)
-		dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-static void print_slot_resources( struct acpi_php_slot	*aps)
-{
-	if (aps->bus_head) {
-		dbg("    BUS Resources:\n");
-		print_pci_resource (aps->bus_head);
-	}
-
-	if (aps->io_head) {
-		dbg("    IO Resources:\n");
-		print_pci_resource (aps->io_head);
-	}
-
-	if (aps->mem_head) {
-		dbg("    MEM Resources:\n");
-		print_pci_resource (aps->mem_head);
-	}
-
-	if (aps->p_mem_head) {
-		dbg("    PMEM Resources:\n");
-		print_pci_resource (aps->p_mem_head);
-	}
-}
-
-static void print_pci_resources( struct acpi_bridge	*ab)
-{
-	if (ab->tbus_head) {
-		dbg("    Total BUS Resources:\n");
-		print_pci_resource (ab->tbus_head);
-	}
-	if (ab->bus_head) {
-		dbg("    BUS Resources:\n");
-		print_pci_resource (ab->bus_head);
-	}
-
-	if (ab->tio_head) {
-		dbg("    Total IO Resources:\n");
-		print_pci_resource (ab->tio_head);
-	}
-	if (ab->io_head) {
-		dbg("    IO Resources:\n");
-		print_pci_resource (ab->io_head);
-	}
-
-	if (ab->tmem_head) {
-		dbg("    Total MEM Resources:\n");
-		print_pci_resource (ab->tmem_head);
-	}
-	if (ab->mem_head) {
-		dbg("    MEM Resources:\n");
-		print_pci_resource (ab->mem_head);
-	}
-
-	if (ab->tp_mem_head) {
-		dbg("    Total PMEM Resources:\n");
-		print_pci_resource (ab->tp_mem_head);
-	}
-	if (ab->p_mem_head) {
-		dbg("    PMEM Resources:\n");
-		print_pci_resource (ab->p_mem_head);
-	}
-	if (ab->_hpp) {
-		dbg("    _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
-		dbg("    _HPP: latency timer  =0x%x\n", ab->_hpp->latency_timer);
-		dbg("    _HPP: enable SERR    =0x%x\n", ab->_hpp->enable_serr);
-		dbg("    _HPP: enable PERR    =0x%x\n", ab->_hpp->enable_perr);
-	}
-}
-
-static int shpchprm_delete_resource(
-	struct pci_resource **aprh,
-	ulong base,
-	ulong size)
-{
-	struct pci_resource *res;
-	struct pci_resource *prevnode;
-	struct pci_resource *split_node;
-	ulong tbase;
-
-	shpchp_resource_sort_and_combine(aprh);
-
-	for (res = *aprh; res; res = res->next) {
-		if (res->base > base)
-			continue;
-
-		if ((res->base + res->length) < (base + size))
-			continue;
-
-		if (res->base < base) {
-			tbase = base;
-
-			if ((res->length - (tbase - res->base)) < size)
-				continue;
-
-			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!split_node)
-				return -ENOMEM;
-
-			split_node->base = res->base;
-			split_node->length = tbase - res->base;
-			res->base = tbase;
-			res->length -= split_node->length;
-
-			split_node->next = res->next;
-			res->next = split_node;
-		}
-
-		if (res->length >= size) {
-			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!split_node)
-				return -ENOMEM;
-
-			split_node->base = res->base + size;
-			split_node->length = res->length - size;
-			res->length = size;
-
-			split_node->next = res->next;
-			res->next = split_node;
-		}
-
-		if (*aprh == res) {
-			*aprh = res->next;
-		} else {
-			prevnode = *aprh;
-			while (prevnode->next != res)
-				prevnode = prevnode->next;
-
-			prevnode->next = res->next;
-		}
-		res->next = NULL;
-		kfree(res);
-		break;
-	}
-
-	return 0;
-}
-
-static int shpchprm_delete_resources(
-	struct pci_resource **aprh,
-	struct pci_resource *this
-	)
-{
-	struct pci_resource *res;
-
-	for (res = this; res; res = res->next)
-		shpchprm_delete_resource(aprh, res->base, res->length);
-
-	return 0;
-}
-
-static int shpchprm_add_resource(
-	struct pci_resource **aprh,
-	ulong base,
-	ulong size)
-{
-	struct pci_resource *res;
-
-	for (res = *aprh; res; res = res->next) {
-		if ((res->base + res->length) == base) {
-			res->length += size;
-			size = 0L;
-			break;
-		}
-		if (res->next == *aprh)
-			break;
-	}
-
-	if (size) {
-		res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-		if (!res) {
-			err ("acpi_shpchprm: alloc for res fail\n");
-			return -ENOMEM;
-		}
-		memset(res, 0, sizeof (struct pci_resource));
-
-		res->base = base;
-		res->length = size;
-		res->next = *aprh;
-		*aprh = res;
-	}
-
-	return 0;
-}
-
-static int shpchprm_add_resources(
-	struct pci_resource **aprh,
-	struct pci_resource *this
-	)
-{
-	struct pci_resource *res;
-	int	rc = 0;
-
-	for (res = this; res && !rc; res = res->next)
-		rc = shpchprm_add_resource(aprh, res->base, res->length);
-
-	return rc;
-}
-
-static void acpi_parse_io (
-	struct acpi_bridge		*ab,
-	union acpi_resource_data	*data
-	)
-{
-	struct acpi_resource_io	*dataio;
-	dataio = (struct acpi_resource_io *) data;
-
-	dbg("Io Resource\n");
-	dbg("  %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
-	dbg("  Range minimum base: %08X\n", dataio->min_base_address);
-	dbg("  Range maximum base: %08X\n", dataio->max_base_address);
-	dbg("  Alignment: %08X\n", dataio->alignment);
-	dbg("  Range Length: %08X\n", dataio->range_length);
-}
-
-static void acpi_parse_fixed_io (
-	struct acpi_bridge		*ab,
-	union acpi_resource_data	*data
-	)
-{
-	struct acpi_resource_fixed_io  *datafio;
-	datafio = (struct acpi_resource_fixed_io *) data;
-
-	dbg("Fixed Io Resource\n");
-	dbg("  Range base address: %08X", datafio->base_address);
-	dbg("  Range length: %08X", datafio->range_length);
-}
-
-static void acpi_parse_address16_32 (
-	struct acpi_bridge		*ab,
-	union acpi_resource_data	*data,
-	acpi_resource_type		id
-	)
-{
-	/* 
-	 * acpi_resource_address16 == acpi_resource_address32
-	 * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
-	 */
-	struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
-	struct pci_resource **aprh, **tprh;
-
-	if (id == ACPI_RSTYPE_ADDRESS16)
-		dbg("acpi_shpchprm:16-Bit Address Space Resource\n");
-	else
-		dbg("acpi_shpchprm:32-Bit Address Space Resource\n");
-
-	switch (data32->resource_type) {
-	case ACPI_MEMORY_RANGE: 
-		dbg("  Resource Type: Memory Range\n");
-		aprh = &ab->mem_head;
-		tprh = &ab->tmem_head;
-
-		switch (data32->attribute.memory.cache_attribute) {
-		case ACPI_NON_CACHEABLE_MEMORY:
-			dbg("  Type Specific: Noncacheable memory\n");
-			break; 
-		case ACPI_CACHABLE_MEMORY:
-			dbg("  Type Specific: Cacheable memory\n");
-			break; 
-		case ACPI_WRITE_COMBINING_MEMORY:
-			dbg("  Type Specific: Write-combining memory\n");
-			break; 
-		case ACPI_PREFETCHABLE_MEMORY:
-			aprh = &ab->p_mem_head;
-			dbg("  Type Specific: Prefetchable memory\n");
-			break; 
-		default:
-			dbg("  Type Specific: Invalid cache attribute\n");
-			break;
-		}
-
-		dbg("  Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
-		break;
-
-	case ACPI_IO_RANGE: 
-		dbg("  Resource Type: I/O Range\n");
-		aprh = &ab->io_head;
-		tprh = &ab->tio_head;
-
-		switch (data32->attribute.io.range_attribute) {
-		case ACPI_NON_ISA_ONLY_RANGES:
-			dbg("  Type Specific: Non-ISA Io Addresses\n");
-			break; 
-		case ACPI_ISA_ONLY_RANGES:
-			dbg("  Type Specific: ISA Io Addresses\n");
-			break; 
-		case ACPI_ENTIRE_RANGE:
-			dbg("  Type Specific: ISA and non-ISA Io Addresses\n");
-			break; 
-		default:
-			dbg("  Type Specific: Invalid range attribute\n");
-			break;
-		}
-		break;
-
-	case ACPI_BUS_NUMBER_RANGE: 
-		dbg("  Resource Type: Bus Number Range(fixed)\n");
-		/* fixup to be compatible with the rest of php driver */
-		data32->min_address_range++;
-		data32->address_length--;
-		aprh = &ab->bus_head;
-		tprh = &ab->tbus_head;
-		break; 
-	default: 
-		dbg("  Resource Type: Invalid resource type. Exiting.\n");
-		return;
-	}
-
-	dbg("  Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
-	dbg("  %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
-	dbg("  Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
-	dbg("  Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
-	dbg("  Granularity: %08X\n", data32->granularity);
-	dbg("  Address range min: %08X\n", data32->min_address_range);
-	dbg("  Address range max: %08X\n", data32->max_address_range);
-	dbg("  Address translation offset: %08X\n", data32->address_translation_offset);
-	dbg("  Address Length: %08X\n", data32->address_length);
-
-	if (0xFF != data32->resource_source.index) {
-		dbg("  Resource Source Index: %X\n", data32->resource_source.index);
-		/* dbg("  Resource Source: %s\n", data32->resource_source.string_ptr); */
-	}
-
-	shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length);
-}
-
-static acpi_status acpi_parse_crs(
-	struct acpi_bridge	*ab,
-	struct acpi_resource	*crsbuf
-	)
-{
-	acpi_status		status = AE_OK;
-	struct acpi_resource	*resource = crsbuf;
-	u8			count = 0;
-	u8			done = 0;
-
-	while (!done) {
-		dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
-		switch (resource->id) {
-		case ACPI_RSTYPE_IRQ:
-			dbg("Irq -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_DMA:
-			dbg("DMA -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_START_DPF:
-			dbg("Start DPF -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_END_DPF:
-			dbg("End DPF -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_IO:
-			acpi_parse_io (ab, &resource->data);
-			break; 
-		case ACPI_RSTYPE_FIXED_IO:
-			acpi_parse_fixed_io (ab, &resource->data);
-			break; 
-		case ACPI_RSTYPE_VENDOR:
-			dbg("Vendor -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_END_TAG:
-			dbg("End_tag -------- Resource\n");
-			done = 1;
-			break; 
-		case ACPI_RSTYPE_MEM24:
-			dbg("Mem24 -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_MEM32:
-			dbg("Mem32 -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_FIXED_MEM32:
-			dbg("Fixed Mem32 -------- Resource\n");
-			break; 
-		case ACPI_RSTYPE_ADDRESS16:
-			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
-			break; 
-		case ACPI_RSTYPE_ADDRESS32:
-			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
-			break; 
-		case ACPI_RSTYPE_ADDRESS64:
-			info("Address64 -------- Resource unparsed\n");
-			break; 
-		case ACPI_RSTYPE_EXT_IRQ:
-			dbg("Ext Irq -------- Resource\n");
-			break; 
-		default:
-			dbg("Invalid -------- resource type 0x%x\n", resource->id);
-			break;
-		}
-
-		resource = (struct acpi_resource *) ((char *)resource + resource->length);
-	}
-
-	return status;
-}
-
-static acpi_status acpi_get_crs( struct acpi_bridge	*ab)
-{
-	acpi_status		status;
-	struct acpi_resource	*crsbuf;
-
-	status = acpi_evaluate_crs(ab->handle, &crsbuf);
-	if (ACPI_SUCCESS(status)) {
-		status = acpi_parse_crs(ab, crsbuf);
-		kfree(crsbuf);
-
-		shpchp_resource_sort_and_combine(&ab->bus_head);
-		shpchp_resource_sort_and_combine(&ab->io_head);
-		shpchp_resource_sort_and_combine(&ab->mem_head);
-		shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
-		shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
-		shpchprm_add_resources (&ab->tio_head, ab->io_head);
-		shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
-		shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-	}
-
-	return status;
-}
-
-/* find acpi_bridge downword from ab.  */
-static struct acpi_bridge *
-find_acpi_bridge_by_bus(
-	struct acpi_bridge *ab,
-	int seg,
-	int bus		/* pdev->subordinate->number */
-	)
-{
-	struct acpi_bridge	*lab = NULL;
-
-	if (!ab)
-		return NULL;
-
-	if ((ab->bus == bus) && (ab->seg == seg))
-		return ab;
-
-	if (ab->child)
-		lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
-
-	if (!lab)
-	if (ab->next)
-		lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
-
-	return lab;
-}
-
-/*
- * Build a device tree of ACPI PCI Bridges
- */
-static void shpchprm_acpi_register_a_bridge (
-	struct acpi_bridge	**head,
-	struct acpi_bridge	*pab,	/* parent bridge to which child bridge is added */
-	struct acpi_bridge	*cab	/* child bridge to add */
-	)
-{
-	struct acpi_bridge	*lpab;
-	struct acpi_bridge	*lcab;
-
-	lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
-	if (!lpab) {
-		if (!(pab->type & BRIDGE_TYPE_HOST))
-			warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
-		pab->next = *head;
-		*head = pab;
-		lpab = pab;
-	}
-
-	if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
-		return;
-
-	lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
-	if (lcab) {
-		if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
-			err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
-		return;
-	} else
-		lcab = cab;
-
-	lcab->parent = lpab;
-	lcab->next = lpab->child;
-	lpab->child = lcab;
-}
-
-static acpi_status shpchprm_acpi_build_php_slots_callback(
-	acpi_handle	handle,
-	u32		Level,
-	void		*context,
-	void		**retval
-	)
-{
-	ulong		bus_num;
-	ulong		seg_num;
-	ulong		sun, adr;
-	ulong		padr = 0;
-	acpi_handle		phandle = NULL;
-	struct acpi_bridge	*pab = (struct acpi_bridge *)context;
-	struct acpi_bridge	*lab;
-	acpi_status		status;
-	u8			*path_name = acpi_path_name(handle);
-
-	/* get _SUN */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
-	switch(status) {
-	case AE_NOT_FOUND:
-		return AE_OK;
-	default:
-		if (ACPI_FAILURE(status)) {
-			err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);
-			return status;
-		}
-	}
-
-	/* get _ADR. _ADR must exist if _SUN exists */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
-		return status;
-	}
-
-	dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
-
-	status = acpi_get_parent(handle, &phandle);
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);
-		return (status);
-	}
-
-	bus_num = pab->bus;
-	seg_num = pab->seg;
-
-	if (pab->bus == bus_num) {
-		lab = pab;
+		err("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
+				status);
 	} else {
-		dbg("WARN: pab is not parent\n");
-		lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
-		if (!lab) {
-			dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
-			lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
-			if (!lab) {
-				err("acpi_shpchprm: alloc for ab fail\n");
-				return AE_NO_MEMORY;
-			}
-			memset(lab, 0, sizeof(struct acpi_bridge));
-
-			lab->handle = phandle;
-			lab->pbus = pab->bus;
-			lab->pdevice = (int)(padr >> 16) & 0xffff;
-			lab->pfunction = (int)(padr & 0xffff);
-			lab->bus = (int)bus_num;
-			lab->scanned = 0;
-			lab->type = BRIDGE_TYPE_P2P;
-
-			shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
-		} else
-			dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
+		dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
 	}
-
-	acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
-	return (status);
-}
-
-static int shpchprm_acpi_build_php_slots(
-	struct acpi_bridge	*ab,
-	u32			depth
-	)
-{
-	acpi_status	status;
-	u8		*path_name = acpi_path_name(ab->handle);
-
-	/* Walk down this pci bridge to get _SUNs if any behind P2P */
-	status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
-				ab->handle,
-				depth,
-				shpchprm_acpi_build_php_slots_callback,
-				ab,
-				NULL );
-	if (ACPI_FAILURE(status)) {
-		dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void build_a_bridge(
-	struct acpi_bridge	*pab,
-	struct acpi_bridge	*ab
-	)
-{
-	u8		*path_name = acpi_path_name(ab->handle);
-
-	shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
-
-	switch (ab->type) {
-	case BRIDGE_TYPE_HOST:
-		dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x)    on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
-			ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
-		break;
-	case BRIDGE_TYPE_P2P:
-		dbg("acpi_shpchprm: Registered PCI  P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
-			ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
-		break;
-	};
-
-	/* build any immediate PHP slots under this pci bridge */
-	shpchprm_acpi_build_php_slots(ab, 1);
-}
-
-static struct acpi_bridge * add_p2p_bridge(
-	acpi_handle handle,
-	struct acpi_bridge	*pab,	/* parent */
-	ulong	adr
-	)
-{
-	struct acpi_bridge	*ab;
-	struct pci_dev	*pdev;
-	ulong		devnum, funcnum;
-	u8			*path_name = acpi_path_name(handle);
-
-	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
-	if (!ab) {
-		err("acpi_shpchprm: alloc for ab fail\n");
-		return NULL;
-	}
-	memset(ab, 0, sizeof(struct acpi_bridge));
-
-	devnum = (adr >> 16) & 0xffff;
-	funcnum = adr & 0xffff;
-
-	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
-	if (!pdev || !pdev->subordinate) {
-		err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);
-		kfree(ab);
-		return NULL;
-	}
-
-	ab->handle = handle;
-	ab->seg = pab->seg;
-	ab->pbus = pab->bus;		/* or pdev->bus->number */
-	ab->pdevice = devnum;		/* or PCI_SLOT(pdev->devfn) */
-	ab->pfunction = funcnum;	/* or PCI_FUNC(pdev->devfn) */
-	ab->bus = pdev->subordinate->number;
-	ab->scanned = 0;
-	ab->type = BRIDGE_TYPE_P2P;
-
-	dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
-		pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-		pab->bus, (u32)devnum, (u32)funcnum, path_name);
-
-	build_a_bridge(pab, ab);
-
-	return ab;
-}
-
-static acpi_status scan_p2p_bridge(
-	acpi_handle		handle,
-	u32			Level,
-	void			*context,
-	void			**retval
-	)
-{
-	struct acpi_bridge	*pab = (struct acpi_bridge *)context;
-	struct acpi_bridge	*ab;
-	acpi_status		status;
-	ulong		adr = 0;
-	u8			*path_name = acpi_path_name(handle);
-	ulong		devnum, funcnum;
-	struct pci_dev	*pdev;
-
-	/* get device, function */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
-	if (ACPI_FAILURE(status)) {
-		if (status != AE_NOT_FOUND)
-			err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
-		return AE_OK;
-	}
-
-	devnum = (adr >> 16) & 0xffff;
-	funcnum = adr & 0xffff;
-
-	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
-	if (!pdev)
-		return AE_OK;
-	if (!pdev->subordinate)
-		return AE_OK;
-
-	ab = add_p2p_bridge(handle, pab, adr);
-	if (ab) {
-		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
-					handle,
-					(u32)1,
-					scan_p2p_bridge,
-					ab,
-					NULL);
-		if (ACPI_FAILURE(status))
-			dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
-	}
-
-	return AE_OK;
-}
-
-static struct acpi_bridge * add_host_bridge(
-	acpi_handle handle,
-	ulong	segnum,
-	ulong	busnum
-	)
-{
-	ulong			adr = 0;
-	acpi_status		status;
-	struct acpi_bridge	*ab;
-	u8			*path_name = acpi_path_name(handle);
-
-	/* get device, function: host br adr is always 0000 though.  */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);
-		return NULL;
-	}
-	dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum, 
-		(u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
-
-	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
-	if (!ab) {
-		err("acpi_shpchprm: alloc for ab fail\n");
-		return NULL;
-	}
-	memset(ab, 0, sizeof(struct acpi_bridge));
-
-	ab->handle = handle;
-	ab->seg = (int)segnum;
-	ab->bus = ab->pbus = (int)busnum;
-	ab->pdevice = (int)(adr >> 16) & 0xffff;
-	ab->pfunction = (int)(adr & 0xffff);
-	ab->scanned = 0;
-	ab->type = BRIDGE_TYPE_HOST;
-
-	/* get root pci bridge's current resources */
-	status = acpi_get_crs(ab);
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
-		kfree(ab);
-		return NULL;
-	}
-	build_a_bridge(ab, ab);
-
-	return ab;
-}
-
-static acpi_status acpi_scan_from_root_pci_callback (
-	acpi_handle	handle,
-	u32			Level,
-	void		*context,
-	void		**retval
-	)
-{
-	ulong		segnum = 0;
-	ulong		busnum = 0;
-	acpi_status		status;
-	struct acpi_bridge	*ab;
-	u8			*path_name = acpi_path_name(handle);
-
-	/* get bus number of this pci root bridge */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
-	if (ACPI_FAILURE(status)) {
-		if (status != AE_NOT_FOUND) {
-			err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
-			return status;
-		}
-		segnum = 0;
-	}
-
-	/* get bus number of this pci root bridge */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
-		return (status);
-	}
-
-	ab = add_host_bridge(handle, segnum, busnum);
-	if (ab) {
-		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
-					handle,
-					1,
-					scan_p2p_bridge,
-					ab,
-					NULL);
-		if (ACPI_FAILURE(status))
-			dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);
-	}
-
-	return AE_OK;
-}
-
-static int shpchprm_acpi_scan_pci (void)
-{
-	acpi_status	status;
-
-	/*
-	 * TBD: traverse LDM device tree with the help of
-	 *  unified ACPI augmented for php device population.
-	 */
-	status = acpi_get_devices ( PCI_ROOT_HID_STRING,
-				acpi_scan_from_root_pci_callback,
-				NULL,
-				NULL );
-	if (ACPI_FAILURE(status)) {
-		err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);
-		return -1;
-	}
-
-	return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctlr_type)
-{
-	int	rc;
-
-	if (ctlr_type != PCI)
-		return -ENODEV;
-
-	dbg("shpchprm ACPI init <enter>\n");
-	acpi_bridges_head = NULL;
-
-	/* construct PCI bus:device tree of acpi_handles */
-	rc = shpchprm_acpi_scan_pci();
-	if (rc)
-		return rc;
-
-	dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");
-	return rc;
-}
-
-static void free_a_slot(struct acpi_php_slot *aps)
-{
-	dbg("        free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
-
-	free_pci_resource (aps->io_head);
-	free_pci_resource (aps->bus_head);
-	free_pci_resource (aps->mem_head);
-	free_pci_resource (aps->p_mem_head);
-
-	kfree(aps);
-}
-
-static void free_a_bridge( struct acpi_bridge	*ab)
-{
-	struct acpi_php_slot	*aps, *next;
-
-	switch (ab->type) {
-	case BRIDGE_TYPE_HOST:
-		dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
-			ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
-		break;
-	case BRIDGE_TYPE_P2P:
-		dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
-			ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
-		break;
-	};
-
-	/* free slots first */
-	for (aps = ab->slots; aps; aps = next) {
-		next = aps->next;
-		free_a_slot(aps);
-	}
-
-	free_pci_resource (ab->io_head);
-	free_pci_resource (ab->tio_head);
-	free_pci_resource (ab->bus_head);
-	free_pci_resource (ab->tbus_head);
-	free_pci_resource (ab->mem_head);
-	free_pci_resource (ab->tmem_head);
-	free_pci_resource (ab->p_mem_head);
-	free_pci_resource (ab->tp_mem_head);
-
-	kfree(ab);
-}
-
-static void shpchprm_free_bridges ( struct acpi_bridge	*ab)
-{
-	if (!ab)
-		return;
-
-	if (ab->child)
-		shpchprm_free_bridges (ab->child);
-
-	if (ab->next)
-		shpchprm_free_bridges (ab->next);
-
-	free_a_bridge(ab);
-}
-
-void shpchprm_cleanup(void)
-{
-	shpchprm_free_bridges (acpi_bridges_head);
-}
-
-static int get_number_of_slots (
-	struct acpi_bridge	*ab,
-	int				selfonly
-	)
-{
-	struct acpi_php_slot	*aps;
-	int	prev_slot = -1;
-	int	slot_num = 0;
-
-	for ( aps = ab->slots; aps; aps = aps->next)
-		if (aps->dev != prev_slot) {
-			prev_slot = aps->dev;
-			slot_num++;
-		}
-
-	if (ab->child)
-		slot_num += get_number_of_slots (ab->child, 0);
-
-	if (selfonly)
-		return slot_num;
-
-	if (ab->next)
-		slot_num += get_number_of_slots (ab->next, 0);
-
-	return slot_num;
-}
-
-static int print_acpi_resources (struct acpi_bridge	*ab)
-{
-	struct acpi_php_slot	*aps;
-	int	i;
-
-	switch (ab->type) {
-	case BRIDGE_TYPE_HOST:
-		dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
-		break;
-	case BRIDGE_TYPE_P2P:
-		dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
-		break;
-	};
-
-	print_pci_resources (ab);
-
-	for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
-		if (aps->dev == i)
-			continue;
-		dbg("  Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-		print_slot_resources(aps);
-		i = aps->dev;
-	}
-
-	if (ab->child)
-		print_acpi_resources (ab->child);
-
-	if (ab->next)
-		print_acpi_resources (ab->next);
-
-	return 0;
-}
-
-int shpchprm_print_pirt(void)
-{
-	dbg("SHPCHPRM ACPI Slots\n");
-	if (acpi_bridges_head)
-		print_acpi_resources (acpi_bridges_head);
-	return 0;
-}
-
-static struct acpi_php_slot * get_acpi_slot (
-	struct acpi_bridge *ab,
-	u32 sun
-	)
-{
-	struct acpi_php_slot	*aps = NULL;
-
-	for ( aps = ab->slots; aps; aps = aps->next)
-		if (aps->sun == sun)
-			return aps;
-
-	if (!aps && ab->child) {
-		aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
-		if (aps)
-			return aps;
-	}
-
-	if (!aps && ab->next) {
-		aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
-		if (aps)
-			return aps;
-	}
-
-	return aps;
-
-}
-
-#if 0
-static void * shpchprm_get_slot(struct slot *slot)
-{
-	struct acpi_bridge	*ab = acpi_bridges_head;
-	struct acpi_php_slot	*aps = get_acpi_slot (ab, slot->number);
-
-	aps->slot = slot;
-
-	dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-
-	return (void *)aps;
-}
-#endif
-
-static void shpchprm_dump_func_res( struct pci_func *fun)
-{
-	struct pci_func *func = fun;
-
-	if (func->bus_head) {
-		dbg(":    BUS Resources:\n");
-		print_pci_resource (func->bus_head);
-	}
-	if (func->io_head) {
-		dbg(":    IO Resources:\n");
-		print_pci_resource (func->io_head);
-	}
-	if (func->mem_head) {
-		dbg(":    MEM Resources:\n");
-		print_pci_resource (func->mem_head);
-	}
-	if (func->p_mem_head) {
-		dbg(":    PMEM Resources:\n");
-		print_pci_resource (func->p_mem_head);
-	}
-}
-
-static void shpchprm_dump_ctrl_res( struct controller *ctlr)
-{
-	struct controller *ctrl = ctlr;
-
-	if (ctrl->bus_head) {
-		dbg(":    BUS Resources:\n");
-		print_pci_resource (ctrl->bus_head);
-	}
-	if (ctrl->io_head) {
-		dbg(":    IO Resources:\n");
-		print_pci_resource (ctrl->io_head);
-	}
-	if (ctrl->mem_head) {
-		dbg(":    MEM Resources:\n");
-		print_pci_resource (ctrl->mem_head);
-	}
-	if (ctrl->p_mem_head) {
-		dbg(":    PMEM Resources:\n");
-		print_pci_resource (ctrl->p_mem_head);
-	}
-}
-
-static int shpchprm_get_used_resources (
-	struct controller *ctrl,
-	struct pci_func *func
-	)
-{
-	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int configure_existing_function(
-	struct controller *ctrl,
-	struct pci_func *func
-	)
-{
-	int rc;
-
-	/* see how much resources the func has used. */
-	rc = shpchprm_get_used_resources (ctrl, func);
-
-	if (!rc) {
-		/* subtract the resources used by the func from ctrl resources */
-		rc  = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);
-		rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);
-		rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);
-		rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
-		if (rc)
-			warn("aCEF: cannot del used resources\n");
-	} else
-		err("aCEF: cannot get used resources\n");
-
-	return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
-	struct pci_func *func, new_func;
-	int busn = ctrl->slot_bus;
-	int devn, funn;
-	u32	vid;
-
-	for (devn = 0; devn < 32; devn++) {
-		for (funn = 0; funn < 8; funn++) {
-			/*
-			if (devn == ctrl->device && funn == ctrl->function)
-				continue;
-			*/
-			/* find out if this entry is for an occupied slot */
-			vid = 0xFFFFFFFF;
-			pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
-			if (vid != 0xFFFFFFFF) {
-				func = shpchp_slot_find(busn, devn, funn);
-				if (!func) {
-					memset(&new_func, 0, sizeof(struct pci_func));
-					new_func.bus = busn;
-					new_func.device = devn;
-					new_func.function = funn;
-					new_func.is_a_board = 1;
-					configure_existing_function(ctrl, &new_func);
-					shpchprm_dump_func_res(&new_func);
-				} else {
-					configure_existing_function(ctrl, func);
-					shpchprm_dump_func_res(func);
-				}
-				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int bind_pci_resources(
-	struct controller 	*ctrl,
-	struct acpi_bridge	*ab
-	)
-{
-	int	status = 0;
-
-	if (ab->bus_head) {
-		dbg("bapr:  BUS Resources add on PCI 0x%x\n", ab->bus);
-		status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);
-		if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head))
-			warn("bapr:  cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
-		if (status) {
-			err("bapr:  BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-			return status;
-		}
-	} else
-		info("bapr:  No BUS Resource on PCI 0x%x.\n", ab->bus);
-
-	if (ab->io_head) {
-		dbg("bapr:  IO Resources add on PCI 0x%x\n", ab->bus);
-		status = shpchprm_add_resources (&ctrl->io_head, ab->io_head);
-		if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head))
-			warn("bapr:  cannot sub IO Resource on PCI 0x%x\n", ab->bus);
-		if (status) {
-			err("bapr:  IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-			return status;
-		}
-	} else
-		info("bapr:  No  IO Resource on PCI 0x%x.\n", ab->bus);
-
-	if (ab->mem_head) {
-		dbg("bapr:  MEM Resources add on PCI 0x%x\n", ab->bus);
-		status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);
-		if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head))
-			warn("bapr:  cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
-		if (status) {
-			err("bapr:  MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-			return status;
-		}
-	} else
-		info("bapr:  No MEM Resource on PCI 0x%x.\n", ab->bus);
-
-	if (ab->p_mem_head) {
-		dbg("bapr:  PMEM Resources add on PCI 0x%x\n", ab->bus);
-		status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
-		if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
-			warn("bapr:  cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
-		if (status) {
-			err("bapr:  PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
-			return status;
-		}
-	} else
-		info("bapr:  No PMEM Resource on PCI 0x%x.\n", ab->bus);
-
-	return status;
-}
-
-static int no_pci_resources( struct acpi_bridge *ab)
-{
-	return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
-}
-
-static int find_pci_bridge_resources (
-	struct controller *ctrl,
-	struct acpi_bridge *ab
-	)
-{
-	int	rc = 0;
-	struct pci_func func;
-
-	memset(&func, 0, sizeof(struct pci_func));
-
-	func.bus = ab->pbus;
-	func.device = ab->pdevice;
-	func.function = ab->pfunction;
-	func.is_a_board = 1;
-
-	/* Get used resources for this PCI bridge */
-	rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-
-	ab->io_head = func.io_head;
-	ab->mem_head = func.mem_head;
-	ab->p_mem_head = func.p_mem_head;
-	ab->bus_head = func.bus_head;
-	if (ab->bus_head)
-		shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1);
-
-	return rc;
-}
-
-static int get_pci_resources_from_bridge(
-	struct controller *ctrl,
-	struct acpi_bridge *ab
-	)
-{
-	int	rc = 0;
-
-	dbg("grfb:  Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
-
-	rc = find_pci_bridge_resources (ctrl, ab);
-
-	shpchp_resource_sort_and_combine(&ab->bus_head);
-	shpchp_resource_sort_and_combine(&ab->io_head);
-	shpchp_resource_sort_and_combine(&ab->mem_head);
-	shpchp_resource_sort_and_combine(&ab->p_mem_head);
-
-	shpchprm_add_resources (&ab->tbus_head, ab->bus_head);
-	shpchprm_add_resources (&ab->tio_head, ab->io_head);
-	shpchprm_add_resources (&ab->tmem_head, ab->mem_head);
-	shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-
-	return rc;
-}
-
-static int get_pci_resources(
-	struct controller	*ctrl,
-	struct acpi_bridge	*ab
-	)
-{
-	int	rc = 0;
-
-	if (no_pci_resources(ab)) {
-		dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
-		rc = get_pci_resources_from_bridge(ctrl, ab);
-	}
-
-	return rc;
 }
 
 int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
@@ -1570,144 +147,40 @@
 	return 0;
 }
 
-/*
- * Get resources for this ctrl.
- *  1. get total resources from ACPI _CRS or bridge (this ctrl)
- *  2. find used resources of existing adapters
- *	3. subtract used resources from total resources
- */
-int shpchprm_find_available_resources( struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-	int rc = 0;
-	struct acpi_bridge	*ab;
-
-	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
-	if (!ab) {
-		err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
-		return -1;
-	}
-	if (no_pci_resources(ab)) {
-		rc = get_pci_resources(ctrl, ab);
-		if (rc) {
-			err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number);
-			return -1;
-		}
-	}
-
-	rc = bind_pci_resources(ctrl, ab);
-	dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
-	shpchprm_dump_ctrl_res(ctrl);
-
-	bind_pci_resources_to_slots (ctrl);
-
-	dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
-	shpchprm_dump_ctrl_res(ctrl);
-
-	return rc;
+	/*
+	 * OSHP is an optional ACPI firmware control method. If present,
+	 * we need to run it to inform BIOS that we will control SHPC
+	 * hardware from now on.
+	 */
+	acpi_handle handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+	if (!handle)
+		return;
+	acpi_run_oshp(handle);
 }
 
-int shpchprm_set_hpp(
-	struct controller *ctrl,
-	struct pci_func *func,
-	u8	card_type
-	)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+		struct hotplug_params *hpp)
 {
-	struct acpi_bridge	*ab;
-	struct pci_bus lpci_bus, *pci_bus;
-	int				rc = 0;
-	unsigned int	devfn;
-	u8				cls= 0x08;	/* default cache line size	*/
-	u8				lt = 0x40;	/* default latency timer	*/
-	u8				ep = 0;
-	u8				es = 0;
+	acpi_status status = AE_NOT_FOUND;
+	struct pci_dev *pdev = dev;
 
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
-
-	if (ab) {
-		if (ab->_hpp) {
-			lt  = (u8)ab->_hpp->latency_timer;
-			cls = (u8)ab->_hpp->cache_line_size;
-			ep  = (u8)ab->_hpp->enable_perr;
-			es  = (u8)ab->_hpp->enable_serr;
-		} else
-			dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-	} else
-		dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-
-
-	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-		/* set subordinate Latency Timer */
-		rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
-	}
-
-	/* set base Latency Timer */
-	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
-	dbg("  set latency timer  =0x%02x: %x\n", lt, rc);
-
-	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
-	dbg("  set cache_line_size=0x%02x: %x\n", cls, rc);
-
-	return rc;
-}
-
-void shpchprm_enable_card(
-	struct controller *ctrl,
-	struct pci_func *func,
-	u8 card_type)
-{
-	u16 command, cmd, bcommand, bcmd;
-	struct pci_bus lpci_bus, *pci_bus;
-	struct acpi_bridge	*ab;
-	unsigned int devfn;
-	int rc;
-
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
-	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-	}
-
-	cmd = command  = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
-		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-	bcmd = bcommand  = bcommand | PCI_BRIDGE_CTL_NO_ISA;
-
-	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
-	if (ab) {
-		if (ab->_hpp) {
-			if (ab->_hpp->enable_perr) {
-				command |= PCI_COMMAND_PARITY;
-				bcommand |= PCI_BRIDGE_CTL_PARITY;
-			} else {
-				command &= ~PCI_COMMAND_PARITY;
-				bcommand &= ~PCI_BRIDGE_CTL_PARITY;
-			}
-			if (ab->_hpp->enable_serr) {
-				command |= PCI_COMMAND_SERR;
-				bcommand |= PCI_BRIDGE_CTL_SERR;
-			} else {
-				command &= ~PCI_COMMAND_SERR;
-				bcommand &= ~PCI_BRIDGE_CTL_SERR;
-			}
-		} else
-			dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-	} else
-		dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-
-	if (command != cmd) {
-		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-	}
-	if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
-		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
+	/*
+	 * _HPP settings apply to all child buses, until another _HPP is
+	 * encountered. If we don't find an _HPP for the input pci dev,
+	 * look for it in the parent device scope since that would apply to
+	 * this pci dev. If we don't find any _HPP, use hardcoded defaults
+	 */
+	while (pdev && (ACPI_FAILURE(status))) {
+		acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+		if (!handle)
+			break;
+		status = acpi_run_hpp(handle, hpp);
+		if (!(pdev->bus->parent))
+			break;
+		/* Check if a parent object supports _HPP */
+		pdev = pdev->bus->parent->self;
 	}
 }
 
diff --git a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c
index ba6c549..ed6c125 100644
--- a/drivers/pci/hotplug/shpchprm_legacy.c
+++ b/drivers/pci/hotplug/shpchprm_legacy.c
@@ -27,33 +27,11 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
 #include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_legacy.h"
-
-static void __iomem *shpchp_rom_start;
-static u16 unused_IRQ;
-
-void shpchprm_cleanup(void)
-{
-	if (shpchp_rom_start)
-		iounmap(shpchp_rom_start);
-}
-
-int shpchprm_print_pirt(void)
-{
-	return 0;
-}
 
 int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
 {
@@ -63,377 +41,14 @@
 	return 0;
 }
 
-/* Find the Hot Plug Resource Table in the specified region of memory */
-static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+		struct hotplug_params *hpp)
 {
-	void __iomem *fp;
-	void __iomem *endp;
-	u8 temp1, temp2, temp3, temp4;
-	int status = 0;
-
-	endp = (end - sizeof(struct hrt) + 1);
-
-	for (fp = begin; fp <= endp; fp += 16) {
-		temp1 = readb(fp + SIG0);
-		temp2 = readb(fp + SIG1);
-		temp3 = readb(fp + SIG2);
-		temp4 = readb(fp + SIG3);
-		if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') {
-			status = 1;
-			break;
-		}
-	}
-
-	if (!status)
-		fp = NULL;
-
-	dbg("Discovered Hotplug Resource Table at %p\n", fp);
-	return fp;
+	return;
 }
 
-/*
- * shpchprm_find_available_resources
- *
- *  Finds available memory, IO, and IRQ resources for programming
- *  devices which may be added to the system
- *  this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-	u8 populated_slot;
-	u8 bridged_slot;
-	void __iomem *one_slot;
-	struct pci_func *func = NULL;
-	int i = 10, index = 0;
-	u32 temp_dword, rc;
-	ulong temp_ulong;
-	struct pci_resource *mem_node;
-	struct pci_resource *p_mem_node;
-	struct pci_resource *io_node;
-	struct pci_resource *bus_node;
-	void __iomem *rom_resource_table;
-	struct pci_bus lpci_bus, *pci_bus;
-	u8 cfgspc_irq, temp;
-
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff);
-	dbg("rom_resource_table = %p\n", rom_resource_table);
-	if (rom_resource_table == NULL)
-		return -ENODEV;
-
-	/* Sum all resources and setup resource maps */
-	unused_IRQ = readl(rom_resource_table + UNUSED_IRQ);
-	dbg("unused_IRQ = %x\n", unused_IRQ);
-
-	temp = 0;
-	while (unused_IRQ) {
-		if (unused_IRQ & 1) {
-			shpchp_disk_irq = temp;
-			break;
-		}
-		unused_IRQ = unused_IRQ >> 1;
-		temp++;
-	}
-
-	dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq);
-	unused_IRQ = unused_IRQ >> 1;
-	temp++;
-
-	while (unused_IRQ) {
-		if (unused_IRQ & 1) {
-			shpchp_nic_irq = temp;
-			break;
-		}
-		unused_IRQ = unused_IRQ >> 1;
-		temp++;
-	}
-
-	dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq);
-	unused_IRQ = readl(rom_resource_table + PCIIRQ);
-
-	temp = 0;
-
-	pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq);
-
-	if (!shpchp_nic_irq) {
-		shpchp_nic_irq = cfgspc_irq;
-	}
-
-	if (!shpchp_disk_irq) {
-		shpchp_disk_irq = cfgspc_irq;
-	}
-
-	dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq);
-
-	one_slot = rom_resource_table + sizeof(struct hrt);
-
-	i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
-	dbg("number_of_entries = %d\n", i);
-
-	if (!readb(one_slot + SECONDARY_BUS))
-		return (1);
-
-	dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n");
-
-	while (i && readb(one_slot + SECONDARY_BUS)) {
-		u8 dev_func = readb(one_slot + DEV_FUNC);
-		u8 primary_bus = readb(one_slot + PRIMARY_BUS);
-		u8 secondary_bus = readb(one_slot + SECONDARY_BUS);
-		u8 max_bus = readb(one_slot + MAX_BUS);
-		u16 io_base = readw(one_slot + IO_BASE);
-		u16 io_length = readw(one_slot + IO_LENGTH);
-		u16 mem_base = readw(one_slot + MEM_BASE);
-		u16 mem_length = readw(one_slot + MEM_LENGTH);
-		u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE);
-		u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH);
-
-		dbg("%2.2x |  %4.4x | %4.4x |  %4.4x | %4.4x |  %4.4x | %4.4x |%2.2x %2.2x %2.2x\n",
-				dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length,
-				primary_bus, secondary_bus, max_bus);
-
-		/* If this entry isn't for our controller's bus, ignore it */
-		if (primary_bus != ctrl->slot_bus) {
-			i--;
-			one_slot += sizeof(struct slot_rt);
-			continue;
-		}
-		/* find out if this entry is for an occupied slot */
-		temp_dword = 0xFFFFFFFF;
-		pci_bus->number = primary_bus;
-		pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
-
-		dbg("temp_D_word = %x\n", temp_dword);
-
-		if (temp_dword != 0xFFFFFFFF) {
-			index = 0;
-			func = shpchp_slot_find(primary_bus, dev_func >> 3, 0);
-
-			while (func && (func->function != (dev_func & 0x07))) {
-				dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index);
-				func = shpchp_slot_find(primary_bus, dev_func >> 3, index++);
-			}
-
-			/* If we can't find a match, skip this table entry */
-			if (!func) {
-				i--;
-				one_slot += sizeof(struct slot_rt);
-				continue;
-			}
-			/* this may not work and shouldn't be used */
-			if (secondary_bus != primary_bus)
-				bridged_slot = 1;
-			else
-				bridged_slot = 0;
-
-			populated_slot = 1;
-		} else {
-			populated_slot = 0;
-			bridged_slot = 0;
-		}
-		dbg("slot populated =%s \n", populated_slot?"yes":"no");
-
-		/* If we've got a valid IO base, use it */
-
-		temp_ulong = io_base + io_length;
-
-		if ((io_base) && (temp_ulong <= 0x10000)) {
-			io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!io_node)
-				return -ENOMEM;
-
-			io_node->base = (ulong)io_base;
-			io_node->length = (ulong)io_length;
-			dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length);
-
-			if (!populated_slot) {
-				io_node->next = ctrl->io_head;
-				ctrl->io_head = io_node;
-			} else {
-				io_node->next = func->io_head;
-				func->io_head = io_node;
-			}
-		}
-
-		/* If we've got a valid memory base, use it */
-		temp_ulong = mem_base + mem_length;
-		if ((mem_base) && (temp_ulong <= 0x10000)) {
-			mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!mem_node)
-				return -ENOMEM;
-
-			mem_node->base = (ulong)mem_base << 16;
-			mem_node->length = (ulong)(mem_length << 16);
-			dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length);
-
-			if (!populated_slot) {
-				mem_node->next = ctrl->mem_head;
-				ctrl->mem_head = mem_node;
-			} else {
-				mem_node->next = func->mem_head;
-				func->mem_head = mem_node;
-			}
-		}
-
-		/*
-		 * If we've got a valid prefetchable memory base, and
-		 * the base + length isn't greater than 0xFFFF
-		 */
-		temp_ulong = pre_mem_base + pre_mem_length;
-		if ((pre_mem_base) && (temp_ulong <= 0x10000)) {
-			p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!p_mem_node)
-				return -ENOMEM;
-
-			p_mem_node->base = (ulong)pre_mem_base << 16;
-			p_mem_node->length = (ulong)pre_mem_length << 16;
-			dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length);
-
-			if (!populated_slot) {
-				p_mem_node->next = ctrl->p_mem_head;
-				ctrl->p_mem_head = p_mem_node;
-			} else {
-				p_mem_node->next = func->p_mem_head;
-				func->p_mem_head = p_mem_node;
-			}
-		}
-
-		/*
-		 * If we've got a valid bus number, use it
-		 * The second condition is to ignore bus numbers on
-		 * populated slots that don't have PCI-PCI bridges
-		 */
-		if (secondary_bus && (secondary_bus != primary_bus)) {
-			bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!bus_node)
-				return -ENOMEM;
-
-			bus_node->base = (ulong)secondary_bus;
-			bus_node->length = (ulong)(max_bus - secondary_bus + 1);
-			dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length);
-
-			if (!populated_slot) {
-				bus_node->next = ctrl->bus_head;
-				ctrl->bus_head = bus_node;
-			} else {
-				bus_node->next = func->bus_head;
-				func->bus_head = bus_node;
-			}
-		}
-
-		i--;
-		one_slot += sizeof(struct slot_rt);
-	}
-
-	/* If all of the following fail, we don't have any resources for hot plug add */
-	rc = 1;
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-	return (rc);
+	return;
 }
 
-int shpchprm_set_hpp(
-	struct controller *ctrl,
-	struct pci_func *func,
-	u8	card_type)
-{
-	u32 rc;
-	u8 temp_byte;
-	struct pci_bus lpci_bus, *pci_bus;
-	unsigned int	devfn;
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	temp_byte = 0x40;	/* hard coded value for LT */
-	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-		/* set subordinate Latency Timer */
-		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-		if (rc) {
-			dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, 
-				func->device, func->function);
-			return rc;
-		}
-	}
-
-	/* set base Latency Timer */
-	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-	if (rc) {
-		dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-		return rc;
-	}
-
-	/* set Cache Line size */
-	temp_byte = 0x08;	/* hard coded value for CLS */
-	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-	if (rc) {
-		dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-	}
-
-	/* set enable_perr */
-	/* set enable_serr */
-
-	return rc;
-}
-
-void shpchprm_enable_card(
-	struct controller *ctrl,
-	struct pci_func *func,
-	u8 card_type)
-{
-	u16 command, bcommand;
-	struct pci_bus lpci_bus, *pci_bus;
-	unsigned int devfn;
-	int rc;
-
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-	command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
-		| PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
-		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-	rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
-	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-		bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
-			| PCI_BRIDGE_CTL_NO_ISA;
-		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
-	}
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
-	shpchp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
-	if (!shpchp_rom_start) {
-		err("Could not ioremap memory region for ROM\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctrl_type)
-{
-	int retval;
-
-	switch (ctrl_type) {
-	case PCI:
-		retval = legacy_shpchprm_init_pci();
-		break;
-	default:
-		retval = -ENODEV;
-		break;
-	}
-
-	return retval;
-}
diff --git a/drivers/pci/hotplug/shpchprm_legacy.h b/drivers/pci/hotplug/shpchprm_legacy.h
deleted file mode 100644
index 21bda74..0000000
--- a/drivers/pci/hotplug/shpchprm_legacy.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_LEGACY_H_
-#define _SHPCHPRM_LEGACY_H_
-
-#define ROM_PHY_ADDR	0x0F0000
-#define ROM_PHY_LEN	0x00FFFF
-
-struct slot_rt {
-	u8 dev_func;
-	u8 primary_bus;
-	u8 secondary_bus;
-	u8 max_bus;
-	u16 io_base;
-	u16 io_length;
-	u16 mem_base;
-	u16 mem_length;
-	u16 pre_mem_base;
-	u16 pre_mem_length;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug slot resource table registers based on the above structure layout */
-enum slot_rt_offsets {
-	DEV_FUNC = offsetof(struct slot_rt, dev_func),
-	PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
-	SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
-	MAX_BUS = offsetof(struct slot_rt, max_bus),
-	IO_BASE = offsetof(struct slot_rt, io_base),
-	IO_LENGTH = offsetof(struct slot_rt, io_length),
-	MEM_BASE = offsetof(struct slot_rt, mem_base),
-	MEM_LENGTH = offsetof(struct slot_rt, mem_length),
-	PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
-	PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
-};
-
-struct hrt {
-	char sig0;
-	char sig1;
-	char sig2;
-	char sig3;
-	u16 unused_IRQ;
-	u16 PCIIRQ;
-	u8 number_of_entries;
-	u8 revision;
-	u16 reserved1;
-	u32 reserved2;
-} __attribute__ ((packed));
-
-/* offsets to the hotplug resource table registers based on the above structure layout */
-enum hrt_offsets {
-	SIG0 = offsetof(struct hrt, sig0),
-	SIG1 = offsetof(struct hrt, sig1),
-	SIG2 = offsetof(struct hrt, sig2),
-	SIG3 = offsetof(struct hrt, sig3),
-	UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
-	PCIIRQ = offsetof(struct hrt, PCIIRQ),
-	NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
-	REVISION = offsetof(struct hrt, revision),
-	HRT_RESERVED1 = offsetof(struct hrt, reserved1),
-	HRT_RESERVED2 = offsetof(struct hrt, reserved2),
-};
-
-struct irq_info {
-	u8 bus, devfn;		/* bus, device and function */
-	struct {
-		u8 link;	/* IRQ line ID, chipset dependent, 0=not routed */
-		u16 bitmap;	/* Available IRQs */
-	} __attribute__ ((packed)) irq[4];
-	u8 slot;		/* slot number, 0=onboard */
-	u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
-	u32 signature;		/* PIRQ_SIGNATURE should be here */
-	u16 version;		/* PIRQ_VERSION */
-	u16 size;			/* Table size in bytes */
-	u8 rtr_bus, rtr_devfn;	/* Where the interrupt router lies */
-	u16 exclusive_irqs;	/* IRQs devoted exclusively to PCI usage */
-	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
-	u32 miniport_data;	/* Crap */
-	u8 rfu[11];
-	u8 checksum;		/* Modulo 256 checksum must give zero */
-	struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif				/* _SHPCHPRM_LEGACY_H_ */
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c
index 5f75ef7..c6b4099 100644
--- a/drivers/pci/hotplug/shpchprm_nonacpi.c
+++ b/drivers/pci/hotplug/shpchprm_nonacpi.c
@@ -32,24 +32,9 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
+#include <linux/slab.h>
+
 #include "shpchp.h"
-#include "shpchprm.h"
-#include "shpchprm_nonacpi.h"
-
-void shpchprm_cleanup(void)
-{
-	return;
-}
-
-int shpchprm_print_pirt(void)
-{
-	return 0;
-}
 
 int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
 {
@@ -60,375 +45,13 @@
 	return 0;
 }
 
-static void print_pci_resource ( struct pci_resource	*aprh)
+void get_hp_params_from_firmware(struct pci_dev *dev,
+		struct hotplug_params *hpp)
 {
-	struct pci_resource	*res;
-
-	for (res = aprh; res; res = res->next)
-		dbg("        base= 0x%x length= 0x%x\n", res->base, res->length);
+	return;
 }
 
-
-static void phprm_dump_func_res( struct pci_func *fun)
+void get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
-	struct pci_func *func = fun;
-
-	if (func->bus_head) {
-		dbg(":    BUS Resources:\n");
-		print_pci_resource (func->bus_head);
-	}
-	if (func->io_head) {
-		dbg(":    IO Resources:\n");
-		print_pci_resource (func->io_head);
-	}
-	if (func->mem_head) {
-		dbg(":    MEM Resources:\n");
-		print_pci_resource (func->mem_head);
-	}
-	if (func->p_mem_head) {
-		dbg(":    PMEM Resources:\n");
-		print_pci_resource (func->p_mem_head);
-	}
-}
-
-static int phprm_get_used_resources (
-	struct controller *ctrl,
-	struct pci_func *func
-	)
-{
-	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int phprm_delete_resource(
-	struct pci_resource **aprh,
-	ulong base,
-	ulong size)
-{
-	struct pci_resource *res;
-	struct pci_resource *prevnode;
-	struct pci_resource *split_node;
-	ulong tbase;
-
-	shpchp_resource_sort_and_combine(aprh);
-
-	for (res = *aprh; res; res = res->next) {
-		if (res->base > base)
-			continue;
-
-		if ((res->base + res->length) < (base + size))
-			continue;
-
-		if (res->base < base) {
-			tbase = base;
-
-			if ((res->length - (tbase - res->base)) < size)
-				continue;
-
-			split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!split_node)
-				return -ENOMEM;
-
-			split_node->base = res->base;
-			split_node->length = tbase - res->base;
-			res->base = tbase;
-			res->length -= split_node->length;
-
-			split_node->next = res->next;
-			res->next = split_node;
-		}
-
-		if (res->length >= size) {
-			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-			if (!split_node)
-				return -ENOMEM;
-
-			split_node->base = res->base + size;
-			split_node->length = res->length - size;
-			res->length = size;
-
-			split_node->next = res->next;
-			res->next = split_node;
-		}
-
-		if (*aprh == res) {
-			*aprh = res->next;
-		} else {
-			prevnode = *aprh;
-			while (prevnode->next != res)
-				prevnode = prevnode->next;
-
-			prevnode->next = res->next;
-		}
-		res->next = NULL;
-		kfree(res);
-		break;
-	}
-
-	return 0;
-}
-
-
-static int phprm_delete_resources(
-	struct pci_resource **aprh,
-	struct pci_resource *this
-	)
-{
-	struct pci_resource *res;
-
-	for (res = this; res; res = res->next)
-		phprm_delete_resource(aprh, res->base, res->length);
-
-	return 0;
-}
-
-
-static int configure_existing_function(
-	struct controller *ctrl,
-	struct pci_func *func
-	)
-{
-	int rc;
-
-	/* see how much resources the func has used. */
-	rc = phprm_get_used_resources (ctrl, func);
-
-	if (!rc) {
-		/* subtract the resources used by the func from ctrl resources */
-		rc  = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
-		rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
-		rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
-		rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
-		if (rc)
-			warn("aCEF: cannot del used resources\n");
-	} else
-		err("aCEF: cannot get used resources\n");
-
-	return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
-	struct pci_func *func, new_func;
-	int busn = ctrl->slot_bus;
-	int devn, funn;
-	u32	vid;
-
-	for (devn = 0; devn < 32; devn++) {
-		for (funn = 0; funn < 8; funn++) {
-			/*
-			if (devn == ctrl->device && funn == ctrl->function)
-				continue;
-			 */
-			/* find out if this entry is for an occupied slot */
-			vid = 0xFFFFFFFF;
-
-			pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
-			if (vid != 0xFFFFFFFF) {
-				func = shpchp_slot_find(busn, devn, funn);
-				if (!func) {
-					memset(&new_func, 0, sizeof(struct pci_func));
-					new_func.bus = busn;
-					new_func.device = devn;
-					new_func.function = funn;
-					new_func.is_a_board = 1;
-					configure_existing_function(ctrl, &new_func);
-					phprm_dump_func_res(&new_func);
-				} else {
-					configure_existing_function(ctrl, func);
-					phprm_dump_func_res(func);
-				}
-				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-			}
-		}
-	}
-
-	return 0;
-}
-
-static void phprm_dump_ctrl_res( struct controller *ctlr)
-{
-	struct controller *ctrl = ctlr;
-
-	if (ctrl->bus_head) {
-		dbg(":    BUS Resources:\n");
-		print_pci_resource (ctrl->bus_head);
-	}
-	if (ctrl->io_head) {
-		dbg(":    IO Resources:\n");
-		print_pci_resource (ctrl->io_head);
-	}
-	if (ctrl->mem_head) {
-		dbg(":    MEM Resources:\n");
-		print_pci_resource (ctrl->mem_head);
-	}
-	if (ctrl->p_mem_head) {
-		dbg(":    PMEM Resources:\n");
-		print_pci_resource (ctrl->p_mem_head);
-	}
-}
-
-/*
- * phprm_find_available_resources
- *
- *  Finds available memory, IO, and IRQ resources for programming
- *  devices which may be added to the system
- *  this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int shpchprm_find_available_resources(struct controller *ctrl)
-{
-	struct pci_func func;
-	u32 rc;
-
-	memset(&func, 0, sizeof(struct pci_func));
-
-	func.bus = ctrl->bus;
-	func.device = ctrl->device;
-	func.function = ctrl->function;
-	func.is_a_board = 1;
-
-	/* Get resources for this PCI bridge */
-	rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-	dbg("%s: shpchp_save_used_resources rc = %d\n", __FUNCTION__, rc);
-
-	if (func.mem_head)
-		func.mem_head->next = ctrl->mem_head;
-	ctrl->mem_head = func.mem_head;
-
-	if (func.p_mem_head)
-		func.p_mem_head->next = ctrl->p_mem_head;
-	ctrl->p_mem_head = func.p_mem_head;
-
-	if (func.io_head)
-		func.io_head->next = ctrl->io_head;
-	ctrl->io_head = func.io_head;
-
-	if(func.bus_head)
-		func.bus_head->next = ctrl->bus_head;
-	ctrl->bus_head = func.bus_head;
-	if (ctrl->bus_head)
-		phprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
-
-	dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
-	phprm_dump_ctrl_res(ctrl);
-	bind_pci_resources_to_slots (ctrl);
-
-	dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
-	phprm_dump_ctrl_res(ctrl);
-
-
-	/* If all of the following fail, we don't have any resources for hot plug add */
-	rc = 1;
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head));
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head));
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head));
-	rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head));
-
-	return (rc);
-}
-
-int shpchprm_set_hpp(
-	struct controller *ctrl,
-	struct pci_func *func,
-	u8	card_type)
-{
-	u32 rc;
-	u8 temp_byte;
-	struct pci_bus lpci_bus, *pci_bus;
-	unsigned int	devfn;
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	temp_byte = 0x40;	/* hard coded value for LT */
-	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-		/* set subordinate Latency Timer */
-		rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-
-		if (rc) {
-			dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, 
-				func->device, func->function);
-			return rc;
-		}
-	}
-
-	/* set base Latency Timer */
-	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-
-	if (rc) {
-		dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-		return rc;
-	}
-
-	/* set Cache Line size */
-	temp_byte = 0x08;	/* hard coded value for CLS */
-
-	rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-
-	if (rc) {
-		dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
-	}
-
-	/* set enable_perr */
-	/* set enable_serr */
-
-	return rc;
-}
-
-void shpchprm_enable_card(
-	struct controller *ctrl,
-	struct pci_func *func,
-	u8 card_type)
-{
-	u16 command, bcommand;
-	struct pci_bus lpci_bus, *pci_bus;
-	unsigned int devfn;
-	int rc;
-
-	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
-	pci_bus = &lpci_bus;
-	pci_bus->number = func->bus;
-	devfn = PCI_DEVFN(func->device, func->function);
-
-	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
-	command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
-		| PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
-		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
-	rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
-	if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-
-		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-
-		bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
-			| PCI_BRIDGE_CTL_NO_ISA;
-
-		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
-	}
-}
-
-static int legacy_shpchprm_init_pci(void)
-{
-	return 0;
-}
-
-int shpchprm_init(enum php_ctlr_type ctrl_type)
-{
-	int retval;
-
-	switch (ctrl_type) {
-	case PCI:
-		retval = legacy_shpchprm_init_pci();
-		break;
-	default:
-		retval = -ENODEV;
-		break;
-	}
-
-	return retval;
+	return;
 }
diff --git a/drivers/pci/hotplug/shpchprm_nonacpi.h b/drivers/pci/hotplug/shpchprm_nonacpi.h
deleted file mode 100644
index cddaaa5..0000000
--- a/drivers/pci/hotplug/shpchprm_nonacpi.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * 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, GOOD TITLE or
- * NON INFRINGEMENT.  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.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _SHPCHPRM_NONACPI_H_
-#define _SHPCHPRM_NONACPI_H_
-
-struct irq_info {
-	u8 bus, devfn;		/* bus, device and function */
-	struct {
-		u8 link;	/* IRQ line ID, chipset dependent, 0=not routed */
-		u16 bitmap;	/* Available IRQs */
-	} __attribute__ ((packed)) irq[4];
-	u8 slot;		/* slot number, 0=onboard */
-	u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
-	u32 signature;		/* PIRQ_SIGNATURE should be here */
-	u16 version;		/* PIRQ_VERSION */
-	u16 size;			/* Table size in bytes */
-	u8 rtr_bus, rtr_devfn;	/* Where the interrupt router lies */
-	u16 exclusive_irqs;	/* IRQs devoted exclusively to PCI usage */
-	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
-	u32 miniport_data;	/* Crap */
-	u8 rfu[11];
-	u8 checksum;		/* Modulo 256 checksum must give zero */
-	struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif				/* _SHPCHPRM_NONACPI_H_ */
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ee8677b..a203355 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -575,6 +575,8 @@
 /**
  * msix_capability_init - configure device's MSI-X capability
  * @dev: pointer to the pci_dev data structure of MSI-X device function
+ * @entries: pointer to an array of struct msix_entry entries
+ * @nvec: number of @entries
  *
  * Setup the MSI-X capability structure of device function with a
  * single MSI-X vector. A return of zero indicates the successful setup of
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 0d0d533..ae986e5 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -8,6 +8,8 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/mempolicy.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include "pci.h"
 
 /*
@@ -26,7 +28,10 @@
 #ifdef CONFIG_HOTPLUG
 
 /**
- * store_new_id
+ * store_new_id - add a new PCI device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
  *
  * Adds a new dynamic pci device ID to this driver,
  * and causes the driver to probe for all devices again.
@@ -194,8 +199,10 @@
 
 /**
  * __pci_device_probe()
+ * @drv: driver to call to check if it wants the PCI device
+ * @pci_dev: PCI device being probed
  * 
- * returns 0  on success, else error.
+ * returns 0 on success, else error.
  * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
  */
 static int
@@ -377,6 +384,10 @@
 	 * the pci shutdown function, this test can go away. */
 	if (!drv->driver.shutdown)
 		drv->driver.shutdown = pci_device_shutdown;
+	else
+		printk(KERN_WARNING "Warning: PCI driver %s has a struct "
+			"device_driver shutdown method, please update!\n",
+			drv->name);
 	drv->driver.owner = drv->owner;
 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
 
@@ -436,11 +447,11 @@
 
 /**
  * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
- * @ids: array of PCI device id structures to search in
  * @dev: the PCI device structure to match against
+ * @drv: the device driver to search for matching PCI device id structures
  * 
  * Used by a driver to check whether a PCI device present in the
- * system is in its list of supported devices.Returns the matching
+ * system is in its list of supported devices. Returns the matching
  * pci_device_id structure or %NULL if there is no match.
  */
 static int pci_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 2898830..965a593 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -130,7 +130,7 @@
 
 	if ((off & 1) && size) {
 		u8 val;
-		pci_read_config_byte(dev, off, &val);
+		pci_user_read_config_byte(dev, off, &val);
 		data[off - init_off] = val;
 		off++;
 		size--;
@@ -138,7 +138,7 @@
 
 	if ((off & 3) && size > 2) {
 		u16 val;
-		pci_read_config_word(dev, off, &val);
+		pci_user_read_config_word(dev, off, &val);
 		data[off - init_off] = val & 0xff;
 		data[off - init_off + 1] = (val >> 8) & 0xff;
 		off += 2;
@@ -147,7 +147,7 @@
 
 	while (size > 3) {
 		u32 val;
-		pci_read_config_dword(dev, off, &val);
+		pci_user_read_config_dword(dev, off, &val);
 		data[off - init_off] = val & 0xff;
 		data[off - init_off + 1] = (val >> 8) & 0xff;
 		data[off - init_off + 2] = (val >> 16) & 0xff;
@@ -158,7 +158,7 @@
 
 	if (size >= 2) {
 		u16 val;
-		pci_read_config_word(dev, off, &val);
+		pci_user_read_config_word(dev, off, &val);
 		data[off - init_off] = val & 0xff;
 		data[off - init_off + 1] = (val >> 8) & 0xff;
 		off += 2;
@@ -167,7 +167,7 @@
 
 	if (size > 0) {
 		u8 val;
-		pci_read_config_byte(dev, off, &val);
+		pci_user_read_config_byte(dev, off, &val);
 		data[off - init_off] = val;
 		off++;
 		--size;
@@ -192,7 +192,7 @@
 	}
 	
 	if ((off & 1) && size) {
-		pci_write_config_byte(dev, off, data[off - init_off]);
+		pci_user_write_config_byte(dev, off, data[off - init_off]);
 		off++;
 		size--;
 	}
@@ -200,7 +200,7 @@
 	if ((off & 3) && size > 2) {
 		u16 val = data[off - init_off];
 		val |= (u16) data[off - init_off + 1] << 8;
-                pci_write_config_word(dev, off, val);
+                pci_user_write_config_word(dev, off, val);
                 off += 2;
                 size -= 2;
         }
@@ -210,7 +210,7 @@
 		val |= (u32) data[off - init_off + 1] << 8;
 		val |= (u32) data[off - init_off + 2] << 16;
 		val |= (u32) data[off - init_off + 3] << 24;
-		pci_write_config_dword(dev, off, val);
+		pci_user_write_config_dword(dev, off, val);
 		off += 4;
 		size -= 4;
 	}
@@ -218,13 +218,13 @@
 	if (size >= 2) {
 		u16 val = data[off - init_off];
 		val |= (u16) data[off - init_off + 1] << 8;
-		pci_write_config_word(dev, off, val);
+		pci_user_write_config_word(dev, off, val);
 		off += 2;
 		size -= 2;
 	}
 
 	if (size) {
-		pci_write_config_byte(dev, off, data[off - init_off]);
+		pci_user_write_config_byte(dev, off, data[off - init_off]);
 		off++;
 		--size;
 	}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 259d247..e74d758 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -15,6 +15,7 @@
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/string.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include "pci.h"
 
@@ -252,6 +253,8 @@
 		pci_update_resource(dev, &dev->resource[i], i);
 }
 
+int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
+
 /**
  * pci_set_power_state - Set the power state of a PCI device
  * @dev: PCI device to be suspended
@@ -266,7 +269,6 @@
  * -EIO if device does not support PCI PM.
  * 0 if we can successfully change the power state.
  */
-int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
 int
 pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
@@ -314,19 +316,19 @@
 	 * sets PowerState to 0.
 	 */
 	switch (dev->current_state) {
+	case PCI_D0:
+	case PCI_D1:
+	case PCI_D2:
+		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+		pmcsr |= state;
+		break;
 	case PCI_UNKNOWN: /* Boot-up */
 		if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
 		 && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
 			need_restore = 1;
 		/* Fall-through: force to D0 */
-	case PCI_D3hot:
-	case PCI_D3cold:
-	case PCI_POWER_ERROR:
-		pmcsr = 0;
-		break;
 	default:
-		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		pmcsr |= state;
+		pmcsr = 0;
 		break;
 	}
 
@@ -808,8 +810,8 @@
 
 /**
  * pci_intx - enables/disables PCI INTx for device dev
- * @dev: the PCI device to operate on
- * @enable: boolean
+ * @pdev: the PCI device to operate on
+ * @enable: boolean: whether to enable or disable PCI INTx
  *
  * Enables/disables PCI INTx for device dev
  */
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d3f3dd4..6527b36 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -15,6 +15,13 @@
 extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
 extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
 
+extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
+extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
+extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
+extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
+extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
+extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
+
 /* PCI /proc functions */
 #ifdef CONFIG_PROC_FS
 extern int pci_proc_attach_device(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 393e0ce..467a4ce 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -11,6 +11,8 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/pm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/pcieport_if.h>
 
 #include "portdrv.h"
@@ -61,7 +63,7 @@
 
 static void pcie_port_shutdown_service(struct device *dev) {}
 
-static int pcie_port_suspend_service(struct device *dev, pm_message_t state, u32 level)
+static int pcie_port_suspend_service(struct device *dev, pm_message_t state)
 {
 	struct pcie_device *pciedev;
 	struct pcie_port_service_driver *driver;
@@ -76,7 +78,7 @@
 	return 0;
 }
 
-static int pcie_port_resume_service(struct device *dev, u32 level)
+static int pcie_port_resume_service(struct device *dev)
 {
 	struct pcie_device *pciedev;
 	struct pcie_port_service_driver *driver;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 3c565ce..0226014 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -12,6 +12,7 @@
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/pcieport_if.h>
 
 #include "portdrv.h"
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0057864..fce2cb2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -669,6 +669,7 @@
 
 /**
  * pci_cfg_space_size - get the configuration space size of the PCI device.
+ * @dev: PCI device
  *
  * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
  * have 4096 bytes.  Even if the device is capable, that doesn't mean we can
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 9613f66..9eb4657 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -80,7 +80,7 @@
 
 	if ((pos & 1) && cnt) {
 		unsigned char val;
-		pci_read_config_byte(dev, pos, &val);
+		pci_user_read_config_byte(dev, pos, &val);
 		__put_user(val, buf);
 		buf++;
 		pos++;
@@ -89,7 +89,7 @@
 
 	if ((pos & 3) && cnt > 2) {
 		unsigned short val;
-		pci_read_config_word(dev, pos, &val);
+		pci_user_read_config_word(dev, pos, &val);
 		__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
 		buf += 2;
 		pos += 2;
@@ -98,7 +98,7 @@
 
 	while (cnt >= 4) {
 		unsigned int val;
-		pci_read_config_dword(dev, pos, &val);
+		pci_user_read_config_dword(dev, pos, &val);
 		__put_user(cpu_to_le32(val), (unsigned int __user *) buf);
 		buf += 4;
 		pos += 4;
@@ -107,7 +107,7 @@
 
 	if (cnt >= 2) {
 		unsigned short val;
-		pci_read_config_word(dev, pos, &val);
+		pci_user_read_config_word(dev, pos, &val);
 		__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
 		buf += 2;
 		pos += 2;
@@ -116,7 +116,7 @@
 
 	if (cnt) {
 		unsigned char val;
-		pci_read_config_byte(dev, pos, &val);
+		pci_user_read_config_byte(dev, pos, &val);
 		__put_user(val, buf);
 		buf++;
 		pos++;
@@ -151,7 +151,7 @@
 	if ((pos & 1) && cnt) {
 		unsigned char val;
 		__get_user(val, buf);
-		pci_write_config_byte(dev, pos, val);
+		pci_user_write_config_byte(dev, pos, val);
 		buf++;
 		pos++;
 		cnt--;
@@ -160,7 +160,7 @@
 	if ((pos & 3) && cnt > 2) {
 		unsigned short val;
 		__get_user(val, (unsigned short __user *) buf);
-		pci_write_config_word(dev, pos, le16_to_cpu(val));
+		pci_user_write_config_word(dev, pos, le16_to_cpu(val));
 		buf += 2;
 		pos += 2;
 		cnt -= 2;
@@ -169,7 +169,7 @@
 	while (cnt >= 4) {
 		unsigned int val;
 		__get_user(val, (unsigned int __user *) buf);
-		pci_write_config_dword(dev, pos, le32_to_cpu(val));
+		pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
 		buf += 4;
 		pos += 4;
 		cnt -= 4;
@@ -178,7 +178,7 @@
 	if (cnt >= 2) {
 		unsigned short val;
 		__get_user(val, (unsigned short __user *) buf);
-		pci_write_config_word(dev, pos, le16_to_cpu(val));
+		pci_user_write_config_word(dev, pos, le16_to_cpu(val));
 		buf += 2;
 		pos += 2;
 		cnt -= 2;
@@ -187,7 +187,7 @@
 	if (cnt) {
 		unsigned char val;
 		__get_user(val, buf);
-		pci_write_config_byte(dev, pos, val);
+		pci_user_write_config_byte(dev, pos, val);
 		buf++;
 		pos++;
 		cnt--;
@@ -484,10 +484,10 @@
 
 	drv = pci_dev_driver(dev);
 
-	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-	pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
-	pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
+	pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+	pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
+	pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
 	seq_printf(m, "  Bus %2d, device %3d, function %2d:\n",
 	       dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
 	seq_printf(m, "    Class %04x", class_rev >> 16);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7992bc8..5627ce1 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -7,6 +7,9 @@
  *
  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  *
+ *  Init/reset quirks for USB host controllers should be in the
+ *  USB quirks file, where their drivers can access reuse it.
+ *
  *  The bridge optimization stuff has been removed. If you really
  *  have a silly BIOS which is unable to set your host bridge right,
  *  use the PowerTweak utility (see http://powertweak.sourceforge.net).
@@ -353,7 +356,7 @@
 /*
  * PIIX4 ACPI: Two IO regions pointed to by longwords at
  *	0x40 (64 bytes of ACPI registers)
- *	0x90 (32 bytes of SMB registers)
+ *	0x90 (16 bytes of SMB registers)
  * and a few strange programmable PIIX4 device resources.
  */
 static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
@@ -363,7 +366,7 @@
 	pci_read_config_dword(dev, 0x40, &region);
 	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
 	pci_read_config_dword(dev, 0x90, &region);
-	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
+	quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
 
 	/* Device resource A has enables for some of the other ones */
 	pci_read_config_dword(dev, 0x5c, &res_a);
@@ -414,6 +417,18 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		quirk_ich4_lpc_acpi );
 
+static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
+{
+	u32 region;
+
+	pci_read_config_dword(dev, 0x40, &region);
+	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+
+	pci_read_config_dword(dev, 0x48, &region);
+	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
+
 /*
  * VIA ACPI: One IO region pointed to by longword at
  *	0x48 or 0x20 (256 bytes of ACPI registers)
@@ -633,28 +648,6 @@
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
 
 /*
- * PIIX3 USB: We have to disable USB interrupts that are
- * hardwired to PIRQD# and may be shared with an
- * external device.
- *
- * Legacy Support Register (LEGSUP):
- *     bit13:  USB PIRQ Enable (USBPIRQDEN),
- *     bit4:   Trap/SMI On IRQ Enable (USBSMIEN).
- *
- * We mask out all r/wc bits, too.
- */
-static void __devinit quirk_piix3_usb(struct pci_dev *dev)
-{
-	u16 legsup;
-
-	pci_read_config_word(dev, 0xc0, &legsup);
-	legsup &= 0x50ef;
-	pci_write_config_word(dev, 0xc0, legsup);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb );
-
-/*
  * VIA VT82C598 has its device ID settable and many BIOSes
  * set it to the ID of VT82C597 for backward compatibility.
  * We need to switch it off to be able to recognize the real
@@ -922,6 +915,12 @@
 			case 0x186a: /* M6Ne notebook */
 				asus_hides_smbus = 1;
 			}
+		if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
+			switch (dev->subsystem_device) {
+			case 0x1882: /* M6V notebook */
+				asus_hides_smbus = 1;
+			}
+		}
 	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
 		if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB)
 			switch(dev->subsystem_device) {
@@ -932,6 +931,7 @@
 		if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
 			switch (dev->subsystem_device) {
 			case 0x12bc: /* HP D330L */
+			case 0x12bd: /* HP D530 */
 				asus_hides_smbus = 1;
 			}
 	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
@@ -966,6 +966,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
 
 static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
 {
@@ -990,6 +991,23 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
 
+static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
+{
+	u32 val, rcba;
+	void __iomem *base;
+
+	if (likely(!asus_hides_smbus))
+		return;
+	pci_read_config_dword(dev, 0xF0, &rcba);
+	base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); /* use bits 31:14, 16 kB aligned */
+	if (base == NULL) return;
+	val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
+	writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
+	iounmap(base);
+	printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc_ich6 );
+
 /*
  * SiS 96x south bridge: BIOS typically hides SMBus device...
  */
@@ -1002,234 +1020,6 @@
 	pci_read_config_byte(dev, 0x77, &val);
 }
 
-
-#define UHCI_USBLEGSUP		0xc0		/* legacy support */
-#define UHCI_USBCMD		0		/* command register */
-#define UHCI_USBSTS		2		/* status register */
-#define UHCI_USBINTR		4		/* interrupt register */
-#define UHCI_USBLEGSUP_DEFAULT	0x2000		/* only PIRQ enable set */
-#define UHCI_USBCMD_RUN		(1 << 0)	/* RUN/STOP bit */
-#define UHCI_USBCMD_GRESET	(1 << 2)	/* Global reset */
-#define UHCI_USBCMD_CONFIGURE	(1 << 6)	/* config semaphore */
-#define UHCI_USBSTS_HALTED	(1 << 5)	/* HCHalted bit */
-
-#define OHCI_CONTROL		0x04
-#define OHCI_CMDSTATUS		0x08
-#define OHCI_INTRSTATUS		0x0c
-#define OHCI_INTRENABLE		0x10
-#define OHCI_INTRDISABLE	0x14
-#define OHCI_OCR		(1 << 3)	/* ownership change request */
-#define OHCI_CTRL_IR		(1 << 8)	/* interrupt routing */
-#define OHCI_INTR_OC		(1 << 30)	/* ownership change */
-
-#define EHCI_HCC_PARAMS		0x08		/* extended capabilities */
-#define EHCI_USBCMD		0		/* command register */
-#define EHCI_USBCMD_RUN		(1 << 0)	/* RUN/STOP bit */
-#define EHCI_USBSTS		4		/* status register */
-#define EHCI_USBSTS_HALTED	(1 << 12)	/* HCHalted bit */
-#define EHCI_USBINTR		8		/* interrupt register */
-#define EHCI_USBLEGSUP		0		/* legacy support register */
-#define EHCI_USBLEGSUP_BIOS	(1 << 16)	/* BIOS semaphore */
-#define EHCI_USBLEGSUP_OS	(1 << 24)	/* OS semaphore */
-#define EHCI_USBLEGCTLSTS	4		/* legacy control/status */
-#define EHCI_USBLEGCTLSTS_SOOE	(1 << 13)	/* SMI on ownership change */
-
-int usb_early_handoff __devinitdata = 0;
-static int __init usb_handoff_early(char *str)
-{
-	usb_early_handoff = 1;
-	return 0;
-}
-__setup("usb-handoff", usb_handoff_early);
-
-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
-{
-	unsigned long base = 0;
-	int wait_time, delta;
-	u16 val, sts;
-	int i;
-
-	for (i = 0; i < PCI_ROM_RESOURCE; i++)
-		if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
-			base = pci_resource_start(pdev, i);
-			break;
-		}
-
-	if (!base)
-		return;
-
-	/*
-	 * stop controller
-	 */
-	sts = inw(base + UHCI_USBSTS);
-	val = inw(base + UHCI_USBCMD);
-	val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE);
-	outw(val, base + UHCI_USBCMD);
-
-	/*
-	 * wait while it stops if it was running
-	 */
-	if ((sts & UHCI_USBSTS_HALTED) == 0)
-	{
-		wait_time = 1000;
-		delta = 100;
-
-		do {
-			outw(0x1f, base + UHCI_USBSTS);
-			udelay(delta);
-			wait_time -= delta;
-			val = inw(base + UHCI_USBSTS);
-			if (val & UHCI_USBSTS_HALTED)
-				break;
-		} while (wait_time > 0);
-	}
-
-	/*
-	 * disable interrupts & legacy support
-	 */
-	outw(0, base + UHCI_USBINTR);
-	outw(0x1f, base + UHCI_USBSTS);
-	pci_read_config_word(pdev, UHCI_USBLEGSUP, &val);
-	if (val & 0xbf) 
-		pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT);
-		
-}
-
-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
-{
-	void __iomem *base;
-	int wait_time;
-
-	base = ioremap_nocache(pci_resource_start(pdev, 0),
-				     pci_resource_len(pdev, 0));
-	if (base == NULL) return;
-
-	if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
-		wait_time = 500; /* 0.5 seconds */
-		writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
-		writel(OHCI_OCR, base + OHCI_CMDSTATUS);
-		while (wait_time > 0 && 
-				readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
-			wait_time -= 10;
-			msleep(10);
-		}
-	}
-
-	/*
-	 * disable interrupts
-	 */
-	writel(~(u32)0, base + OHCI_INTRDISABLE);
-	writel(~(u32)0, base + OHCI_INTRSTATUS);
-
-	iounmap(base);
-}
-
-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
-{
-	int wait_time, delta;
-	void __iomem *base, *op_reg_base;
-	u32 hcc_params, val, temp;
-	u8 cap_length;
-
-	base = ioremap_nocache(pci_resource_start(pdev, 0),
-				pci_resource_len(pdev, 0));
-	if (base == NULL) return;
-
-	cap_length = readb(base);
-	op_reg_base = base + cap_length;
-	hcc_params = readl(base + EHCI_HCC_PARAMS);
-	hcc_params = (hcc_params >> 8) & 0xff;
-	if (hcc_params) {
-		pci_read_config_dword(pdev, 
-					hcc_params + EHCI_USBLEGSUP,
-					&val);
-		if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
-			/*
-			 * Ok, BIOS is in smm mode, try to hand off...
-			 */
-			pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						&temp);
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						temp | EHCI_USBLEGCTLSTS_SOOE);
-			val |= EHCI_USBLEGSUP_OS;
-			pci_write_config_dword(pdev, 
-						hcc_params + EHCI_USBLEGSUP, 
-						val);
-
-			wait_time = 500;
-			do {
-				msleep(10);
-				wait_time -= 10;
-				pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						&val);
-			} while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
-			if (!wait_time) {
-				/*
-				 * well, possibly buggy BIOS...
-				 */
-				printk(KERN_WARNING "EHCI early BIOS handoff "
-						"failed (BIOS bug ?)\n");
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						EHCI_USBLEGSUP_OS);
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						0);
-			}
-		}
-	}
-
-	/*
-	 * halt EHCI & disable its interrupts in any case
-	 */
-	val = readl(op_reg_base + EHCI_USBSTS);
-	if ((val & EHCI_USBSTS_HALTED) == 0) {
-		val = readl(op_reg_base + EHCI_USBCMD);
-		val &= ~EHCI_USBCMD_RUN;
-		writel(val, op_reg_base + EHCI_USBCMD);
-
-		wait_time = 2000;
-		delta = 100;
-		do {
-			writel(0x3f, op_reg_base + EHCI_USBSTS);
-			udelay(delta);
-			wait_time -= delta;
-			val = readl(op_reg_base + EHCI_USBSTS);
-			if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
-				break;
-			}
-		} while (wait_time > 0);
-	}
-	writel(0, op_reg_base + EHCI_USBINTR);
-	writel(0x3f, op_reg_base + EHCI_USBSTS);
-
-	iounmap(base);
-
-	return;
-}
-
-
-
-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
-{
-	if (!usb_early_handoff)
-		return;
-
-	if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */
-		quirk_usb_handoff_uhci(pdev);
-	} else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */
-		quirk_usb_handoff_ohci(pdev);
-	} else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */
-		quirk_usb_disable_ehci(pdev);
-	}
-
-	return;
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
-
 /*
  * ... This is further complicated by the fact that some SiS96x south
  * bridges pretend to be 85C503/5513 instead.  In that case see if we
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 49bd217..598a115 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
 
 #include "pci.h"
 
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index c071790..87fafc0 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -13,7 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <asm/uaccess.h>
-
+#include "pci.h"
 
 asmlinkage long
 sys_pciconfig_read(unsigned long bus, unsigned long dfn,
@@ -38,13 +38,13 @@
 	lock_kernel();
 	switch (len) {
 	case 1:
-		cfg_ret = pci_read_config_byte(dev, off, &byte);
+		cfg_ret = pci_user_read_config_byte(dev, off, &byte);
 		break;
 	case 2:
-		cfg_ret = pci_read_config_word(dev, off, &word);
+		cfg_ret = pci_user_read_config_word(dev, off, &word);
 		break;
 	case 4:
-		cfg_ret = pci_read_config_dword(dev, off, &dword);
+		cfg_ret = pci_user_read_config_dword(dev, off, &dword);
 		break;
 	default:
 		err = -EINVAL;
@@ -112,7 +112,7 @@
 		err = get_user(byte, (u8 __user *)buf);
 		if (err)
 			break;
-		err = pci_write_config_byte(dev, off, byte);
+		err = pci_user_write_config_byte(dev, off, byte);
 		if (err != PCIBIOS_SUCCESSFUL)
 			err = -EIO;
 		break;
@@ -121,7 +121,7 @@
 		err = get_user(word, (u16 __user *)buf);
 		if (err)
 			break;
-		err = pci_write_config_word(dev, off, word);
+		err = pci_user_write_config_word(dev, off, word);
 		if (err != PCIBIOS_SUCCESSFUL)
 			err = -EIO;
 		break;
@@ -130,7 +130,7 @@
 		err = get_user(dword, (u32 __user *)buf);
 		if (err)
 			break;
-		err = pci_write_config_dword(dev, off, dword);
+		err = pci_user_write_config_dword(dev, off, dword);
 		if (err != PCIBIOS_SUCCESSFUL)
 			err = -EIO;
 		break;
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index cb4861d..fe37541 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -43,9 +43,11 @@
 au1x00_ss-y					+= au1000_generic.o
 au1x00_ss-$(CONFIG_MIPS_PB1000)			+= au1000_pb1x00.o
 au1x00_ss-$(CONFIG_MIPS_PB1100)			+= au1000_pb1x00.o
+au1x00_ss-$(CONFIG_MIPS_PB1200)			+= au1000_db1x00.o
 au1x00_ss-$(CONFIG_MIPS_PB1500)			+= au1000_pb1x00.o
 au1x00_ss-$(CONFIG_MIPS_DB1000)			+= au1000_db1x00.o
 au1x00_ss-$(CONFIG_MIPS_DB1100)			+= au1000_db1x00.o
+au1x00_ss-$(CONFIG_MIPS_DB1200)                 += au1000_db1x00.o
 au1x00_ss-$(CONFIG_MIPS_DB1500)			+= au1000_db1x00.o
 au1x00_ss-$(CONFIG_MIPS_DB1550)			+= au1000_db1x00.o
 au1x00_ss-$(CONFIG_MIPS_XXS1500)               += au1000_xxs1500.o
@@ -58,6 +60,7 @@
 sa1100_cs-y					+= sa1100_generic.o
 sa1100_cs-$(CONFIG_SA1100_ASSABET)		+= sa1100_assabet.o
 sa1100_cs-$(CONFIG_SA1100_CERF)			+= sa1100_cerf.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE)              += pxa2xx_sharpsl.o
 sa1100_cs-$(CONFIG_SA1100_H3600)		+= sa1100_h3600.o
 sa1100_cs-$(CONFIG_SA1100_SHANNON)		+= sa1100_shannon.o
 sa1100_cs-$(CONFIG_SA1100_SIMPAD)		+= sa1100_simpad.o
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c
index 42cf8bf..24cfee1 100644
--- a/drivers/pcmcia/au1000_db1x00.c
+++ b/drivers/pcmcia/au1000_db1x00.c
@@ -40,7 +40,15 @@
 #include <asm/irq.h>
 #include <asm/signal.h>
 #include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-db1x00/db1x00.h>
+
+#if defined(CONFIG_MIPS_DB1200)
+	#include <db1200.h>
+#elif defined(CONFIG_MIPS_PB1200)
+	#include <pb1200.h>
+#else
+	#include <asm/mach-db1x00/db1x00.h>
+	static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+#endif
 
 #include "au1000_generic.h"
 
@@ -50,7 +58,6 @@
 #define debug(x,args...)
 #endif
 
-static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
 
 struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS];
 extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int);
@@ -59,6 +66,8 @@
 {
 #ifdef CONFIG_MIPS_DB1550
 	skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3;
+#elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
+	skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT;
 #else
 	skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2;
 #endif
@@ -85,11 +94,19 @@
 	switch (skt->nr) {
 	case 0:
 		vs = bcsr->status & 0x3;
+#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
+		inserted = BOARD_CARD_INSERTED(0);
+#else
 		inserted = !(bcsr->status & (1<<4));
+#endif
 		break;
 	case 1:
 		vs = (bcsr->status & 0xC)>>2;
+#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
+		inserted = BOARD_CARD_INSERTED(1);
+#else
 		inserted = !(bcsr->status & (1<<5));
+#endif
 		break;
 	default:/* should never happen */
 		return;
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 470ef75..ba48cef 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -490,7 +490,7 @@
 		flush_scheduled_work();
 		skt->ops->hw_shutdown(skt);
 		au1x00_pcmcia_config_skt(skt, &dead_socket);
-		iounmap(skt->virt_io);
+		iounmap(skt->virt_io + (u32)mips_io_port_base);
 		skt->virt_io = NULL;
 	}
 
@@ -519,36 +519,15 @@
 }
 
 
-static int au1x00_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int au1x00_drv_pcmcia_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
-
 static struct device_driver au1x00_pcmcia_driver = {
 	.probe		= au1x00_drv_pcmcia_probe,
 	.remove		= au1x00_drv_pcmcia_remove,
 	.name		= "au1x00-pcmcia",
 	.bus		= &platform_bus_type,
-	.suspend	= au1x00_drv_pcmcia_suspend,
-	.resume		= au1x00_drv_pcmcia_resume
+	.suspend	= pcmcia_socket_dev_suspend,
+	.resume		= pcmcia_socket_dev_resume,
 };
 
-static struct platform_device au1x00_device = {
-	.name = "au1x00-pcmcia",
-	.id = 0,
-};
 
 /* au1x00_pcmcia_init()
  *
@@ -562,7 +541,6 @@
 	int error = 0;
 	if ((error = driver_register(&au1x00_pcmcia_driver)))
 		return error;
-	platform_device_register(&au1x00_device);
 	return error;
 }
 
@@ -573,7 +551,6 @@
 static void __exit au1x00_pcmcia_exit(void)
 {
 	driver_unregister(&au1x00_pcmcia_driver);
-	platform_device_unregister(&au1x00_device);
 }
 
 module_init(au1x00_pcmcia_init);
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index d5122b1..b0e7908 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -44,13 +44,13 @@
 /* pcmcia socket 1 needs external glue logic so the memory map
  * differs from board to board.
  */
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550)
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_PB1200)
 #define AU1X_SOCK1_IO        0xF08000000
 #define AU1X_SOCK1_PHYS_ATTR 0xF48000000
 #define AU1X_SOCK1_PHYS_MEM  0xF88000000
 #define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000
 #define AU1X_SOCK1_PSEUDO_PHYS_MEM  0xF8800000
-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550)
+#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || defined(CONFIG_MIPS_DB1200)
 #define AU1X_SOCK1_IO        0xF04000000
 #define AU1X_SOCK1_PHYS_ATTR 0xF44000000
 #define AU1X_SOCK1_PHYS_MEM  0xF84000000
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 080608c..39d096b 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1157,7 +1157,8 @@
 	.requery = pcmcia_bus_rescan,
 };
 
-static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
+static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
+					   struct class_interface *class_intf)
 {
 	struct pcmcia_socket *socket = class_get_devdata(class_dev);
 	int ret;
@@ -1192,7 +1193,8 @@
 	return 0;
 }
 
-static void pcmcia_bus_remove_socket(struct class_device *class_dev)
+static void pcmcia_bus_remove_socket(struct class_device *class_dev,
+				     struct class_interface *class_intf)
 {
 	struct pcmcia_socket *socket = class_get_devdata(class_dev);
 
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 316f8bc..b57a0b9 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -844,27 +844,11 @@
 	local_irq_restore(flags);
 }
 
-static int hd64465_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int hd64465_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
 static struct device_driver hd64465_driver = {
 	.name = "hd64465-pcmcia",
 	.bus = &platform_bus_type,
-	.suspend = hd64465_suspend,
-	.resume = hd64465_resume,
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device hd64465_device = {
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index a713015..4a41f67 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1332,27 +1332,11 @@
 
 /*====================================================================*/
 
-static int i82365_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int i82365_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
 static struct device_driver i82365_driver = {
 	.name = "i82365",
 	.bus = &platform_bus_type,
-	.suspend = i82365_suspend,
-	.resume = i82365_resume,
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device i82365_device = {
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 65f3ee3..c6ed70e 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -731,28 +731,11 @@
 
 /*====================================================================*/
 
-static int m32r_pcc_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int m32r_pcc_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
-
 static struct device_driver pcc_driver = {
 	.name = "cfc",
 	.bus = &platform_bus_type,
-	.suspend = m32r_pcc_suspend,
-	.resume = m32r_pcc_resume,
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device pcc_device = {
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 7b14d7e..3397ff2 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -695,28 +695,11 @@
 
 /*====================================================================*/
 
-static int m32r_pcc_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int m32r_pcc_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
-
 static struct device_driver pcc_driver = {
 	.name = "pcc",
 	.bus = &platform_bus_type,
-	.suspend = m32r_pcc_suspend,
-	.resume = m32r_pcc_resume,
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device pcc_device = {
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 94be9e5..2558c3c 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -329,27 +329,13 @@
 	return 0;
 }
 
-static int omap_cf_suspend(struct device *dev, pm_message_t mesg, u32 level)
-{
-	if (level != SUSPEND_SAVE_STATE)
-		return 0;
-	return pcmcia_socket_dev_suspend(dev, mesg);
-}
-
-static int omap_cf_resume(struct device *dev, u32 level)
-{
-	if (level != RESUME_RESTORE_STATE)
-		return 0;
-	return pcmcia_socket_dev_resume(dev);
-}
-
 static struct device_driver omap_cf_driver = {
 	.name		= (char *) driver_name,
 	.bus		= &platform_bus_type,
 	.probe		= omap_cf_probe,
 	.remove		= __devexit_p(omap_cf_remove),
-	.suspend 	= omap_cf_suspend,
-	.resume 	= omap_cf_resume,
+	.suspend 	= pcmcia_socket_dev_suspend,
+	.resume 	= pcmcia_socket_dev_resume,
 };
 
 static int __init omap_cf_init(void)
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 325c992..c2a12d5 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -205,32 +205,20 @@
 }
 EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe);
 
-static int pxa2xx_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxa2xx_drv_pcmcia_resume(struct device *dev)
 {
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
+	struct pcmcia_low_level *ops = dev->platform_data;
+	int nr = ops ? ops->nr : 0;
 
-static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-	{
-		struct pcmcia_low_level *ops = dev->platform_data;
-		int nr = ops ? ops->nr : 0;
+	MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
 
-		MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
-		ret = pcmcia_socket_dev_resume(dev);
-	}
-	return ret;
+	return pcmcia_socket_dev_resume(dev);
 }
 
 static struct device_driver pxa2xx_pcmcia_driver = {
 	.probe		= pxa2xx_drv_pcmcia_probe,
 	.remove		= soc_common_drv_pcmcia_remove,
-	.suspend 	= pxa2xx_drv_pcmcia_suspend,
+	.suspend 	= pcmcia_socket_dev_suspend,
 	.resume 	= pxa2xx_drv_pcmcia_resume,
 	.name		= "pxa2xx-pcmcia",
 	.bus		= &platform_bus_type,
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index a1178a6..bd92433 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -18,10 +18,15 @@
 #include <linux/interrupt.h>
 #include <linux/device.h>
 
+#include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/hardware/scoop.h>
-#include <asm/arch/pxa-regs.h>
+#ifdef CONFIG_SA1100_COLLIE
+#include <asm/arch-sa1100/collie.h>
+#else
+#include <asm/arch-pxa/pxa-regs.h>
+#endif
 
 #include "soc_common.h"
 
@@ -38,6 +43,7 @@
 {
 	int ret;
 
+#ifndef CONFIG_SA1100_COLLIE
 	/*
 	 * Setup default state of GPIO outputs
 	 * before we enable them as outputs.
@@ -60,6 +66,7 @@
 	pxa_gpio_mode(GPIO55_nPREG_MD);
 	pxa_gpio_mode(GPIO56_nPWAIT_MD);
 	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+#endif
 
 	/* Register interrupts */
 	if (scoop_devs[skt->nr].cd_irq >= 0) {
@@ -213,12 +220,20 @@
 	write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0);
 	write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101);
 	scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
+
+	if (machine_is_collie())
+		/* We need to disable SS_OUTPUT_ENA here. */
+		write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080);
 }
 
 static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
 	/* CF_BUS_OFF */
 	sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
+
+	if (machine_is_collie())
+		/* We need to disable SS_OUTPUT_ENA here. */
+		write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080);
 }
 
 static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -235,6 +250,19 @@
 
 static struct platform_device *sharpsl_pcmcia_device;
 
+#ifdef CONFIG_SA1100_COLLIE
+int __init pcmcia_collie_init(struct device *dev)
+{
+       int ret = -ENODEV;
+
+       if (machine_is_collie())
+               ret = sa11xx_drv_pcmcia_probe(dev, &sharpsl_pcmcia_ops, 0, 1);
+
+       return ret;
+}
+
+#else
+
 static int __init sharpsl_pcmcia_init(void)
 {
 	int ret;
@@ -269,6 +297,7 @@
 
 fs_initcall(sharpsl_pcmcia_init);
 module_exit(sharpsl_pcmcia_exit);
+#endif
 
 MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support");
 MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index f9a5c70..00960a3 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -779,7 +779,7 @@
 	if (!s->cb_dev || !s->cb_dev->bus)
 		return -ENODEV;
 
-#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
+#if defined(CONFIG_X86)
 	/* If this is the root bus, the risk of hitting
 	 * some strange system devices which aren't protected
 	 * by either ACPI resource tables or properly requested
@@ -994,7 +994,8 @@
 	NULL,
 };
 
-static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev,
+					   struct class_interface *class_intf)
 {
 	struct pcmcia_socket *s = class_get_devdata(class_dev);
 	struct class_device_attribute **attr;
@@ -1011,7 +1012,8 @@
 	return ret;
 }
 
-static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev,
+					       struct class_interface *class_intf)
 {
 	struct pcmcia_socket *s = class_get_devdata(class_dev);
 	struct class_device_attribute **attr;
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index d4ed508..acf60ff 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -38,8 +38,12 @@
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
+#include <asm/hardware/scoop.h>
+
 #include "sa1100_generic.h"
 
+int __init pcmcia_collie_init(struct device *dev);
+
 static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
 #ifdef CONFIG_SA1100_ASSABET
 	pcmcia_assabet_init,
@@ -56,6 +60,9 @@
 #ifdef CONFIG_SA1100_SIMPAD
 	pcmcia_simpad_init,
 #endif
+#ifdef CONFIG_SA1100_COLLIE
+       pcmcia_collie_init,
+#endif
 };
 
 static int sa11x0_drv_pcmcia_probe(struct device *dev)
@@ -74,29 +81,13 @@
 	return ret;
 }
 
-static int sa11x0_drv_pcmcia_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int sa11x0_drv_pcmcia_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
 static struct device_driver sa11x0_pcmcia_driver = {
 	.probe		= sa11x0_drv_pcmcia_probe,
 	.remove		= soc_common_drv_pcmcia_remove,
 	.name		= "sa11x0-pcmcia",
 	.bus		= &platform_bus_type,
-	.suspend 	= sa11x0_drv_pcmcia_suspend,
-	.resume 	= sa11x0_drv_pcmcia_resume,
+	.suspend 	= pcmcia_socket_dev_suspend,
+	.resume 	= pcmcia_socket_dev_resume,
 };
 
 /* sa11x0_pcmcia_init()
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index bb90a14..81ded52 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -122,7 +122,7 @@
 
 static int pcmcia_probe(struct sa1111_dev *dev)
 {
-	char *base;
+	void __iomem *base;
 
 	if (!request_mem_region(dev->res.start, 512,
 				SA1111_DRIVER_NAME(dev)))
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 1040a6c..4a3150a 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -341,7 +341,8 @@
 	.write = pccard_store_cis,
 };
 
-static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev,
+					     struct class_interface *class_intf)
 {
 	struct class_device_attribute **attr;
 	int ret = 0;
@@ -357,7 +358,8 @@
 	return ret;
 }
 
-static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev,
+						 struct class_interface *class_intf)
 {
 	struct class_device_attribute **attr;
 
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index d5a61ea..f158b67 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -372,27 +372,11 @@
 
 /*====================================================================*/
 
-static int tcic_drv_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int ret = 0;
-	if (level == SUSPEND_SAVE_STATE)
-		ret = pcmcia_socket_dev_suspend(dev, state);
-	return ret;
-}
-
-static int tcic_drv_resume(struct device *dev, u32 level)
-{
-	int ret = 0;
-	if (level == RESUME_RESTORE_STATE)
-		ret = pcmcia_socket_dev_resume(dev);
-	return ret;
-}
-
 static struct device_driver tcic_driver = {
 	.name = "tcic-pcmcia",
 	.bus = &platform_bus_type,
-	.suspend = tcic_drv_suspend,
-	.resume = tcic_drv_resume,
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device tcic_device = {
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 17bb2da..3d2dca6 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -774,31 +774,11 @@
 
 __setup("vrc4171_card=", vrc4171_card_setup);
 
-static int vrc4171_card_suspend(struct device *dev, pm_message_t state, u32 level)
-{
-	int retval = 0;
-
-	if (level == SUSPEND_SAVE_STATE)
-		retval = pcmcia_socket_dev_suspend(dev, state);
-
-	return retval;
-}
-
-static int vrc4171_card_resume(struct device *dev, u32 level)
-{
-	int retval = 0;
-
-	if (level == RESUME_RESTORE_STATE)
-		retval = pcmcia_socket_dev_resume(dev);
-
-	return retval;
-}
-
 static struct device_driver vrc4171_card_driver = {
 	.name		= vrc4171_card_name,
 	.bus		= &platform_bus_type,
-	.suspend	= vrc4171_card_suspend,
-	.resume		= vrc4171_card_resume,
+	.suspend	= pcmcia_socket_dev_suspend,
+	.resume		= pcmcia_socket_dev_resume,
 };
 
 static int __devinit vrc4171_card_init(void)
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index db9f952..ec6ab65 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -151,6 +151,40 @@
 	readb(socket->base + 0x800 + reg + 1);
 }
 
+static ssize_t show_yenta_registers(struct device *yentadev, struct device_attribute *attr, char *buf)
+{
+	struct pci_dev *dev = to_pci_dev(yentadev);
+	struct yenta_socket *socket = pci_get_drvdata(dev);
+	int offset = 0, i;
+
+	offset = snprintf(buf, PAGE_SIZE, "CB registers:");
+	for (i = 0; i < 0x24; i += 4) {
+		unsigned val;
+		if (!(i & 15))
+			offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+		val = cb_readl(socket, i);
+		offset += snprintf(buf + offset, PAGE_SIZE - offset, " %08x", val);
+	}
+
+	offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n\nExCA registers:");
+	for (i = 0; i < 0x45; i++) {
+		unsigned char val;
+		if (!(i & 7)) {
+			if (i & 8) {
+				memcpy(buf + offset, " -", 2);
+				offset += 2;
+			} else
+				offset += snprintf(buf + offset, PAGE_SIZE - offset, "\n%02x:", i);
+		}
+		val = exca_readb(socket, i);
+		offset += snprintf(buf + offset, PAGE_SIZE - offset, " %02x", val);
+	}
+	buf[offset++] = '\n';
+	return offset;
+}
+
+static DEVICE_ATTR(yenta_registers, S_IRUSR, show_yenta_registers, NULL);
+
 /*
  * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
  * on what kind of card is inserted..
@@ -765,6 +799,9 @@
 {
 	struct yenta_socket *sock = pci_get_drvdata(dev);
 
+	/* Remove the register attributes */
+	device_remove_file(&dev->dev, &dev_attr_yenta_registers);
+
 	/* we don't want a dying socket registered */
 	pcmcia_unregister_socket(&sock->socket);
 	
@@ -1138,8 +1175,11 @@
 
 	/* Register it with the pcmcia layer.. */
 	ret = pcmcia_register_socket(&socket->socket);
-	if (ret == 0)
+	if (ret == 0) {
+		/* Add the yenta register attributes */
+		device_create_file(&dev->dev, &dev_attr_yenta_registers);
 		goto out;
+	}
 
  unmap:
 	iounmap(socket->base);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 94442ff..cbb2749 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pnp.h>
+#include <linux/slab.h>
+#include <linux/bitmap.h>
 #include "base.h"
 
 DECLARE_MUTEX(pnp_res_mutex);
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index b0ca65b..5e38cd7 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -7,6 +7,8 @@
 #include <linux/ctype.h>
 #include <linux/pnp.h>
 #include <linux/pnpbios.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index fc7a213..c570a9f 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -213,6 +213,9 @@
 	struct string *s, *n;
 	int rc;
 
+	if (cp->view.dev)
+		raw3270_activate_view(&cp->view);
+
 	wrq = xchg(&cp->write, 0);
 	if (!wrq) {
 		con3270_set_timer(cp, 1);
@@ -489,8 +492,6 @@
 	unsigned char c;
 
 	cp = condev;
-	if (cp->view.dev)
-		raw3270_activate_view(&cp->view);
 	spin_lock_irqsave(&cp->view.lock, flags);
 	while (count-- > 0) {
 		c = *str++;
@@ -620,7 +621,7 @@
 		     (void (*)(unsigned long)) con3270_read_tasklet,
 		     (unsigned long) condev->read);
 
-	raw3270_add_view(&condev->view, &con3270_fn, 0);
+	raw3270_add_view(&condev->view, &con3270_fn, 1);
 
 	INIT_LIST_HEAD(&condev->freemem);
 	for (i = 0; i < CON3270_STRING_PAGES; i++) {
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 60afcdc..735a7fc 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -33,8 +33,11 @@
 	int read_command;		/* ccw command to use for reads. */
 	int write_command;		/* ccw command to use for writes. */
 	int attention;			/* Got attention. */
-	struct raw3270_request *clear;	/* single clear request. */
-	wait_queue_head_t attn_wait;	/* Attention wait queue. */
+	int active;			/* Fullscreen view is active. */
+	struct raw3270_request *init;	/* single init request. */
+	wait_queue_head_t wait;		/* Init & attention wait queue. */
+	struct idal_buffer *rdbuf;	/* full-screen-deactivate buffer */
+	size_t rdbuf_size;		/* size of data returned by RDBUF */
 };
 
 static void
@@ -43,58 +46,172 @@
 	wake_up((wait_queue_head_t *) data);
 }
 
+static inline int
+fs3270_working(struct fs3270 *fp)
+{
+	/*
+	 * The fullscreen view is in working order if the view
+	 * has been activated AND the initial request is finished.
+	 */
+	return fp->active && raw3270_request_final(fp->init);
+}
+
 static int
 fs3270_do_io(struct raw3270_view *view, struct raw3270_request *rq)
 {
-	wait_queue_head_t wq;
+	struct fs3270 *fp;
 	int rc;
 
-	init_waitqueue_head(&wq);
+	fp = (struct fs3270 *) view;
 	rq->callback = fs3270_wake_up;
-	rq->callback_data = &wq;
-	rc = raw3270_start(view, rq);
-	if (rc)
-		return rc;
-	/* Started sucessfully. Now wait for completion. */
-	wait_event(wq, raw3270_request_final(rq));
-	return rq->rc;
-}
+	rq->callback_data = &fp->wait;
 
-static void
-fs3270_reset_callback(struct raw3270_request *rq, void *data)
-{
-	raw3270_request_reset(rq);
+	do {
+		if (!fs3270_working(fp)) {
+			/* Fullscreen view isn't ready yet. */
+			rc = wait_event_interruptible(fp->wait,
+						      fs3270_working(fp));
+			if (rc != 0)
+				break;
+		}
+		rc = raw3270_start(view, rq);
+		if (rc == 0) {
+			/* Started sucessfully. Now wait for completion. */
+			wait_event(fp->wait, raw3270_request_final(rq));
+		}
+	} while (rc == -EACCES);
+	return rc;
 }
 
 /*
  * Switch to the fullscreen view.
  */
+static void
+fs3270_reset_callback(struct raw3270_request *rq, void *data)
+{
+	struct fs3270 *fp;
+
+	fp = (struct fs3270 *) rq->view;
+	raw3270_request_reset(rq);
+	wake_up(&fp->wait);
+}
+
+static void
+fs3270_restore_callback(struct raw3270_request *rq, void *data)
+{
+	struct fs3270 *fp;
+
+	fp = (struct fs3270 *) rq->view;
+	if (rq->rc != 0 || rq->rescnt != 0) {
+		if (fp->fs_pid)
+			kill_proc(fp->fs_pid, SIGHUP, 1);
+	}
+	fp->rdbuf_size = 0;
+	raw3270_request_reset(rq);
+	wake_up(&fp->wait);
+}
+
 static int
 fs3270_activate(struct raw3270_view *view)
 {
 	struct fs3270 *fp;
+	char *cp;
+	int rc;
 
 	fp = (struct fs3270 *) view;
-	raw3270_request_set_cmd(fp->clear, TC_EWRITEA);
-	fp->clear->callback = fs3270_reset_callback;
-	return raw3270_start(view, fp->clear);
+
+	/* If an old init command is still running just return. */
+	if (!raw3270_request_final(fp->init))
+		return 0;
+
+	if (fp->rdbuf_size == 0) {
+		/* No saved buffer. Just clear the screen. */
+		raw3270_request_set_cmd(fp->init, TC_EWRITEA);
+		fp->init->callback = fs3270_reset_callback;
+	} else {
+		/* Restore fullscreen buffer saved by fs3270_deactivate. */
+		raw3270_request_set_cmd(fp->init, TC_EWRITEA);
+		raw3270_request_set_idal(fp->init, fp->rdbuf);
+		fp->init->ccw.count = fp->rdbuf_size;
+		cp = fp->rdbuf->data[0];
+		cp[0] = TW_KR;
+		cp[1] = TO_SBA;
+		cp[2] = cp[6];
+		cp[3] = cp[7];
+		cp[4] = TO_IC;
+		cp[5] = TO_SBA;
+		cp[6] = 0x40;
+		cp[7] = 0x40;
+		fp->init->rescnt = 0;
+		fp->init->callback = fs3270_restore_callback;
+	}
+	rc = fp->init->rc = raw3270_start_locked(view, fp->init);
+	if (rc)
+		fp->init->callback(fp->init, NULL);
+	else
+		fp->active = 1;
+	return rc;
 }
 
 /*
  * Shutdown fullscreen view.
  */
 static void
+fs3270_save_callback(struct raw3270_request *rq, void *data)
+{
+	struct fs3270 *fp;
+
+	fp = (struct fs3270 *) rq->view;
+
+	/* Correct idal buffer element 0 address. */
+	fp->rdbuf->data[0] -= 5;
+	fp->rdbuf->size += 5;
+
+	/*
+	 * If the rdbuf command failed or the idal buffer is
+	 * to small for the amount of data returned by the
+	 * rdbuf command, then we have no choice but to send
+	 * a SIGHUP to the application.
+	 */
+	if (rq->rc != 0 || rq->rescnt == 0) {
+		if (fp->fs_pid)
+			kill_proc(fp->fs_pid, SIGHUP, 1);
+		fp->rdbuf_size = 0;
+	} else
+		fp->rdbuf_size = fp->rdbuf->size - rq->rescnt;
+	raw3270_request_reset(rq);
+	wake_up(&fp->wait);
+}
+
+static void
 fs3270_deactivate(struct raw3270_view *view)
 {
-	// FIXME: is this a good idea? The user program using fullscreen 3270
-	// will die just because a console message appeared. On the other
-	// hand the fullscreen device is unoperational now.
 	struct fs3270 *fp;
 
 	fp = (struct fs3270 *) view;
-	if (fp->fs_pid != 0)
-		kill_proc(fp->fs_pid, SIGHUP, 1);
-	fp->fs_pid = 0;
+	fp->active = 0;
+
+	/* If an old init command is still running just return. */
+	if (!raw3270_request_final(fp->init))
+		return;
+
+	/* Prepare read-buffer request. */
+	raw3270_request_set_cmd(fp->init, TC_RDBUF);
+	/*
+	 * Hackish: skip first 5 bytes of the idal buffer to make
+	 * room for the TW_KR/TO_SBA/<address>/<address>/TO_IC sequence
+	 * in the activation command.
+	 */
+	fp->rdbuf->data[0] += 5;
+	fp->rdbuf->size -= 5;
+	raw3270_request_set_idal(fp->init, fp->rdbuf);
+	fp->init->rescnt = 0;
+	fp->init->callback = fs3270_save_callback;
+
+	/* Start I/O to read in the 3270 buffer. */
+	fp->init->rc = raw3270_start_locked(view, fp->init);
+	if (fp->init->rc)
+		fp->init->callback(fp->init, NULL);
 }
 
 static int
@@ -103,7 +220,7 @@
 	/* Handle ATTN. Set indication and wake waiters for attention. */
 	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
 		fp->attention = 1;
-		wake_up(&fp->attn_wait);
+		wake_up(&fp->wait);
 	}
 
 	if (rq) {
@@ -125,7 +242,7 @@
 	struct fs3270 *fp;
 	struct raw3270_request *rq;
 	struct idal_buffer *ib;
-	int rc;
+	ssize_t rc;
 	
 	if (count == 0 || count > 65535)
 		return -EINVAL;
@@ -133,7 +250,7 @@
 	if (!fp)
 		return -ENODEV;
 	ib = idal_buffer_alloc(count, 0);
-	if (!ib)
+	if (IS_ERR(ib))
 		return -ENOMEM;
 	rq = raw3270_request_alloc(0);
 	if (!IS_ERR(rq)) {
@@ -141,10 +258,19 @@
 			fp->read_command = 6;
 		raw3270_request_set_cmd(rq, fp->read_command ? : 2);
 		raw3270_request_set_idal(rq, ib);
-		wait_event(fp->attn_wait, fp->attention);
-		rc = fs3270_do_io(&fp->view, rq);
-		if (rc == 0 && idal_buffer_to_user(ib, data, count))
-			rc = -EFAULT;
+		rc = wait_event_interruptible(fp->wait, fp->attention);
+		fp->attention = 0;
+		if (rc == 0) {
+			rc = fs3270_do_io(&fp->view, rq);
+			if (rc == 0) {
+				count -= rq->rescnt;
+				if (idal_buffer_to_user(ib, data, count) != 0)
+					rc = -EFAULT;
+				else
+					rc = count;
+
+			}
+		}
 		raw3270_request_free(rq);
 	} else
 		rc = PTR_ERR(rq);
@@ -162,13 +288,13 @@
 	struct raw3270_request *rq;
 	struct idal_buffer *ib;
 	int write_command;
-	int rc;
+	ssize_t rc;
 
 	fp = filp->private_data;
 	if (!fp)
 		return -ENODEV;
 	ib = idal_buffer_alloc(count, 0);
-	if (!ib)
+	if (IS_ERR(ib))
 		return -ENOMEM;
 	rq = raw3270_request_alloc(0);
 	if (!IS_ERR(rq)) {
@@ -179,6 +305,8 @@
 			raw3270_request_set_cmd(rq, write_command);
 			raw3270_request_set_idal(rq, ib);
 			rc = fs3270_do_io(&fp->view, rq);
+			if (rc == 0)
+				rc = count - rq->rescnt;
 		} else
 			rc = -EFAULT;
 		raw3270_request_free(rq);
@@ -232,7 +360,7 @@
 }
 
 /*
- * Allocate tty3270 structure.
+ * Allocate fs3270 structure.
  */
 static struct fs3270 *
 fs3270_alloc_view(void)
@@ -243,8 +371,8 @@
 	if (!fp)
 		return ERR_PTR(-ENOMEM);
 	memset(fp, 0, sizeof(struct fs3270));
-	fp->clear = raw3270_request_alloc(0);
-	if (!IS_ERR(fp->clear)) {
+	fp->init = raw3270_request_alloc(0);
+	if (IS_ERR(fp->init)) {
 		kfree(fp);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -252,12 +380,17 @@
 }
 
 /*
- * Free tty3270 structure.
+ * Free fs3270 structure.
  */
 static void
 fs3270_free_view(struct raw3270_view *view)
 {
-	raw3270_request_free(((struct fs3270 *) view)->clear);
+	struct fs3270 *fp;
+
+	fp = (struct fs3270 *) view;
+	if (fp->rdbuf)
+		idal_buffer_free(fp->rdbuf);
+	raw3270_request_free(((struct fs3270 *) view)->init);
 	kfree(view);
 }
 
@@ -285,11 +418,20 @@
 fs3270_open(struct inode *inode, struct file *filp)
 {
 	struct fs3270 *fp;
+	struct idal_buffer *ib;
 	int minor, rc;
 
 	if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR)
 		return -ENODEV;
 	minor = iminor(filp->f_dentry->d_inode);
+	/* Check for minor 0 multiplexer. */
+	if (minor == 0) {
+		if (!current->signal->tty)
+			return -ENODEV;
+		if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR)
+			return -ENODEV;
+		minor = current->signal->tty->index + RAW3270_FIRSTMINOR;
+	}
 	/* Check if some other program is already using fullscreen mode. */
 	fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
 	if (!IS_ERR(fp)) {
@@ -301,7 +443,7 @@
 	if (IS_ERR(fp))
 		return PTR_ERR(fp);
 
-	init_waitqueue_head(&fp->attn_wait);
+	init_waitqueue_head(&fp->wait);
 	fp->fs_pid = current->pid;
 	rc = raw3270_add_view(&fp->view, &fs3270_fn, minor);
 	if (rc) {
@@ -309,8 +451,18 @@
 		return rc;
 	}
 
+	/* Allocate idal-buffer. */
+	ib = idal_buffer_alloc(2*fp->view.rows*fp->view.cols + 5, 0);
+	if (IS_ERR(ib)) {
+		raw3270_put_view(&fp->view);
+		raw3270_del_view(&fp->view);
+		return PTR_ERR(fp);
+	}
+	fp->rdbuf = ib;
+
 	rc = raw3270_activate_view(&fp->view);
 	if (rc) {
+		raw3270_put_view(&fp->view);
 		raw3270_del_view(&fp->view);
 		return rc;
 	}
@@ -329,8 +481,12 @@
 
 	fp = filp->private_data;
 	filp->private_data = 0;
-	if (fp)
+	if (fp) {
+		fp->fs_pid = 0;
+		raw3270_reset(&fp->view);
+		raw3270_put_view(&fp->view);
 		raw3270_del_view(&fp->view);
+	}
 	return 0;
 }
 
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 328d9cb..d669464 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -25,6 +25,12 @@
 
 #include "raw3270.h"
 
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/device.h>
+
+struct class *class3270;
+
 /* The main 3270 data structure. */
 struct raw3270 {
 	struct list_head list;
@@ -41,6 +47,8 @@
 	struct timer_list timer;	/* Device timer. */
 
 	unsigned char *ascebc;		/* ascii -> ebcdic table */
+	struct class_device *clttydev;	/* 3270-class tty device ptr */
+	struct class_device *cltubdev;	/* 3270-class tub device ptr */
 };
 
 /* raw3270->flags */
@@ -317,6 +325,22 @@
 }
 
 int
+raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
+{
+	struct raw3270 *rp;
+	int rc;
+
+	rp = view->dev;
+	if (!rp || rp->view != view)
+		rc = -EACCES;
+	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
+		rc = -ENODEV;
+	else
+		rc =  __raw3270_start(rp, view, rq);
+	return rc;
+}
+
+int
 raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
 {
 	struct raw3270 *rp;
@@ -744,6 +768,22 @@
 	return rc;
 }
 
+int
+raw3270_reset(struct raw3270_view *view)
+{
+	struct raw3270 *rp;
+	int rc;
+
+	rp = view->dev;
+	if (!rp || rp->view != view)
+		rc = -EACCES;
+	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))
+		rc = -ENODEV;
+	else
+		rc = raw3270_reset_device(view->dev);
+	return rc;
+}
+
 /*
  * Setup new 3270 device.
  */
@@ -774,11 +814,12 @@
 
 	/*
 	 * Add device to list and find the smallest unused minor
-	 * number for it.
+	 * number for it. Note: there is no device with minor 0,
+	 * see special case for fs3270.c:fs3270_open().
 	 */
 	down(&raw3270_sem);
 	/* Keep the list sorted. */
-	minor = 0;
+	minor = RAW3270_FIRSTMINOR;
 	rp->minor = -1;
 	list_for_each(l, &raw3270_devices) {
 		tmp = list_entry(l, struct raw3270, list);
@@ -789,7 +830,7 @@
 		}
 		minor++;
 	}
-	if (rp->minor == -1 && minor < RAW3270_MAXDEVS) {
+	if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
 		rp->minor = minor;
 		list_add_tail(&rp->list, &raw3270_devices);
 	}
@@ -941,11 +982,12 @@
 		list_add_tail(&view->list, &rp->view_list);
 		/* Try to activate another view. */
 		if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
-			list_for_each_entry(view, &rp->view_list, list)
-				if (view->fn->activate(view) == 0) {
-					rp->view = view;
+			list_for_each_entry(view, &rp->view_list, list) {
+				rp->view = view;
+				if (view->fn->activate(view) == 0)
 					break;
-				}
+				rp->view = 0;
+			}
 		}
 	}
 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -961,6 +1003,8 @@
 	struct raw3270 *rp;
 	int rc;
 
+	if (minor <= 0)
+		return -ENODEV;
 	down(&raw3270_sem);
 	rc = -ENODEV;
 	list_for_each_entry(rp, &raw3270_devices, list) {
@@ -976,7 +1020,7 @@
 			view->cols = rp->cols;
 			view->ascebc = rp->ascebc;
 			spin_lock_init(&view->lock);
-			list_add_tail(&view->list, &rp->view_list);
+			list_add(&view->list, &rp->view_list);
 			rc = 0;
 		}
 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
@@ -1039,7 +1083,7 @@
 	if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) {
 		/* Try to activate another view. */
 		list_for_each_entry(nv, &rp->view_list, list) {
-			if (nv->fn->activate(view) == 0) {
+			if (nv->fn->activate(nv) == 0) {
 				rp->view = nv;
 				break;
 			}
@@ -1063,6 +1107,12 @@
 
 	/* Remove from device chain. */
 	down(&raw3270_sem);
+	if (rp->clttydev)
+		class_device_destroy(class3270,
+				     MKDEV(IBM_TTY3270_MAJOR, rp->minor));
+	if (rp->cltubdev)
+		class_device_destroy(class3270,
+				     MKDEV(IBM_FS3270_MAJOR, rp->minor));
 	list_del_init(&rp->list);
 	up(&raw3270_sem);
 
@@ -1129,6 +1179,16 @@
 {
 	//FIXME: check return code
 	sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
+	rp->clttydev =
+		class_device_create(class3270,
+				    MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+				    &rp->cdev->dev, "tty%s",
+				    rp->cdev->dev.bus_id);
+	rp->cltubdev =
+		class_device_create(class3270,
+				    MKDEV(IBM_FS3270_MAJOR, rp->minor),
+				    &rp->cdev->dev, "tub%s",
+				    rp->cdev->dev.bus_id);
 }
 
 /*
@@ -1189,13 +1249,13 @@
 		return PTR_ERR(rp);
 	rc = raw3270_reset_device(rp);
 	if (rc)
-		return rc;
+		goto failure;
 	rc = raw3270_size_device(rp);
 	if (rc)
-		return rc;
+		goto failure;
 	rc = raw3270_reset_device(rp);
 	if (rc)
-		return rc;
+		goto failure;
 	raw3270_create_attributes(rp);
 	set_bit(RAW3270_FLAGS_READY, &rp->flags);
 	down(&raw3270_sem);
@@ -1203,6 +1263,10 @@
 		np->notifier(rp->minor, 1);
 	up(&raw3270_sem);
 	return 0;
+
+failure:
+	raw3270_delete_device(rp);
+	return rc;
 }
 
 /*
@@ -1217,6 +1281,14 @@
 	struct raw3270_notifier *np;
 
 	rp = cdev->dev.driver_data;
+	/*
+	 * _remove is the opposite of _probe; it's probe that
+	 * should set up rp.  raw3270_remove gets entered for
+	 * devices even if they haven't been varied online.
+	 * Thus, rp may validly be NULL here.
+	 */
+	if (rp == NULL)
+		return;
 	clear_bit(RAW3270_FLAGS_READY, &rp->flags);
 
 	sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
@@ -1301,6 +1373,7 @@
 	if (rc == 0) {
 		/* Create attributes for early (= console) device. */
 		down(&raw3270_sem);
+		class3270 = class_create(THIS_MODULE, "3270");
 		list_for_each_entry(rp, &raw3270_devices, list) {
 			get_device(&rp->cdev->dev);
 			raw3270_create_attributes(rp);
@@ -1314,6 +1387,7 @@
 raw3270_exit(void)
 {
 	ccw_driver_unregister(&raw3270_ccw_driver);
+	class_destroy(class3270);
 }
 
 MODULE_LICENSE("GPL");
@@ -1335,7 +1409,9 @@
 EXPORT_SYMBOL(raw3270_activate_view);
 EXPORT_SYMBOL(raw3270_deactivate_view);
 EXPORT_SYMBOL(raw3270_start);
+EXPORT_SYMBOL(raw3270_start_locked);
 EXPORT_SYMBOL(raw3270_start_irq);
+EXPORT_SYMBOL(raw3270_reset);
 EXPORT_SYMBOL(raw3270_register_notifier);
 EXPORT_SYMBOL(raw3270_unregister_notifier);
 EXPORT_SYMBOL(raw3270_wait_queue);
diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h
index ed5d4eb..b635bf8 100644
--- a/drivers/s390/char/raw3270.h
+++ b/drivers/s390/char/raw3270.h
@@ -21,6 +21,7 @@
 
 /* Local Channel Commands */
 #define TC_WRITE	0x01		/* Write */
+#define TC_RDBUF	0x02		/* Read Buffer */
 #define TC_EWRITE	0x05		/* Erase write */
 #define TC_READMOD	0x06		/* Read modified */
 #define TC_EWRITEA	0x0d		/* Erase write alternate */
@@ -76,7 +77,8 @@
 #define TW_KR		0xc2		/* Keyboard restore */
 #define TW_PLUSALARM	0x04		/* Add this bit for alarm */
 
-#define RAW3270_MAXDEVS	256
+#define RAW3270_FIRSTMINOR	1	/* First minor number */
+#define RAW3270_MAXDEVS		255	/* Max number of 3270 devices */
 
 /* For TUBGETMOD and TUBSETMOD. Should include. */
 struct raw3270_iocb {
@@ -166,7 +168,10 @@
 void raw3270_deactivate_view(struct raw3270_view *);
 struct raw3270_view *raw3270_find_view(struct raw3270_fn *, int);
 int raw3270_start(struct raw3270_view *, struct raw3270_request *);
+int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *);
 int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *);
+int raw3270_reset(struct raw3270_view *);
+struct raw3270_view *raw3270_view(struct raw3270_view *);
 
 /* Reference count inliner for view structures. */
 static inline void
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index ed0cb1f..fcaee44 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -72,6 +72,7 @@
 
 	tcd->class_device = class_device_create(
 				tape_class,
+				NULL,
 				tcd->char_device->dev,
 				device,
 				"%s", tcd->device_name
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 7db5ebc..4b90693 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -653,18 +653,12 @@
 	tp->update_flags = TTY_UPDATE_ALL;
 	tty3270_set_timer(tp, 1);
 	spin_unlock_irqrestore(&tp->view.lock, flags);
-	start_tty(tp->tty);
 	return 0;
 }
 
 static void
 tty3270_deactivate(struct raw3270_view *view)
 {
-	struct tty3270 *tp;
-
-	tp = (struct tty3270 *) view;
-	if (tp && tp->tty)
-		stop_tty(tp->tty);
 }
 
 static int
@@ -716,13 +710,13 @@
 				  tp->freemem_pages[pages], PAGE_SIZE);
 	}
 	tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE);
-	if (!tp->write)
+	if (IS_ERR(tp->write))
 		goto out_pages;
 	tp->read = raw3270_request_alloc(0);
-	if (!tp->read)
+	if (IS_ERR(tp->read))
 		goto out_write;
 	tp->kreset = raw3270_request_alloc(1);
-	if (!tp->kreset)
+	if (IS_ERR(tp->kreset))
 		goto out_read;
 	tp->kbd = kbd_alloc();
 	if (!tp->kbd)
@@ -845,7 +839,8 @@
 	int i;
 
 	for (i = 0; i < tty3270_max_index; i++) {
-		tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, i);
+		tp = (struct tty3270 *)
+			raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);
 		if (!IS_ERR(tp))
 			raw3270_del_view(&tp->view);
 	}
@@ -871,7 +866,9 @@
 	if (tty->count > 1)
 		return 0;
 	/* Check if the tty3270 is already there. */
-	tp = (struct tty3270 *) raw3270_find_view(&tty3270_fn, tty->index);
+	tp = (struct tty3270 *)
+		raw3270_find_view(&tty3270_fn,
+				  tty->index + RAW3270_FIRSTMINOR);
 	if (!IS_ERR(tp)) {
 		tty->driver_data = tp;
 		tty->winsize.ws_row = tp->view.rows - 2;
@@ -903,7 +900,8 @@
 		     (void (*)(unsigned long)) tty3270_read_tasklet,
 		     (unsigned long) tp->read);
 
-	rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
+	rc = raw3270_add_view(&tp->view, &tty3270_fn,
+			      tty->index + RAW3270_FIRSTMINOR);
 	if (rc) {
 		tty3270_free_view(tp);
 		return rc;
@@ -911,8 +909,8 @@
 
 	rc = tty3270_alloc_screen(tp);
 	if (rc) {
-		raw3270_del_view(&tp->view);
 		raw3270_put_view(&tp->view);
+		raw3270_del_view(&tp->view);
 		return rc;
 	}
 
@@ -1780,7 +1778,7 @@
 	struct tty_driver *driver;
 	int ret;
 
-	driver = alloc_tty_driver(256);
+	driver = alloc_tty_driver(RAW3270_MAXDEVS);
 	if (!driver)
 		return -ENOMEM;
 
@@ -1794,6 +1792,7 @@
 	driver->driver_name = "ttyTUB";
 	driver->name = "ttyTUB";
 	driver->major = IBM_TTY3270_MAJOR;
+	driver->minor_start = RAW3270_FIRSTMINOR;
 	driver->type = TTY_DRIVER_TYPE_SYSTEM;
 	driver->subtype = SYSTEM_TYPE_TTY;
 	driver->init_termios = tty_std_termios;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 491f00c..b2d75de 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -788,6 +788,7 @@
 	}
 	priv->class_device = class_device_create(
 				vmlogrdr_class,
+				NULL,
 				MKDEV(vmlogrdr_major, priv->minor_num),
 				dev,
 				"%s", dev->bus_id );
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 8cc4f1a..c05b069 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -30,10 +30,13 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/timex.h>	/* get_clock() */
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
 #include <asm/cmb.h>
+#include <asm/div64.h>
 
 #include "cio.h"
 #include "css.h"
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 9adc11e..811c9d1 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -22,6 +22,7 @@
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
+#include <asm/param.h>		/* HZ */
 
 #include "cio.h"
 #include "css.h"
@@ -252,6 +253,23 @@
 }
 
 static ssize_t
+modalias_show (struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct ccw_device_id *id = &(cdev->id);
+	int ret;
+
+	ret = sprintf(buf, "ccw:t%04Xm%02x",
+			id->cu_type, id->cu_model);
+	if (id->dev_type != 0)
+		ret += sprintf(buf + ret, "dt%04Xdm%02X\n",
+				id->dev_type, id->dev_model);
+	else
+		ret += sprintf(buf + ret, "dtdm\n");
+	return ret;
+}
+
+static ssize_t
 online_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
@@ -448,6 +466,7 @@
 static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
 static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
 static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
+static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
 static DEVICE_ATTR(online, 0644, online_show, online_store);
 extern struct device_attribute dev_attr_cmb_enable;
 static DEVICE_ATTR(availability, 0444, available_show, NULL);
@@ -471,6 +490,7 @@
 static struct attribute * ccwdev_attrs[] = {
 	&dev_attr_devtype.attr,
 	&dev_attr_cutype.attr,
+	&dev_attr_modalias.attr,
 	&dev_attr_online.attr,
 	&dev_attr_cmb_enable.attr,
 	&dev_attr_availability.attr,
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index fbe4202..c1c89f4 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -11,6 +11,8 @@
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
 
 #include <asm/ccwdev.h>
 #include <asm/cio.h>
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index fa09440..38f50b7 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -16,7 +16,7 @@
 
 fsm_instance *
 init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
-		int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
+		int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
 {
 	int i;
 	fsm_instance *this;
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h
index f9a0110..1b8a7e7 100644
--- a/drivers/s390/net/fsm.h
+++ b/drivers/s390/net/fsm.h
@@ -110,7 +110,7 @@
 init_fsm(char *name, const char **state_names,
 	 const char **event_names,
 	 int nr_states, int nr_events, const fsm_node *tmpl,
-	 int tmpl_len, int order);
+	 int tmpl_len, gfp_t order);
 
 /**
  * Releases an FSM
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 9963479..38a2441 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -275,6 +275,10 @@
 	QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
 	QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
 	QETH_MAX_QUEUES,0x103}, \
+	{0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+	QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+	QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+	QETH_MAX_QUEUES,0}, \
 	{0,0,0,0,0,0,0,0,0}}
 
 #define QETH_REAL_CARD		1
@@ -363,10 +367,22 @@
 	__u8 reserved2[16];
 } __attribute__ ((packed));
 
+struct qeth_hdr_osn {
+	__u8 id;
+	__u8 reserved;
+	__u16 seq_no;
+	__u16 reserved2;
+	__u16 control_flags;
+	__u16 pdu_length;
+	__u8 reserved3[18];
+	__u32 ccid;
+} __attribute__ ((packed));
+					    
 struct qeth_hdr {
 	union {
 		struct qeth_hdr_layer2 l2;
 		struct qeth_hdr_layer3 l3;
+		struct qeth_hdr_osn    osn;
 	} hdr;
 } __attribute__ ((packed));
 
@@ -413,6 +429,7 @@
 	QETH_HEADER_TYPE_LAYER3 = 0x01,
 	QETH_HEADER_TYPE_LAYER2 = 0x02,
 	QETH_HEADER_TYPE_TSO	= 0x03,
+	QETH_HEADER_TYPE_OSN    = 0x04,
 };
 /* flags for qeth_hdr.ext_flags */
 #define QETH_HDR_EXT_VLAN_FRAME       0x01
@@ -582,7 +599,6 @@
  * Protocol versions
  */
 enum qeth_prot_versions {
-	QETH_PROT_SNA  = 0x0001,
 	QETH_PROT_IPV4 = 0x0004,
 	QETH_PROT_IPV6 = 0x0006,
 };
@@ -761,6 +777,11 @@
 	QETH_RECOVER_THREAD = 2,
 };
 
+struct qeth_osn_info {
+	int (*assist_cb)(struct net_device *dev, void *data);
+	int (*data_cb)(struct sk_buff *skb);
+};
+
 struct qeth_card {
 	struct list_head list;
 	enum qeth_card_states state;
@@ -803,6 +824,7 @@
 	int use_hard_stop;
 	int (*orig_hard_header)(struct sk_buff *,struct net_device *,
 				unsigned short,void *,void *,unsigned);
+	struct qeth_osn_info osn_info; 
 };
 
 struct qeth_card_list_struct {
@@ -916,10 +938,12 @@
 static inline unsigned short
 qeth_get_netdev_flags(struct qeth_card *card)
 {
-	if (card->options.layer2)
+	if (card->options.layer2 &&
+	   (card->info.type == QETH_CARD_TYPE_OSAE))
 		return 0;
 	switch (card->info.type) {
 	case QETH_CARD_TYPE_IQD:
+	case QETH_CARD_TYPE_OSN:	
 		return IFF_NOARP;
 #ifdef CONFIG_QETH_IPV6
 	default:
@@ -956,9 +980,10 @@
 qeth_get_max_mtu_for_card(int cardtype)
 {
 	switch (cardtype) {
+		
 	case QETH_CARD_TYPE_UNKNOWN:
-		return 61440;
 	case QETH_CARD_TYPE_OSAE:
+	case QETH_CARD_TYPE_OSN:
 		return 61440;
 	case QETH_CARD_TYPE_IQD:
 		return 57344;
@@ -1004,6 +1029,7 @@
 	case QETH_CARD_TYPE_IQD:
 		return ((mtu >= 576) &&
 			(mtu <= card->info.max_mtu + 4096 - 32));
+	case QETH_CARD_TYPE_OSN:
 	case QETH_CARD_TYPE_UNKNOWN:
 	default:
 		return 1;
@@ -1015,6 +1041,7 @@
 {
 	switch (cardtype) {
 	case QETH_CARD_TYPE_OSAE:
+	case QETH_CARD_TYPE_OSN:
 		switch (linktype) {
 		case QETH_LINK_TYPE_LANE_TR:
 		case QETH_LINK_TYPE_HSTR:
@@ -1182,4 +1209,16 @@
 extern void
 qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
 
+extern int
+qeth_osn_assist(struct net_device *, void *, int);
+
+extern int
+qeth_osn_register(unsigned char *read_dev_no,
+                 struct net_device **,
+                 int (*assist_cb)(struct net_device *, void *),
+                 int (*data_cb)(struct sk_buff *));
+
+extern void
+qeth_osn_deregister(struct net_device *);
+		
 #endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
index 5c9a51c..c0b4c8d 100644
--- a/drivers/s390/net/qeth_fs.h
+++ b/drivers/s390/net/qeth_fs.h
@@ -12,7 +12,7 @@
 #ifndef __QETH_FS_H__
 #define __QETH_FS_H__
 
-#define VERSION_QETH_FS_H "$Revision: 1.9 $"
+#define VERSION_QETH_FS_H "$Revision: 1.10 $"
 
 extern const char *VERSION_QETH_PROC_C;
 extern const char *VERSION_QETH_SYS_C;
@@ -43,6 +43,12 @@
 qeth_remove_device_attributes(struct device *dev);
 
 extern int
+qeth_create_device_attributes_osn(struct device *dev);
+
+extern void
+qeth_remove_device_attributes_osn(struct device *dev);
+		    
+extern int
 qeth_create_driver_attributes(void);
 
 extern void
@@ -108,6 +114,8 @@
 			return " OSD Express";
 		case QETH_CARD_TYPE_IQD:
 			return " HiperSockets";
+		case QETH_CARD_TYPE_OSN:
+			return " OSN QDIO";
 		default:
 			return " unknown";
 		}
@@ -153,6 +161,8 @@
 			}
 		case QETH_CARD_TYPE_IQD:
 			return "HiperSockets";
+		case QETH_CARD_TYPE_OSN:
+			return "OSN";
 		default:
 			return "unknown";
 		}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index bd28e24..692003c 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -196,7 +196,6 @@
 {
 	struct qeth_notify_list_struct *n_entry;
 
-
 	/*check first if entry already exists*/
 	spin_lock(&qeth_notify_lock);
 	list_for_each_entry(n_entry, &qeth_notify_list, list) {
@@ -1024,7 +1023,10 @@
 	card->options.fake_broadcast = 0;
 	card->options.add_hhlen = DEFAULT_ADD_HHLEN;
 	card->options.fake_ll = 0;
-	card->options.layer2 = 0;
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		card->options.layer2 = 1;
+	else
+		card->options.layer2 = 0;
 }
 
 /**
@@ -1113,19 +1115,20 @@
 
 	QETH_DBF_TEXT(setup, 2, "detcdtyp");
 
+	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
 	while (known_devices[i][4]) {
 		if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
 		    (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
 			card->info.type = known_devices[i][4];
+			card->qdio.no_out_queues = known_devices[i][8];
+			card->info.is_multicast_different = known_devices[i][9];
 			if (is_1920_device(card)) {
 				PRINT_INFO("Priority Queueing not able "
 					   "due to hardware limitations!\n");
 				card->qdio.no_out_queues = 1;
 				card->qdio.default_out_queue = 0;
-			} else {
-				card->qdio.no_out_queues = known_devices[i][8];
-			}
-			card->info.is_multicast_different = known_devices[i][9];
+			} 
 			return 0;
 		}
 		i++;
@@ -1149,6 +1152,8 @@
 	if (!get_device(dev))
 		return -ENODEV;
 
+	QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+	
 	card = qeth_alloc_card();
 	if (!card) {
 		put_device(dev);
@@ -1158,28 +1163,27 @@
 	card->read.ccwdev  = gdev->cdev[0];
 	card->write.ccwdev = gdev->cdev[1];
 	card->data.ccwdev  = gdev->cdev[2];
-
-	if ((rc = qeth_setup_card(card))){
-		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		put_device(dev);
-		qeth_free_card(card);
-		return rc;
-	}
 	gdev->dev.driver_data = card;
 	card->gdev = gdev;
 	gdev->cdev[0]->handler = qeth_irq;
 	gdev->cdev[1]->handler = qeth_irq;
 	gdev->cdev[2]->handler = qeth_irq;
 
-	rc = qeth_create_device_attributes(dev);
-	if (rc) {
+	if ((rc = qeth_determine_card_type(card))){
+		PRINT_WARN("%s: not a valid card type\n", __func__);
+		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+		put_device(dev);
+		qeth_free_card(card);
+		return rc;
+	}			    
+	if ((rc = qeth_setup_card(card))){
+		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
 		put_device(dev);
 		qeth_free_card(card);
 		return rc;
 	}
-	if ((rc = qeth_determine_card_type(card))){
-		PRINT_WARN("%s: not a valid card type\n", __func__);
-		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+	rc = qeth_create_device_attributes(dev);
+	if (rc) {
 		put_device(dev);
 		qeth_free_card(card);
 		return rc;
@@ -1660,6 +1664,8 @@
 				netif_carrier_on(card->dev);
 				qeth_schedule_recovery(card);
 				return NULL;
+			case IPA_CMD_MODCCID:
+				return cmd;
 			case IPA_CMD_REGISTER_LOCAL_ADDR:
 				QETH_DBF_TEXT(trace,3, "irla");
 				break;
@@ -1721,6 +1727,14 @@
 	cmd = qeth_check_ipa_data(card, iob);
 	if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
 		goto out;
+	/*in case of OSN : check if cmd is set */
+	if (card->info.type == QETH_CARD_TYPE_OSN &&
+	    cmd &&
+	    cmd->hdr.command != IPA_CMD_STARTLAN &&
+	    card->osn_info.assist_cb != NULL) {
+		card->osn_info.assist_cb(card->dev, cmd);
+		goto out;
+	}
 
 	spin_lock_irqsave(&card->lock, flags);
 	list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
@@ -1737,8 +1751,7 @@
 					keep_reply = reply->callback(card,
 							reply,
 							(unsigned long)cmd);
-				}
-				else
+				} else
 					keep_reply = reply->callback(card,
 							reply,
 							(unsigned long)iob);
@@ -1768,6 +1781,24 @@
 	qeth_release_buffer(channel,iob);
 }
 
+static inline void
+qeth_prepare_control_data(struct qeth_card *card, int len,
+struct qeth_cmd_buffer *iob)
+{
+	qeth_setup_ccw(&card->write,iob->data,len);
+	iob->callback = qeth_release_buffer;
+
+	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.trans_hdr++;
+	memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+	card->seqno.pdu_hdr++;
+	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+}
+						    
 static int
 qeth_send_control_data(struct qeth_card *card, int len,
 		       struct qeth_cmd_buffer *iob,
@@ -1778,24 +1809,11 @@
 {
 	int rc;
 	unsigned long flags;
-	struct qeth_reply *reply;
+	struct qeth_reply *reply = NULL;
 	struct timer_list timer;
 
 	QETH_DBF_TEXT(trace, 2, "sendctl");
 
-	qeth_setup_ccw(&card->write,iob->data,len);
-
-	memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
-	       &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
-	card->seqno.trans_hdr++;
-
-	memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
-	       &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
-	card->seqno.pdu_hdr++;
-	memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
-	       &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
-	iob->callback = qeth_release_buffer;
-
 	reply = qeth_alloc_reply(card);
 	if (!reply) {
 		PRINT_WARN("Could no alloc qeth_reply!\n");
@@ -1810,10 +1828,6 @@
 	init_timer(&timer);
 	timer.function = qeth_cmd_timeout;
 	timer.data = (unsigned long) reply;
-	if (IS_IPA(iob->data))
-		timer.expires = jiffies + QETH_IPA_TIMEOUT;
-	else
-		timer.expires = jiffies + QETH_TIMEOUT;
 	init_waitqueue_head(&reply->wait_q);
 	spin_lock_irqsave(&card->lock, flags);
 	list_add_tail(&reply->list, &card->cmd_waiter_list);
@@ -1821,6 +1835,11 @@
 	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
 	wait_event(card->wait_q,
 		   atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+	qeth_prepare_control_data(card, len, iob);
+	if (IS_IPA(iob->data))
+		timer.expires = jiffies + QETH_IPA_TIMEOUT;
+	else
+		timer.expires = jiffies + QETH_TIMEOUT;
 	QETH_DBF_TEXT(trace, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
 	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
@@ -1848,6 +1867,62 @@
 }
 
 static int
+qeth_osn_send_control_data(struct qeth_card *card, int len,
+			   struct qeth_cmd_buffer *iob)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	QETH_DBF_TEXT(trace, 5, "osndctrd");
+
+	wait_event(card->wait_q,
+		   atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+	qeth_prepare_control_data(card, len, iob);
+	QETH_DBF_TEXT(trace, 6, "osnoirqp");
+	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+	rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+			      (addr_t) iob, 0, 0);
+	spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+	if (rc){
+		PRINT_WARN("qeth_osn_send_control_data: "
+			   "ccw_device_start rc = %i\n", rc);
+		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+		qeth_release_buffer(iob->channel, iob);
+		atomic_set(&card->write.irq_pending, 0);
+		wake_up(&card->wait_q);
+	}
+	return rc;
+}					
+
+static inline void
+qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+		     char prot_type)
+{
+	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+}
+
+static int
+qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+		      int data_len)
+{
+	u16 s1, s2;
+
+QETH_DBF_TEXT(trace,4,"osndipa");
+
+	qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+	s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+	s2 = (u16)data_len;
+	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+	return qeth_osn_send_control_data(card, s1, iob);
+}
+							    
+static int
 qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
 		  int (*reply_cb)
 		  (struct qeth_card *,struct qeth_reply*, unsigned long),
@@ -1858,17 +1933,14 @@
 
 	QETH_DBF_TEXT(trace,4,"sendipa");
 
-	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
-
 	if (card->options.layer2)
-		prot_type = QETH_PROT_LAYER2;
+		if (card->info.type == QETH_CARD_TYPE_OSN)
+			prot_type = QETH_PROT_OSN2;
+		else
+			prot_type = QETH_PROT_LAYER2;
 	else
 		prot_type = QETH_PROT_TCPIP;
-
-	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
-	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
-	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-
+	qeth_prepare_ipa_cmd(card,iob,prot_type);
 	rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
 				    reply_cb, reply_param);
 	return rc;
@@ -2010,7 +2082,10 @@
 	*(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
 		(__u8) card->info.portno;
 	if (card->options.layer2)
-		prot_type = QETH_PROT_LAYER2;
+		if (card->info.type == QETH_CARD_TYPE_OSN)
+			prot_type = QETH_PROT_OSN2;
+		else
+			prot_type = QETH_PROT_LAYER2;
 	else
 		prot_type = QETH_PROT_TCPIP;
 
@@ -2100,15 +2175,21 @@
 }
 
 static inline struct sk_buff *
-qeth_get_skb(unsigned int length)
+qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
 {
 	struct sk_buff* skb;
+	int add_len;
+
+	add_len = 0;
+	if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+		add_len = sizeof(struct qeth_hdr);
 #ifdef CONFIG_QETH_VLAN
-	if ((skb = dev_alloc_skb(length + VLAN_HLEN)))
-		skb_reserve(skb, VLAN_HLEN);
-#else
-	skb = dev_alloc_skb(length);
+	else
+		add_len = VLAN_HLEN;
 #endif
+	skb = dev_alloc_skb(length + add_len);
+	if (skb && add_len)
+		skb_reserve(skb, add_len);
 	return skb;
 }
 
@@ -2138,7 +2219,10 @@
 
 	offset += sizeof(struct qeth_hdr);
 	if (card->options.layer2)
-		skb_len = (*hdr)->hdr.l2.pkt_length;
+		if (card->info.type == QETH_CARD_TYPE_OSN)
+			skb_len = (*hdr)->hdr.osn.pdu_length;
+		else
+			skb_len = (*hdr)->hdr.l2.pkt_length;
 	else
 		skb_len = (*hdr)->hdr.l3.length;
 
@@ -2146,15 +2230,15 @@
 		return NULL;
 	if (card->options.fake_ll){
 		if(card->dev->type == ARPHRD_IEEE802_TR){
-			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
+			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
 				goto no_mem;
 			skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
 		} else {
-			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
+			if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
 				goto no_mem;
 			skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
 		}
-	} else if (!(skb = qeth_get_skb(skb_len)))
+	} else if (!(skb = qeth_get_skb(skb_len, *hdr)))
 		goto no_mem;
 	data_ptr = element->addr + offset;
 	while (skb_len) {
@@ -2453,8 +2537,12 @@
 		skb->dev = card->dev;
 		if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
 			vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
-		else
+		else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)     
 			qeth_rebuild_skb(card, skb, hdr);
+		else { /*in case of OSN*/
+			skb_push(skb, sizeof(struct qeth_hdr));
+			memcpy(skb->data, hdr, sizeof(struct qeth_hdr));
+		}
 		/* is device UP ? */
 		if (!(card->dev->flags & IFF_UP)){
 			dev_kfree_skb_any(skb);
@@ -2465,7 +2553,10 @@
 			vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
 		else
 #endif
-		rxrc = netif_rx(skb);
+		if (card->info.type == QETH_CARD_TYPE_OSN)
+			rxrc = card->osn_info.data_cb(skb);
+		else
+			rxrc = netif_rx(skb);
 		card->dev->last_rx = jiffies;
 		card->stats.rx_packets++;
 		card->stats.rx_bytes += skb->len;
@@ -3150,8 +3241,6 @@
 	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
 	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
 	/* outbound */
-	card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
-	card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
 }
 
 static int
@@ -3466,7 +3555,7 @@
 
 	return 0;
 out_qdio:
-	qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE);
+	qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
 	return rc;
 }
 
@@ -3491,6 +3580,9 @@
 	case QETH_CARD_TYPE_IQD:
 		dev = alloc_netdev(0, "hsi%d", ether_setup);
 		break;
+	case QETH_CARD_TYPE_OSN:
+		dev = alloc_netdev(0, "osn%d", ether_setup);
+		break;
 	default:
 		dev = alloc_etherdev(0);
 	}
@@ -3655,7 +3747,8 @@
 	if (card->state != CARD_STATE_SOFTSETUP)
 		return -ENODEV;
 
-	if ( (card->options.layer2) &&
+	if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+	     (card->options.layer2) &&
 	     (!card->info.layer2_mac_registered)) {
 		QETH_DBF_TEXT(trace,4,"nomacadr");
 		return -EPERM;
@@ -3693,6 +3786,9 @@
 {
 	int cast_type = RTN_UNSPEC;
 
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return cast_type;
+
 	if (skb->dst && skb->dst->neighbour){
 		cast_type = skb->dst->neighbour->type;
 		if ((cast_type == RTN_BROADCAST) ||
@@ -3782,13 +3878,16 @@
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
 		 struct qeth_hdr **hdr, int ipv)
 {
-	int rc;
+	int rc = 0;
 #ifdef CONFIG_QETH_VLAN
 	u16 *tag;
 #endif
 
 	QETH_DBF_TEXT(trace, 6, "prepskb");
-
+	if (card->info.type == QETH_CARD_TYPE_OSN) {
+		*hdr = (struct qeth_hdr *)(*skb)->data;
+		return rc;
+	}
         rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
         if (rc)
                 return rc;
@@ -4291,8 +4390,14 @@
 			}
 		}
 	}
+	if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+		(skb->protocol == htons(ETH_P_IPV6))) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
 	cast_type = qeth_get_cast_type(card, skb);
-	if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){
+	if ((cast_type == RTN_BROADCAST) && 
+	    (card->info.broadcast_capable == 0)){
 		card->stats.tx_dropped++;
 		card->stats.tx_errors++;
 		dev_kfree_skb_any(skb);
@@ -4320,7 +4425,8 @@
 			QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
 			return rc;
 		}
-		qeth_fill_header(card, hdr, skb, ipv, cast_type);
+		if (card->info.type != QETH_CARD_TYPE_OSN)
+			qeth_fill_header(card, hdr, skb, ipv, cast_type);
 	}
 
 	if (large_send == QETH_LARGE_SEND_EDDP) {
@@ -4381,6 +4487,7 @@
 	case MII_BMCR: /* Basic mode control register */
 		rc = BMCR_FULLDPLX;
 		if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+		    (card->info.link_type != QETH_LINK_TYPE_OSN) &&
 		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
 			rc |= BMCR_SPEED100;
 		break;
@@ -5004,6 +5111,9 @@
             (card->state != CARD_STATE_SOFTSETUP))
 		return -ENODEV;
 
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return -EPERM;
+
 	switch (cmd){
 	case SIOC_QETH_ARP_SET_NO_ENTRIES:
 		if ( !capable(CAP_NET_ADMIN) ||
@@ -5329,6 +5439,9 @@
 {
 	struct qeth_card *card = (struct qeth_card *) dev->priv;
 
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return ;
+	 
 	QETH_DBF_TEXT(trace,3,"setmulti");
 	qeth_delete_mc_addresses(card);
 	qeth_add_multicast_ipv4(card);
@@ -5370,6 +5483,94 @@
 	return addr;
 }
 
+int
+qeth_osn_assist(struct net_device *dev,
+		void *data,
+		int data_len)
+{
+	struct qeth_cmd_buffer *iob;
+	struct qeth_card *card;
+	int rc;
+	
+	QETH_DBF_TEXT(trace, 2, "osnsdmc");
+	if (!dev)
+		return -ENODEV;
+	card = (struct qeth_card *)dev->priv;
+	if (!card)
+		return -ENODEV;
+	if ((card->state != CARD_STATE_UP) &&
+	    (card->state != CARD_STATE_SOFTSETUP))
+		return -ENODEV;
+	iob = qeth_wait_for_buffer(&card->write);
+	memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+	rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+	return rc;
+}
+
+static struct net_device *
+qeth_netdev_by_devno(unsigned char *read_dev_no)
+{
+	struct qeth_card *card;
+	struct net_device *ndev;
+	unsigned char *readno;
+	__u16 temp_dev_no, card_dev_no;
+	char *endp;
+	unsigned long flags;
+
+	ndev = NULL;
+	memcpy(&temp_dev_no, read_dev_no, 2);
+	read_lock_irqsave(&qeth_card_list.rwlock, flags);
+	list_for_each_entry(card, &qeth_card_list.list, list) {
+		readno = CARD_RDEV_ID(card);
+		readno += (strlen(readno) - 4);
+		card_dev_no = simple_strtoul(readno, &endp, 16);
+		if (card_dev_no == temp_dev_no) {
+			ndev = card->dev;
+			break;
+		}
+	}
+	read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+	return ndev;
+}
+
+int
+qeth_osn_register(unsigned char *read_dev_no,
+		  struct net_device **dev,
+		  int (*assist_cb)(struct net_device *, void *),
+		  int (*data_cb)(struct sk_buff *))
+{
+	struct qeth_card * card;
+
+	QETH_DBF_TEXT(trace, 2, "osnreg");
+	*dev = qeth_netdev_by_devno(read_dev_no);
+	if (*dev == NULL)
+		return -ENODEV;
+	card = (struct qeth_card *)(*dev)->priv;
+	if (!card)
+		return -ENODEV;
+	if ((assist_cb == NULL) || (data_cb == NULL))
+		return -EINVAL;
+	card->osn_info.assist_cb = assist_cb;
+	card->osn_info.data_cb = data_cb;
+	return 0;
+}
+
+void
+qeth_osn_deregister(struct net_device * dev)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT(trace, 2, "osndereg");
+	if (!dev)
+		return;
+	card = (struct qeth_card *)dev->priv;
+	if (!card)
+		return;
+	card->osn_info.assist_cb = NULL;
+	card->osn_info.data_cb = NULL;
+	return;
+}
+					   
 static void
 qeth_delete_mc_addresses(struct qeth_card *card)
 {
@@ -5700,6 +5901,12 @@
 		QETH_DBF_TEXT(trace, 3, "setmcLY3");
 		return -EOPNOTSUPP;
 	}
+	if (card->info.type == QETH_CARD_TYPE_OSN) {
+		PRINT_WARN("Setting MAC address on %s is not supported.\n",
+			   dev->name);
+		QETH_DBF_TEXT(trace, 3, "setmcOSN");
+		return -EOPNOTSUPP;
+	}
 	QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
 	QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
 	rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
@@ -6076,9 +6283,8 @@
 			qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
 	dev->addr_len = OSA_ADDR_LEN;
 	dev->mtu = card->info.initial_mtu;
-
-	SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
-
+	if (card->info.type != QETH_CARD_TYPE_OSN)
+		SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
 	SET_MODULE_OWNER(dev);
 	return 0;
 }
@@ -6095,6 +6301,7 @@
 					QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
 	} else {
 		if (card->info.type == QETH_CARD_TYPE_IQD)
+		/*FIXME:why do we have same values for  dis and ena for osae??? */
 			card->info.func_level =
 				QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
 		else
@@ -6124,7 +6331,7 @@
 		ccw_device_set_online(CARD_WDEV(card));
 		ccw_device_set_online(CARD_DDEV(card));
 	}
-	rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE);
+	rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
 	if (rc == -ERESTARTSYS) {
 		QETH_DBF_TEXT(setup, 2, "break1");
 		return rc;
@@ -6176,8 +6383,8 @@
 	card->dev = qeth_get_netdevice(card->info.type,
 				       card->info.link_type);
 	if (!card->dev){
-		qeth_qdio_clear_card(card, card->info.type ==
-				     QETH_CARD_TYPE_OSAE);
+		qeth_qdio_clear_card(card, card->info.type !=
+				     QETH_CARD_TYPE_IQD);
 		rc = -ENODEV;
 		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
 		goto out;
@@ -7084,6 +7291,8 @@
 			return rc;
 	} else
 		card->lan_online = 1;
+	if (card->info.type==QETH_CARD_TYPE_OSN)
+		goto out;
 	if (card->options.layer2) {
 		card->dev->features |=
 			NETIF_F_HW_VLAN_FILTER |
@@ -7255,7 +7464,8 @@
 	if (card->read.state == CH_STATE_UP &&
 	    card->write.state == CH_STATE_UP &&
 	    (card->state == CARD_STATE_UP)) {
-		if(recovery_mode) {
+		if (recovery_mode && 
+		    card->info.type != QETH_CARD_TYPE_OSN) {
 			qeth_stop(card->dev);
 		} else {
 			rtnl_lock();
@@ -7437,7 +7647,8 @@
 {
 	QETH_DBF_TEXT(setup ,2, "startag");
 
-	if(recovery_mode) {
+	if (recovery_mode && 
+	    card->info.type != QETH_CARD_TYPE_OSN) {
 		qeth_open(card->dev);
 	} else {
 		rtnl_lock();
@@ -7469,33 +7680,36 @@
 static void qeth_make_parameters_consistent(struct qeth_card *card)
 {
 
-        if (card->options.layer2) {
-                if (card->info.type == QETH_CARD_TYPE_IQD) {
-                        PRINT_ERR("Device %s does not support " \
-                                  "layer 2 functionality. "  \
-                                  "Ignoring layer2 option.\n",CARD_BUS_ID(card));
-                }
-                IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
-                                 "Routing options are");
+	if (card->options.layer2 == 0)
+		return;
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return;
+	if (card->info.type == QETH_CARD_TYPE_IQD) {
+       		PRINT_ERR("Device %s does not support layer 2 functionality." \
+	               	  " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+       		card->options.layer2 = 0;
+		return;
+	}
+       	IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+               	         "Routing options are");
 #ifdef CONFIG_QETH_IPV6
-                IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
-                                 "Routing options are");
+       	IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+               	         "Routing options are");
 #endif
-                IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
-                                QETH_CHECKSUM_DEFAULT,
-                                "Checksumming options are");
-                IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
-                                 QETH_TR_BROADCAST_ALLRINGS,
-                                 "Broadcast mode options are");
-                IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
-                                 QETH_TR_MACADDR_NONCANONICAL,
-                                 "Canonical MAC addr options are");
-                IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
-				 "Broadcast faking options are");
-                IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
-                                 DEFAULT_ADD_HHLEN,"Option add_hhlen is");
-                IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
-        }
+       	IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+                       	QETH_CHECKSUM_DEFAULT,
+               	        "Checksumming options are");
+       	IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+                       	 QETH_TR_BROADCAST_ALLRINGS,
+               	         "Broadcast mode options are");
+       	IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+                       	 QETH_TR_MACADDR_NONCANONICAL,
+               	         "Canonical MAC addr options are");
+       	IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+			 "Broadcast faking options are");
+       	IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+       	                 DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+        IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
 }
 
 
@@ -7525,8 +7739,7 @@
 		return -EIO;
 	}
 
-	if (card->options.layer2)
-		qeth_make_parameters_consistent(card);
+	qeth_make_parameters_consistent(card);
 
 	if ((rc = qeth_hardsetup_card(card))){
 		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
@@ -7585,6 +7798,7 @@
 static struct ccw_device_id qeth_ids[] = {
 	{CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
 	{CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
+	{CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN},
 	{},
 };
 MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -8329,6 +8543,9 @@
 	printk("qeth: removed\n");
 }
 
+EXPORT_SYMBOL(qeth_osn_register);
+EXPORT_SYMBOL(qeth_osn_deregister);
+EXPORT_SYMBOL(qeth_osn_assist);
 module_init(qeth_init);
 module_exit(qeth_exit);
 MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index f685ecc..30e053d 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -11,7 +11,7 @@
 #include <asm/cio.h>
 #include "qeth_mpc.h"
 
-const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $";
+const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $";
 
 unsigned char IDX_ACTIVATE_READ[]={
 	0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
@@ -138,7 +138,9 @@
 		sizeof(struct qeth_ipa_cmd)%256,
 	0x00,
 		sizeof(struct qeth_ipa_cmd)/256,
-		sizeof(struct qeth_ipa_cmd),0x05, 0x77,0x77,0x77,0x77,
+		sizeof(struct qeth_ipa_cmd)%256,
+	0x05,
+	0x77,0x77,0x77,0x77,
 	0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
 	0x01,0x00,
 		sizeof(struct qeth_ipa_cmd)/256,
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 3d916b5..7edc5f1 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -46,13 +46,16 @@
 /* IP Assist related definitions                                             */
 /*****************************************************************************/
 #define IPA_CMD_INITIATOR_HOST  0x00
-#define IPA_CMD_INITIATOR_HYDRA 0x01
+#define IPA_CMD_INITIATOR_OSA   0x01
+#define IPA_CMD_INITIATOR_HOST_REPLY  0x80
+#define IPA_CMD_INITIATOR_OSA_REPLY   0x81
 #define IPA_CMD_PRIM_VERSION_NO 0x01
 
 enum qeth_card_types {
 	QETH_CARD_TYPE_UNKNOWN = 0,
 	QETH_CARD_TYPE_OSAE    = 10,
 	QETH_CARD_TYPE_IQD     = 1234,
+	QETH_CARD_TYPE_OSN     = 11,
 };
 
 #define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -61,6 +64,7 @@
 	QETH_LINK_TYPE_FAST_ETH     = 0x01,
 	QETH_LINK_TYPE_HSTR         = 0x02,
 	QETH_LINK_TYPE_GBIT_ETH     = 0x03,
+	QETH_LINK_TYPE_OSN          = 0x04,
 	QETH_LINK_TYPE_10GBIT_ETH   = 0x10,
 	QETH_LINK_TYPE_LANE_ETH100  = 0x81,
 	QETH_LINK_TYPE_LANE_TR      = 0x82,
@@ -111,6 +115,9 @@
 	IPA_CMD_DELGMAC 	      = 0x24,
 	IPA_CMD_SETVLAN 	      = 0x25,
 	IPA_CMD_DELVLAN 	      = 0x26,
+	IPA_CMD_SETCCID               = 0x41,
+	IPA_CMD_DELCCID               = 0x42,
+	IPA_CMD_MODCCID               = 0x43,
 	IPA_CMD_SETIP                 = 0xb1,
 	IPA_CMD_DELIP                 = 0xb7,
 	IPA_CMD_QIPASSIST             = 0xb2,
@@ -437,8 +444,9 @@
 #define QETH_ARP_DATA_SIZE 3968
 #define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
 /* Helper functions */
-#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST)
-
+#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+			   (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+	
 /*****************************************************************************/
 /* END OF   IP Assist related definitions                                    */
 /*****************************************************************************/
@@ -483,6 +491,7 @@
 /* Layer 2 defintions */
 #define QETH_PROT_LAYER2 0x08
 #define QETH_PROT_TCPIP  0x03
+#define QETH_PROT_OSN2   0x0a     
 #define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
 #define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
 
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index dda105b..f91a02d 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to sysfs.
@@ -20,7 +20,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
 
 /*****************************************************************************/
 /*                                                                           */
@@ -937,6 +937,19 @@
 	.attrs = (struct attribute **)qeth_device_attrs,
 };
 
+static struct device_attribute * qeth_osn_device_attrs[] = {
+	&dev_attr_state,
+	&dev_attr_chpid,
+	&dev_attr_if_name,
+	&dev_attr_card_type,
+	&dev_attr_buffer_count,
+	&dev_attr_recover,
+	NULL,
+};
+
+static struct attribute_group qeth_osn_device_attr_group = {
+	.attrs = (struct attribute **)qeth_osn_device_attrs,
+};
 
 #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store)			     \
 struct device_attribute dev_attr_##_id = {				     \
@@ -1667,7 +1680,12 @@
 qeth_create_device_attributes(struct device *dev)
 {
 	int ret;
+	struct qeth_card *card = dev->driver_data;
 
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return sysfs_create_group(&dev->kobj,
+					  &qeth_osn_device_attr_group);
+   	
 	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
 		return ret;
 	if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1693,6 +1711,12 @@
 void
 qeth_remove_device_attributes(struct device *dev)
 {
+	struct qeth_card *card = dev->driver_data;
+
+	if (card->info.type == QETH_CARD_TYPE_OSN)
+		return sysfs_remove_group(&dev->kobj,
+					  &qeth_osn_device_attr_group);
+		      
 	sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
 	sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
 	sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3ee9b8b..9c9f162 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -489,11 +489,11 @@
 
 	  If unsure, say N.
 
-config SCSI_SATA_PROMISE
-	tristate "Promise SATA TX2/TX4 support"
+config SCSI_PDC_ADMA
+	tristate "Pacific Digital ADMA support"
 	depends on SCSI_SATA && PCI
 	help
-	  This option enables support for Promise Serial ATA TX2/TX4.
+	  This option enables support for Pacific Digital ADMA controllers
 
 	  If unsure, say N.
 
@@ -505,6 +505,14 @@
 
 	  If unsure, say N.
 
+config SCSI_SATA_PROMISE
+	tristate "Promise SATA TX2/TX4 support"
+	depends on SCSI_SATA && PCI
+	help
+	  This option enables support for Promise Serial ATA TX2/TX4.
+
+	  If unsure, say N.
+
 config SCSI_SATA_SX4
 	tristate "Promise SATA SX4 support"
 	depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -521,6 +529,14 @@
 
 	  If unsure, say N.
 
+config SCSI_SATA_SIL24
+	tristate "Silicon Image 3124/3132 SATA support"
+	depends on SCSI_SATA && PCI && EXPERIMENTAL
+	help
+	  This option enables support for Silicon Image 3124/3132 Serial ATA.
+
+	  If unsure, say N.
+
 config SCSI_SATA_SIS
 	tristate "SiS 964/180 SATA support"
 	depends on SCSI_SATA && PCI && EXPERIMENTAL
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 48529d1..2d44398 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -130,6 +130,7 @@
 obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
 obj-$(CONFIG_SCSI_SATA_QSTOR)	+= libata.o sata_qstor.o
 obj-$(CONFIG_SCSI_SATA_SIL)	+= libata.o sata_sil.o
+obj-$(CONFIG_SCSI_SATA_SIL24)	+= libata.o sata_sil24.o
 obj-$(CONFIG_SCSI_SATA_VIA)	+= libata.o sata_via.o
 obj-$(CONFIG_SCSI_SATA_VITESSE)	+= libata.o sata_vsc.o
 obj-$(CONFIG_SCSI_SATA_SIS)	+= libata.o sata_sis.o
@@ -137,6 +138,7 @@
 obj-$(CONFIG_SCSI_SATA_NV)	+= libata.o sata_nv.o
 obj-$(CONFIG_SCSI_SATA_ULI)	+= libata.o sata_uli.o
 obj-$(CONFIG_SCSI_SATA_MV)	+= libata.o sata_mv.o
+obj-$(CONFIG_SCSI_PDC_ADMA)	+= libata.o pdc_adma.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index c2c8fa8..e2a5657 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -192,7 +193,6 @@
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
-static u8 ahci_check_err(struct ata_port *ap);
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 static void ahci_remove_one (struct pci_dev *pdev);
 
@@ -216,12 +216,11 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations ahci_ops = {
+static const struct ata_port_operations ahci_ops = {
 	.port_disable		= ata_port_disable,
 
 	.check_status		= ahci_check_status,
 	.check_altstatus	= ahci_check_status,
-	.check_err		= ahci_check_err,
 	.dev_select		= ata_noop_dev_select,
 
 	.tf_read		= ahci_tf_read,
@@ -407,7 +406,7 @@
 		return 0xffffffffU;
 	}
 
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -425,7 +424,7 @@
 		return;
 	}
 
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void ahci_phy_reset(struct ata_port *ap)
@@ -453,18 +452,11 @@
 
 static u8 ahci_check_status(struct ata_port *ap)
 {
-	void *mmio = (void *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
 
 	return readl(mmio + PORT_TFDATA) & 0xFF;
 }
 
-static u8 ahci_check_err(struct ata_port *ap)
-{
-	void *mmio = (void *) ap->ioaddr.cmd_addr;
-
-	return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
-}
-
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ahci_port_priv *pp = ap->private_data;
@@ -609,7 +601,7 @@
 	 	 * not being called from the SCSI EH.
 	 	 */
 		qc->scsidone = scsi_finish_command;
-		ata_qc_complete(qc, ATA_ERR);
+		ata_qc_complete(qc, AC_ERR_OTHER);
 	}
 
 	spin_unlock_irqrestore(&host_set->lock, flags);
@@ -638,7 +630,7 @@
 	if (status & PORT_IRQ_FATAL) {
 		ahci_intr_error(ap, status);
 		if (qc)
-			ata_qc_complete(qc, ATA_ERR);
+			ata_qc_complete(qc, AC_ERR_OTHER);
 	}
 
 	return 1;
@@ -672,17 +664,35 @@
 
         for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap;
-		u32 tmp;
 
-		VPRINTK("port %u\n", i);
+		if (!(irq_stat & (1 << i)))
+			continue;
+
 		ap = host_set->ports[i];
-		tmp = irq_stat & (1 << i);
-		if (tmp && ap) {
+		if (ap) {
 			struct ata_queued_cmd *qc;
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (ahci_host_intr(ap, qc))
-				irq_ack |= (1 << i);
+			if (!ahci_host_intr(ap, qc))
+				if (ata_ratelimit()) {
+					struct pci_dev *pdev =
+						to_pci_dev(ap->host_set->dev);
+					dev_printk(KERN_WARNING, &pdev->dev,
+					  "unhandled interrupt on port %u\n",
+					  i);
+				}
+
+			VPRINTK("port %u\n", i);
+		} else {
+			VPRINTK("port %u (no irq)\n", i);
+			if (ata_ratelimit()) {
+				struct pci_dev *pdev =
+					to_pci_dev(ap->host_set->dev);
+				dev_printk(KERN_WARNING, &pdev->dev,
+					"interrupt on disabled port %u\n", i);
+			}
 		}
+
+		irq_ack |= (1 << i);
 	}
 
 	if (irq_ack) {
@@ -750,8 +760,8 @@
 
 	tmp = readl(mmio + HOST_CTL);
 	if (tmp & HOST_RESET) {
-		printk(KERN_ERR DRV_NAME "(%s): controller reset failed (0x%x)\n",
-			pci_name(pdev), tmp);
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "controller reset failed (0x%x)\n", tmp);
 		return -EIO;
 	}
 
@@ -779,22 +789,22 @@
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 			if (rc) {
-				printk(KERN_ERR DRV_NAME "(%s): 64-bit DMA enable failed\n",
-					pci_name(pdev));
+				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) {
-			printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
-				pci_name(pdev));
+			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) {
-			printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
-				pci_name(pdev));
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit consistent DMA enable failed\n");
 			return rc;
 		}
 	}
@@ -897,10 +907,10 @@
 	else
 		scc_s = "unknown";
 
-	printk(KERN_INFO DRV_NAME "(%s) AHCI %02x%02x.%02x%02x "
+	dev_printk(KERN_INFO, &pdev->dev,
+		"AHCI %02x%02x.%02x%02x "
 		"%u slots %u ports %s Gbps 0x%x impl %s mode\n"
 	       	,
-	       	pci_name(pdev),
 
 	       	(vers >> 24) & 0xff,
 	       	(vers >> 16) & 0xff,
@@ -913,11 +923,11 @@
 		impl,
 		scc_s);
 
-	printk(KERN_INFO DRV_NAME "(%s) flags: "
+	dev_printk(KERN_INFO, &pdev->dev,
+		"flags: "
 	       	"%s%s%s%s%s%s"
 	       	"%s%s%s%s%s%s%s\n"
 	       	,
-	       	pci_name(pdev),
 
 		cap & (1 << 31) ? "64bit " : "",
 		cap & (1 << 30) ? "ncq " : "",
@@ -950,7 +960,7 @@
 	VPRINTK("ENTER\n");
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	rc = pci_enable_device(pdev);
 	if (rc)
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index 48e1c4d..1993764 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -10,6 +10,8 @@
  *  Commonly used scsi driver functions.
  */
 
+#include <linux/scatterlist.h>
+
 #define BELT_AND_BRACES
 
 /*
@@ -22,9 +24,7 @@
 
 	BUG_ON(bufs + 1 > max);
 
-	sg->page   = virt_to_page(SCp->ptr);
-	sg->offset = offset_in_page(SCp->ptr);
-	sg->length = SCp->this_residual;
+	sg_set_buf(sg, SCp->ptr, SCp->this_residual);
 
 	if (bufs)
 		memcpy(sg + 1, SCp->buffer + 1,
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index d71cef7..7f8aa1b 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -45,6 +45,7 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -147,7 +148,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations piix_pata_ops = {
+static const struct ata_port_operations piix_pata_ops = {
 	.port_disable		= ata_port_disable,
 	.set_piomode		= piix_set_piomode,
 	.set_dmamode		= piix_set_dmamode,
@@ -177,7 +178,7 @@
 	.host_stop		= ata_host_stop,
 };
 
-static struct ata_port_operations piix_sata_ops = {
+static const struct ata_port_operations piix_sata_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -621,18 +622,19 @@
 {
 	static int printed_version;
 	struct ata_port_info *port_info[2];
-	unsigned int combined = 0, n_ports = 1;
+	unsigned int combined = 0;
 	unsigned int pata_chan = 0, sata_chan = 0;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev,
+			   "version " DRV_VERSION "\n");
 
 	/* no hotplugging support (FIXME) */
 	if (!in_module_init)
 		return -ENODEV;
 
 	port_info[0] = &piix_port_info[ent->driver_data];
-	port_info[1] = NULL;
+	port_info[1] = &piix_port_info[ent->driver_data];
 
 	if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
 		u8 tmp;
@@ -670,12 +672,13 @@
 		port_info[sata_chan] = &piix_port_info[ent->driver_data];
 		port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
 		port_info[pata_chan] = &piix_port_info[ich5_pata];
-		n_ports++;
 
-		printk(KERN_WARNING DRV_NAME ": combined mode detected\n");
+		dev_printk(KERN_WARNING, &pdev->dev,
+			   "combined mode detected (p=%u, s=%u)\n",
+			   pata_chan, sata_chan);
 	}
 
-	return ata_pci_init_one(pdev, port_info, n_ports);
+	return ata_pci_init_one(pdev, port_info, 2);
 }
 
 static int __init piix_init(void)
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index da6e51c..540147c 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -936,7 +936,7 @@
 	if (init)
 		ch_init_elem(ch);
 
-	class_device_create(ch_sysfs_class,
+	class_device_create(ch_sysfs_class, NULL,
 			    MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
 			    dev, "s%s", ch->name);
 
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index 315f95a..4f39890 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -228,7 +228,7 @@
 			mem_start = get_tc_base_addr(slot);
 
 			/* Store base addr into esp struct */
-			esp->slot = PHYSADDR(mem_start);
+			esp->slot = CPHYSADDR(mem_start);
 
 			esp->dregs = 0;
 			esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG);
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index c10e45b..3d13fde 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -1357,7 +1357,7 @@
 
 	for (i = 0; i < shost->can_queue; i++) {
 		size_t sz = shost->sg_tablesize *sizeof(struct sg_list);
-		unsigned int gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
+		gfp_t gfp_mask = (shost->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC;
 		ha->cp[i].sglist = kmalloc(sz, gfp_mask);
 		if (!ha->cp[i].sglist) {
 			printk
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 02fe371..f24d845 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -287,7 +287,8 @@
 struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
 {
 	struct Scsi_Host *shost;
-	int gfp_mask = GFP_KERNEL, rval;
+	gfp_t gfp_mask = GFP_KERNEL;
+	int rval;
 
 	if (sht->unchecked_isa_dma && privsize)
 		gfp_mask |= __GFP_DMA;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 3d62c9b..00d6a66 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -180,19 +180,12 @@
 			return;
 		}
 		count = min(pc->sg->length - pc->b_count, bcount);
-		if (PageHighMem(pc->sg->page)) {
-			unsigned long flags;
-
-			local_irq_save(flags);
-			buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset;
-			drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
-			kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
-			local_irq_restore(flags);
-		} else {
-			buf = page_address(pc->sg->page) + pc->sg->offset;
-			drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
-		}
-		bcount -= count; pc->b_count += count;
+		buf = kmap_atomic(pc->sg->page, KM_IRQ0);
+		drive->hwif->atapi_input_bytes(drive,
+				buf + pc->b_count + pc->sg->offset, count);
+		kunmap_atomic(buf, KM_IRQ0);
+		bcount -= count;
+		pc->b_count += count;
 		if (pc->b_count == pc->sg->length) {
 			pc->sg++;
 			pc->b_count = 0;
@@ -212,19 +205,12 @@
 			return;
 		}
 		count = min(pc->sg->length - pc->b_count, bcount);
-		if (PageHighMem(pc->sg->page)) {
-			unsigned long flags;
-
-			local_irq_save(flags);
-			buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset;
-			drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
-			kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
-			local_irq_restore(flags);
-		} else {
-			buf = page_address(pc->sg->page) + pc->sg->offset;
-			drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
-		}
-		bcount -= count; pc->b_count += count;
+		buf = kmap_atomic(pc->sg->page, KM_IRQ0);
+		drive->hwif->atapi_output_bytes(drive,
+				buf + pc->b_count + pc->sg->offset, count);
+		kunmap_atomic(buf, KM_IRQ0);
+		bcount -= count;
+		pc->b_count += count;
 		if (pc->b_count == pc->sg->length) {
 			pc->sg++;
 			pc->b_count = 0;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index babd483..e0039df 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -4944,6 +4944,7 @@
 	int rc;
 
 	ENTER;
+	pci_unblock_user_cfg_access(ioa_cfg->pdev);
 	rc = pci_restore_state(ioa_cfg->pdev);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
@@ -4998,6 +4999,7 @@
 	int rc;
 
 	ENTER;
+	pci_block_user_cfg_access(ioa_cfg->pdev);
 	rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 4cbb618..459a4da 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -98,7 +98,7 @@
 static int __init
 lasi700_probe(struct parisc_device *dev)
 {
-	unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET;
+	unsigned long base = dev->hpa.start + LASI_SCSI_CORE_OFFSET;
 	struct NCR_700_Host_Parameters *hostdata;
 	struct Scsi_Host *host;
 
@@ -125,8 +125,6 @@
 		hostdata->dmode_extra = DMODE_FC2;
 	}
 
-	NCR_700_set_mem_mapped(hostdata);
-
 	host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
 	if (!host)
 		goto out_kfree;
@@ -168,7 +166,7 @@
 }
 
 static struct parisc_driver lasi700_driver = {
-	.name =		"Lasi SCSI",
+	.name =		"lasi_scsi",
 	.id_table =	lasi700_ids,
 	.probe =	lasi700_probe,
 	.remove =	__devexit_p(lasi700_driver_remove),
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index e5b0199..8be7dc0 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -48,6 +48,8 @@
 #include <linux/completion.h>
 #include <linux/suspend.h>
 #include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/scatterlist.h>
 #include <scsi/scsi.h>
 #include "scsi.h"
 #include "scsi_priv.h"
@@ -62,14 +64,15 @@
 static unsigned int ata_busy_sleep (struct ata_port *ap,
 				    unsigned long tmout_pat,
 			    	    unsigned long tmout);
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
 static void ata_set_mode(struct ata_port *ap);
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
-static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift);
 static int fgb(u32 bitmap);
-static int ata_choose_xfer_mode(struct ata_port *ap,
+static int ata_choose_xfer_mode(const struct ata_port *ap,
 				u8 *xfer_mode_out,
 				unsigned int *xfer_shift_out);
-static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
 static void __ata_qc_complete(struct ata_queued_cmd *qc);
 
 static unsigned int ata_unique_id = 1;
@@ -85,7 +88,7 @@
 MODULE_VERSION(DRV_VERSION);
 
 /**
- *	ata_tf_load - send taskfile registers to host controller
+ *	ata_tf_load_pio - send taskfile registers to host controller
  *	@ap: Port to which output is sent
  *	@tf: ATA taskfile register set
  *
@@ -95,7 +98,7 @@
  *	Inherited from caller.
  */
 
-static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -153,7 +156,7 @@
  *	Inherited from caller.
  */
 
-static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -222,7 +225,7 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
 		ata_tf_load_mmio(ap, tf);
@@ -242,7 +245,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
@@ -263,7 +266,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
@@ -283,7 +286,7 @@
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
-void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
 		ata_exec_command_mmio(ap, tf);
@@ -303,7 +306,7 @@
  *	Obtains host_set lock.
  */
 
-static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
+static inline void ata_exec(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	unsigned long flags;
 
@@ -326,7 +329,7 @@
  *	Obtains host_set lock.
  */
 
-static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	ap->ops->tf_load(ap, tf);
 
@@ -346,7 +349,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
+void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	ap->ops->tf_load(ap, tf);
 	ap->ops->exec_command(ap, tf);
@@ -368,6 +371,8 @@
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
+	tf->command = ata_check_status(ap);
+	tf->feature = inb(ioaddr->error_addr);
 	tf->nsect = inb(ioaddr->nsect_addr);
 	tf->lbal = inb(ioaddr->lbal_addr);
 	tf->lbam = inb(ioaddr->lbam_addr);
@@ -400,6 +405,8 @@
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
+	tf->command = ata_check_status(ap);
+	tf->feature = readb((void __iomem *)ioaddr->error_addr);
 	tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
 	tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
 	tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
@@ -520,30 +527,6 @@
 
 
 /**
- *	ata_chk_err - Read device error reg
- *	@ap: port where the device is
- *
- *	Reads ATA taskfile error register for
- *	currently-selected device and return its value.
- *
- *	Note: may NOT be used as the check_err() entry in
- *	ata_port_operations.
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-u8 ata_chk_err(struct ata_port *ap)
-{
-	if (ap->ops->check_err)
-		return ap->ops->check_err(ap);
-
-	if (ap->flags & ATA_FLAG_MMIO) {
-		return readb((void __iomem *) ap->ioaddr.error_addr);
-	}
-	return inb(ap->ioaddr.error_addr);
-}
-
-/**
  *	ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
  *	@tf: Taskfile to convert
  *	@fis: Buffer into which data will output
@@ -556,7 +539,7 @@
  *	Inherited from caller.
  */
 
-void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp)
+void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
 {
 	fis[0] = 0x27;	/* Register - Host to Device FIS */
 	fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
@@ -597,7 +580,7 @@
  *	Inherited from caller.
  */
 
-void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
+void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf)
 {
 	tf->command	= fis[2];	/* status */
 	tf->feature	= fis[3];	/* error */
@@ -615,79 +598,53 @@
 	tf->hob_nsect	= fis[13];
 }
 
-/**
- *	ata_prot_to_cmd - determine which read/write opcodes to use
- *	@protocol: ATA_PROT_xxx taskfile protocol
- *	@lba48: true is lba48 is present
- *
- *	Given necessary input, determine which read/write commands
- *	to use to transfer data.
- *
- *	LOCKING:
- *	None.
- */
-static int ata_prot_to_cmd(int protocol, int lba48)
-{
-	int rcmd = 0, wcmd = 0;
-
-	switch (protocol) {
-	case ATA_PROT_PIO:
-		if (lba48) {
-			rcmd = ATA_CMD_PIO_READ_EXT;
-			wcmd = ATA_CMD_PIO_WRITE_EXT;
-		} else {
-			rcmd = ATA_CMD_PIO_READ;
-			wcmd = ATA_CMD_PIO_WRITE;
-		}
-		break;
-
-	case ATA_PROT_DMA:
-		if (lba48) {
-			rcmd = ATA_CMD_READ_EXT;
-			wcmd = ATA_CMD_WRITE_EXT;
-		} else {
-			rcmd = ATA_CMD_READ;
-			wcmd = ATA_CMD_WRITE;
-		}
-		break;
-
-	default:
-		return -1;
-	}
-
-	return rcmd | (wcmd << 8);
-}
+static const u8 ata_rw_cmds[] = {
+	/* pio multi */
+	ATA_CMD_READ_MULTI,
+	ATA_CMD_WRITE_MULTI,
+	ATA_CMD_READ_MULTI_EXT,
+	ATA_CMD_WRITE_MULTI_EXT,
+	/* pio */
+	ATA_CMD_PIO_READ,
+	ATA_CMD_PIO_WRITE,
+	ATA_CMD_PIO_READ_EXT,
+	ATA_CMD_PIO_WRITE_EXT,
+	/* dma */
+	ATA_CMD_READ,
+	ATA_CMD_WRITE,
+	ATA_CMD_READ_EXT,
+	ATA_CMD_WRITE_EXT
+};
 
 /**
- *	ata_dev_set_protocol - set taskfile protocol and r/w commands
- *	@dev: device to examine and configure
+ *	ata_rwcmd_protocol - set taskfile r/w commands and protocol
+ *	@qc: command to examine and configure
  *
- *	Examine the device configuration, after we have
- *	read the identify-device page and configured the
- *	data transfer mode.  Set internal state related to
- *	the ATA taskfile protocol (pio, pio mult, dma, etc.)
- *	and calculate the proper read/write commands to use.
+ *	Examine the device configuration and tf->flags to calculate 
+ *	the proper read/write commands and protocol to use.
  *
  *	LOCKING:
  *	caller.
  */
-static void ata_dev_set_protocol(struct ata_device *dev)
+void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
 {
-	int pio = (dev->flags & ATA_DFLAG_PIO);
-	int lba48 = (dev->flags & ATA_DFLAG_LBA48);
-	int proto, cmd;
+	struct ata_taskfile *tf = &qc->tf;
+	struct ata_device *dev = qc->dev;
 
-	if (pio)
-		proto = dev->xfer_protocol = ATA_PROT_PIO;
-	else
-		proto = dev->xfer_protocol = ATA_PROT_DMA;
+	int index, lba48, write;
+ 
+	lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
+	write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
 
-	cmd = ata_prot_to_cmd(proto, lba48);
-	if (cmd < 0)
-		BUG();
+	if (dev->flags & ATA_DFLAG_PIO) {
+		tf->protocol = ATA_PROT_PIO;
+		index = dev->multi_count ? 0 : 4;
+	} else {
+		tf->protocol = ATA_PROT_DMA;
+		index = 8;
+	}
 
-	dev->read_cmd = cmd & 0xff;
-	dev->write_cmd = (cmd >> 8) & 0xff;
+	tf->command = ata_rw_cmds[index + lba48 + write];
 }
 
 static const char * xfer_mode_str[] = {
@@ -869,7 +826,7 @@
  *	the event of failure.
  */
 
-unsigned int ata_dev_classify(struct ata_taskfile *tf)
+unsigned int ata_dev_classify(const struct ata_taskfile *tf)
 {
 	/* Apple's open source Darwin code hints that some devices only
 	 * put a proper signature into the LBA mid/high registers,
@@ -921,8 +878,8 @@
 
 	memset(&tf, 0, sizeof(tf));
 
-	err = ata_chk_err(ap);
 	ap->ops->tf_read(ap, &tf);
+	err = tf.feature;
 
 	dev->class = ATA_DEV_NONE;
 
@@ -961,7 +918,7 @@
  *	caller.
  */
 
-void ata_dev_id_string(u16 *id, unsigned char *s,
+void ata_dev_id_string(const u16 *id, unsigned char *s,
 		       unsigned int ofs, unsigned int len)
 {
 	unsigned int c;
@@ -1078,7 +1035,7 @@
  *	caller.
  */
 
-static inline void ata_dump_id(struct ata_device *dev)
+static inline void ata_dump_id(const struct ata_device *dev)
 {
 	DPRINTK("49==0x%04x  "
 		"53==0x%04x  "
@@ -1106,6 +1063,31 @@
 		dev->id[93]);
 }
 
+/*
+ *	Compute the PIO modes available for this device. This is not as
+ *	trivial as it seems if we must consider early devices correctly.
+ *
+ *	FIXME: pre IDE drive timing (do we care ?). 
+ */
+
+static unsigned int ata_pio_modes(const struct ata_device *adev)
+{
+	u16 modes;
+
+	/* Usual case. Word 53 indicates word 88 is valid */
+	if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+		modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
+		modes <<= 3;
+		modes |= 0x7;
+		return modes;
+	}
+
+	/* If word 88 isn't valid then Word 51 holds the PIO timing number
+	   for the maximum. Turn it into a mask and return it */
+	modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+	return modes;
+}
+
 /**
  *	ata_dev_identify - obtain IDENTIFY x DEVICE page
  *	@ap: port on which device we wish to probe resides
@@ -1131,10 +1113,9 @@
 static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 {
 	struct ata_device *dev = &ap->device[device];
-	unsigned int i;
+	unsigned int major_version;
 	u16 tmp;
 	unsigned long xfer_modes;
-	u8 status;
 	unsigned int using_edd;
 	DECLARE_COMPLETION(wait);
 	struct ata_queued_cmd *qc;
@@ -1188,8 +1169,11 @@
 	else
 		wait_for_completion(&wait);
 
-	status = ata_chk_status(ap);
-	if (status & ATA_ERR) {
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	ap->ops->tf_read(ap, &qc->tf);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (qc->tf.command & ATA_ERR) {
 		/*
 		 * arg!  EDD works for all test cases, but seems to return
 		 * the ATA signature for some ATAPI devices.  Until the
@@ -1202,7 +1186,7 @@
 		 * to have this problem.
 		 */
 		if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
-			u8 err = ata_chk_err(ap);
+			u8 err = qc->tf.feature;
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
 				qc->cursg = 0;
@@ -1229,9 +1213,9 @@
 	 * common ATA, ATAPI feature tests
 	 */
 
-	/* we require LBA and DMA support (bits 8 & 9 of word 49) */
-	if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) {
-		printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
+	/* we require DMA support (bits 8 of word 49) */
+	if (!ata_id_has_dma(dev->id)) {
+		printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
 		goto err_out_nosup;
 	}
 
@@ -1239,10 +1223,8 @@
 	xfer_modes = dev->id[ATA_ID_UDMA_MODES];
 	if (!xfer_modes)
 		xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
-	if (!xfer_modes) {
-		xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
-		xfer_modes |= (0x7 << ATA_SHIFT_PIO);
-	}
+	if (!xfer_modes)
+		xfer_modes = ata_pio_modes(dev);
 
 	ata_dump_id(dev);
 
@@ -1251,32 +1233,75 @@
 		if (!ata_id_is_ata(dev->id))	/* sanity check */
 			goto err_out_nosup;
 
+		/* get major version */
 		tmp = dev->id[ATA_ID_MAJOR_VER];
-		for (i = 14; i >= 1; i--)
-			if (tmp & (1 << i))
+		for (major_version = 14; major_version >= 1; major_version--)
+			if (tmp & (1 << major_version))
 				break;
 
-		/* we require at least ATA-3 */
-		if (i < 3) {
-			printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
-			goto err_out_nosup;
+		/*
+		 * The exact sequence expected by certain pre-ATA4 drives is:
+		 * SRST RESET
+		 * IDENTIFY
+		 * INITIALIZE DEVICE PARAMETERS
+		 * anything else..
+		 * Some drives were very specific about that exact sequence.
+		 */
+		if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
+			ata_dev_init_params(ap, dev);
+
+			/* current CHS translation info (id[53-58]) might be
+			 * changed. reread the identify device info.
+			 */
+			ata_dev_reread_id(ap, dev);
 		}
 
-		if (ata_id_has_lba48(dev->id)) {
-			dev->flags |= ATA_DFLAG_LBA48;
-			dev->n_sectors = ata_id_u64(dev->id, 100);
-		} else {
-			dev->n_sectors = ata_id_u32(dev->id, 60);
+		if (ata_id_has_lba(dev->id)) {
+			dev->flags |= ATA_DFLAG_LBA;
+
+			if (ata_id_has_lba48(dev->id)) {
+				dev->flags |= ATA_DFLAG_LBA48;
+				dev->n_sectors = ata_id_u64(dev->id, 100);
+			} else {
+				dev->n_sectors = ata_id_u32(dev->id, 60);
+			}
+
+			/* print device info to dmesg */
+			printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
+			       ap->id, device,
+			       major_version,
+			       ata_mode_string(xfer_modes),
+			       (unsigned long long)dev->n_sectors,
+			       dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
+		} else { 
+			/* CHS */
+
+			/* Default translation */
+			dev->cylinders	= dev->id[1];
+			dev->heads	= dev->id[3];
+			dev->sectors	= dev->id[6];
+			dev->n_sectors	= dev->cylinders * dev->heads * dev->sectors;
+
+			if (ata_id_current_chs_valid(dev->id)) {
+				/* Current CHS translation is valid. */
+				dev->cylinders = dev->id[54];
+				dev->heads     = dev->id[55];
+				dev->sectors   = dev->id[56];
+				
+				dev->n_sectors = ata_id_u32(dev->id, 57);
+			}
+
+			/* print device info to dmesg */
+			printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
+			       ap->id, device,
+			       major_version,
+			       ata_mode_string(xfer_modes),
+			       (unsigned long long)dev->n_sectors,
+			       (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
+
 		}
 
 		ap->host->max_cmd_len = 16;
-
-		/* print device info to dmesg */
-		printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
-		       ap->id, device,
-		       ata_mode_string(xfer_modes),
-		       (unsigned long long)dev->n_sectors,
-		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
 	}
 
 	/* ATAPI-specific feature tests */
@@ -1310,7 +1335,7 @@
 }
 
 
-static inline u8 ata_dev_knobble(struct ata_port *ap)
+static inline u8 ata_dev_knobble(const struct ata_port *ap)
 {
 	return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
 }
@@ -1496,7 +1521,153 @@
 	ap->flags |= ATA_FLAG_PORT_DISABLED;
 }
 
-static struct {
+/*
+ * This mode timing computation functionality is ported over from
+ * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
+ */
+/*
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
+ * These were taken from ATA/ATAPI-6 standard, rev 0a, except
+ * for PIO 5, which is a nonstandard extension and UDMA6, which
+ * is currently supported only by Maxtor drives. 
+ */
+
+static const struct ata_timing ata_timing[] = {
+
+	{ 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_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_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_5,     20,  50,  30, 100,  50,  30, 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 }, */
+
+	{ 0xFF }
+};
+
+#define ENOUGH(v,unit)		(((v)-1)/(unit)+1)
+#define EZ(v,unit)		((v)?ENOUGH(v,unit):0)
+
+static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
+{
+	q->setup   = EZ(t->setup   * 1000,  T);
+	q->act8b   = EZ(t->act8b   * 1000,  T);
+	q->rec8b   = EZ(t->rec8b   * 1000,  T);
+	q->cyc8b   = EZ(t->cyc8b   * 1000,  T);
+	q->active  = EZ(t->active  * 1000,  T);
+	q->recover = EZ(t->recover * 1000,  T);
+	q->cycle   = EZ(t->cycle   * 1000,  T);
+	q->udma    = EZ(t->udma    * 1000, UT);
+}
+
+void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
+		      struct ata_timing *m, unsigned int what)
+{
+	if (what & ATA_TIMING_SETUP  ) m->setup   = max(a->setup,   b->setup);
+	if (what & ATA_TIMING_ACT8B  ) m->act8b   = max(a->act8b,   b->act8b);
+	if (what & ATA_TIMING_REC8B  ) m->rec8b   = max(a->rec8b,   b->rec8b);
+	if (what & ATA_TIMING_CYC8B  ) m->cyc8b   = max(a->cyc8b,   b->cyc8b);
+	if (what & ATA_TIMING_ACTIVE ) m->active  = max(a->active,  b->active);
+	if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+	if (what & ATA_TIMING_CYCLE  ) m->cycle   = max(a->cycle,   b->cycle);
+	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 *t;
+
+	for (t = ata_timing; t->mode != speed; t++)
+		if (t->mode == 0xFF)
+			return NULL;
+	return t; 
+}
+
+int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+		       struct ata_timing *t, int T, int UT)
+{
+	const struct ata_timing *s;
+	struct ata_timing p;
+
+	/*
+	 * Find the mode. 
+	*/
+
+	if (!(s = ata_timing_find_mode(speed)))
+		return -EINVAL;
+
+	/*
+	 * If the drive is an EIDE drive, it can tell us it needs extended
+	 * PIO/MW_DMA cycle timing.
+	 */
+
+	if (adev->id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */
+		memset(&p, 0, sizeof(p));
+		if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+			if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
+					    else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
+		} else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
+			p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
+		}
+		ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
+	}
+
+	/*
+	 * Convert the timing to bus clock counts.
+	 */
+
+	ata_timing_quantize(s, t, T, UT);
+
+	/*
+	 * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
+	 * and some other commands. We have to ensure that the DMA cycle timing is
+	 * slower/equal than the fastest PIO timing.
+	 */
+
+	if (speed > XFER_PIO_4) {
+		ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
+		ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
+	}
+
+	/*
+	 * Lenghten active & recovery time so that cycle time is correct.
+	 */
+
+	if (t->act8b + t->rec8b < t->cyc8b) {
+		t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
+		t->rec8b = t->cyc8b - t->act8b;
+	}
+
+	if (t->active + t->recover < t->cycle) {
+		t->active += (t->cycle - (t->active + t->recover)) / 2;
+		t->recover = t->cycle - t->active;
+	}
+
+	return 0;
+}
+
+static const struct {
 	unsigned int shift;
 	u8 base;
 } xfer_mode_classes[] = {
@@ -1603,7 +1774,7 @@
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-	unsigned int i, xfer_shift;
+	unsigned int xfer_shift;
 	u8 xfer_mode;
 	int rc;
 
@@ -1632,11 +1803,6 @@
 	if (ap->ops->post_set_mode)
 		ap->ops->post_set_mode(ap);
 
-	for (i = 0; i < 2; i++) {
-		struct ata_device *dev = &ap->device[i];
-		ata_dev_set_protocol(dev);
-	}
-
 	return;
 
 err_out:
@@ -1910,7 +2076,8 @@
 	DPRINTK("EXIT\n");
 }
 
-static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev)
+static void ata_pr_blacklisted(const struct ata_port *ap,
+			       const struct ata_device *dev)
 {
 	printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
 		ap->id, dev->devno);
@@ -1948,7 +2115,7 @@
 	"_NEC DV5800A",
 };
 
-static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
+static int ata_dma_blacklisted(const struct ata_device *dev)
 {
 	unsigned char model_num[40];
 	char *s;
@@ -1973,9 +2140,9 @@
 	return 0;
 }
 
-static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
+static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift)
 {
-	struct ata_device *master, *slave;
+	const struct ata_device *master, *slave;
 	unsigned int mask;
 
 	master = &ap->device[0];
@@ -1987,14 +2154,14 @@
 		mask = ap->udma_mask;
 		if (ata_dev_present(master)) {
 			mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
-			if (ata_dma_blacklisted(ap, master)) {
+			if (ata_dma_blacklisted(master)) {
 				mask = 0;
 				ata_pr_blacklisted(ap, master);
 			}
 		}
 		if (ata_dev_present(slave)) {
 			mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-			if (ata_dma_blacklisted(ap, slave)) {
+			if (ata_dma_blacklisted(slave)) {
 				mask = 0;
 				ata_pr_blacklisted(ap, slave);
 			}
@@ -2004,14 +2171,14 @@
 		mask = ap->mwdma_mask;
 		if (ata_dev_present(master)) {
 			mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
-			if (ata_dma_blacklisted(ap, master)) {
+			if (ata_dma_blacklisted(master)) {
 				mask = 0;
 				ata_pr_blacklisted(ap, master);
 			}
 		}
 		if (ata_dev_present(slave)) {
 			mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
-			if (ata_dma_blacklisted(ap, slave)) {
+			if (ata_dma_blacklisted(slave)) {
 				mask = 0;
 				ata_pr_blacklisted(ap, slave);
 			}
@@ -2075,7 +2242,7 @@
  *	Zero on success, negative on error.
  */
 
-static int ata_choose_xfer_mode(struct ata_port *ap,
+static int ata_choose_xfer_mode(const struct ata_port *ap,
 				u8 *xfer_mode_out,
 				unsigned int *xfer_shift_out)
 {
@@ -2144,6 +2311,110 @@
 }
 
 /**
+ *	ata_dev_reread_id - Reread the device identify device info
+ *	@ap: port where the device is
+ *	@dev: device to reread the identify device info
+ *
+ *	LOCKING:
+ */
+
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
+{
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int rc;
+
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
+
+	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+	qc->dma_dir = DMA_FROM_DEVICE;
+
+	if (dev->class == ATA_DEV_ATA) {
+		qc->tf.command = ATA_CMD_ID_ATA;
+		DPRINTK("do ATA identify\n");
+	} else {
+		qc->tf.command = ATA_CMD_ID_ATAPI;
+		DPRINTK("do ATAPI identify\n");
+	}
+
+	qc->tf.flags |= ATA_TFLAG_DEVICE;
+	qc->tf.protocol = ATA_PROT_PIO;
+	qc->nsect = 1;
+
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (rc)
+		goto err_out;
+
+	wait_for_completion(&wait);
+
+	swap_buf_le16(dev->id, ATA_ID_WORDS);
+
+	ata_dump_id(dev);
+
+	DPRINTK("EXIT\n");
+
+	return;
+err_out:
+	ata_port_disable(ap);
+}
+
+/**
+ *	ata_dev_init_params - Issue INIT DEV PARAMS command
+ *	@ap: Port associated with device @dev
+ *	@dev: Device to which command will be sent
+ *
+ *	LOCKING:
+ */
+
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+{
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	int rc;
+	unsigned long flags;
+	u16 sectors = dev->id[6];
+	u16 heads   = dev->id[3];
+
+	/* Number of sectors per track 1-255. Number of heads 1-16 */
+	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+		return;
+
+	/* set up init dev params taskfile */
+	DPRINTK("init dev params \n");
+
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
+
+	qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	qc->tf.protocol = ATA_PROT_NODATA;
+	qc->tf.nsect = sectors;
+	qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (rc)
+		ata_port_disable(ap);
+	else
+		wait_for_completion(&wait);
+
+	DPRINTK("EXIT\n");
+}
+
+/**
  *	ata_sg_clean - Unmap DMA memory associated with command
  *	@qc: Command containing DMA memory to be released
  *
@@ -2284,19 +2555,12 @@
 
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
-	struct scatterlist *sg;
-
 	qc->flags |= ATA_QCFLAG_SINGLE;
 
-	memset(&qc->sgent, 0, sizeof(qc->sgent));
 	qc->sg = &qc->sgent;
 	qc->n_elem = 1;
 	qc->buf_virt = buf;
-
-	sg = qc->sg;
-	sg->page = virt_to_page(buf);
-	sg->offset = (unsigned long) buf & ~PAGE_MASK;
-	sg->length = buflen;
+	sg_init_one(qc->sg, buf, buflen);
 }
 
 /**
@@ -2399,7 +2663,7 @@
  *	None.  (grabs host lock)
  */
 
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned long flags;
@@ -2407,38 +2671,38 @@
 	spin_lock_irqsave(&ap->host_set->lock, flags);
 	ap->flags &= ~ATA_FLAG_NOINTR;
 	ata_irq_on(ap);
-	ata_qc_complete(qc, drv_stat);
+	ata_qc_complete(qc, err_mask);
 	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
 /**
  *	ata_pio_poll -
- *	@ap:
+ *	@ap: the target ata_port
  *
  *	LOCKING:
  *	None.  (executing in kernel thread context)
  *
  *	RETURNS:
- *
+ *	timeout value to use
  */
 
 static unsigned long ata_pio_poll(struct ata_port *ap)
 {
 	u8 status;
-	unsigned int poll_state = PIO_ST_UNKNOWN;
-	unsigned int reg_state = PIO_ST_UNKNOWN;
-	const unsigned int tmout_state = PIO_ST_TMOUT;
+	unsigned int poll_state = HSM_ST_UNKNOWN;
+	unsigned int reg_state = HSM_ST_UNKNOWN;
+	const unsigned int tmout_state = HSM_ST_TMOUT;
 
-	switch (ap->pio_task_state) {
-	case PIO_ST:
-	case PIO_ST_POLL:
-		poll_state = PIO_ST_POLL;
-		reg_state = PIO_ST;
+	switch (ap->hsm_task_state) {
+	case HSM_ST:
+	case HSM_ST_POLL:
+		poll_state = HSM_ST_POLL;
+		reg_state = HSM_ST;
 		break;
-	case PIO_ST_LAST:
-	case PIO_ST_LAST_POLL:
-		poll_state = PIO_ST_LAST_POLL;
-		reg_state = PIO_ST_LAST;
+	case HSM_ST_LAST:
+	case HSM_ST_LAST_POLL:
+		poll_state = HSM_ST_LAST_POLL;
+		reg_state = HSM_ST_LAST;
 		break;
 	default:
 		BUG();
@@ -2448,20 +2712,20 @@
 	status = ata_chk_status(ap);
 	if (status & ATA_BUSY) {
 		if (time_after(jiffies, ap->pio_task_timeout)) {
-			ap->pio_task_state = tmout_state;
+			ap->hsm_task_state = tmout_state;
 			return 0;
 		}
-		ap->pio_task_state = poll_state;
+		ap->hsm_task_state = poll_state;
 		return ATA_SHORT_PAUSE;
 	}
 
-	ap->pio_task_state = reg_state;
+	ap->hsm_task_state = reg_state;
 	return 0;
 }
 
 /**
- *	ata_pio_complete -
- *	@ap:
+ *	ata_pio_complete - check if drive is busy or idle
+ *	@ap: the target ata_port
  *
  *	LOCKING:
  *	None.  (executing in kernel thread context)
@@ -2480,14 +2744,14 @@
 	 * we enter, BSY will be cleared in a chk-status or two.  If not,
 	 * the drive is probably seeking or something.  Snooze for a couple
 	 * msecs, then chk-status again.  If still busy, fall back to
-	 * PIO_ST_POLL state.
+	 * HSM_ST_POLL state.
 	 */
 	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
 	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
 		msleep(2);
 		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
 		if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
-			ap->pio_task_state = PIO_ST_LAST_POLL;
+			ap->hsm_task_state = HSM_ST_LAST_POLL;
 			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
 			return 0;
 		}
@@ -2495,16 +2759,16 @@
 
 	drv_stat = ata_wait_idle(ap);
 	if (!ata_ok(drv_stat)) {
-		ap->pio_task_state = PIO_ST_ERR;
+		ap->hsm_task_state = HSM_ST_ERR;
 		return 0;
 	}
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
-	ap->pio_task_state = PIO_ST_IDLE;
+	ap->hsm_task_state = HSM_ST_IDLE;
 
-	ata_poll_qc_complete(qc, drv_stat);
+	ata_poll_qc_complete(qc, 0);
 
 	/* another command may start at this point */
 
@@ -2513,7 +2777,7 @@
 
 
 /**
- *	swap_buf_le16 -
+ *	swap_buf_le16 - swap halves of 16-words in place
  *	@buf:  Buffer to swap
  *	@buf_words:  Number of 16-bit words in buffer.
  *
@@ -2522,6 +2786,7 @@
  *	vice-versa.
  *
  *	LOCKING:
+ *	Inherited from caller.
  */
 void swap_buf_le16(u16 *buf, unsigned int buf_words)
 {
@@ -2544,7 +2809,6 @@
  *
  *	LOCKING:
  *	Inherited from caller.
- *
  */
 
 static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2590,7 +2854,6 @@
  *
  *	LOCKING:
  *	Inherited from caller.
- *
  */
 
 static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2630,7 +2893,6 @@
  *
  *	LOCKING:
  *	Inherited from caller.
- *
  */
 
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2662,7 +2924,7 @@
 	unsigned char *buf;
 
 	if (qc->cursect == (qc->nsect - 1))
-		ap->pio_task_state = PIO_ST_LAST;
+		ap->hsm_task_state = HSM_ST_LAST;
 
 	page = sg[qc->cursg].page;
 	offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
@@ -2712,7 +2974,7 @@
 	unsigned int offset, count;
 
 	if (qc->curbytes + bytes >= qc->nbytes)
-		ap->pio_task_state = PIO_ST_LAST;
+		ap->hsm_task_state = HSM_ST_LAST;
 
 next_sg:
 	if (unlikely(qc->cursg >= qc->n_elem)) {
@@ -2734,7 +2996,7 @@
 		for (i = 0; i < words; i++)
 			ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
 
-		ap->pio_task_state = PIO_ST_LAST;
+		ap->hsm_task_state = HSM_ST_LAST;
 		return;
 	}
 
@@ -2783,7 +3045,6 @@
  *
  *	LOCKING:
  *	Inherited from caller.
- *
  */
 
 static void atapi_pio_bytes(struct ata_queued_cmd *qc)
@@ -2815,12 +3076,12 @@
 err_out:
 	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
 	      ap->id, dev->devno);
-	ap->pio_task_state = PIO_ST_ERR;
+	ap->hsm_task_state = HSM_ST_ERR;
 }
 
 /**
- *	ata_pio_sector -
- *	@ap:
+ *	ata_pio_block - start PIO on a block
+ *	@ap: the target ata_port
  *
  *	LOCKING:
  *	None.  (executing in kernel thread context)
@@ -2832,19 +3093,19 @@
 	u8 status;
 
 	/*
-	 * This is purely hueristic.  This is a fast path.
+	 * This is purely heuristic.  This is a fast path.
 	 * Sometimes when we enter, BSY will be cleared in
 	 * a chk-status or two.  If not, the drive is probably seeking
 	 * or something.  Snooze for a couple msecs, then
 	 * chk-status again.  If still busy, fall back to
-	 * PIO_ST_POLL state.
+	 * HSM_ST_POLL state.
 	 */
 	status = ata_busy_wait(ap, ATA_BUSY, 5);
 	if (status & ATA_BUSY) {
 		msleep(2);
 		status = ata_busy_wait(ap, ATA_BUSY, 10);
 		if (status & ATA_BUSY) {
-			ap->pio_task_state = PIO_ST_POLL;
+			ap->hsm_task_state = HSM_ST_POLL;
 			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
 			return;
 		}
@@ -2856,7 +3117,7 @@
 	if (is_atapi_taskfile(&qc->tf)) {
 		/* no more data to transfer or unsupported ATAPI command */
 		if ((status & ATA_DRQ) == 0) {
-			ap->pio_task_state = PIO_ST_LAST;
+			ap->hsm_task_state = HSM_ST_LAST;
 			return;
 		}
 
@@ -2864,7 +3125,7 @@
 	} else {
 		/* handle BSY=0, DRQ=0 as error */
 		if ((status & ATA_DRQ) == 0) {
-			ap->pio_task_state = PIO_ST_ERR;
+			ap->hsm_task_state = HSM_ST_ERR;
 			return;
 		}
 
@@ -2875,18 +3136,15 @@
 static void ata_pio_error(struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc;
-	u8 drv_stat;
+
+	printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
-	drv_stat = ata_chk_status(ap);
-	printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
-	       ap->id, drv_stat);
+	ap->hsm_task_state = HSM_ST_IDLE;
 
-	ap->pio_task_state = PIO_ST_IDLE;
-
-	ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
+	ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
 }
 
 static void ata_pio_task(void *_data)
@@ -2899,25 +3157,25 @@
 	timeout = 0;
 	qc_completed = 0;
 
-	switch (ap->pio_task_state) {
-	case PIO_ST_IDLE:
+	switch (ap->hsm_task_state) {
+	case HSM_ST_IDLE:
 		return;
 
-	case PIO_ST:
+	case HSM_ST:
 		ata_pio_block(ap);
 		break;
 
-	case PIO_ST_LAST:
+	case HSM_ST_LAST:
 		qc_completed = ata_pio_complete(ap);
 		break;
 
-	case PIO_ST_POLL:
-	case PIO_ST_LAST_POLL:
+	case HSM_ST_POLL:
+	case HSM_ST_LAST_POLL:
 		timeout = ata_pio_poll(ap);
 		break;
 
-	case PIO_ST_TMOUT:
-	case PIO_ST_ERR:
+	case HSM_ST_TMOUT:
+	case HSM_ST_ERR:
 		ata_pio_error(ap);
 		return;
 	}
@@ -2928,52 +3186,6 @@
 		goto fsm_start;
 }
 
-static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
-				struct scsi_cmnd *cmd)
-{
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
-	int rc;
-
-	DPRINTK("ATAPI request sense\n");
-
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	/* FIXME: is this needed? */
-	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-
-	ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
-	qc->dma_dir = DMA_FROM_DEVICE;
-
-	memset(&qc->cdb, 0, ap->cdb_len);
-	qc->cdb[0] = REQUEST_SENSE;
-	qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
-
-	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	qc->tf.command = ATA_CMD_PACKET;
-
-	qc->tf.protocol = ATA_PROT_ATAPI;
-	qc->tf.lbam = (8 * 1024) & 0xff;
-	qc->tf.lbah = (8 * 1024) >> 8;
-	qc->nbytes = SCSI_SENSE_BUFFERSIZE;
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	if (rc)
-		ata_port_disable(ap);
-	else
-		wait_for_completion(&wait);
-
-	DPRINTK("EXIT\n");
-}
-
 /**
  *	ata_qc_timeout - Handle timeout of queued command
  *	@qc: Command that timed out
@@ -3055,7 +3267,7 @@
 		       ap->id, qc->tf.command, drv_stat, host_stat);
 
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, drv_stat);
+		ata_qc_complete(qc, ac_err_mask(drv_stat));
 		break;
 	}
 
@@ -3091,14 +3303,14 @@
 	DPRINTK("ENTER\n");
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
-	if (!qc) {
+	if (qc)
+		ata_qc_timeout(qc);
+	else {
 		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
 		       ap->id);
 		goto out;
 	}
 
-	ata_qc_timeout(qc);
-
 out:
 	DPRINTK("EXIT\n");
 }
@@ -3155,15 +3367,12 @@
 		qc->nbytes = qc->curbytes = 0;
 
 		ata_tf_init(ap, &qc->tf, dev->devno);
-
-		if (dev->flags & ATA_DFLAG_LBA48)
-			qc->tf.flags |= ATA_TFLAG_LBA48;
 	}
 
 	return qc;
 }
 
-static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
 	return 0;
 }
@@ -3201,7 +3410,6 @@
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
- *
  */
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
@@ -3221,10 +3429,9 @@
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
- *
  */
 
-void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
 	int rc;
 
@@ -3241,7 +3448,7 @@
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
 	/* call completion callback */
-	rc = qc->complete_fn(qc, drv_stat);
+	rc = qc->complete_fn(qc, err_mask);
 
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
@@ -3360,7 +3567,7 @@
 	case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
 		ata_qc_set_polling(qc);
 		ata_tf_to_host_nolock(ap, &qc->tf);
-		ap->pio_task_state = PIO_ST;
+		ap->hsm_task_state = HSM_ST;
 		queue_work(ata_wq, &ap->pio_task);
 		break;
 
@@ -3586,7 +3793,7 @@
 		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 	} else
-	host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 	return host_stat;
 }
 
@@ -3679,7 +3886,7 @@
 		ap->ops->irq_clear(ap);
 
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, status);
+		ata_qc_complete(qc, ac_err_mask(status));
 		break;
 
 	default:
@@ -3715,7 +3922,6 @@
  *
  *	RETURNS:
  *	IRQ_NONE or IRQ_HANDLED.
- *
  */
 
 irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
@@ -3775,7 +3981,7 @@
 	/* sleep-wait for BSY to clear */
 	DPRINTK("busy wait\n");
 	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
-		goto err_out;
+		goto err_out_status;
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
@@ -3806,14 +4012,16 @@
 		ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
 		/* PIO commands are handled by polling */
-		ap->pio_task_state = PIO_ST;
+		ap->hsm_task_state = HSM_ST;
 		queue_work(ata_wq, &ap->pio_task);
 	}
 
 	return;
 
+err_out_status:
+	status = ata_chk_status(ap);
 err_out:
-	ata_poll_qc_complete(qc, ATA_ERR);
+	ata_poll_qc_complete(qc, __ac_err_mask(status));
 }
 
 
@@ -3827,6 +4035,7 @@
  *	May be used as the port_start() entry in ata_port_operations.
  *
  *	LOCKING:
+ *	Inherited from caller.
  */
 
 int ata_port_start (struct ata_port *ap)
@@ -3852,6 +4061,7 @@
  *	May be used as the port_stop() entry in ata_port_operations.
  *
  *	LOCKING:
+ *	Inherited from caller.
  */
 
 void ata_port_stop (struct ata_port *ap)
@@ -3874,6 +4084,7 @@
  *	@do_unregister: 1 if we fully unregister, 0 to just stop the port
  *
  *	LOCKING:
+ *	Inherited from caller.
  */
 
 static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
@@ -3901,12 +4112,11 @@
  *
  *	LOCKING:
  *	Inherited from caller.
- *
  */
 
 static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
 			  struct ata_host_set *host_set,
-			  struct ata_probe_ent *ent, unsigned int port_no)
+			  const struct ata_probe_ent *ent, unsigned int port_no)
 {
 	unsigned int i;
 
@@ -3962,10 +4172,9 @@
  *
  *	RETURNS:
  *	New ata_port on success, for NULL on error.
- *
  */
 
-static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
+static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
 				      struct ata_host_set *host_set,
 				      unsigned int port_no)
 {
@@ -4010,10 +4219,9 @@
  *
  *	RETURNS:
  *	Number of ports registered.  Zero on error (no ports registered).
- *
  */
 
-int ata_device_add(struct ata_probe_ent *ent)
+int ata_device_add(const struct ata_probe_ent *ent)
 {
 	unsigned int count = 0, i;
 	struct device *dev = ent->dev;
@@ -4021,11 +4229,10 @@
 
 	DPRINTK("ENTER\n");
 	/* alloc a container for our list of ATA ports (buses) */
-	host_set = kmalloc(sizeof(struct ata_host_set) +
+	host_set = kzalloc(sizeof(struct ata_host_set) +
 			   (ent->n_ports * sizeof(void *)), GFP_KERNEL);
 	if (!host_set)
 		return 0;
-	memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *)));
 	spin_lock_init(&host_set->lock);
 
 	host_set->dev = dev;
@@ -4065,10 +4272,8 @@
 		count++;
 	}
 
-	if (!count) {
-		kfree(host_set);
-		return 0;
-	}
+	if (!count)
+		goto err_free_ret;
 
 	/* obtain irq, that is shared between channels */
 	if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
@@ -4113,7 +4318,7 @@
 	for (i = 0; i < count; i++) {
 		struct ata_port *ap = host_set->ports[i];
 
-		scsi_scan_host(ap->host);
+		ata_scsi_scan_host(ap);
 	}
 
 	dev_set_drvdata(dev, host_set);
@@ -4126,6 +4331,7 @@
 		ata_host_remove(host_set->ports[i], 1);
 		scsi_host_put(host_set->ports[i]->host);
 	}
+err_free_ret:
 	kfree(host_set);
 	VPRINTK("EXIT, returning 0\n");
 	return 0;
@@ -4142,7 +4348,6 @@
  *	Inherited from calling layer (may sleep).
  */
 
-
 void ata_host_set_remove(struct ata_host_set *host_set)
 {
 	struct ata_port *ap;
@@ -4232,19 +4437,17 @@
 }
 
 static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
+ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
 {
 	struct ata_probe_ent *probe_ent;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       kobject_name(&(dev->kobj)));
 		return NULL;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-
 	INIT_LIST_HEAD(&probe_ent->node);
 	probe_ent->dev = dev;
 
@@ -4273,85 +4476,86 @@
  *	ata_pci_init_native_mode - Initialize native-mode driver
  *	@pdev:  pci device to be initialized
  *	@port:  array[2] of pointers to port info structures.
+ *	@ports: bitmap of ports present
  *
  *	Utility function which allocates and initializes an
  *	ata_probe_ent structure for a standard dual-port
  *	PIO-based IDE controller.  The returned ata_probe_ent
  *	structure can be passed to ata_device_add().  The returned
  *	ata_probe_ent structure should then be freed with kfree().
+ *
+ *	The caller need only pass the address of the primary port, the
+ *	secondary will be deduced automatically. If the device has non
+ *	standard secondary port mappings this function can be called twice,
+ *	once for each interface.
  */
 
 struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
 {
 	struct ata_probe_ent *probe_ent =
 		ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+	int p = 0;
+
 	if (!probe_ent)
 		return NULL;
 
-	probe_ent->n_ports = 2;
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = SA_SHIRQ;
 
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+	if (ports & ATA_PORT_PRIMARY) {
+		probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
+		probe_ent->port[p].altstatus_addr =
+		probe_ent->port[p].ctl_addr =
+			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+		probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+		ata_std_ports(&probe_ent->port[p]);
+		p++;
+	}
 
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+	if (ports & ATA_PORT_SECONDARY) {
+		probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
+		probe_ent->port[p].altstatus_addr =
+		probe_ent->port[p].ctl_addr =
+			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+		probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+		ata_std_ports(&probe_ent->port[p]);
+		p++;
+	}
 
-	ata_std_ports(&probe_ent->port[0]);
-	ata_std_ports(&probe_ent->port[1]);
-
+	probe_ent->n_ports = p;
 	return probe_ent;
 }
 
-static struct ata_probe_ent *
-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
-    struct ata_probe_ent **ppe2)
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num)
 {
-	struct ata_probe_ent *probe_ent, *probe_ent2;
+	struct ata_probe_ent *probe_ent;
 
-	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
 	if (!probe_ent)
 		return NULL;
-	probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
-	if (!probe_ent2) {
-		kfree(probe_ent);
-		return NULL;
-	}
 
-	probe_ent->n_ports = 1;
-	probe_ent->irq = 14;
-
-	probe_ent->hard_port_no = 0;
 	probe_ent->legacy_mode = 1;
+	probe_ent->n_ports = 1;
+	probe_ent->hard_port_no = port_num;
 
-	probe_ent2->n_ports = 1;
-	probe_ent2->irq = 15;
-
-	probe_ent2->hard_port_no = 1;
-	probe_ent2->legacy_mode = 1;
-
-	probe_ent->port[0].cmd_addr = 0x1f0;
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr = 0x3f6;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
-	probe_ent2->port[0].cmd_addr = 0x170;
-	probe_ent2->port[0].altstatus_addr =
-	probe_ent2->port[0].ctl_addr = 0x376;
-	probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-
+	switch(port_num)
+	{
+		case 0:
+			probe_ent->irq = 14;
+			probe_ent->port[0].cmd_addr = 0x1f0;
+			probe_ent->port[0].altstatus_addr =
+			probe_ent->port[0].ctl_addr = 0x3f6;
+			break;
+		case 1:
+			probe_ent->irq = 15;
+			probe_ent->port[0].cmd_addr = 0x170;
+			probe_ent->port[0].altstatus_addr =
+			probe_ent->port[0].ctl_addr = 0x376;
+			break;
+	}
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num;
 	ata_std_ports(&probe_ent->port[0]);
-	ata_std_ports(&probe_ent2->port[0]);
-
-	*ppe2 = probe_ent2;
 	return probe_ent;
 }
 
@@ -4374,13 +4578,12 @@
  *
  *	RETURNS:
  *	Zero on success, negative on errno-based value on error.
- *
  */
 
 int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 		      unsigned int n_ports)
 {
-	struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
+	struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
 	struct ata_port_info *port[2];
 	u8 tmp8, mask;
 	unsigned int legacy_mode = 0;
@@ -4397,7 +4600,7 @@
 
 	if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
 	    && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
-		/* TODO: support transitioning to native mode? */
+		/* 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)
@@ -4405,11 +4608,20 @@
 	}
 
 	/* FIXME... */
-	if ((!legacy_mode) && (n_ports > 1)) {
-		printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n");
-		return -EINVAL;
+	if ((!legacy_mode) && (n_ports > 2)) {
+		printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
+		n_ports = 2;
+		/* For now */
 	}
 
+	/* 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 = pci_enable_device(pdev);
 	if (rc)
 		return rc;
@@ -4420,6 +4632,7 @@
 		goto err_out;
 	}
 
+	/* FIXME: Should use platform specific mappers for legacy port ranges */
 	if (legacy_mode) {
 		if (!request_region(0x1f0, 8, "libata")) {
 			struct resource *conflict, res;
@@ -4464,10 +4677,17 @@
 		goto err_out_regions;
 
 	if (legacy_mode) {
-		probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
-	} else
-		probe_ent = ata_pci_init_native_mode(pdev, port);
-	if (!probe_ent) {
+		if (legacy_mode & (1 << 0))
+			probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
+		if (legacy_mode & (1 << 1))
+			probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
+	} else {
+		if (n_ports == 2)
+			probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+		else
+			probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
+	}
+	if (!probe_ent && !probe_ent2) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
@@ -4505,7 +4725,7 @@
  *	@pdev: PCI device that was removed
  *
  *	PCI layer indicates to libata via this hook that
- *	hot-unplug or module unload event has occured.
+ *	hot-unplug or module unload event has occurred.
  *	Handle this by unregistering all objects associated
  *	with this PCI device.  Free those objects.  Then finally
  *	release PCI resources and disable device.
@@ -4526,7 +4746,7 @@
 }
 
 /* move to PCI subsystem */
-int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
+int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
 {
 	unsigned long tmp = 0;
 
@@ -4579,6 +4799,27 @@
 module_init(ata_init);
 module_exit(ata_exit);
 
+static unsigned long ratelimit_time;
+static spinlock_t ata_ratelimit_lock = SPIN_LOCK_UNLOCKED;
+
+int ata_ratelimit(void)
+{
+	int rc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ata_ratelimit_lock, flags);
+
+	if (time_after(jiffies, ratelimit_time)) {
+		rc = 1;
+		ratelimit_time = jiffies + (HZ/5);
+	} else
+		rc = 0;
+
+	spin_unlock_irqrestore(&ata_ratelimit_lock, flags);
+
+	return rc;
+}
+
 /*
  * libata is essentially a library of internal helper functions for
  * low-level ATA host controller drivers.  As such, the API/ABI is
@@ -4603,7 +4844,6 @@
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
 EXPORT_SYMBOL_GPL(ata_check_status);
 EXPORT_SYMBOL_GPL(ata_altstatus);
-EXPORT_SYMBOL_GPL(ata_chk_err);
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
@@ -4620,6 +4860,7 @@
 EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
 EXPORT_SYMBOL_GPL(ata_port_disable);
+EXPORT_SYMBOL_GPL(ata_ratelimit);
 EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_error);
@@ -4631,6 +4872,9 @@
 EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
+EXPORT_SYMBOL_GPL(ata_timing_compute);
+EXPORT_SYMBOL_GPL(ata_timing_merge);
+
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
 EXPORT_SYMBOL_GPL(ata_pci_host_stop);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 104fd9a..1e3792f 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -40,14 +40,64 @@
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include <linux/hdreg.h>
 #include <asm/uaccess.h>
 
 #include "libata.h"
 
-typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
-static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
+#define SECTOR_SIZE	512
 
+typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+
+#define RW_RECOVERY_MPAGE 0x1
+#define RW_RECOVERY_MPAGE_LEN 12
+#define CACHE_MPAGE 0x8
+#define CACHE_MPAGE_LEN 20
+#define CONTROL_MPAGE 0xa
+#define CONTROL_MPAGE_LEN 12
+#define ALL_MPAGES 0x3f
+#define ALL_SUB_MPAGES 0xff
+
+
+static const u8 def_rw_recovery_mpage[] = {
+	RW_RECOVERY_MPAGE,
+	RW_RECOVERY_MPAGE_LEN - 2,
+	(1 << 7) |	/* AWRE, sat-r06 say it shall be 0 */
+	    (1 << 6),	/* ARRE (auto read reallocation) */
+	0,		/* read retry count */
+	0, 0, 0, 0,
+	0,		/* write retry count */
+	0, 0, 0
+};
+
+static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = {
+	CACHE_MPAGE,
+	CACHE_MPAGE_LEN - 2,
+	0,		/* contains WCE, needs to be 0 for logic */
+	0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,		/* contains DRA, needs to be 0 for logic */
+	0, 0, 0, 0, 0, 0, 0
+};
+
+static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
+	CONTROL_MPAGE,
+	CONTROL_MPAGE_LEN - 2,
+	2,	/* DSENSE=0, GLTSD=1 */
+	0,	/* [QAM+QERR may be 1, see 05-359r1] */
+	0, 0, 0, 0, 0xff, 0xff,
+	0, 30	/* extended self test time, see 05-359r1 */
+};
+
+
+static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+				   void (*done)(struct scsi_cmnd *))
+{
+	ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	/* "Invalid field in cbd" */
+	done(cmd);
+}
 
 /**
  *	ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
@@ -78,6 +128,150 @@
 	return 0;
 }
 
+/**
+ *	ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
+ *	@dev: Device to whom we are issuing command
+ *	@arg: User provided data for issuing command
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+
+int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+	int rc = 0;
+	u8 scsi_cmd[MAX_COMMAND_SIZE];
+	u8 args[4], *argbuf = NULL;
+	int argsize = 0;
+	struct scsi_request *sreq;
+
+	if (NULL == (void *)arg)
+		return -EINVAL;
+
+	if (copy_from_user(args, arg, sizeof(args)))
+		return -EFAULT;
+
+	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+	if (!sreq)
+		return -EINTR;
+
+	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+
+	if (args[3]) {
+		argsize = SECTOR_SIZE * args[3];
+		argbuf = kmalloc(argsize, GFP_KERNEL);
+		if (argbuf == NULL) {
+			rc = -ENOMEM;
+			goto error;
+		}
+
+		scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
+		scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+		                            block count in sector count field */
+		sreq->sr_data_direction = DMA_FROM_DEVICE;
+	} else {
+		scsi_cmd[1]  = (3 << 1); /* Non-data */
+		/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+		sreq->sr_data_direction = DMA_NONE;
+	}
+
+	scsi_cmd[0] = ATA_16;
+
+	scsi_cmd[4] = args[2];
+	if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */
+		scsi_cmd[6]  = args[3];
+		scsi_cmd[8]  = args[1];
+		scsi_cmd[10] = 0x4f;
+		scsi_cmd[12] = 0xc2;
+	} else {
+		scsi_cmd[6]  = args[1];
+	}
+	scsi_cmd[14] = args[0];
+
+	/* Good values for timeout and retries?  Values below
+	   from scsi_ioctl_send_command() for default case... */
+	scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);
+
+	if (sreq->sr_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Need code to retrieve data from check condition? */
+
+	if ((argbuf)
+	 && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
+		rc = -EFAULT;
+error:
+	scsi_release_request(sreq);
+
+	if (argbuf)
+		kfree(argbuf);
+
+	return rc;
+}
+
+/**
+ *	ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl
+ *	@dev: Device to whom we are issuing command
+ *	@arg: User provided data for issuing command
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero on success, negative errno on error.
+ */
+int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
+{
+	int rc = 0;
+	u8 scsi_cmd[MAX_COMMAND_SIZE];
+	u8 args[7];
+	struct scsi_request *sreq;
+
+	if (NULL == (void *)arg)
+		return -EINVAL;
+
+	if (copy_from_user(args, arg, sizeof(args)))
+		return -EFAULT;
+
+	memset(scsi_cmd, 0, sizeof(scsi_cmd));
+	scsi_cmd[0]  = ATA_16;
+	scsi_cmd[1]  = (3 << 1); /* Non-data */
+	/* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+	scsi_cmd[4]  = args[1];
+	scsi_cmd[6]  = args[2];
+	scsi_cmd[8]  = args[3];
+	scsi_cmd[10] = args[4];
+	scsi_cmd[12] = args[5];
+	scsi_cmd[14] = args[0];
+
+	sreq = scsi_allocate_request(scsidev, GFP_KERNEL);
+	if (!sreq) {
+		rc = -EINTR;
+		goto error;
+	}
+
+	sreq->sr_data_direction = DMA_NONE;
+	/* Good values for timeout and retries?  Values below
+	   from scsi_ioctl_send_command() for default case... */
+	scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
+
+	if (sreq->sr_result) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Need code to retrieve data from check condition? */
+
+error:
+	scsi_release_request(sreq);
+	return rc;
+}
+
 int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
 {
 	struct ata_port *ap;
@@ -107,6 +301,16 @@
 			return -EINVAL;
 		return 0;
 
+	case HDIO_DRIVE_CMD:
+		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			return -EACCES;
+		return ata_cmd_ioctl(scsidev, arg);
+
+	case HDIO_DRIVE_TASK:
+		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+			return -EACCES;
+		return ata_task_ioctl(scsidev, arg);
+
 	default:
 		rc = -ENOTTY;
 		break;
@@ -165,24 +369,70 @@
 }
 
 /**
- *	ata_to_sense_error - convert ATA error to SCSI error
- *	@qc: Command that we are erroring out
- *	@drv_stat: value contained in ATA status register
+ *	ata_dump_status - user friendly display of error info
+ *	@id: id of the port in question
+ *	@tf: ptr to filled out taskfile
  *
- *	Converts an ATA error into a SCSI error. While we are at it
- *	we decode and dump the ATA error for the user so that they
- *	have some idea what really happened at the non make-believe
- *	layer.
+ *	Decode and dump the ATA error/status registers for the user so
+ *	that they have some idea what really happened at the non
+ *	make-believe layer.
+ *
+ *	LOCKING:
+ *	inherited from caller
+ */
+void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+{
+	u8 stat = tf->command, err = tf->feature;
+
+	printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
+	if (stat & ATA_BUSY) {
+		printk("Busy }\n");	/* Data is not valid in this case */
+	} else {
+		if (stat & 0x40)	printk("DriveReady ");
+		if (stat & 0x20)	printk("DeviceFault ");
+		if (stat & 0x10)	printk("SeekComplete ");
+		if (stat & 0x08)	printk("DataRequest ");
+		if (stat & 0x04)	printk("CorrectedError ");
+		if (stat & 0x02)	printk("Index ");
+		if (stat & 0x01)	printk("Error ");
+		printk("}\n");
+
+		if (err) {
+			printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
+			if (err & 0x04)		printk("DriveStatusError ");
+			if (err & 0x80) {
+				if (err & 0x04)	printk("BadCRC ");
+				else		printk("Sector ");
+			}
+			if (err & 0x40)		printk("UncorrectableError ");
+			if (err & 0x10)		printk("SectorIdNotFound ");
+			if (err & 0x02)		printk("TrackZeroNotFound ");
+			if (err & 0x01)		printk("AddrMarkNotFound ");
+			printk("}\n");
+		}
+	}
+}
+
+/**
+ *	ata_to_sense_error - convert ATA error to SCSI error
+ *	@drv_stat: value contained in ATA status register
+ *	@drv_err: value contained in ATA error register
+ *	@sk: the sense key we'll fill out
+ *	@asc: the additional sense code we'll fill out
+ *	@ascq: the additional sense code qualifier we'll fill out
+ *
+ *	Converts an ATA error into a SCSI error.  Fill out pointers to
+ *	SK, ASC, and ASCQ bytes for later use in fixed or descriptor
+ *	format sense blocks.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
-
-void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, 
+			u8 *ascq)
 {
-	struct scsi_cmnd *cmd = qc->scsicmd;
-	u8 err = 0;
-	unsigned char *sb = cmd->sense_buffer;
+	int i;
+
 	/* Based on the 3ware driver translation table */
 	static unsigned char sense_table[][4] = {
 		/* BBD|ECC|ID|MAR */
@@ -223,105 +473,192 @@
 		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
 		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
 	};
-	int i = 0;
-
-	cmd->result = SAM_STAT_CHECK_CONDITION;
 
 	/*
 	 *	Is this an error we can process/parse
 	 */
-
-	if(drv_stat & ATA_ERR)
-		/* Read the err bits */
-		err = ata_chk_err(qc->ap);
-
-	/* Display the ATA level error info */
-
-	printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
-	if(drv_stat & 0x80)
-	{
-		printk("Busy ");
-		err = 0;	/* Data is not valid in this case */
+	if (drv_stat & ATA_BUSY) {
+		drv_err = 0;	/* Ignore the err bits, they're invalid */
 	}
-	else {
-		if(drv_stat & 0x40)	printk("DriveReady ");
-		if(drv_stat & 0x20)	printk("DeviceFault ");
-		if(drv_stat & 0x10)	printk("SeekComplete ");
-		if(drv_stat & 0x08)	printk("DataRequest ");
-		if(drv_stat & 0x04)	printk("CorrectedError ");
-		if(drv_stat & 0x02)	printk("Index ");
-		if(drv_stat & 0x01)	printk("Error ");
-	}
-	printk("}\n");
 
-	if(err)
-	{
-		printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
-		if(err & 0x04)		printk("DriveStatusError ");
-		if(err & 0x80)
-		{
-			if(err & 0x04)
-				printk("BadCRC ");
-			else
-				printk("Sector ");
+	if (drv_err) {
+		/* Look for drv_err */
+		for (i = 0; sense_table[i][0] != 0xFF; i++) {
+			/* Look for best matches first */
+			if ((sense_table[i][0] & drv_err) == 
+			    sense_table[i][0]) {
+				*sk = sense_table[i][1];
+				*asc = sense_table[i][2];
+				*ascq = sense_table[i][3];
+				goto translate_done;
+			}
 		}
-		if(err & 0x40)		printk("UncorrectableError ");
-		if(err & 0x10)		printk("SectorIdNotFound ");
-		if(err & 0x02)		printk("TrackZeroNotFound ");
-		if(err & 0x01)		printk("AddrMarkNotFound ");
-		printk("}\n");
-
-		/* Should we dump sector info here too ?? */
+		/* No immediate match */
+		printk(KERN_WARNING "ata%u: no sense translation for "
+		       "error 0x%02x\n", id, drv_err);
 	}
 
-
-	/* Look for err */
-	while(sense_table[i][0] != 0xFF)
-	{
-		/* Look for best matches first */
-		if((sense_table[i][0] & err) == sense_table[i][0])
-		{
-			sb[0] = 0x70;
-			sb[2] = sense_table[i][1];
-			sb[7] = 0x0a;
-			sb[12] = sense_table[i][2];
-			sb[13] = sense_table[i][3];
-			return;
-		}
-		i++;
-	}
-	/* No immediate match */
-	if(err)
-		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
-
-	i = 0;
 	/* Fall back to interpreting status bits */
-	while(stat_table[i][0] != 0xFF)
-	{
-		if(stat_table[i][0] & drv_stat)
-		{
-			sb[0] = 0x70;
-			sb[2] = stat_table[i][1];
-			sb[7] = 0x0a;
-			sb[12] = stat_table[i][2];
-			sb[13] = stat_table[i][3];
-			return;
+	for (i = 0; stat_table[i][0] != 0xFF; i++) {
+		if (stat_table[i][0] & drv_stat) {
+			*sk = stat_table[i][1];
+			*asc = stat_table[i][2];
+			*ascq = stat_table[i][3];
+			goto translate_done;
 		}
-		i++;
 	}
-	/* No error ?? */
-	printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
-	/* additional-sense-code[-qualifier] */
+	/* No error?  Undecoded? */
+	printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", 
+	       id, drv_stat);
+
+	/* For our last chance pick, use medium read error because
+	 * it's much more common than an ATA drive telling you a write
+	 * has failed.
+	 */
+	*sk = MEDIUM_ERROR;
+	*asc = 0x11; /* "unrecovered read error" */
+	*ascq = 0x04; /*  "auto-reallocation failed" */
+
+ translate_done:
+	printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
+	       "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err,
+	       *sk, *asc, *ascq);
+	return;
+}
+
+/*
+ *	ata_gen_ata_desc_sense - Generate check condition sense block.
+ *	@qc: Command that completed.
+ *
+ *	This function is specific to the ATA descriptor format sense
+ *	block specified for the ATA pass through commands.  Regardless
+ *	of whether the command errored or not, return a sense
+ *	block. Copy all controller registers into the sense
+ *	block. Clear sense key, ASC & ASCQ if there is no error.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned char *sb = cmd->sense_buffer;
+	unsigned char *desc = sb + 8;
+
+	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+	/*
+	 * Read the controller registers.
+	 */
+	assert(NULL != qc->ap->ops->tf_read);
+	qc->ap->ops->tf_read(qc->ap, tf);
+
+	/*
+	 * Use ata_to_sense_error() to map status register bits
+	 * onto sense key, asc & ascq.
+	 */
+	if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+				   &sb[1], &sb[2], &sb[3]);
+		sb[1] &= 0x0f;
+	}
+
+	/*
+	 * Sense data is current and format is descriptor.
+	 */
+	sb[0] = 0x72;
+
+	desc[0] = 0x09;
+
+	/*
+	 * Set length of additional sense data.
+	 * Since we only populate descriptor 0, the total
+	 * length is the same (fixed) length as descriptor 0.
+	 */
+	desc[1] = sb[7] = 14;
+
+	/*
+	 * Copy registers into sense buffer.
+	 */
+	desc[2] = 0x00;
+	desc[3] = tf->feature;	/* == error reg */
+	desc[5] = tf->nsect;
+	desc[7] = tf->lbal;
+	desc[9] = tf->lbam;
+	desc[11] = tf->lbah;
+	desc[12] = tf->device;
+	desc[13] = tf->command; /* == status reg */
+
+	/*
+	 * Fill in Extend bit, and the high order bytes
+	 * if applicable.
+	 */
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		desc[2] |= 0x01;
+		desc[4] = tf->hob_nsect;
+		desc[6] = tf->hob_lbal;
+		desc[8] = tf->hob_lbam;
+		desc[10] = tf->hob_lbah;
+	}
+}
+
+/**
+ *	ata_gen_fixed_sense - generate a SCSI fixed sense block
+ *	@qc: Command that we are erroring out
+ *
+ *	Leverage ata_to_sense_error() to give us the codes.  Fit our
+ *	LBA in here if there's room.
+ *
+ *	LOCKING:
+ *	inherited from caller
+ */
+void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned char *sb = cmd->sense_buffer;
+
+	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+
+	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+	/*
+	 * Read the controller registers.
+	 */
+	assert(NULL != qc->ap->ops->tf_read);
+	qc->ap->ops->tf_read(qc->ap, tf);
+
+	/*
+	 * Use ata_to_sense_error() to map status register bits
+	 * onto sense key, asc & ascq.
+	 */
+	if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
+				   &sb[2], &sb[12], &sb[13]);
+		sb[2] &= 0x0f;
+	}
 
 	sb[0] = 0x70;
-	sb[2] = MEDIUM_ERROR;
-	sb[7] = 0x0A;
-	if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
-		sb[12] = 0x11; /* "unrecovered read error" */
-		sb[13] = 0x04;
-	} else {
-		sb[12] = 0x0C; /* "write error -             */
-		sb[13] = 0x02; /*  auto-reallocation failed" */
+	sb[7] = 0x0a;
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		/* TODO: find solution for LBA48 descriptors */
+	}
+
+	else if (tf->flags & ATA_TFLAG_LBA) {
+		/* A small (28b) LBA will fit in the 32b info field */
+		sb[0] |= 0x80;		/* set valid bit */
+		sb[3] = tf->device & 0x0f;
+		sb[4] = tf->lbah;
+		sb[5] = tf->lbam;
+		sb[6] = tf->lbal;
+	}
+
+	else {
+		/* TODO: C/H/S */
 	}
 }
 
@@ -420,7 +757,7 @@
  */
 
 static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
-					     u8 *scsicmd)
+					     const u8 *scsicmd)
 {
 	struct ata_taskfile *tf = &qc->tf;
 
@@ -430,15 +767,26 @@
 		;	/* ignore IMMED bit, violates sat-r05 */
 	}
 	if (scsicmd[4] & 0x2)
-		return 1;	/* LOEJ bit set not supported */
+		goto invalid_fld;       /* LOEJ bit set not supported */
 	if (((scsicmd[4] >> 4) & 0xf) != 0)
-		return 1;	/* power conditions not supported */
+		goto invalid_fld;       /* power conditions not supported */
 	if (scsicmd[4] & 0x1) {
 		tf->nsect = 1;	/* 1 sector, lba=0 */
-		tf->lbah = 0x0;
-		tf->lbam = 0x0;
-		tf->lbal = 0x0;
-		tf->device |= ATA_LBA;
+
+		if (qc->dev->flags & ATA_DFLAG_LBA) {
+			qc->tf.flags |= ATA_TFLAG_LBA;
+
+			tf->lbah = 0x0;
+			tf->lbam = 0x0;
+			tf->lbal = 0x0;
+			tf->device |= ATA_LBA;
+		} else {
+			/* CHS */
+			tf->lbal = 0x1; /* sect */
+			tf->lbam = 0x0; /* cyl low */
+			tf->lbah = 0x0; /* cyl high */
+		}
+
 		tf->command = ATA_CMD_VERIFY;	/* READ VERIFY */
 	} else {
 		tf->nsect = 0;	/* time period value (0 implies now) */
@@ -453,6 +801,11 @@
 	 */
 
 	return 0;
+
+invalid_fld:
+	ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	/* "Invalid field in cbd" */
+	return 1;
 }
 
 
@@ -471,14 +824,14 @@
  *	Zero on success, non-zero on error.
  */
 
-static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
 {
 	struct ata_taskfile *tf = &qc->tf;
 
 	tf->flags |= ATA_TFLAG_DEVICE;
 	tf->protocol = ATA_PROT_NODATA;
 
-	if ((tf->flags & ATA_TFLAG_LBA48) &&
+	if ((qc->dev->flags & ATA_DFLAG_LBA48) &&
 	    (ata_id_has_flush_ext(qc->dev->id)))
 		tf->command = ATA_CMD_FLUSH_EXT;
 	else
@@ -488,6 +841,99 @@
 }
 
 /**
+ *	scsi_6_lba_len - Get LBA and transfer length
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Calculate LBA and transfer length for 6-byte commands.
+ *
+ *	RETURNS:
+ *	@plba: the LBA
+ *	@plen: the transfer length
+ */
+
+static void scsi_6_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+	u64 lba = 0;
+	u32 len = 0;
+
+	VPRINTK("six-byte command\n");
+
+	lba |= ((u64)scsicmd[2]) << 8;
+	lba |= ((u64)scsicmd[3]);
+
+	len |= ((u32)scsicmd[4]);
+
+	*plba = lba;
+	*plen = len;
+}
+
+/**
+ *	scsi_10_lba_len - Get LBA and transfer length
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Calculate LBA and transfer length for 10-byte commands.
+ *
+ *	RETURNS:
+ *	@plba: the LBA
+ *	@plen: the transfer length
+ */
+
+static void scsi_10_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+	u64 lba = 0;
+	u32 len = 0;
+
+	VPRINTK("ten-byte command\n");
+
+	lba |= ((u64)scsicmd[2]) << 24;
+	lba |= ((u64)scsicmd[3]) << 16;
+	lba |= ((u64)scsicmd[4]) << 8;
+	lba |= ((u64)scsicmd[5]);
+
+	len |= ((u32)scsicmd[7]) << 8;
+	len |= ((u32)scsicmd[8]);
+
+	*plba = lba;
+	*plen = len;
+}
+
+/**
+ *	scsi_16_lba_len - Get LBA and transfer length
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Calculate LBA and transfer length for 16-byte commands.
+ *
+ *	RETURNS:
+ *	@plba: the LBA
+ *	@plen: the transfer length
+ */
+
+static void scsi_16_lba_len(const u8 *scsicmd, u64 *plba, u32 *plen)
+{
+	u64 lba = 0;
+	u32 len = 0;
+
+	VPRINTK("sixteen-byte command\n");
+
+	lba |= ((u64)scsicmd[2]) << 56;
+	lba |= ((u64)scsicmd[3]) << 48;
+	lba |= ((u64)scsicmd[4]) << 40;
+	lba |= ((u64)scsicmd[5]) << 32;
+	lba |= ((u64)scsicmd[6]) << 24;
+	lba |= ((u64)scsicmd[7]) << 16;
+	lba |= ((u64)scsicmd[8]) << 8;
+	lba |= ((u64)scsicmd[9]);
+
+	len |= ((u32)scsicmd[10]) << 24;
+	len |= ((u32)scsicmd[11]) << 16;
+	len |= ((u32)scsicmd[12]) << 8;
+	len |= ((u32)scsicmd[13]);
+
+	*plba = lba;
+	*plen = len;
+}
+
+/**
  *	ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
  *	@qc: Storage for translated ATA taskfile
  *	@scsicmd: SCSI command to translate
@@ -501,82 +947,110 @@
  *	Zero on success, non-zero on error.
  */
 
-static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
 {
 	struct ata_taskfile *tf = &qc->tf;
-	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+	struct ata_device *dev = qc->dev;
 	u64 dev_sectors = qc->dev->n_sectors;
-	u64 sect = 0;
-	u32 n_sect = 0;
+	u64 block;
+	u32 n_block;
 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	tf->protocol = ATA_PROT_NODATA;
-	tf->device |= ATA_LBA;
 
-	if (scsicmd[0] == VERIFY) {
-		sect |= ((u64)scsicmd[2]) << 24;
-		sect |= ((u64)scsicmd[3]) << 16;
-		sect |= ((u64)scsicmd[4]) << 8;
-		sect |= ((u64)scsicmd[5]);
-
-		n_sect |= ((u32)scsicmd[7]) << 8;
-		n_sect |= ((u32)scsicmd[8]);
-	}
-
-	else if (scsicmd[0] == VERIFY_16) {
-		sect |= ((u64)scsicmd[2]) << 56;
-		sect |= ((u64)scsicmd[3]) << 48;
-		sect |= ((u64)scsicmd[4]) << 40;
-		sect |= ((u64)scsicmd[5]) << 32;
-		sect |= ((u64)scsicmd[6]) << 24;
-		sect |= ((u64)scsicmd[7]) << 16;
-		sect |= ((u64)scsicmd[8]) << 8;
-		sect |= ((u64)scsicmd[9]);
-
-		n_sect |= ((u32)scsicmd[10]) << 24;
-		n_sect |= ((u32)scsicmd[11]) << 16;
-		n_sect |= ((u32)scsicmd[12]) << 8;
-		n_sect |= ((u32)scsicmd[13]);
-	}
-
+	if (scsicmd[0] == VERIFY)
+		scsi_10_lba_len(scsicmd, &block, &n_block);
+	else if (scsicmd[0] == VERIFY_16)
+		scsi_16_lba_len(scsicmd, &block, &n_block);
 	else
-		return 1;
+		goto invalid_fld;
 
-	if (!n_sect)
-		return 1;
-	if (sect >= dev_sectors)
-		return 1;
-	if ((sect + n_sect) > dev_sectors)
-		return 1;
-	if (lba48) {
-		if (n_sect > (64 * 1024))
-			return 1;
+	if (!n_block)
+		goto nothing_to_do;
+	if (block >= dev_sectors)
+		goto out_of_range;
+	if ((block + n_block) > dev_sectors)
+		goto out_of_range;
+
+	if (dev->flags & ATA_DFLAG_LBA) {
+		tf->flags |= ATA_TFLAG_LBA;
+
+		if (dev->flags & ATA_DFLAG_LBA48) {
+			if (n_block > (64 * 1024))
+				goto invalid_fld;
+
+			/* use LBA48 */
+			tf->flags |= ATA_TFLAG_LBA48;
+			tf->command = ATA_CMD_VERIFY_EXT;
+
+			tf->hob_nsect = (n_block >> 8) & 0xff;
+
+			tf->hob_lbah = (block >> 40) & 0xff;
+			tf->hob_lbam = (block >> 32) & 0xff;
+			tf->hob_lbal = (block >> 24) & 0xff;
+		} else {
+			if (n_block > 256)
+				goto invalid_fld;
+
+			/* use LBA28 */
+			tf->command = ATA_CMD_VERIFY;
+
+			tf->device |= (block >> 24) & 0xf;
+		}
+
+		tf->nsect = n_block & 0xff;
+
+		tf->lbah = (block >> 16) & 0xff;
+		tf->lbam = (block >> 8) & 0xff;
+		tf->lbal = block & 0xff;
+
+		tf->device |= ATA_LBA;
 	} else {
-		if (n_sect > 256)
-			return 1;
-	}
+		/* CHS */
+		u32 sect, head, cyl, track;
 
-	if (lba48) {
-		tf->command = ATA_CMD_VERIFY_EXT;
+		if (n_block > 256)
+			goto invalid_fld;
 
-		tf->hob_nsect = (n_sect >> 8) & 0xff;
+		/* Convert LBA to CHS */
+		track = (u32)block / dev->sectors;
+		cyl   = track / dev->heads;
+		head  = track % dev->heads;
+		sect  = (u32)block % dev->sectors + 1;
 
-		tf->hob_lbah = (sect >> 40) & 0xff;
-		tf->hob_lbam = (sect >> 32) & 0xff;
-		tf->hob_lbal = (sect >> 24) & 0xff;
-	} else {
+		DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+			(u32)block, track, cyl, head, sect);
+		
+		/* Check whether the converted CHS can fit. 
+		   Cylinder: 0-65535 
+		   Head: 0-15
+		   Sector: 1-255*/
+		if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
+			goto out_of_range;
+		
 		tf->command = ATA_CMD_VERIFY;
-
-		tf->device |= (sect >> 24) & 0xf;
+		tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+		tf->lbal = sect;
+		tf->lbam = cyl;
+		tf->lbah = cyl >> 8;
+		tf->device |= head;
 	}
 
-	tf->nsect = n_sect & 0xff;
-
-	tf->lbah = (sect >> 16) & 0xff;
-	tf->lbam = (sect >> 8) & 0xff;
-	tf->lbal = sect & 0xff;
-
 	return 0;
+
+invalid_fld:
+	ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	/* "Invalid field in cbd" */
+	return 1;
+
+out_of_range:
+	ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+	/* "Logical Block Address out of range" */
+	return 1;
+
+nothing_to_do:
+	qc->scsicmd->result = SAM_STAT_GOOD;
+	return 1;
 }
 
 /**
@@ -599,117 +1073,175 @@
  *	Zero on success, non-zero on error.
  */
 
-static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
 {
 	struct ata_taskfile *tf = &qc->tf;
-	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+	struct ata_device *dev = qc->dev;
+	u64 block;
+	u32 n_block;
 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf->protocol = qc->dev->xfer_protocol;
-	tf->device |= ATA_LBA;
 
-	if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
-	    scsicmd[0] == READ_16) {
-		tf->command = qc->dev->read_cmd;
-	} else {
-		tf->command = qc->dev->write_cmd;
+	if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
+	    scsicmd[0] == WRITE_16)
 		tf->flags |= ATA_TFLAG_WRITE;
+
+	/* Calculate the SCSI LBA and transfer length. */
+	switch (scsicmd[0]) {
+	case READ_10:
+	case WRITE_10:
+		scsi_10_lba_len(scsicmd, &block, &n_block);
+		break;
+	case READ_6:
+	case WRITE_6:
+		scsi_6_lba_len(scsicmd, &block, &n_block);
+
+		/* for 6-byte r/w commands, transfer length 0
+		 * means 256 blocks of data, not 0 block.
+		 */
+		if (!n_block)
+			n_block = 256;
+		break;
+	case READ_16:
+	case WRITE_16:
+		scsi_16_lba_len(scsicmd, &block, &n_block);
+		break;
+	default:
+		DPRINTK("no-byte command\n");
+		goto invalid_fld;
 	}
 
-	if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
-		if (lba48) {
-			tf->hob_nsect = scsicmd[7];
-			tf->hob_lbal = scsicmd[2];
+	/* Check and compose ATA command */
+	if (!n_block)
+		/* For 10-byte and 16-byte SCSI R/W commands, transfer
+		 * length 0 means transfer 0 block of data.
+		 * However, for ATA R/W commands, sector count 0 means
+		 * 256 or 65536 sectors, not 0 sectors as in SCSI.
+		 */
+		goto nothing_to_do;
 
-			qc->nsect = ((unsigned int)scsicmd[7] << 8) |
-					scsicmd[8];
-		} else {
-			/* if we don't support LBA48 addressing, the request
-			 * -may- be too large. */
-			if ((scsicmd[2] & 0xf0) || scsicmd[7])
-				return 1;
+	if (dev->flags & ATA_DFLAG_LBA) {
+		tf->flags |= ATA_TFLAG_LBA;
 
-			/* stores LBA27:24 in lower 4 bits of device reg */
-			tf->device |= scsicmd[2];
+		if (dev->flags & ATA_DFLAG_LBA48) {
+			/* The request -may- be too large for LBA48. */
+			if ((block >> 48) || (n_block > 65536))
+				goto out_of_range;
 
-			qc->nsect = scsicmd[8];
+			/* use LBA48 */
+			tf->flags |= ATA_TFLAG_LBA48;
+
+			tf->hob_nsect = (n_block >> 8) & 0xff;
+
+			tf->hob_lbah = (block >> 40) & 0xff;
+			tf->hob_lbam = (block >> 32) & 0xff;
+			tf->hob_lbal = (block >> 24) & 0xff;
+		} else { 
+			/* use LBA28 */
+
+			/* The request -may- be too large for LBA28. */
+			if ((block >> 28) || (n_block > 256))
+				goto out_of_range;
+
+			tf->device |= (block >> 24) & 0xf;
 		}
 
-		tf->nsect = scsicmd[8];
-		tf->lbal = scsicmd[5];
-		tf->lbam = scsicmd[4];
-		tf->lbah = scsicmd[3];
+		ata_rwcmd_protocol(qc);
 
-		VPRINTK("ten-byte command\n");
-		if (qc->nsect == 0) /* we don't support length==0 cmds */
-			return 1;
-		return 0;
+		qc->nsect = n_block;
+		tf->nsect = n_block & 0xff;
+
+		tf->lbah = (block >> 16) & 0xff;
+		tf->lbam = (block >> 8) & 0xff;
+		tf->lbal = block & 0xff;
+
+		tf->device |= ATA_LBA;
+	} else { 
+		/* CHS */
+		u32 sect, head, cyl, track;
+
+		/* The request -may- be too large for CHS addressing. */
+		if ((block >> 28) || (n_block > 256))
+			goto out_of_range;
+
+		ata_rwcmd_protocol(qc);
+
+		/* Convert LBA to CHS */
+		track = (u32)block / dev->sectors;
+		cyl   = track / dev->heads;
+		head  = track % dev->heads;
+		sect  = (u32)block % dev->sectors + 1;
+
+		DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+			(u32)block, track, cyl, head, sect);
+
+		/* Check whether the converted CHS can fit. 
+		   Cylinder: 0-65535 
+		   Head: 0-15
+		   Sector: 1-255*/
+		if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+			goto out_of_range;
+
+		qc->nsect = n_block;
+		tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+		tf->lbal = sect;
+		tf->lbam = cyl;
+		tf->lbah = cyl >> 8;
+		tf->device |= head;
 	}
 
-	if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
-		qc->nsect = tf->nsect = scsicmd[4];
-		if (!qc->nsect) {
-			qc->nsect = 256;
-			if (lba48)
-				tf->hob_nsect = 1;
-		}
+	return 0;
 
-		tf->lbal = scsicmd[3];
-		tf->lbam = scsicmd[2];
-		tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
+invalid_fld:
+	ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	/* "Invalid field in cbd" */
+	return 1;
 
-		VPRINTK("six-byte command\n");
-		return 0;
-	}
+out_of_range:
+	ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0);
+	/* "Logical Block Address out of range" */
+	return 1;
 
-	if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
-		/* rule out impossible LBAs and sector counts */
-		if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
-			return 1;
-
-		if (lba48) {
-			tf->hob_nsect = scsicmd[12];
-			tf->hob_lbal = scsicmd[6];
-			tf->hob_lbam = scsicmd[5];
-			tf->hob_lbah = scsicmd[4];
-
-			qc->nsect = ((unsigned int)scsicmd[12] << 8) |
-					scsicmd[13];
-		} else {
-			/* once again, filter out impossible non-zero values */
-			if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
-			    (scsicmd[6] & 0xf0))
-				return 1;
-
-			/* stores LBA27:24 in lower 4 bits of device reg */
-			tf->device |= scsicmd[6];
-
-			qc->nsect = scsicmd[13];
-		}
-
-		tf->nsect = scsicmd[13];
-		tf->lbal = scsicmd[9];
-		tf->lbam = scsicmd[8];
-		tf->lbah = scsicmd[7];
-
-		VPRINTK("sixteen-byte command\n");
-		if (qc->nsect == 0) /* we don't support length==0 cmds */
-			return 1;
-		return 0;
-	}
-
-	DPRINTK("no-byte command\n");
+nothing_to_do:
+	qc->scsicmd->result = SAM_STAT_GOOD;
 	return 1;
 }
 
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
+				unsigned int err_mask)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	u8 *cdb = cmd->cmnd;
+ 	int need_sense = (err_mask != 0);
 
-	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
-		ata_to_sense_error(qc, drv_stat);
-	else
-		cmd->result = SAM_STAT_GOOD;
+	/* For ATA pass thru (SAT) commands, generate a sense block if
+	 * user mandated it or if there's an error.  Note that if we
+	 * generate because the user forced us to, a check condition
+	 * is generated and the ATA register values are returned
+	 * whether the command completed successfully or not. If there
+	 * was no error, SK, ASC and ASCQ will all be zero.
+	 */
+	if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
+ 	    ((cdb[2] & 0x20) || need_sense)) {
+ 		ata_gen_ata_desc_sense(qc);
+	} else {
+		if (!need_sense) {
+			cmd->result = SAM_STAT_GOOD;
+		} else {
+			/* TODO: decide which descriptor format to use
+			 * for 48b LBA devices and call that here
+			 * instead of the fixed desc, which is only
+			 * good for smaller LBA (and maybe CHS?)
+			 * devices.
+			 */
+			ata_gen_fixed_sense(qc);
+		}
+	}
+
+	if (need_sense) {
+		/* The ata_gen_..._sense routines fill in tf */
+		ata_dump_status(qc->ap->id, &qc->tf);
+	}
 
 	qc->scsidone(cmd);
 
@@ -731,6 +1263,12 @@
  *	This function sets up an ata_queued_cmd structure for the
  *	SCSI command, and sends that ata_queued_cmd to the hardware.
  *
+ *	The xlat_func argument (actor) returns 0 if ready to execute
+ *	ATA command, else 1 to finish translation. If 1 is returned
+ *	then cmd->result (and possibly cmd->sense_buffer) are assumed
+ *	to be set reflecting an error condition or clean (early)
+ *	termination.
+ *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
@@ -747,7 +1285,7 @@
 
 	qc = ata_scsi_qc_new(ap, dev, cmd, done);
 	if (!qc)
-		return;
+		goto err_mem;
 
 	/* data is present; dma-map it */
 	if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
@@ -755,7 +1293,7 @@
 		if (unlikely(cmd->request_bufflen < 1)) {
 			printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
 			       ap->id, dev->devno);
-			goto err_out;
+			goto err_did;
 		}
 
 		if (cmd->use_sg)
@@ -770,19 +1308,28 @@
 	qc->complete_fn = ata_scsi_qc_complete;
 
 	if (xlat_func(qc, scsicmd))
-		goto err_out;
+		goto early_finish;
 
 	/* select device, send command to hardware */
 	if (ata_qc_issue(qc))
-		goto err_out;
+		goto err_did;
 
 	VPRINTK("EXIT\n");
 	return;
 
-err_out:
+early_finish:
+        ata_qc_free(qc);
+	done(cmd);
+	DPRINTK("EXIT - early finish (good or error)\n");
+	return;
+
+err_did:
 	ata_qc_free(qc);
-	ata_bad_cdb(cmd, done);
-	DPRINTK("EXIT - badcmd\n");
+err_mem:
+	cmd->result = (DID_ERROR << 16);
+	done(cmd);
+	DPRINTK("EXIT - internal\n");
+	return;
 }
 
 /**
@@ -849,7 +1396,8 @@
  *	Mapping the response buffer, calling the command's handler,
  *	and handling the handler's return value.  This return value
  *	indicates whether the handler wishes the SCSI command to be
- *	completed successfully, or not.
+ *	completed successfully (0), or not (in which case cmd->result
+ *	and sense buffer are assumed to be set).
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
@@ -868,12 +1416,9 @@
 	rc = actor(args, rbuf, buflen);
 	ata_scsi_rbuf_put(cmd, rbuf);
 
-	if (rc)
-		ata_bad_cdb(cmd, args->done);
-	else {
+	if (rc == 0)
 		cmd->result = SAM_STAT_GOOD;
-		args->done(cmd);
-	}
+	args->done(cmd);
 }
 
 /**
@@ -1087,13 +1632,9 @@
 static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
 				       const u8 *last)
 {
-	u8 page[] = {
-		0x8,				/* page code */
-		0x12,				/* page length */
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 10 zeroes */
-		0, 0, 0, 0, 0, 0, 0, 0		/* 8 zeroes */
-	};
+	u8 page[CACHE_MPAGE_LEN];
 
+	memcpy(page, def_cache_mpage, sizeof(page));
 	if (ata_id_wcache_enabled(id))
 		page[2] |= (1 << 2);	/* write cache enable */
 	if (!ata_id_rahead_enabled(id))
@@ -1117,15 +1658,9 @@
 
 static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
 {
-	const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30};
-
-	/* byte 2: set the descriptor format sense data bit (bit 2)
-	 * since we need to support returning this format for SAT
-	 * commands and any SCSI commands against a 48b LBA device.
-	 */
-
-	ata_msense_push(ptr_io, last, page, sizeof(page));
-	return sizeof(page);
+	ata_msense_push(ptr_io, last, def_control_mpage,
+			sizeof(def_control_mpage));
+	return sizeof(def_control_mpage);
 }
 
 /**
@@ -1142,15 +1677,10 @@
 
 static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
 {
-	const u8 page[] = {
-		0x1,			  /* page code */
-		0xa,			  /* page length */
-		(1 << 7) | (1 << 6),	  /* note auto r/w reallocation */
-		0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
-	};
 
-	ata_msense_push(ptr_io, last, page, sizeof(page));
-	return sizeof(page);
+	ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
+			sizeof(def_rw_recovery_mpage));
+	return sizeof(def_rw_recovery_mpage);
 }
 
 /**
@@ -1159,7 +1689,9 @@
  *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *	@buflen: Response buffer length.
  *
- *	Simulate MODE SENSE commands.
+ *	Simulate MODE SENSE commands. Assume this is invoked for direct
+ *	access devices (e.g. disks) only. There should be no block
+ *	descriptor for other device types.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
@@ -1169,61 +1701,115 @@
 				  unsigned int buflen)
 {
 	u8 *scsicmd = args->cmd->cmnd, *p, *last;
-	unsigned int page_control, six_byte, output_len;
+	const u8 sat_blk_desc[] = {
+		0, 0, 0, 0,	/* number of blocks: sat unspecified */
+		0,
+		0, 0x2, 0x0	/* block length: 512 bytes */
+	};
+	u8 pg, spg;
+	unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
 
 	VPRINTK("ENTER\n");
 
 	six_byte = (scsicmd[0] == MODE_SENSE);
-
-	/* we only support saved and current values (which we treat
-	 * in the same manner)
+	ebd = !(scsicmd[1] & 0x8);      /* dbd bit inverted == edb */
+	/*
+	 * LLBA bit in msense(10) ignored (compliant)
 	 */
-	page_control = scsicmd[2] >> 6;
-	if ((page_control != 0) && (page_control != 3))
-		return 1;
 
-	if (six_byte)
-		output_len = 4;
-	else
-		output_len = 8;
+	page_control = scsicmd[2] >> 6;
+	switch (page_control) {
+	case 0: /* current */
+		break;  /* supported */
+	case 3: /* saved */
+		goto saving_not_supp;
+	case 1: /* changeable */
+	case 2: /* defaults */
+	default:
+		goto invalid_fld;
+	}
+
+	if (six_byte) {
+		output_len = 4 + (ebd ? 8 : 0);
+		alloc_len = scsicmd[4];
+	} else {
+		output_len = 8 + (ebd ? 8 : 0);
+		alloc_len = (scsicmd[7] << 8) + scsicmd[8];
+	}
+	minlen = (alloc_len < buflen) ? alloc_len : buflen;
 
 	p = rbuf + output_len;
-	last = rbuf + buflen - 1;
+	last = rbuf + minlen - 1;
 
-	switch(scsicmd[2] & 0x3f) {
-	case 0x01:		/* r/w error recovery */
+	pg = scsicmd[2] & 0x3f;
+	spg = scsicmd[3];
+	/*
+	 * No mode subpages supported (yet) but asking for _all_
+	 * subpages may be valid
+	 */
+	if (spg && (spg != ALL_SUB_MPAGES))
+		goto invalid_fld;
+
+	switch(pg) {
+	case RW_RECOVERY_MPAGE:
 		output_len += ata_msense_rw_recovery(&p, last);
 		break;
 
-	case 0x08:		/* caching */
+	case CACHE_MPAGE:
 		output_len += ata_msense_caching(args->id, &p, last);
 		break;
 
-	case 0x0a: {		/* control mode */
+	case CONTROL_MPAGE: {
 		output_len += ata_msense_ctl_mode(&p, last);
 		break;
 		}
 
-	case 0x3f:		/* all pages */
+	case ALL_MPAGES:
 		output_len += ata_msense_rw_recovery(&p, last);
 		output_len += ata_msense_caching(args->id, &p, last);
 		output_len += ata_msense_ctl_mode(&p, last);
 		break;
 
 	default:		/* invalid page code */
-		return 1;
+		goto invalid_fld;
 	}
 
+	if (minlen < 1)
+		return 0;
 	if (six_byte) {
 		output_len--;
 		rbuf[0] = output_len;
+		if (ebd) {
+			if (minlen > 3)
+				rbuf[3] = sizeof(sat_blk_desc);
+			if (minlen > 11)
+				memcpy(rbuf + 4, sat_blk_desc,
+				       sizeof(sat_blk_desc));
+		}
 	} else {
 		output_len -= 2;
 		rbuf[0] = output_len >> 8;
-		rbuf[1] = output_len;
+		if (minlen > 1)
+			rbuf[1] = output_len;
+		if (ebd) {
+			if (minlen > 7)
+				rbuf[7] = sizeof(sat_blk_desc);
+			if (minlen > 15)
+				memcpy(rbuf + 8, sat_blk_desc,
+				       sizeof(sat_blk_desc));
+		}
 	}
-
 	return 0;
+
+invalid_fld:
+	ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	/* "Invalid field in cbd" */
+	return 1;
+
+saving_not_supp:
+	ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+	 /* "Saving parameters not supported" */
+	return 1;
 }
 
 /**
@@ -1246,10 +1832,20 @@
 
 	VPRINTK("ENTER\n");
 
-	if (ata_id_has_lba48(args->id))
-		n_sectors = ata_id_u64(args->id, 100);
-	else
-		n_sectors = ata_id_u32(args->id, 60);
+	if (ata_id_has_lba(args->id)) {
+		if (ata_id_has_lba48(args->id))
+			n_sectors = ata_id_u64(args->id, 100);
+		else
+			n_sectors = ata_id_u32(args->id, 60);
+	} else {
+		/* CHS default translation */
+		n_sectors = args->id[1] * args->id[3] * args->id[6];
+
+		if (ata_id_current_chs_valid(args->id))
+			/* CHS current translation */
+			n_sectors = ata_id_u32(args->id, 57);
+	}
+
 	n_sectors--;		/* ATA TotalUserSectors - 1 */
 
 	if (args->cmd->cmnd[0] == READ_CAPACITY) {
@@ -1313,6 +1909,34 @@
 }
 
 /**
+ *	ata_scsi_set_sense - Set SCSI sense data and status
+ *	@cmd: SCSI request to be handled
+ *	@sk: SCSI-defined sense key
+ *	@asc: SCSI-defined additional sense code
+ *	@ascq: SCSI-defined additional sense code qualifier
+ *
+ *	Helper function that builds a valid fixed format, current
+ *	response code and the given sense key (sk), additional sense
+ *	code (asc) and additional sense code qualifier (ascq) with
+ *	a SCSI command status of %SAM_STAT_CHECK_CONDITION and
+ *	DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
+ *
+ *	LOCKING:
+ *	Not required
+ */
+
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+	cmd->sense_buffer[0] = 0x70;	/* fixed format, current */
+	cmd->sense_buffer[2] = sk;
+	cmd->sense_buffer[7] = 18 - 8;	/* additional sense length */
+	cmd->sense_buffer[12] = asc;
+	cmd->sense_buffer[13] = ascq;
+}
+
+/**
  *	ata_scsi_badcmd - End a SCSI request with an error
  *	@cmd: SCSI request to be handled
  *	@done: SCSI command completion function
@@ -1330,30 +1954,89 @@
 void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
 {
 	DPRINTK("ENTER\n");
-	cmd->result = SAM_STAT_CHECK_CONDITION;
-
-	cmd->sense_buffer[0] = 0x70;
-	cmd->sense_buffer[2] = ILLEGAL_REQUEST;
-	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
-	cmd->sense_buffer[12] = asc;
-	cmd->sense_buffer[13] = ascq;
+	ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
 
 	done(cmd);
 }
 
-static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+			 struct scsi_cmnd *cmd)
+{
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int rc;
+
+	DPRINTK("ATAPI request sense\n");
+
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
+
+	/* FIXME: is this needed? */
+	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+
+	ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
+	qc->dma_dir = DMA_FROM_DEVICE;
+
+	memset(&qc->cdb, 0, ap->cdb_len);
+	qc->cdb[0] = REQUEST_SENSE;
+	qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	qc->tf.command = ATA_CMD_PACKET;
+
+	qc->tf.protocol = ATA_PROT_ATAPI;
+	qc->tf.lbam = (8 * 1024) & 0xff;
+	qc->tf.lbah = (8 * 1024) >> 8;
+	qc->nbytes = SCSI_SENSE_BUFFERSIZE;
+
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (rc)
+		ata_port_disable(ap);
+	else
+		wait_for_completion(&wait);
+
+	DPRINTK("EXIT\n");
+}
+
+static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 
-	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+	VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
+
+	if (unlikely(err_mask & AC_ERR_DEV)) {
 		DPRINTK("request check condition\n");
 
+		/* FIXME: command completion with check condition
+		 * but no sense causes the error handler to run,
+		 * which then issues REQUEST SENSE, fills in the sense 
+		 * buffer, and completes the command (for the second
+		 * time).  We need to issue REQUEST SENSE some other
+		 * way, to avoid completing the command twice.
+		 */
 		cmd->result = SAM_STAT_CHECK_CONDITION;
 
 		qc->scsidone(cmd);
 
 		return 1;
-	} else {
+	}
+
+	else if (unlikely(err_mask))
+		/* FIXME: not quite right; we don't want the
+		 * translation of taskfile registers into
+		 * a sense descriptors, since that's only
+		 * correct for ATA, not ATAPI
+		 */
+		ata_gen_ata_desc_sense(qc);
+
+	else {
 		u8 *scsicmd = cmd->cmnd;
 
 		if (scsicmd[0] == INQUIRY) {
@@ -1361,15 +2044,30 @@
 			unsigned int buflen;
 
 			buflen = ata_scsi_rbuf_get(cmd, &buf);
-			buf[2] = 0x5;
-			buf[3] = (buf[3] & 0xf0) | 2;
+
+	/* ATAPI devices typically report zero for their SCSI version,
+	 * and sometimes deviate from the spec WRT response data
+	 * format.  If SCSI version is reported as zero like normal,
+	 * then we make the following fixups:  1) Fake MMC-5 version,
+	 * to indicate to the Linux scsi midlayer this is a modern
+	 * device.  2) Ensure response data format / ATAPI information
+	 * are always correct.
+	 */
+	/* FIXME: do we ever override EVPD pages and the like, with
+	 * this code?
+	 */
+			if (buf[2] == 0) {
+				buf[2] = 0x5;
+				buf[3] = 0x32;
+			}
+
 			ata_scsi_rbuf_put(cmd, buf);
 		}
+
 		cmd->result = SAM_STAT_GOOD;
 	}
 
 	qc->scsidone(cmd);
-
 	return 0;
 }
 /**
@@ -1384,7 +2082,7 @@
  *	Zero on success, non-zero on failure.
  */
 
-static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_device *dev = qc->dev;
@@ -1453,7 +2151,7 @@
  */
 
 static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
+ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
 {
 	struct ata_device *dev;
 
@@ -1478,6 +2176,143 @@
 	return dev;
 }
 
+/*
+ *	ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
+ *	@byte1: Byte 1 from pass-thru CDB.
+ *
+ *	RETURNS:
+ *	ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
+ */
+static u8
+ata_scsi_map_proto(u8 byte1)
+{
+	switch((byte1 & 0x1e) >> 1) {
+		case 3:		/* Non-data */
+			return ATA_PROT_NODATA;
+
+		case 6:		/* DMA */
+			return ATA_PROT_DMA;
+
+		case 4:		/* PIO Data-in */
+		case 5:		/* PIO Data-out */
+			if (byte1 & 0xe0) {
+				return ATA_PROT_PIO_MULT;
+			}
+			return ATA_PROT_PIO;
+
+		case 10:	/* Device Reset */
+		case 0:		/* Hard Reset */
+		case 1:		/* SRST */
+		case 2:		/* Bus Idle */
+		case 7:		/* Packet */
+		case 8:		/* DMA Queued */
+		case 9:		/* Device Diagnostic */
+		case 11:	/* UDMA Data-in */
+		case 12:	/* UDMA Data-Out */
+		case 13:	/* FPDMA */
+		default:	/* Reserved */
+			break;
+	}
+
+	return ATA_PROT_UNKNOWN;
+}
+
+/**
+ *	ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
+ *	@qc: command structure to be initialized
+ *	@cmd: SCSI command to convert
+ *
+ *	Handles either 12 or 16-byte versions of the CDB.
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on failure.
+ */
+static unsigned int
+ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &(qc->tf);
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
+		return 1;
+
+	/*
+	 * 12 and 16 byte CDBs use different offsets to
+	 * provide the various register values.
+	 */
+	if (scsicmd[0] == ATA_16) {
+		/*
+		 * 16-byte CDB - may contain extended commands.
+		 *
+		 * If that is the case, copy the upper byte register values.
+		 */
+		if (scsicmd[1] & 0x01) {
+			tf->hob_feature = scsicmd[3];
+			tf->hob_nsect = scsicmd[5];
+			tf->hob_lbal = scsicmd[7];
+			tf->hob_lbam = scsicmd[9];
+			tf->hob_lbah = scsicmd[11];
+			tf->flags |= ATA_TFLAG_LBA48;
+		} else
+			tf->flags &= ~ATA_TFLAG_LBA48;
+
+		/*
+		 * Always copy low byte, device and command registers.
+		 */
+		tf->feature = scsicmd[4];
+		tf->nsect = scsicmd[6];
+		tf->lbal = scsicmd[8];
+		tf->lbam = scsicmd[10];
+		tf->lbah = scsicmd[12];
+		tf->device = scsicmd[13];
+		tf->command = scsicmd[14];
+	} else {
+		/*
+		 * 12-byte CDB - incapable of extended commands.
+		 */
+		tf->flags &= ~ATA_TFLAG_LBA48;
+
+		tf->feature = scsicmd[3];
+		tf->nsect = scsicmd[4];
+		tf->lbal = scsicmd[5];
+		tf->lbam = scsicmd[6];
+		tf->lbah = scsicmd[7];
+		tf->device = scsicmd[8];
+		tf->command = scsicmd[9];
+	}
+
+	/*
+	 * Filter SET_FEATURES - XFER MODE command -- otherwise,
+	 * SET_FEATURES - XFER MODE must be preceded/succeeded
+	 * by an update to hardware-specific registers for each
+	 * controller (i.e. the reason for ->set_piomode(),
+	 * ->set_dmamode(), and ->post_set_mode() hooks).
+	 */
+	if ((tf->command == ATA_CMD_SET_FEATURES)
+	 && (tf->feature == SETFEATURES_XFER))
+		return 1;
+
+	/*
+	 * Set flags so that all registers will be written,
+	 * and pass on write indication (used for PIO/DMA
+	 * setup.)
+	 */
+	tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE);
+
+	if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		tf->flags |= ATA_TFLAG_WRITE;
+
+	/*
+	 * Set transfer length.
+	 *
+	 * TODO: find out if we need to do more here to
+	 *       cover scatter/gather case.
+	 */
+	qc->nsect = cmd->bufflen / ATA_SECT_SIZE;
+
+	return 0;
+}
+
 /**
  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
  *	@dev: ATA device
@@ -1510,6 +2345,11 @@
 	case VERIFY:
 	case VERIFY_16:
 		return ata_scsi_verify_xlat;
+
+	case ATA_12:
+	case ATA_16:
+		return ata_scsi_pass_thru;
+
 	case START_STOP:
 		return ata_scsi_start_stop_xlat;
 	}
@@ -1610,7 +2450,7 @@
 		      void (*done)(struct scsi_cmnd *))
 {
 	struct ata_scsi_args args;
-	u8 *scsicmd = cmd->cmnd;
+	const u8 *scsicmd = cmd->cmnd;
 
 	args.id = id;
 	args.cmd = cmd;
@@ -1630,7 +2470,7 @@
 
 		case INQUIRY:
 			if (scsicmd[1] & 2)	           /* is CmdDt set?  */
-				ata_bad_cdb(cmd, done);
+				ata_scsi_invalid_field(cmd, done);
 			else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */
 				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
 			else if (scsicmd[2] == 0x00)
@@ -1640,7 +2480,7 @@
 			else if (scsicmd[2] == 0x83)
 				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
 			else
-				ata_bad_cdb(cmd, done);
+				ata_scsi_invalid_field(cmd, done);
 			break;
 
 		case MODE_SENSE:
@@ -1650,7 +2490,7 @@
 
 		case MODE_SELECT:	/* unconditionally return */
 		case MODE_SELECT_10:	/* bad-field-in-cdb */
-			ata_bad_cdb(cmd, done);
+			ata_scsi_invalid_field(cmd, done);
 			break;
 
 		case READ_CAPACITY:
@@ -1661,20 +2501,38 @@
 			if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
 				ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
 			else
-				ata_bad_cdb(cmd, done);
+				ata_scsi_invalid_field(cmd, done);
 			break;
 
 		case REPORT_LUNS:
 			ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
 			break;
 
-		/* mandantory commands we haven't implemented yet */
+		/* mandatory commands we haven't implemented yet */
 		case REQUEST_SENSE:
 
 		/* all other commands */
 		default:
-			ata_bad_scsiop(cmd, done);
+			ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+			/* "Invalid command operation code" */
+			done(cmd);
 			break;
 	}
 }
 
+void ata_scsi_scan_host(struct ata_port *ap)
+{
+	struct ata_device *dev;
+	unsigned int i;
+
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		dev = &ap->device[i];
+
+		if (ata_dev_present(dev))
+			scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0);
+	}
+}
+
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index d608b3a..10ecd9e 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -39,19 +39,25 @@
 
 /* libata-core.c */
 extern int atapi_enabled;
+extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
+extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
-extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf);
 extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
+extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 
 
 /* libata-scsi.c */
-extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
+extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+			 struct scsi_cmnd *cmd);
+extern void ata_scsi_scan_host(struct ata_port *ap);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
@@ -76,18 +82,10 @@
 extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
 			    void (*done)(struct scsi_cmnd *),
 			    u8 asc, u8 ascq);
+extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
+			       u8 sk, u8 asc, u8 ascq);
 extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
 
-static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-	ata_scsi_badcmd(cmd, done, 0x20, 0x00);
-}
-
-static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-	ata_scsi_badcmd(cmd, done, 0x24, 0x00);
-}
-
 #endif /* __LIBATA_H__ */
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 0aba13c..352df47 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -39,7 +39,7 @@
 #define LPFC_MEM_POOL_SIZE      64      /* max elem in non-DMA safety pool */
 
 static void *
-lpfc_pool_kmalloc(unsigned int gfp_flags, void *data)
+lpfc_pool_kmalloc(gfp_t gfp_flags, void *data)
 {
 	return kmalloc((unsigned long)data, gfp_flags);
 }
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index d47be8e..c9e743b 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -76,7 +76,7 @@
 
 static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
 static void megaraid_detach_one(struct pci_dev *);
-static void megaraid_mbox_shutdown(struct device *);
+static void megaraid_mbox_shutdown(struct pci_dev *);
 
 static int megaraid_io_attach(adapter_t *);
 static void megaraid_io_detach(adapter_t *);
@@ -369,9 +369,7 @@
 	.id_table	= pci_id_table_g,
 	.probe		= megaraid_probe_one,
 	.remove		= __devexit_p(megaraid_detach_one),
-	.driver		= {
-		.shutdown	= megaraid_mbox_shutdown,
-	}
+	.shutdown	= megaraid_mbox_shutdown,
 };
 
 
@@ -673,9 +671,9 @@
  * Shutdown notification, perform flush cache
  */
 static void
-megaraid_mbox_shutdown(struct device *device)
+megaraid_mbox_shutdown(struct pci_dev *pdev)
 {
-	adapter_t		*adapter = pci_get_drvdata(to_pci_dev(device));
+	adapter_t		*adapter = pci_get_drvdata(pdev);
 	static int		counter;
 
 	if (!adapter) {
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index b235556..bdccf73 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -730,7 +730,7 @@
 		 * issue a SEQ_MSGOUT to get the mesh to drop ACK.
 		 */
 		if ((in_8(&mr->bus_status0) & BS0_ATN) == 0) {
-			dlog(ms, "bus0 was %.2x explictly asserting ATN", mr->bus_status0);
+			dlog(ms, "bus0 was %.2x explicitly asserting ATN", mr->bus_status0);
 			out_8(&mr->bus_status0, BS0_ATN); /* explicit ATN */
 			mesh_flush_io(mr);
 			udelay(1);
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 3f2f246..172839f 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5146,7 +5146,8 @@
 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
 static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
 {
-	int i, priority;
+	int i;
+	gfp_t priority;
 	struct osst_buffer *tb;
 
 	if (from_initialization)
@@ -5178,7 +5179,8 @@
 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
 static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
 {
-	int segs, nbr, max_segs, b_size, priority, order, got;
+	int segs, nbr, max_segs, b_size, order, got;
+	gfp_t priority;
 
 	if (STbuffer->buffer_size >= OS_FRAME_SIZE)
 		return 1;
@@ -5627,7 +5629,7 @@
 
 	if (!osst_sysfs_valid) return;
 
-	osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name);
+	osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name);
 	if (IS_ERR(osst_class_member)) {
 		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
 		return;
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
new file mode 100644
index 0000000..665017e
--- /dev/null
+++ b/drivers/scsi/pdc_adma.c
@@ -0,0 +1,741 @@
+/*
+ *  pdc_adma.c - Pacific Digital Corporation ADMA
+ *
+ *  Maintained by:  Mark Lord <mlord@pobox.com>
+ *
+ *  Copyright 2005 Mark Lord
+ *
+ *  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, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *
+ *  Supports ATA disks in single-packet ADMA mode.
+ *  Uses PIO for everything else.
+ *
+ *  TODO:  Use ADMA transfers for ATAPI devices, when possible.
+ *  This requires careful attention to a number of quirks of the chip.
+ *
+ */
+
+#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 <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME	"pdc_adma"
+#define DRV_VERSION	"0.03"
+
+/* macro to calculate base address for ATA regs */
+#define ADMA_ATA_REGS(base,port_no)	((base) + ((port_no) * 0x40))
+
+/* macro to calculate base address for ADMA regs */
+#define ADMA_REGS(base,port_no)	((base) + 0x80 + ((port_no) * 0x20))
+
+enum {
+	ADMA_PORTS		= 2,
+	ADMA_CPB_BYTES		= 40,
+	ADMA_PRD_BYTES		= LIBATA_MAX_PRD * 16,
+	ADMA_PKT_BYTES		= ADMA_CPB_BYTES + ADMA_PRD_BYTES,
+
+	ADMA_DMA_BOUNDARY	= 0xffffffff,
+
+	/* global register offsets */
+	ADMA_MODE_LOCK		= 0x00c7,
+
+	/* per-channel register offsets */
+	ADMA_CONTROL		= 0x0000, /* ADMA control */
+	ADMA_STATUS		= 0x0002, /* ADMA status */
+	ADMA_CPB_COUNT		= 0x0004, /* CPB count */
+	ADMA_CPB_CURRENT	= 0x000c, /* current CPB address */
+	ADMA_CPB_NEXT		= 0x000c, /* next CPB address */
+	ADMA_CPB_LOOKUP		= 0x0010, /* CPB lookup table */
+	ADMA_FIFO_IN		= 0x0014, /* input FIFO threshold */
+	ADMA_FIFO_OUT		= 0x0016, /* output FIFO threshold */
+
+	/* ADMA_CONTROL register bits */
+	aNIEN			= (1 << 8), /* irq mask: 1==masked */
+	aGO			= (1 << 7), /* packet trigger ("Go!") */
+	aRSTADM			= (1 << 5), /* ADMA logic reset */
+	aPIOMD4			= 0x0003,   /* PIO mode 4 */
+
+	/* ADMA_STATUS register bits */
+	aPSD			= (1 << 6),
+	aUIRQ			= (1 << 4),
+	aPERR			= (1 << 0),
+
+	/* CPB bits */
+	cDONE			= (1 << 0),
+	cVLD			= (1 << 0),
+	cDAT			= (1 << 2),
+	cIEN			= (1 << 3),
+
+	/* PRD bits */
+	pORD			= (1 << 4),
+	pDIRO			= (1 << 5),
+	pEND			= (1 << 7),
+
+	/* ATA register flags */
+	rIGN			= (1 << 5),
+	rEND			= (1 << 7),
+
+	/* ATA register addresses */
+	ADMA_REGS_CONTROL	= 0x0e,
+	ADMA_REGS_SECTOR_COUNT	= 0x12,
+	ADMA_REGS_LBA_LOW	= 0x13,
+	ADMA_REGS_LBA_MID	= 0x14,
+	ADMA_REGS_LBA_HIGH	= 0x15,
+	ADMA_REGS_DEVICE	= 0x16,
+	ADMA_REGS_COMMAND	= 0x17,
+
+	/* PCI device IDs */
+	board_1841_idx		= 0,	/* ADMA 2-port controller */
+};
+
+typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
+
+struct adma_port_priv {
+	u8			*pkt;
+	dma_addr_t		pkt_dma;
+	adma_state_t		state;
+};
+
+static int adma_ata_init_one (struct pci_dev *pdev,
+				const struct pci_device_id *ent);
+static irqreturn_t adma_intr (int irq, void *dev_instance,
+				struct pt_regs *regs);
+static int adma_port_start(struct ata_port *ap);
+static void adma_host_stop(struct ata_host_set *host_set);
+static void adma_port_stop(struct ata_port *ap);
+static void adma_phy_reset(struct ata_port *ap);
+static void adma_qc_prep(struct ata_queued_cmd *qc);
+static int adma_qc_issue(struct ata_queued_cmd *qc);
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
+static void adma_bmdma_stop(struct ata_queued_cmd *qc);
+static u8 adma_bmdma_status(struct ata_port *ap);
+static void adma_irq_clear(struct ata_port *ap);
+static void adma_eng_timeout(struct ata_port *ap);
+
+static Scsi_Host_Template adma_ata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ADMA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static const struct ata_port_operations adma_ata_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.check_atapi_dma	= adma_check_atapi_dma,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+	.phy_reset		= adma_phy_reset,
+	.qc_prep		= adma_qc_prep,
+	.qc_issue		= adma_qc_issue,
+	.eng_timeout		= adma_eng_timeout,
+	.irq_handler		= adma_intr,
+	.irq_clear		= adma_irq_clear,
+	.port_start		= adma_port_start,
+	.port_stop		= adma_port_stop,
+	.host_stop		= adma_host_stop,
+	.bmdma_stop		= adma_bmdma_stop,
+	.bmdma_status		= adma_bmdma_status,
+};
+
+static struct ata_port_info adma_port_info[] = {
+	/* board_1841_idx */
+	{
+		.sht		= &adma_ata_sht,
+		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
+		.pio_mask	= 0x10, /* pio4 */
+		.udma_mask	= 0x1f, /* udma0-4 */
+		.port_ops	= &adma_ata_ops,
+	},
+};
+
+static struct pci_device_id adma_ata_pci_tbl[] = {
+	{ PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_1841_idx },
+
+	{ }	/* terminate list */
+};
+
+static struct pci_driver adma_ata_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= adma_ata_pci_tbl,
+	.probe			= adma_ata_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	return 1;	/* ATAPI DMA not yet supported */
+}
+
+static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	/* nothing */
+}
+
+static u8 adma_bmdma_status(struct ata_port *ap)
+{
+	return 0;
+}
+
+static void adma_irq_clear(struct ata_port *ap)
+{
+	/* nothing */
+}
+
+static void adma_reset_engine(void __iomem *chan)
+{
+	/* reset ADMA to idle state */
+	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+	udelay(2);
+	writew(aPIOMD4, chan + ADMA_CONTROL);
+	udelay(2);
+}
+
+static void adma_reinit_engine(struct ata_port *ap)
+{
+	struct adma_port_priv *pp = ap->private_data;
+	void __iomem *mmio_base = ap->host_set->mmio_base;
+	void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
+
+	/* mask/clear ATA interrupts */
+	writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
+	ata_check_status(ap);
+
+	/* reset the ADMA engine */
+	adma_reset_engine(chan);
+
+	/* set in-FIFO threshold to 0x100 */
+	writew(0x100, chan + ADMA_FIFO_IN);
+
+	/* set CPB pointer */
+	writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
+
+	/* set out-FIFO threshold to 0x100 */
+	writew(0x100, chan + ADMA_FIFO_OUT);
+
+	/* set CPB count */
+	writew(1, chan + ADMA_CPB_COUNT);
+
+	/* read/discard ADMA status */
+	readb(chan + ADMA_STATUS);
+}
+
+static inline void adma_enter_reg_mode(struct ata_port *ap)
+{
+	void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+	writew(aPIOMD4, chan + ADMA_CONTROL);
+	readb(chan + ADMA_STATUS);	/* flush */
+}
+
+static void adma_phy_reset(struct ata_port *ap)
+{
+	struct adma_port_priv *pp = ap->private_data;
+
+	pp->state = adma_state_idle;
+	adma_reinit_engine(ap);
+	ata_port_probe(ap);
+	ata_bus_reset(ap);
+}
+
+static void adma_eng_timeout(struct ata_port *ap)
+{
+	struct adma_port_priv *pp = ap->private_data;
+
+	if (pp->state != adma_state_idle) /* healthy paranoia */
+		pp->state = adma_state_mmio;
+	adma_reinit_engine(ap);
+	ata_eng_timeout(ap);
+}
+
+static int adma_fill_sg(struct ata_queued_cmd *qc)
+{
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	struct adma_port_priv *pp = ap->private_data;
+	u8  *buf = pp->pkt;
+	int nelem, i = (2 + buf[3]) * 8;
+	u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
+
+	for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
+		u32 addr;
+		u32 len;
+
+		addr = (u32)sg_dma_address(sg);
+		*(__le32 *)(buf + i) = cpu_to_le32(addr);
+		i += 4;
+
+		len = sg_dma_len(sg) >> 3;
+		*(__le32 *)(buf + i) = cpu_to_le32(len);
+		i += 4;
+
+		if ((nelem + 1) == qc->n_elem)
+			pFLAGS |= pEND;
+		buf[i++] = pFLAGS;
+		buf[i++] = qc->dev->dma_mode & 0xf;
+		buf[i++] = 0;	/* pPKLW */
+		buf[i++] = 0;	/* reserved */
+
+		*(__le32 *)(buf + i)
+			= (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
+		i += 4;
+
+		VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem,
+					(unsigned long)addr, len);
+	}
+	return i;
+}
+
+static void adma_qc_prep(struct ata_queued_cmd *qc)
+{
+	struct adma_port_priv *pp = qc->ap->private_data;
+	u8  *buf = pp->pkt;
+	u32 pkt_dma = (u32)pp->pkt_dma;
+	int i = 0;
+
+	VPRINTK("ENTER\n");
+
+	adma_enter_reg_mode(qc->ap);
+	if (qc->tf.protocol != ATA_PROT_DMA) {
+		ata_qc_prep(qc);
+		return;
+	}
+
+	buf[i++] = 0;	/* Response flags */
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = cVLD | cDAT | cIEN;
+	i++;		/* cLEN, gets filled in below */
+
+	*(__le32 *)(buf+i) = cpu_to_le32(pkt_dma);	/* cNCPB */
+	i += 4;		/* cNCPB */
+	i += 4;		/* cPRD, gets filled in below */
+
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = 0;	/* reserved */
+
+	/* ATA registers; must be a multiple of 4 */
+	buf[i++] = qc->tf.device;
+	buf[i++] = ADMA_REGS_DEVICE;
+	if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
+		buf[i++] = qc->tf.hob_nsect;
+		buf[i++] = ADMA_REGS_SECTOR_COUNT;
+		buf[i++] = qc->tf.hob_lbal;
+		buf[i++] = ADMA_REGS_LBA_LOW;
+		buf[i++] = qc->tf.hob_lbam;
+		buf[i++] = ADMA_REGS_LBA_MID;
+		buf[i++] = qc->tf.hob_lbah;
+		buf[i++] = ADMA_REGS_LBA_HIGH;
+	}
+	buf[i++] = qc->tf.nsect;
+	buf[i++] = ADMA_REGS_SECTOR_COUNT;
+	buf[i++] = qc->tf.lbal;
+	buf[i++] = ADMA_REGS_LBA_LOW;
+	buf[i++] = qc->tf.lbam;
+	buf[i++] = ADMA_REGS_LBA_MID;
+	buf[i++] = qc->tf.lbah;
+	buf[i++] = ADMA_REGS_LBA_HIGH;
+	buf[i++] = 0;
+	buf[i++] = ADMA_REGS_CONTROL;
+	buf[i++] = rIGN;
+	buf[i++] = 0;
+	buf[i++] = qc->tf.command;
+	buf[i++] = ADMA_REGS_COMMAND | rEND;
+
+	buf[3] = (i >> 3) - 2;				/* cLEN */
+	*(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i);	/* cPRD */
+
+	i = adma_fill_sg(qc);
+	wmb();	/* flush PRDs and pkt to memory */
+#if 0
+	/* dump out CPB + PRDs for debug */
+	{
+		int j, len = 0;
+		static char obuf[2048];
+		for (j = 0; j < i; ++j) {
+			len += sprintf(obuf+len, "%02x ", buf[j]);
+			if ((j & 7) == 7) {
+				printk("%s\n", obuf);
+				len = 0;
+			}
+		}
+		if (len)
+			printk("%s\n", obuf);
+	}
+#endif
+}
+
+static inline void adma_packet_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+	VPRINTK("ENTER, ap %p\n", ap);
+
+	/* fire up the ADMA engine */
+	writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
+}
+
+static int adma_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct adma_port_priv *pp = qc->ap->private_data;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		pp->state = adma_state_pkt;
+		adma_packet_start(qc);
+		return 0;
+
+	case ATA_PROT_ATAPI_DMA:
+		BUG();
+		break;
+
+	default:
+		break;
+	}
+
+	pp->state = adma_state_mmio;
+	return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
+{
+	unsigned int handled = 0, port_no;
+	u8 __iomem *mmio_base = host_set->mmio_base;
+
+	for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+		struct ata_port *ap = host_set->ports[port_no];
+		struct adma_port_priv *pp;
+		struct ata_queued_cmd *qc;
+		void __iomem *chan = ADMA_REGS(mmio_base, port_no);
+		u8 status = readb(chan + ADMA_STATUS);
+
+		if (status == 0)
+			continue;
+		handled = 1;
+		adma_enter_reg_mode(ap);
+		if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+			continue;
+		pp = ap->private_data;
+		if (!pp || pp->state != adma_state_pkt)
+			continue;
+		qc = ata_qc_from_tag(ap, ap->active_tag);
+		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+			unsigned int err_mask = 0;
+
+			if ((status & (aPERR | aPSD | aUIRQ)))
+				err_mask = AC_ERR_OTHER;
+			else if (pp->pkt[0] != cDONE)
+				err_mask = AC_ERR_OTHER;
+
+			ata_qc_complete(qc, err_mask);
+		}
+	}
+	return handled;
+}
+
+static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
+{
+	unsigned int handled = 0, port_no;
+
+	for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+		struct ata_port *ap;
+		ap = host_set->ports[port_no];
+		if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
+			struct ata_queued_cmd *qc;
+			struct adma_port_priv *pp = ap->private_data;
+			if (!pp || pp->state != adma_state_mmio)
+				continue;
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+
+				/* check main status, clearing INTRQ */
+				u8 status = ata_check_status(ap);
+				if ((status & ATA_BUSY))
+					continue;
+				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+					ap->id, qc->tf.protocol, status);
+		
+				/* complete taskfile transaction */
+				pp->state = adma_state_idle;
+				ata_qc_complete(qc, ac_err_mask(status));
+				handled = 1;
+			}
+		}
+	}
+	return handled;
+}
+
+static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	unsigned int handled = 0;
+
+	VPRINTK("ENTER\n");
+
+	spin_lock(&host_set->lock);
+	handled  = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
+	spin_unlock(&host_set->lock);
+
+	VPRINTK("EXIT\n");
+
+	return IRQ_RETVAL(handled);
+}
+
+static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+	port->cmd_addr		=
+	port->data_addr		= base + 0x000;
+	port->error_addr	=
+	port->feature_addr	= base + 0x004;
+	port->nsect_addr	= base + 0x008;
+	port->lbal_addr		= base + 0x00c;
+	port->lbam_addr		= base + 0x010;
+	port->lbah_addr		= base + 0x014;
+	port->device_addr	= base + 0x018;
+	port->status_addr	=
+	port->command_addr	= base + 0x01c;
+	port->altstatus_addr	=
+	port->ctl_addr		= base + 0x038;
+}
+
+static int adma_port_start(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct adma_port_priv *pp;
+	int rc;
+
+	rc = ata_port_start(ap);
+	if (rc)
+		return rc;
+	adma_enter_reg_mode(ap);
+	rc = -ENOMEM;
+	pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		goto err_out;
+	pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
+								GFP_KERNEL);
+	if (!pp->pkt)
+		goto err_out_kfree;
+	/* paranoia? */
+	if ((pp->pkt_dma & 7) != 0) {
+		printk("bad alignment for pp->pkt_dma: %08x\n",
+						(u32)pp->pkt_dma);
+		dma_free_coherent(dev, ADMA_PKT_BYTES,
+						pp->pkt, pp->pkt_dma);
+		goto err_out_kfree;
+	}
+	memset(pp->pkt, 0, ADMA_PKT_BYTES);
+	ap->private_data = pp;
+	adma_reinit_engine(ap);
+	return 0;
+
+err_out_kfree:
+	kfree(pp);
+err_out:
+	ata_port_stop(ap);
+	return rc;
+}
+
+static void adma_port_stop(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct adma_port_priv *pp = ap->private_data;
+
+	adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
+	if (pp != NULL) {
+		ap->private_data = NULL;
+		if (pp->pkt != NULL)
+			dma_free_coherent(dev, ADMA_PKT_BYTES,
+					pp->pkt, pp->pkt_dma);
+		kfree(pp);
+	}
+	ata_port_stop(ap);
+}
+
+static void adma_host_stop(struct ata_host_set *host_set)
+{
+	unsigned int port_no;
+
+	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+		adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
+
+	ata_pci_host_stop(host_set);
+}
+
+static void adma_host_init(unsigned int chip_id,
+				struct ata_probe_ent *probe_ent)
+{
+	unsigned int port_no;
+	void __iomem *mmio_base = probe_ent->mmio_base;
+
+	/* enable/lock aGO operation */
+	writeb(7, mmio_base + ADMA_MODE_LOCK);
+
+	/* reset the ADMA logic */
+	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+		adma_reset_engine(ADMA_REGS(mmio_base, port_no));
+}
+
+static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+	int rc;
+
+	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 0;
+}
+
+static int adma_ata_init_one(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	void __iomem *mmio_base;
+	unsigned int board_idx = (unsigned int) ent->driver_data;
+	int rc, port_no;
+
+	if (!printed_version++)
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+		rc = -ENODEV;
+		goto err_out_regions;
+	}
+
+	mmio_base = pci_iomap(pdev, 4, 0);
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	rc = adma_set_dma_masks(pdev, mmio_base);
+	if (rc)
+		goto err_out_iounmap;
+
+	probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_iounmap;
+	}
+
+	probe_ent->dev = pci_dev_to_dev(pdev);
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht		= adma_port_info[board_idx].sht;
+	probe_ent->host_flags	= adma_port_info[board_idx].host_flags;
+	probe_ent->pio_mask	= adma_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= adma_port_info[board_idx].mwdma_mask;
+	probe_ent->udma_mask	= adma_port_info[board_idx].udma_mask;
+	probe_ent->port_ops	= adma_port_info[board_idx].port_ops;
+
+	probe_ent->irq		= pdev->irq;
+	probe_ent->irq_flags	= SA_SHIRQ;
+	probe_ent->mmio_base	= mmio_base;
+	probe_ent->n_ports	= ADMA_PORTS;
+
+	for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+		adma_ata_setup_port(&probe_ent->port[port_no],
+			ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
+	}
+
+	pci_set_master(pdev);
+
+	/* initialize adapter */
+	adma_host_init(board_idx, probe_ent);
+
+	rc = ata_device_add(probe_ent);
+	kfree(probe_ent);
+	if (rc != ADMA_PORTS)
+		goto err_out_iounmap;
+	return 0;
+
+err_out_iounmap:
+	pci_iounmap(pdev, mmio_base);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init adma_ata_init(void)
+{
+	return pci_module_init(&adma_ata_pci_driver);
+}
+
+static void __exit adma_ata_exit(void)
+{
+	pci_unregister_driver(&adma_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(adma_ata_init);
+module_exit(adma_ata_exit);
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1ed32e7..e451941 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -52,7 +52,7 @@
 extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
 extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
 
-extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
 
 extern int qla2x00_loop_resync(scsi_qla_host_t *);
 
@@ -277,7 +277,7 @@
 /*
  * Global Function Prototypes in qla_rscn.c source file.
  */
-extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, int);
+extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t);
 extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *,
     int);
 extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 23d095d..fbb6fee 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1685,7 +1685,7 @@
  * Returns a pointer to the allocated fcport, or NULL, if none available.
  */
 fc_port_t *
-qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
 {
 	fc_port_t *fcport;
 
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index 1eba988..7534efc 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -1066,7 +1066,7 @@
  * Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
  */
 fc_port_t *
-qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, int flags)
+qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
 {
 	fc_port_t *fcport;
 
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index ea76fe4..46dbdee 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -29,13 +29,14 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <asm/io.h>
 
 #define DRV_NAME	"sata_mv"
-#define DRV_VERSION	"0.12"
+#define DRV_VERSION	"0.25"
 
 enum {
 	/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -55,31 +56,61 @@
 	MV_SATAHC_ARBTR_REG_SZ	= MV_MINOR_REG_AREA_SZ,		/* arbiter */
 	MV_PORT_REG_SZ		= MV_MINOR_REG_AREA_SZ,
 
-	MV_Q_CT			= 32,
-	MV_CRQB_SZ		= 32,
-	MV_CRPB_SZ		= 8,
+	MV_USE_Q_DEPTH		= ATA_DEF_QUEUE,
 
-	MV_DMA_BOUNDARY		= 0xffffffffU,
-	SATAHC_MASK		= (~(MV_SATAHC_REG_SZ - 1)),
+	MV_MAX_Q_DEPTH		= 32,
+	MV_MAX_Q_DEPTH_MASK	= MV_MAX_Q_DEPTH - 1,
+
+	/* 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_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),
+
+	/* Our DMA boundary is determined by an ePRD being unable to handle
+	 * anything larger than 64KB
+	 */
+	MV_DMA_BOUNDARY		= 0xffffU,
 
 	MV_PORTS_PER_HC		= 4,
 	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
 	MV_PORT_HC_SHIFT	= 2,
-	/* == (port % MV_PORTS_PER_HC) to determine port from 0-7 port */
+	/* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
 	MV_PORT_MASK		= 3,
 
 	/* Host Flags */
 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
-	MV_FLAG_BDMA		= (1 << 28),  /* Basic DMA */
+	MV_FLAG_GLBL_SFT_RST	= (1 << 28),  /* Global Soft Reset support */
+	MV_COMMON_FLAGS		= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
+	MV_6XXX_FLAGS		= (MV_FLAG_IRQ_COALESCE | 
+				   MV_FLAG_GLBL_SFT_RST),
 
 	chip_504x		= 0,
 	chip_508x		= 1,
 	chip_604x		= 2,
 	chip_608x		= 3,
 
+	CRQB_FLAG_READ		= (1 << 0),
+	CRQB_TAG_SHIFT		= 1,
+	CRQB_CMD_ADDR_SHIFT	= 8,
+	CRQB_CMD_CS		= (0x2 << 11),
+	CRQB_CMD_LAST		= (1 << 15),
+
+	CRPB_FLAG_STATUS_SHIFT	= 8,
+
+	EPRD_FLAG_END_OF_TBL	= (1 << 31),
+
 	/* PCI interface registers */
 
+	PCI_COMMAND_OFS		= 0xc00,
+
 	PCI_MAIN_CMD_STS_OFS	= 0xd30,
 	STOP_PCI_MASTER		= (1 << 2),
 	PCI_MASTER_EMPTY	= (1 << 3),
@@ -111,20 +142,13 @@
 	HC_CFG_OFS		= 0,
 
 	HC_IRQ_CAUSE_OFS	= 0x14,
-	CRBP_DMA_DONE		= (1 << 0),	/* shift by port # */
+	CRPB_DMA_DONE		= (1 << 0),	/* shift by port # */
 	HC_IRQ_COAL		= (1 << 4),	/* IRQ coalescing */
 	DEV_IRQ			= (1 << 8),	/* shift by port # */
 
 	/* Shadow block registers */
-	SHD_PIO_DATA_OFS	= 0x100,
-	SHD_FEA_ERR_OFS		= 0x104,
-	SHD_SECT_CNT_OFS	= 0x108,
-	SHD_LBA_L_OFS		= 0x10C,
-	SHD_LBA_M_OFS		= 0x110,
-	SHD_LBA_H_OFS		= 0x114,
-	SHD_DEV_HD_OFS		= 0x118,
-	SHD_CMD_STA_OFS		= 0x11C,
-	SHD_CTL_AST_OFS		= 0x120,
+	SHD_BLK_OFS		= 0x100,
+	SHD_CTL_AST_OFS		= 0x20,		/* ofs from SHD_BLK_OFS */
 
 	/* SATA registers */
 	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
@@ -132,6 +156,11 @@
 
 	/* 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_ERR_IRQ_CAUSE_OFS	= 0x8,
 	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
@@ -161,33 +190,84 @@
 				   EDMA_ERR_LNK_DATA_TX | 
 				   EDMA_ERR_TRANS_PROTO),
 
+	EDMA_REQ_Q_BASE_HI_OFS	= 0x10,
+	EDMA_REQ_Q_IN_PTR_OFS	= 0x14,		/* also contains BASE_LO */
+	EDMA_REQ_Q_BASE_LO_MASK	= 0xfffffc00U,
+
+	EDMA_REQ_Q_OUT_PTR_OFS	= 0x18,
+	EDMA_REQ_Q_PTR_SHIFT	= 5,
+
+	EDMA_RSP_Q_BASE_HI_OFS	= 0x1c,
+	EDMA_RSP_Q_IN_PTR_OFS	= 0x20,
+	EDMA_RSP_Q_OUT_PTR_OFS	= 0x24,		/* also contains BASE_LO */
+	EDMA_RSP_Q_BASE_LO_MASK	= 0xffffff00U,
+	EDMA_RSP_Q_PTR_SHIFT	= 3,
+
 	EDMA_CMD_OFS		= 0x28,
 	EDMA_EN			= (1 << 0),
 	EDMA_DS			= (1 << 1),
 	ATA_RST			= (1 << 2),
 
-	/* BDMA is 6xxx part only */
-	BDMA_CMD_OFS		= 0x224,
-	BDMA_START		= (1 << 0),
+	/* Host private flags (hp_flags) */
+	MV_HP_FLAG_MSI		= (1 << 0),
 
-	MV_UNDEF		= 0,
+	/* Port private flags (pp_flags) */
+	MV_PP_FLAG_EDMA_EN	= (1 << 0),
+	MV_PP_FLAG_EDMA_DS_ACT	= (1 << 1),
+};
+
+/* Command ReQuest Block: 32B */
+struct mv_crqb {
+	u32			sg_addr;
+	u32			sg_addr_hi;
+	u16			ctrl_flags;
+	u16			ata_cmd[11];
+};
+
+/* Command ResPonse Block: 8B */
+struct mv_crpb {
+	u16			id;
+	u16			flags;
+	u32			tmstmp;
+};
+
+/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
+struct mv_sg {
+	u32			addr;
+	u32			flags_size;
+	u32			addr_hi;
+	u32			reserved;
 };
 
 struct mv_port_priv {
+	struct mv_crqb		*crqb;
+	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;
 
+	unsigned		req_producer;		/* cp of req_in_ptr */
+	unsigned		rsp_consumer;		/* cp of rsp_out_ptr */
+	u32			pp_flags;
 };
 
 struct mv_host_priv {
-
+	u32			hp_flags;
 };
 
 static void mv_irq_clear(struct ata_port *ap);
 static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
 static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
 static void mv_phy_reset(struct ata_port *ap);
-static int mv_master_reset(void __iomem *mmio_base);
+static void mv_host_stop(struct ata_host_set *host_set);
+static int mv_port_start(struct ata_port *ap);
+static void mv_port_stop(struct ata_port *ap);
+static void mv_qc_prep(struct ata_queued_cmd *qc);
+static int mv_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t mv_interrupt(int irq, void *dev_instance,
 				struct pt_regs *regs);
+static void mv_eng_timeout(struct ata_port *ap);
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
 static Scsi_Host_Template mv_sht = {
@@ -196,13 +276,13 @@
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
-	.can_queue		= ATA_DEF_QUEUE,
+	.can_queue		= MV_USE_Q_DEPTH,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= MV_UNDEF,
+	.sg_tablesize		= MV_MAX_SG_CT,
 	.max_sectors		= ATA_MAX_SECTORS,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
-	.use_clustering		= MV_UNDEF,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= MV_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
@@ -210,7 +290,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations mv_ops = {
+static const struct ata_port_operations mv_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -221,10 +301,10 @@
 
 	.phy_reset		= mv_phy_reset,
 
-	.qc_prep		= ata_qc_prep,
-	.qc_issue		= ata_qc_issue_prot,
+	.qc_prep		= mv_qc_prep,
+	.qc_issue		= mv_qc_issue,
 
-	.eng_timeout		= ata_eng_timeout,
+	.eng_timeout		= mv_eng_timeout,
 
 	.irq_handler		= mv_interrupt,
 	.irq_clear		= mv_irq_clear,
@@ -232,46 +312,39 @@
 	.scr_read		= mv_scr_read,
 	.scr_write		= mv_scr_write,
 
-	.port_start		= ata_port_start,
-	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
+	.port_start		= mv_port_start,
+	.port_stop		= mv_port_stop,
+	.host_stop		= mv_host_stop,
 };
 
 static struct ata_port_info mv_port_info[] = {
 	{  /* chip_504x */
 		.sht		= &mv_sht,
-		.host_flags	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
-		.pio_mask	= 0x1f,	/* pio4-0 */
-		.udma_mask	= 0,	/* 0x7f (udma6-0 disabled for now) */
+		.host_flags	= MV_COMMON_FLAGS,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.udma_mask	= 0,	/* 0x7f (udma0-6 disabled for now) */
 		.port_ops	= &mv_ops,
 	},
 	{  /* chip_508x */
 		.sht		= &mv_sht,
-		.host_flags	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 
-				   MV_FLAG_DUAL_HC),
-		.pio_mask	= 0x1f,	/* pio4-0 */
-		.udma_mask	= 0,	/* 0x7f (udma6-0 disabled for now) */
+		.host_flags	= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.udma_mask	= 0,	/* 0x7f (udma0-6 disabled for now) */
 		.port_ops	= &mv_ops,
 	},
 	{  /* chip_604x */
 		.sht		= &mv_sht,
-		.host_flags	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 
-				   MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA),
-		.pio_mask	= 0x1f,	/* pio4-0 */
-		.udma_mask	= 0,	/* 0x7f (udma6-0 disabled for now) */
+		.host_flags	= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &mv_ops,
 	},
 	{  /* chip_608x */
 		.sht		= &mv_sht,
-		.host_flags	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-				   MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC |
-				   MV_FLAG_BDMA),
-		.pio_mask	= 0x1f,	/* pio4-0 */
-		.udma_mask	= 0,	/* 0x7f (udma6-0 disabled for now) */
+		.host_flags	= (MV_COMMON_FLAGS | MV_6XXX_FLAGS | 
+				   MV_FLAG_DUAL_HC),
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &mv_ops,
 	},
 };
@@ -306,12 +379,6 @@
 	(void) readl(addr);	/* flush to avoid PCI posted write */
 }
 
-static inline void __iomem *mv_port_addr_to_hc_base(void __iomem *port_mmio)
-{
-	return ((void __iomem *)((unsigned long)port_mmio & 
-				 (unsigned long)SATAHC_MASK));
-}
-
 static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
 {
 	return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
@@ -329,26 +396,152 @@
 	return mv_port_base(ap->host_set->mmio_base, ap->port_no);
 }
 
-static inline int mv_get_hc_count(unsigned long flags)
+static inline int mv_get_hc_count(unsigned long hp_flags)
 {
-	return ((flags & MV_FLAG_DUAL_HC) ? 2 : 1);
-}
-
-static inline int mv_is_edma_active(struct ata_port *ap)
-{
-	void __iomem *port_mmio = mv_ap_base(ap);
-	return (EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
-}
-
-static inline int mv_port_bdma_capable(struct ata_port *ap)
-{
-	return (ap->flags & MV_FLAG_BDMA);
+	return ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
 }
 
 static void mv_irq_clear(struct ata_port *ap)
 {
 }
 
+/**
+ *      mv_start_dma - Enable eDMA engine
+ *      @base: port base address
+ *      @pp: port private data
+ *
+ *      Verify the local cache of the eDMA state is accurate with an
+ *      assert.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+{
+	if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
+		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+	}
+	assert(EDMA_EN & readl(base + EDMA_CMD_OFS));
+}
+
+/**
+ *      mv_stop_dma - Disable eDMA engine
+ *      @ap: ATA channel to manipulate
+ *
+ *      Verify the local cache of the eDMA state is accurate with an
+ *      assert.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_stop_dma(struct ata_port *ap)
+{
+	void __iomem *port_mmio = mv_ap_base(ap);
+	struct mv_port_priv *pp	= ap->private_data;
+	u32 reg;
+	int i;
+
+	if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+		/* Disable EDMA if active.   The disable bit auto clears.
+		 */
+		writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+	} else {
+		assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+  	}
+	
+	/* now properly wait for the eDMA to stop */
+	for (i = 1000; i > 0; i--) {
+		reg = readl(port_mmio + EDMA_CMD_OFS);
+		if (!(EDMA_EN & reg)) {
+			break;
+		}
+		udelay(100);
+	}
+
+	if (EDMA_EN & reg) {
+		printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+		/* FIXME: Consider doing a reset here to recover */
+	}
+}
+
+#ifdef ATA_DEBUG
+static void mv_dump_mem(void __iomem *start, unsigned bytes)
+{
+	int b, w;
+	for (b = 0; b < bytes; ) {
+		DPRINTK("%p: ", start + b);
+		for (w = 0; b < bytes && w < 4; w++) {
+			printk("%08x ",readl(start + b));
+			b += sizeof(u32);
+		}
+		printk("\n");
+	}
+}
+#endif
+
+static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
+{
+#ifdef ATA_DEBUG
+	int b, w;
+	u32 dw;
+	for (b = 0; b < bytes; ) {
+		DPRINTK("%02x: ", b);
+		for (w = 0; b < bytes && w < 4; w++) {
+			(void) pci_read_config_dword(pdev,b,&dw);
+			printk("%08x ",dw);
+			b += sizeof(u32);
+		}
+		printk("\n");
+	}
+#endif
+}
+static void mv_dump_all_regs(void __iomem *mmio_base, int port,
+			     struct pci_dev *pdev)
+{
+#ifdef ATA_DEBUG
+	void __iomem *hc_base = mv_hc_base(mmio_base, 
+					   port >> MV_PORT_HC_SHIFT);
+	void __iomem *port_base;
+	int start_port, num_ports, p, start_hc, num_hcs, hc;
+
+	if (0 > port) {
+		start_hc = start_port = 0;
+		num_ports = 8;		/* shld be benign for 4 port devs */
+		num_hcs = 2;
+	} else {
+		start_hc = port >> MV_PORT_HC_SHIFT;
+		start_port = port;
+		num_ports = num_hcs = 1;
+	}
+	DPRINTK("All registers for port(s) %u-%u:\n", start_port, 
+		num_ports > 1 ? num_ports - 1 : start_port);
+
+	if (NULL != pdev) {
+		DPRINTK("PCI config space regs:\n");
+		mv_dump_pci_cfg(pdev, 0x68);
+	}
+	DPRINTK("PCI regs:\n");
+	mv_dump_mem(mmio_base+0xc00, 0x3c);
+	mv_dump_mem(mmio_base+0xd00, 0x34);
+	mv_dump_mem(mmio_base+0xf00, 0x4);
+	mv_dump_mem(mmio_base+0x1d00, 0x6c);
+	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
+		hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+		DPRINTK("HC regs (HC %i):\n", hc);
+		mv_dump_mem(hc_base, 0x1c);
+	}
+	for (p = start_port; p < start_port + num_ports; p++) {
+		port_base = mv_port_base(mmio_base, p);
+		DPRINTK("EDMA regs (port %i):\n",p);
+		mv_dump_mem(port_base, 0x54);
+		DPRINTK("SATA regs (port %i):\n",p);
+		mv_dump_mem(port_base+0x300, 0x60);
+	}
+#endif
+}
+
 static unsigned int mv_scr_offset(unsigned int sc_reg_in)
 {
 	unsigned int ofs;
@@ -389,30 +582,37 @@
 	}
 }
 
-static int mv_master_reset(void __iomem *mmio_base)
+/**
+ *      mv_global_soft_reset - Perform the 6xxx global soft reset
+ *      @mmio_base: base address of the HBA
+ *
+ *      This routine only applies to 6xxx parts.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv_global_soft_reset(void __iomem *mmio_base)
 {
 	void __iomem *reg = mmio_base + PCI_MAIN_CMD_STS_OFS;
 	int i, rc = 0;
 	u32 t;
 
-	VPRINTK("ENTER\n");
-
 	/* Following procedure defined in PCI "main command and status
 	 * register" table.
 	 */
 	t = readl(reg);
 	writel(t | STOP_PCI_MASTER, reg);
 
-	for (i = 0; i < 100; i++) {
-		msleep(10);
+	for (i = 0; i < 1000; i++) {
+		udelay(1);
 		t = readl(reg);
 		if (PCI_MASTER_EMPTY & t) {
 			break;
 		}
 	}
 	if (!(PCI_MASTER_EMPTY & t)) {
-		printk(KERN_ERR DRV_NAME "PCI master won't flush\n");
-		rc = 1;		/* broken HW? */
+		printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
+		rc = 1;
 		goto done;
 	}
 
@@ -425,48 +625,412 @@
 	} while (!(GLOB_SFT_RST & t) && (i-- > 0));
 
 	if (!(GLOB_SFT_RST & t)) {
-		printk(KERN_ERR DRV_NAME "can't set global reset\n");
-		rc = 1;		/* broken HW? */
+		printk(KERN_ERR DRV_NAME ": can't set global reset\n");
+		rc = 1;
 		goto done;
 	}
 
-	/* clear reset */
+	/* clear reset and *reenable the PCI master* (not mentioned in spec) */
 	i = 5;
 	do {
-		writel(t & ~GLOB_SFT_RST, reg);
+		writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
 		t = readl(reg);
 		udelay(1);
 	} while ((GLOB_SFT_RST & t) && (i-- > 0));
 
 	if (GLOB_SFT_RST & t) {
-		printk(KERN_ERR DRV_NAME "can't clear global reset\n");
-		rc = 1;		/* broken HW? */
+		printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
+		rc = 1;
 	}
-
- done:
-	VPRINTK("EXIT, rc = %i\n", rc);
+done:
 	return rc;
 }
 
+/**
+ *      mv_host_stop - Host specific cleanup/stop routine.
+ *      @host_set: host data structure
+ *
+ *      Disable ints, cleanup host memory, call general purpose
+ *      host_stop.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_host_stop(struct ata_host_set *host_set)
+{
+	struct mv_host_priv *hpriv = host_set->private_data;
+	struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+	if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
+		pci_disable_msi(pdev);
+	} else {
+		pci_intx(pdev, 0);
+	}
+	kfree(hpriv);
+	ata_host_stop(host_set);
+}
+
+/**
+ *      mv_port_start - Port specific init/start routine.
+ *      @ap: ATA channel to manipulate
+ *
+ *      Allocate and point to DMA memory, init port private memory,
+ *      zero indices.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv_port_start(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct mv_port_priv *pp;
+	void __iomem *port_mmio = mv_ap_base(ap);
+	void *mem;
+	dma_addr_t mem_dma;
+
+	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	if (!pp) {
+		return -ENOMEM;
+	}
+	memset(pp, 0, sizeof(*pp));
+
+	mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, 
+				 GFP_KERNEL);
+	if (!mem) {
+		kfree(pp);
+		return -ENOMEM;
+	}
+	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
+
+	/* 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;
+
+	/* 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;
+
+	/* Third item:
+	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
+	 */
+	pp->sg_tbl = mem;
+	pp->sg_tbl_dma = mem_dma;
+
+	writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | 
+		 EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
+
+	writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+	writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, 
+		 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+	writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+	writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+	writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+	writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, 
+		 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+	pp->req_producer = pp->rsp_consumer = 0;
+
+	/* Don't turn on EDMA here...do it before DMA commands only.  Else
+	 * we'll be unable to send non-data, PIO, etc due to restricted access
+	 * to shadow regs.
+	 */
+	ap->private_data = pp;
+	return 0;
+}
+
+/**
+ *      mv_port_stop - Port specific cleanup/stop routine.
+ *      @ap: ATA channel to manipulate
+ *
+ *      Stop DMA, cleanup port memory.
+ *
+ *      LOCKING:
+ *      This routine uses the host_set lock to protect the DMA stop.
+ */
+static void mv_port_stop(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct mv_port_priv *pp = ap->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	mv_stop_dma(ap);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	ap->private_data = NULL;
+	dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
+	kfree(pp);
+}
+
+/**
+ *      mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries
+ *      @qc: queued command whose SG list to source from
+ *
+ *      Populate the SG list and mark the last entry.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_fill_sg(struct ata_queued_cmd *qc)
+{
+	struct mv_port_priv *pp = qc->ap->private_data;
+	unsigned int i;
+
+	for (i = 0; i < qc->n_elem; i++) {
+		u32 sg_len;
+		dma_addr_t addr;
+
+		addr = sg_dma_address(&qc->sg[i]);
+		sg_len = sg_dma_len(&qc->sg[i]);
+
+		pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
+		pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+		assert(0 == (sg_len & ~MV_DMA_BOUNDARY));
+		pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len);
+	}
+	if (0 < qc->n_elem) {
+		pp->sg_tbl[qc->n_elem - 1].flags_size |= 
+			cpu_to_le32(EPRD_FLAG_END_OF_TBL);
+	}
+}
+
+static inline unsigned mv_inc_q_index(unsigned *index)
+{
+	*index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
+	return *index;
+}
+
+static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+{
+	*cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+		(last ? CRQB_CMD_LAST : 0);
+}
+
+/**
+ *      mv_qc_prep - Host specific command preparation.
+ *      @qc: queued command to prepare
+ *
+ *      This routine simply redirects to the general purpose routine
+ *      if command is not DMA.  Else, it handles prep of the CRQB
+ *      (command request block), does some sanity checking, and calls
+ *      the SG load routine.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_qc_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct mv_port_priv *pp = ap->private_data;
+	u16 *cw;
+	struct ata_taskfile *tf;
+	u16 flags = 0;
+
+ 	if (ATA_PROT_DMA != qc->tf.protocol) {
+		return;
+	}
+
+	/* the req producer index should be the same as we remember it */
+	assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> 
+		 EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+	       pp->req_producer);
+
+	/* Fill in command request block
+	 */
+	if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+		flags |= CRQB_FLAG_READ;
+	}
+	assert(MV_MAX_Q_DEPTH > qc->tag);
+	flags |= qc->tag << CRQB_TAG_SHIFT;
+
+	pp->crqb[pp->req_producer].sg_addr = 
+		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+	pp->crqb[pp->req_producer].sg_addr_hi = 
+		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+	pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+
+	cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+	tf = &qc->tf;
+
+	/* Sadly, the CRQB cannot accomodate all registers--there are
+	 * only 11 bytes...so we must pick and choose required
+	 * registers based on the command.  So, we drop feature and
+	 * hob_feature for [RW] DMA commands, but they are needed for
+	 * NCQ.  NCQ will drop hob_nsect.
+	 */
+	switch (tf->command) {
+	case ATA_CMD_READ:
+	case ATA_CMD_READ_EXT:
+	case ATA_CMD_WRITE:
+	case ATA_CMD_WRITE_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
+		 * of which are defined/used by Linux.  If we get here, this
+		 * driver needs work.
+		 *
+		 * FIXME: modify libata to give qc_prep a return value and
+		 * return error here.
+		 */
+		BUG_ON(tf->command);
+		break;
+	}
+	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
+	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
+	mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
+	mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
+	mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
+	mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
+	mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
+	mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
+	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
+
+	if (!(qc->flags & ATA_QCFLAG_DMAMAP)) {
+		return;
+	}
+	mv_fill_sg(qc);
+}
+
+/**
+ *      mv_qc_issue - Initiate a command to the host
+ *      @qc: queued command to start
+ *
+ *      This routine simply redirects to the general purpose routine
+ *      if command is not DMA.  Else, it sanity checks our local
+ *      caches of the request producer/consumer indices then enables
+ *      DMA and bumps the request producer index.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv_qc_issue(struct ata_queued_cmd *qc)
+{
+	void __iomem *port_mmio = mv_ap_base(qc->ap);
+	struct mv_port_priv *pp = qc->ap->private_data;
+	u32 in_ptr;
+
+	if (ATA_PROT_DMA != qc->tf.protocol) {
+		/* 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.
+		 */
+		mv_stop_dma(qc->ap);
+		return ata_qc_issue_prot(qc);
+	}
+
+	in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+	/* the req producer index should be the same as we remember it */
+	assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+	       pp->req_producer);
+	/* until we do queuing, the queue should be empty at this point */
+	assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+	       ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> 
+		 EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+
+	mv_inc_q_index(&pp->req_producer);	/* now incr producer index */
+
+	mv_start_dma(port_mmio, pp);
+
+	/* and write the request in pointer to kick the EDMA to life */
+	in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
+	in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+	writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+	return 0;
+}
+
+/**
+ *      mv_get_crpb_status - get status from most recently completed cmd
+ *      @ap: ATA channel to manipulate
+ *
+ *      This routine is for use when the port is in DMA mode, when it
+ *      will be using the CRPB (command response block) method of
+ *      returning command completion information.  We assert indices
+ *      are good, grab status, and bump the response consumer index to
+ *      prove that we're up to date.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static u8 mv_get_crpb_status(struct ata_port *ap)
+{
+	void __iomem *port_mmio = mv_ap_base(ap);
+	struct mv_port_priv *pp = ap->private_data;
+	u32 out_ptr;
+
+	out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+	/* the response consumer index should be the same as we remember it */
+	assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == 
+	       pp->rsp_consumer);
+
+	/* increment our consumer index... */
+	pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+	
+	/* and, until we do NCQ, there should only be 1 CRPB waiting */
+	assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> 
+		 EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == 
+	       pp->rsp_consumer);
+
+	/* write out our inc'd consumer index so EDMA knows we're caught up */
+	out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
+	out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+	writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+	/* Return ATA status register for completed CRPB */
+	return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT);
+}
+
+/**
+ *      mv_err_intr - Handle error interrupts on the port
+ *      @ap: ATA channel to manipulate
+ *
+ *      In most cases, just clear the interrupt and move on.  However,
+ *      some cases require an eDMA reset, which is done right before
+ *      the COMRESET in mv_phy_reset().  The SERR case requires a
+ *      clear of pending errors in the SATA SERROR register.  Finally,
+ *      if the port disabled DMA, update our cached copy to match.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
 static void mv_err_intr(struct ata_port *ap)
 {
-	void __iomem *port_mmio;
+	void __iomem *port_mmio = mv_ap_base(ap);
 	u32 edma_err_cause, serr = 0;
 
-	/* bug here b/c we got an err int on a port we don't know about,
-	 * so there's no way to clear it
-	 */
-	BUG_ON(NULL == ap);
-	port_mmio = mv_ap_base(ap);
-
 	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
 	if (EDMA_ERR_SERR & edma_err_cause) {
 		serr = scr_read(ap, SCR_ERROR);
 		scr_write_flush(ap, SCR_ERROR, serr);
 	}
-	DPRINTK("port %u error; EDMA err cause: 0x%08x SERR: 0x%08x\n", 
-		ap->port_no, edma_err_cause, serr);
+	if (EDMA_ERR_SELF_DIS & edma_err_cause) {
+		struct mv_port_priv *pp	= ap->private_data;
+		pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+	}
+	DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
+		"SERR: 0x%08x\n", ap->id, edma_err_cause, serr);
 
 	/* Clear EDMA now that SERR cleanup done */
 	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@@ -477,7 +1041,21 @@
 	}
 }
 
-/* Handle any outstanding interrupts in a single SATAHC 
+/**
+ *      mv_host_intr - Handle all interrupts on the given host controller
+ *      @host_set: host specific structure
+ *      @relevant: port error bits relevant to this host controller
+ *      @hc: which host controller we're to look at
+ *
+ *      Read then write clear the HC interrupt status then walk each
+ *      port connected to the HC and see if it needs servicing.  Port
+ *      success ints are reported in the HC interrupt status reg, the
+ *      port error ints are reported in the higher level main
+ *      interrupt status register and thus are passed in via the
+ *      'relevant' argument.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
  */
 static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
 			 unsigned int hc)
@@ -487,8 +1065,9 @@
 	struct ata_port *ap;
 	struct ata_queued_cmd *qc;
 	u32 hc_irq_cause;
-	int shift, port, port0, hard_port;
-	u8 ata_status;
+	int shift, port, port0, hard_port, handled;
+	unsigned int err_mask;
+	u8 ata_status = 0;
 
 	if (hc == 0) {
 		port0 = 0;
@@ -499,7 +1078,7 @@
 	/* we'll need the HC success int register in most cases */
 	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
 	if (hc_irq_cause) {
-		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
+		writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
 	}
 
 	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
@@ -508,54 +1087,70 @@
 	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
 		ap = host_set->ports[port];
 		hard_port = port & MV_PORT_MASK;	/* range 0-3 */
-		ata_status = 0xffU;
+		handled = 0;	/* ensure ata_status is set if handled++ */
 
-		if (((CRBP_DMA_DONE | DEV_IRQ) << hard_port) & hc_irq_cause) {
-			BUG_ON(NULL == ap);
-			/* rcv'd new resp, basic DMA complete, or ATA IRQ */
-			/* This is needed to clear the ATA INTRQ.
-			 * FIXME: don't read the status reg in EDMA mode!
+		if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+			/* new CRPB on the queue; just one at a time until NCQ
+			 */
+			ata_status = mv_get_crpb_status(ap);
+			handled++;
+		} else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+			/* received ATA IRQ; read the status reg to clear INTRQ
 			 */
 			ata_status = readb((void __iomem *)
 					   ap->ioaddr.status_addr);
+			handled++;
 		}
 
-		shift = port * 2;
+		err_mask = ac_err_mask(ata_status);
+
+		shift = port << 1;		/* (port * 2) */
 		if (port >= MV_PORTS_PER_HC) {
 			shift++;	/* skip bit 8 in the HC Main IRQ reg */
 		}
 		if ((PORT0_ERR << shift) & relevant) {
 			mv_err_intr(ap);
-			/* FIXME: smart to OR in ATA_ERR? */
-			ata_status = readb((void __iomem *)
-					   ap->ioaddr.status_addr) | ATA_ERR;
+			err_mask |= AC_ERR_OTHER;
+			handled++;
 		}
 		
-		if (ap) {
+		if (handled && ap) {
 			qc = ata_qc_from_tag(ap, ap->active_tag);
 			if (NULL != qc) {
 				VPRINTK("port %u IRQ found for qc, "
 					"ata_status 0x%x\n", port,ata_status);
-				BUG_ON(0xffU == ata_status);
 				/* mark qc status appropriately */
-				ata_qc_complete(qc, ata_status);
+				ata_qc_complete(qc, err_mask);
 			}
 		}
 	}
 	VPRINTK("EXIT\n");
 }
 
+/**
+ *      mv_interrupt - 
+ *      @irq: unused
+ *      @dev_instance: private data; in this case the host structure
+ *      @regs: unused
+ *
+ *      Read the read only register to determine if any host
+ *      controllers have pending interrupts.  If so, call lower level
+ *      routine to handle.  Also check for PCI errors which are only
+ *      reported here.
+ *
+ *      LOCKING: 
+ *      This routine holds the host_set lock while processing pending
+ *      interrupts.
+ */
 static irqreturn_t mv_interrupt(int irq, void *dev_instance,
 				struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
 	unsigned int hc, handled = 0, n_hcs;
-	void __iomem *mmio;
+	void __iomem *mmio = host_set->mmio_base;
 	u32 irq_stat;
 
-	mmio = host_set->mmio_base;
 	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
-	n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
 
 	/* check the cases where we either have nothing pending or have read
 	 * a bogus register value which can indicate HW removal or PCI fault
@@ -564,64 +1159,89 @@
 		return IRQ_NONE;
 	}
 
+	n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
 	spin_lock(&host_set->lock);
 
 	for (hc = 0; hc < n_hcs; hc++) {
 		u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
 		if (relevant) {
 			mv_host_intr(host_set, relevant, hc);
-			handled = 1;
+			handled++;
 		}
 	}
 	if (PCI_ERR & irq_stat) {
-		/* FIXME: these are all masked by default, but still need
-		 * to recover from them properly.
-		 */
-	}
+		printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
+		       readl(mmio + PCI_IRQ_CAUSE_OFS));
 
+		DPRINTK("All regs @ PCI error\n");
+		mv_dump_all_regs(mmio, -1, to_pci_dev(host_set->dev));
+
+		writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+		handled++;
+	}
 	spin_unlock(&host_set->lock);
 
 	return IRQ_RETVAL(handled);
 }
 
+/**
+ *      mv_phy_reset - Perform eDMA reset followed by COMRESET
+ *      @ap: ATA channel to manipulate
+ *
+ *      Part of this is taken from __sata_phy_reset and modified to
+ *      not sleep since this routine gets called from interrupt level.
+ *
+ *      LOCKING:
+ *      Inherited from caller.  This is coded to safe to call at
+ *      interrupt level, i.e. it does not sleep.
+ */
 static void mv_phy_reset(struct ata_port *ap)
 {
 	void __iomem *port_mmio = mv_ap_base(ap);
 	struct ata_taskfile tf;
 	struct ata_device *dev = &ap->device[0];
-	u32 edma = 0, bdma;
+	unsigned long timeout;
 
 	VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
 
-	edma = readl(port_mmio + EDMA_CMD_OFS);
-	if (EDMA_EN & edma) {
-		/* disable EDMA if active */
-		edma &= ~EDMA_EN;
-		writelfl(edma | EDMA_DS, port_mmio + EDMA_CMD_OFS);
-		udelay(1);
-	} else if (mv_port_bdma_capable(ap) &&
-		   (bdma = readl(port_mmio + BDMA_CMD_OFS)) & BDMA_START) {
-		/* disable BDMA if active */
-		writelfl(bdma & ~BDMA_START, port_mmio + BDMA_CMD_OFS);
-	}
+	mv_stop_dma(ap);
 
-	writelfl(edma | ATA_RST, port_mmio + EDMA_CMD_OFS);
+	writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
 	udelay(25);		/* allow reset propagation */
 
 	/* Spec never mentions clearing the bit.  Marvell's driver does
 	 * clear the bit, however.
 	 */
-	writelfl(edma & ~ATA_RST, port_mmio + EDMA_CMD_OFS);
+	writelfl(0, port_mmio + EDMA_CMD_OFS);
 
-	VPRINTK("Done.  Now calling __sata_phy_reset()\n");
+	VPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
 
 	/* proceed to init communications via the scr_control reg */
-	__sata_phy_reset(ap);
+	scr_write_flush(ap, SCR_CONTROL, 0x301);
+	mdelay(1);
+	scr_write_flush(ap, SCR_CONTROL, 0x300);
+	timeout = jiffies + (HZ * 1);
+	do {
+		mdelay(10);
+		if ((scr_read(ap, SCR_STATUS) & 0xf) != 1)
+			break;
+	} while (time_before(jiffies, timeout));
 
-	if (ap->flags & ATA_FLAG_PORT_DISABLED) {
-		VPRINTK("Port disabled pre-sig.  Exiting.\n");
+	VPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+	if (sata_dev_present(ap)) {
+		ata_port_probe(ap);
+	} else {
+		printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+		       ap->id, scr_read(ap, SCR_STATUS));
+		ata_port_disable(ap);
 		return;
 	}
+	ap->cbl = ATA_CBL_SATA;
 
 	tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
 	tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
@@ -636,37 +1256,118 @@
 	VPRINTK("EXIT\n");
 }
 
-static void mv_port_init(struct ata_ioports *port, unsigned long base)
+/**
+ *      mv_eng_timeout - Routine called by libata when SCSI times out I/O
+ *      @ap: ATA channel to manipulate
+ *
+ *      Intent is to clear all pending error conditions, reset the
+ *      chip/bus, fail the command, and move on.
+ *
+ *      LOCKING:
+ *      This routine holds the host_set lock while failing the command.
+ */
+static void mv_eng_timeout(struct ata_port *ap)
 {
-	/* PIO related setup */
-	port->data_addr = base + SHD_PIO_DATA_OFS;
-	port->error_addr = port->feature_addr = base + SHD_FEA_ERR_OFS;
-	port->nsect_addr = base + SHD_SECT_CNT_OFS;
-	port->lbal_addr = base + SHD_LBA_L_OFS;
-	port->lbam_addr = base + SHD_LBA_M_OFS;
-	port->lbah_addr = base + SHD_LBA_H_OFS;
-	port->device_addr = base + SHD_DEV_HD_OFS;
-	port->status_addr = port->command_addr = base + SHD_CMD_STA_OFS;
-	port->altstatus_addr = port->ctl_addr = base + SHD_CTL_AST_OFS;
-	/* unused */
-	port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
 
-	/* unmask all EDMA error interrupts */
-	writel(~0, (void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS);
+	printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+	DPRINTK("All regs @ start of eng_timeout\n");
+	mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, 
+			 to_pci_dev(ap->host_set->dev));
 
-	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 
-		readl((void __iomem *)base + EDMA_CFG_OFS),
-		readl((void __iomem *)base + EDMA_ERR_IRQ_CAUSE_OFS),
-		readl((void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS));
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
+	       ap->host_set->mmio_base, ap, qc, qc->scsicmd, 
+	       &qc->scsicmd->cmnd);
+
+	mv_err_intr(ap);
+	mv_phy_reset(ap);
+
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+	} else {
+		/* hack alert!  We cannot use the supplied completion
+	 	 * function from inside the ->eh_strategy_handler() thread.
+	 	 * libata is the only user of ->eh_strategy_handler() in
+	 	 * any kernel, so the default scsi_done() assumes it is
+	 	 * not being called from the SCSI EH.
+	 	 */
+		spin_lock_irqsave(&ap->host_set->lock, flags);
+		qc->scsidone = scsi_finish_command;
+		ata_qc_complete(qc, AC_ERR_OTHER);
+		spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	}
 }
 
+/**
+ *      mv_port_init - Perform some early initialization on a single port.
+ *      @port: libata data structure storing shadow register addresses
+ *      @port_mmio: base address of the port
+ *
+ *      Initialize shadow register mmio addresses, clear outstanding
+ *      interrupts on the port, and unmask interrupts for the future
+ *      start of the port.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
+{
+	unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
+	unsigned serr_ofs;
+
+	/* PIO related setup 
+	 */
+	port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
+	port->error_addr = 
+		port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
+	port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
+	port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
+	port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
+	port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
+	port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
+	port->status_addr = 
+		port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
+	/* special case: control/altstatus doesn't have ATA_REG_ address */
+	port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
+
+	/* unused: */
+	port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
+
+	/* Clear any currently outstanding port interrupt conditions */
+	serr_ofs = mv_scr_offset(SCR_ERROR);
+	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);
+
+	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 
+		readl(port_mmio + EDMA_CFG_OFS),
+		readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
+		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
+}
+
+/**
+ *      mv_host_init - Perform some early initialization of the host.
+ *      @probe_ent: early data struct representing the host
+ *
+ *      If possible, do an early global reset of the host.  Then do
+ *      our port init and clear/unmask all/relevant host interrupts.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
 static int mv_host_init(struct ata_probe_ent *probe_ent)
 {
 	int rc = 0, n_hc, port, hc;
 	void __iomem *mmio = probe_ent->mmio_base;
 	void __iomem *port_mmio;
 
-	if (mv_master_reset(probe_ent->mmio_base)) {
+	if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) && 
+	    mv_global_soft_reset(probe_ent->mmio_base)) {
 		rc = 1;
 		goto done;
 	}
@@ -676,17 +1377,27 @@
 
 	for (port = 0; port < probe_ent->n_ports; port++) {
 		port_mmio = mv_port_base(mmio, port);
-		mv_port_init(&probe_ent->port[port], (unsigned long)port_mmio);
+		mv_port_init(&probe_ent->port[port], port_mmio);
 	}
 
 	for (hc = 0; hc < n_hc; hc++) {
-		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause=0x%08x\n", hc,
-			readl(mv_hc_base(mmio, hc) + HC_CFG_OFS),
-			readl(mv_hc_base(mmio, hc) + HC_IRQ_CAUSE_OFS));
+		void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+
+		VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
+			"(before clear)=0x%08x\n", hc,
+			readl(hc_mmio + HC_CFG_OFS),
+			readl(hc_mmio + HC_IRQ_CAUSE_OFS));
+
+		/* Clear any currently outstanding hc interrupt conditions */
+		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
 	}
 
-	writel(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
-	writel(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+	/* Clear any currently outstanding host interrupt conditions */
+	writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+	/* and unmask interrupt generation for host regs */
+	writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+	writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
 
 	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
 		"PCI int cause/mask=0x%08x/0x%08x\n", 
@@ -694,11 +1405,53 @@
 		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
 		readl(mmio + PCI_IRQ_CAUSE_OFS),
 		readl(mmio + PCI_IRQ_MASK_OFS));
-
- done:
+done:
 	return rc;
 }
 
+/**
+ *      mv_print_info - Dump key info to kernel log for perusal.
+ *      @probe_ent: early data struct representing the host
+ *
+ *      FIXME: complete this.
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static void mv_print_info(struct ata_probe_ent *probe_ent)
+{
+	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+	struct mv_host_priv *hpriv = probe_ent->private_data;
+	u8 rev_id, scc;
+	const char *scc_s;
+
+	/* Use this to determine the HW stepping of the chip so we know
+	 * what errata to workaround
+	 */
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+	pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
+	if (scc == 0)
+		scc_s = "SCSI";
+	else if (scc == 0x01)
+		scc_s = "RAID";
+	else
+		scc_s = "unknown";
+
+	dev_printk(KERN_INFO, &pdev->dev,
+	       "%u slots %u ports %s mode IRQ via %s\n",
+	       (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports, 
+	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+}
+
+/**
+ *      mv_init_one - handle a positive probe of a Marvell host
+ *      @pdev: PCI device found
+ *      @ent: PCI device ID entry for the matched host
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version = 0;
@@ -706,15 +1459,10 @@
 	struct mv_host_priv *hpriv;
 	unsigned int board_idx = (unsigned int)ent->driver_data;
 	void __iomem *mmio_base;
-	int pci_dev_busy = 0;
-	int rc;
+	int pci_dev_busy = 0, rc;
 
-	if (!printed_version++) {
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
-	}
-
-	VPRINTK("ENTER for PCI Bus:Slot.Func=%u:%u.%u\n", pdev->bus->number,
-		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+	if (!printed_version++)
+		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
 
 	rc = pci_enable_device(pdev);
 	if (rc) {
@@ -727,8 +1475,6 @@
 		goto err_out;
 	}
 
-	pci_intx(pdev, 1);
-
 	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (probe_ent == NULL) {
 		rc = -ENOMEM;
@@ -739,8 +1485,7 @@
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = ioremap_nocache(pci_resource_start(pdev, MV_PRIMARY_BAR),
-				    pci_resource_len(pdev, MV_PRIMARY_BAR));
+	mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
@@ -769,37 +1514,40 @@
 	if (rc) {
 		goto err_out_hpriv;
 	}
-/* 	mv_print_info(probe_ent); */
 
-	{
-		int b, w;
-		u32 dw[4];	/* hold a line of 16b */
-		VPRINTK("PCI config space:\n");
-		for (b = 0; b < 0x40; ) {
-			for (w = 0; w < 4; w++) {
-				(void) pci_read_config_dword(pdev,b,&dw[w]);
-				b += sizeof(*dw);
-			}
-			VPRINTK("%08x %08x %08x %08x\n",
-				dw[0],dw[1],dw[2],dw[3]);
-		}
+	/* Enable interrupts */
+	if (pci_enable_msi(pdev) == 0) {
+		hpriv->hp_flags |= MV_HP_FLAG_MSI;
+	} else {
+		pci_intx(pdev, 1);
 	}
 
-	/* FIXME: check ata_device_add return value */
-	ata_device_add(probe_ent);
-	kfree(probe_ent);
+	mv_dump_pci_cfg(pdev, 0x68);
+	mv_print_info(probe_ent);
 
+	if (ata_device_add(probe_ent) == 0) {
+		rc = -ENODEV;		/* No devices discovered */
+		goto err_out_dev_add;
+	}
+
+	kfree(probe_ent);
 	return 0;
 
- err_out_hpriv:
+err_out_dev_add:
+	if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
+		pci_disable_msi(pdev);
+	} else {
+		pci_intx(pdev, 0);
+	}
+err_out_hpriv:
 	kfree(hpriv);
- err_out_iounmap:
-	iounmap(mmio_base);
- err_out_free_ent:
+err_out_iounmap:
+	pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
 	kfree(probe_ent);
- err_out_regions:
+err_out_regions:
 	pci_release_regions(pdev);
- err_out:
+err_out:
 	if (!pci_dev_busy) {
 		pci_disable_device(pdev);
 	}
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index cb832b0..d573888 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -61,6 +61,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -238,7 +239,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations nv_ops = {
+static const struct ata_port_operations nv_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -331,7 +332,7 @@
 		return 0xffffffffU;
 
 	if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-		return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+		return readl((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
 	else
 		return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
@@ -345,7 +346,7 @@
 		return;
 
 	if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-		writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+		writel(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
 	else
 		outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
@@ -383,7 +384,7 @@
 			return -ENODEV;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	rc = pci_enable_device(pdev);
 	if (rc)
@@ -405,7 +406,7 @@
 	rc = -ENOMEM;
 
 	ppi = &nv_port_info;
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
 		goto err_out_regions;
 
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 538ad72..b41c977 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -87,8 +88,8 @@
 static void pdc_pata_phy_reset(struct ata_port *ap);
 static void pdc_sata_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_irq_clear(struct ata_port *ap);
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
@@ -113,7 +114,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations pdc_sata_ops = {
+static const struct ata_port_operations pdc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
 	.tf_read		= ata_tf_read,
@@ -136,7 +137,7 @@
 	.host_stop		= ata_pci_host_stop,
 };
 
-static struct ata_port_operations pdc_pata_ops = {
+static const struct ata_port_operations pdc_pata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
 	.tf_read		= ata_tf_read,
@@ -195,6 +196,8 @@
 static struct pci_device_id pdc_ata_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -207,6 +210,8 @@
 	  board_2037x },
 	{ PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
 
 	{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20319 },
@@ -324,7 +329,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -333,7 +338,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void pdc_qc_prep(struct ata_queued_cmd *qc)
@@ -395,7 +400,8 @@
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+		drv_stat = ata_wait_idle(ap);
+		ata_qc_complete(qc, __ac_err_mask(drv_stat));
 		break;
 
 	default:
@@ -404,7 +410,7 @@
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 
-		ata_qc_complete(qc, drv_stat);
+		ata_qc_complete(qc, ac_err_mask(drv_stat));
 		break;
 	}
 
@@ -416,33 +422,30 @@
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
-	u8 status;
-	unsigned int handled = 0, have_err = 0;
+	unsigned int handled = 0, err_mask = 0;
 	u32 tmp;
 	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
 	tmp = readl(mmio);
 	if (tmp & PDC_ERR_MASK) {
-		have_err = 1;
+		err_mask = AC_ERR_DEV;
 		pdc_reset_port(ap);
 	}
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
-		status = ata_wait_idle(ap);
-		if (have_err)
-			status |= ATA_ERR;
-		ata_qc_complete(qc, status);
+		err_mask |= ac_err_mask(ata_wait_idle(ap));
+		ata_qc_complete(qc, err_mask);
 		handled = 1;
 		break;
 
         default:
-                ap->stats.idle_irq++;
-                break;
+		ap->stats.idle_irq++;
+		break;
         }
 
-        return handled;
+	return handled;
 }
 
 static void pdc_irq_clear(struct ata_port *ap)
@@ -523,8 +526,8 @@
 
 	pp->pkt[2] = seq;
 	wmb();			/* flush PRD, pkt writes */
-	writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-	readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+	writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+	readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
 }
 
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
@@ -546,7 +549,7 @@
 	return ata_qc_issue_prot(qc);
 }
 
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+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_NODATA);
@@ -554,7 +557,7 @@
 }
 
 
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *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_NODATA);
@@ -631,7 +634,7 @@
 	int rc;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	/*
 	 * If this driver happens to only be useful on Apple's K2, then
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index ffcdeb6..9938dae 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <asm/io.h>
@@ -51,8 +52,6 @@
 	QS_PRD_BYTES		= QS_MAX_PRD * 16,
 	QS_PKT_BYTES		= QS_CPB_BYTES + QS_PRD_BYTES,
 
-	QS_DMA_BOUNDARY		= ~0UL,
-
 	/* global register offsets */
 	QS_HCF_CNFG3		= 0x0003, /* host configuration offset */
 	QS_HID_HPHY		= 0x0004, /* host physical interface info */
@@ -101,6 +100,10 @@
 	board_2068_idx		= 0,	/* QStor 4-port SATA/RAID */
 };
 
+enum {
+	QS_DMA_BOUNDARY		= ~0UL
+};
+
 typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
 
 struct qs_port_priv {
@@ -145,7 +148,7 @@
 	.bios_param		= ata_std_bios_param,
 };
 
-static struct ata_port_operations qs_ata_ops = {
+static const struct ata_port_operations qs_ata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -398,11 +401,12 @@
 				qc = ata_qc_from_tag(ap, ap->active_tag);
 				if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 					switch (sHST) {
-					case 0: /* sucessful CPB */
+					case 0: /* successful CPB */
 					case 3: /* device error */
 						pp->state = qs_state_idle;
 						qs_enter_reg_mode(qc->ap);
-						ata_qc_complete(qc, sDST);
+						ata_qc_complete(qc,
+							ac_err_mask(sDST));
 						break;
 					default:
 						break;
@@ -431,7 +435,7 @@
 			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
 
 				/* check main status, clearing INTRQ */
-				u8 status = ata_chk_status(ap);
+				u8 status = ata_check_status(ap);
 				if ((status & ATA_BUSY))
 					continue;
 				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
@@ -439,7 +443,7 @@
 
 				/* complete taskfile transaction */
 				pp->state = qs_state_idle;
-				ata_qc_complete(qc, status);
+				ata_qc_complete(qc, ac_err_mask(status));
 				handled = 1;
 			}
 		}
@@ -597,25 +601,22 @@
 		if (rc) {
 			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 			if (rc) {
-				printk(KERN_ERR DRV_NAME
-					"(%s): 64-bit DMA enable failed\n",
-					pci_name(pdev));
+				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) {
-			printk(KERN_ERR DRV_NAME
-				"(%s): 32-bit DMA enable failed\n",
-				pci_name(pdev));
+			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) {
-			printk(KERN_ERR DRV_NAME
-				"(%s): 32-bit consistent DMA enable failed\n",
-				pci_name(pdev));
+			dev_printk(KERN_ERR, &pdev->dev,
+				"32-bit consistent DMA enable failed\n");
 			return rc;
 		}
 	}
@@ -632,7 +633,7 @@
 	int rc, port_no;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	rc = pci_enable_device(pdev);
 	if (rc)
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index ba98a17..435f7e0 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -41,6 +41,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -150,7 +151,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations sil_ops = {
+static const struct ata_port_operations sil_ops = {
 	.port_disable		= ata_port_disable,
 	.dev_config		= sil_dev_config,
 	.tf_load		= ata_tf_load,
@@ -289,7 +290,7 @@
 
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
-	void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+	void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		return readl(mmio);
 	return 0xffffffffU;
@@ -297,7 +298,7 @@
 
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
-	void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+	void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		writel(val, mmio);
 }
@@ -386,7 +387,7 @@
 	u8 cls;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	/*
 	 * If this driver happens to only be useful on Apple's K2, then
@@ -463,8 +464,8 @@
 			writeb(cls, mmio_base + SIL_FIFO_W3);
 		}
 	} else
-		printk(KERN_WARNING DRV_NAME "(%s): cache line size not set.  Driver may not function\n",
-			pci_name(pdev));
+		dev_printk(KERN_WARNING, &pdev->dev,
+			 "cache line size not set.  Driver may not function\n");
 
 	if (ent->driver_data == sil_3114) {
 		irq_mask = SIL_MASK_4PORT;
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
new file mode 100644
index 0000000..c665480
--- /dev/null
+++ b/drivers/scsi/sata_sil24.c
@@ -0,0 +1,871 @@
+/*
+ * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
+ *
+ * Copyright 2005  Tejun Heo
+ *
+ * Based on preview driver from Silicon Image.
+ *
+ * NOTE: No NCQ/ATAPI support yet.  The preview driver didn't support
+ * NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make
+ * those work.  Enabling those shouldn't be difficult.  Basic
+ * structure is all there (in libata-dev tree).  If you have any
+ * information about this hardware, please contact me or linux-ide.
+ * Info is needed on...
+ *
+ * - How to issue tagged commands and turn on sactive on issue accordingly.
+ * - Where to put an ATAPI command and how to tell the device to send it.
+ * - How to enable/use 64bit.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <scsi/scsi_host.h>
+#include "scsi.h"
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME	"sata_sil24"
+#define DRV_VERSION	"0.22"	/* Silicon Image's preview driver was 0.10 */
+
+/*
+ * Port request block (PRB) 32 bytes
+ */
+struct sil24_prb {
+	u16	ctrl;
+	u16	prot;
+	u32	rx_cnt;
+	u8	fis[6 * 4];
+};
+
+/*
+ * Scatter gather entry (SGE) 16 bytes
+ */
+struct sil24_sge {
+	u64	addr;
+	u32	cnt;
+	u32	flags;
+};
+
+/*
+ * Port multiplier
+ */
+struct sil24_port_multiplier {
+	u32	diag;
+	u32	sactive;
+};
+
+enum {
+	/*
+	 * Global controller registers (128 bytes @ BAR0)
+	 */
+		/* 32 bit regs */
+	HOST_SLOT_STAT		= 0x00, /* 32 bit slot stat * 4 */
+	HOST_CTRL		= 0x40,
+	HOST_IRQ_STAT		= 0x44,
+	HOST_PHY_CFG		= 0x48,
+	HOST_BIST_CTRL		= 0x50,
+	HOST_BIST_PTRN		= 0x54,
+	HOST_BIST_STAT		= 0x58,
+	HOST_MEM_BIST_STAT	= 0x5c,
+	HOST_FLASH_CMD		= 0x70,
+		/* 8 bit regs */
+	HOST_FLASH_DATA		= 0x74,
+	HOST_TRANSITION_DETECT	= 0x75,
+	HOST_GPIO_CTRL		= 0x76,
+	HOST_I2C_ADDR		= 0x78, /* 32 bit */
+	HOST_I2C_DATA		= 0x7c,
+	HOST_I2C_XFER_CNT	= 0x7e,
+	HOST_I2C_CTRL		= 0x7f,
+
+	/* HOST_SLOT_STAT bits */
+	HOST_SSTAT_ATTN		= (1 << 31),
+
+	/*
+	 * Port registers
+	 * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
+	 */
+	PORT_REGS_SIZE		= 0x2000,
+	PORT_PRB		= 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
+
+	PORT_PM			= 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
+		/* 32 bit regs */
+	PORT_CTRL_STAT		= 0x1000, /* write: ctrl-set, read: stat */
+	PORT_CTRL_CLR		= 0x1004, /* write: ctrl-clear */
+	PORT_IRQ_STAT		= 0x1008, /* high: status, low: interrupt */
+	PORT_IRQ_ENABLE_SET	= 0x1010, /* write: enable-set */
+	PORT_IRQ_ENABLE_CLR	= 0x1014, /* write: enable-clear */
+	PORT_ACTIVATE_UPPER_ADDR= 0x101c,
+	PORT_EXEC_FIFO		= 0x1020, /* command execution fifo */
+	PORT_CMD_ERR		= 0x1024, /* command error number */
+	PORT_FIS_CFG		= 0x1028,
+	PORT_FIFO_THRES		= 0x102c,
+		/* 16 bit regs */
+	PORT_DECODE_ERR_CNT	= 0x1040,
+	PORT_DECODE_ERR_THRESH	= 0x1042,
+	PORT_CRC_ERR_CNT	= 0x1044,
+	PORT_CRC_ERR_THRESH	= 0x1046,
+	PORT_HSHK_ERR_CNT	= 0x1048,
+	PORT_HSHK_ERR_THRESH	= 0x104a,
+		/* 32 bit regs */
+	PORT_PHY_CFG		= 0x1050,
+	PORT_SLOT_STAT		= 0x1800,
+	PORT_CMD_ACTIVATE	= 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
+	PORT_EXEC_DIAG		= 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
+	PORT_PSD_DIAG		= 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
+	PORT_SCONTROL		= 0x1f00,
+	PORT_SSTATUS		= 0x1f04,
+	PORT_SERROR		= 0x1f08,
+	PORT_SACTIVE		= 0x1f0c,
+
+	/* PORT_CTRL_STAT bits */
+	PORT_CS_PORT_RST	= (1 << 0), /* port reset */
+	PORT_CS_DEV_RST		= (1 << 1), /* device reset */
+	PORT_CS_INIT		= (1 << 2), /* port initialize */
+	PORT_CS_IRQ_WOC		= (1 << 3), /* interrupt write one to clear */
+	PORT_CS_RESUME		= (1 << 6), /* port resume */
+	PORT_CS_32BIT_ACTV	= (1 << 10), /* 32-bit activation */
+	PORT_CS_PM_EN		= (1 << 13), /* port multiplier enable */
+	PORT_CS_RDY		= (1 << 31), /* port ready to accept commands */
+
+	/* PORT_IRQ_STAT/ENABLE_SET/CLR */
+	/* bits[11:0] are masked */
+	PORT_IRQ_COMPLETE	= (1 << 0), /* command(s) completed */
+	PORT_IRQ_ERROR		= (1 << 1), /* command execution error */
+	PORT_IRQ_PORTRDY_CHG	= (1 << 2), /* port ready change */
+	PORT_IRQ_PWR_CHG	= (1 << 3), /* power management change */
+	PORT_IRQ_PHYRDY_CHG	= (1 << 4), /* PHY ready change */
+	PORT_IRQ_COMWAKE	= (1 << 5), /* COMWAKE received */
+	PORT_IRQ_UNK_FIS	= (1 << 6), /* Unknown FIS received */
+	PORT_IRQ_SDB_FIS	= (1 << 11), /* SDB FIS received */
+
+	/* bits[27:16] are unmasked (raw) */
+	PORT_IRQ_RAW_SHIFT	= 16,
+	PORT_IRQ_MASKED_MASK	= 0x7ff,
+	PORT_IRQ_RAW_MASK	= (0x7ff << PORT_IRQ_RAW_SHIFT),
+
+	/* ENABLE_SET/CLR specific, intr steering - 2 bit field */
+	PORT_IRQ_STEER_SHIFT	= 30,
+	PORT_IRQ_STEER_MASK	= (3 << PORT_IRQ_STEER_SHIFT),
+
+	/* PORT_CMD_ERR constants */
+	PORT_CERR_DEV		= 1, /* Error bit in D2H Register FIS */
+	PORT_CERR_SDB		= 2, /* Error bit in SDB FIS */
+	PORT_CERR_DATA		= 3, /* Error in data FIS not detected by dev */
+	PORT_CERR_SEND		= 4, /* Initial cmd FIS transmission failure */
+	PORT_CERR_INCONSISTENT	= 5, /* Protocol mismatch */
+	PORT_CERR_DIRECTION	= 6, /* Data direction mismatch */
+	PORT_CERR_UNDERRUN	= 7, /* Ran out of SGEs while writing */
+	PORT_CERR_OVERRUN	= 8, /* Ran out of SGEs while reading */
+	PORT_CERR_PKT_PROT	= 11, /* DIR invalid in 1st PIO setup of ATAPI */
+	PORT_CERR_SGT_BOUNDARY	= 16, /* PLD ecode 00 - SGT not on qword boundary */
+	PORT_CERR_SGT_TGTABRT	= 17, /* PLD ecode 01 - target abort */
+	PORT_CERR_SGT_MSTABRT	= 18, /* PLD ecode 10 - master abort */
+	PORT_CERR_SGT_PCIPERR	= 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
+	PORT_CERR_CMD_BOUNDARY	= 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
+	PORT_CERR_CMD_TGTABRT	= 25, /* ctrl[15:13] 010 - target abort */
+	PORT_CERR_CMD_MSTABRT	= 26, /* ctrl[15:13] 100 - master abort */
+	PORT_CERR_CMD_PCIPERR	= 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
+	PORT_CERR_XFR_UNDEF	= 32, /* PSD ecode 00 - undefined */
+	PORT_CERR_XFR_TGTABRT	= 33, /* PSD ecode 01 - target abort */
+	PORT_CERR_XFR_MSGABRT	= 34, /* PSD ecode 10 - master abort */
+	PORT_CERR_XFR_PCIPERR	= 35, /* PSD ecode 11 - PCI prity err during transfer */
+	PORT_CERR_SENDSERVICE	= 36, /* FIS received while sending service */
+
+	/*
+	 * Other constants
+	 */
+	SGE_TRM			= (1 << 31), /* Last SGE in chain */
+	PRB_SOFT_RST		= (1 << 7),  /* Soft reset request (ign BSY?) */
+
+	/* board id */
+	BID_SIL3124		= 0,
+	BID_SIL3132		= 1,
+	BID_SIL3131		= 2,
+
+	IRQ_STAT_4PORTS		= 0xf,
+};
+
+struct sil24_cmd_block {
+	struct sil24_prb prb;
+	struct sil24_sge sge[LIBATA_MAX_PRD];
+};
+
+/*
+ * ap->private_data
+ *
+ * The preview driver always returned 0 for status.  We emulate it
+ * here from the previous interrupt.
+ */
+struct sil24_port_priv {
+	struct sil24_cmd_block *cmd_block;	/* 32 cmd blocks */
+	dma_addr_t cmd_block_dma;		/* DMA base addr for them */
+	struct ata_taskfile tf;			/* Cached taskfile registers */
+};
+
+/* ap->host_set->private_data */
+struct sil24_host_priv {
+	void __iomem *host_base;	/* global controller control (128 bytes @BAR0) */
+	void __iomem *port_base;	/* port registers (4 * 8192 bytes @BAR2) */
+};
+
+static u8 sil24_check_status(struct ata_port *ap);
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void sil24_phy_reset(struct ata_port *ap);
+static void sil24_qc_prep(struct ata_queued_cmd *qc);
+static int sil24_qc_issue(struct ata_queued_cmd *qc);
+static void sil24_irq_clear(struct ata_port *ap);
+static void sil24_eng_timeout(struct ata_port *ap);
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int sil24_port_start(struct ata_port *ap);
+static void sil24_port_stop(struct ata_port *ap);
+static void sil24_host_stop(struct ata_host_set *host_set);
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static struct pci_device_id sil24_pci_tbl[] = {
+	{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+	{ 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
+	{ 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+	{ 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+	{ } /* terminate list */
+};
+
+static struct pci_driver sil24_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= sil24_pci_tbl,
+	.probe			= sil24_init_one,
+	.remove			= ata_pci_remove_one, /* safe? */
+};
+
+static Scsi_Host_Template sil24_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.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,
+	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1, /* NCQ not supported yet */
+};
+
+static const struct ata_port_operations sil24_ops = {
+	.port_disable		= ata_port_disable,
+
+	.check_status		= sil24_check_status,
+	.check_altstatus	= sil24_check_status,
+	.dev_select		= ata_noop_dev_select,
+
+	.tf_read		= sil24_tf_read,
+
+	.phy_reset		= sil24_phy_reset,
+
+	.qc_prep		= sil24_qc_prep,
+	.qc_issue		= sil24_qc_issue,
+
+	.eng_timeout		= sil24_eng_timeout,
+
+	.irq_handler		= sil24_interrupt,
+	.irq_clear		= sil24_irq_clear,
+
+	.scr_read		= sil24_scr_read,
+	.scr_write		= sil24_scr_write,
+
+	.port_start		= sil24_port_start,
+	.port_stop		= sil24_port_stop,
+	.host_stop		= sil24_host_stop,
+};
+
+/*
+ * Use bits 30-31 of host_flags to encode available port numbers.
+ * Current maxium is 4.
+ */
+#define SIL24_NPORTS2FLAG(nports)	((((unsigned)(nports) - 1) & 0x3) << 30)
+#define SIL24_FLAG2NPORTS(flag)		((((flag) >> 30) & 0x3) + 1)
+
+static struct ata_port_info sil24_port_info[] = {
+	/* sil_3124 */
+	{
+		.sht		= &sil24_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil24_ops,
+	},
+	/* sil_3132 */ 
+	{
+		.sht		= &sil24_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil24_ops,
+	},
+	/* sil_3131/sil_3531 */
+	{
+		.sht		= &sil24_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil24_ops,
+	},
+};
+
+static inline void sil24_update_tf(struct ata_port *ap)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	struct sil24_prb __iomem *prb = port;
+	u8 fis[6 * 4];
+
+	memcpy_fromio(fis, prb->fis, 6 * 4);
+	ata_tf_from_fis(fis, &pp->tf);
+}
+
+static u8 sil24_check_status(struct ata_port *ap)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	return pp->tf.command;
+}
+
+static int sil24_scr_map[] = {
+	[SCR_CONTROL]	= 0,
+	[SCR_STATUS]	= 1,
+	[SCR_ERROR]	= 2,
+	[SCR_ACTIVE]	= 3,
+};
+
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
+{
+	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+		void __iomem *addr;
+		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+		return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
+	}
+	return 0xffffffffU;
+}
+
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+{
+	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+		void __iomem *addr;
+		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+		writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
+	}
+}
+
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	*tf = pp->tf;
+}
+
+static void sil24_phy_reset(struct ata_port *ap)
+{
+	__sata_phy_reset(ap);
+	/*
+	 * No ATAPI yet.  Just unconditionally indicate ATA device.
+	 * If ATAPI device is attached, it will fail ATA_CMD_ID_ATA
+	 * and libata core will ignore the device.
+	 */
+	if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+		ap->device[0].class = ATA_DEV_ATA;
+}
+
+static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+				 struct sil24_cmd_block *cb)
+{
+	struct scatterlist *sg = qc->sg;
+	struct sil24_sge *sge = cb->sge;
+	unsigned i;
+
+	for (i = 0; i < qc->n_elem; i++, sg++, sge++) {
+		sge->addr = cpu_to_le64(sg_dma_address(sg));
+		sge->cnt = cpu_to_le32(sg_dma_len(sg));
+		sge->flags = 0;
+		sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM);
+	}
+}
+
+static void sil24_qc_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct sil24_port_priv *pp = ap->private_data;
+	struct sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+	struct sil24_prb *prb = &cb->prb;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+	case ATA_PROT_DMA:
+	case ATA_PROT_NODATA:
+		break;
+	default:
+		/* ATAPI isn't supported yet */
+		BUG();
+	}
+
+	ata_tf_to_fis(&qc->tf, prb->fis, 0);
+
+	if (qc->flags & ATA_QCFLAG_DMAMAP)
+		sil24_fill_sg(qc, cb);
+}
+
+static int sil24_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	struct sil24_port_priv *pp = ap->private_data;
+	dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+
+	writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+	return 0;
+}
+
+static void sil24_irq_clear(struct ata_port *ap)
+{
+	/* unused */
+}
+
+static int __sil24_reset_controller(void __iomem *port)
+{
+	int cnt;
+	u32 tmp;
+
+	/* Reset controller state.  Is this correct? */
+	writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+	readl(port + PORT_CTRL_STAT);	/* sync */
+
+	/* Max ~100ms */
+	for (cnt = 0; cnt < 1000; cnt++) {
+		udelay(100);
+		tmp = readl(port + PORT_CTRL_STAT);
+		if (!(tmp & PORT_CS_DEV_RST))
+			break;
+	}
+
+	if (tmp & PORT_CS_DEV_RST)
+		return -1;
+	return 0;
+}
+
+static void sil24_reset_controller(struct ata_port *ap)
+{
+	printk(KERN_NOTICE DRV_NAME
+	       " ata%u: resetting controller...\n", ap->id);
+	if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
+                printk(KERN_ERR DRV_NAME
+                       " ata%u: failed to reset controller\n", ap->id);
+}
+
+static void sil24_eng_timeout(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+		return;
+	}
+
+	/*
+	 * hack alert!  We cannot use the supplied completion
+	 * function from inside the ->eh_strategy_handler() thread.
+	 * libata is the only user of ->eh_strategy_handler() in
+	 * any kernel, so the default scsi_done() assumes it is
+	 * not being called from the SCSI EH.
+	 */
+	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+	qc->scsidone = scsi_finish_command;
+	ata_qc_complete(qc, AC_ERR_OTHER);
+
+	sil24_reset_controller(ap);
+}
+
+static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	struct sil24_port_priv *pp = ap->private_data;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	u32 irq_stat, cmd_err, sstatus, serror;
+	unsigned int err_mask;
+
+	irq_stat = readl(port + PORT_IRQ_STAT);
+	writel(irq_stat, port + PORT_IRQ_STAT);		/* clear irq */
+
+	if (!(irq_stat & PORT_IRQ_ERROR)) {
+		/* ignore non-completion, non-error irqs for now */
+		printk(KERN_WARNING DRV_NAME
+		       "ata%u: non-error exception irq (irq_stat %x)\n",
+		       ap->id, irq_stat);
+		return;
+	}
+
+	cmd_err = readl(port + PORT_CMD_ERR);
+	sstatus = readl(port + PORT_SSTATUS);
+	serror = readl(port + PORT_SERROR);
+	if (serror)
+		writel(serror, port + PORT_SERROR);
+
+	printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n"
+	       "  stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
+	       ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
+
+	if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
+		/*
+		 * Device is reporting error, tf registers are valid.
+		 */
+		sil24_update_tf(ap);
+		err_mask = ac_err_mask(pp->tf.command);
+	} else {
+		/*
+		 * Other errors.  libata currently doesn't have any
+		 * mechanism to report these errors.  Just turn on
+		 * ATA_ERR.
+		 */
+		err_mask = AC_ERR_OTHER;
+	}
+
+	if (qc)
+		ata_qc_complete(qc, err_mask);
+
+	sil24_reset_controller(ap);
+}
+
+static inline void sil24_host_intr(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	u32 slot_stat;
+
+	slot_stat = readl(port + PORT_SLOT_STAT);
+	if (!(slot_stat & HOST_SSTAT_ATTN)) {
+		struct sil24_port_priv *pp = ap->private_data;
+		/*
+		 * !HOST_SSAT_ATTN guarantees successful completion,
+		 * so reading back tf registers is unnecessary for
+		 * most commands.  TODO: read tf registers for
+		 * commands which require these values on successful
+		 * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
+		 * DEVICE RESET and READ PORT MULTIPLIER (any more?).
+		 */
+		sil24_update_tf(ap);
+
+		if (qc)
+			ata_qc_complete(qc, ac_err_mask(pp->tf.command));
+	} else
+		sil24_error_intr(ap, slot_stat);
+}
+
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	struct sil24_host_priv *hpriv = host_set->private_data;
+	unsigned handled = 0;
+	u32 status;
+	int i;
+
+	status = readl(hpriv->host_base + HOST_IRQ_STAT);
+
+	if (status == 0xffffffff) {
+		printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
+		       "PCI fault or device removal?\n");
+		goto out;
+	}
+
+	if (!(status & IRQ_STAT_4PORTS))
+		goto out;
+
+	spin_lock(&host_set->lock);
+
+	for (i = 0; i < host_set->n_ports; i++)
+		if (status & (1 << i)) {
+			struct ata_port *ap = host_set->ports[i];
+			if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
+				sil24_host_intr(host_set->ports[i]);
+				handled++;
+			} else
+				printk(KERN_ERR DRV_NAME
+				       ": interrupt from disabled port %d\n", i);
+		}
+
+	spin_unlock(&host_set->lock);
+ out:
+	return IRQ_RETVAL(handled);
+}
+
+static int sil24_port_start(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct sil24_port_priv *pp;
+	struct sil24_cmd_block *cb;
+	size_t cb_size = sizeof(*cb);
+	dma_addr_t cb_dma;
+
+	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+	memset(pp, 0, sizeof(*pp));
+
+	pp->tf.command = ATA_DRDY;
+
+	cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+	if (!cb) {
+		kfree(pp);
+		return -ENOMEM;
+	}
+	memset(cb, 0, cb_size);
+
+	pp->cmd_block = cb;
+	pp->cmd_block_dma = cb_dma;
+
+	ap->private_data = pp;
+
+	return 0;
+}
+
+static void sil24_port_stop(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct sil24_port_priv *pp = ap->private_data;
+	size_t cb_size = sizeof(*pp->cmd_block);
+
+	dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
+	kfree(pp);
+}
+
+static void sil24_host_stop(struct ata_host_set *host_set)
+{
+	struct sil24_host_priv *hpriv = host_set->private_data;
+
+	iounmap(hpriv->host_base);
+	iounmap(hpriv->port_base);
+	kfree(hpriv);
+}
+
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version = 0;
+	unsigned int board_id = (unsigned int)ent->driver_data;
+	struct ata_port_info *pinfo = &sil24_port_info[board_id];
+	struct ata_probe_ent *probe_ent = NULL;
+	struct sil24_host_priv *hpriv = NULL;
+	void __iomem *host_base = NULL;
+	void __iomem *port_base = NULL;
+	int i, rc;
+
+	if (!printed_version++)
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto out_disable;
+
+	rc = -ENOMEM;
+	/* ioremap mmio registers */
+	host_base = ioremap(pci_resource_start(pdev, 0),
+			    pci_resource_len(pdev, 0));
+	if (!host_base)
+		goto out_free;
+	port_base = ioremap(pci_resource_start(pdev, 2),
+			    pci_resource_len(pdev, 2));
+	if (!port_base)
+		goto out_free;
+
+	/* allocate & init probe_ent and hpriv */
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent)
+		goto out_free;
+
+	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		goto out_free;
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->dev = pci_dev_to_dev(pdev);
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht		= pinfo->sht;
+	probe_ent->host_flags	= pinfo->host_flags;
+	probe_ent->pio_mask	= pinfo->pio_mask;
+	probe_ent->udma_mask	= pinfo->udma_mask;
+	probe_ent->port_ops	= pinfo->port_ops;
+	probe_ent->n_ports	= SIL24_FLAG2NPORTS(pinfo->host_flags);
+
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->mmio_base = port_base;
+	probe_ent->private_data = hpriv;
+
+	memset(hpriv, 0, sizeof(*hpriv));
+	hpriv->host_base = host_base;
+	hpriv->port_base = port_base;
+
+	/*
+	 * Configure the device
+	 */
+	/*
+	 * FIXME: This device is certainly 64-bit capable.  We just
+	 * don't know how to use it.  After fixing 32bit activation in
+	 * this function, enable 64bit masks here.
+	 */
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "32-bit DMA enable failed\n");
+		goto out_free;
+	}
+	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");
+		goto out_free;
+	}
+
+	/* GPIO off */
+	writel(0, host_base + HOST_FLASH_CMD);
+
+	/* Mask interrupts during initialization */
+	writel(0, host_base + HOST_CTRL);
+
+	for (i = 0; i < probe_ent->n_ports; i++) {
+		void __iomem *port = port_base + i * PORT_REGS_SIZE;
+		unsigned long portu = (unsigned long)port;
+		u32 tmp;
+		int cnt;
+
+		probe_ent->port[i].cmd_addr = portu + PORT_PRB;
+		probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
+
+		ata_std_ports(&probe_ent->port[i]);
+
+		/* Initial PHY setting */
+		writel(0x20c, port + PORT_PHY_CFG);
+
+		/* Clear port RST */
+		tmp = readl(port + PORT_CTRL_STAT);
+		if (tmp & PORT_CS_PORT_RST) {
+			writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
+			readl(port + PORT_CTRL_STAT);	/* sync */
+			for (cnt = 0; cnt < 10; cnt++) {
+				msleep(10);
+				tmp = readl(port + PORT_CTRL_STAT);
+				if (!(tmp & PORT_CS_PORT_RST))
+					break;
+			}
+			if (tmp & PORT_CS_PORT_RST)
+				dev_printk(KERN_ERR, &pdev->dev,
+				           "failed to clear port RST\n");
+		}
+
+		/* Zero error counters. */
+		writel(0x8000, port + PORT_DECODE_ERR_THRESH);
+		writel(0x8000, port + PORT_CRC_ERR_THRESH);
+		writel(0x8000, port + PORT_HSHK_ERR_THRESH);
+		writel(0x0000, port + PORT_DECODE_ERR_CNT);
+		writel(0x0000, port + PORT_CRC_ERR_CNT);
+		writel(0x0000, port + PORT_HSHK_ERR_CNT);
+
+		/* FIXME: 32bit activation? */
+		writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
+		writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
+
+		/* Configure interrupts */
+		writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
+		writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
+		       port + PORT_IRQ_ENABLE_SET);
+
+		/* Clear interrupts */
+		writel(0x0fff0fff, port + PORT_IRQ_STAT);
+		writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+		/* Clear port multiplier enable and resume bits */
+		writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+
+		/* Reset itself */
+		if (__sil24_reset_controller(port))
+			dev_printk(KERN_ERR, &pdev->dev,
+			           "failed to reset controller\n");
+	}
+
+	/* Turn on interrupts */
+	writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+
+	pci_set_master(pdev);
+
+	/* FIXME: check ata_device_add return value */
+	ata_device_add(probe_ent);
+
+	kfree(probe_ent);
+	return 0;
+
+ out_free:
+	if (host_base)
+		iounmap(host_base);
+	if (port_base)
+		iounmap(port_base);
+	kfree(probe_ent);
+	kfree(hpriv);
+	pci_release_regions(pdev);
+ out_disable:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init sil24_init(void)
+{
+	return pci_module_init(&sil24_pci_driver);
+}
+
+static void __exit sil24_exit(void)
+{
+	pci_unregister_driver(&sil24_pci_driver);
+}
+
+MODULE_AUTHOR("Tejun Heo");
+MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
+
+module_init(sil24_init);
+module_exit(sil24_exit);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index b227e51..42288be 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -38,6 +38,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -102,7 +103,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations sis_ops = {
+static const struct ata_port_operations sis_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -237,6 +238,7 @@
 
 static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 	u32 genctl;
@@ -245,6 +247,9 @@
 	u8 pmr;
 	u8 port2_start;
 
+	if (!printed_version++)
+		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
 	rc = pci_enable_device(pdev);
 	if (rc)
 		return rc;
@@ -263,7 +268,7 @@
 		goto err_out_regions;
 
 	ppi = &sis_port_info;
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
@@ -288,16 +293,18 @@
 	pci_read_config_byte(pdev, SIS_PMR, &pmr);
 	if (ent->device != 0x182) {
 		if ((pmr & SIS_PMR_COMBINED) == 0) {
-			printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n");
+			dev_printk(KERN_INFO, &pdev->dev,
+				   "Detected SiS 180/181 chipset in SATA mode\n");
 			port2_start = 64;
 		}
 		else {
-			printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n");
+			dev_printk(KERN_INFO, &pdev->dev,
+				   "Detected SiS 180/181 chipset in combined mode\n");
 			port2_start=0;
 		}
 	}
 	else {
-		printk(KERN_INFO "sata_sis: Detected SiS 182 chipset\n");
+		dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n");
 		port2_start = 0x20;
 	}
 
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index d89d968..db615ff 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -44,6 +44,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -84,6 +85,8 @@
 /* Port stride */
 #define K2_SATA_PORT_OFFSET		0x100
 
+static u8 k2_stat_check_status(struct ata_port *ap);
+
 
 static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
@@ -102,7 +105,7 @@
 }
 
 
-static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -136,16 +139,24 @@
 static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
-	u16 nsect, lbal, lbam, lbah;
+	u16 nsect, lbal, lbam, lbah, feature;
 
-	nsect = tf->nsect = readw(ioaddr->nsect_addr);
-	lbal = tf->lbal = readw(ioaddr->lbal_addr);
-	lbam = tf->lbam = readw(ioaddr->lbam_addr);
-	lbah = tf->lbah = readw(ioaddr->lbah_addr);
+	tf->command = k2_stat_check_status(ap);
 	tf->device = readw(ioaddr->device_addr);
+	feature = readw(ioaddr->error_addr);
+	nsect = readw(ioaddr->nsect_addr);
+	lbal = readw(ioaddr->lbal_addr);
+	lbam = readw(ioaddr->lbam_addr);
+	lbah = readw(ioaddr->lbah_addr);
+
+	tf->feature = feature;
+	tf->nsect = nsect;
+	tf->lbal = lbal;
+	tf->lbam = lbam;
+	tf->lbah = lbah;
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		tf->hob_feature = readw(ioaddr->error_addr) >> 8;
+		tf->hob_feature = feature >> 8;
 		tf->hob_nsect = nsect >> 8;
 		tf->hob_lbal = lbal >> 8;
 		tf->hob_lbam = lbam >> 8;
@@ -297,7 +308,7 @@
 };
 
 
-static struct ata_port_operations k2_sata_ops = {
+static const struct ata_port_operations k2_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= k2_sata_tf_load,
 	.tf_read		= k2_sata_tf_read,
@@ -352,7 +363,7 @@
 	int i;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	/*
 	 * If this driver happens to only be useful on Apple's K2, then
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 540a851..0ec21e09 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -137,7 +138,7 @@
 };
 
 struct pdc_host_priv {
-	void			*dimm_mmio;
+	void			__iomem *dimm_mmio;
 
 	unsigned int		doing_hdma;
 	unsigned int		hdma_prod;
@@ -157,8 +158,8 @@
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
 static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
@@ -196,7 +197,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations pdc_20621_ops = {
+static const struct ata_port_operations pdc_20621_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
 	.tf_read		= ata_tf_read,
@@ -247,7 +248,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(host_set->dev);
 	struct pdc_host_priv *hpriv = host_set->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = hpriv->dimm_mmio;
 
 	pci_iounmap(pdev, dimm_mmio);
 	kfree(hpriv);
@@ -669,8 +670,8 @@
 		readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
 
 		writel(port_ofs + PDC_DIMM_ATA_PKT,
-		       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-		readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		       (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
 			port_ofs + PDC_DIMM_ATA_PKT,
 			port_ofs + PDC_DIMM_ATA_PKT,
@@ -718,7 +719,7 @@
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
-			ata_qc_complete(qc, ata_wait_idle(ap));
+			ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -747,8 +748,8 @@
 			writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
 			readl(mmio + PDC_20621_SEQCTL + (seq * 4));
 			writel(port_ofs + PDC_DIMM_ATA_PKT,
-			       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-			readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			       (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		}
 
 		/* step two - execute ATA command */
@@ -756,7 +757,7 @@
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
-			ata_qc_complete(qc, ata_wait_idle(ap));
+			ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
@@ -766,7 +767,7 @@
 
 		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
-		ata_qc_complete(qc, status);
+		ata_qc_complete(qc, ac_err_mask(status));
 		handled = 1;
 
 	} else {
@@ -881,7 +882,7 @@
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+		ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
 		break;
 
 	default:
@@ -890,7 +891,7 @@
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 
-		ata_qc_complete(qc, drv_stat);
+		ata_qc_complete(qc, ac_err_mask(drv_stat));
 		break;
 	}
 
@@ -899,7 +900,7 @@
 	DPRINTK("EXIT\n");
 }
 
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+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_NODATA);
@@ -907,7 +908,7 @@
 }
 
 
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *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_NODATA);
@@ -1014,7 +1015,7 @@
 	idx++;
 	dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
 		(long) (window_size - offset);
-	memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
+	memcpy_toio(dimm_mmio + offset / 4, psource, dist);
 	writel(0x01, mmio + PDC_GENERAL_CTLR);
 	readl(mmio + PDC_GENERAL_CTLR);
 
@@ -1023,8 +1024,7 @@
 	for (; (long) size >= (long) window_size ;) {
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_toio((char *) (dimm_mmio), (char *) psource,
-			    window_size / 4);
+		memcpy_toio(dimm_mmio, psource, window_size / 4);
 		writel(0x01, mmio + PDC_GENERAL_CTLR);
 		readl(mmio + PDC_GENERAL_CTLR);
 		psource += window_size;
@@ -1035,7 +1035,7 @@
 	if (size) {
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
+		memcpy_toio(dimm_mmio, psource, size / 4);
 		writel(0x01, mmio + PDC_GENERAL_CTLR);
 		readl(mmio + PDC_GENERAL_CTLR);
 	}
@@ -1386,7 +1386,7 @@
 	int rc;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	/*
 	 * If this driver happens to only be useful on Apple's K2, then
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 4c9fb8b..a5e245c 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -32,6 +32,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -90,7 +91,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations uli_ops = {
+static const struct ata_port_operations uli_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -178,12 +179,16 @@
 
 static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	static int printed_version;
 	struct ata_probe_ent *probe_ent;
 	struct ata_port_info *ppi;
 	int rc;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	int pci_dev_busy = 0;
 
+	if (!printed_version++)
+		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
 	rc = pci_enable_device(pdev);
 	if (rc)
 		return rc;
@@ -202,7 +207,7 @@
 		goto err_out_regions;
 
 	ppi = &uli_port_info;
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 128b996..b3ecdbe 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -41,6 +41,7 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -109,7 +110,7 @@
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations svia_sata_ops = {
+static const struct ata_port_operations svia_sata_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -212,7 +213,7 @@
 	struct ata_probe_ent *probe_ent;
 	struct ata_port_info *ppi = &svia_port_info;
 
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
 		return NULL;
 
@@ -259,15 +260,15 @@
 	u8 tmp8;
 
 	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
-	printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
-	       pci_name(pdev),
+	dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n",
 	       (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
 
 	/* make sure SATA channels are enabled */
 	pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
 	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-		printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
-		       pci_name(pdev), (int) tmp8);
+		dev_printk(KERN_DEBUG, &pdev->dev,
+			   "enabling SATA channels (0x%x)\n",
+		           (int) tmp8);
 		tmp8 |= ALL_PORTS;
 		pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
 	}
@@ -275,8 +276,9 @@
 	/* make sure interrupts for each channel sent to us */
 	pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
 	if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
-		printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
-		       pci_name(pdev), (int) tmp8);
+		dev_printk(KERN_DEBUG, &pdev->dev,
+			   "enabling SATA channel interrupts (0x%x)\n",
+		           (int) tmp8);
 		tmp8 |= ALL_PORTS;
 		pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
 	}
@@ -284,8 +286,9 @@
 	/* make sure native mode is enabled */
 	pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
 	if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
-		printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
-		       pci_name(pdev), (int) tmp8);
+		dev_printk(KERN_DEBUG, &pdev->dev,
+			   "enabling SATA channel native mode (0x%x)\n",
+		           (int) tmp8);
 		tmp8 |= NATIVE_MODE_ALL;
 		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
 	}
@@ -303,7 +306,7 @@
 	u8 tmp8;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	rc = pci_enable_device(pdev);
 	if (rc)
@@ -318,8 +321,9 @@
 	if (board_id == vt6420) {
 		pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
 		if (tmp8 & SATA_2DEV) {
-			printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
-		       	pci_name(pdev), (int) tmp8);
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "SATA master/slave not supported (0x%x)\n",
+		       		   (int) tmp8);
 			rc = -EIO;
 			goto err_out_regions;
 		}
@@ -332,10 +336,11 @@
 	for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
 		if ((pci_resource_start(pdev, i) == 0) ||
 		    (pci_resource_len(pdev, i) < bar_sizes[i])) {
-			printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
-			       pci_name(pdev), i,
-			       pci_resource_start(pdev, i),
-			       pci_resource_len(pdev, i));
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
+				   i,
+			           pci_resource_start(pdev, i),
+			           pci_resource_len(pdev, i));
 			rc = -ENODEV;
 			goto err_out_regions;
 		}
@@ -353,8 +358,7 @@
 		probe_ent = vt6421_init_probe_ent(pdev);
 
 	if (!probe_ent) {
-		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
-		       pci_name(pdev));
+		dev_printk(KERN_ERR, &pdev->dev, "out of memory\n");
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index cf94e01..bb84ba0 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -42,6 +42,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
+#include <linux/device.h>
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
@@ -86,7 +87,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -95,16 +96,16 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
 static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
 {
-	unsigned long mask_addr;
+	void __iomem *mask_addr;
 	u8 mask;
 
-	mask_addr = (unsigned long) ap->host_set->mmio_base +
+	mask_addr = ap->host_set->mmio_base +
 		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
 	mask = readb(mask_addr);
 	if (ctl & ATA_NIEN)
@@ -115,7 +116,7 @@
 }
 
 
-static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -153,16 +154,24 @@
 static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
-	u16 nsect, lbal, lbam, lbah;
+	u16 nsect, lbal, lbam, lbah, feature;
 
-	nsect = tf->nsect = readw(ioaddr->nsect_addr);
-	lbal = tf->lbal = readw(ioaddr->lbal_addr);
-	lbam = tf->lbam = readw(ioaddr->lbam_addr);
-	lbah = tf->lbah = readw(ioaddr->lbah_addr);
+	tf->command = ata_check_status(ap);
 	tf->device = readw(ioaddr->device_addr);
+	feature = readw(ioaddr->error_addr);
+	nsect = readw(ioaddr->nsect_addr);
+	lbal = readw(ioaddr->lbal_addr);
+	lbam = readw(ioaddr->lbam_addr);
+	lbah = readw(ioaddr->lbah_addr);
+
+	tf->feature = feature;
+	tf->nsect = nsect;
+	tf->lbal = lbal;
+	tf->lbam = lbam;
+	tf->lbah = lbah;
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		tf->hob_feature = readb(ioaddr->error_addr);
+		tf->hob_feature = feature >> 8;
 		tf->hob_nsect = nsect >> 8;
 		tf->hob_lbal = lbal >> 8;
 		tf->hob_lbam = lbam >> 8;
@@ -231,7 +240,7 @@
 };
 
 
-static struct ata_port_operations vsc_sata_ops = {
+static const struct ata_port_operations vsc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= vsc_sata_tf_load,
 	.tf_read		= vsc_sata_tf_read,
@@ -283,11 +292,11 @@
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
 	int pci_dev_busy = 0;
-	void *mmio_base;
+	void __iomem *mmio_base;
 	int rc;
 
 	if (!printed_version++)
-		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
 	rc = pci_enable_device(pdev);
 	if (rc)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 1f0ebab..a5711d5 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -130,7 +130,7 @@
  * Returns:     Pointer to request block.
  */
 struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
-					   int gfp_mask)
+					   gfp_t gfp_mask)
 {
 	const int offset = ALIGN(sizeof(struct scsi_request), 4);
 	const int size = offset + sizeof(struct request);
@@ -196,7 +196,7 @@
 	unsigned int	users;
 	char		*name;
 	unsigned int	slab_flags;
-	unsigned int	gfp_mask;
+	gfp_t		gfp_mask;
 };
 
 static struct scsi_host_cmd_pool scsi_cmd_pool = {
@@ -213,7 +213,7 @@
 static DECLARE_MUTEX(host_cmd_pool_mutex);
 
 static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
-					    int gfp_mask)
+					    gfp_t gfp_mask)
 {
 	struct scsi_cmnd *cmd;
 
@@ -245,7 +245,7 @@
  *
  * Returns:	The allocated scsi command structure.
  */
-struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask)
+struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask)
 {
 	struct scsi_cmnd *cmd;
 
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index de7f98c..6a3f6aa 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -205,7 +205,8 @@
 	unsigned int inlen, outlen, cmdlen;
 	unsigned int needed, buf_needed;
 	int timeout, retries, result;
-	int data_direction, gfp_mask = GFP_KERNEL;
+	int data_direction;
+	gfp_t gfp_mask = GFP_KERNEL;
 
 	if (!sic)
 		return -EINVAL;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 0074f28..3ff5388 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -677,7 +677,7 @@
 	return NULL;
 }
 
-static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, int gfp_mask)
+static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
 	struct scsi_host_sg_pool *sgp;
 	struct scatterlist *sgl;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 771e97e..b856e14 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -26,6 +26,7 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sched.h>	/* workqueue stuff, HZ */
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 8bb8222..d2caa35 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -19,6 +19,9 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 #include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ad94367..d86d5c2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -49,6 +49,7 @@
 #include <linux/seq_file.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/scatterlist.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -104,8 +105,8 @@
 
 #define SG_DEV_ARR_LUMP 32	/* amount to over allocate sg_dev_arr by */
 
-static int sg_add(struct class_device *);
-static void sg_remove(struct class_device *);
+static int sg_add(struct class_device *, struct class_interface *);
+static void sg_remove(struct class_device *, struct class_interface *);
 
 static Scsi_Request *dummy_cmdp;	/* only used for sizeof */
 
@@ -1506,7 +1507,7 @@
 }
 
 static int
-sg_add(struct class_device *cl_dev)
+sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
 	struct gendisk *disk;
@@ -1550,7 +1551,7 @@
 	if (sg_sysfs_valid) {
 		struct class_device * sg_class_member;
 
-		sg_class_member = class_device_create(sg_sysfs_class,
+		sg_class_member = class_device_create(sg_sysfs_class, NULL,
 				MKDEV(SCSI_GENERIC_MAJOR, k), 
 				cl_dev->dev, "%s", 
 				disk->disk_name);
@@ -1582,7 +1583,7 @@
 }
 
 static void
-sg_remove(struct class_device *cl_dev)
+sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
 {
 	struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
 	Sg_device *sdp = NULL;
@@ -1886,13 +1887,17 @@
 	int i;
 
 	for (i=0; i < nr_pages; i++) {
-		if (dirtied && !PageReserved(sgl[i].page))
-			SetPageDirty(sgl[i].page);
-		/* unlock_page(sgl[i].page); */
+		struct page *page = sgl[i].page;
+
+		/* XXX: just for debug. Remove when PageReserved is removed */
+		BUG_ON(PageReserved(page));
+		if (dirtied)
+			SetPageDirty(page);
+		/* unlock_page(page); */
 		/* FIXME: cache flush missing for rw==READ
 		 * FIXME: call the correct reference counting function
 		 */
-		page_cache_release(sgl[i].page);
+		page_cache_release(page);
 	}
 
 	return 0;
@@ -1992,9 +1997,7 @@
 				if (!p)
 					break;
 			}
-			sclp->page = virt_to_page(p);
-			sclp->offset = offset_in_page(p);
-			sclp->length = ret_sz;
+			sg_set_buf(sclp, p, ret_sz);
 
 			SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
 					  k, sg_scatg2virt(sclp), ret_sz));
@@ -2644,7 +2647,7 @@
 sg_page_malloc(int rqSz, int lowDma, int *retSzp)
 {
 	char *resp = NULL;
-	int page_mask;
+	gfp_t page_mask;
 	int order, a_size;
 	int resSz = rqSz;
 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index d001c04..da97662 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3577,7 +3577,8 @@
 static struct st_buffer *
  new_tape_buffer(int from_initialization, int need_dma, int max_sg)
 {
-	int i, priority, got = 0, segs = 0;
+	int i, got = 0, segs = 0;
+	gfp_t priority;
 	struct st_buffer *tb;
 
 	if (from_initialization)
@@ -3610,7 +3611,8 @@
 /* Try to allocate enough space in the tape buffer */
 static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
 {
-	int segs, nbr, max_segs, b_size, priority, order, got;
+	int segs, nbr, max_segs, b_size, order, got;
+	gfp_t priority;
 
 	if (new_size <= STbuffer->buffer_size)
 		return 1;
@@ -4375,7 +4377,7 @@
 		snprintf(name, 10, "%s%s%s", rew ? "n" : "",
 			 STp->disk->disk_name, st_formats[i]);
 		st_class_member =
-			class_device_create(st_sysfs_class,
+			class_device_create(st_sysfs_class, NULL,
 					    MKDEV(SCSI_TAPE_MAJOR,
 						  TAPE_MINOR(dev_num, mode, rew)),
 					    &STp->device->sdev_gendev, "%s", name);
@@ -4524,12 +4526,16 @@
 	int i;
 
 	for (i=0; i < nr_pages; i++) {
-		if (dirtied && !PageReserved(sgl[i].page))
-			SetPageDirty(sgl[i].page);
+		struct page *page = sgl[i].page;
+
+		/* XXX: just for debug. Remove when PageReserved is removed */
+		BUG_ON(PageReserved(page));
+		if (dirtied)
+			SetPageDirty(page);
 		/* FIXME: cache flush missing for rw==READ
 		 * FIXME: call the correct reference counting function
 		 */
-		page_cache_release(sgl[i].page);
+		page_cache_release(page);
 	}
 
 	return 0;
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index e753ba2..a1a58e1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -37,6 +37,9 @@
  * 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/slab.h>
+
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 3131a6b..3a264a4 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -37,6 +37,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/gfp.h>
+
 #ifndef SYM_HIPD_H
 #define SYM_HIPD_H
 
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 5a51051..b131432 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -88,7 +88,7 @@
 	struct gsc_irq gsc_irq;
 	u32 zalon_vers;
 	int error = -ENODEV;
-	void __iomem *zalon = ioremap(dev->hpa, 4096);
+	void __iomem *zalon = ioremap(dev->hpa.start, 4096);
 	void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
 	static int unit = 0;
 	struct Scsi_Host *host;
@@ -127,7 +127,7 @@
 	device.chip		= zalon720_chip;
 	device.host_id		= 7;
 	device.dev		= &dev->dev;
-	device.slot.base	= dev->hpa + GSC_SCSI_ZALON_OFFSET;
+	device.slot.base	= dev->hpa.start + GSC_SCSI_ZALON_OFFSET;
 	device.slot.base_v	= io_port;
 	device.slot.irq		= dev->irq;
 	device.differential	= 2;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 4d75cdf..afb7ddf 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2358,13 +2358,10 @@
 	return 0;
 }
 
-static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
+static int serial8250_suspend(struct device *dev, pm_message_t state)
 {
 	int i;
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
@@ -2375,13 +2372,10 @@
 	return 0;
 }
 
-static int serial8250_resume(struct device *dev, u32 level)
+static int serial8250_resume(struct device *dev)
 {
 	int i;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	for (i = 0; i < UART_NR; i++) {
 		struct uart_8250_port *up = &serial8250_ports[i];
 
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 431aa57..8b49479 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -29,7 +29,6 @@
 static int __init 
 serial_init_chip(struct parisc_device *dev)
 {
-	static int serial_line_nr;
 	struct uart_port port;
 	unsigned long address;
 	int err;
@@ -42,12 +41,13 @@
 		 */
 		if (parisc_parent(dev)->id.hw_type != HPHW_IOA) {
 			printk(KERN_INFO "Serial: device 0x%lx not configured.\n"
-				"Enable support for Wax, Lasi, Asp or Dino.\n", dev->hpa);
+				"Enable support for Wax, Lasi, Asp or Dino.\n",
+				dev->hpa.start);
 		}
 		return -ENODEV;
 	}
 
-	address = dev->hpa;
+	address = dev->hpa.start;
 	if (dev->id.sversion != 0x8d) {
 		address += 0x800;
 	}
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 679e678..ddd0307 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -50,6 +50,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/hardware.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_serial.h>
 
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 1ff629c..938d185 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -50,6 +50,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/sizes.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/clock.h>
 #include <asm/hardware/amba_serial.h>
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 87ef368..6a67e8f 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -408,7 +408,11 @@
 	{
 		.iobase		= SYSCON1,
 		.irq		= IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
+#ifdef CONFIG_MP1000_90MHZ
+		.uartclk	= 4515840,
+#else
 		.uartclk	= 3686400,
+#endif
 		.fifosize	= 16,
 		.ops		= &clps711x_pops,
 		.line		= 0,
@@ -417,7 +421,11 @@
 	{
 		.iobase		= SYSCON2,
 		.irq		= IRQ_UTXINT2, /* IRQ_URXINT2 */
+#ifdef CONFIG_MP1000_90MHZ
+		.uartclk	= 4515840,
+#else
 		.uartclk	= 3686400,
+#endif
 		.fifosize	= 16,
 		.ops		= &clps711x_pops,
 		.line		= 1,
@@ -551,6 +559,7 @@
 static struct uart_driver clps711x_reg = {
 	.driver_name		= "ttyCL",
 	.dev_name		= "ttyCL",
+	.devfs_name		= "ttyCL",
 	.major			= SERIAL_CLPS711X_MAJOR,
 	.minor			= SERIAL_CLPS711X_MINOR,
 	.nr			= UART_NR,
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index bdb4e45..5b3933b 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -921,21 +921,21 @@
 	.cons           = IMX_CONSOLE,
 };
 
-static int serial_imx_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_imx_suspend(struct device *_dev, pm_message_t state)
 {
         struct imx_port *sport = dev_get_drvdata(_dev);
 
-        if (sport && level == SUSPEND_DISABLE)
+        if (sport)
                 uart_suspend_port(&imx_reg, &sport->port);
 
         return 0;
 }
 
-static int serial_imx_resume(struct device *_dev, u32 level)
+static int serial_imx_resume(struct device *_dev)
 {
         struct imx_port *sport = dev_get_drvdata(_dev);
 
-        if (sport && level == RESUME_ENABLE)
+        if (sport)
                 uart_resume_port(&imx_reg, &sport->port);
 
         return 0;
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index f88fdd4..771676a 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -308,6 +308,8 @@
 typedef void ioc4_intr_func_f(void *, uint32_t);
 typedef ioc4_intr_func_f *ioc4_intr_func_t;
 
+static unsigned int Num_of_ioc4_cards;
+
 /* defining this will get you LOTS of great debug info */
 //#define DEBUG_INTERRUPTS
 #define DPRINT_CONFIG(_x...)	;
@@ -317,7 +319,8 @@
 #define WAKEUP_CHARS	256
 
 /* number of characters we want to transmit to the lower level at a time */
-#define IOC4_MAX_CHARS	128
+#define IOC4_MAX_CHARS	256
+#define IOC4_FIFO_CHARS	255
 
 /* Device name we're using */
 #define DEVICE_NAME	"ttyIOC"
@@ -1038,6 +1041,7 @@
 			return -ENOMEM;
 		}
 		memset(port, 0, sizeof(struct ioc4_port));
+		spin_lock_init(&port->ip_lock);
 
 		/* we need to remember the previous ones, to point back to
 		 * them farther down - setting up the ring buffers.
@@ -1691,12 +1695,14 @@
 		baud = 9600;
 
 	if (!the_port->fifosize)
-		the_port->fifosize = IOC4_MAX_CHARS;
+		the_port->fifosize = IOC4_FIFO_CHARS;
 	the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10));
 	the_port->timeout += HZ / 50;	/* Add .02 seconds of slop */
 
 	the_port->ignore_status_mask = N_ALL_INPUT;
 
+	info->tty->low_latency = 1;
+
 	if (I_IGNPAR(info->tty))
 		the_port->ignore_status_mask &= ~(N_PARITY_ERROR
 						| N_FRAMING_ERROR);
@@ -1742,7 +1748,6 @@
  */
 static inline int ic4_startup_local(struct uart_port *the_port)
 {
-	int retval = 0;
 	struct ioc4_port *port;
 	struct uart_info *info;
 
@@ -1754,9 +1759,6 @@
 		return -1;
 
 	info = the_port->info;
-	if (info->flags & UIF_INITIALIZED) {
-		return retval;
-	}
 
 	if (info->tty) {
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1775,7 +1777,6 @@
 	/* set the speed of the serial port */
 	ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
 
-	info->flags |= UIF_INITIALIZED;
 	return 0;
 }
 
@@ -1785,9 +1786,13 @@
  */
 static void ioc4_cb_output_lowat(struct ioc4_port *port)
 {
+	unsigned long pflags;
+
 	/* ip_lock is set on the call here */
 	if (port->ip_port) {
+		spin_lock_irqsave(&port->ip_port->lock, pflags);
 		transmit_chars(port->ip_port);
+		spin_unlock_irqrestore(&port->ip_port->lock, pflags);
 	}
 }
 
@@ -2064,8 +2069,7 @@
 	 * available data as long as it returns some.
 	 */
 	/* Re-arm the timer */
-	writel(port->ip_rx_cons | IOC4_SRCIR_ARM,
-			&port->ip_serial_regs->srcir);
+	writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
 
 	prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
 	cons_ptr = port->ip_rx_cons;
@@ -2299,6 +2303,7 @@
 	}
 	return total;
 }
+
 /**
  * receive_chars - upper level read. Called with ip_lock.
  * @the_port: port to read from
@@ -2307,9 +2312,11 @@
 {
 	struct tty_struct *tty;
 	unsigned char ch[IOC4_MAX_CHARS];
-	int read_count, request_count;
+	int read_count, request_count = IOC4_MAX_CHARS;
 	struct uart_icount *icount;
 	struct uart_info *info = the_port->info;
+	int flip = 0;
+	unsigned long pflags;
 
 	/* Make sure all the pointers are "good" ones */
 	if (!info)
@@ -2317,16 +2324,17 @@
 	if (!info->tty)
 		return;
 
+	spin_lock_irqsave(&the_port->lock, pflags);
 	tty = info->tty;
 
-	request_count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
+	if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count)
+		request_count = TTY_FLIPBUF_SIZE - tty->flip.count;
 
 	if (request_count > 0) {
-		if (request_count > IOC4_MAX_CHARS - 2)
-			request_count = IOC4_MAX_CHARS - 2;
 		icount = &the_port->icount;
 		read_count = do_read(the_port, ch, request_count);
 		if (read_count > 0) {
+			flip = 1;
 			memcpy(tty->flip.char_buf_ptr, ch, read_count);
 			memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count);
 			tty->flip.char_buf_ptr += read_count;
@@ -2335,7 +2343,11 @@
 			icount->rx += read_count;
 		}
 	}
-	tty_flip_buffer_push(tty);
+
+	spin_unlock_irqrestore(&the_port->lock, pflags);
+
+	if (flip)
+		tty_flip_buffer_push(tty);
 }
 
 /**
@@ -2393,18 +2405,14 @@
 
 	info = the_port->info;
 
-	if (!(info->flags & UIF_INITIALIZED))
-		return;
-
 	wake_up_interruptible(&info->delta_msr_wait);
 
 	if (info->tty)
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
 
-	spin_lock_irqsave(&port->ip_lock, port_flags);
+	spin_lock_irqsave(&the_port->lock, port_flags);
 	set_notification(port, N_ALL, 0);
-	info->flags &= ~UIF_INITIALIZED;
-	spin_unlock_irqrestore(&port->ip_lock, port_flags);
+	spin_unlock_irqrestore(&the_port->lock, port_flags);
 }
 
 /**
@@ -2463,12 +2471,10 @@
 static void ic4_start_tx(struct uart_port *the_port)
 {
 	struct ioc4_port *port = get_ioc4_port(the_port);
-	unsigned long flags;
 
 	if (port) {
-		spin_lock_irqsave(&port->ip_lock, flags);
-		transmit_chars(the_port);
-		spin_unlock_irqrestore(&port->ip_lock, flags);
+		set_notification(port, N_OUTPUT_LOWAT, 1);
+		enable_intrs(port, port->ip_hooks->intr_tx_mt);
 	}
 }
 
@@ -2510,9 +2516,9 @@
 	}
 
 	/* Start up the serial port */
-	spin_lock_irqsave(&port->ip_lock, port_flags);
+	spin_lock_irqsave(&the_port->lock, port_flags);
 	retval = ic4_startup_local(the_port);
-	spin_unlock_irqrestore(&port->ip_lock, port_flags);
+	spin_unlock_irqrestore(&the_port->lock, port_flags);
 	return retval;
 }
 
@@ -2527,12 +2533,11 @@
 ic4_set_termios(struct uart_port *the_port,
 		struct termios *termios, struct termios *old_termios)
 {
-	struct ioc4_port *port = get_ioc4_port(the_port);
 	unsigned long port_flags;
 
-	spin_lock_irqsave(&port->ip_lock, port_flags);
+	spin_lock_irqsave(&the_port->lock, port_flags);
 	ioc4_change_speed(the_port, termios, old_termios);
-	spin_unlock_irqrestore(&port->ip_lock, port_flags);
+	spin_unlock_irqrestore(&the_port->lock, port_flags);
 }
 
 /**
@@ -2607,24 +2612,25 @@
 				__FUNCTION__, (void *)the_port,
 				(void *)port));
 
-		spin_lock_init(&the_port->lock);
 		/* membase, iobase and mapbase just need to be non-0 */
 		the_port->membase = (unsigned char __iomem *)1;
-		the_port->line = the_port->iobase = ii;
+		the_port->iobase = (pdev->bus->number << 16) |  ii;
+		the_port->line = (Num_of_ioc4_cards << 2) | ii;
 		the_port->mapbase = 1;
 		the_port->type = PORT_16550A;
-		the_port->fifosize = IOC4_MAX_CHARS;
+		the_port->fifosize = IOC4_FIFO_CHARS;
 		the_port->ops = &ioc4_ops;
 		the_port->irq = control->ic_irq;
 		the_port->dev = &pdev->dev;
+		spin_lock_init(&the_port->lock);
 		if (uart_add_one_port(&ioc4_uart, the_port) < 0) {
 			printk(KERN_WARNING
-				       "%s: unable to add port %d\n",
-				       __FUNCTION__, the_port->line);
+		           "%s: unable to add port %d bus %d\n",
+			       __FUNCTION__, the_port->line, pdev->bus->number);
 		} else {
 			DPRINT_CONFIG(
-				    ("IOC4 serial driver port %d irq = %d\n",
-				       the_port->line, the_port->irq));
+			    ("IOC4 serial port %d irq = %d, bus %d\n",
+			       the_port->line, the_port->irq, pdev->bus->number));
 		}
 		/* all ports are rs232 for now */
 		ioc4_set_proto(port, PROTO_RS232);
@@ -2734,6 +2740,8 @@
 	if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
 		goto out4;
 
+	Num_of_ioc4_cards++;
+
 	return ret;
 
 	/* error exits that give back resources */
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 0585ab2..8a79968 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -781,22 +781,22 @@
 
 #ifdef CONFIG_PM
 static int
-mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level)
+mpc52xx_uart_suspend(struct device *dev, pm_message_t state)
 {
 	struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
 
-	if (sport && level == SUSPEND_DISABLE)
+	if (sport)
 		uart_suspend_port(&mpc52xx_uart_driver, port);
 
 	return 0;
 }
 
 static int
-mpc52xx_uart_resume(struct device *dev, u32 level)
+mpc52xx_uart_resume(struct device *dev)
 {
 	struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
 
-	if (port && level == RESUME_ENABLE)
+	if (port)
 		uart_resume_port(&mpc52xx_uart_driver, port);
 
 	return 0;
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index efe79b1..aec83f5 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -1100,6 +1100,8 @@
 {
 	pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line);
 
+	/* Issue a Receive Abort to clear any receive errors */
+	writel(MPSC_CHR_2_RA, pi->mpsc_base + MPSC_CHR_2);
 	if (pi->rcv_data) {
 		mpsc_enter_hunt(pi);
 		mpsc_sdma_cmd(pi, SDMA_SDCM_ERD);
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 1890646..660bae5 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -27,6 +27,7 @@
 #include <linux/delay.h> /* for udelay */
 #include <linux/device.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/parisc-device.h>
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -444,7 +445,7 @@
 	unsigned long bytecnt;
 	struct uart_port *port;
 
-	status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32);
+	status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
 	if(status != PDC_OK) {
 		printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
 		return 1;
@@ -469,16 +470,18 @@
 	for(i = 0; i < ports; ++i, ++port_cnt) {
 		port = &mux_ports[port_cnt];
 		port->iobase	= 0;
-		port->mapbase	= dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
+		port->mapbase	= dev->hpa.start + MUX_OFFSET +
+						(i * MUX_LINE_OFFSET);
 		port->membase	= ioremap(port->mapbase, MUX_LINE_OFFSET);
 		port->iotype	= SERIAL_IO_MEM;
 		port->type	= PORT_MUX;
-		port->irq	= SERIAL_IRQ_NONE;
+		port->irq	= NO_IRQ;
 		port->uartclk	= 0;
 		port->fifosize	= MUX_FIFO_SIZE;
 		port->ops	= &mux_pops;
 		port->flags	= UPF_BOOT_AUTOCONF;
 		port->line	= port_cnt;
+		spin_lock_init(&port->lock);
 		status = uart_add_one_port(&mux_driver, port);
 		BUG_ON(status);
 	}
@@ -497,7 +500,7 @@
 MODULE_DEVICE_TABLE(parisc, mux_tbl);
 
 static struct parisc_driver serial_mux_driver = {
-	.name =		"Serial MUX",
+	.name =		"serial_mux",
 	.id_table =	mux_tbl,
 	.probe =	mux_probe,
 };
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 90c2a86..8cc4ced 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -358,6 +358,9 @@
 	unsigned long flags;
 	int retval;
 
+	if (port->line == 3) /* HWUART */
+		up->mcr |= UART_MCR_AFE;
+	else
 	up->mcr = 0;
 
 	/*
@@ -481,8 +484,10 @@
 
 	if ((up->port.uartclk / quot) < (2400 * 16))
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-	else
+	else if ((up->port.uartclk / quot) < (230400 * 16))
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
+	else
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32;
 
 	/*
 	 * Ok, we're now changing the port state.  Do it with
@@ -772,6 +777,20 @@
 		.ops		= &serial_pxa_pops,
 		.line		= 2,
 	},
+  }, {  /* HWUART */
+	.name	= "HWUART",
+	.cken	= CKEN4_HWUART,
+	.port = {
+		.type		= PORT_PXA,
+		.iotype		= UPIO_MEM,
+		.membase	= (void *)&HWUART,
+		.mapbase	= __PREG(HWUART),
+		.irq		= IRQ_HWUART,
+		.uartclk	= 921600 * 16,
+		.fifosize	= 64,
+		.ops		= &serial_pxa_pops,
+		.line		= 3,
+	},
   }
 };
 
@@ -786,21 +805,21 @@
 	.cons		= PXA_CONSOLE,
 };
 
-static int serial_pxa_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int serial_pxa_suspend(struct device *_dev, pm_message_t state)
 {
         struct uart_pxa_port *sport = dev_get_drvdata(_dev);
 
-        if (sport && level == SUSPEND_DISABLE)
+        if (sport)
                 uart_suspend_port(&serial_pxa_reg, &sport->port);
 
         return 0;
 }
 
-static int serial_pxa_resume(struct device *_dev, u32 level)
+static int serial_pxa_resume(struct device *_dev)
 {
         struct uart_pxa_port *sport = dev_get_drvdata(_dev);
 
-        if (sport && level == RESUME_ENABLE)
+        if (sport)
                 uart_resume_port(&serial_pxa_reg, &sport->port);
 
         return 0;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 52692aa..06a17df 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -1134,23 +1134,22 @@
 
 #ifdef CONFIG_PM
 
-static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state,
-				  u32 level)
+static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state)
 {
 	struct uart_port *port = s3c24xx_dev_to_port(dev);
 
-	if (port && level == SUSPEND_DISABLE)
+	if (port)
 		uart_suspend_port(&s3c24xx_uart_drv, port);
 
 	return 0;
 }
 
-static int s3c24xx_serial_resume(struct device *dev, u32 level)
+static int s3c24xx_serial_resume(struct device *dev)
 {
 	struct uart_port *port = s3c24xx_dev_to_port(dev);
 	struct s3c24xx_uart_port *ourport = to_ourport(port);
 
-	if (port && level == RESUME_ENABLE) {
+	if (port) {
 		clk_enable(ourport->clk);
 		s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
 		clk_disable(ourport->clk);
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index dd8aed2..c4a789e 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -834,21 +834,21 @@
 	.cons			= SA1100_CONSOLE,
 };
 
-static int sa1100_serial_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int sa1100_serial_suspend(struct device *_dev, pm_message_t state)
 {
 	struct sa1100_port *sport = dev_get_drvdata(_dev);
 
-	if (sport && level == SUSPEND_DISABLE)
+	if (sport)
 		uart_suspend_port(&sa1100_reg, &sport->port);
 
 	return 0;
 }
 
-static int sa1100_serial_resume(struct device *_dev, u32 level)
+static int sa1100_serial_resume(struct device *_dev)
 {
 	struct sa1100_port *sport = dev_get_drvdata(_dev);
 
-	if (sport && level == RESUME_ENABLE)
+	if (sport)
 		uart_resume_port(&sa1100_reg, &sport->port);
 
 	return 0;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 2d8622e..401d94a 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -147,8 +147,7 @@
 	 * once we have successfully opened the port.  Also set
 	 * up the tty->alt_speed kludge
 	 */
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
+	set_bit(TTY_IO_ERROR, &info->tty->flags);
 
 	if (port->type == PORT_UNKNOWN)
 		return 0;
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 0c5d65a..2b623ab 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -976,14 +976,11 @@
 	return 0;
 }
 
-static int siu_suspend(struct device *dev, pm_message_t state, u32 level)
+static int siu_suspend(struct device *dev, pm_message_t state)
 {
 	struct uart_port *port;
 	int i;
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	for (i = 0; i < siu_uart_driver.nr; i++) {
 		port = &siu_uart_ports[i];
 		if ((port->type == PORT_VR41XX_SIU ||
@@ -995,14 +992,11 @@
 	return 0;
 }
 
-static int siu_resume(struct device *dev, u32 level)
+static int siu_resume(struct device *dev)
 {
 	struct uart_port *port;
 	int i;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	for (i = 0; i < siu_uart_driver.nr; i++) {
 		port = &siu_uart_ports[i];
 		if ((port->type == PORT_VR41XX_SIU ||
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index f056276..28757cb 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -16,6 +16,8 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/superhyway.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 static int superhyway_devices;
 
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index a89ef4d..a0e5af6 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -8,33 +8,31 @@
  * for more details.
  *
  * Copyright (c) Harald Koerfgen, 1998
- * Copyright (c) 2001, 2003  Maciej W. Rozycki
+ * Copyright (c) 2001, 2003, 2005  Maciej W. Rozycki
  */
-#include <linux/string.h>
 #include <linux/init.h>
-#include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/bug.h>
 #include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/paccess.h>
+
 #include <asm/dec/machtype.h>
 #include <asm/dec/prom.h>
 #include <asm/dec/tcinfo.h>
 #include <asm/dec/tcmodule.h>
 #include <asm/dec/interrupts.h>
-#include <asm/paccess.h>
-#include <asm/ptrace.h>
-
-#define TC_DEBUG
 
 MODULE_LICENSE("GPL");
 slot_info tc_bus[MAX_SLOT];
 static int num_tcslots;
 static tcinfo *info;
 
-unsigned long system_base;
-
 /*
  * Interface to the world. Read comment in include/asm-mips/tc.h.
  */
@@ -97,13 +95,16 @@
 static void __init tc_probe(unsigned long startaddr, unsigned long size,
 			    int slots)
 {
+	unsigned long slotaddr;
 	int i, slot, err;
 	long offset;
-	unsigned char pattern[4];
-	unsigned char *module;
+	u8 pattern[4];
+	volatile u8 *module;
 
 	for (slot = 0; slot < slots; slot++) {
-		module = (char *)(startaddr + slot * size);
+		slotaddr = startaddr + slot * size;
+		module = ioremap_nocache(slotaddr, size);
+		BUG_ON(!module);
 
 		offset = OLDCARD;
 
@@ -112,8 +113,10 @@
 		err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1);
 		err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2);
 		err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3);
-		if (err)
+		if (err) {
+			iounmap(module);
 			continue;
+		}
 
 		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
 		    pattern[2] != 0xaa || pattern[3] != 0xff) {
@@ -124,16 +127,20 @@
 			err |= get_dbe(pattern[1], module + TC_PATTERN1);
 			err |= get_dbe(pattern[2], module + TC_PATTERN2);
 			err |= get_dbe(pattern[3], module + TC_PATTERN3);
-			if (err)
+			if (err) {
+				iounmap(module);
 				continue;
+			}
 		}
 
 		if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
-		    pattern[2] != 0xaa || pattern[3] != 0xff)
+		    pattern[2] != 0xaa || pattern[3] != 0xff) {
+			iounmap(module);
 			continue;
+		}
 
-		tc_bus[slot].base_addr = (unsigned long)module;
-		for(i = 0; i < 8; i++) {
+		tc_bus[slot].base_addr = slotaddr;
+		for (i = 0; i < 8; i++) {
 			tc_bus[slot].firmware[i] =
 				module[TC_FIRM_VER + offset + 4 * i];
 			tc_bus[slot].vendor[i] =
@@ -171,13 +178,15 @@
 			tc_bus[slot].interrupt = -1;
 			break;
 		}
+
+		iounmap(module);
 	}
 }
 
 /*
  * the main entry
  */
-void __init tc_init(void)
+static int __init tc_init(void)
 {
 	int tc_clock;
 	int i;
@@ -185,7 +194,7 @@
 	unsigned long slot_size;
 
 	if (!TURBOCHANNEL)
-		return;
+		return 0;
 
 	for (i = 0; i < MAX_SLOT; i++) {
 		tc_bus[i].base_addr = 0;
@@ -196,8 +205,8 @@
 		tc_bus[i].flags = FREE;
 	}
 
-	info = (tcinfo *) rex_gettcinfo();
-	slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0));
+	info = rex_gettcinfo();
+	slot0addr = CPHYSADDR((long)rex_slot_address(0));
 
 	switch (mips_machtype) {
 	case MACH_DS5000_200:
@@ -216,37 +225,24 @@
 
 	tc_clock = 10000 / info->clk_period;
 
-	if (TURBOCHANNEL && info->slot_size && slot0addr) {
-		printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision,
-			tc_clock / 10, tc_clock % 10);
-		printk("(with%s parity)\n", info->parity ? "" : "out");
+	if (info->slot_size && slot0addr) {
+		pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n",
+			info->revision, tc_clock / 10, tc_clock % 10,
+			info->parity ? "" : "out");
 
 		slot_size = info->slot_size << 20;
 
 		tc_probe(slot0addr, slot_size, num_tcslots);
 
-  		/*
-  		 * All TURBOchannel DECstations have the onboard devices
- 		 * where the (num_tcslots + 0 or 1 on DS5k/xx) Option Module
- 		 * would be.
- 		 */
- 		if(mips_machtype == MACH_DS5000_XX)
- 			i = 1;
-		else
- 			i = 0;
-
- 	        system_base = slot0addr + slot_size * (num_tcslots + i);
-
-#ifdef TC_DEBUG
-		for (i = 0; i < num_tcslots; i++)
-			if (tc_bus[i].base_addr) {
-				printk("    slot %d: ", i);
-				printk("%s %s %s\n", tc_bus[i].vendor,
-					tc_bus[i].name, tc_bus[i].firmware);
-			}
-#endif
-		ioport_resource.end = KSEG2 - 1;
+		for (i = 0; i < num_tcslots; i++) {
+			if (!tc_bus[i].base_addr)
+				continue;
+			pr_info("    slot %d: %s %s %s\n", i, tc_bus[i].vendor,
+				tc_bus[i].name, tc_bus[i].firmware);
+		}
 	}
+
+	return 0;
 }
 
 subsys_initcall(tc_init);
@@ -257,4 +253,3 @@
 EXPORT_SYMBOL(get_tc_base_addr);
 EXPORT_SYMBOL(get_tc_irq_nr);
 EXPORT_SYMBOL(get_tc_speed);
-EXPORT_SYMBOL(system_base);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 6bed871..c52af73 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -65,14 +65,14 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
-#include <asm/dec/serial.h>
 
-#ifdef CONFIG_MACH_DECSTATION
 #include <asm/dec/interrupts.h>
-#include <asm/dec/machtype.h>
-#include <asm/dec/tc.h>
 #include <asm/dec/ioasic_addrs.h>
-#endif
+#include <asm/dec/machtype.h>
+#include <asm/dec/serial.h>
+#include <asm/dec/system.h>
+#include <asm/dec/tc.h>
+
 #ifdef CONFIG_KGDB
 #include <asm/kgdb.h>
 #endif
@@ -192,18 +192,6 @@
 static void change_speed(struct dec_serial *info);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
-/*
- * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-static DECLARE_MUTEX(tmp_buf_sem);
-
 static inline int serial_paranoia_check(struct dec_serial *info,
 					char *name, const char *routine)
 {
@@ -1628,30 +1616,22 @@
 		return;
 	}
 
-	/*
-	 * When serial console is activated, tc_init has not been called yet
-	 * and system_base is undefined. Unfortunately we have to hardcode
-	 * system_base for this case :-(. HK
-	 */
 	switch(mips_machtype) {
 #ifdef CONFIG_MACH_DECSTATION
 	case MACH_DS5000_2X0:
 	case MACH_DS5900:
-		system_base = KSEG1ADDR(0x1f800000);
 		n_chips = 2;
 		zs_parms = &ds_parms;
 		zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
 		zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1];
 		break;
 	case MACH_DS5000_1XX:
-		system_base = KSEG1ADDR(0x1c000000);
 		n_chips = 2;
 		zs_parms = &ds_parms;
 		zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
 		zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1];
 		break;
 	case MACH_DS5000_XX:
-		system_base = KSEG1ADDR(0x1c000000);
 		n_chips = 1;
 		zs_parms = &ds_parms;
 		zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0];
@@ -1673,10 +1653,10 @@
 			 * The sccs reside on the high byte of the 16 bit IOBUS
 			 */
 			zs_channels[n_channels].control =
-				(volatile unsigned char *)system_base +
+				(volatile void *)CKSEG1ADDR(dec_kn_slot_base +
 			  (0 == chip ? zs_parms->scc0 : zs_parms->scc1) +
 			  (0 == channel ? zs_parms->channel_a_offset :
-			                  zs_parms->channel_b_offset);
+			                  zs_parms->channel_b_offset));
 			zs_channels[n_channels].data =
 				zs_channels[n_channels].control + 4;
 
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index df014c2..a50c2bc 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -8,6 +8,7 @@
 
 obj-$(CONFIG_USB_MON)		+= mon/
 
+obj-$(CONFIG_PCI)		+= host/
 obj-$(CONFIG_USB_EHCI_HCD)	+= host/
 obj-$(CONFIG_USB_ISP116X_HCD)	+= host/
 obj-$(CONFIG_USB_OHCI_HCD)	+= host/
@@ -17,7 +18,6 @@
 
 obj-$(CONFIG_USB_ACM)		+= class/
 obj-$(CONFIG_USB_AUDIO)		+= class/
-obj-$(CONFIG_USB_BLUETOOTH_TTY)	+= class/
 obj-$(CONFIG_USB_MIDI)		+= class/
 obj-$(CONFIG_USB_PRINTER)	+= class/
 
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 333e39b..ef105a9 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -28,29 +28,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called audio.
 
-comment "USB Bluetooth TTY can only be used with disabled Bluetooth subsystem"
-	depends on USB && BT
-
-config USB_BLUETOOTH_TTY
-	tristate "USB Bluetooth TTY support"
-	depends on USB && BT=n
-	---help---
-	  This driver implements a nonstandard tty interface to a Bluetooth
-	  device that can be used only by specialized Bluetooth HCI software.
-
-	  Say Y here if you want to use OpenBT Bluetooth stack (available
-	  at <http://developer.axis.com/software>), or other TTY based
-	  Bluetooth stacks, and want to connect a USB Bluetooth device
-	  to your computer's USB port.
-
-	  Do *not* enable this driver if you want to use generic Linux
-	  Bluetooth support.
-
-	  If in doubt, say N here.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called bluetty.
-
 config USB_MIDI
 	tristate "USB MIDI support"
 	depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER
diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
index 971e549..2294712 100644
--- a/drivers/usb/class/Makefile
+++ b/drivers/usb/class/Makefile
@@ -5,6 +5,5 @@
 
 obj-$(CONFIG_USB_ACM)		+= cdc-acm.o
 obj-$(CONFIG_USB_AUDIO)		+= audio.o
-obj-$(CONFIG_USB_BLUETOOTH_TTY)	+= bluetty.o
 obj-$(CONFIG_USB_MIDI)		+= usb-midi.o
 obj-$(CONFIG_USB_PRINTER)	+= usblp.o
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
deleted file mode 100644
index 5240233..0000000
--- a/drivers/usb/class/bluetty.c
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * bluetty.c   Version 0.13
- *
- * Copyright (C) 2000, 2001 Greg Kroah-Hartman	<greg@kroah.com>
- * Copyright (C) 2000 Mark Douglas Corner	<mcorner@umich.edu>
- *
- * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
- * 
- * (2001/11/30) Version 0.13 gkh
- *	- added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
- *	- removed active variable, as open_count will do.
- *
- * (2001/07/09) Version 0.12 gkh
- *	- removed in_interrupt() call, as it doesn't make sense to do 
- *	  that anymore.
- *
- * (2001/06/05) Version 0.11 gkh
- *	- Fixed problem with read urb status saying that we have shutdown,
- *	  and that we shouldn't resubmit the urb.  Patch from unknown.
- *
- * (2001/05/28) Version 0.10 gkh
- *	- Fixed problem with using data from userspace in the bluetooth_write
- *	  function as found by the CHECKER project.
- *	- Added a buffer to the write_urb_pool which reduces the number of
- *	  buffers being created and destroyed for ever write.  Also cleans
- *	  up the logic a bit.
- *	- Added a buffer to the control_urb_pool which fixes a memory leak
- *	  when the device is removed from the system.
- *
- * (2001/05/28) Version 0.9 gkh
- *	Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback
- *	which was found by both the CHECKER project and Mikko Rahkonen.
- *
- * (08/04/2001) gb
- *	Identify version on module load.
- *
- * (2001/03/10) Version 0.8 gkh
- *	Fixed problem with not unlinking interrupt urb on device close
- *	and resubmitting the read urb on error with bluetooth struct.
- *	Thanks to Narayan Mohanram <narayan@RovingNetworks.com> for the
- *	fixes.
- *
- * (11/29/2000) Version 0.7 gkh
- *	Fixed problem with overrunning the tty flip buffer.
- *	Removed unneeded NULL pointer initialization.
- *
- * (10/05/2000) Version 0.6 gkh
- *	Fixed bug with urb->dev not being set properly, now that the usb
- *	core needs it.
- *	Got a real major id number and name.
- *
- * (08/06/2000) Version 0.5 gkh
- *	Fixed problem of not resubmitting the bulk read urb if there is
- *	an error in the callback.  Ericsson devices seem to need this.
- *
- * (07/11/2000) Version 0.4 gkh
- *	Fixed bug in disconnect for when we call tty_hangup
- *	Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not
- *	getting attached to the control urb properly.
- *	Fixed bug in bluetooth_write where we pay attention to the result
- *	of bluetooth_ctrl_msg.
- *
- * (08/03/2000) Version 0.3 gkh mdc
- *	Merged in Mark's changes to make the driver play nice with the Axis
- *	stack.
- *	Made the write bulk use an urb pool to enable larger transfers with
- *	fewer calls to the driver.
- *	Fixed off by one bug in acl pkt receive
- *	Made packet counters specific to each bluetooth device 
- *	Added checks for zero length callbacks
- *	Added buffers for int and bulk packets.  Had to do this otherwise 
- *	packet types could intermingle.
- *	Made a control urb pool for the control messages.
- *
- * (07/11/2000) Version 0.2 gkh
- *	Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe 
- *	function.
- *
- * (07/09/2000) Version 0.1 gkh
- *	Initial release. Has support for sending ACL data (which is really just
- *	a HCI frame.) Raw HCI commands and HCI events are not supported.
- *	A ioctl will probably be needed for the HCI commands and events in the
- *	future. All isoch endpoints are ignored at this time also.
- *	This driver should work for all currently shipping USB Bluetooth 
- *	devices at this time :)
- * 
- */
-
-/*
- * 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/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-#define DEBUG
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.13"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
-#define DRIVER_DESC "USB Bluetooth tty driver"
-
-/* define this if you have hardware that is not good */
-/*#define	BTBUGGYHARDWARE */
-
-/* Class, SubClass, and Protocol codes that describe a Bluetooth device */
-#define WIRELESS_CLASS_CODE			0xe0
-#define RF_SUBCLASS_CODE			0x01
-#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE	0x01
-
-
-#define BLUETOOTH_TTY_MAJOR	216	/* real device node major id */
-#define BLUETOOTH_TTY_MINORS	256	/* whole lotta bluetooth devices */
-
-#define USB_BLUETOOTH_MAGIC	0x6d02	/* magic number for bluetooth struct */
-
-#define BLUETOOTH_CONTROL_REQUEST_TYPE	0x20
-
-/* Bluetooth packet types */
-#define CMD_PKT			0x01
-#define ACL_PKT			0x02
-#define SCO_PKT			0x03
-#define EVENT_PKT		0x04
-#define ERROR_PKT		0x05
-#define NEG_PKT			0x06
-
-/* Message sizes */
-#define MAX_EVENT_SIZE		0xFF
-#define EVENT_HDR_SIZE		3	/* 2 for the header + 1 for the type indicator */
-#define EVENT_BUFFER_SIZE	(MAX_EVENT_SIZE + EVENT_HDR_SIZE)
-
-#define MAX_ACL_SIZE		0xFFFF
-#define ACL_HDR_SIZE		5	/* 4 for the header + 1 for the type indicator */
-#define ACL_BUFFER_SIZE		(MAX_ACL_SIZE + ACL_HDR_SIZE)
-
-/* parity check flag */
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-#define CHAR2INT16(c1,c0)	(((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
-
-#define NUM_BULK_URBS		24
-#define NUM_CONTROL_URBS	16
-
-struct usb_bluetooth {
-	int			magic;
-	struct usb_device *	dev;
-	struct tty_driver *	tty_driver;	/* the tty_driver for this device */
-	struct tty_struct *	tty;		/* the corresponding tty for this port */
-
-	unsigned char		minor;		/* the starting minor number for this device */
-	int			throttle;	/* throttled by tty layer */
-	int			open_count;
-	
-	__u8			control_out_bInterfaceNum;
-	struct urb *		control_urb_pool[NUM_CONTROL_URBS];
-	struct usb_ctrlrequest	dr[NUM_CONTROL_URBS];
-
-	unsigned char *		interrupt_in_buffer;
-	struct urb *		interrupt_in_urb;
-	__u8			interrupt_in_endpointAddress;
-	__u8			interrupt_in_interval;
-	int			interrupt_in_buffer_size;
-
-	unsigned char *		bulk_in_buffer;
-	struct urb *		read_urb;
-	__u8			bulk_in_endpointAddress;
-	int			bulk_in_buffer_size;
-
-	int			bulk_out_buffer_size;
-	__u8			bulk_out_endpointAddress;
-
-	wait_queue_head_t	write_wait;
-
-	struct work_struct			work;	/* work queue entry for line discipline waking up */
-	
-	unsigned int		int_packet_pos;
-	unsigned char		int_buffer[EVENT_BUFFER_SIZE];
-	unsigned int		bulk_packet_pos;
-	unsigned char		bulk_buffer[ACL_BUFFER_SIZE];	/* 64k preallocated, fix? */
-	struct semaphore	lock;
-};
-
-
-/* local function prototypes */
-static int  bluetooth_open		(struct tty_struct *tty, struct file *filp);
-static void bluetooth_close		(struct tty_struct *tty, struct file *filp);
-static int  bluetooth_write		(struct tty_struct *tty, const unsigned char *buf, int count);
-static int  bluetooth_write_room	(struct tty_struct *tty);
-static int  bluetooth_chars_in_buffer	(struct tty_struct *tty);
-static void bluetooth_throttle		(struct tty_struct *tty);
-static void bluetooth_unthrottle	(struct tty_struct *tty);
-static int  bluetooth_ioctl		(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void bluetooth_set_termios	(struct tty_struct *tty, struct termios *old);
-
-static void bluetooth_int_callback		(struct urb *urb, struct pt_regs *regs);
-static void bluetooth_ctrl_callback		(struct urb *urb, struct pt_regs *regs);
-static void bluetooth_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void bluetooth_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-
-static int usb_bluetooth_probe (struct usb_interface *intf, 
-				const struct usb_device_id *id);
-static void usb_bluetooth_disconnect	(struct usb_interface *intf);
-
-
-static struct usb_device_id usb_bluetooth_ids [] = {
-	{ USB_DEVICE_INFO(WIRELESS_CLASS_CODE, RF_SUBCLASS_CODE, BLUETOOTH_PROGRAMMING_PROTOCOL_CODE) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
-
-static struct usb_driver usb_bluetooth_driver = {
-	.owner =	THIS_MODULE,
-	.name =		"bluetty",
-	.probe =	usb_bluetooth_probe,
-	.disconnect =	usb_bluetooth_disconnect,
-	.id_table =	usb_bluetooth_ids,
-};
-
-static struct tty_driver	*bluetooth_tty_driver;
-static struct usb_bluetooth	*bluetooth_table[BLUETOOTH_TTY_MINORS];
-
-
-static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
-{
-	if (!bluetooth) {
-		dbg("%s - bluetooth == NULL", function);
-		return -1;
-	}
-	if (bluetooth->magic != USB_BLUETOOTH_MAGIC) {
-		dbg("%s - bad magic number for bluetooth", function);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function)
-{
-	if (!bluetooth || 
-	    bluetooth_paranoia_check (bluetooth, function)) { 
-		/* then say that we don't have a valid usb_bluetooth thing, which will
-		 * end up generating -ENODEV return values */
-		return NULL;
-	}
-
-	return bluetooth;
-}
-
-
-static inline struct usb_bluetooth *get_bluetooth_by_index (int index)
-{
-	return bluetooth_table[index];
-}
-
-
-static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
-{
-	struct urb *urb = NULL;
-	struct usb_ctrlrequest *dr = NULL;
-	int i;
-	int status;
-
-	dbg ("%s", __FUNCTION__);
-
-	/* try to find a free urb in our list */
-	for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-		if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) {
-			urb = bluetooth->control_urb_pool[i];
-			dr = &bluetooth->dr[i];
-			break;
-		}
-	}
-	if (urb == NULL) {
-		dbg ("%s - no free urbs", __FUNCTION__);
-		return -ENOMEM;
-	}
-
-	/* keep increasing the urb transfer buffer to fit the size of the message */
-	if (urb->transfer_buffer == NULL) {
-		urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
-		if (urb->transfer_buffer == NULL) {
-			err ("%s - out of memory", __FUNCTION__);
-			return -ENOMEM;
-		}
-	}
-	if (urb->transfer_buffer_length < len) {
-		kfree(urb->transfer_buffer);
-		urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
-		if (urb->transfer_buffer == NULL) {
-			err ("%s - out of memory", __FUNCTION__);
-			return -ENOMEM;
-		}
-	}
-	memcpy (urb->transfer_buffer, buf, len);
-
-	dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16((u16) value);
-	dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
-	dr->wLength = cpu_to_le16((u16) len);
-	
-	usb_fill_control_urb (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
-			  (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
-
-	/* send it down the pipe */
-	status = usb_submit_urb(urb, GFP_KERNEL);
-	if (status)
-		dbg("%s - usb_submit_urb(control) failed with status = %d", __FUNCTION__, status);
-	
-	return status;
-}
-
-
-
-
-
-/*****************************************************************************
- * Driver tty interface functions
- *****************************************************************************/
-static int bluetooth_open (struct tty_struct *tty, struct file * filp)
-{
-	struct usb_bluetooth *bluetooth;
-	int result;
-
-	dbg("%s", __FUNCTION__);
-
-	/* initialize the pointer incase something fails */
-	tty->driver_data = NULL;
-
-	/* get the bluetooth object associated with this tty pointer */
-	bluetooth = get_bluetooth_by_index (tty->index);
-
-	if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
-		return -ENODEV;
-	}
-
-	down (&bluetooth->lock);
- 
-	++bluetooth->open_count;
-	if (bluetooth->open_count == 1) {
-		/* set up our structure making the tty driver remember our object, and us it */
-		tty->driver_data = bluetooth;
-		bluetooth->tty = tty;
-
-		/* force low_latency on so that our tty_push actually forces the data through, 
-	 	* otherwise it is scheduled, and with high data rates (like with OHCI) data
-	 	* can get lost. */
-		bluetooth->tty->low_latency = 1;
-	
-		/* Reset the packet position counters */
-		bluetooth->int_packet_pos = 0;
-		bluetooth->bulk_packet_pos = 0;
-
-#ifndef BTBUGGYHARDWARE
-		/* Start reading from the device */
-		usb_fill_bulk_urb (bluetooth->read_urb, bluetooth->dev, 
-			       usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-			       bluetooth->bulk_in_buffer,
-			       bluetooth->bulk_in_buffer_size,
-			       bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-		if (result)
-			dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
-#endif
-		usb_fill_int_urb (bluetooth->interrupt_in_urb, bluetooth->dev,
-			      usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
-			      bluetooth->interrupt_in_buffer,
-			      bluetooth->interrupt_in_buffer_size,
-			      bluetooth_int_callback, bluetooth,
-			      bluetooth->interrupt_in_interval);
-		result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL);
-		if (result)
-			dbg("%s - usb_submit_urb(interrupt in) failed with status %d", __FUNCTION__, result);
-	}
-	
-	up(&bluetooth->lock);
-
-	return 0;
-}
-
-
-static void bluetooth_close (struct tty_struct *tty, struct file * filp)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not opened", __FUNCTION__);
-		return;
-	}
-
-	down (&bluetooth->lock);
- 
-	--bluetooth->open_count;
-	if (bluetooth->open_count <= 0) {
-		bluetooth->open_count = 0;
-
-		/* shutdown any in-flight urbs that we know about */
-		usb_kill_urb (bluetooth->read_urb);
-		usb_kill_urb (bluetooth->interrupt_in_urb);
-	}
-	up(&bluetooth->lock);
-}
-
-
-static int bluetooth_write (struct tty_struct * tty, const unsigned char *buf, int count)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	struct urb *urb = NULL;
-	unsigned char *temp_buffer = NULL;
-	const unsigned char *current_buffer;
-	unsigned char *urb_buffer;
-	int i;
-	int retval = 0;
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	dbg("%s - %d byte(s)", __FUNCTION__, count);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not opened", __FUNCTION__);
-		return -EINVAL;
-	}
-
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __FUNCTION__);
-		return 0;
-	}
-	if (count == 1) {
-		dbg("%s - write request only included type %d", __FUNCTION__, buf[0]);
-		return 1;
-	}
-
-#ifdef DEBUG
-	printk (KERN_DEBUG __FILE__ ": %s - length = %d, data = ", __FUNCTION__, count);
-	for (i = 0; i < count; ++i) {
-		printk ("%.2x ", buf[i]);
-	}
-	printk ("\n");
-#endif
-
-	current_buffer = buf;
-
-	switch (*current_buffer) {
-		/* First byte indicates the type of packet */
-		case CMD_PKT:
-			/* dbg("%s- Send cmd_pkt len:%d", __FUNCTION__, count);*/
-
-			retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, &current_buffer[1], count-1);
-			if (retval) {
-				goto exit;
-			}
-			retval = count;
-			break;
-
-		case ACL_PKT:
-			++current_buffer;
-			--count;
-
-			urb_buffer = kmalloc (count, GFP_ATOMIC);
-			if (!urb_buffer) {
-				dev_err(&bluetooth->dev->dev, "out of memory\n");
-				retval = -ENOMEM;
-				goto exit;
-			}
-
-			urb = usb_alloc_urb(0, GFP_ATOMIC);
-			if (!urb) {
-				dev_err(&bluetooth->dev->dev, "no more free urbs\n");
-				kfree(urb_buffer);
-				retval = -ENOMEM;
-				goto exit;
-			}
-			memcpy (urb_buffer, current_buffer, count);
-
-			/* build up our urb */
-			usb_fill_bulk_urb(urb, bluetooth->dev, 
-					  usb_sndbulkpipe(bluetooth->dev,
-						  	  bluetooth->bulk_out_endpointAddress),
-					  urb_buffer,
-					  count,
-					  bluetooth_write_bulk_callback,
-					  bluetooth);
-
-
-			/* send it down the pipe */
-			retval = usb_submit_urb(urb, GFP_KERNEL);
-			if (retval) {
-				dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval);
-				goto exit;
-			}
-
-			/* we are done with this urb, so let the host driver
-			 * really free it when it is finished with it */
-			usb_free_urb (urb);
-			retval = count + 1;
-			break;
-		
-		default :
-			dbg("%s - unsupported (at this time) write type", __FUNCTION__);
-			retval = -EINVAL;
-			break;
-	}
-
-exit:
-	kfree(temp_buffer);
-
-	return retval;
-} 
-
-
-static int bluetooth_write_room (struct tty_struct *tty) 
-{
-	dbg("%s", __FUNCTION__);
-
-	/*
-	 * We really can take anything the user throws at us
-	 * but let's pick a nice big number to tell the tty
-	 * layer that we have lots of free space
-	 */
-	return 2048;
-}
-
-
-static int bluetooth_chars_in_buffer (struct tty_struct *tty) 
-{
-	dbg("%s", __FUNCTION__);
-
-	/* 
-	 * We can't really account for how much data we
-	 * have sent out, but hasn't made it through to the
-	 * device, so just tell the tty layer that everything
-	 * is flushed.
-	 */
-	return 0;
-}
-
-
-static void bluetooth_throttle (struct tty_struct * tty)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return;
-	}
-	
-	dbg("%s unsupported (at this time)", __FUNCTION__);
-
-	return;
-}
-
-
-static void bluetooth_unthrottle (struct tty_struct * tty)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return;
-	}
-
-	dbg("%s unsupported (at this time)", __FUNCTION__);
-}
-
-
-static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	dbg("%s - cmd 0x%.4x", __FUNCTION__, cmd);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return -ENODEV;
-	}
-
-	/* FIXME!!! */
-	return -ENOIOCTLCMD;
-}
-
-
-static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return;
-	}
-
-	/* FIXME!!! */
-
-	return;
-}
-
-
-#ifdef BTBUGGYHARDWARE
-void btusb_enable_bulk_read(struct tty_struct *tty){
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int result;
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return;
-	}
-
-	if (bluetooth->read_urb) {
-		usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, 
-			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-			      bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-		if (result)
-			err ("%s - failed submitting read urb, error %d", __FUNCTION__, result);
-	}
-}
-
-void btusb_disable_bulk_read(struct tty_struct *tty){
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return;
-	}
-
-	if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length))
-		usb_kill_urb(bluetooth->read_urb);
-}
-#endif
-
-
-/*****************************************************************************
- * urb callback functions
- *****************************************************************************/
-
-
-static void bluetooth_int_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-	unsigned char *data = urb->transfer_buffer;
-	unsigned int i;
-	unsigned int count = urb->actual_length;
-	unsigned int packet_size;
-	int status;
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth) {
-		dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-		return;
-	}
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	if (!count) {
-		dbg("%s - zero length int", __FUNCTION__);
-		goto exit;
-	}
-
-
-#ifdef DEBUG
-	if (count) {
-		printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
-		for (i = 0; i < count; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
-
-#ifdef BTBUGGYHARDWARE
-	if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) {
-		data += 2;
-		count -= 2;
-	}
-	if (count == 0) {
-		urb->actual_length = 0;
-		goto exit;
-	}
-#endif
-	/* We add  a packet type identifier to the beginning of each
-	   HCI frame.  This makes the data in the tty look like a
-	   serial USB devices.  Each HCI frame can be broken across
-	   multiple URBs so we buffer them until we have a full hci
-	   packet */
-
-	if (!bluetooth->int_packet_pos) {
-		bluetooth->int_buffer[0] = EVENT_PKT;
-		bluetooth->int_packet_pos++;
-	}
-	
-	if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
-		err("%s - exceeded EVENT_BUFFER_SIZE", __FUNCTION__);
-		bluetooth->int_packet_pos = 0;
-		goto exit;
-	}
-
-	memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos],
-		urb->transfer_buffer, count);
-	bluetooth->int_packet_pos += count;
-	urb->actual_length = 0;
-
-	if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE)
-		packet_size = bluetooth->int_buffer[2];
-	else
-		goto exit;
-
-	if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
-		err("%s - packet was too long", __FUNCTION__);
-		bluetooth->int_packet_pos = 0;
-		goto exit;
-	}
-
-	if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
-		for (i = 0; i < bluetooth->int_packet_pos; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
-			if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(bluetooth->tty);
-			}
-			tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
-		}
-		tty_flip_buffer_push(bluetooth->tty);
-
-		bluetooth->int_packet_pos = 0;
-	}
-
-exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, status);
-}
-
-
-static void bluetooth_ctrl_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth) {
-		dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-		return;
-	}
-
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-}
-
-
-static void bluetooth_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-	unsigned char *data = urb->transfer_buffer;
-	unsigned int count = urb->actual_length;
-	unsigned int i;
-	unsigned int packet_size;
-	int result;
-
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth) {
-		dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-		return;
-	}
-
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-		if (urb->status == -ENOENT) {                   
-			dbg("%s - URB canceled, won't reschedule", __FUNCTION__);
-			return;
-		}
-		goto exit;
-	}
-
-	if (!count) {
-		dbg("%s - zero length read bulk", __FUNCTION__);
-		goto exit;
-	}
-
-#ifdef DEBUG
-	if (count) {
-		printk (KERN_DEBUG __FILE__ ": %s- length = %d, data = ", __FUNCTION__, count);
-		for (i = 0; i < count; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
-#ifdef BTBUGGYHARDWARE
-	if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00)
-	    && (data[2] == 0x00) && (data[3] == 0x00)) {
-		urb->actual_length = 0;
-		usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, 
-			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-			      bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-		if (result)
-			err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-
-		return;
-	}
-#endif
-	/* We add  a packet type identifier to the beginning of each
-	   HCI frame.  This makes the data in the tty look like a
-	   serial USB devices.  Each HCI frame can be broken across
-	   multiple URBs so we buffer them until we have a full hci
-	   packet */
-	
-	if (!bluetooth->bulk_packet_pos) {
-		bluetooth->bulk_buffer[0] = ACL_PKT;
-		bluetooth->bulk_packet_pos++;
-	}
-
-	if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
-		err("%s - exceeded ACL_BUFFER_SIZE", __FUNCTION__);
-		bluetooth->bulk_packet_pos = 0;
-		goto exit;
-	}
-
-	memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos],
-		urb->transfer_buffer, count);
-	bluetooth->bulk_packet_pos += count;
-	urb->actual_length = 0;
-
-	if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) {
-		packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]);
-	} else {
-		goto exit;
-	}
-
-	if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
-		err("%s - packet was too long", __FUNCTION__);
-		bluetooth->bulk_packet_pos = 0;
-		goto exit;
-	}
-
-	if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
-		for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(bluetooth->tty);
-			}
-			tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
-		}
-		tty_flip_buffer_push(bluetooth->tty);
-		bluetooth->bulk_packet_pos = 0;
-	}	
-
-exit:
-	if (!bluetooth || !bluetooth->open_count)
-		return;
-
-	usb_fill_bulk_urb(bluetooth->read_urb, bluetooth->dev, 
-		      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-		      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-		      bluetooth_read_bulk_callback, bluetooth);
-	result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-	if (result)
-		err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-
-	return;
-}
-
-
-static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
-	dbg("%s", __FUNCTION__);
-
-	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree(urb->transfer_buffer);
-
-	if (!bluetooth) {
-		dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
-		return;
-	}
-
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	/* wake up our little function to let the tty layer know that something happened */
-	schedule_work(&bluetooth->work);
-}
-
-
-static void bluetooth_softint(void *private)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
-
-	dbg("%s", __FUNCTION__);
-
-	if (!bluetooth)
-		return;
-
-	tty_wakeup(bluetooth->tty);
-}
-
-
-static int usb_bluetooth_probe (struct usb_interface *intf, 
-				const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev (intf);
-	struct usb_bluetooth *bluetooth = NULL;
-	struct usb_host_interface *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_endpoint_descriptor *interrupt_in_endpoint[8];
-	struct usb_endpoint_descriptor *bulk_in_endpoint[8];
-	struct usb_endpoint_descriptor *bulk_out_endpoint[8];
-	int control_out_endpoint;
-
-	int minor;
-	int buffer_size;
-	int i;
-	int num_interrupt_in = 0;
-	int num_bulk_in = 0;
-	int num_bulk_out = 0;
-
-	interface = intf->cur_altsetting;
-	control_out_endpoint = interface->desc.bInterfaceNumber;
-
-	/* find the endpoints that we need */
-	for (i = 0; i < interface->desc.bNumEndpoints; ++i) {
-		endpoint = &interface->endpoint[i].desc;
-
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found a bulk in endpoint */
-			dbg("found bulk in");
-			bulk_in_endpoint[num_bulk_in] = endpoint;
-			++num_bulk_in;
-		}
-
-		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found a bulk out endpoint */
-			dbg("found bulk out");
-			bulk_out_endpoint[num_bulk_out] = endpoint;
-			++num_bulk_out;
-		}
-
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x03)) {
-			/* we found a interrupt in endpoint */
-			dbg("found interrupt in");
-			interrupt_in_endpoint[num_interrupt_in] = endpoint;
-			++num_interrupt_in;
-		}
-	}
-
-	/* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */
-	if ((num_bulk_in != 1) ||
-	    (num_bulk_out != 1) ||
-	    (num_interrupt_in != 1)) {
-		dbg ("%s - improper number of endpoints. Bluetooth driver not bound.", __FUNCTION__);
-		return -EIO;
-	}
-
-	info("USB Bluetooth converter detected");
-
-	for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor)
-		;
-	if (bluetooth_table[minor]) {
-		err("No more free Bluetooth devices");
-		return -ENODEV;
-	}
-
-	if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) {
-		err("Out of memory");
-		return -ENOMEM;
-	}
-
-	memset(bluetooth, 0, sizeof(struct usb_bluetooth));
-
-	bluetooth->magic = USB_BLUETOOTH_MAGIC;
-	bluetooth->dev = dev;
-	bluetooth->minor = minor;
-	INIT_WORK(&bluetooth->work, bluetooth_softint, bluetooth);
-	init_MUTEX(&bluetooth->lock);
-
-	/* record the interface number for the control out */
-	bluetooth->control_out_bInterfaceNum = control_out_endpoint;
-	
-	/* create our control out urb pool */ 
-	for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-		struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (urb == NULL) {
-			err("No free urbs available");
-			goto probe_error;
-		}
-		urb->transfer_buffer = NULL;
-		bluetooth->control_urb_pool[i] = urb;
-	}
-
-	/* set up the endpoint information */
-	endpoint = bulk_in_endpoint[0];
-	bluetooth->read_urb = usb_alloc_urb (0, GFP_KERNEL);
-	if (!bluetooth->read_urb) {
-		err("No free urbs available");
-		goto probe_error;
-	}
-	bluetooth->bulk_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-	bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress;
-	bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-	if (!bluetooth->bulk_in_buffer) {
-		err("Couldn't allocate bulk_in_buffer");
-		goto probe_error;
-	}
-	usb_fill_bulk_urb(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
-		      bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth);
-
-	endpoint = bulk_out_endpoint[0];
-	bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
-	bluetooth->bulk_out_buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
-
-	endpoint = interrupt_in_endpoint[0];
-	bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!bluetooth->interrupt_in_urb) {
-		err("No free urbs available");
-		goto probe_error;
-	}
-	bluetooth->interrupt_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-	bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
-	bluetooth->interrupt_in_interval = endpoint->bInterval;
-	bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-	if (!bluetooth->interrupt_in_buffer) {
-		err("Couldn't allocate interrupt_in_buffer");
-		goto probe_error;
-	}
-	usb_fill_int_urb(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-		     bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback,
-		     bluetooth, endpoint->bInterval);
-
-	/* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
-	tty_register_device (bluetooth_tty_driver, minor, &intf->dev);
-	info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
-
-	bluetooth_table[minor] = bluetooth;
-
-	/* success */
-	usb_set_intfdata (intf, bluetooth);
-	return 0;
-
-probe_error:
-	if (bluetooth->read_urb)
-		usb_free_urb (bluetooth->read_urb);
-	if (bluetooth->bulk_in_buffer)
-		kfree (bluetooth->bulk_in_buffer);
-	if (bluetooth->interrupt_in_urb)
-		usb_free_urb (bluetooth->interrupt_in_urb);
-	if (bluetooth->interrupt_in_buffer)
-		kfree (bluetooth->interrupt_in_buffer);
-	for (i = 0; i < NUM_CONTROL_URBS; ++i) 
-		if (bluetooth->control_urb_pool[i]) {
-			if (bluetooth->control_urb_pool[i]->transfer_buffer)
-				kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
-			usb_free_urb (bluetooth->control_urb_pool[i]);
-		}
-
-	bluetooth_table[minor] = NULL;
-
-	/* free up any memory that we allocated */
-	kfree (bluetooth);
-	return -EIO;
-}
-
-
-static void usb_bluetooth_disconnect(struct usb_interface *intf)
-{
-	struct usb_bluetooth *bluetooth = usb_get_intfdata (intf);
-	int i;
-
-	usb_set_intfdata (intf, NULL);
-	if (bluetooth) {
-		if ((bluetooth->open_count) && (bluetooth->tty))
-			tty_hangup(bluetooth->tty);
-
-		bluetooth->open_count = 0;
-
-		if (bluetooth->read_urb) {
-			usb_kill_urb (bluetooth->read_urb);
-			usb_free_urb (bluetooth->read_urb);
-		}
-		if (bluetooth->bulk_in_buffer)
-			kfree (bluetooth->bulk_in_buffer);
-
-		if (bluetooth->interrupt_in_urb) {
-			usb_kill_urb (bluetooth->interrupt_in_urb);
-			usb_free_urb (bluetooth->interrupt_in_urb);
-		}
-		if (bluetooth->interrupt_in_buffer)
-			kfree (bluetooth->interrupt_in_buffer);
-
-		tty_unregister_device (bluetooth_tty_driver, bluetooth->minor);
-
-		for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-			if (bluetooth->control_urb_pool[i]) {
-				usb_kill_urb (bluetooth->control_urb_pool[i]);
-				if (bluetooth->control_urb_pool[i]->transfer_buffer)
-					kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
-				usb_free_urb (bluetooth->control_urb_pool[i]);
-			}
-		}
-		
-		info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor);
-
-		bluetooth_table[bluetooth->minor] = NULL;
-
-		/* free up any memory that we allocated */
-		kfree (bluetooth);
-	} else {
-		info("device disconnected");
-	}
-}
-
-static struct tty_operations bluetooth_ops = {
-	.open =			bluetooth_open,
-	.close =		bluetooth_close,
-	.write =		bluetooth_write,
-	.write_room =		bluetooth_write_room,
-	.ioctl =		bluetooth_ioctl,
-	.set_termios =		bluetooth_set_termios,
-	.throttle =		bluetooth_throttle,
-	.unthrottle =		bluetooth_unthrottle,
-	.chars_in_buffer =	bluetooth_chars_in_buffer,
-};
-
-static int usb_bluetooth_init(void)
-{
-	int i;
-	int result;
-
-	/* Initialize our global data */
-	for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) {
-		bluetooth_table[i] = NULL;
-	}
-
-	info ("USB Bluetooth support registered");
-
-	bluetooth_tty_driver = alloc_tty_driver(BLUETOOTH_TTY_MINORS);
-	if (!bluetooth_tty_driver)
-		return -ENOMEM;
-
-	bluetooth_tty_driver->owner = THIS_MODULE;
-	bluetooth_tty_driver->driver_name = "usb-bluetooth";
-	bluetooth_tty_driver->name = "ttyUB";
-	bluetooth_tty_driver->devfs_name = "usb/ttub/";
-	bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR;
-	bluetooth_tty_driver->minor_start = 0;
-	bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	bluetooth_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	bluetooth_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	bluetooth_tty_driver->init_termios = tty_std_termios;
-	bluetooth_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	tty_set_operations(bluetooth_tty_driver, &bluetooth_ops);
-	if (tty_register_driver (bluetooth_tty_driver)) {
-		err("%s - failed to register tty driver", __FUNCTION__);
-		put_tty_driver(bluetooth_tty_driver);
-		return -1;
-	}
-
-	/* register the USB driver */
-	result = usb_register(&usb_bluetooth_driver);
-	if (result < 0) {
-		tty_unregister_driver(bluetooth_tty_driver);
-		put_tty_driver(bluetooth_tty_driver);
-		err("usb_register failed for the USB bluetooth driver. Error number %d", result);
-		return -1;
-	}
-
-	info(DRIVER_DESC " " DRIVER_VERSION);
-
-	return 0;
-}
-
-
-static void usb_bluetooth_exit(void)
-{
-	usb_deregister(&usb_bluetooth_driver);
-	tty_unregister_driver(bluetooth_tty_driver);
-	put_tty_driver(bluetooth_tty_driver);
-}
-
-
-module_init(usb_bluetooth_init);
-module_exit(usb_bluetooth_exit);
-
-/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 16ecad3..1b47514 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -827,11 +827,10 @@
 		return -ENODEV;
 	}
 
-	if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
-		dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
+	if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
+		dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
 		goto alloc_fail;
 	}
-	memset(acm, 0, sizeof(struct acm));
 
 	ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
 	readsize = le16_to_cpu(epread->wMaxPacketSize);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index e195709..357e753 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -844,9 +844,8 @@
 };
 
 static struct usb_class_driver usblp_class = {
-	.name =		"usb/lp%d",
+	.name =		"lp%d",
 	.fops =		&usblp_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
 	.minor_base =	USBLP_MINOR_BASE,
 };
 
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 1a9ff61..ff03184 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -61,14 +61,17 @@
 	  If you are unsure about this, say N here.
 
 config USB_SUSPEND
-	bool "USB suspend/resume (EXPERIMENTAL)"
+	bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
 	depends on USB && PM && EXPERIMENTAL
 	help
 	  If you say Y here, you can use driver calls or the sysfs
 	  "power/state" file to suspend or resume individual USB
-	  peripherals.  There are many related features, such as
-	  remote wakeup and driver-specific suspend processing, that
-	  may not yet work as expected.
+	  peripherals.
+
+	  Also, USB "remote wakeup" signaling is supported, whereby some
+	  USB devices (like keyboards and network adapters) can wake up
+	  their parent hub.  That wakeup cascades up the USB tree, and
+	  could wake the system from states like suspend-to-RAM.
 
 	  If you are unsure about this, say N here.
 
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index d5503cf..dd1c4d2 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -3,7 +3,7 @@
 #
 
 usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o \
-			config.o file.o buffer.o sysfs.o devio.o
+			config.o file.o buffer.o sysfs.o devio.o notify.o
 
 ifeq ($(CONFIG_PCI),y)
 	usbcore-objs	+= hcd-pci.o
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index fc15b4a..57e800a 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -106,7 +106,7 @@
 void *hcd_buffer_alloc (
 	struct usb_bus 		*bus,
 	size_t			size,
-	unsigned		mem_flags,
+	gfp_t			mem_flags,
 	dma_addr_t		*dma
 )
 {
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 99595e0..9930195 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -112,8 +112,12 @@
 	struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
 	int j;
 
-	for (j = 0; j < intfc->num_altsetting; j++)
-		kfree(intfc->altsetting[j].endpoint);
+	for (j = 0; j < intfc->num_altsetting; j++) {
+		struct usb_host_interface *alt = &intfc->altsetting[j];
+
+		kfree(alt->endpoint);
+		kfree(alt->string);
+	}
 	kfree(intfc);
 }
 
@@ -188,10 +192,9 @@
 	}
 
 	len = sizeof(struct usb_host_endpoint) * num_ep;
-	alt->endpoint = kmalloc(len, GFP_KERNEL);
+	alt->endpoint = kzalloc(len, GFP_KERNEL);
 	if (!alt->endpoint)
 		return -ENOMEM;
-	memset(alt->endpoint, 0, len);
 
 	/* Parse all the endpoint descriptors */
 	n = 0;
@@ -353,10 +356,9 @@
 		}
 
 		len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
-		config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
+		config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
 		if (!intfc)
 			return -ENOMEM;
-		memset(intfc, 0, len);
 		kref_init(&intfc->ref);
 	}
 
@@ -422,8 +424,6 @@
 		struct usb_host_config *cf = &dev->config[c];
 
 		kfree(cf->string);
-		cf->string = NULL;
-
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
 				kref_put(&cf->intf_cache[i]->ref, 
@@ -459,16 +459,14 @@
 	}
 
 	length = ncfg * sizeof(struct usb_host_config);
-	dev->config = kmalloc(length, GFP_KERNEL);
+	dev->config = kzalloc(length, GFP_KERNEL);
 	if (!dev->config)
 		goto err2;
-	memset(dev->config, 0, length);
 
 	length = ncfg * sizeof(char *);
-	dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
+	dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
 	if (!dev->rawdescriptors)
 		goto err2;
-	memset(dev->rawdescriptors, 0, length);
 
 	buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
 	if (!buffer)
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 487ff67..942cd43 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -46,6 +46,7 @@
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/cdev.h>
+#include <linux/notifier.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 #include <linux/moduleparam.h>
@@ -209,10 +210,10 @@
 static struct async *alloc_async(unsigned int numisoframes)
 {
         unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
-        struct async *as = kmalloc(assize, GFP_KERNEL);
+        struct async *as = kzalloc(assize, GFP_KERNEL);
+
         if (!as)
                 return NULL;
-        memset(as, 0, assize);
 	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
 	if (!as->urb) {
 		kfree(as);
@@ -279,6 +280,28 @@
         return NULL;
 }
 
+static void snoop_urb(struct urb *urb, void __user *userurb)
+{
+	int j;
+	unsigned char *data = urb->transfer_buffer;
+
+	if (!usbfs_snoop)
+		return;
+
+	if (urb->pipe & USB_DIR_IN)
+		dev_info(&urb->dev->dev, "direction=IN\n");
+	else
+		dev_info(&urb->dev->dev, "direction=OUT\n");
+	dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
+	dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
+		 urb->transfer_buffer_length);
+	dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
+	dev_info(&urb->dev->dev, "data: ");
+	for (j = 0; j < urb->transfer_buffer_length; ++j)
+		printk ("%02x ", data[j]);
+	printk("\n");
+}
+
 static void async_completed(struct urb *urb, struct pt_regs *regs)
 {
         struct async *as = (struct async *)urb->context;
@@ -296,7 +319,9 @@
 		kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid, 
 				      as->euid);
 	}
-        wake_up(&ps->wait);
+	snoop(&urb->dev->dev, "urb complete\n");
+	snoop_urb(urb, as->userurb);
+	wake_up(&ps->wait);
 }
 
 static void destroy_async (struct dev_state *ps, struct list_head *list)
@@ -493,6 +518,23 @@
 	return ret;
 }
 
+static struct usb_device *usbdev_lookup_minor(int minor)
+{
+	struct class_device *class_dev;
+	struct usb_device *dev = NULL;
+
+	down(&usb_device_class->sem);
+	list_for_each_entry(class_dev, &usb_device_class->children, node) {
+		if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
+			dev = class_dev->class_data;
+			break;
+		}
+	}
+	up(&usb_device_class->sem);
+
+	return dev;
+};
+
 /*
  * file operations
  */
@@ -601,7 +643,7 @@
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "control read: data ");
 				for (j = 0; j < i; ++j)
-					printk ("%02x ", (unsigned char)(tbuf)[j]);
+					printk("%02x ", (unsigned char)(tbuf)[j]);
 				printk("\n");
 			}
 			if (copy_to_user(ctrl.data, tbuf, i)) {
@@ -624,7 +666,7 @@
 		if (usbfs_snoop) {
 			dev_info(&dev->dev, "control write: data: ");
 			for (j = 0; j < ctrl.wLength; ++j)
-				printk ("%02x ", (unsigned char)(tbuf)[j]);
+				printk("%02x ", (unsigned char)(tbuf)[j]);
 			printk("\n");
 		}
 		usb_unlock_device(dev);
@@ -649,7 +691,7 @@
 	unsigned int tmo, len1, pipe;
 	int len2;
 	unsigned char *tbuf;
-	int i, ret;
+	int i, j, ret;
 
 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
 		return -EFAULT;
@@ -674,10 +716,18 @@
 			kfree(tbuf);
 			return -EINVAL;
 		}
+		snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n",
+			bulk.len, bulk.timeout);
 		usb_unlock_device(dev);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 		usb_lock_device(dev);
 		if (!i && len2) {
+			if (usbfs_snoop) {
+				dev_info(&dev->dev, "bulk read: data ");
+				for (j = 0; j < len2; ++j)
+					printk("%02x ", (unsigned char)(tbuf)[j]);
+				printk("\n");
+			}
 			if (copy_to_user(bulk.data, tbuf, len2)) {
 				kfree(tbuf);
 				return -EFAULT;
@@ -690,6 +740,14 @@
 				return -EFAULT;
 			}
 		}
+		snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n",
+			bulk.len, bulk.timeout);
+		if (usbfs_snoop) {
+			dev_info(&dev->dev, "bulk write: data: ");
+			for (j = 0; j < len1; ++j)
+				printk("%02x ", (unsigned char)(tbuf)[j]);
+			printk("\n");
+		}
 		usb_unlock_device(dev);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 		usb_lock_device(dev);
@@ -835,7 +893,6 @@
 	return status;
 }
 
-
 static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 			     struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
 			     void __user *arg)
@@ -896,6 +953,7 @@
 			kfree(dr);
 			return -EFAULT;
 		}
+		snoop(&ps->dev->dev, "control urb\n");
 		break;
 
 	case USBDEVFS_URB_TYPE_BULK:
@@ -910,6 +968,7 @@
 			return -EINVAL;
 		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
 			return -EFAULT;
+		snoop(&ps->dev->dev, "bulk urb\n");
 		break;
 
 	case USBDEVFS_URB_TYPE_ISO:
@@ -939,6 +998,7 @@
 			return -EINVAL;
 		}
 		uurb->buffer_length = totlen;
+		snoop(&ps->dev->dev, "iso urb\n");
 		break;
 
 	case USBDEVFS_URB_TYPE_INTERRUPT:
@@ -954,6 +1014,7 @@
 			return -EINVAL;
 		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
 			return -EFAULT;
+		snoop(&ps->dev->dev, "interrupt urb\n");
 		break;
 
 	default:
@@ -1003,6 +1064,8 @@
 			return -EFAULT;
 		}
 	}
+	snoop(&as->urb->dev->dev, "submit urb\n");
+	snoop_urb(as->urb, as->userurb);
         async_newpending(as);
         if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
 		dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
@@ -1238,23 +1301,20 @@
 	return 0;
 }
 
-static int proc_ioctl (struct dev_state *ps, void __user *arg)
+static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 {
-	struct usbdevfs_ioctl	ctrl;
 	int			size;
 	void			*buf = NULL;
 	int			retval = 0;
 	struct usb_interface    *intf = NULL;
 	struct usb_driver       *driver = NULL;
 
-	/* get input parameters and alloc buffer */
-	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
-		return -EFAULT;
-	if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
+	/* alloc buffer */
+	if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
 		if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
-		if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
-			if (copy_from_user (buf, ctrl.data, size)) {
+		if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
+			if (copy_from_user (buf, ctl->data, size)) {
 				kfree(buf);
 				return -EFAULT;
 			}
@@ -1270,9 +1330,9 @@
 
 	if (ps->dev->state != USB_STATE_CONFIGURED)
 		retval = -EHOSTUNREACH;
-	else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
+	else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
                retval = -EINVAL;
-	else switch (ctrl.ioctl_code) {
+	else switch (ctl->ioctl_code) {
 
 	/* disconnect kernel driver from interface */
 	case USBDEVFS_DISCONNECT:
@@ -1304,7 +1364,7 @@
 		if (driver == NULL || driver->ioctl == NULL) {
 			retval = -ENOTTY;
 		} else {
-			retval = driver->ioctl (intf, ctrl.ioctl_code, buf);
+			retval = driver->ioctl (intf, ctl->ioctl_code, buf);
 			if (retval == -ENOIOCTLCMD)
 				retval = -ENOTTY;
 		}
@@ -1313,15 +1373,42 @@
 
 	/* cleanup and return */
 	if (retval >= 0
-			&& (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
+			&& (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
 			&& size > 0
-			&& copy_to_user (ctrl.data, buf, size) != 0)
+			&& copy_to_user (ctl->data, buf, size) != 0)
 		retval = -EFAULT;
 
 	kfree(buf);
 	return retval;
 }
 
+static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
+{
+	struct usbdevfs_ioctl	ctrl;
+
+	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+		return -EFAULT;
+	return proc_ioctl(ps, &ctrl);
+}
+
+#ifdef CONFIG_COMPAT
+static int proc_ioctl_compat(struct dev_state *ps, void __user *arg)
+{
+	struct usbdevfs_ioctl32 __user *uioc;
+	struct usbdevfs_ioctl ctrl;
+	u32 udata;
+
+	uioc = compat_ptr(arg);
+	if (get_user(ctrl.ifno, &uioc->ifno) ||
+	    get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
+	    __get_user(udata, &uioc->data))
+		return -EFAULT;
+	ctrl.data = compat_ptr(udata);
+
+	return proc_ioctl(ps, &ctrl);
+}
+#endif
+
 /*
  * NOTE:  All requests here that have interface numbers as parameters
  * are assuming that somehow the configuration has been prevented from
@@ -1422,6 +1509,10 @@
 		ret = proc_reapurbnonblock_compat(ps, p);
 		break;
 
+	case USBDEVFS_IOCTL32:
+		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
+		ret = proc_ioctl_compat(ps, p);
+		break;
 #endif
 
 	case USBDEVFS_DISCARDURB:
@@ -1456,7 +1547,7 @@
 
 	case USBDEVFS_IOCTL:
 		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
-		ret = proc_ioctl(ps, p);
+		ret = proc_ioctl_default(ps, p);
 		break;
 	}
 	usb_unlock_device(dev);
@@ -1488,39 +1579,40 @@
 	.release =	usbdev_release,
 };
 
-struct usb_device *usbdev_lookup_minor(int minor)
-{
-	struct class_device *class_dev;
-	struct usb_device *dev = NULL;
-
-	down(&usb_device_class->sem);
-	list_for_each_entry(class_dev, &usb_device_class->children, node) {
-		if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
-			dev = class_dev->class_data;
-			break;
-		}
-	}
-	up(&usb_device_class->sem);
-
-	return dev;
-};
-
-void usbdev_add(struct usb_device *dev)
+static void usbdev_add(struct usb_device *dev)
 {
 	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
-	dev->class_dev = class_device_create(usb_device_class,
+	dev->class_dev = class_device_create(usb_device_class, NULL,
 				MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
 				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
 
 	dev->class_dev->class_data = dev;
 }
 
-void usbdev_remove(struct usb_device *dev)
+static void usbdev_remove(struct usb_device *dev)
 {
 	class_device_unregister(dev->class_dev);
 }
 
+static int usbdev_notify(struct notifier_block *self, unsigned long action,
+			 void *dev)
+{
+	switch (action) {
+	case USB_DEVICE_ADD:
+		usbdev_add(dev);
+		break;
+	case USB_DEVICE_REMOVE:
+		usbdev_remove(dev);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block usbdev_nb = {
+	.notifier_call = 	usbdev_notify,
+};
+
 static struct cdev usb_device_cdev = {
 	.kobj   = {.name = "usb_device", },
 	.owner  = THIS_MODULE,
@@ -1540,24 +1632,32 @@
 	retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
 	if (retval) {
 		err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
-		unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
-		goto out;
+		goto error_cdev;
 	}
 	usb_device_class = class_create(THIS_MODULE, "usb_device");
 	if (IS_ERR(usb_device_class)) {
 		err("unable to register usb_device class");
 		retval = PTR_ERR(usb_device_class);
-		usb_device_class = NULL;
-		cdev_del(&usb_device_cdev);
-		unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+		goto error_class;
 	}
 
+	usb_register_notify(&usbdev_nb);
+
 out:
 	return retval;
+
+error_class:
+	usb_device_class = NULL;
+	cdev_del(&usb_device_cdev);
+
+error_cdev:
+	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
+	goto out;
 }
 
 void usbdev_cleanup(void)
 {
+	usb_unregister_notify(&usbdev_nb);
 	class_destroy(usb_device_class);
 	cdev_del(&usb_device_cdev);
 	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 65ca131..e695308 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -17,7 +17,6 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 
@@ -88,8 +87,6 @@
 		goto out;
 	}
 
-	devfs_mk_dir("usb");
-
 out:
 	return error;
 }
@@ -97,7 +94,6 @@
 void usb_major_cleanup(void)
 {
 	class_destroy(usb_class);
-	devfs_remove("usb");
 	unregister_chrdev(USB_MAJOR, "usb");
 }
 
@@ -112,8 +108,7 @@
  * enabled, the minor number will be based on the next available free minor,
  * starting at the class_driver->minor_base.
  *
- * This function also creates the devfs file for the usb device, if devfs
- * is enabled, and creates a usb class device in the sysfs tree.
+ * This function also creates a usb class device in the sysfs tree.
  *
  * usb_deregister_dev() must be called when the driver is done with
  * the minor numbers given out by this function.
@@ -162,22 +157,20 @@
 
 	intf->minor = minor;
 
-	/* handle the devfs registration */
-	snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
-	devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
-
 	/* create a usb class device for this usb interface */
+	snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
 	temp = strrchr(name, '/');
 	if (temp && (temp[1] != 0x00))
 		++temp;
 	else
 		temp = name;
-	intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+	intf->class_dev = class_device_create(usb_class, NULL,
+					      MKDEV(USB_MAJOR, minor),
+					      &intf->dev, "%s", temp);
 	if (IS_ERR(intf->class_dev)) {
 		spin_lock (&minor_lock);
 		usb_minors[intf->minor] = NULL;
 		spin_unlock (&minor_lock);
-		devfs_remove (name);
 		retval = PTR_ERR(intf->class_dev);
 	}
 exit:
@@ -195,9 +188,8 @@
  * call to usb_register_dev() (usually when the device is disconnected
  * from the system.)
  *
- * This function also cleans up the devfs file for the usb device, if devfs
- * is enabled, and removes the usb class device from the sysfs tree.
- * 
+ * This function also removes the usb class device from the sysfs tree.
+ *
  * This should be called by all drivers that use the USB major number.
  */
 void usb_deregister_dev(struct usb_interface *intf,
@@ -220,7 +212,6 @@
 	spin_unlock (&minor_lock);
 
 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
-	devfs_remove (name);
 	class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));
 	intf->class_dev = NULL;
 	intf->minor = -1;
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 6385d1a..84d9e69 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -30,6 +30,8 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <linux/usb.h>
+
+#include "usb.h"
 #include "hcd.h"
 
 
@@ -197,6 +199,26 @@
 
 	hcd = pci_get_drvdata(dev);
 
+	/* Root hub suspend should have stopped all downstream traffic,
+	 * and all bus master traffic.  And done so for both the interface
+	 * and the stub usb_device (which we check here).  But maybe it
+	 * didn't; writing sysfs power/state files ignores such rules...
+	 *
+	 * We must ignore the FREEZE vs SUSPEND distinction here, because
+	 * otherwise the swsusp will save (and restore) garbage state.
+	 */
+	if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
+		return -EBUSY;
+
+	if (hcd->driver->suspend) {
+		retval = hcd->driver->suspend(hcd, message);
+		if (retval) {
+			dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n",
+				retval);
+			goto done;
+		}
+	}
+
 	/* FIXME until the generic PM interfaces change a lot more, this
 	 * can't use PCI D1 and D2 states.  For example, the confusion
 	 * between messages and states will need to vanish, and messages
@@ -215,31 +237,13 @@
 	 */
 	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
 
-	switch (hcd->state) {
-
-	/* entry if root hub wasn't yet suspended ... from sysfs,
-	 * without autosuspend, or if USB_SUSPEND isn't configured.
+	/* Downstream ports from this root hub should already be quiesced, so
+	 * there will be no DMA activity.  Now we can shut down the upstream
+	 * link (except maybe for PME# resume signaling) and enter some PCI
+	 * low power state, if the hardware allows.
 	 */
-	case HC_STATE_RUNNING:
-		hcd->state = HC_STATE_QUIESCING;
-		retval = hcd->driver->suspend (hcd, message);
-		if (retval) {
-			dev_dbg (hcd->self.controller, 
-					"suspend fail, retval %d\n",
-					retval);
-			break;
-		}
-		hcd->state = HC_STATE_SUSPENDED;
-		/* FALLTHROUGH */
+	if (hcd->state == HC_STATE_SUSPENDED) {
 
-	/* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
-	 * controller and/or root hub will already have been suspended,
-	 * but it won't be ready for a PCI resume call.
-	 *
-	 * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
-	 * have been called, otherwise root hub timers still run ...
-	 */
-	case HC_STATE_SUSPENDED:
 		/* no DMA or IRQs except when HC is active */
 		if (dev->current_state == PCI_D0) {
 			pci_save_state (dev);
@@ -248,7 +252,7 @@
 
 		if (!has_pci_pm) {
 			dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
-			break;
+			goto done;
 		}
 
 		/* NOTE:  dev->current_state becomes nonzero only here, and
@@ -259,28 +263,29 @@
 		retval = pci_set_power_state (dev, PCI_D3hot);
 		if (retval == 0) {
 			dev_dbg (hcd->self.controller, "--> PCI D3\n");
-			retval = pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
-			if (retval)
-				break;
-			retval = pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
-		} else if (retval < 0) {
+
+			/* Ignore these return values.  We rely on pci code to
+			 * reject requests the hardware can't implement, rather
+			 * than coding the same thing.
+			 */
+			(void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+			(void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
+		} else {
 			dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
 					retval);
 			(void) usb_hcd_pci_resume (dev);
-			break;
 		}
-		break;
-	default:
+
+	} else {
 		dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
 			hcd->state);
 		WARN_ON(1);
 		retval = -EINVAL;
-		break;
 	}
 
-	/* update power_state **ONLY** to make sysfs happier */
+done:
 	if (retval == 0)
-		dev->dev.power.power_state = message;
+		dev->dev.power.power_state = PMSG_SUSPEND;
 	return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_suspend);
@@ -336,20 +341,9 @@
 				dev->current_state);
 		}
 #endif
-		retval = pci_enable_wake (dev, dev->current_state, 0);
-		if (retval) {
-			dev_err(hcd->self.controller,
-				"can't enable_wake to %d, %d!\n",
-				dev->current_state, retval);
-			return retval;
-		}
-		retval = pci_enable_wake (dev, PCI_D3cold, 0);
-		if (retval) {
-			dev_err(hcd->self.controller,
-				"can't enable_wake to %d, %d!\n",
-				PCI_D3cold, retval);
-			return retval;
-		}
+		/* yes, ignore these results too... */
+		(void) pci_enable_wake (dev, dev->current_state, 0);
+		(void) pci_enable_wake (dev, PCI_D3cold, 0);
 	} else {
 		/* Same basic cases: clean (powered/not), dirty */
 		dev_dbg(hcd->self.controller, "PCI legacy resume\n");
@@ -371,17 +365,17 @@
 
 	dev->dev.power.power_state = PMSG_ON;
 
-	hcd->state = HC_STATE_RESUMING;
 	hcd->saw_irq = 0;
 
-	retval = hcd->driver->resume (hcd);
-	if (!HC_IS_RUNNING (hcd->state)) {
-		dev_dbg (hcd->self.controller, 
-				"resume fail, retval %d\n", retval);
-		usb_hc_died (hcd);
+	if (hcd->driver->resume) {
+		retval = hcd->driver->resume(hcd);
+		if (retval) {
+			dev_err (hcd->self.controller,
+				"PCI post-resume error %d!\n", retval);
+			usb_hc_died (hcd);
+		}
 	}
 
-	retval = pci_enable_device(dev);
 	return retval;
 }
 EXPORT_SYMBOL (usb_hcd_pci_resume);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1017a97..6c7ca5b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -130,7 +130,7 @@
 	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
 	0x00,	    /*  __u8  bDeviceSubClass; */
 	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
 	0x00, 0x00, /*  __le16 idVendor; */
  	0x00, 0x00, /*  __le16 idProduct; */
@@ -153,7 +153,7 @@
 	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
 	0x00,	    /*  __u8  bDeviceSubClass; */
 	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
 	0x00, 0x00, /*  __le16 idVendor; */
  	0x00, 0x00, /*  __le16 idProduct; */
@@ -458,22 +458,18 @@
 
 	default:
 		/* non-generic request */
-		if (HC_IS_SUSPENDED (hcd->state))
-			status = -EAGAIN;
-		else {
-			switch (typeReq) {
-			case GetHubStatus:
-			case GetPortStatus:
-				len = 4;
-				break;
-			case GetHubDescriptor:
-				len = sizeof (struct usb_hub_descriptor);
-				break;
-			}
-			status = hcd->driver->hub_control (hcd,
-				typeReq, wValue, wIndex,
-				tbuf, wLength);
+		switch (typeReq) {
+		case GetHubStatus:
+		case GetPortStatus:
+			len = 4;
+			break;
+		case GetHubDescriptor:
+			len = sizeof (struct usb_hub_descriptor);
+			break;
 		}
+		status = hcd->driver->hub_control (hcd,
+			typeReq, wValue, wIndex,
+			tbuf, wLength);
 		break;
 error:
 		/* "protocol stall" on error */
@@ -487,7 +483,7 @@
 				"CTRL: TypeReq=0x%x val=0x%x "
 				"idx=0x%x len=%d ==> %d\n",
 				typeReq, wValue, wIndex,
-				wLength, urb->status);
+				wLength, status);
 		}
 	}
 	if (len) {
@@ -748,10 +744,9 @@
 {
 	struct usb_bus *bus;
 
-	bus = kmalloc (sizeof *bus, GFP_KERNEL);
+	bus = kzalloc (sizeof *bus, GFP_KERNEL);
 	if (!bus)
 		return NULL;
-	memset(bus, 0, sizeof(struct usb_bus));
 	usb_bus_init (bus);
 	bus->op = op;
 	return bus;
@@ -782,7 +777,8 @@
 		return -E2BIG;
 	}
 
-	bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum);
+	bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
+					     bus->controller, "usb_host%d", busnum);
 	if (IS_ERR(bus->class_dev)) {
 		clear_bit(busnum, busmap.busmap);
 		up(&usb_bus_list_lock);
@@ -795,8 +791,7 @@
 	list_add (&bus->bus_list, &usb_bus_list);
 	up (&usb_bus_list_lock);
 
-	usbfs_add_bus (bus);
-	usbmon_notify_bus_add (bus);
+	usb_notify_add_bus(bus);
 
 	dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
 	return 0;
@@ -823,8 +818,7 @@
 	list_del (&bus->bus_list);
 	up (&usb_bus_list_lock);
 
-	usbmon_notify_bus_remove (bus);
-	usbfs_remove_bus (bus);
+	usb_notify_remove_bus(bus);
 
 	clear_bit (bus->busnum, busmap.busmap);
 
@@ -1112,7 +1106,7 @@
  * expects usb_submit_urb() to have sanity checked and conditioned all
  * inputs in the urb
  */
-static int hcd_submit_urb (struct urb *urb, unsigned mem_flags)
+static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
 	int			status;
 	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;
@@ -1142,10 +1136,20 @@
 	else switch (hcd->state) {
 	case HC_STATE_RUNNING:
 	case HC_STATE_RESUMING:
+doit:
 		usb_get_dev (urb->dev);
 		list_add_tail (&urb->urb_list, &ep->urb_list);
 		status = 0;
 		break;
+	case HC_STATE_SUSPENDED:
+		/* HC upstream links (register access, wakeup signaling) can work
+		 * even when the downstream links (and DMA etc) are quiesced; let
+		 * usbcore talk to the root hub.
+		 */
+		if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
+				&& urb->dev->parent == NULL)
+			goto doit;
+		/* FALL THROUGH */
 	default:
 		status = -ESHUTDOWN;
 		break;
@@ -1293,12 +1297,6 @@
 		goto done;
 	}
 
-	/* running ~= hc unlink handshake works (irq, timer, etc)
-	 * halted ~= no unlink handshake is needed
-	 * suspended, resuming == should never happen
-	 */
-	WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
-
 	/* insist the urb is still queued */
 	list_for_each(tmp, &ep->urb_list) {
 		if (tmp == &urb->urb_list)
@@ -1430,28 +1428,92 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef	CONFIG_USB_SUSPEND
+#ifdef	CONFIG_PM
 
-static int hcd_hub_suspend (struct usb_bus *bus)
+int hcd_bus_suspend (struct usb_bus *bus)
 {
 	struct usb_hcd		*hcd;
+	int			status;
 
 	hcd = container_of (bus, struct usb_hcd, self);
-	if (hcd->driver->hub_suspend)
-		return hcd->driver->hub_suspend (hcd);
-	return 0;
+	if (!hcd->driver->bus_suspend)
+		return -ENOENT;
+	hcd->state = HC_STATE_QUIESCING;
+	status = hcd->driver->bus_suspend (hcd);
+	if (status == 0)
+		hcd->state = HC_STATE_SUSPENDED;
+	else
+		dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+				"suspend", status);
+	return status;
 }
 
-static int hcd_hub_resume (struct usb_bus *bus)
+int hcd_bus_resume (struct usb_bus *bus)
 {
 	struct usb_hcd		*hcd;
+	int			status;
 
 	hcd = container_of (bus, struct usb_hcd, self);
-	if (hcd->driver->hub_resume)
-		return hcd->driver->hub_resume (hcd);
-	return 0;
+	if (!hcd->driver->bus_resume)
+		return -ENOENT;
+	if (hcd->state == HC_STATE_RUNNING)
+		return 0;
+	hcd->state = HC_STATE_RESUMING;
+	status = hcd->driver->bus_resume (hcd);
+	if (status == 0)
+		hcd->state = HC_STATE_RUNNING;
+	else {
+		dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+				"resume", status);
+		usb_hc_died(hcd);
+	}
+	return status;
 }
 
+/*
+ * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
+ * @hcd: host controller for this root hub
+ *
+ * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
+ * that the HCD's root hub polling is deactivated; and that the root's hub
+ * driver is suspended.  HCDs may call this to autosuspend when their root
+ * hub's downstream ports are all inactive:  unpowered, disconnected,
+ * disabled, or suspended.
+ *
+ * The HCD will autoresume on device connect change detection (using SRP
+ * or a D+/D- pullup).  The HCD also autoresumes on remote wakeup signaling
+ * from any ports that are suspended (if that is enabled).  In most cases,
+ * overcurrent signaling (on powered ports) will also start autoresume.
+ *
+ * Always called with IRQs blocked.
+ */
+void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
+{
+	struct urb	*urb;
+
+	spin_lock (&hcd_root_hub_lock);
+	usb_suspend_root_hub (hcd->self.root_hub);
+
+	/* force status urb to complete/unlink while suspended */
+	if (hcd->status_urb) {
+		urb = hcd->status_urb;
+		urb->status = -ECONNRESET;
+		urb->hcpriv = NULL;
+		urb->actual_length = 0;
+
+		del_timer (&hcd->rh_timer);
+		hcd->poll_pending = 0;
+		hcd->status_urb = NULL;
+	} else
+		urb = NULL;
+	spin_unlock (&hcd_root_hub_lock);
+	hcd->state = HC_STATE_SUSPENDED;
+
+	if (urb)
+		usb_hcd_giveback_urb (hcd, urb, NULL);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
+
 /**
  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
  * @hcd: host controller for this root hub
@@ -1459,7 +1521,7 @@
  * The USB host controller calls this function when its root hub is
  * suspended (with the remote wakeup feature enabled) and a remote
  * wakeup request is received.  It queues a request for khubd to
- * resume the root hub.
+ * resume the root hub (that is, manage its downstream ports again).
  */
 void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
 {
@@ -1470,14 +1532,10 @@
 		usb_resume_root_hub (hcd->self.root_hub);
 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
 }
-
-#else
-void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
-{
-}
-#endif
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 #ifdef	CONFIG_USB_OTG
@@ -1529,10 +1587,6 @@
 	.buffer_alloc =		hcd_buffer_alloc,
 	.buffer_free =		hcd_buffer_free,
 	.disable =		hcd_endpoint_disable,
-#ifdef	CONFIG_USB_SUSPEND
-	.hub_suspend =		hcd_hub_suspend,
-	.hub_resume =		hcd_hub_resume,
-#endif
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index ac451fa..24a62a2 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -142,22 +142,18 @@
 
 struct usb_operations {
 	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb *urb, unsigned mem_flags);
+	int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
 	int (*unlink_urb) (struct urb *urb, int status);
 
 	/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
 	void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
-			unsigned mem_flags,
+			gfp_t mem_flags,
 			dma_addr_t *dma);
 	void (*buffer_free)(struct usb_bus *bus, size_t size,
 			void *addr, dma_addr_t dma);
 
 	void (*disable)(struct usb_device *udev,
 			struct usb_host_endpoint *ep);
-
-	/* global suspend/resume of bus */
-	int (*hub_suspend)(struct usb_bus *);
-	int (*hub_resume)(struct usb_bus *);
 };
 
 /* each driver provides one of these, and hardware init support */
@@ -182,12 +178,12 @@
 	int	(*start) (struct usb_hcd *hcd);
 
 	/* NOTE:  these suspend/resume calls relate to the HC as
-	 * a whole, not just the root hub; they're for bus glue.
+	 * a whole, not just the root hub; they're for PCI bus glue.
 	 */
-	/* called after all devices were suspended */
+	/* called after suspending the hub, before entering D3 etc */
 	int	(*suspend) (struct usb_hcd *hcd, pm_message_t message);
 
-	/* called before any devices get resumed */
+	/* called after entering D0 (etc), before resuming the hub */
 	int	(*resume) (struct usb_hcd *hcd);
 
 	/* cleanly make HCD stop writing memory and doing I/O */
@@ -200,7 +196,7 @@
 	int	(*urb_enqueue) (struct usb_hcd *hcd,
 					struct usb_host_endpoint *ep,
 					struct urb *urb,
-					unsigned mem_flags);
+					gfp_t mem_flags);
 	int	(*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
 
 	/* hw synch, freeing endpoint resources that urb_dequeue can't */
@@ -212,8 +208,8 @@
 	int		(*hub_control) (struct usb_hcd *hcd,
 				u16 typeReq, u16 wValue, u16 wIndex,
 				char *buf, u16 wLength);
-	int		(*hub_suspend)(struct usb_hcd *);
-	int		(*hub_resume)(struct usb_hcd *);
+	int		(*bus_suspend)(struct usb_hcd *);
+	int		(*bus_resume)(struct usb_hcd *);
 	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
 	void		(*hub_irq_enable)(struct usb_hcd *);
 		/* Needed only if port-change IRQs are level-triggered */
@@ -247,7 +243,7 @@
 void hcd_buffer_destroy (struct usb_hcd *hcd);
 
 void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
-	unsigned mem_flags, dma_addr_t *dma);
+	gfp_t mem_flags, dma_addr_t *dma);
 void hcd_buffer_free (struct usb_bus *bus, size_t size,
 	void *addr, dma_addr_t dma);
 
@@ -355,8 +351,6 @@
 
 extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
 
-extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
-
 extern void usb_set_device_state(struct usb_device *udev,
 		enum usb_device_state new_state);
 
@@ -378,6 +372,33 @@
 
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
+#ifdef CONFIG_PM
+extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
+extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+extern int hcd_bus_suspend (struct usb_bus *bus);
+extern int hcd_bus_resume (struct usb_bus *bus);
+#else
+static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
+{
+	return;
+}
+
+static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
+{
+	return;
+}
+
+static inline int hcd_bus_suspend(struct usb_bus *bus)
+{
+	return 0;
+}
+
+static inline int hcd_bus_resume (struct usb_bus *bus)
+{
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 /*
  * USB device fs stuff
  */
@@ -388,23 +409,13 @@
  * these are expected to be called from the USB core/hub thread
  * with the kernel lock held
  */
-extern void usbfs_add_bus(struct usb_bus *bus);
-extern void usbfs_remove_bus(struct usb_bus *bus);
-extern void usbfs_add_device(struct usb_device *dev);
-extern void usbfs_remove_device(struct usb_device *dev);
 extern void usbfs_update_special (void);
-
 extern int usbfs_init(void);
 extern void usbfs_cleanup(void);
 
 #else /* CONFIG_USB_DEVICEFS */
 
-static inline void usbfs_add_bus(struct usb_bus *bus) {}
-static inline void usbfs_remove_bus(struct usb_bus *bus) {}
-static inline void usbfs_add_device(struct usb_device *dev) {}
-static inline void usbfs_remove_device(struct usb_device *dev) {}
 static inline void usbfs_update_special (void) {}
-
 static inline int usbfs_init(void) { return 0; }
 static inline void usbfs_cleanup(void) { }
 
@@ -419,8 +430,6 @@
 	void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
 	void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
 	/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
-	void (*bus_add)(struct usb_bus *bus);
-	void (*bus_remove)(struct usb_bus *bus);
 };
 
 extern struct usb_mon_operations *mon_ops;
@@ -443,18 +452,6 @@
 	if (bus->monitored)
 		(*mon_ops->urb_complete)(bus, urb);
 }
- 
-static inline void usbmon_notify_bus_add(struct usb_bus *bus)
-{
-	if (mon_ops)
-		(*mon_ops->bus_add)(bus);
-}
-
-static inline void usbmon_notify_bus_remove(struct usb_bus *bus)
-{
-	if (mon_ops)
-		(*mon_ops->bus_remove)(bus);
-}
 
 int usb_mon_register(struct usb_mon_operations *ops);
 void usb_mon_deregister(void);
@@ -465,8 +462,6 @@
 static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
     int error) {}
 static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
-static inline void usbmon_notify_bus_add(struct usb_bus *bus) {}
-static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {}
 
 #endif /* CONFIG_USB_MON */
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a12cab5..256d9f6 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -436,9 +436,10 @@
 {
 	int port1;
 	unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
+	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 
 	/* if hub supports power switching, enable power on each port */
-	if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
+	if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
 		dev_dbg(hub->intfdev, "enabling power on all ports\n");
 		for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
 			set_port_feature(hub->hdev, port1,
@@ -449,10 +450,18 @@
 	msleep(max(pgood_delay, (unsigned) 100));
 }
 
+static inline void __hub_quiesce(struct usb_hub *hub)
+{
+	/* (nonblocking) khubd and related activity won't re-trigger */
+	hub->quiescing = 1;
+	hub->activating = 0;
+	hub->resume_root_hub = 0;
+}
+
 static void hub_quiesce(struct usb_hub *hub)
 {
-	/* stop khubd and related activity */
-	hub->quiescing = 1;
+	/* (blocking) stop khubd and related activity */
+	__hub_quiesce(hub);
 	usb_kill_urb(hub->urb);
 	if (hub->has_indicators)
 		cancel_delayed_work(&hub->leds);
@@ -466,6 +475,7 @@
 
 	hub->quiescing = 0;
 	hub->activating = 1;
+	hub->resume_root_hub = 0;
 	status = usb_submit_urb(hub->urb, GFP_NOIO);
 	if (status < 0)
 		dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -516,6 +526,7 @@
 	struct usb_device *hdev = hub->hdev;
 	struct device *hub_dev = hub->intfdev;
 	u16 hubstatus, hubchange;
+	u16 wHubCharacteristics;
 	unsigned int pipe;
 	int maxp, ret;
 	char *message;
@@ -561,9 +572,9 @@
 	dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
 		(hdev->maxchild == 1) ? "" : "s");
 
-	le16_to_cpus(&hub->descriptor->wHubCharacteristics);
+	wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 
-	if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) {
+	if (wHubCharacteristics & HUB_CHAR_COMPOUND) {
 		int	i;
 		char	portstr [USB_MAXCHILDREN + 1];
 
@@ -576,7 +587,7 @@
 	} else
 		dev_dbg(hub_dev, "standalone hub\n");
 
-	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
+	switch (wHubCharacteristics & HUB_CHAR_LPSM) {
 		case 0x00:
 			dev_dbg(hub_dev, "ganged power switching\n");
 			break;
@@ -589,7 +600,7 @@
 			break;
 	}
 
-	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
+	switch (wHubCharacteristics & HUB_CHAR_OCPM) {
 		case 0x00:
 			dev_dbg(hub_dev, "global over-current protection\n");
 			break;
@@ -629,7 +640,7 @@
 	}
 
 	/* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
-	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) {
+	switch (wHubCharacteristics & HUB_CHAR_TTTT) {
 		case HUB_TTTT_8_BITS:
 			if (hdev->descriptor.bDeviceProtocol != 0) {
 				hub->tt.think_time = 666;
@@ -659,7 +670,7 @@
 	}
 
 	/* probe() zeroes hub->indicator[] */
-	if (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) {
+	if (wHubCharacteristics & HUB_CHAR_PORTIND) {
 		hub->has_indicators = 1;
 		dev_dbg(hub_dev, "Port indicators are supported\n");
 	}
@@ -704,7 +715,7 @@
 			(hubstatus & HUB_STATUS_LOCAL_POWER)
 			? "lost (inactive)" : "good");
 
-	if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) == 0)
+	if ((wHubCharacteristics & HUB_CHAR_OCPM) == 0)
 		dev_dbg(hub_dev, "%sover-current condition exists\n",
 			(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
 
@@ -854,14 +865,12 @@
 	/* We found a hub */
 	dev_info (&intf->dev, "USB hub found\n");
 
-	hub = kmalloc(sizeof(*hub), GFP_KERNEL);
+	hub = kzalloc(sizeof(*hub), GFP_KERNEL);
 	if (!hub) {
 		dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
 		return -ENOMEM;
 	}
 
-	memset(hub, 0, sizeof(*hub));
-
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->intfdev = &intf->dev;
 	hub->hdev = hdev;
@@ -1020,9 +1029,15 @@
 	spin_lock_irqsave(&device_state_lock, flags);
 	if (udev->state == USB_STATE_NOTATTACHED)
 		;	/* do nothing */
-	else if (new_state != USB_STATE_NOTATTACHED)
+	else if (new_state != USB_STATE_NOTATTACHED) {
 		udev->state = new_state;
-	else
+		if (new_state == USB_STATE_CONFIGURED)
+			device_init_wakeup(&udev->dev,
+				(udev->actconfig->desc.bmAttributes
+				 & USB_CONFIG_ATT_WAKEUP));
+		else if (new_state != USB_STATE_SUSPENDED)
+			device_init_wakeup(&udev->dev, 0);
+	} else
 		recursively_mark_NOTATTACHED(udev);
 	spin_unlock_irqrestore(&device_state_lock, flags);
 }
@@ -1111,14 +1126,14 @@
 	 */
 	usb_disable_device(udev, 0);
 
+	usb_notify_remove_device(udev);
+
 	/* Free the device number, remove the /proc/bus/usb entry and
 	 * the sysfs attributes, and delete the parent's children[]
 	 * (or root_hub) pointer.
 	 */
 	dev_dbg (&udev->dev, "unregistering device\n");
 	release_address(udev);
-	usbfs_remove_device(udev);
-	usbdev_remove(udev);
 	usb_remove_sysfs_dev_files(udev);
 
 	/* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1189,21 +1204,6 @@
 {}
 #endif
 
-static void get_string(struct usb_device *udev, char **string, int index)
-{
-	char *buf;
-
-	if (!index)
-		return;
-	buf = kmalloc(256, GFP_KERNEL);
-	if (!buf)
-		return;
-	if (usb_string(udev, index, buf, 256) > 0)
-		*string = buf;
-	else
-		kfree(buf);
-}
-
 
 #ifdef	CONFIG_USB_OTG
 #include "otg_whitelist.h"
@@ -1242,9 +1242,10 @@
 	}
 
 	/* read the standard strings and cache them if present */
-	get_string(udev, &udev->product, udev->descriptor.iProduct);
-	get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
-	get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
+	udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
+	udev->manufacturer = usb_cache_string(udev,
+			udev->descriptor.iManufacturer);
+	udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
 
 	/* Tell the world! */
 	dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
@@ -1316,11 +1317,9 @@
 		 * (Includes HNP test device.)
 		 */
 		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-			static int __usb_suspend_device (struct usb_device *,
-						int port1, pm_message_t state);
-			err = __usb_suspend_device(udev,
-					udev->bus->otg_port,
-					PMSG_SUSPEND);
+			static int __usb_suspend_device(struct usb_device *,
+						int port1);
+			err = __usb_suspend_device(udev, udev->bus->otg_port);
 			if (err < 0)
 				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
 		}
@@ -1356,10 +1355,8 @@
 	}
 
 	/* USB device state == configured ... usable */
+	usb_notify_add_device(udev);
 
-	/* add a /proc/bus/usb entry */
-	usbdev_add(udev);
-	usbfs_add_device(udev);
 	return 0;
 
 fail:
@@ -1510,7 +1507,7 @@
 	/* FIXME let caller ask to power down the port:
 	 *  - some devices won't enumerate without a VBUS power cycle
 	 *  - SRP saves power that way
-	 *  - usb_suspend_device(dev, PMSG_SUSPEND)
+	 *  - ... new call, TBD ...
 	 * That's easy if this hub can switch power per-port, and
 	 * khubd reactivates the port later (timer, SRP, etc).
 	 * Powerdown must be optional, because of reset/DFU.
@@ -1546,11 +1543,7 @@
 	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
 	 * we don't explicitly enable it here.
 	 */
-	if (udev->actconfig
-			// && FIXME (remote wakeup enabled on this bus)
-			// ... currently assuming it's always appropriate
-			&& (udev->actconfig->desc.bmAttributes
-				& USB_CONFIG_ATT_WAKEUP) != 0) {
+	if (device_may_wakeup(&udev->dev)) {
 		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
 				USB_DEVICE_REMOTE_WAKEUP, 0,
@@ -1596,11 +1589,14 @@
  * Other than re-initializing the hub (plug/unplug, except for root hubs),
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
+ *
+ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+ * the root hub for their bus goes into global suspend ... so we don't
+ * (falsely) update the device power state to say it suspended.
  */
-static int __usb_suspend_device (struct usb_device *udev, int port1,
-				 pm_message_t state)
+static int __usb_suspend_device (struct usb_device *udev, int port1)
 {
-	int	status;
+	int	status = 0;
 
 	/* caller owns the udev device lock */
 	if (port1 < 0)
@@ -1611,95 +1607,39 @@
 		return 0;
 	}
 
-	/* suspend interface drivers; if this is a hub, it
-	 * suspends the child devices
-	 */
+	/* all interfaces must already be suspended */
 	if (udev->actconfig) {
 		int	i;
 
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			struct usb_interface	*intf;
-			struct usb_driver	*driver;
 
 			intf = udev->actconfig->interface[i];
-			if (state.event <= intf->dev.power.power_state.event)
-				continue;
-			if (!intf->dev.driver)
-				continue;
-			driver = to_usb_driver(intf->dev.driver);
-
-			if (driver->suspend) {
-				status = driver->suspend(intf, state);
-				if (intf->dev.power.power_state.event != state.event
-						|| status)
-					dev_err(&intf->dev,
-						"suspend %d fail, code %d\n",
-						state.event, status);
-			}
-
-			/* only drivers with suspend() can ever resume();
-			 * and after power loss, even they won't.
-			 * bus_rescan_devices() can rebind drivers later.
-			 *
-			 * FIXME the PM core self-deadlocks when unbinding
-			 * drivers during suspend/resume ... everything grabs
-			 * dpm_sem (not a spinlock, ugh).  we want to unbind,
-			 * since we know every driver's probe/disconnect works
-			 * even for drivers that can't suspend.
-			 */
-			if (!driver->suspend || state.event > PM_EVENT_FREEZE) {
-#if 1
-				dev_warn(&intf->dev, "resume is unsafe!\n");
-#else
-				down_write(&usb_bus_type.rwsem);
-				device_release_driver(&intf->dev);
-				up_write(&usb_bus_type.rwsem);
-#endif
+			if (is_active(intf)) {
+				dev_dbg(&intf->dev, "nyet suspended\n");
+				return -EBUSY;
 			}
 		}
 	}
 
-	/*
-	 * FIXME this needs port power off call paths too, to help force
-	 * USB into the "generic" PM model.  At least for devices on
-	 * ports that aren't using ganged switching (usually root hubs).
-	 *
-	 * NOTE: SRP-capable links should adopt more aggressive poweroff
-	 * policies (when HNP doesn't apply) once we have mechanisms to
-	 * turn power back on!  (Likely not before 2.7...)
+	/* we only change a device's upstream USB link.
+	 * root hubs have no upstream USB link.
 	 */
-	if (state.event > PM_EVENT_FREEZE) {
-		dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
-	}
-
-	/* "global suspend" of the HC-to-USB interface (root hub), or
-	 * "selective suspend" of just one hub-device link.
-	 */
-	if (!udev->parent) {
-		struct usb_bus	*bus = udev->bus;
-		if (bus && bus->op->hub_suspend) {
-			status = bus->op->hub_suspend (bus);
-			if (status == 0) {
-				dev_dbg(&udev->dev, "usb suspend\n");
-				usb_set_device_state(udev,
-						USB_STATE_SUSPENDED);
-			}
-		} else
-			status = -EOPNOTSUPP;
-	} else
+	if (udev->parent)
 		status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
 				udev);
 
 	if (status == 0)
-		udev->dev.power.power_state = state;
+		udev->dev.power.power_state = PMSG_SUSPEND;
 	return status;
 }
 
-/**
+#endif
+
+/*
  * usb_suspend_device - suspend a usb device
  * @udev: device that's no longer in active use
- * @state: PMSG_SUSPEND to suspend
- * Context: must be able to sleep; device not locked
+ * Context: must be able to sleep; device not locked; pm locks held
  *
  * Suspends a USB device that isn't in active use, conserving power.
  * Devices may wake out of a suspend, if anything important happens,
@@ -1707,37 +1647,50 @@
  * suspend by the host, using usb_resume_device().  It's also routine
  * to disconnect devices while they are suspended.
  *
+ * This only affects the USB hardware for a device; its interfaces
+ * (and, for hubs, child devices) must already have been suspended.
+ *
  * Suspending OTG devices may trigger HNP, if that's been enabled
  * between a pair of dual-role devices.  That will change roles, such
  * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
+int usb_suspend_device(struct usb_device *udev)
 {
+#ifdef	CONFIG_USB_SUSPEND
 	int	port1, status;
 
 	port1 = locktree(udev);
 	if (port1 < 0)
 		return port1;
 
-	status = __usb_suspend_device(udev, port1, state);
+	status = __usb_suspend_device(udev, port1);
 	usb_unlock_device(udev);
 	return status;
+#else
+	/* NOTE:  udev->state unchanged, it's not lying ... */
+	udev->dev.power.power_state = PMSG_SUSPEND;
+	return 0;
+#endif
 }
+EXPORT_SYMBOL_GPL(usb_suspend_device);
 
 /*
+ * If the USB "suspend" state is in use (rather than "global suspend"),
+ * many devices will be individually taken out of suspend state using
+ * special" resume" signaling.  These routines kick in shortly after
  * hardware resume signaling is finished, either because of selective
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
  */
-static int finish_port_resume(struct usb_device *udev)
+static int finish_device_resume(struct usb_device *udev)
 {
 	int	status;
 	u16	devstatus;
 
 	/* caller owns the udev device lock */
-	dev_dbg(&udev->dev, "usb resume\n");
+	dev_dbg(&udev->dev, "finish resume\n");
 
 	/* usb ch9 identifies four variants of SUSPENDED, based on what
 	 * state the device resumes to.  Linux currently won't see the
@@ -1747,7 +1700,6 @@
 	usb_set_device_state(udev, udev->actconfig
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
-	udev->dev.power.power_state = PMSG_ON;
 
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
@@ -1760,9 +1712,11 @@
 			status);
 	else if (udev->actconfig) {
 		unsigned	i;
+		int		(*resume)(struct device *);
 
 		le16_to_cpus(&devstatus);
-		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
+				&& udev->parent) {
 			status = usb_control_msg(udev,
 					usb_sndctrlpipe(udev, 0),
 					USB_REQ_CLEAR_FEATURE,
@@ -1778,33 +1732,11 @@
 		}
 
 		/* resume interface drivers; if this is a hub, it
-		 * resumes the child devices
+		 * may have a child resume event to deal with soon
 		 */
-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-			struct usb_interface	*intf;
-			struct usb_driver	*driver;
-
-			intf = udev->actconfig->interface[i];
-			if (intf->dev.power.power_state.event == PM_EVENT_ON)
-				continue;
-			if (!intf->dev.driver) {
-				/* FIXME maybe force to alt 0 */
-				continue;
-			}
-			driver = to_usb_driver(intf->dev.driver);
-
-			/* bus_rescan_devices() may rebind drivers */
-			if (!driver->resume)
-				continue;
-
-			/* can we do better than just logging errors? */
-			status = driver->resume(intf);
-			if (intf->dev.power.power_state.event != PM_EVENT_ON
-					|| status)
-				dev_dbg(&intf->dev,
-					"resume fail, state %d code %d\n",
-					intf->dev.power.power_state.event, status);
-		}
+		resume = udev->dev.bus->resume;
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
+			(void) resume(&udev->actconfig->interface[i]->dev);
 		status = 0;
 
 	} else if (udev->devnum <= 0) {
@@ -1814,6 +1746,8 @@
 	return status;
 }
 
+#ifdef	CONFIG_USB_SUSPEND
+
 static int
 hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 {
@@ -1859,7 +1793,7 @@
 			/* TRSMRCY = 10 msec */
 			msleep(10);
 			if (udev)
-				status = finish_port_resume(udev);
+				status = finish_device_resume(udev);
 		}
 	}
 	if (status < 0)
@@ -1868,12 +1802,12 @@
 	return status;
 }
 
-static int hub_resume (struct usb_interface *intf);
+#endif
 
-/**
+/*
  * usb_resume_device - re-activate a suspended usb device
  * @udev: device to re-activate
- * Context: must be able to sleep; device not locked
+ * Context: must be able to sleep; device not locked; pm locks held
  *
  * This will re-activate the suspended device, increasing power usage
  * while letting drivers communicate again with its endpoints.
@@ -1891,35 +1825,22 @@
 	if (port1 < 0)
 		return port1;
 
-	/* "global resume" of the HC-to-USB interface (root hub), or
-	 * selective resume of one hub-to-device port
-	 */
-	if (!udev->parent) {
-		struct usb_bus	*bus = udev->bus;
-		if (bus && bus->op->hub_resume) {
-			status = bus->op->hub_resume (bus);
+#ifdef	CONFIG_USB_SUSPEND
+	/* selective resume of one downstream hub-to-device port */
+	if (udev->parent) {
+		if (udev->state == USB_STATE_SUSPENDED) {
+			// NOTE swsusp may bork us, device state being wrong...
+			// NOTE this fails if parent is also suspended...
+			status = hub_port_resume(hdev_to_hub(udev->parent),
+					port1, udev);
 		} else
-			status = -EOPNOTSUPP;
-		if (status == 0) {
-			dev_dbg(&udev->dev, "usb resume\n");
-			/* TRSMRCY = 10 msec */
-			msleep(10);
-			usb_set_device_state (udev, USB_STATE_CONFIGURED);
-			udev->dev.power.power_state = PMSG_ON;
-			status = hub_resume (udev
-					->actconfig->interface[0]);
-		}
-	} else if (udev->state == USB_STATE_SUSPENDED) {
-		// NOTE this fails if parent is also suspended...
-		status = hub_port_resume(hdev_to_hub(udev->parent),
-				port1, udev);
-	} else {
-		status = 0;
-	}
-	if (status < 0) {
+			status = 0;
+	} else
+#endif
+		status = finish_device_resume(udev);
+	if (status < 0)
 		dev_dbg(&udev->dev, "can't resume, status %d\n",
 			status);
-	}
 
 	usb_unlock_device(udev);
 
@@ -1936,6 +1857,8 @@
 {
 	int	status = 0;
 
+#ifdef	CONFIG_USB_SUSPEND
+
 	/* don't repeat RESUME sequence if this device
 	 * was already woken up by some other task
 	 */
@@ -1944,38 +1867,52 @@
 		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
 		/* TRSMRCY = 10 msec */
 		msleep(10);
-		status = finish_port_resume(udev);
+		status = finish_device_resume(udev);
 	}
 	up(&udev->serialize);
+#endif
 	return status;
 }
 
-static int hub_suspend(struct usb_interface *intf, pm_message_t state)
+static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
 	struct usb_hub		*hub = usb_get_intfdata (intf);
 	struct usb_device	*hdev = hub->hdev;
 	unsigned		port1;
-	int			status;
 
-	/* stop khubd and related activity */
-	hub_quiesce(hub);
-
-	/* then suspend every port */
+	/* fail if children aren't already suspended */
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
 		struct usb_device	*udev;
 
 		udev = hdev->children [port1-1];
-		if (!udev)
-			continue;
-		down(&udev->serialize);
-		status = __usb_suspend_device(udev, port1, state);
-		up(&udev->serialize);
-		if (status < 0)
-			dev_dbg(&intf->dev, "suspend port %d --> %d\n",
-				port1, status);
+		if (udev && (udev->dev.power.power_state.event
+					== PM_EVENT_ON
+#ifdef	CONFIG_USB_SUSPEND
+				|| udev->state != USB_STATE_SUSPENDED
+#endif
+				)) {
+			dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+			return -EBUSY;
+		}
 	}
 
-	intf->dev.power.power_state = state;
+	/* "global suspend" of the downstream HC-to-USB interface */
+	if (!hdev->parent) {
+		struct usb_bus	*bus = hdev->bus;
+		if (bus) {
+			int	status = hcd_bus_suspend (bus);
+
+			if (status != 0) {
+				dev_dbg(&hdev->dev, "'global' suspend %d\n",
+					status);
+				return status;
+			}
+		} else
+			return -EOPNOTSUPP;
+	}
+
+	/* stop khubd and related activity */
+	hub_quiesce(hub);
 	return 0;
 }
 
@@ -1983,11 +1920,35 @@
 {
 	struct usb_device	*hdev = interface_to_usbdev(intf);
 	struct usb_hub		*hub = usb_get_intfdata (intf);
-	unsigned		port1;
 	int			status;
 
-	if (intf->dev.power.power_state.event == PM_EVENT_ON)
-		return 0;
+	/* "global resume" of the downstream HC-to-USB interface */
+	if (!hdev->parent) {
+		struct usb_bus	*bus = hdev->bus;
+		if (bus) {
+			status = hcd_bus_resume (bus);
+			if (status) {
+				dev_dbg(&intf->dev, "'global' resume %d\n",
+					status);
+				return status;
+			}
+		} else
+			return -EOPNOTSUPP;
+		if (status == 0) {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+		}
+	}
+
+	hub_activate(hub);
+
+	/* REVISIT:  this recursion probably shouldn't exist.  Remove
+	 * this code sometime, after retesting with different root and
+	 * external hubs.
+	 */
+#ifdef	CONFIG_USB_SUSPEND
+	{
+	unsigned		port1;
 
 	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
 		struct usb_device	*udev;
@@ -2013,7 +1974,7 @@
 		if (portstat & USB_PORT_STAT_SUSPEND)
 			status = hub_port_resume(hub, port1, udev);
 		else {
-			status = finish_port_resume(udev);
+			status = finish_device_resume(udev);
 			if (status < 0) {
 				dev_dbg(&intf->dev, "resume port %d --> %d\n",
 					port1, status);
@@ -2022,13 +1983,23 @@
 		}
 		up(&udev->serialize);
 	}
-	intf->dev.power.power_state = PMSG_ON;
-
-	hub->resume_root_hub = 0;
-	hub_activate(hub);
+	}
+#endif
 	return 0;
 }
 
+void usb_suspend_root_hub(struct usb_device *hdev)
+{
+	struct usb_hub *hub = hdev_to_hub(hdev);
+
+	/* This also makes any led blinker stop retriggering.  We're called
+	 * from irq, so the blinker might still be scheduled.  Caller promises
+	 * that the root hub status URB will be canceled.
+	 */
+	__hub_quiesce(hub);
+	mark_quiesced(to_usb_interface(hub->intfdev));
+}
+
 void usb_resume_root_hub(struct usb_device *hdev)
 {
 	struct usb_hub *hub = hdev_to_hub(hdev);
@@ -2037,28 +2008,6 @@
 	kick_khubd(hub);
 }
 
-#else	/* !CONFIG_USB_SUSPEND */
-
-int usb_suspend_device(struct usb_device *udev, pm_message_t state)
-{
-	return 0;
-}
-
-int usb_resume_device(struct usb_device *udev)
-{
-	return 0;
-}
-
-#define	hub_suspend		NULL
-#define	hub_resume		NULL
-#define	remote_wakeup(x)	0
-
-#endif	/* CONFIG_USB_SUSPEND */
-
-EXPORT_SYMBOL(usb_suspend_device);
-EXPORT_SYMBOL(usb_resume_device);
-
-
 
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
  *
@@ -2467,6 +2416,7 @@
 {
 	struct usb_device *hdev = hub->hdev;
 	struct device *hub_dev = hub->intfdev;
+	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 	int status, i;
  
 	dev_dbg (hub_dev,
@@ -2504,8 +2454,7 @@
 	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 
 		/* maybe switch power back on (e.g. root hub was reset) */
-		if ((hub->descriptor->wHubCharacteristics
-					& HUB_CHAR_LPSM) < 2
+		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
 				&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
 			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
  
@@ -2684,21 +2633,28 @@
 		intf = to_usb_interface(hub->intfdev);
 		hub_dev = &intf->dev;
 
-		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
+		i = hub->resume_root_hub;
+
+		dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
 				hdev->state, hub->descriptor
 					? hub->descriptor->bNbrPorts
 					: 0,
 				/* NOTE: expects max 15 ports... */
 				(u16) hub->change_bits[0],
-				(u16) hub->event_bits[0]);
+				(u16) hub->event_bits[0],
+				i ? ", resume root" : "");
 
 		usb_get_intf(intf);
-		i = hub->resume_root_hub;
 		spin_unlock_irq(&hub_event_lock);
 
-		/* Is this is a root hub wanting to be resumed? */
-		if (i)
-			usb_resume_device(hdev);
+		/* Is this is a root hub wanting to reactivate the downstream
+		 * ports?  If so, be sure the interface resumes even if its
+		 * stub "device" node was never suspended.
+		 */
+		if (i) {
+			dpm_runtime_resume(&hdev->dev);
+			dpm_runtime_resume(&intf->dev);
+		}
 
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index e7fa9b5..bf23f89 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -131,7 +131,7 @@
 	__u8  bDescLength;
 	__u8  bDescriptorType;
 	__u8  bNbrPorts;
-	__u16 wHubCharacteristics;
+	__le16 wHubCharacteristics;
 	__u8  bPwrOn2PwrGood;
 	__u8  bHubContrCurrent;
 	    	/* add 1 bit for hub status change; round to bytes */
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index d07bba0..12f490f 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -39,6 +39,7 @@
 #include <linux/usbdevice_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/parser.h>
+#include <linux/notifier.h>
 #include <asm/byteorder.h>
 #include "usb.h"
 #include "hcd.h"
@@ -619,7 +620,7 @@
 	}
 }
 
-void usbfs_add_bus(struct usb_bus *bus)
+static void usbfs_add_bus(struct usb_bus *bus)
 {
 	struct dentry *parent;
 	char name[8];
@@ -642,12 +643,9 @@
 		err ("error creating usbfs bus entry");
 		return;
 	}
-
-	usbfs_update_special();
-	usbfs_conn_disc_event();
 }
 
-void usbfs_remove_bus(struct usb_bus *bus)
+static void usbfs_remove_bus(struct usb_bus *bus)
 {
 	if (bus->usbfs_dentry) {
 		fs_remove_file (bus->usbfs_dentry);
@@ -659,12 +657,9 @@
 		remove_special_files();
 		num_buses = 0;
 	}
-
-	usbfs_update_special();
-	usbfs_conn_disc_event();
 }
 
-void usbfs_add_device(struct usb_device *dev)
+static void usbfs_add_device(struct usb_device *dev)
 {
 	char name[8];
 	int i;
@@ -690,12 +685,9 @@
 	}
 	if (dev->usbfs_dentry->d_inode)
 		dev->usbfs_dentry->d_inode->i_size = i_size;
-
-	usbfs_update_special();
-	usbfs_conn_disc_event();
 }
 
-void usbfs_remove_device(struct usb_device *dev)
+static void usbfs_remove_device(struct usb_device *dev)
 {
 	struct dev_state *ds;
 	struct siginfo sinfo;
@@ -716,10 +708,33 @@
 			kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid);
 		}
 	}
+}
+
+static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
+{
+	switch (action) {
+	case USB_DEVICE_ADD:
+		usbfs_add_device(dev);
+		break;
+	case USB_DEVICE_REMOVE:
+		usbfs_remove_device(dev);
+		break;
+	case USB_BUS_ADD:
+		usbfs_add_bus(dev);
+		break;
+	case USB_BUS_REMOVE:
+		usbfs_remove_bus(dev);
+	}
+
 	usbfs_update_special();
 	usbfs_conn_disc_event();
+	return NOTIFY_OK;
 }
 
+static struct notifier_block usbfs_nb = {
+	.notifier_call = 	usbfs_notify,
+};
+
 /* --------------------------------------------------------------------- */
 
 static struct proc_dir_entry *usbdir = NULL;
@@ -732,6 +747,8 @@
 	if (retval)
 		return retval;
 
+	usb_register_notify(&usbfs_nb);
+
 	/* create mount point for usbfs */
 	usbdir = proc_mkdir("usb", proc_bus);
 
@@ -740,6 +757,7 @@
 
 void usbfs_cleanup(void)
 {
+	usb_unregister_notify(&usbfs_nb);
 	unregister_filesystem(&usb_fs_type);
 	if (usbdir)
 		remove_proc_entry("usb", proc_bus);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f1fb67f..644a3d4 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -187,21 +187,37 @@
  *      If a thread in your driver uses this call, make sure your disconnect()
  *      method can wait for it to complete.  Since you don't have a handle on
  *      the URB used, you can't cancel the request.
+ *
+ *	Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
+ *	ioctl, users are forced to abuse this routine by using it to submit
+ *	URBs for interrupt endpoints.  We will take the liberty of creating
+ *	an interrupt URB (with the default interval) if the target is an
+ *	interrupt endpoint.
  */
 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
 			void *data, int len, int *actual_length, int timeout)
 {
 	struct urb *urb;
+	struct usb_host_endpoint *ep;
 
-	if (len < 0)
+	ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
+			[usb_pipeendpoint(pipe)];
+	if (!ep || len < 0)
 		return -EINVAL;
 
-	urb=usb_alloc_urb(0, GFP_KERNEL);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb)
 		return -ENOMEM;
 
-	usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
-			  usb_api_blocking_completion, NULL);
+	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+			USB_ENDPOINT_XFER_INT) {
+		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+				usb_api_blocking_completion, NULL,
+				ep->desc.bInterval);
+	} else
+		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+				usb_api_blocking_completion, NULL);
 
 	return usb_start_wait_urb(urb, timeout, actual_length);
 }
@@ -321,7 +337,7 @@
 	struct scatterlist	*sg,
 	int			nents,
 	size_t			length,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 )
 {
 	int			i;
@@ -771,6 +787,31 @@
 	return err;
 }
 
+/**
+ * usb_cache_string - read a string descriptor and cache it for later use
+ * @udev: the device whose string descriptor is being read
+ * @index: the descriptor index
+ *
+ * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
+ * or NULL if the index is 0 or the string could not be read.
+ */
+char *usb_cache_string(struct usb_device *udev, int index)
+{
+	char *buf;
+	char *smallbuf = NULL;
+	int len;
+
+	if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
+		if ((len = usb_string(udev, index, buf, 256)) > 0) {
+			if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+				return buf;
+			memcpy(smallbuf, buf, len);
+		}
+		kfree(buf);
+	}
+	return smallbuf;
+}
+
 /*
  * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
  * @dev: the device whose device descriptor is being updated
@@ -992,8 +1033,6 @@
 			dev_dbg (&dev->dev, "unregistering interface %s\n",
 				interface->dev.bus_id);
 			usb_remove_sysfs_intf_files(interface);
-			kfree(interface->cur_altsetting->string);
-			interface->cur_altsetting->string = NULL;
 			device_del (&interface->dev);
 		}
 
@@ -1133,6 +1172,8 @@
 	 */
 
 	/* prevent submissions using previous endpoint settings */
+	if (device_is_registered(&iface->dev))
+		usb_remove_sysfs_intf_files(iface);
 	usb_disable_interface(dev, iface);
 
 	iface->cur_altsetting = alt;
@@ -1168,6 +1209,8 @@
 	 * (Likewise, EP0 never "halts" on well designed devices.)
 	 */
 	usb_enable_interface(dev, iface);
+	if (device_is_registered(&iface->dev))
+		usb_create_sysfs_intf_files(iface);
 
 	return 0;
 }
@@ -1217,10 +1260,8 @@
 			USB_REQ_SET_CONFIGURATION, 0,
 			config->desc.bConfigurationValue, 0,
 			NULL, 0, USB_CTRL_SET_TIMEOUT);
-	if (retval < 0) {
-		usb_set_device_state(dev, USB_STATE_ADDRESS);
+	if (retval < 0)
 		return retval;
-	}
 
 	dev->toggle[0] = dev->toggle[1] = 0;
 
@@ -1229,6 +1270,8 @@
 		struct usb_interface *intf = config->interface[i];
 		struct usb_host_interface *alt;
 
+		if (device_is_registered(&intf->dev))
+			usb_remove_sysfs_intf_files(intf);
 		alt = usb_altnum_to_altsetting(intf, 0);
 
 		/* No altsetting 0?  We'll assume the first altsetting.
@@ -1241,6 +1284,8 @@
 
 		intf->cur_altsetting = alt;
 		usb_enable_interface(dev, intf);
+		if (device_is_registered(&intf->dev))
+			usb_create_sysfs_intf_files(intf);
 	}
 	return 0;
 }
@@ -1328,7 +1373,7 @@
 		}
 
 		for (; n < nintf; ++n) {
-			new_interfaces[n] = kmalloc(
+			new_interfaces[n] = kzalloc(
 					sizeof(struct usb_interface),
 					GFP_KERNEL);
 			if (!new_interfaces[n]) {
@@ -1369,7 +1414,6 @@
 			struct usb_host_interface *alt;
 
 			cp->interface[i] = intf = new_interfaces[i];
-			memset(intf, 0, sizeof(*intf));
 			intfc = cp->intf_cache[i];
 			intf->altsetting = intfc->altsetting;
 			intf->num_altsetting = intfc->num_altsetting;
@@ -1393,6 +1437,7 @@
 			intf->dev.dma_mask = dev->dev.dma_mask;
 			intf->dev.release = release_interface;
 			device_initialize (&intf->dev);
+			mark_quiesced(intf);
 			sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
 				 dev->bus->busnum, dev->devpath,
 				 configuration,
@@ -1400,12 +1445,9 @@
 		}
 		kfree(new_interfaces);
 
-		if ((cp->desc.iConfiguration) &&
-		    (cp->string == NULL)) {
-			cp->string = kmalloc(256, GFP_KERNEL);
-			if (cp->string)
-				usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
-		}
+		if (cp->string == NULL)
+			cp->string = usb_cache_string(dev,
+					cp->desc.iConfiguration);
 
 		/* Now that all the interfaces are set up, register them
 		 * to trigger binding of drivers to interfaces.  probe()
@@ -1415,13 +1457,12 @@
 		 */
 		for (i = 0; i < nintf; ++i) {
 			struct usb_interface *intf = cp->interface[i];
-			struct usb_interface_descriptor *desc;
+			struct usb_host_interface *alt = intf->cur_altsetting;
 
-			desc = &intf->altsetting [0].desc;
 			dev_dbg (&dev->dev,
 				"adding %s (config #%d, interface %d)\n",
 				intf->dev.bus_id, configuration,
-				desc->bInterfaceNumber);
+				alt->desc.bInterfaceNumber);
 			ret = device_add (&intf->dev);
 			if (ret != 0) {
 				dev_err(&dev->dev,
@@ -1430,13 +1471,6 @@
 					ret);
 				continue;
 			}
-			if ((intf->cur_altsetting->desc.iInterface) &&
-			    (intf->cur_altsetting->string == NULL)) {
-				intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
-				if (intf->cur_altsetting->string)
-					usb_string(dev, intf->cur_altsetting->desc.iInterface,
-						   intf->cur_altsetting->string, 256);
-			}
 			usb_create_sysfs_intf_files (intf);
 		}
 	}
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
new file mode 100644
index 0000000..37da059
--- /dev/null
+++ b/drivers/usb/core/notify.c
@@ -0,0 +1,120 @@
+/*
+ * All the USB notify logic
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * notifier functions originally based on those in kernel/sys.c
+ * but fixed up to not be so broken.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb.h"
+
+
+static struct notifier_block *usb_notifier_list;
+static DECLARE_MUTEX(usb_notifier_lock);
+
+static void usb_notifier_chain_register(struct notifier_block **list,
+					struct notifier_block *n)
+{
+	down(&usb_notifier_lock);
+	while (*list) {
+		if (n->priority > (*list)->priority)
+			break;
+		list = &((*list)->next);
+	}
+	n->next = *list;
+	*list = n;
+	up(&usb_notifier_lock);
+}
+
+static void usb_notifier_chain_unregister(struct notifier_block **nl,
+				   struct notifier_block *n)
+{
+	down(&usb_notifier_lock);
+	while ((*nl)!=NULL) {
+		if ((*nl)==n) {
+			*nl = n->next;
+			goto exit;
+		}
+		nl=&((*nl)->next);
+	}
+exit:
+	up(&usb_notifier_lock);
+}
+
+static int usb_notifier_call_chain(struct notifier_block **n,
+				   unsigned long val, void *v)
+{
+	int ret=NOTIFY_DONE;
+	struct notifier_block *nb = *n;
+
+	down(&usb_notifier_lock);
+	while (nb) {
+		ret = nb->notifier_call(nb,val,v);
+		if (ret&NOTIFY_STOP_MASK) {
+			goto exit;
+		}
+		nb = nb->next;
+	}
+exit:
+	up(&usb_notifier_lock);
+	return ret;
+}
+
+/**
+ * usb_register_notify - register a notifier callback whenever a usb change happens
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * These changes are either USB devices or busses being added or removed.
+ */
+void usb_register_notify(struct notifier_block *nb)
+{
+	usb_notifier_chain_register(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_register_notify);
+
+/**
+ * usb_unregister_notify - unregister a notifier callback
+ * @nb: pointer to the notifier block for the callback events.
+ *
+ * usb_register_notifier() must have been previously called for this function
+ * to work properly.
+ */
+void usb_unregister_notify(struct notifier_block *nb)
+{
+	usb_notifier_chain_unregister(&usb_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(usb_unregister_notify);
+
+
+void usb_notify_add_device(struct usb_device *udev)
+{
+	usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+}
+
+void usb_notify_remove_device(struct usb_device *udev)
+{
+	usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
+}
+
+void usb_notify_add_bus(struct usb_bus *ubus)
+{
+	usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+}
+
+void usb_notify_remove_bus(struct usb_bus *ubus)
+{
+	usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 00297f1..edd83e0 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -22,9 +22,207 @@
 
 #include "usb.h"
 
+/* endpoint stuff */
+struct ep_object {
+	struct usb_endpoint_descriptor *desc;
+	struct usb_device *udev;
+	struct kobject kobj;
+};
+#define to_ep_object(_kobj) \
+	container_of(_kobj, struct ep_object, kobj)
+
+struct ep_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct usb_device *,
+			struct usb_endpoint_descriptor *, char *);
+};
+#define to_ep_attribute(_attr) \
+	container_of(_attr, struct ep_attribute, attr)
+
+#define EP_ATTR(_name)						\
+struct ep_attribute ep_##_name = {				\
+	.attr = {.name = #_name, .owner = THIS_MODULE,		\
+			.mode = S_IRUGO},			\
+	.show = show_ep_##_name}
+
+#define usb_ep_attr(field, format_string)			\
+static ssize_t show_ep_##field(struct usb_device *udev,		\
+		struct usb_endpoint_descriptor *desc, 		\
+		char *buf)					\
+{								\
+	return sprintf(buf, format_string, desc->field);	\
+}								\
+static EP_ATTR(field);
+
+usb_ep_attr(bLength, "%02x\n")
+usb_ep_attr(bEndpointAddress, "%02x\n")
+usb_ep_attr(bmAttributes, "%02x\n")
+usb_ep_attr(bInterval, "%02x\n")
+
+static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
+		struct usb_endpoint_descriptor *desc, char *buf)
+{
+	return sprintf(buf, "%04x\n",
+			le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
+}
+static EP_ATTR(wMaxPacketSize);
+
+static ssize_t show_ep_type(struct usb_device *udev,
+		struct usb_endpoint_descriptor *desc, char *buf)
+{
+	char *type = "unknown";
+
+	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		type = "Control";
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		type = "Isoc";
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		type = "Bulk";
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		type = "Interrupt";
+		break;
+	}
+	return sprintf(buf, "%s\n", type);
+}
+static EP_ATTR(type);
+
+static ssize_t show_ep_interval(struct usb_device *udev,
+		struct usb_endpoint_descriptor *desc, char *buf)
+{
+	char unit;
+	unsigned interval = 0;
+	unsigned in;
+
+	in = (desc->bEndpointAddress & USB_DIR_IN);
+
+	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		if (udev->speed == USB_SPEED_HIGH) 	/* uframes per NAK */
+			interval = desc->bInterval;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		interval = 1 << (desc->bInterval - 1);
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+			interval = desc->bInterval;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		if (udev->speed == USB_SPEED_HIGH)
+			interval = 1 << (desc->bInterval - 1);
+		else
+			interval = desc->bInterval;
+		break;
+	}
+	interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
+	if (interval % 1000)
+		unit = 'u';
+	else {
+		unit = 'm';
+		interval /= 1000;
+	}
+
+	return sprintf(buf, "%d%cs\n", interval, unit);
+}
+static EP_ATTR(interval);
+
+static ssize_t show_ep_direction(struct usb_device *udev,
+		struct usb_endpoint_descriptor *desc, char *buf)
+{
+	char *direction;
+
+	if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+			USB_ENDPOINT_XFER_CONTROL)
+		direction = "both";
+	else if (desc->bEndpointAddress & USB_DIR_IN)
+		direction = "in";
+	else
+		direction = "out";
+	return sprintf(buf, "%s\n", direction);
+}
+static EP_ATTR(direction);
+
+static struct attribute *ep_attrs[] = {
+	&ep_bLength.attr,
+	&ep_bEndpointAddress.attr,
+	&ep_bmAttributes.attr,
+	&ep_bInterval.attr,
+	&ep_wMaxPacketSize.attr,
+	&ep_type.attr,
+	&ep_interval.attr,
+	&ep_direction.attr,
+	NULL,
+};
+
+static void ep_object_release(struct kobject *kobj)
+{
+	kfree(to_ep_object(kobj));
+}
+
+static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
+		char *buf)
+{
+	struct ep_object *ep_obj = to_ep_object(kobj);
+	struct ep_attribute *ep_attr = to_ep_attribute(attr);
+
+	return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
+}
+
+static struct sysfs_ops ep_object_sysfs_ops = {
+	.show =			ep_object_show,
+};
+
+static struct kobj_type ep_object_ktype = {
+	.release =		ep_object_release,
+	.sysfs_ops =		&ep_object_sysfs_ops,
+	.default_attrs =	ep_attrs,
+};
+
+static void usb_create_ep_files(struct kobject *parent,
+		struct usb_host_endpoint *endpoint,
+		struct usb_device *udev)
+{
+	struct ep_object *ep_obj;
+	struct kobject *kobj;
+
+	ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
+	if (!ep_obj)
+		return;
+
+	ep_obj->desc = &endpoint->desc;
+	ep_obj->udev = udev;
+
+	kobj = &ep_obj->kobj;
+	kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
+	kobj->parent = parent;
+	kobj->ktype = &ep_object_ktype;
+
+	/* Don't use kobject_register, because it generates a hotplug event */
+	kobject_init(kobj);
+	if (kobject_add(kobj) == 0)
+		endpoint->kobj = kobj;
+	else
+		kobject_put(kobj);
+}
+
+static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+{
+
+	if (endpoint->kobj) {
+		kobject_del(endpoint->kobj);
+		kobject_put(endpoint->kobj);
+		endpoint->kobj = NULL;
+	}
+}
+
 /* Active configuration fields */
 #define usb_actconfig_show(field, multiplier, format_string)		\
-static ssize_t  show_##field (struct device *dev, struct device_attribute *attr, char *buf)		\
+static ssize_t  show_##field (struct device *dev,			\
+		struct device_attribute *attr, char *buf)		\
 {									\
 	struct usb_device *udev;					\
 	struct usb_host_config *actconfig;				\
@@ -46,22 +244,17 @@
 usb_actconfig_attr (bmAttributes, 1, "%2x\n")
 usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
 
-static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_configuration_string(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
 	struct usb_host_config *actconfig;
-	int len;
 
 	udev = to_usb_device (dev);
 	actconfig = udev->actconfig;
 	if ((!actconfig) || (!actconfig->string))
 		return 0;
-	len = sprintf(buf, actconfig->string, PAGE_SIZE);
-	if (len < 0)
-		return 0;
-	buf[len] = '\n';
-	buf[len+1] = 0;
-	return len+1;
+	return sprintf(buf, "%s\n", actconfig->string);
 }
 static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
 
@@ -69,7 +262,8 @@
 usb_actconfig_show(bConfigurationValue, 1, "%u\n");
 
 static ssize_t
-set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	struct usb_device	*udev = udev = to_usb_device (dev);
 	int			config, value;
@@ -87,18 +281,13 @@
 
 /* String fields */
 #define usb_string_attr(name)						\
-static ssize_t  show_##name(struct device *dev, struct device_attribute *attr, char *buf)		\
+static ssize_t  show_##name(struct device *dev,				\
+		struct device_attribute *attr, char *buf)		\
 {									\
 	struct usb_device *udev;					\
-	int len;							\
 									\
 	udev = to_usb_device (dev);					\
-	len = snprintf(buf, 256, "%s", udev->name);			\
-	if (len < 0)							\
-		return 0;						\
-	buf[len] = '\n';						\
-	buf[len+1] = 0;							\
-	return len+1;							\
+	return sprintf(buf, "%s\n", udev->name);			\
 }									\
 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
@@ -167,7 +356,8 @@
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)			\
 static ssize_t								\
-show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
+show_##field (struct device *dev, struct device_attribute *attr,	\
+		char *buf)						\
 {									\
 	struct usb_device *udev;					\
 									\
@@ -183,7 +373,8 @@
 
 #define usb_descriptor_attr(field, format_string)			\
 static ssize_t								\
-show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
+show_##field (struct device *dev, struct device_attribute *attr,	\
+		char *buf)						\
 {									\
 	struct usb_device *udev;					\
 									\
@@ -236,19 +427,21 @@
 	if (udev->serial)
 		device_create_file (dev, &dev_attr_serial);
 	device_create_file (dev, &dev_attr_configuration);
+	usb_create_ep_files(&dev->kobj, &udev->ep0, udev);
 }
 
 void usb_remove_sysfs_dev_files (struct usb_device *udev)
 {
 	struct device *dev = &udev->dev;
 
+	usb_remove_ep_files(&udev->ep0);
 	sysfs_remove_group(&dev->kobj, &dev_attr_grp);
 
-	if (udev->descriptor.iManufacturer)
+	if (udev->manufacturer)
 		device_remove_file(dev, &dev_attr_manufacturer);
-	if (udev->descriptor.iProduct)
+	if (udev->product)
 		device_remove_file(dev, &dev_attr_product);
-	if (udev->descriptor.iSerialNumber)
+	if (udev->serial)
 		device_remove_file(dev, &dev_attr_serial);
 	device_remove_file (dev, &dev_attr_configuration);
 }
@@ -256,11 +449,13 @@
 /* Interface fields */
 #define usb_intf_attr(field, format_string)				\
 static ssize_t								\
-show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
+show_##field (struct device *dev, struct device_attribute *attr,	\
+		char *buf)						\
 {									\
 	struct usb_interface *intf = to_usb_interface (dev);		\
 									\
-	return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
+	return sprintf (buf, format_string,				\
+			intf->cur_altsetting->desc.field); 		\
 }									\
 static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
 
@@ -271,7 +466,8 @@
 usb_intf_attr (bInterfaceSubClass, "%02x\n")
 usb_intf_attr (bInterfaceProtocol, "%02x\n")
 
-static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_interface_string(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf;
 	struct usb_device *udev;
@@ -288,34 +484,28 @@
 }
 static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
 
-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_modalias(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf;
 	struct usb_device *udev;
-	int len;
+	struct usb_host_interface *alt;
 
 	intf = to_usb_interface(dev);
 	udev = interface_to_usbdev(intf);
+	alt = intf->cur_altsetting;
 
-	len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
-			       le16_to_cpu(udev->descriptor.idVendor),
-			       le16_to_cpu(udev->descriptor.idProduct),
-			       le16_to_cpu(udev->descriptor.bcdDevice),
-			       udev->descriptor.bDeviceClass,
-			       udev->descriptor.bDeviceSubClass,
-			       udev->descriptor.bDeviceProtocol);
-	buf += len;
-
-	if (udev->descriptor.bDeviceClass == 0) {
-		struct usb_host_interface *alt = intf->cur_altsetting;
-
-		return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
-			       alt->desc.bInterfaceClass,
-			       alt->desc.bInterfaceSubClass,
-			       alt->desc.bInterfaceProtocol);
- 	} else {
-		return len + sprintf(buf, "*isc*ip*\n");
-	}
+	return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
+			"ic%02Xisc%02Xip%02X\n",
+			le16_to_cpu(udev->descriptor.idVendor),
+			le16_to_cpu(udev->descriptor.idProduct),
+			le16_to_cpu(udev->descriptor.bcdDevice),
+			udev->descriptor.bDeviceClass,
+			udev->descriptor.bDeviceSubClass,
+			udev->descriptor.bDeviceProtocol,
+			alt->desc.bInterfaceClass,
+			alt->desc.bInterfaceSubClass,
+			alt->desc.bInterfaceProtocol);
 }
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 
@@ -333,20 +523,47 @@
 	.attrs = intf_attrs,
 };
 
+static inline void usb_create_intf_ep_files(struct usb_interface *intf,
+		struct usb_device *udev)
+{
+	struct usb_host_interface *iface_desc;
+	int i;
+
+	iface_desc = intf->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+		usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
+				udev);
+}
+
+static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
+{
+	struct usb_host_interface *iface_desc;
+	int i;
+
+	iface_desc = intf->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+		usb_remove_ep_files(&iface_desc->endpoint[i]);
+}
+
 void usb_create_sysfs_intf_files (struct usb_interface *intf)
 {
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usb_host_interface *alt = intf->cur_altsetting;
+
 	sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
 
-	if (intf->cur_altsetting->string)
+	if (alt->string == NULL)
+		alt->string = usb_cache_string(udev, alt->desc.iInterface);
+	if (alt->string)
 		device_create_file(&intf->dev, &dev_attr_interface);
-		
+	usb_create_intf_ep_files(intf, udev);
 }
 
 void usb_remove_sysfs_intf_files (struct usb_interface *intf)
 {
+	usb_remove_intf_ep_files(intf);
 	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
 
 	if (intf->cur_altsetting->string)
 		device_remove_file(&intf->dev, &dev_attr_interface);
-
 }
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c846fef..f2a1fed 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -60,7 +60,7 @@
  *
  * The driver must call usb_free_urb() when it is finished with the urb.
  */
-struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags)
+struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
 {
 	struct urb *urb;
 
@@ -224,7 +224,7 @@
  *      GFP_NOIO, unless b) or c) apply
  *
  */
-int usb_submit_urb(struct urb *urb, unsigned mem_flags)
+int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
 	int			pipe, temp, max;
 	struct usb_device	*dev;
@@ -237,7 +237,8 @@
 	    (dev->state < USB_STATE_DEFAULT) ||
 	    (!dev->bus) || (dev->devnum <= 0))
 		return -ENODEV;
-	if (dev->state == USB_STATE_SUSPENDED)
+	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
+			|| dev->state == USB_STATE_SUSPENDED)
 		return -EHOSTUNREACH;
 	if (!(op = dev->bus->op) || !op->submit_urb)
 		return -ENODEV;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 7d13150..0eefff7 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -107,10 +107,19 @@
 	id = usb_match_id (intf, driver->id_table);
 	if (id) {
 		dev_dbg (dev, "%s - got id\n", __FUNCTION__);
+
+		/* Interface "power state" doesn't correspond to any hardware
+		 * state whatsoever.  We use it to record when it's bound to
+		 * a driver that may start I/0:  it's not frozen/quiesced.
+		 */
+		mark_active(intf);
 		intf->condition = USB_INTERFACE_BINDING;
 		error = driver->probe (intf, id);
-		intf->condition = error ? USB_INTERFACE_UNBOUND :
-				USB_INTERFACE_BOUND;
+		if (error) {
+			mark_quiesced(intf);
+			intf->condition = USB_INTERFACE_UNBOUND;
+		} else
+			intf->condition = USB_INTERFACE_BOUND;
 	}
 
 	return error;
@@ -136,6 +145,7 @@
 			0);
 	usb_set_intfdata(intf, NULL);
 	intf->condition = USB_INTERFACE_UNBOUND;
+	mark_quiesced(intf);
 
 	return 0;
 }
@@ -299,6 +309,7 @@
 	dev->driver = &driver->driver;
 	usb_set_intfdata(iface, priv);
 	iface->condition = USB_INTERFACE_BOUND;
+	mark_active(iface);
 
 	/* if interface was already added, bind now; else let
 	 * the future device_add() bind it, bypassing probe()
@@ -345,6 +356,7 @@
 	dev->driver = NULL;
 	usb_set_intfdata(iface, NULL);
 	iface->condition = USB_INTERFACE_UNBOUND;
+	mark_quiesced(iface);
 }
 
 /**
@@ -557,6 +569,7 @@
 {
 	struct usb_interface *intf;
 	struct usb_device *usb_dev;
+	struct usb_host_interface *alt;
 	int i = 0;
 	int length = 0;
 
@@ -573,7 +586,8 @@
 
 	intf = to_usb_interface(dev);
 	usb_dev = interface_to_usbdev (intf);
-	
+	alt = intf->cur_altsetting;
+
 	if (usb_dev->devnum < 0) {
 		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
 		return -ENODEV;
@@ -615,46 +629,27 @@
 				usb_dev->descriptor.bDeviceProtocol))
 		return -ENOMEM;
 
-	if (usb_dev->descriptor.bDeviceClass == 0) {
-		struct usb_host_interface *alt = intf->cur_altsetting;
+	if (add_hotplug_env_var(envp, num_envp, &i,
+				buffer, buffer_size, &length,
+				"INTERFACE=%d/%d/%d",
+				alt->desc.bInterfaceClass,
+				alt->desc.bInterfaceSubClass,
+				alt->desc.bInterfaceProtocol))
+		return -ENOMEM;
 
-		/* 2.4 only exposed interface zero.  in 2.5, hotplug
-		 * agents are called for all interfaces, and can use
-		 * $DEVPATH/bInterfaceNumber if necessary.
-		 */
-		if (add_hotplug_env_var(envp, num_envp, &i,
-					buffer, buffer_size, &length,
-					"INTERFACE=%d/%d/%d",
-					alt->desc.bInterfaceClass,
-					alt->desc.bInterfaceSubClass,
-					alt->desc.bInterfaceProtocol))
-			return -ENOMEM;
-
-		if (add_hotplug_env_var(envp, num_envp, &i,
-					buffer, buffer_size, &length,
-					"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-					le16_to_cpu(usb_dev->descriptor.idVendor),
-					le16_to_cpu(usb_dev->descriptor.idProduct),
-					le16_to_cpu(usb_dev->descriptor.bcdDevice),
-					usb_dev->descriptor.bDeviceClass,
-					usb_dev->descriptor.bDeviceSubClass,
-					usb_dev->descriptor.bDeviceProtocol,
-					alt->desc.bInterfaceClass,
-					alt->desc.bInterfaceSubClass,
-					alt->desc.bInterfaceProtocol))
-			return -ENOMEM;
- 	} else {
-		if (add_hotplug_env_var(envp, num_envp, &i,
-					buffer, buffer_size, &length,
-					"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
-					le16_to_cpu(usb_dev->descriptor.idVendor),
-					le16_to_cpu(usb_dev->descriptor.idProduct),
-					le16_to_cpu(usb_dev->descriptor.bcdDevice),
-					usb_dev->descriptor.bDeviceClass,
-					usb_dev->descriptor.bDeviceSubClass,
-					usb_dev->descriptor.bDeviceProtocol))
-			return -ENOMEM;
-	}
+	if (add_hotplug_env_var(envp, num_envp, &i,
+				buffer, buffer_size, &length,
+				"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+				le16_to_cpu(usb_dev->descriptor.idVendor),
+				le16_to_cpu(usb_dev->descriptor.idProduct),
+				le16_to_cpu(usb_dev->descriptor.bcdDevice),
+				usb_dev->descriptor.bDeviceClass,
+				usb_dev->descriptor.bDeviceSubClass,
+				usb_dev->descriptor.bDeviceProtocol,
+				alt->desc.bInterfaceClass,
+				alt->desc.bInterfaceSubClass,
+				alt->desc.bInterfaceProtocol))
+		return -ENOMEM;
 
 	envp[i] = NULL;
 
@@ -709,12 +704,10 @@
 {
 	struct usb_device *dev;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
-	memset(dev, 0, sizeof(*dev));
-
 	bus = usb_bus_get(bus);
 	if (!bus) {
 		kfree(dev);
@@ -1147,7 +1140,7 @@
 void *usb_buffer_alloc (
 	struct usb_device *dev,
 	size_t size,
-	unsigned mem_flags,
+	gfp_t mem_flags,
 	dma_addr_t *dma
 )
 {
@@ -1402,13 +1395,30 @@
 			usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 
+static int verify_suspended(struct device *dev, void *unused)
+{
+	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+}
+
 static int usb_generic_suspend(struct device *dev, pm_message_t message)
 {
-	struct usb_interface *intf;
-	struct usb_driver *driver;
+	struct usb_interface	*intf;
+	struct usb_driver	*driver;
+	int			status;
 
-	if (dev->driver == &usb_generic_driver)
-		return usb_suspend_device (to_usb_device(dev), message);
+	/* USB devices enter SUSPEND state through their hubs, but can be
+	 * marked for FREEZE as soon as their children are already idled.
+	 * But those semantics are useless, so we equate the two (sigh).
+	 */
+	if (dev->driver == &usb_generic_driver) {
+		if (dev->power.power_state.event == message.event)
+			return 0;
+		/* we need to rule out bogus requests through sysfs */
+		status = device_for_each_child(dev, NULL, verify_suspended);
+		if (status)
+			return status;
+ 		return usb_suspend_device (to_usb_device(dev));
+	}
 
 	if ((dev->driver == NULL) ||
 	    (dev->driver_data == &usb_generic_driver_data))
@@ -1417,23 +1427,44 @@
 	intf = to_usb_interface(dev);
 	driver = to_usb_driver(dev->driver);
 
-	/* there's only one USB suspend state */
-	if (intf->dev.power.power_state.event)
+	/* with no hardware, USB interfaces only use FREEZE and ON states */
+	if (!is_active(intf))
 		return 0;
 
-	if (driver->suspend)
-		return driver->suspend(intf, message);
-	return 0;
+	if (driver->suspend && driver->resume) {
+		status = driver->suspend(intf, message);
+		if (status)
+			dev_err(dev, "%s error %d\n", "suspend", status);
+		else
+			mark_quiesced(intf);
+	} else {
+		// FIXME else if there's no suspend method, disconnect...
+		dev_warn(dev, "no %s?\n", "suspend");
+		status = 0;
+	}
+	return status;
 }
 
 static int usb_generic_resume(struct device *dev)
 {
-	struct usb_interface *intf;
-	struct usb_driver *driver;
+	struct usb_interface	*intf;
+	struct usb_driver	*driver;
+	struct usb_device	*udev;
+	int			status;
 
-	/* devices resume through their hub */
-	if (dev->driver == &usb_generic_driver)
+	if (dev->power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	/* mark things as "on" immediately, no matter what errors crop up */
+	dev->power.power_state.event = PM_EVENT_ON;
+
+	/* devices resume through their hubs */
+	if (dev->driver == &usb_generic_driver) {
+		udev = to_usb_device(dev);
+		if (udev->state == USB_STATE_NOTATTACHED)
+			return 0;
 		return usb_resume_device (to_usb_device(dev));
+	}
 
 	if ((dev->driver == NULL) ||
 	    (dev->driver_data == &usb_generic_driver_data))
@@ -1442,8 +1473,22 @@
 	intf = to_usb_interface(dev);
 	driver = to_usb_driver(dev->driver);
 
-	if (driver->resume)
-		return driver->resume(intf);
+	udev = interface_to_usbdev(intf);
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return 0;
+
+	/* if driver was suspended, it has a resume method;
+	 * however, sysfs can wrongly mark things as suspended
+	 * (on the "no suspend method" FIXME path above)
+	 */
+	if (driver->resume) {
+		status = driver->resume(intf);
+		if (status) {
+			dev_err(dev, "%s error %d\n", "resume", status);
+			mark_quiesced(intf);
+		}
+	} else
+		dev_warn(dev, "no %s?\n", "resume");
 	return 0;
 }
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index e6504f3..1c4a684 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -13,12 +13,14 @@
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
 		unsigned int size);
+extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_lock_all_devices(void);
 extern void usb_unlock_all_devices(void);
 
 extern void usb_kick_khubd(struct usb_device *dev);
+extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
 
 extern int  usb_hub_init(void);
@@ -28,6 +30,28 @@
 extern int usb_host_init(void);
 extern void usb_host_cleanup(void);
 
+extern int usb_suspend_device(struct usb_device *dev);
+extern int usb_resume_device(struct usb_device *dev);
+
+
+/* Interfaces and their "power state" are owned by usbcore */
+
+static inline void mark_active(struct usb_interface *f)
+{
+	f->dev.power.power_state.event = PM_EVENT_ON;
+}
+
+static inline void mark_quiesced(struct usb_interface *f)
+{
+	f->dev.power.power_state.event = PM_EVENT_FREEZE;
+}
+
+static inline int is_active(struct usb_interface *f)
+{
+	return f->dev.power.power_state.event == PM_EVENT_ON;
+}
+
+
 /* for labeling diagnostics */
 extern const char *usbcore_name;
 
@@ -39,9 +63,6 @@
 
 extern int usbdev_init(void);
 extern void usbdev_cleanup(void);
-extern void usbdev_add(struct usb_device *dev);
-extern void usbdev_remove(struct usb_device *dev);
-extern struct usb_device *usbdev_lookup_minor(int minor);
 
 struct dev_state {
 	struct list_head list;      /* state list */
@@ -58,3 +79,9 @@
 	unsigned long ifclaimed;
 };
 
+/* internal notify stuff */
+extern void usb_notify_add_device(struct usb_device *udev);
+extern void usb_notify_remove_device(struct usb_device *udev);
+extern void usb_notify_add_bus(struct usb_bus *ubus);
+extern void usb_notify_remove_bus(struct usb_bus *ubus);
+
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 583db7c..02106be 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -470,7 +470,7 @@
 }
 
 static struct usb_request *
-dummy_alloc_request (struct usb_ep *_ep, unsigned mem_flags)
+dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
@@ -507,7 +507,7 @@
 	struct usb_ep *_ep,
 	unsigned bytes,
 	dma_addr_t *dma,
-	unsigned mem_flags
+	gfp_t mem_flags
 ) {
 	char			*retval;
 	struct dummy_ep		*ep;
@@ -541,7 +541,7 @@
 
 static int
 dummy_queue (struct usb_ep *_ep, struct usb_request *_req,
-		unsigned mem_flags)
+		gfp_t mem_flags)
 {
 	struct dummy_ep		*ep;
 	struct dummy_request	*req;
@@ -935,14 +935,10 @@
 	return 0;
 }
 
-static int dummy_udc_suspend (struct device *dev, pm_message_t state,
-		u32 level)
+static int dummy_udc_suspend (struct device *dev, pm_message_t state)
 {
 	struct dummy	*dum = dev_get_drvdata(dev);
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	dev_dbg (dev, "%s\n", __FUNCTION__);
 	spin_lock_irq (&dum->lock);
 	dum->udc_suspended = 1;
@@ -954,13 +950,10 @@
 	return 0;
 }
 
-static int dummy_udc_resume (struct device *dev, u32 level)
+static int dummy_udc_resume (struct device *dev)
 {
 	struct dummy	*dum = dev_get_drvdata(dev);
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	dev_dbg (dev, "%s\n", __FUNCTION__);
 	spin_lock_irq (&dum->lock);
 	dum->udc_suspended = 0;
@@ -974,6 +967,7 @@
 
 static struct device_driver dummy_udc_driver = {
 	.name		= (char *) gadget_name,
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= dummy_udc_probe,
 	.remove		= dummy_udc_remove,
@@ -999,7 +993,7 @@
 	struct usb_hcd			*hcd,
 	struct usb_host_endpoint	*ep,
 	struct urb			*urb,
-	unsigned			mem_flags
+	gfp_t				mem_flags
 ) {
 	struct dummy	*dum;
 	struct urbp	*urbp;
@@ -1758,7 +1752,7 @@
 	return retval;
 }
 
-static int dummy_hub_suspend (struct usb_hcd *hcd)
+static int dummy_bus_suspend (struct usb_hcd *hcd)
 {
 	struct dummy *dum = hcd_to_dummy (hcd);
 
@@ -1769,7 +1763,7 @@
 	return 0;
 }
 
-static int dummy_hub_resume (struct usb_hcd *hcd)
+static int dummy_bus_resume (struct usb_hcd *hcd)
 {
 	struct dummy *dum = hcd_to_dummy (hcd);
 
@@ -1901,8 +1895,8 @@
 
 	.hub_status_data = 	dummy_hub_status,
 	.hub_control = 		dummy_hub_control,
-	.hub_suspend =		dummy_hub_suspend,
-	.hub_resume =		dummy_hub_resume,
+	.bus_suspend =		dummy_bus_suspend,
+	.bus_resume =		dummy_bus_resume,
 };
 
 static int dummy_hcd_probe (struct device *dev)
@@ -1936,52 +1930,32 @@
 	return 0;
 }
 
-static int dummy_hcd_suspend (struct device *dev, pm_message_t state,
-		u32 level)
+static int dummy_hcd_suspend (struct device *dev, pm_message_t state)
 {
 	struct usb_hcd		*hcd;
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	dev_dbg (dev, "%s\n", __FUNCTION__);
 	hcd = dev_get_drvdata (dev);
 
-#ifndef CONFIG_USB_SUSPEND
-	/* Otherwise this would never happen */
-	usb_lock_device (hcd->self.root_hub);
-	dummy_hub_suspend (hcd);
-	usb_unlock_device (hcd->self.root_hub);
-#endif
-
 	hcd->state = HC_STATE_SUSPENDED;
 	return 0;
 }
 
-static int dummy_hcd_resume (struct device *dev, u32 level)
+static int dummy_hcd_resume (struct device *dev)
 {
 	struct usb_hcd		*hcd;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	dev_dbg (dev, "%s\n", __FUNCTION__);
 	hcd = dev_get_drvdata (dev);
 	hcd->state = HC_STATE_RUNNING;
 
-#ifndef CONFIG_USB_SUSPEND
-	/* Otherwise this would never happen */
-	usb_lock_device (hcd->self.root_hub);
-	dummy_hub_resume (hcd);
-	usb_unlock_device (hcd->self.root_hub);
-#endif
-
 	usb_hcd_poll_rh_status (hcd);
 	return 0;
 }
 
 static struct device_driver dummy_hcd_driver = {
 	.name		= (char *) driver_name,
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= dummy_hcd_probe,
 	.remove		= dummy_hcd_remove,
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 49459e3..8f402f8 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -945,11 +945,11 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags);
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
 
 static int
-set_ether_config (struct eth_dev *dev, unsigned gfp_flags)
+set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
 {
 	int					result = 0;
 	struct usb_gadget			*gadget = dev->gadget;
@@ -1081,7 +1081,7 @@
  * that returns config descriptors, and altsetting code.
  */
 static int
-eth_set_config (struct eth_dev *dev, unsigned number, unsigned gfp_flags)
+eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_gadget	*gadget = dev->gadget;
@@ -1598,7 +1598,7 @@
 static void rx_complete (struct usb_ep *ep, struct usb_request *req);
 
 static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, unsigned gfp_flags)
+rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
 {
 	struct sk_buff		*skb;
 	int			retval = -ENOMEM;
@@ -1724,7 +1724,7 @@
 }
 
 static int prealloc (struct list_head *list, struct usb_ep *ep,
-			unsigned n, unsigned gfp_flags)
+			unsigned n, gfp_t gfp_flags)
 {
 	unsigned		i;
 	struct usb_request	*req;
@@ -1763,7 +1763,7 @@
 	return 0;
 }
 
-static int alloc_requests (struct eth_dev *dev, unsigned n, unsigned gfp_flags)
+static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
 {
 	int status;
 
@@ -1779,7 +1779,7 @@
 	return status;
 }
 
-static void rx_fill (struct eth_dev *dev, unsigned gfp_flags)
+static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
 {
 	struct usb_request	*req;
 	unsigned long		flags;
@@ -1962,7 +1962,7 @@
  * normally just one notification will be queued.
  */
 
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned);
+static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
 static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
 
 static void
@@ -2024,7 +2024,7 @@
 
 #endif	/* RNDIS */
 
-static void eth_start (struct eth_dev *dev, unsigned gfp_flags)
+static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
 {
 	DEBUG (dev, "%s\n", __FUNCTION__);
 
@@ -2092,7 +2092,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags)
+eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
 {
 	struct usb_request	*req;
 
@@ -2533,6 +2533,7 @@
 
 	.driver 	= {
 		.name		= (char *) shortname,
+		.owner		= THIS_MODULE,
 		// .shutdown = ...
 		// .suspend = ...
 		// .resume = ...
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index a41d9d4..ea09aaa 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kthread.h>
 #include <linux/limits.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -669,7 +670,6 @@
 	wait_queue_head_t	thread_wqh;
 	int			thread_wakeup_needed;
 	struct completion	thread_notifier;
-	int			thread_pid;
 	struct task_struct	*thread_task;
 	sigset_t		thread_signal_mask;
 
@@ -1084,7 +1084,6 @@
 static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
 {
 	unsigned long		flags;
-	struct task_struct	*thread_task;
 
 	/* Do nothing if a higher-priority exception is already in progress.
 	 * If a lower-or-equal priority exception is in progress, preempt it
@@ -1093,9 +1092,9 @@
 	if (fsg->state <= new_state) {
 		fsg->exception_req_tag = fsg->ep0_req_tag;
 		fsg->state = new_state;
-		thread_task = fsg->thread_task;
-		if (thread_task)
-			send_sig_info(SIGUSR1, SEND_SIG_FORCED, thread_task);
+		if (fsg->thread_task)
+			send_sig_info(SIGUSR1, SEND_SIG_FORCED,
+					fsg->thread_task);
 	}
 	spin_unlock_irqrestore(&fsg->lock, flags);
 }
@@ -3383,11 +3382,6 @@
 {
 	struct fsg_dev		*fsg = (struct fsg_dev *) fsg_;
 
-	fsg->thread_task = current;
-
-	/* Release all our userspace resources */
-	daemonize("file-storage-gadget");
-
 	/* Allow the thread to be killed by a signal, but set the signal mask
 	 * to block everything but INT, TERM, KILL, and USR1. */
 	siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
@@ -3400,9 +3394,6 @@
 	 * that expects a __user pointer and it will work okay. */
 	set_fs(get_ds());
 
-	/* Wait for the gadget registration to finish up */
-	wait_for_completion(&fsg->thread_notifier);
-
 	/* The main loop */
 	while (fsg->state != FSG_STATE_TERMINATED) {
 		if (exception_in_progress(fsg) || signal_pending(current)) {
@@ -3440,8 +3431,9 @@
 		spin_unlock_irq(&fsg->lock);
 		}
 
+	spin_lock_irq(&fsg->lock);
 	fsg->thread_task = NULL;
-	flush_signals(current);
+	spin_unlock_irq(&fsg->lock);
 
 	/* In case we are exiting because of a signal, unregister the
 	 * gadget driver and close the backing file. */
@@ -3831,12 +3823,11 @@
 
 	/* Create the LUNs, open their backing files, and register the
 	 * LUN devices in sysfs. */
-	fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
+	fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL);
 	if (!fsg->luns) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(fsg->luns, 0, i * sizeof(struct lun));
 	fsg->nluns = i;
 
 	for (i = 0; i < fsg->nluns; ++i) {
@@ -3959,10 +3950,12 @@
 		sprintf(&serial[i], "%02X", c);
 	}
 
-	if ((rc = kernel_thread(fsg_main_thread, fsg, (CLONE_VM | CLONE_FS |
-			CLONE_FILES))) < 0)
+	fsg->thread_task = kthread_create(fsg_main_thread, fsg,
+			"file-storage-gadget");
+	if (IS_ERR(fsg->thread_task)) {
+		rc = PTR_ERR(fsg->thread_task);
 		goto out;
-	fsg->thread_pid = rc;
+	}
 
 	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
@@ -3994,7 +3987,12 @@
 	DBG(fsg, "removable=%d, stall=%d, buflen=%u\n",
 			mod_data.removable, mod_data.can_stall,
 			mod_data.buflen);
-	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid);
+	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_task->pid);
+
+	set_bit(REGISTERED, &fsg->atomic_bitflags);
+
+	/* Tell the thread to start working */
+	wake_up_process(fsg->thread_task);
 	return 0;
 
 autoconf_fail:
@@ -4046,6 +4044,7 @@
 
 	.driver		= {
 		.name		= (char *) shortname,
+		.owner		= THIS_MODULE,
 		// .release = ...
 		// .suspend = ...
 		// .resume = ...
@@ -4057,10 +4056,9 @@
 {
 	struct fsg_dev		*fsg;
 
-	fsg = kmalloc(sizeof *fsg, GFP_KERNEL);
+	fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
 	if (!fsg)
 		return -ENOMEM;
-	memset(fsg, 0, sizeof *fsg);
 	spin_lock_init(&fsg->lock);
 	init_rwsem(&fsg->filesem);
 	init_waitqueue_head(&fsg->thread_wqh);
@@ -4086,15 +4084,9 @@
 	if ((rc = fsg_alloc()) != 0)
 		return rc;
 	fsg = the_fsg;
-	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) {
+	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
 		fsg_free(fsg);
-		return rc;
-	}
-	set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* Tell the thread to start working */
-	complete(&fsg->thread_notifier);
-	return 0;
+	return rc;
 }
 module_init(fsg_init);
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index eaab26f..6544697 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -269,7 +269,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-goku_alloc_request(struct usb_ep *_ep, unsigned gfp_flags)
+goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 {
 	struct goku_request	*req;
 
@@ -327,7 +327,7 @@
  */
 static void *
 goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-			dma_addr_t *dma, unsigned gfp_flags)
+			dma_addr_t *dma, gfp_t gfp_flags)
 {
 	void		*retval;
 	struct goku_ep	*ep;
@@ -789,7 +789,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-goku_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
 	struct goku_request	*req;
 	struct goku_ep		*ep;
@@ -1970,6 +1970,7 @@
 static struct pci_driver goku_pci_driver = {
 	.name =		(char *) driver_name,
 	.id_table =	pci_ids,
+	.owner =	THIS_MODULE,
 
 	.probe =	goku_probe,
 	.remove =	goku_remove,
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 4842577..9b36739 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -71,13 +71,13 @@
 static int lh7a40x_ep_enable(struct usb_ep *ep,
 			     const struct usb_endpoint_descriptor *);
 static int lh7a40x_ep_disable(struct usb_ep *ep);
-static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int);
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
 static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
 static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
-				  int);
+				  gfp_t);
 static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
 				unsigned);
-static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int);
+static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
 static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
 static int lh7a40x_set_halt(struct usb_ep *ep, int);
 static int lh7a40x_fifo_status(struct usb_ep *ep);
@@ -1106,7 +1106,7 @@
 }
 
 static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
-						 unsigned gfp_flags)
+						 gfp_t gfp_flags)
 {
 	struct lh7a40x_request *req;
 
@@ -1134,7 +1134,7 @@
 }
 
 static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
-				  dma_addr_t * dma, unsigned gfp_flags)
+				  dma_addr_t * dma, gfp_t gfp_flags)
 {
 	char *retval;
 
@@ -1158,7 +1158,7 @@
  *  NOTE: Sets INDEX register
  */
 static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
-			 unsigned gfp_flags)
+			 gfp_t gfp_flags)
 {
 	struct lh7a40x_request *req;
 	struct lh7a40x_ep *ep;
@@ -2140,6 +2140,7 @@
 
 static struct device_driver udc_driver = {
 	.name = (char *)driver_name,
+	.owner = THIS_MODULE,
 	.bus = &platform_bus_type,
 	.probe = lh7a40x_udc_probe,
 	.remove = lh7a40x_udc_remove
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 477fab2..0dc6bb0 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -376,7 +376,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 {
 	struct net2280_ep	*ep;
 	struct net2280_request	*req;
@@ -463,7 +463,7 @@
 	struct usb_ep		*_ep,
 	unsigned		bytes,
 	dma_addr_t		*dma,
-	unsigned		gfp_flags
+	gfp_t			gfp_flags
 )
 {
 	void			*retval;
@@ -897,7 +897,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
 	struct net2280_request	*req;
 	struct net2280_ep	*ep;
@@ -2948,6 +2948,7 @@
 static struct pci_driver net2280_pci_driver = {
 	.name =		(char *) driver_name,
 	.id_table =	pci_ids,
+	.owner =	THIS_MODULE,
 
 	.probe =	net2280_probe,
 	.remove =	net2280_remove,
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index ff5533e..41c96b0 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -269,7 +269,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-omap_alloc_request(struct usb_ep *ep, unsigned gfp_flags)
+omap_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 {
 	struct omap_req	*req;
 
@@ -298,7 +298,7 @@
 	struct usb_ep	*_ep,
 	unsigned	bytes,
 	dma_addr_t	*dma,
-	unsigned	gfp_flags
+	gfp_t		gfp_flags
 )
 {
 	void		*retval;
@@ -691,7 +691,7 @@
 }
 
 static void
-finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
+finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
 {
 	u16	count;
 
@@ -699,6 +699,8 @@
 		ep->dma_counter = (u16) (req->req.dma + req->req.actual);
 	count = dma_dest_len(ep, req->req.dma + req->req.actual);
 	count += req->req.actual;
+	if (one)
+		count--;
 	if (count <= req->req.length)
 		req->req.actual = count;
 
@@ -747,7 +749,7 @@
 		if (!list_empty(&ep->queue)) {
 			req = container_of(ep->queue.next,
 					struct omap_req, queue);
-			finish_out_dma(ep, req, 0);
+			finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
 		}
 		UDC_IRQ_SRC_REG = UDC_RXN_EOT;
 
@@ -925,7 +927,7 @@
 		while (UDC_RXDMA_CFG_REG & mask)
 			udelay(10);
 		if (req)
-			finish_out_dma(ep, req, -ECONNRESET);
+			finish_out_dma(ep, req, -ECONNRESET, 0);
 	}
 	omap_free_dma(ep->lch);
 	ep->dma_channel = 0;
@@ -937,7 +939,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
 	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
 	struct omap_req	*req = container_of(_req, struct omap_req, req);
@@ -1786,8 +1788,12 @@
 					udc->driver->suspend(&udc->gadget);
 					spin_lock(&udc->lock);
 				}
+				if (udc->transceiver)
+					otg_set_suspend(udc->transceiver, 1);
 			} else {
 				VDBG("resume\n");
+				if (udc->transceiver)
+					otg_set_suspend(udc->transceiver, 0);
 				if (udc->gadget.speed == USB_SPEED_FULL
 						&& udc->driver->resume) {
 					spin_unlock(&udc->lock);
@@ -2909,12 +2915,10 @@
  * may involve talking to an external transceiver (e.g. isp1301).
  */
 
-static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level)
+static int omap_udc_suspend(struct device *dev, pm_message_t message)
 {
 	u32	devstat;
 
-	if (level != SUSPEND_POWER_DOWN)
-		return 0;
 	devstat = UDC_DEVSTAT_REG;
 
 	/* we're requesting 48 MHz clock if the pullup is enabled
@@ -2931,11 +2935,8 @@
 	return 0;
 }
 
-static int omap_udc_resume(struct device *dev, u32 level)
+static int omap_udc_resume(struct device *dev)
 {
-	if (level != RESUME_POWER_ON)
-		return 0;
-
 	DBG("resume + wakeup/SRP\n");
 	omap_pullup(&udc->gadget, 1);
 
@@ -2948,6 +2949,7 @@
 
 static struct device_driver udc_driver = {
 	.name		= (char *) driver_name,
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= omap_udc_probe,
 	.remove		= __exit_p(omap_udc_remove),
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 73f8c94..f83a926 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -332,7 +332,7 @@
  * 	pxa2xx_ep_alloc_request - allocate a request data structure
  */
 static struct usb_request *
-pxa2xx_ep_alloc_request (struct usb_ep *_ep, unsigned gfp_flags)
+pxa2xx_ep_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 {
 	struct pxa2xx_request *req;
 
@@ -367,7 +367,7 @@
  */
 static void *
 pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
-	dma_addr_t *dma, unsigned gfp_flags)
+	dma_addr_t *dma, gfp_t gfp_flags)
 {
 	char			*retval;
 
@@ -422,7 +422,7 @@
 }
 
 static int
-write_packet(volatile unsigned long *uddr, struct pxa2xx_request *req, unsigned max)
+write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max)
 {
 	u8		*buf;
 	unsigned	length, count;
@@ -874,7 +874,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags)
+pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
 	struct pxa2xx_request	*req;
 	struct pxa2xx_ep	*ep;
@@ -2602,24 +2602,23 @@
  * VBUS IRQs should probably be ignored so that the PXA device just acts
  * "dead" to USB hosts until system resume.
  */
-static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state)
 {
 	struct pxa2xx_udc	*udc = dev_get_drvdata(dev);
 
-	if (level == SUSPEND_POWER_DOWN) {
-		if (!udc->mach->udc_command)
-			WARN("USB host won't detect disconnect!\n");
-		pullup(udc, 0);
-	}
+	if (!udc->mach->udc_command)
+		WARN("USB host won't detect disconnect!\n");
+	pullup(udc, 0);
+
 	return 0;
 }
 
-static int pxa2xx_udc_resume(struct device *dev, u32 level)
+static int pxa2xx_udc_resume(struct device *dev)
 {
 	struct pxa2xx_udc	*udc = dev_get_drvdata(dev);
 
-	if (level == RESUME_POWER_ON)
-		pullup(udc, 1);
+	pullup(udc, 1);
+
 	return 0;
 }
 
@@ -2632,6 +2631,7 @@
 
 static struct device_driver udc_driver = {
 	.name		= "pxa2xx-udc",
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= pxa2xx_udc_probe,
 	.shutdown	= pxa2xx_udc_shutdown,
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index a58f3e6..19a883f 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -69,11 +69,11 @@
 	 * UDDR = UDC Endpoint Data Register (the fifo)
 	 * DRCM = DMA Request Channel Map
 	 */
-	volatile unsigned long			*reg_udccs;
-	volatile unsigned long			*reg_ubcr;
-	volatile unsigned long			*reg_uddr;
+	volatile u32				*reg_udccs;
+	volatile u32				*reg_ubcr;
+	volatile u32				*reg_uddr;
 #ifdef USE_DMA
-	volatile unsigned long			*reg_drcmr;
+	volatile u32			*reg_drcmr;
 #define	drcmr(n)  .reg_drcmr = & DRCMR ## n ,
 #else
 #define	drcmr(n)  
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index c925d92..b35ac6d 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -300,18 +300,18 @@
 		u8 type, unsigned int index, int is_otg);
 
 static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
-	unsigned kmalloc_flags);
+	gfp_t kmalloc_flags);
 static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
 
 static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,
-	unsigned kmalloc_flags);
+	gfp_t kmalloc_flags);
 static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);
 
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags);
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
 static void gs_free_ports(struct gs_dev *dev);
 
 /* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags);
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
 static void gs_buf_free(struct gs_buf *gb);
 static void gs_buf_clear(struct gs_buf *gb);
 static unsigned int gs_buf_data_avail(struct gs_buf *gb);
@@ -2091,7 +2091,7 @@
  * usb_request or NULL if there is an error.
  */
 static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags)
+gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
 {
 	struct usb_request *req;
 
@@ -2132,7 +2132,7 @@
  * endpoint, buffer len, and kmalloc flags.
  */
 static struct gs_req_entry *
-gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags)
+gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
 {
 	struct gs_req_entry	*req;
 
@@ -2173,7 +2173,7 @@
  *
  * The device lock is normally held when calling this function.
  */
-static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags)
+static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
 {
 	int i;
 	struct gs_port *port;
@@ -2255,7 +2255,7 @@
  *
  * Allocate a circular buffer and all associated memory.
  */
-static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags)
+static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
 {
 	struct gs_buf *gb;
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 6890e77..6c58636 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -612,7 +612,7 @@
 }
 
 static struct usb_request *
-source_sink_start_ep (struct usb_ep *ep, unsigned gfp_flags)
+source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
 {
 	struct usb_request	*req;
 	int			status;
@@ -640,7 +640,7 @@
 }
 
 static int
-set_source_sink_config (struct zero_dev *dev, unsigned gfp_flags)
+set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_ep		*ep;
@@ -744,7 +744,7 @@
 }
 
 static int
-set_loopback_config (struct zero_dev *dev, unsigned gfp_flags)
+set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_ep		*ep;
@@ -845,7 +845,7 @@
  * by limiting configuration choices (like the pxa2xx).
  */
 static int
-zero_set_config (struct zero_dev *dev, unsigned number, unsigned gfp_flags)
+zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)
 {
 	int			result = 0;
 	struct usb_gadget	*gadget = dev->gadget;
@@ -1302,6 +1302,7 @@
 
 	.driver 	= {
 		.name		= (char *) shortname,
+		.owner		= THIS_MODULE,
 		// .shutdown = ...
 		// .suspend = ...
 		// .resume = ...
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 350d14f..58321d3 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -1,8 +1,9 @@
 #
-# Makefile for USB Host Controller Driver
-# framework and drivers
+# Makefile for USB Host Controller Drivers
 #
 
+obj-$(CONFIG_PCI)		+= pci-quirks.o
+
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b948ffd..af3c05e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -182,6 +182,9 @@
 {
 	u32	temp = readl (&ehci->regs->status);
 
+	/* disable any irqs left enabled by previous code */
+	writel (0, &ehci->regs->intr_enable);
+
 	if ((temp & STS_HALT) != 0)
 		return 0;
 
@@ -297,50 +300,17 @@
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
-#ifdef	CONFIG_PCI
-
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
+/* Reboot notifiers kick in for silicon on any bus (not just pci, etc).
+ * This forcibly disables dma and IRQs, helping kexec and other cases
+ * where the next system software may expect clean state.
  */
-static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
-{
-	struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
-	/* always say Linux will own the hardware */
-	pci_write_config_byte(pdev, where + 3, 1);
-
-	/* maybe wait a while for BIOS to respond */
-	if (cap & (1 << 16)) {
-		int msec = 5000;
-
-		do {
-			msleep(10);
-			msec -= 10;
-			pci_read_config_dword(pdev, where, &cap);
-		} while ((cap & (1 << 16)) && msec);
-		if (cap & (1 << 16)) {
-			ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
-				where, cap);
-			// some BIOS versions seem buggy...
-			// return 1;
-			ehci_warn (ehci, "continuing after BIOS bug...\n");
-			/* disable all SMIs, and clear "BIOS owns" flag */
-			pci_write_config_dword(pdev, where + 4, 0);
-			pci_write_config_byte(pdev, where + 2, 0);
-		} else
-			ehci_dbg(ehci, "BIOS handoff succeeded\n");
-	}
-	return 0;
-}
-
-#endif
-
 static int
 ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
 {
 	struct ehci_hcd		*ehci;
 
 	ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+	(void) ehci_halt (ehci);
 
 	/* make BIOS/etc use companion controller during reboot */
 	writel (0, &ehci->regs->configured_flag);
@@ -363,156 +333,90 @@
 	msleep(20);
 }
 
+/*-------------------------------------------------------------------------*/
 
-/* called by khubd or root hub init threads */
-
-static int ehci_hc_reset (struct usb_hcd *hcd)
+/*
+ * ehci_work is called from some interrupts, timers, and so on.
+ * it calls driver completion functions, after dropping ehci->lock.
+ */
+static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	u32			temp;
-	unsigned		count = 256/4;
+	timer_action_done (ehci, TIMER_IO_WATCHDOG);
+	if (ehci->reclaim_ready)
+		end_unlink_async (ehci, regs);
 
-	spin_lock_init (&ehci->lock);
+	/* another CPU may drop ehci->lock during a schedule scan while
+	 * it reports urb completions.  this flag guards against bogus
+	 * attempts at re-entrant schedule scanning.
+	 */
+	if (ehci->scanning)
+		return;
+	ehci->scanning = 1;
+	scan_async (ehci, regs);
+	if (ehci->next_uframe != -1)
+		scan_periodic (ehci, regs);
+	ehci->scanning = 0;
 
-	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
-	dbg_hcs_params (ehci, "reset");
-	dbg_hcc_params (ehci, "reset");
-
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl (&ehci->caps->hcs_params);
-
-#ifdef	CONFIG_PCI
-	if (hcd->self.controller->bus == &pci_bus_type) {
-		struct pci_dev	*pdev = to_pci_dev(hcd->self.controller);
-
-		switch (pdev->vendor) {
-		case PCI_VENDOR_ID_TDI:
-			if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
-				ehci->is_tdi_rh_tt = 1;
-				tdi_reset (ehci);
-			}
-			break;
-		case PCI_VENDOR_ID_AMD:
-			/* AMD8111 EHCI doesn't work, according to AMD errata */
-			if (pdev->device == 0x7463) {
-				ehci_info (ehci, "ignoring AMD8111 (errata)\n");
-				return -EIO;
-			}
-			break;
-		case PCI_VENDOR_ID_NVIDIA:
-			/* NVidia reports that certain chips don't handle
-			 * QH, ITD, or SITD addresses above 2GB.  (But TD,
-			 * data buffer, and periodic schedule are normal.)
-			 */
-			switch (pdev->device) {
-			case 0x003c:	/* MCP04 */
-			case 0x005b:	/* CK804 */
-			case 0x00d8:	/* CK8 */
-			case 0x00e8:	/* CK8S */
-				if (pci_set_consistent_dma_mask(pdev,
-							DMA_31BIT_MASK) < 0)
-					ehci_warn (ehci, "can't enable NVidia "
-						"workaround for >2GB RAM\n");
-				break;
-			}
-			break;
-		}
-
-		/* optional debug port, normally in the first BAR */
-		temp = pci_find_capability (pdev, 0x0a);
-		if (temp) {
-			pci_read_config_dword(pdev, temp, &temp);
-			temp >>= 16;
-			if ((temp & (3 << 13)) == (1 << 13)) {
-				temp &= 0x1fff;
-				ehci->debug = hcd->regs + temp;
-				temp = readl (&ehci->debug->control);
-				ehci_info (ehci, "debug port %d%s\n",
-					HCS_DEBUG_PORT(ehci->hcs_params),
-					(temp & DBGP_ENABLED)
-						? " IN USE"
-						: "");
-				if (!(temp & DBGP_ENABLED))
-					ehci->debug = NULL;
-			}
-		}
-
-		temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
-	} else
-		temp = 0;
-
-	/* EHCI 0.96 and later may have "extended capabilities" */
-	while (temp && count--) {
-		u32		cap;
-
-		pci_read_config_dword (to_pci_dev(hcd->self.controller),
-				temp, &cap);
-		ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
-		switch (cap & 0xff) {
-		case 1:			/* BIOS/SMM/... handoff */
-			if (bios_handoff (ehci, temp, cap) != 0)
-				return -EOPNOTSUPP;
-			break;
-		case 0:			/* illegal reserved capability */
-			ehci_warn (ehci, "illegal capability!\n");
-			cap = 0;
-			/* FALLTHROUGH */
-		default:		/* unknown */
-			break;
-		}
-		temp = (cap >> 8) & 0xff;
-	}
-	if (!count) {
-		ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
-		return -EIO;
-	}
-	if (ehci_is_TDI(ehci))
-		ehci_reset (ehci);
-#endif
-
-	ehci_port_power (ehci, 0);
-
-	/* at least the Genesys GL880S needs fixup here */
-	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
-	temp &= 0x0f;
-	if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
-		ehci_dbg (ehci, "bogus port configuration: "
-			"cc=%d x pcc=%d < ports=%d\n",
-			HCS_N_CC(ehci->hcs_params),
-			HCS_N_PCC(ehci->hcs_params),
-			HCS_N_PORTS(ehci->hcs_params));
-
-#ifdef	CONFIG_PCI
-		if (hcd->self.controller->bus == &pci_bus_type) {
-			struct pci_dev	*pdev;
-
-			pdev = to_pci_dev(hcd->self.controller);
-			switch (pdev->vendor) {
-			case 0x17a0:		/* GENESYS */
-				/* GL880S: should be PORTS=2 */
-				temp |= (ehci->hcs_params & ~0xf);
-				ehci->hcs_params = temp;
-				break;
-			case PCI_VENDOR_ID_NVIDIA:
-				/* NF4: should be PCC=10 */
-				break;
-			}
-		}
-#endif
-	}
-
-	/* force HC to halt state */
-	return ehci_halt (ehci);
+	/* the IO watchdog guards against hardware or driver bugs that
+	 * misplace IRQs, and should let us run completely without IRQs.
+	 * such lossage has been observed on both VT6202 and VT8235.
+	 */
+	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+			(ehci->async->qh_next.ptr != NULL ||
+			 ehci->periodic_sched != 0))
+		timer_action (ehci, TIMER_IO_WATCHDOG);
 }
 
-static int ehci_start (struct usb_hcd *hcd)
+static void ehci_stop (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+
+	ehci_dbg (ehci, "stop\n");
+
+	/* Turn off port power on all root hub ports. */
+	ehci_port_power (ehci, 0);
+
+	/* no more interrupts ... */
+	del_timer_sync (&ehci->watchdog);
+
+	spin_lock_irq(&ehci->lock);
+	if (HC_IS_RUNNING (hcd->state))
+		ehci_quiesce (ehci);
+
+	ehci_reset (ehci);
+	writel (0, &ehci->regs->intr_enable);
+	spin_unlock_irq(&ehci->lock);
+
+	/* let companion controllers work when we aren't */
+	writel (0, &ehci->regs->configured_flag);
+	unregister_reboot_notifier (&ehci->reboot_notifier);
+
+	remove_debug_files (ehci);
+
+	/* root hub is shut down separately (first, when possible) */
+	spin_lock_irq (&ehci->lock);
+	if (ehci->async)
+		ehci_work (ehci, NULL);
+	spin_unlock_irq (&ehci->lock);
+	ehci_mem_cleanup (ehci);
+
+#ifdef	EHCI_STATS
+	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
+		ehci->stats.lost_iaa);
+	ehci_dbg (ehci, "complete %ld unlink %ld\n",
+		ehci->stats.complete, ehci->stats.unlink);
+#endif
+
+	dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
+}
+
+static int ehci_run (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			temp;
 	int			retval;
 	u32			hcc_params;
-	u8                      sbrn = 0;
 	int			first;
 
 	/* skip some things on restart paths */
@@ -551,27 +455,6 @@
 	}
 	writel (ehci->periodic_dma, &ehci->regs->frame_list);
 
-#ifdef	CONFIG_PCI
-	if (hcd->self.controller->bus == &pci_bus_type) {
-		struct pci_dev		*pdev;
-		u16			port_wake;
-
-		pdev = to_pci_dev(hcd->self.controller);
-
-		/* Serial Bus Release Number is at PCI 0x60 offset */
-		pci_read_config_byte(pdev, 0x60, &sbrn);
-
-		/* port wake capability, reported by boot firmware */
-		pci_read_config_word(pdev, 0x62, &port_wake);
-		hcd->can_wakeup = (port_wake & 1) != 0;
-
-		/* help hc dma work well with cachelines */
-		retval = pci_set_mwi(pdev);
-		if (retval)
-			ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
-	}
-#endif
-
 	/*
 	 * dedicate a qh for the async ring head, since we couldn't unlink
 	 * a 'real' qh without stopping the async schedule [4.8].  use it
@@ -667,7 +550,7 @@
 	temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
 	ehci_info (ehci,
 		"USB %x.%x %s, EHCI %x.%02x, driver %s\n",
-		((sbrn & 0xf0)>>4), (sbrn & 0x0f),
+		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
 		first ? "initialized" : "restarted",
 		temp >> 8, temp & 0xff, DRIVER_VERSION);
 
@@ -679,188 +562,6 @@
 	return 0;
 }
 
-/* always called by thread; normally rmmod */
-
-static void ehci_stop (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-
-	ehci_dbg (ehci, "stop\n");
-
-	/* Turn off port power on all root hub ports. */
-	ehci_port_power (ehci, 0);
-
-	/* no more interrupts ... */
-	del_timer_sync (&ehci->watchdog);
-
-	spin_lock_irq(&ehci->lock);
-	if (HC_IS_RUNNING (hcd->state))
-		ehci_quiesce (ehci);
-
-	ehci_reset (ehci);
-	writel (0, &ehci->regs->intr_enable);
-	spin_unlock_irq(&ehci->lock);
-
-	/* let companion controllers work when we aren't */
-	writel (0, &ehci->regs->configured_flag);
-	unregister_reboot_notifier (&ehci->reboot_notifier);
-
-	remove_debug_files (ehci);
-
-	/* root hub is shut down separately (first, when possible) */
-	spin_lock_irq (&ehci->lock);
-	if (ehci->async)
-		ehci_work (ehci, NULL);
-	spin_unlock_irq (&ehci->lock);
-	ehci_mem_cleanup (ehci);
-
-#ifdef	EHCI_STATS
-	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
-		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
-		ehci->stats.lost_iaa);
-	ehci_dbg (ehci, "complete %ld unlink %ld\n",
-		ehci->stats.complete, ehci->stats.unlink);
-#endif
-
-	dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
-}
-
-static int ehci_get_frame (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-
-/* suspend/resume, section 4.3 */
-
-/* These routines rely on the bus (pci, platform, etc)
- * to handle powerdown and wakeup, and currently also on
- * transceivers that don't need any software attention to set up
- * the right sort of wakeup.  
- */
-
-static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-
-	if (time_before (jiffies, ehci->next_statechange))
-		msleep (100);
-
-#ifdef	CONFIG_USB_SUSPEND
-	(void) usb_suspend_device (hcd->self.root_hub, message);
-#else
-	usb_lock_device (hcd->self.root_hub);
-	(void) ehci_hub_suspend (hcd);
-	usb_unlock_device (hcd->self.root_hub);
-#endif
-
-	// save (PCI) FLADJ in case of Vaux power loss
-	// ... we'd only use it to handle clock skew
-
-	return 0;
-}
-
-static int ehci_resume (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	unsigned		port;
-	struct usb_device	*root = hcd->self.root_hub;
-	int			retval = -EINVAL;
-
-	// maybe restore (PCI) FLADJ
-
-	if (time_before (jiffies, ehci->next_statechange))
-		msleep (100);
-
-	/* If any port is suspended (or owned by the companion),
-	 * we know we can/must resume the HC (and mustn't reset it).
-	 */
-	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
-		u32	status;
-		port--;
-		status = readl (&ehci->regs->port_status [port]);
-		if (!(status & PORT_POWER))
-			continue;
-		if (status & (PORT_SUSPEND | PORT_OWNER)) {
-			down (&hcd->self.root_hub->serialize);
-			retval = ehci_hub_resume (hcd);
-			up (&hcd->self.root_hub->serialize);
-			break;
-		}
-		if (!root->children [port])
-			continue;
-		dbg_port (ehci, __FUNCTION__, port + 1, status);
-		usb_set_device_state (root->children[port],
-					USB_STATE_NOTATTACHED);
-	}
-
-	/* Else reset, to cope with power loss or flush-to-storage
-	 * style "resume" having activated BIOS during reboot.
-	 */
-	if (port == 0) {
-		(void) ehci_halt (ehci);
-		(void) ehci_reset (ehci);
-		(void) ehci_hc_reset (hcd);
-
-		/* emptying the schedule aborts any urbs */
-		spin_lock_irq (&ehci->lock);
-		if (ehci->reclaim)
-			ehci->reclaim_ready = 1;
-		ehci_work (ehci, NULL);
-		spin_unlock_irq (&ehci->lock);
-
-		/* restart; khubd will disconnect devices */
-		retval = ehci_start (hcd);
-
-		/* here we "know" root ports should always stay powered;
-		 * but some controllers may lose all power.
-		 */
-		ehci_port_power (ehci, 1);
-	}
-
-	return retval;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * ehci_work is called from some interrupts, timers, and so on.
- * it calls driver completion functions, after dropping ehci->lock.
- */
-static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
-{
-	timer_action_done (ehci, TIMER_IO_WATCHDOG);
-	if (ehci->reclaim_ready)
-		end_unlink_async (ehci, regs);
-
-	/* another CPU may drop ehci->lock during a schedule scan while
-	 * it reports urb completions.  this flag guards against bogus
-	 * attempts at re-entrant schedule scanning.
-	 */
-	if (ehci->scanning)
-		return;
-	ehci->scanning = 1;
-	scan_async (ehci, regs);
-	if (ehci->next_uframe != -1)
-		scan_periodic (ehci, regs);
-	ehci->scanning = 0;
-
-	/* the IO watchdog guards against hardware or driver bugs that
-	 * misplace IRQs, and should let us run completely without IRQs.
-	 * such lossage has been observed on both VT6202 and VT8235. 
-	 */
-	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
-			(ehci->async->qh_next.ptr != NULL ||
-			 ehci->periodic_sched != 0))
-		timer_action (ehci, TIMER_IO_WATCHDOG);
-}
-
 /*-------------------------------------------------------------------------*/
 
 static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
@@ -983,7 +684,7 @@
 	struct usb_hcd	*hcd,
 	struct usb_host_endpoint *ep,
 	struct urb	*urb,
-	unsigned	mem_flags
+	gfp_t		mem_flags
 ) {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	struct list_head	qtd_list;
@@ -1171,106 +872,24 @@
 	return;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ehci_driver = {
-	.description =		hcd_name,
-	.product_desc =		"EHCI Host Controller",
-	.hcd_priv_size =	sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ehci_irq,
-	.flags =		HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset =		ehci_hc_reset,
-	.start =		ehci_start,
-#ifdef	CONFIG_PM
-	.suspend =		ehci_suspend,
-	.resume =		ehci_resume,
-#endif
-	.stop =			ehci_stop,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ehci_urb_enqueue,
-	.urb_dequeue =		ehci_urb_dequeue,
-	.endpoint_disable =	ehci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ehci_hub_status_data,
-	.hub_control =		ehci_hub_control,
-	.hub_suspend =		ehci_hub_suspend,
-	.hub_resume =		ehci_hub_resume,
-};
+static int ehci_get_frame (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
+}
 
 /*-------------------------------------------------------------------------*/
 
-/* EHCI 1.0 doesn't require PCI */
-
-#ifdef	CONFIG_PCI
-
-/* PCI driver selection metadata; PCI hotplugging uses this */
-static const struct pci_device_id pci_ids [] = { {
-	/* handle any USB 2.0 EHCI controller */
-	PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
-	.driver_data =	(unsigned long) &ehci_driver,
-	},
-	{ /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver ehci_pci_driver = {
-	.name =		(char *) hcd_name,
-	.id_table =	pci_ids,
-
-	.probe =	usb_hcd_pci_probe,
-	.remove =	usb_hcd_pci_remove,
-
-#ifdef	CONFIG_PM
-	.suspend =	usb_hcd_pci_suspend,
-	.resume =	usb_hcd_pci_resume,
-#endif
-};
-
-#endif	/* PCI */
-
-
 #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
 
 MODULE_DESCRIPTION (DRIVER_INFO);
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_LICENSE ("GPL");
 
-static int __init init (void) 
-{
-	if (usb_disabled())
-		return -ENODEV;
+#ifdef CONFIG_PCI
+#include "ehci-pci.c"
+#endif
 
-	pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
-		hcd_name,
-		sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
-		sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
-
-	return pci_register_driver (&ehci_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void) 
-{	
-	pci_unregister_driver (&ehci_pci_driver);
-}
-module_exit (cleanup);
+#if !defined(CONFIG_PCI)
+#error "missing bus glue for ehci-hcd"
+#endif
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 18d3f22..88cb4ad 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -30,7 +30,7 @@
 
 #ifdef	CONFIG_PM
 
-static int ehci_hub_suspend (struct usb_hcd *hcd)
+static int ehci_bus_suspend (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	int			port;
@@ -83,7 +83,7 @@
 
 
 /* caller has locked the root hub, and should reset/reinit on error */
-static int ehci_hub_resume (struct usb_hcd *hcd)
+static int ehci_bus_resume (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	u32			temp;
@@ -159,8 +159,8 @@
 
 #else
 
-#define ehci_hub_suspend	NULL
-#define ehci_hub_resume		NULL
+#define ehci_bus_suspend	NULL
+#define ehci_bus_resume		NULL
 
 #endif	/* CONFIG_PM */
 
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 5c38ad8..91c2ab43 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -45,7 +45,7 @@
 	INIT_LIST_HEAD (&qtd->qtd_list);
 }
 
-static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
 {
 	struct ehci_qtd		*qtd;
 	dma_addr_t		dma;
@@ -79,7 +79,7 @@
 	dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
 }
 
-static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
+static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
 {
 	struct ehci_qh		*qh;
 	dma_addr_t		dma;
@@ -161,7 +161,7 @@
 }
 
 /* remember to add cleanup code (above) if you add anything here */
-static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
+static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
 {
 	int i;
 
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
new file mode 100644
index 0000000..1450088
--- /dev/null
+++ b/drivers/usb/host/ehci-pci.c
@@ -0,0 +1,415 @@
+/*
+ * EHCI HCD (Host Controller Driver) PCI Bus Glue.
+ *
+ * Copyright (c) 2000-2004 by 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.
+ */
+
+#ifndef CONFIG_PCI
+#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
+ * off the controller (maybe it can boot from highspeed USB disks).
+ */
+static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
+{
+	struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
+
+	/* always say Linux will own the hardware */
+	pci_write_config_byte(pdev, where + 3, 1);
+
+	/* maybe wait a while for BIOS to respond */
+	if (cap & (1 << 16)) {
+		int msec = 5000;
+
+		do {
+			msleep(10);
+			msec -= 10;
+			pci_read_config_dword(pdev, where, &cap);
+		} while ((cap & (1 << 16)) && msec);
+		if (cap & (1 << 16)) {
+			ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
+				where, cap);
+			// some BIOS versions seem buggy...
+			// return 1;
+			ehci_warn (ehci, "continuing after BIOS bug...\n");
+			/* disable all SMIs, and clear "BIOS owns" flag */
+			pci_write_config_dword(pdev, where + 4, 0);
+			pci_write_config_byte(pdev, where + 2, 0);
+		} else
+			ehci_dbg(ehci, "BIOS handoff succeeded\n");
+	}
+	return 0;
+}
+
+/* called by khubd or root hub init threads */
+static int ehci_pci_reset (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	u32			temp;
+	unsigned		count = 256/4;
+
+	spin_lock_init (&ehci->lock);
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase));
+	dbg_hcs_params (ehci, "reset");
+	dbg_hcc_params (ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl (&ehci->caps->hcs_params);
+
+	if (hcd->self.controller->bus == &pci_bus_type) {
+		struct pci_dev	*pdev = to_pci_dev(hcd->self.controller);
+
+		switch (pdev->vendor) {
+		case PCI_VENDOR_ID_TDI:
+			if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+				ehci->is_tdi_rh_tt = 1;
+				tdi_reset (ehci);
+			}
+			break;
+		case PCI_VENDOR_ID_AMD:
+			/* AMD8111 EHCI doesn't work, according to AMD errata */
+			if (pdev->device == 0x7463) {
+				ehci_info (ehci, "ignoring AMD8111 (errata)\n");
+				return -EIO;
+			}
+			break;
+		case PCI_VENDOR_ID_NVIDIA:
+			/* NVidia reports that certain chips don't handle
+			 * QH, ITD, or SITD addresses above 2GB.  (But TD,
+			 * data buffer, and periodic schedule are normal.)
+			 */
+			switch (pdev->device) {
+			case 0x003c:	/* MCP04 */
+			case 0x005b:	/* CK804 */
+			case 0x00d8:	/* CK8 */
+			case 0x00e8:	/* CK8S */
+				if (pci_set_consistent_dma_mask(pdev,
+							DMA_31BIT_MASK) < 0)
+					ehci_warn (ehci, "can't enable NVidia "
+						"workaround for >2GB RAM\n");
+				break;
+			}
+			break;
+		}
+
+		/* optional debug port, normally in the first BAR */
+		temp = pci_find_capability (pdev, 0x0a);
+		if (temp) {
+			pci_read_config_dword(pdev, temp, &temp);
+			temp >>= 16;
+			if ((temp & (3 << 13)) == (1 << 13)) {
+				temp &= 0x1fff;
+				ehci->debug = hcd->regs + temp;
+				temp = readl (&ehci->debug->control);
+				ehci_info (ehci, "debug port %d%s\n",
+					HCS_DEBUG_PORT(ehci->hcs_params),
+					(temp & DBGP_ENABLED)
+						? " IN USE"
+						: "");
+				if (!(temp & DBGP_ENABLED))
+					ehci->debug = NULL;
+			}
+		}
+
+		temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
+	} else
+		temp = 0;
+
+	/* EHCI 0.96 and later may have "extended capabilities" */
+	while (temp && count--) {
+		u32		cap;
+
+		pci_read_config_dword (to_pci_dev(hcd->self.controller),
+				temp, &cap);
+		ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
+		switch (cap & 0xff) {
+		case 1:			/* BIOS/SMM/... handoff */
+			if (bios_handoff (ehci, temp, cap) != 0)
+				return -EOPNOTSUPP;
+			break;
+		case 0:			/* illegal reserved capability */
+			ehci_warn (ehci, "illegal capability!\n");
+			cap = 0;
+			/* FALLTHROUGH */
+		default:		/* unknown */
+			break;
+		}
+		temp = (cap >> 8) & 0xff;
+	}
+	if (!count) {
+		ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
+		return -EIO;
+	}
+	if (ehci_is_TDI(ehci))
+		ehci_reset (ehci);
+
+	ehci_port_power (ehci, 0);
+
+	/* at least the Genesys GL880S needs fixup here */
+	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
+	temp &= 0x0f;
+	if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
+		ehci_dbg (ehci, "bogus port configuration: "
+			"cc=%d x pcc=%d < ports=%d\n",
+			HCS_N_CC(ehci->hcs_params),
+			HCS_N_PCC(ehci->hcs_params),
+			HCS_N_PORTS(ehci->hcs_params));
+
+		if (hcd->self.controller->bus == &pci_bus_type) {
+			struct pci_dev	*pdev;
+
+			pdev = to_pci_dev(hcd->self.controller);
+			switch (pdev->vendor) {
+			case 0x17a0:		/* GENESYS */
+				/* GL880S: should be PORTS=2 */
+				temp |= (ehci->hcs_params & ~0xf);
+				ehci->hcs_params = temp;
+				break;
+			case PCI_VENDOR_ID_NVIDIA:
+				/* NF4: should be PCC=10 */
+				break;
+			}
+		}
+	}
+
+	/* force HC to halt state */
+	return ehci_halt (ehci);
+}
+
+static int ehci_pci_start (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	int result = 0;
+
+	if (hcd->self.controller->bus == &pci_bus_type) {
+		struct pci_dev		*pdev;
+		u16			port_wake;
+
+		pdev = to_pci_dev(hcd->self.controller);
+
+		/* Serial Bus Release Number is at PCI 0x60 offset */
+		pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+
+		/* port wake capability, reported by boot firmware */
+		pci_read_config_word(pdev, 0x62, &port_wake);
+		hcd->can_wakeup = (port_wake & 1) != 0;
+
+		/* help hc dma work well with cachelines */
+		result = pci_set_mwi(pdev);
+		if (result)
+			ehci_dbg(ehci, "unable to enable MWI - not fatal.\n");
+	}
+
+	return ehci_run (hcd);
+}
+
+/* always called by thread; normally rmmod */
+
+static void ehci_pci_stop (struct usb_hcd *hcd)
+{
+	ehci_stop (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+/* These routines rely on the bus (pci, platform, etc)
+ * to handle powerdown and wakeup, and currently also on
+ * transceivers that don't need any software attention to set up
+ * the right sort of wakeup.
+ */
+
+static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+
+	if (time_before (jiffies, ehci->next_statechange))
+		msleep (100);
+
+#ifdef	CONFIG_USB_SUSPEND
+	(void) usb_suspend_device (hcd->self.root_hub);
+#else
+	usb_lock_device (hcd->self.root_hub);
+	(void) ehci_bus_suspend (hcd);
+	usb_unlock_device (hcd->self.root_hub);
+#endif
+
+	// save (PCI) FLADJ in case of Vaux power loss
+	// ... we'd only use it to handle clock skew
+
+	return 0;
+}
+
+static int ehci_pci_resume (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	unsigned		port;
+	struct usb_device	*root = hcd->self.root_hub;
+	int			retval = -EINVAL;
+
+	// maybe restore (PCI) FLADJ
+
+	if (time_before (jiffies, ehci->next_statechange))
+		msleep (100);
+
+	/* If any port is suspended (or owned by the companion),
+	 * we know we can/must resume the HC (and mustn't reset it).
+	 */
+	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+		u32	status;
+		port--;
+		status = readl (&ehci->regs->port_status [port]);
+		if (!(status & PORT_POWER))
+			continue;
+		if (status & (PORT_SUSPEND | PORT_OWNER)) {
+			down (&hcd->self.root_hub->serialize);
+			retval = ehci_bus_resume (hcd);
+			up (&hcd->self.root_hub->serialize);
+			break;
+		}
+		if (!root->children [port])
+			continue;
+		dbg_port (ehci, __FUNCTION__, port + 1, status);
+		usb_set_device_state (root->children[port],
+					USB_STATE_NOTATTACHED);
+	}
+
+	/* Else reset, to cope with power loss or flush-to-storage
+	 * style "resume" having activated BIOS during reboot.
+	 */
+	if (port == 0) {
+		(void) ehci_halt (ehci);
+		(void) ehci_reset (ehci);
+		(void) ehci_pci_reset (hcd);
+
+		/* emptying the schedule aborts any urbs */
+		spin_lock_irq (&ehci->lock);
+		if (ehci->reclaim)
+			ehci->reclaim_ready = 1;
+		ehci_work (ehci, NULL);
+		spin_unlock_irq (&ehci->lock);
+
+		/* restart; khubd will disconnect devices */
+		retval = ehci_run (hcd);
+
+		/* here we "know" root ports should always stay powered;
+		 * but some controllers may lose all power.
+		 */
+		ehci_port_power (ehci, 1);
+	}
+
+	return retval;
+}
+#endif
+
+static const struct hc_driver ehci_pci_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"EHCI Host Controller",
+	.hcd_priv_size =	sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ehci_irq,
+	.flags =		HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset =		ehci_pci_reset,
+	.start =		ehci_pci_start,
+#ifdef	CONFIG_PM
+	.suspend =		ehci_pci_suspend,
+	.resume =		ehci_pci_resume,
+#endif
+	.stop =			ehci_pci_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ehci_urb_enqueue,
+	.urb_dequeue =		ehci_urb_dequeue,
+	.endpoint_disable =	ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ehci_hub_status_data,
+	.hub_control =		ehci_hub_control,
+	.bus_suspend =		ehci_bus_suspend,
+	.bus_resume =		ehci_bus_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* PCI driver selection metadata; PCI hotplugging uses this */
+static const struct pci_device_id pci_ids [] = { {
+	/* handle any USB 2.0 EHCI controller */
+	PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
+	.driver_data =	(unsigned long) &ehci_pci_hc_driver,
+	},
+	{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver ehci_pci_driver = {
+	.name =		(char *) hcd_name,
+	.id_table =	pci_ids,
+	.owner = 	THIS_MODULE,
+
+	.probe =	usb_hcd_pci_probe,
+	.remove =	usb_hcd_pci_remove,
+
+#ifdef	CONFIG_PM
+	.suspend =	usb_hcd_pci_suspend,
+	.resume =	usb_hcd_pci_resume,
+#endif
+};
+
+static int __init ehci_hcd_pci_init (void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+		hcd_name,
+		sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
+		sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+
+	return pci_register_driver (&ehci_pci_driver);
+}
+module_init (ehci_hcd_pci_init);
+
+static void __exit ehci_hcd_pci_cleanup (void)
+{
+	pci_unregister_driver (&ehci_pci_driver);
+}
+module_exit (ehci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 940d38c..5bb872c 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -477,7 +477,7 @@
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
 	struct list_head	*head,
-	int			flags
+	gfp_t			flags
 ) {
 	struct ehci_qtd		*qtd, *qtd_prev;
 	dma_addr_t		buf;
@@ -629,7 +629,7 @@
 qh_make (
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
-	int			flags
+	gfp_t			flags
 ) {
 	struct ehci_qh		*qh = ehci_qh_alloc (ehci, flags);
 	u32			info1 = 0, info2 = 0;
@@ -906,7 +906,7 @@
 	struct usb_host_endpoint *ep,
 	struct urb		*urb,
 	struct list_head	*qtd_list,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 ) {
 	struct ehci_qtd		*qtd;
 	int			epnum;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index ccc7300..f0c8aa1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -589,7 +589,7 @@
 	struct usb_host_endpoint *ep,
 	struct urb		*urb,
 	struct list_head	*qtd_list,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 ) {
 	unsigned		epnum;
 	unsigned long		flags;
@@ -634,7 +634,7 @@
 /* ehci_iso_stream ops work with both ITD and SITD */
 
 static struct ehci_iso_stream *
-iso_stream_alloc (unsigned mem_flags)
+iso_stream_alloc (gfp_t mem_flags)
 {
 	struct ehci_iso_stream *stream;
 
@@ -851,7 +851,7 @@
 /* ehci_iso_sched ops can be ITD-only or SITD-only */
 
 static struct ehci_iso_sched *
-iso_sched_alloc (unsigned packets, unsigned mem_flags)
+iso_sched_alloc (unsigned packets, gfp_t mem_flags)
 {
 	struct ehci_iso_sched	*iso_sched;
 	int			size = sizeof *iso_sched;
@@ -924,7 +924,7 @@
 	struct ehci_iso_stream	*stream,
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 )
 {
 	struct ehci_itd		*itd;
@@ -1418,7 +1418,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
-	unsigned mem_flags)
+	gfp_t mem_flags)
 {
 	int			status = -EINVAL;
 	unsigned long		flags;
@@ -1529,7 +1529,7 @@
 	struct ehci_iso_stream	*stream,
 	struct ehci_hcd		*ehci,
 	struct urb		*urb,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 )
 {
 	struct ehci_sitd	*sitd;
@@ -1779,7 +1779,7 @@
 
 
 static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
-	unsigned mem_flags)
+	gfp_t mem_flags)
 {
 	int			status = -EINVAL;
 	unsigned long		flags;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index f34a051..18e257c 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -97,6 +97,7 @@
 #else
 #	define COUNT(x) do {} while (0)
 #endif
+	u8			sbrn;		/* packed release number */
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */ 
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index e142056..ddb8fc5 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -638,7 +638,7 @@
 				  + msecs_to_jiffies(20) + 1);
 		if (intstat & HCINT_RD) {
 			DBG("---- remote wakeup\n");
-			schedule_work(&isp116x->rh_resume);
+			usb_hcd_resume_root_hub(hcd);
 			ret = IRQ_HANDLED;
 		}
 		irqstat &= ~HCuPINT_OPR;
@@ -694,7 +694,7 @@
 
 static int isp116x_urb_enqueue(struct usb_hcd *hcd,
 			       struct usb_host_endpoint *hep, struct urb *urb,
-			       unsigned mem_flags)
+			       gfp_t mem_flags)
 {
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	struct usb_device *udev = urb->dev;
@@ -1160,7 +1160,7 @@
 
 #ifdef	CONFIG_PM
 
-static int isp116x_hub_suspend(struct usb_hcd *hcd)
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
 {
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	unsigned long flags;
@@ -1200,7 +1200,7 @@
 	return ret;
 }
 
-static int isp116x_hub_resume(struct usb_hcd *hcd)
+static int isp116x_bus_resume(struct usb_hcd *hcd)
 {
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	u32 val;
@@ -1263,21 +1263,11 @@
 	return 0;
 }
 
-static void isp116x_rh_resume(void *_hcd)
-{
-	struct usb_hcd *hcd = _hcd;
-
-	usb_resume_device(hcd->self.root_hub);
-}
 
 #else
 
-#define	isp116x_hub_suspend	NULL
-#define	isp116x_hub_resume	NULL
-
-static void isp116x_rh_resume(void *_hcd)
-{
-}
+#define	isp116x_bus_suspend	NULL
+#define	isp116x_bus_resume	NULL
 
 #endif
 
@@ -1636,8 +1626,8 @@
 
 	.hub_status_data = isp116x_hub_status_data,
 	.hub_control = isp116x_hub_control,
-	.hub_suspend = isp116x_hub_suspend,
-	.hub_resume = isp116x_hub_resume,
+	.bus_suspend = isp116x_bus_suspend,
+	.bus_resume = isp116x_bus_resume,
 };
 
 /*----------------------------------------------------------------*/
@@ -1732,7 +1722,6 @@
 	isp116x->addr_reg = addr_reg;
 	spin_lock_init(&isp116x->lock);
 	INIT_LIST_HEAD(&isp116x->async);
-	INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd);
 	isp116x->board = dev->platform_data;
 
 	if (!isp116x->board) {
@@ -1774,22 +1763,13 @@
 /*
   Suspend of platform device
 */
-static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)
+static int isp116x_suspend(struct device *dev, pm_message_t state)
 {
 	int ret = 0;
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
-	VDBG("%s: state %x, phase %x\n", __func__, state, phase);
+	VDBG("%s: state %x\n", __func__, state);
 
-	if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN)
-		return 0;
-
-	ret = usb_suspend_device(hcd->self.root_hub, state);
-	if (!ret) {
-		dev->power.power_state = state;
-		INFO("%s suspended\n", hcd_name);
-	} else
-		ERR("%s suspend failed\n", hcd_name);
+	dev->power.power_state = state;
 
 	return ret;
 }
@@ -1797,21 +1777,14 @@
 /*
   Resume platform device
 */
-static int isp116x_resume(struct device *dev, u32 phase)
+static int isp116x_resume(struct device *dev)
 {
 	int ret = 0;
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
-	VDBG("%s:  state %x, phase %x\n", __func__, dev->power.power_state,
-	     phase);
-	if (phase != RESUME_POWER_ON)
-		return 0;
+	VDBG("%s:  state %x\n", __func__, dev->power.power_state);
 
-	ret = usb_resume_device(hcd->self.root_hub);
-	if (!ret) {
-		dev->power.power_state = PMSG_ON;
-		VDBG("%s resumed\n", (char *)hcd_name);
-	}
+	dev->power.power_state = PMSG_ON;
+
 	return ret;
 }
 
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index 5887347..c6fec96 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -253,7 +253,6 @@
 
 struct isp116x {
 	spinlock_t lock;
-	struct work_struct rh_resume;
 
 	void __iomem *addr_reg;
 	void __iomem *data_reg;
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 3981bf1..a277e25 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -214,6 +214,11 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -259,6 +264,7 @@
 
 static struct device_driver ohci_hcd_au1xxx_driver = {
 	.name		= "au1xxx-ohci",
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_au1xxx_drv_probe,
 	.remove		= ohci_hcd_au1xxx_drv_remove,
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 7924c74..7bfffcb 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -193,10 +193,6 @@
 
 	maybe_print_eds (controller, "donehead",
 			ohci_readl (controller, &regs->donehead), next, size);
-
-	/* broken fminterval means traffic won't flow! */ 
-	ohci_dbg (controller, "fminterval %08x\n", 
-			ohci_readl (controller, &regs->fminterval));
 }
 
 #define dbg_port_sw(hc,num,value,next,size) \
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 67c1aa5..5c0c6c8 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -180,7 +180,7 @@
 	struct usb_hcd	*hcd,
 	struct usb_host_endpoint *ep,
 	struct urb	*urb,
-	unsigned	mem_flags
+	gfp_t		mem_flags
 ) {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	struct ed	*ed;
@@ -723,7 +723,7 @@
 		ohci_vdbg (ohci, "resume detect\n");
 		ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
 		if (hcd->state != HC_STATE_QUIESCING)
-			schedule_work(&ohci->rh_resume);
+			usb_hcd_resume_root_hub(hcd);
 	}
 
 	if (ints & OHCI_INTR_WDH) {
@@ -791,7 +791,7 @@
 
 /* must not be called from interrupt context */
 
-#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef	CONFIG_PM
 
 static int ohci_restart (struct ohci_hcd *ohci)
 {
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index ce7b28d..e01e77b 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -36,7 +36,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef	CONFIG_PM
 
 #define OHCI_SCHED_ENABLES \
 	(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
@@ -45,7 +45,7 @@
 static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
 static int ohci_restart (struct ohci_hcd *ohci);
 
-static int ohci_hub_suspend (struct usb_hcd *hcd)
+static int ohci_bus_suspend (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	int			status = 0;
@@ -73,7 +73,6 @@
 	ohci_dbg (ohci, "suspend root hub\n");
 
 	/* First stop any processing */
-	hcd->state = HC_STATE_QUIESCING;
 	if (ohci->hc_control & OHCI_SCHED_ENABLES) {
 		int		limit;
 
@@ -108,7 +107,9 @@
 	else
 		ohci->hc_control &= ~OHCI_CTRL_RWE;
 
-	/* Suspend hub */
+	/* Suspend hub ... this is the "global (to this bus) suspend" mode,
+	 * which doesn't imply ports will first be individually suspended.
+	 */
 	ohci->hc_control &= ~OHCI_CTRL_HCFS;
 	ohci->hc_control |= OHCI_USB_SUSPEND;
 	ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
@@ -118,8 +119,9 @@
 	ohci->next_statechange = jiffies + msecs_to_jiffies (5);
 
 done:
+	/* external suspend vs self autosuspend ... same effect */
 	if (status == 0)
-		hcd->state = HC_STATE_SUSPENDED;
+		usb_hcd_suspend_root_hub(hcd);
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	return status;
 }
@@ -133,7 +135,7 @@
 }
 
 /* caller has locked the root hub */
-static int ohci_hub_resume (struct usb_hcd *hcd)
+static int ohci_bus_resume (struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 	u32			temp, enables;
@@ -146,7 +148,7 @@
 	ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
 
 	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-		/* this can happen after suspend-to-disk */
+		/* this can happen after resuming a swsusp snapshot */
 		if (hcd->state == HC_STATE_RESUMING) {
 			ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
 					ohci->hc_control);
@@ -169,11 +171,12 @@
 		ohci_info (ohci, "wakeup\n");
 		break;
 	case OHCI_USB_OPER:
-		ohci_dbg (ohci, "already resumed\n");
-		status = 0;
+		/* this can happen after resuming a swsusp snapshot */
+		ohci_dbg (ohci, "snapshot resume? reinit\n");
+		status = -EBUSY;
 		break;
 	default:		/* RESET, we lost power */
-		ohci_dbg (ohci, "root hub hardware reset\n");
+		ohci_dbg (ohci, "lost power\n");
 		status = -EBUSY;
 	}
 	spin_unlock_irq (&ohci->lock);
@@ -198,8 +201,7 @@
 	}
 
 	/* Some controllers (lucent erratum) need extra-long delays */
-	hcd->state = HC_STATE_RESUMING;
-	mdelay (20 /* usb 11.5.1.10 */ + 15);
+	msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
 
 	temp = ohci_readl (ohci, &ohci->regs->control);
 	temp &= OHCI_CTRL_HCFS;
@@ -273,28 +275,10 @@
 		(void) ohci_readl (ohci, &ohci->regs->control);
 	}
 
-	hcd->state = HC_STATE_RUNNING;
 	return 0;
 }
 
-static void ohci_rh_resume (void *_hcd)
-{
-	struct usb_hcd	*hcd = _hcd;
-
-	usb_lock_device (hcd->self.root_hub);
-	(void) ohci_hub_resume (hcd);
-	usb_unlock_device (hcd->self.root_hub);
-}
-
-#else
-
-static void ohci_rh_resume (void *_hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (_hcd);
-	ohci_dbg(ohci, "rh_resume ??\n");
-}
-
-#endif	/* CONFIG_USB_SUSPEND || CONFIG_PM */
+#endif	/* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 
@@ -367,7 +351,6 @@
 #ifdef CONFIG_PM
 	/* save power by suspending idle root hubs;
 	 * INTR_RD wakes us when there's work
-	 * NOTE: if we can do this, we don't need a root hub timer!
 	 */
 	if (can_suspend
 			&& !changed
@@ -379,8 +362,7 @@
 			&& usb_trylock_device (hcd->self.root_hub)
 			) {
 		ohci_vdbg (ohci, "autosuspend\n");
-		(void) ohci_hub_suspend (hcd);
-		hcd->state = HC_STATE_RUNNING;
+		(void) ohci_bus_suspend (hcd);
 		usb_unlock_device (hcd->self.root_hub);
 	}
 #endif
@@ -554,7 +536,7 @@
 			temp = RH_PS_POCI;
 			if ((ohci->hc_control & OHCI_CTRL_HCFS)
 					!= OHCI_USB_OPER)
-				schedule_work (&ohci->rh_resume);
+				usb_hcd_resume_root_hub(hcd);
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
 			temp = RH_PS_PSSC;
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 859aca7b..238fa4a 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -193,6 +193,11 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -239,6 +244,7 @@
 
 static struct device_driver ohci_hcd_lh7a404_driver = {
 	.name		= "lh7a404-ohci",
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_lh7a404_drv_probe,
 	.remove		= ohci_hcd_lh7a404_drv_remove,
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index fd3c4d3..bfbe328 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,7 +28,6 @@
 	ohci->next_statechange = jiffies;
 	spin_lock_init (&ohci->lock);
 	INIT_LIST_HEAD (&ohci->pending);
-	INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci));
 	ohci->reboot_notifier.notifier_call = ohci_reboot;
 }
 
@@ -84,7 +83,7 @@
 
 /* TDs ... */
 static struct td *
-td_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
 {
 	dma_addr_t	dma;
 	struct td	*td;
@@ -118,7 +117,7 @@
 
 /* EDs ... */
 static struct ed *
-ed_alloc (struct ohci_hcd *hc, unsigned mem_flags)
+ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
 {
 	dma_addr_t	dma;
 	struct ed	*ed;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index d8f3ba7..49815ec 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -14,6 +14,9 @@
  * This file is licenced under the GPL.
  */
 
+#include <linux/signal.h>	/* SA_INTERRUPT */
+#include <linux/jiffies.h>
+
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
@@ -420,9 +423,9 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_USB_SUSPEND
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
 	.start_port_reset =	ohci_start_port_reset,
 };
@@ -455,50 +458,32 @@
 
 #ifdef	CONFIG_PM
 
-static int ohci_omap_suspend(struct device *dev, pm_message_t message, u32 level)
+static int ohci_omap_suspend(struct device *dev, pm_message_t message)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
-	int		status = -EINVAL;
-
-	if (level != SUSPEND_POWER_DOWN)
-		return 0;
-
-	down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-	status = ohci_hub_suspend(ohci_to_hcd(ohci));
-	if (status == 0) {
-		omap_ohci_clock_power(0);
-		ohci_to_hcd(ohci)->self.root_hub->state =
-			USB_STATE_SUSPENDED;
-		ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-		dev->power.power_state = PMSG_SUSPEND;
-	}
-	up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-	return status;
-}
-
-static int ohci_omap_resume(struct device *dev, u32 level)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
-	int		status = 0;
-
-	if (level != RESUME_POWER_ON)
-		return 0;
 
 	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
 	ohci->next_statechange = jiffies;
+
+	omap_ohci_clock_power(0);
+	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+	dev->power.power_state = PMSG_SUSPEND;
+	return 0;
+}
+
+static int ohci_omap_resume(struct device *dev)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
 	omap_ohci_clock_power(1);
-#ifdef	CONFIG_USB_SUSPEND
-	/* get extra cleanup even if remote wakeup isn't in use */
-	status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
-#else
-	down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-	status = ohci_hub_resume(ohci_to_hcd(ohci));
-	up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-#endif
-	if (status == 0)
-		dev->power.power_state = PMSG_ON;
-	return status;
+	dev->power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+	return 0;
 }
 
 #endif
@@ -510,6 +495,7 @@
  */
 static struct device_driver ohci_hcd_omap_driver = {
 	.name		= "ohci",
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_omap_drv_probe,
 	.remove		= ohci_hcd_omap_drv_remove,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index eede6be..7ce1d9e 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -14,6 +14,8 @@
  * This file is licenced under the GPL.
  */
  
+#include <linux/jiffies.h>
+
 #ifdef CONFIG_PPC_PMAC
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
@@ -112,23 +114,13 @@
 
 static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
 {
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	/* root hub was already suspended */
 
-	/* suspend root hub, hoping it keeps power during suspend */
-	if (time_before (jiffies, ohci->next_statechange))
-		msleep (100);
-
-#ifdef	CONFIG_USB_SUSPEND
-	(void) usb_suspend_device (hcd->self.root_hub, message);
-#else
-	usb_lock_device (hcd->self.root_hub);
-	(void) ohci_hub_suspend (hcd);
-	usb_unlock_device (hcd->self.root_hub);
-#endif
-
-	/* let things settle down a bit */
-	msleep (100);
-	
+	/* FIXME these PMAC things get called in the wrong places.  ASIC
+	 * clocks should be turned off AFTER entering D3, and on BEFORE
+	 * trying to enter D0.  Evidently the PCI layer doesn't currently
+	 * provide the right sort of platform hooks for this ...
+	 */
 #ifdef CONFIG_PPC_PMAC
 	if (_machine == _MACH_Pmac) {
 	   	struct device_node	*of_node;
@@ -145,9 +137,6 @@
 
 static int ohci_pci_resume (struct usb_hcd *hcd)
 {
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	int			retval = 0;
-
 #ifdef CONFIG_PPC_PMAC
 	if (_machine == _MACH_Pmac) {
 		struct device_node *of_node;
@@ -159,19 +148,8 @@
 	}
 #endif /* CONFIG_PPC_PMAC */
 
-	/* resume root hub */
-	if (time_before (jiffies, ohci->next_statechange))
-		msleep (100);
-#ifdef	CONFIG_USB_SUSPEND
-	/* get extra cleanup even if remote wakeup isn't in use */
-	retval = usb_resume_device (hcd->self.root_hub);
-#else
-	usb_lock_device (hcd->self.root_hub);
-	retval = ohci_hub_resume (hcd);
-	usb_unlock_device (hcd->self.root_hub);
-#endif
-
-	return retval;
+	usb_hcd_resume_root_hub(hcd);
+	return 0;
 }
 
 #endif	/* CONFIG_PM */
@@ -218,9 +196,9 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_USB_SUSPEND
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
 	.start_port_reset =	ohci_start_port_reset,
 };
@@ -240,6 +218,7 @@
 static struct pci_driver ohci_pci_driver = {
 	.name =		(char *) hcd_name,
 	.id_table =	pci_ids,
+	.owner =	THIS_MODULE,
 
 	.probe =	usb_hcd_pci_probe,
 	.remove =	usb_hcd_pci_remove,
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 2515333..4832e57 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -163,9 +163,9 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_USB_SUSPEND
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
 	.start_port_reset =	ohci_start_port_reset,
 };
@@ -193,10 +193,11 @@
 
 static struct device_driver ohci_hcd_ppc_soc_driver = {
 	.name		= "ppc-soc-ohci",
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_ppc_soc_drv_probe,
 	.remove		= ohci_hcd_ppc_soc_drv_remove,
-#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef	CONFIG_PM
 	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/
 	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/
 #endif
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 2fdb262..f4a4aed 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -20,6 +20,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/signal.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
@@ -278,10 +279,11 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-#ifdef  CONFIG_USB_SUSPEND
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+#ifdef  CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -309,7 +311,7 @@
 	return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state, u32 level)
+static int ohci_hcd_pxa27x_drv_suspend(struct device *dev, pm_message_t state)
 {
 //	struct platform_device *pdev = to_platform_device(dev);
 //	struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -318,7 +320,7 @@
 	return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_resume(struct device *dev, u32 level)
+static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
 {
 //	struct platform_device *pdev = to_platform_device(dev);
 //	struct usb_hcd *hcd = dev_get_drvdata(dev);
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index da7d547..fab420a 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -448,11 +448,11 @@
 	 */
 	.hub_status_data =	ohci_s3c2410_hub_status_data,
 	.hub_control =		ohci_s3c2410_hub_control,
-
-#if defined(CONFIG_USB_SUSPEND) && 0
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /* device driver */
@@ -474,6 +474,7 @@
 
 static struct device_driver ohci_hcd_s3c2410_driver = {
 	.name		= "s3c2410-ohci",
+	.owner		= THIS_MODULE,
 	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_s3c2410_drv_probe,
 	.remove		= ohci_hcd_s3c2410_drv_remove,
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 814d2be..fb3221e 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -235,10 +235,11 @@
 	 */
 	.hub_status_data =	ohci_hub_status_data,
 	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_USB_SUSPEND
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 8a9b9d9..caacf14 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -389,7 +389,6 @@
 	unsigned long		next_statechange;	/* suspend/resume */
 	u32			fminterval;		/* saved register */
 
-	struct work_struct	rh_resume;
 	struct notifier_block	reboot_notifier;
 
 	unsigned long		flags;		/* for HC bugs */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
new file mode 100644
index 0000000..b7fd3f6
--- /dev/null
+++ b/drivers/usb/host/pci-quirks.c
@@ -0,0 +1,296 @@
+/*
+ * This file contains code to reset and initialize USB host controllers.
+ * Some of it includes work-arounds for PCI hardware and BIOS quirks.
+ * It may need to run early during booting -- before USB would normally
+ * initialize -- to ensure that Linux doesn't use any legacy modes.
+ *
+ *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
+ *  (and others)
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+
+#define UHCI_USBLEGSUP		0xc0		/* legacy support */
+#define UHCI_USBCMD		0		/* command register */
+#define UHCI_USBINTR		4		/* interrupt register */
+#define UHCI_USBLEGSUP_RWC	0x8f00		/* the R/WC bits */
+#define UHCI_USBLEGSUP_RO	0x5040		/* R/O and reserved bits */
+#define UHCI_USBCMD_RUN		0x0001		/* RUN/STOP bit */
+#define UHCI_USBCMD_HCRESET	0x0002		/* Host Controller reset */
+#define UHCI_USBCMD_EGSM	0x0008		/* Global Suspend Mode */
+#define UHCI_USBCMD_CONFIGURE	0x0040		/* Config Flag */
+#define UHCI_USBINTR_RESUME	0x0002		/* Resume interrupt enable */
+
+#define OHCI_CONTROL		0x04
+#define OHCI_CMDSTATUS		0x08
+#define OHCI_INTRSTATUS		0x0c
+#define OHCI_INTRENABLE		0x10
+#define OHCI_INTRDISABLE	0x14
+#define OHCI_OCR		(1 << 3)	/* ownership change request */
+#define OHCI_CTRL_RWC		(1 << 9)	/* remote wakeup connected */
+#define OHCI_CTRL_IR		(1 << 8)	/* interrupt routing */
+#define OHCI_INTR_OC		(1 << 30)	/* ownership change */
+
+#define EHCI_HCC_PARAMS		0x08		/* extended capabilities */
+#define EHCI_USBCMD		0		/* command register */
+#define EHCI_USBCMD_RUN		(1 << 0)	/* RUN/STOP bit */
+#define EHCI_USBSTS		4		/* status register */
+#define EHCI_USBSTS_HALTED	(1 << 12)	/* HCHalted bit */
+#define EHCI_USBINTR		8		/* interrupt register */
+#define EHCI_USBLEGSUP		0		/* legacy support register */
+#define EHCI_USBLEGSUP_BIOS	(1 << 16)	/* BIOS semaphore */
+#define EHCI_USBLEGSUP_OS	(1 << 24)	/* OS semaphore */
+#define EHCI_USBLEGCTLSTS	4		/* legacy control/status */
+#define EHCI_USBLEGCTLSTS_SOOE	(1 << 13)	/* SMI on ownership change */
+
+
+/*
+ * Make sure the controller is completely inactive, unable to
+ * generate interrupts or do DMA.
+ */
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base)
+{
+	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
+	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
+	 */
+	pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
+
+	/* Reset the HC - this will force us to get a
+	 * new notification of any already connected
+	 * ports due to the virtual disconnect that it
+	 * implies.
+	 */
+	outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD);
+	mb();
+	udelay(5);
+	if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
+		dev_warn(&pdev->dev, "HCRESET not completed yet!\n");
+
+	/* Just to be safe, disable interrupt requests and
+	 * make sure the controller is stopped.
+	 */
+	outw(0, base + UHCI_USBINTR);
+	outw(0, base + UHCI_USBCMD);
+}
+EXPORT_SYMBOL_GPL(uhci_reset_hc);
+
+/*
+ * Initialize a controller that was newly discovered or has just been
+ * resumed.  In either case we can't be sure of its previous state.
+ *
+ * Returns: 1 if the controller was reset, 0 otherwise.
+ */
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+{
+	u16 legsup;
+	unsigned int cmd, intr;
+
+	/*
+	 * When restarting a suspended controller, we expect all the
+	 * settings to be the same as we left them:
+	 *
+	 *	PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
+	 *	Controller is stopped and configured with EGSM set;
+	 *	No interrupts enabled except possibly Resume Detect.
+	 *
+	 * If any of these conditions are violated we do a complete reset.
+	 */
+	pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
+	if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
+		dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
+				__FUNCTION__, legsup);
+		goto reset_needed;
+	}
+
+	cmd = inw(base + UHCI_USBCMD);
+	if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
+			!(cmd & UHCI_USBCMD_EGSM)) {
+		dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
+				__FUNCTION__, cmd);
+		goto reset_needed;
+	}
+
+	intr = inw(base + UHCI_USBINTR);
+	if (intr & (~UHCI_USBINTR_RESUME)) {
+		dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
+				__FUNCTION__, intr);
+		goto reset_needed;
+	}
+	return 0;
+
+reset_needed:
+	dev_dbg(&pdev->dev, "Performing full reset\n");
+	uhci_reset_hc(pdev, base);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
+
+static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
+{
+	unsigned long base = 0;
+	int i;
+
+	for (i = 0; i < PCI_ROM_RESOURCE; i++)
+		if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
+			base = pci_resource_start(pdev, i);
+			break;
+		}
+
+	if (base)
+		uhci_check_and_reset_hc(pdev, base);
+}
+
+static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+{
+	void __iomem *base;
+	int wait_time;
+	u32 control;
+
+	base = ioremap_nocache(pci_resource_start(pdev, 0),
+				     pci_resource_len(pdev, 0));
+	if (base == NULL) return;
+
+/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
+#ifndef __hppa__
+	control = readl(base + OHCI_CONTROL);
+	if (control & OHCI_CTRL_IR) {
+		wait_time = 500; /* arbitrary; 5 seconds */
+		writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
+		writel(OHCI_OCR, base + OHCI_CMDSTATUS);
+		while (wait_time > 0 &&
+				readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) {
+			wait_time -= 10;
+			msleep(10);
+		}
+		if (wait_time <= 0)
+			printk(KERN_WARNING "%s %s: early BIOS handoff "
+					"failed (BIOS bug ?)\n",
+					pdev->dev.bus_id, "OHCI");
+
+		/* reset controller, preserving RWC */
+		writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
+	}
+#endif
+
+	/*
+	 * disable interrupts
+	 */
+	writel(~(u32)0, base + OHCI_INTRDISABLE);
+	writel(~(u32)0, base + OHCI_INTRSTATUS);
+
+	iounmap(base);
+}
+
+static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+{
+	int wait_time, delta;
+	void __iomem *base, *op_reg_base;
+	u32 hcc_params, val, temp;
+	u8 cap_length;
+
+	base = ioremap_nocache(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0));
+	if (base == NULL) return;
+
+	cap_length = readb(base);
+	op_reg_base = base + cap_length;
+	hcc_params = readl(base + EHCI_HCC_PARAMS);
+	hcc_params = (hcc_params >> 8) & 0xff;
+	if (hcc_params) {
+		pci_read_config_dword(pdev,
+					hcc_params + EHCI_USBLEGSUP,
+					&val);
+		if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
+			/*
+			 * Ok, BIOS is in smm mode, try to hand off...
+			 */
+			pci_read_config_dword(pdev,
+						hcc_params + EHCI_USBLEGCTLSTS,
+						&temp);
+			pci_write_config_dword(pdev,
+						hcc_params + EHCI_USBLEGCTLSTS,
+						temp | EHCI_USBLEGCTLSTS_SOOE);
+			val |= EHCI_USBLEGSUP_OS;
+			pci_write_config_dword(pdev,
+						hcc_params + EHCI_USBLEGSUP,
+						val);
+
+			wait_time = 500;
+			do {
+				msleep(10);
+				wait_time -= 10;
+				pci_read_config_dword(pdev,
+						hcc_params + EHCI_USBLEGSUP,
+						&val);
+			} while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
+			if (!wait_time) {
+				/*
+				 * well, possibly buggy BIOS...
+				 */
+				printk(KERN_WARNING "%s %s: early BIOS handoff "
+						"failed (BIOS bug ?)\n",
+					pdev->dev.bus_id, "EHCI");
+				pci_write_config_dword(pdev,
+						hcc_params + EHCI_USBLEGSUP,
+						EHCI_USBLEGSUP_OS);
+				pci_write_config_dword(pdev,
+						hcc_params + EHCI_USBLEGCTLSTS,
+						0);
+			}
+		}
+	}
+
+	/*
+	 * halt EHCI & disable its interrupts in any case
+	 */
+	val = readl(op_reg_base + EHCI_USBSTS);
+	if ((val & EHCI_USBSTS_HALTED) == 0) {
+		val = readl(op_reg_base + EHCI_USBCMD);
+		val &= ~EHCI_USBCMD_RUN;
+		writel(val, op_reg_base + EHCI_USBCMD);
+
+		wait_time = 2000;
+		delta = 100;
+		do {
+			writel(0x3f, op_reg_base + EHCI_USBSTS);
+			udelay(delta);
+			wait_time -= delta;
+			val = readl(op_reg_base + EHCI_USBSTS);
+			if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
+				break;
+			}
+		} while (wait_time > 0);
+	}
+	writel(0, op_reg_base + EHCI_USBINTR);
+	writel(0x3f, op_reg_base + EHCI_USBSTS);
+
+	iounmap(base);
+
+	return;
+}
+
+
+
+static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
+{
+	if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
+		quirk_usb_handoff_uhci(pdev);
+	else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
+		quirk_usb_handoff_ohci(pdev);
+	else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI)
+		quirk_usb_disable_ehci(pdev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index d42a15d..40169d9 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -818,7 +818,7 @@
 	struct usb_hcd		*hcd,
 	struct usb_host_endpoint *hep,
 	struct urb		*urb,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 ) {
 	struct sl811		*sl811 = hcd_to_sl811(hcd);
 	struct usb_device	*udev = urb->dev;
@@ -1363,7 +1363,7 @@
 #ifdef	CONFIG_PM
 
 static int
-sl811h_hub_suspend(struct usb_hcd *hcd)
+sl811h_bus_suspend(struct usb_hcd *hcd)
 {
 	// SOFs off
 	DBG("%s\n", __FUNCTION__);
@@ -1371,7 +1371,7 @@
 }
 
 static int
-sl811h_hub_resume(struct usb_hcd *hcd)
+sl811h_bus_resume(struct usb_hcd *hcd)
 {
 	// SOFs on
 	DBG("%s\n", __FUNCTION__);
@@ -1380,8 +1380,8 @@
 
 #else
 
-#define	sl811h_hub_suspend	NULL
-#define	sl811h_hub_resume	NULL
+#define	sl811h_bus_suspend	NULL
+#define	sl811h_bus_resume	NULL
 
 #endif
 
@@ -1623,8 +1623,8 @@
 	 */
 	.hub_status_data =	sl811h_hub_status_data,
 	.hub_control =		sl811h_hub_control,
-	.hub_suspend =		sl811h_hub_suspend,
-	.hub_resume =		sl811h_hub_resume,
+	.bus_suspend =		sl811h_bus_suspend,
+	.bus_resume =		sl811h_bus_resume,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1784,17 +1784,14 @@
  */
 
 static int
-sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
+sl811h_suspend(struct device *dev, pm_message_t state)
 {
 	struct usb_hcd	*hcd = dev_get_drvdata(dev);
 	struct sl811	*sl811 = hcd_to_sl811(hcd);
 	int		retval = 0;
 
-	if (phase != SUSPEND_POWER_DOWN)
-		return retval;
-
 	if (state.event == PM_EVENT_FREEZE)
-		retval = sl811h_hub_suspend(hcd);
+		retval = sl811h_bus_suspend(hcd);
 	else if (state.event == PM_EVENT_SUSPEND)
 		port_power(sl811, 0);
 	if (retval == 0)
@@ -1803,14 +1800,11 @@
 }
 
 static int
-sl811h_resume(struct device *dev, u32 phase)
+sl811h_resume(struct device *dev)
 {
 	struct usb_hcd	*hcd = dev_get_drvdata(dev);
 	struct sl811	*sl811 = hcd_to_sl811(hcd);
 
-	if (phase != RESUME_POWER_ON)
-		return 0;
-
 	/* with no "check to see if VBUS is still powered" board hook,
 	 * let's assume it'd only be powered to enable remote wakeup.
 	 */
@@ -1822,7 +1816,7 @@
 	}
 
 	dev->power.power_state = PMSG_ON;
-	return sl811h_hub_resume(hcd);
+	return sl811h_bus_resume(hcd);
 }
 
 #else
@@ -1837,6 +1831,7 @@
 struct device_driver sl811h_driver = {
 	.name =		(char *) hcd_name,
 	.bus =		&platform_bus_type,
+	.owner =	THIS_MODULE,
 
 	.probe =	sl811h_probe,
 	.remove =	__devexit_p(sl811h_remove),
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 4538a98..151154d 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -348,7 +348,6 @@
 
 	if (urbp->urb->status != -EINPROGRESS)
 		out += sprintf(out, "Status=%d ", urbp->urb->status);
-	//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
 	//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
 
 	count = 0;
@@ -446,11 +445,11 @@
 	out += sprintf(out, "Frame List\n");
 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
 		int shown = 0;
-		td = uhci->fl->frame_cpu[i];
+		td = uhci->frame_cpu[i];
 		if (!td)
 			continue;
 
-		if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+		if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
 			show_frame_num();
 			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
 		}
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 0c02489..15e0a51 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -101,37 +101,16 @@
 #include "uhci-q.c"
 #include "uhci-hub.c"
 
+extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+
 /*
- * Make sure the controller is completely inactive, unable to
- * generate interrupts or do DMA.
+ * Finish up a host controller reset and update the recorded state.
  */
-static void reset_hc(struct uhci_hcd *uhci)
+static void finish_reset(struct uhci_hcd *uhci)
 {
 	int port;
 
-	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
-	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
-	 */
-	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
-			USBLEGSUP_RWC);
-
-	/* Reset the HC - this will force us to get a
-	 * new notification of any already connected
-	 * ports due to the virtual disconnect that it
-	 * implies.
-	 */
-	outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
-	mb();
-	udelay(5);
-	if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
-		dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
-
-	/* Just to be safe, disable interrupt requests and
-	 * make sure the controller is stopped.
-	 */
-	outw(0, uhci->io_addr + USBINTR);
-	outw(0, uhci->io_addr + USBCMD);
-
 	/* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
 	 * bits in the port status and control registers.
 	 * We have to clear them by hand.
@@ -153,7 +132,8 @@
  */
 static void hc_died(struct uhci_hcd *uhci)
 {
-	reset_hc(uhci);
+	uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
+	finish_reset(uhci);
 	uhci->hc_inaccessible = 1;
 }
 
@@ -163,44 +143,8 @@
  */
 static void check_and_reset_hc(struct uhci_hcd *uhci)
 {
-	u16 legsup;
-	unsigned int cmd, intr;
-
-	/*
-	 * When restarting a suspended controller, we expect all the
-	 * settings to be the same as we left them:
-	 *
-	 *	PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
-	 *	Controller is stopped and configured with EGSM set;
-	 *	No interrupts enabled except possibly Resume Detect.
-	 *
-	 * If any of these conditions are violated we do a complete reset.
-	 */
-	pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
-	if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) {
-		dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
-				__FUNCTION__, legsup);
-		goto reset_needed;
-	}
-
-	cmd = inw(uhci->io_addr + USBCMD);
-	if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
-		dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
-				__FUNCTION__, cmd);
-		goto reset_needed;
-	}
-
-	intr = inw(uhci->io_addr + USBINTR);
-	if (intr & (~USBINTR_RESUME)) {
-		dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
-				__FUNCTION__, intr);
-		goto reset_needed;
-	}
-	return;
-
-reset_needed:
-	dev_dbg(uhci_dev(uhci), "Performing full reset\n");
-	reset_hc(uhci);
+	if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr))
+		finish_reset(uhci);
 }
 
 /*
@@ -212,13 +156,13 @@
 	outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
 
 	/* Store the frame list base address */
-	outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+	outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
 
 	/* Set the current frame number */
 	outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
 
-	/* Mark controller as running before we enable interrupts */
-	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+	/* Mark controller as not halted before we enable interrupts */
+	uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
 	mb();
 
 	/* Enable PIRQ */
@@ -319,6 +263,7 @@
 
 static void start_rh(struct uhci_hcd *uhci)
 {
+	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
 	uhci->is_stopped = 0;
 	smp_wmb();
 
@@ -437,36 +382,21 @@
 	int i;
 
 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
-		if (uhci->skelqh[i]) {
-			uhci_free_qh(uhci, uhci->skelqh[i]);
-			uhci->skelqh[i] = NULL;
-		}
+		uhci_free_qh(uhci, uhci->skelqh[i]);
 
-	if (uhci->term_td) {
-		uhci_free_td(uhci, uhci->term_td);
-		uhci->term_td = NULL;
-	}
+	uhci_free_td(uhci, uhci->term_td);
 
-	if (uhci->qh_pool) {
-		dma_pool_destroy(uhci->qh_pool);
-		uhci->qh_pool = NULL;
-	}
+	dma_pool_destroy(uhci->qh_pool);
 
-	if (uhci->td_pool) {
-		dma_pool_destroy(uhci->td_pool);
-		uhci->td_pool = NULL;
-	}
+	dma_pool_destroy(uhci->td_pool);
 
-	if (uhci->fl) {
-		dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-				uhci->fl, uhci->fl->dma_handle);
-		uhci->fl = NULL;
-	}
+	kfree(uhci->frame_cpu);
 
-	if (uhci->dentry) {
-		debugfs_remove(uhci->dentry);
-		uhci->dentry = NULL;
-	}
+	dma_free_coherent(uhci_dev(uhci),
+			UHCI_NUMFRAMES * sizeof(*uhci->frame),
+			uhci->frame, uhci->frame_dma_handle);
+
+	debugfs_remove(uhci->dentry);
 }
 
 static int uhci_reset(struct usb_hcd *hcd)
@@ -545,7 +475,6 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	int retval = -EBUSY;
 	int i;
-	dma_addr_t dma_handle;
 	struct dentry *dentry;
 
 	hcd->uses_new_polling = 1;
@@ -579,17 +508,23 @@
 
 	init_waitqueue_head(&uhci->waitqh);
 
-	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-			&dma_handle, 0);
-	if (!uhci->fl) {
+	uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+			UHCI_NUMFRAMES * sizeof(*uhci->frame),
+			&uhci->frame_dma_handle, 0);
+	if (!uhci->frame) {
 		dev_err(uhci_dev(uhci), "unable to allocate "
 				"consistent memory for frame list\n");
-		goto err_alloc_fl;
+		goto err_alloc_frame;
 	}
+	memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
 
-	memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
-
-	uhci->fl->dma_handle = dma_handle;
+	uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
+			GFP_KERNEL);
+	if (!uhci->frame_cpu) {
+		dev_err(uhci_dev(uhci), "unable to allocate "
+				"memory for frame pointers\n");
+		goto err_alloc_frame_cpu;
+	}
 
 	uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
 			sizeof(struct uhci_td), 16, 0);
@@ -672,7 +607,7 @@
 			irq = 7;
 
 		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] = UHCI_PTR_QH |
+		uhci->frame[i] = UHCI_PTR_QH |
 				cpu_to_le32(uhci->skelqh[irq]->dma_handle);
 	}
 
@@ -690,31 +625,29 @@
  * error exits:
  */
 err_alloc_skelqh:
-	for (i = 0; i < UHCI_NUM_SKELQH; i++)
-		if (uhci->skelqh[i]) {
+	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+		if (uhci->skelqh[i])
 			uhci_free_qh(uhci, uhci->skelqh[i]);
-			uhci->skelqh[i] = NULL;
-		}
+	}
 
 	uhci_free_td(uhci, uhci->term_td);
-	uhci->term_td = NULL;
 
 err_alloc_term_td:
 	dma_pool_destroy(uhci->qh_pool);
-	uhci->qh_pool = NULL;
 
 err_create_qh_pool:
 	dma_pool_destroy(uhci->td_pool);
-	uhci->td_pool = NULL;
 
 err_create_td_pool:
-	dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-			uhci->fl, uhci->fl->dma_handle);
-	uhci->fl = NULL;
+	kfree(uhci->frame_cpu);
 
-err_alloc_fl:
+err_alloc_frame_cpu:
+	dma_free_coherent(uhci_dev(uhci),
+			UHCI_NUMFRAMES * sizeof(*uhci->frame),
+			uhci->frame, uhci->frame_dma_handle);
+
+err_alloc_frame:
 	debugfs_remove(uhci->dentry);
-	uhci->dentry = NULL;
 
 err_create_debug_entry:
 	return retval;
@@ -726,7 +659,7 @@
 
 	spin_lock_irq(&uhci->lock);
 	if (!uhci->hc_inaccessible)
-		reset_hc(uhci);
+		hc_died(uhci);
 	uhci_scan_schedule(uhci, NULL);
 	spin_unlock_irq(&uhci->lock);
 
@@ -774,14 +707,8 @@
 	if (uhci->hc_inaccessible)	/* Dead or already suspended */
 		goto done;
 
-#ifndef CONFIG_USB_SUSPEND
-	/* Otherwise this would never happen */
-	suspend_rh(uhci, UHCI_RH_SUSPENDED);
-#endif
-
 	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
 		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
-		hcd->state = HC_STATE_RUNNING;
 		rc = -EBUSY;
 		goto done;
 	};
@@ -820,10 +747,6 @@
 	check_and_reset_hc(uhci);
 	configure_hc(uhci);
 
-#ifndef CONFIG_USB_SUSPEND
-	/* Otherwise this would never happen */
-	wakeup_rh(uhci);
-#endif
 	if (uhci->rh_state == UHCI_RH_RESET)
 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
 
@@ -881,8 +804,8 @@
 #ifdef CONFIG_PM
 	.suspend =		uhci_suspend,
 	.resume =		uhci_resume,
-	.hub_suspend =		uhci_rh_suspend,
-	.hub_resume =		uhci_rh_resume,
+	.bus_suspend =		uhci_rh_suspend,
+	.bus_resume =		uhci_rh_resume,
 #endif
 	.stop =			uhci_stop,
 
@@ -908,6 +831,7 @@
 static struct pci_driver uhci_pci_driver = {
 	.name =		(char *)hcd_name,
 	.id_table =	uhci_pci_ids,
+	.owner =	THIS_MODULE,
 
 	.probe =	usb_hcd_pci_probe,
 	.remove =	usb_hcd_pci_remove,
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 282f40b..e576db5 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -7,6 +7,7 @@
 #define usb_packetid(pipe)	(usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
 #define PIPE_DEVEP_MASK		0x0007ff00
 
+
 /*
  * Universal Host Controller Interface data structures and defines
  */
@@ -82,15 +83,10 @@
 #define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
 #define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
 
-struct uhci_frame_list {
-	__le32 frame[UHCI_NUMFRAMES];
 
-	void *frame_cpu[UHCI_NUMFRAMES];
-
-	dma_addr_t dma_handle;
-};
-
-struct urb_priv;
+/*
+ *	Queue Headers
+ */
 
 /*
  * One role of a QH is to hold a queue of TDs for some endpoint.  Each QH is
@@ -116,13 +112,13 @@
 
 	struct urb_priv *urbp;
 
-	struct list_head list;		/* P: uhci->frame_list_lock */
-	struct list_head remove_list;	/* P: uhci->remove_list_lock */
+	struct list_head list;
+	struct list_head remove_list;
 } __attribute__((aligned(16)));
 
 /*
  * We need a special accessor for the element pointer because it is
- * subject to asynchronous updates by the controller
+ * subject to asynchronous updates by the controller.
  */
 static __le32 inline qh_element(struct uhci_qh *qh) {
 	__le32 element = qh->element;
@@ -131,6 +127,11 @@
 	return element;
 }
 
+
+/*
+ *	Transfer Descriptors
+ */
+
 /*
  * for TD <status>:
  */
@@ -183,17 +184,10 @@
  *
  * That's silly, the hardware doesn't care. The hardware only cares that
  * the hardware words are 16-byte aligned, and we can have any amount of
- * sw space after the TD entry as far as I can tell.
- *
- * But let's just go with the documentation, at least for 32-bit machines.
- * On 64-bit machines we probably want to take advantage of the fact that
- * hw doesn't really care about the size of the sw-only area.
- *
- * Alas, not anymore, we have more than 4 words for software, woops.
- * Everything still works tho, surprise! -jerdfelt
+ * sw space after the TD entry.
  *
  * td->link points to either another TD (not necessarily for the same urb or
- * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs)
+ * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs).
  */
 struct uhci_td {
 	/* Hardware fields */
@@ -205,18 +199,16 @@
 	/* Software fields */
 	dma_addr_t dma_handle;
 
-	struct urb *urb;
-
-	struct list_head list;		/* P: urb->lock */
-	struct list_head remove_list;	/* P: uhci->td_remove_list_lock */
+	struct list_head list;
+	struct list_head remove_list;
 
 	int frame;			/* for iso: what frame? */
-	struct list_head fl_list;	/* P: uhci->frame_list_lock */
+	struct list_head fl_list;
 } __attribute__((aligned(16)));
 
 /*
  * We need a special accessor for the control/status word because it is
- * subject to asynchronous updates by the controller
+ * subject to asynchronous updates by the controller.
  */
 static u32 inline td_status(struct uhci_td *td) {
 	__le32 status = td->status;
@@ -227,6 +219,10 @@
 
 
 /*
+ *	Skeleton Queue Headers
+ */
+
+/*
  * The UHCI driver places Interrupt, Control and Bulk into QH's both
  * to group together TD's for one transfer, and also to faciliate queuing
  * of URB's. To make it easy to insert entries into the schedule, we have
@@ -256,15 +252,15 @@
  *
  * The terminating QH is used for 2 reasons:
  * - To place a terminating TD which is used to workaround a PIIX bug
- *   (see Intel errata for explanation)
+ *   (see Intel errata for explanation), and
  * - To loop back to the full-speed control queue for full-speed bandwidth
- *   reclamation
+ *   reclamation.
  *
  * Isochronous transfers are stored before the start of the skeleton
  * schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. Since we don't
- * need to use them either, we follow the spec diagrams in hope that it'll
- * be more compatible with future UHCI implementations.
+ * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * says that queues never advance on an error completion status, which
+ * makes them totally unsuitable for Isochronous transfers.
  */
 
 #define UHCI_NUM_SKELQH		12
@@ -314,8 +310,13 @@
 	return 0;				/* int128 for 128-255 ms (Max.) */
 }
 
+
 /*
- * States for the root hub.
+ *	The UHCI controller and root hub
+ */
+
+/*
+ * States for the root hub:
  *
  * To prevent "bouncing" in the presence of electrical noise,
  * when there are no devices attached we delay for 1 second in the
@@ -326,7 +327,7 @@
  */
 enum uhci_rh_state {
 	/* In the following states the HC must be halted.
-	 * These two must come first */
+	 * These two must come first. */
 	UHCI_RH_RESET,
 	UHCI_RH_SUSPENDED,
 
@@ -338,13 +339,13 @@
 	UHCI_RH_SUSPENDING,
 
 	/* In the following states it's an error if the HC is halted.
-	 * These two must come last */
+	 * These two must come last. */
 	UHCI_RH_RUNNING,		/* The normal state */
 	UHCI_RH_RUNNING_NODEVS,		/* Running with no devices attached */
 };
 
 /*
- * This describes the full uhci information.
+ * The full UHCI controller information:
  */
 struct uhci_hcd {
 
@@ -361,7 +362,11 @@
 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
 
 	spinlock_t lock;
-	struct uhci_frame_list *fl;		/* P: uhci->lock */
+
+	dma_addr_t frame_dma_handle;		/* Hardware frame list */
+	__le32 *frame;
+	void **frame_cpu;			/* CPU's frame list */
+
 	int fsbr;				/* Full-speed bandwidth reclamation */
 	unsigned long fsbrtimeout;		/* FSBR delay */
 
@@ -385,22 +390,22 @@
 	unsigned long ports_timeout;		/* Time to stop signalling */
 
 	/* Main list of URB's currently controlled by this HC */
-	struct list_head urb_list;		/* P: uhci->lock */
+	struct list_head urb_list;
 
 	/* List of QH's that are done, but waiting to be unlinked (race) */
-	struct list_head qh_remove_list;	/* P: uhci->lock */
+	struct list_head qh_remove_list;
 	unsigned int qh_remove_age;		/* Age in frames */
 
 	/* List of TD's that are done, but waiting to be freed (race) */
-	struct list_head td_remove_list;	/* P: uhci->lock */
+	struct list_head td_remove_list;
 	unsigned int td_remove_age;		/* Age in frames */
 
 	/* List of asynchronously unlinked URB's */
-	struct list_head urb_remove_list;	/* P: uhci->lock */
+	struct list_head urb_remove_list;
 	unsigned int urb_remove_age;		/* Age in frames */
 
 	/* List of URB's awaiting completion callback */
-	struct list_head complete_list;		/* P: uhci->lock */
+	struct list_head complete_list;
 
 	int rh_numports;			/* Number of root-hub ports */
 
@@ -419,13 +424,17 @@
 
 #define uhci_dev(u)	(uhci_to_hcd(u)->self.controller)
 
+
+/*
+ *	Private per-URB data
+ */
 struct urb_priv {
 	struct list_head urb_list;
 
 	struct urb *urb;
 
 	struct uhci_qh *qh;		/* QH for this URB */
-	struct list_head td_list;	/* P: urb->lock */
+	struct list_head td_list;
 
 	unsigned fsbr : 1;		/* URB turned on FSBR */
 	unsigned fsbr_timeout : 1;	/* URB timed out on FSBR */
@@ -434,12 +443,12 @@
 						/*  a control transfer, retrigger */
 						/*  the status phase */
 
-	unsigned long inserttime;	/* In jiffies */
 	unsigned long fsbrtime;		/* In jiffies */
 
-	struct list_head queue_list;	/* P: uhci->frame_list_lock */
+	struct list_head queue_list;
 };
 
+
 /*
  * Locking in uhci.c
  *
@@ -459,6 +468,5 @@
 
 #define PCI_VENDOR_ID_GENESYS		0x17a0
 #define PCI_DEVICE_ID_GL880S_UHCI	0x8083
-#define PCI_DEVICE_ID_GL880S_EHCI	0x8084
 
 #endif
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index ea0d168..7e46887 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -89,10 +89,10 @@
 	td->frame = framenum;
 
 	/* Is there a TD already mapped there? */
-	if (uhci->fl->frame_cpu[framenum]) {
+	if (uhci->frame_cpu[framenum]) {
 		struct uhci_td *ftd, *ltd;
 
-		ftd = uhci->fl->frame_cpu[framenum];
+		ftd = uhci->frame_cpu[framenum];
 		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
 
 		list_add_tail(&td->fl_list, &ftd->fl_list);
@@ -101,29 +101,32 @@
 		wmb();
 		ltd->link = cpu_to_le32(td->dma_handle);
 	} else {
-		td->link = uhci->fl->frame[framenum];
+		td->link = uhci->frame[framenum];
 		wmb();
-		uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
-		uhci->fl->frame_cpu[framenum] = td;
+		uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+		uhci->frame_cpu[framenum] = td;
 	}
 }
 
-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci,
+		struct uhci_td *td)
 {
 	/* If it's not inserted, don't remove it */
-	if (td->frame == -1 && list_empty(&td->fl_list))
+	if (td->frame == -1) {
+		WARN_ON(!list_empty(&td->fl_list));
 		return;
+	}
 
-	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+	if (uhci->frame_cpu[td->frame] == td) {
 		if (list_empty(&td->fl_list)) {
-			uhci->fl->frame[td->frame] = td->link;
-			uhci->fl->frame_cpu[td->frame] = NULL;
+			uhci->frame[td->frame] = td->link;
+			uhci->frame_cpu[td->frame] = NULL;
 		} else {
 			struct uhci_td *ntd;
 
 			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-			uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
-			uhci->fl->frame_cpu[td->frame] = ntd;
+			uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+			uhci->frame_cpu[td->frame] = ntd;
 		}
 	} else {
 		struct uhci_td *ptd;
@@ -132,13 +135,20 @@
 		ptd->link = td->link;
 	}
 
-	wmb();
-	td->link = UHCI_PTR_TERM;
-
 	list_del_init(&td->fl_list);
 	td->frame = -1;
 }
 
+static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+	struct uhci_td *td;
+
+	list_for_each_entry(td, &urbp->td_list, list)
+		uhci_remove_td_frame_list(uhci, td);
+	wmb();
+}
+
 /*
  * Inserts a td list into qh.
  */
@@ -443,7 +453,6 @@
 
 	memset((void *)urbp, 0, sizeof(*urbp));
 
-	urbp->inserttime = jiffies;
 	urbp->fsbrtime = jiffies;
 	urbp->urb = urb;
 	
@@ -462,8 +471,6 @@
 {
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
-	td->urb = urb;
-
 	list_add_tail(&td->list, &urbp->td_list);
 }
 
@@ -473,8 +480,6 @@
 		return;
 
 	list_del_init(&td->list);
-
-	td->urb = NULL;
 }
 
 static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
@@ -503,7 +508,6 @@
 
 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
 		uhci_remove_td_from_urb(td);
-		uhci_remove_td(uhci, td);
 		list_add(&td->remove_list, &uhci->td_remove_list);
 	}
 
@@ -1073,6 +1077,7 @@
 	struct uhci_td *td;
 	int i, ret, frame;
 	int status, destination;
+	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1081,11 +1086,7 @@
 	if (ret)
 		return ret;
 
-	frame = urb->start_frame;
-	for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
-		if (!urb->iso_frame_desc[i].length)
-			continue;
-
+	for (i = 0; i < urb->number_of_packets; i++) {
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			return -ENOMEM;
@@ -1096,8 +1097,12 @@
 
 		if (i + 1 >= urb->number_of_packets)
 			td->status |= cpu_to_le32(TD_CTRL_IOC);
+	}
 
+	frame = urb->start_frame;
+	list_for_each_entry(td, &urbp->td_list, list) {
 		uhci_insert_td_frame_list(uhci, td, frame);
+		frame += urb->interval;
 	}
 
 	return -EINPROGRESS;
@@ -1110,7 +1115,7 @@
 	int status;
 	int i, ret = 0;
 
-	urb->actual_length = 0;
+	urb->actual_length = urb->error_count = 0;
 
 	i = 0;
 	list_for_each_entry(td, &urbp->td_list, list) {
@@ -1134,6 +1139,7 @@
 
 		i++;
 	}
+	unlink_isochronous_tds(uhci, urb);
 
 	return ret;
 }
@@ -1164,7 +1170,7 @@
 
 static int uhci_urb_enqueue(struct usb_hcd *hcd,
 		struct usb_host_endpoint *ep,
-		struct urb *urb, unsigned mem_flags)
+		struct urb *urb, gfp_t mem_flags)
 {
 	int ret;
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -1366,6 +1372,8 @@
 		goto done;
 	list_del_init(&urbp->urb_list);
 
+	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+		unlink_isochronous_tds(uhci, urb);
 	uhci_unlink_generic(uhci, urb);
 
 	uhci_get_current_frame_number(uhci);
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index a330a4b..1d973bc 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -425,9 +425,8 @@
 static struct usb_driver mdc800_usb_driver;
 static struct file_operations mdc800_device_ops;
 static struct usb_class_driver mdc800_class = {
-	.name =		"usb/mdc800%d",
+	.name =		"mdc800%d",
 	.fops =		&mdc800_device_ops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
 	.minor_base =	MDC800_DEVICE_MINOR_BASE,
 };
 
@@ -976,13 +975,13 @@
 	Init and Cleanup this driver (Main Functions)
 *************************************************************************/
 
-#define try(A)           if (!(A)) goto cleanup_on_fail;
-
 static int __init usb_mdc800_init (void)
 {
 	int retval = -ENODEV;
 	/* Allocate Memory */
-	try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
+	mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL);
+	if (!mdc800)
+		goto cleanup_on_fail;
 
 	memset(mdc800, 0, sizeof(struct mdc800_data));
 	mdc800->dev = NULL;
@@ -998,13 +997,25 @@
 	mdc800->downloaded = 0;
 	mdc800->written = 0;
 
-	try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
-	try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
-	try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
+	mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
+	if (!mdc800->irq_urb_buffer)
+		goto cleanup_on_fail;
+	mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
+	if (!mdc800->write_urb_buffer)
+		goto cleanup_on_fail;
+	mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
+	if (!mdc800->download_urb_buffer)
+		goto cleanup_on_fail;
 
-	try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
-	try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
-	try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
+	mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL);
+	if (!mdc800->irq_urb)
+		goto cleanup_on_fail;
+	mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL);
+	if (!mdc800->download_urb)
+		goto cleanup_on_fail;
+	mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL);
+	if (!mdc800->write_urb)
+		goto cleanup_on_fail;
 
 	/* Register the driver */
 	retval = usb_register(&mdc800_usb_driver);
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index c84e148..c89d076 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -773,11 +773,10 @@
 	}
 	
 	
-	new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
+	new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL);
 	if (!new_desc)
 		goto out;
 
-	memset(new_desc, 0, sizeof(*new_desc));
 	new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!new_desc->urb)
 		goto out_kfree;
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 74f8760..a32558b 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -53,7 +53,7 @@
 	char name[128];
 	char phys[64];
 	struct usb_device *usbdev;
-	struct input_dev dev;
+	struct input_dev *input;
 	struct urb *irq;
 
 	signed char *data;
@@ -64,7 +64,7 @@
 {
 	struct usb_acecad *acecad = urb->context;
 	unsigned char *data = acecad->data;
-	struct input_dev *dev = &acecad->dev;
+	struct input_dev *dev = acecad->input;
 	int prox, status;
 
 	switch (urb->status) {
@@ -135,8 +135,8 @@
 	struct usb_host_interface *interface = intf->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_acecad *acecad;
+	struct input_dev *input_dev;
 	int pipe, maxp;
-	char path[64];
 
 	if (interface->desc.bNumEndpoints != 1)
 		return -ENODEV;
@@ -153,8 +153,9 @@
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
 	acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
-	if (!acecad)
-		return -ENOMEM;
+	input_dev = input_allocate_device();
+	if (!acecad || !input_dev)
+		goto fail1;
 
 	acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
 	if (!acecad->data)
@@ -164,6 +165,9 @@
 	if (!acecad->irq)
 		goto fail2;
 
+	acecad->usbdev = dev;
+	acecad->input = input_dev;
+
 	if (dev->manufacturer)
 		strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
 
@@ -173,48 +177,48 @@
 		strlcat(acecad->name, dev->product, sizeof(acecad->name));
 	}
 
-	usb_make_path(dev, path, sizeof(path));
-	snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path);
+	usb_make_path(dev, acecad->phys, sizeof(acecad->phys));
+	strlcat(acecad->phys, "/input0", sizeof(acecad->phys));
 
-	acecad->usbdev = dev;
+	input_dev->name = acecad->name;
+	input_dev->phys = acecad->phys;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = acecad;
 
-	acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-	acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-	acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
+	input_dev->open = usb_acecad_open;
+	input_dev->close = usb_acecad_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+	input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
 
 	switch (id->driver_info) {
 		case 0:
-			acecad->dev.absmax[ABS_X] = 5000;
-			acecad->dev.absmax[ABS_Y] = 3750;
-			acecad->dev.absmax[ABS_PRESSURE] = 512;
+			input_dev->absmax[ABS_X] = 5000;
+			input_dev->absmax[ABS_Y] = 3750;
+			input_dev->absmax[ABS_PRESSURE] = 512;
 			if (!strlen(acecad->name))
 				snprintf(acecad->name, sizeof(acecad->name),
 					"USB Acecad Flair Tablet %04x:%04x",
-					dev->descriptor.idVendor, dev->descriptor.idProduct);
+					le16_to_cpu(dev->descriptor.idVendor),
+					le16_to_cpu(dev->descriptor.idProduct));
 			break;
 		case 1:
-			acecad->dev.absmax[ABS_X] = 3000;
-			acecad->dev.absmax[ABS_Y] = 2250;
-			acecad->dev.absmax[ABS_PRESSURE] = 1024;
+			input_dev->absmax[ABS_X] = 3000;
+			input_dev->absmax[ABS_Y] = 2250;
+			input_dev->absmax[ABS_PRESSURE] = 1024;
 			if (!strlen(acecad->name))
 				snprintf(acecad->name, sizeof(acecad->name),
 					"USB Acecad 302 Tablet %04x:%04x",
-					dev->descriptor.idVendor, dev->descriptor.idProduct);
+					le16_to_cpu(dev->descriptor.idVendor),
+					le16_to_cpu(dev->descriptor.idProduct));
 			break;
 	}
 
-	acecad->dev.absfuzz[ABS_X] = 4;
-	acecad->dev.absfuzz[ABS_Y] = 4;
-
-	acecad->dev.private = acecad;
-	acecad->dev.open = usb_acecad_open;
-	acecad->dev.close = usb_acecad_close;
-
-	acecad->dev.name = acecad->name;
-	acecad->dev.phys = acecad->phys;
-	usb_to_input_id(dev, &acecad->dev.id);
-	acecad->dev.dev = &intf->dev;
+	input_dev->absfuzz[ABS_X] = 4;
+	input_dev->absfuzz[ABS_Y] = 4;
 
 	usb_fill_int_urb(acecad->irq, dev, pipe,
 			acecad->data, maxp > 8 ? 8 : maxp,
@@ -222,17 +226,15 @@
 	acecad->irq->transfer_dma = acecad->data_dma;
 	acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(&acecad->dev);
-
-	printk(KERN_INFO "input: %s with packet size %d on %s\n",
-		acecad->name, maxp, path);
+	input_register_device(acecad->input);
 
 	usb_set_intfdata(intf, acecad);
 
 	return 0;
 
  fail2:	usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
- fail1:	kfree(acecad);
+ fail1: input_free_device(input_dev);
+	kfree(acecad);
 	return -ENOMEM;
 }
 
@@ -243,7 +245,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (acecad) {
 		usb_kill_urb(acecad->irq);
-		input_unregister_device(&acecad->dev);
+		input_unregister_device(acecad->input);
 		usb_free_urb(acecad->irq);
 		usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma);
 		kfree(acecad);
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index cd0cbfe..1c3b472 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -317,7 +317,7 @@
 };
 
 struct aiptek {
-	struct input_dev inputdev;		/* input device struct           */
+	struct input_dev *inputdev;		/* input device struct           */
 	struct usb_device *usbdev;		/* usb device struct             */
 	struct urb *urb;			/* urb for incoming reports      */
 	dma_addr_t data_dma;			/* our dma stuffage              */
@@ -402,7 +402,7 @@
 {
 	struct aiptek *aiptek = urb->context;
 	unsigned char *data = aiptek->data;
-	struct input_dev *inputdev = &aiptek->inputdev;
+	struct input_dev *inputdev = aiptek->inputdev;
 	int jitterable = 0;
 	int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck;
 
@@ -955,20 +955,20 @@
 	/* Query getXextension */
 	if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0)
 		return ret;
-	aiptek->inputdev.absmin[ABS_X] = 0;
-	aiptek->inputdev.absmax[ABS_X] = ret - 1;
+	aiptek->inputdev->absmin[ABS_X] = 0;
+	aiptek->inputdev->absmax[ABS_X] = ret - 1;
 
 	/* Query getYextension */
 	if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0)
 		return ret;
-	aiptek->inputdev.absmin[ABS_Y] = 0;
-	aiptek->inputdev.absmax[ABS_Y] = ret - 1;
+	aiptek->inputdev->absmin[ABS_Y] = 0;
+	aiptek->inputdev->absmax[ABS_Y] = ret - 1;
 
 	/* Query getPressureLevels */
 	if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0)
 		return ret;
-	aiptek->inputdev.absmin[ABS_PRESSURE] = 0;
-	aiptek->inputdev.absmax[ABS_PRESSURE] = ret - 1;
+	aiptek->inputdev->absmin[ABS_PRESSURE] = 0;
+	aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1;
 
 	/* Depending on whether we are in absolute or relative mode, we will
 	 * do a switchToTablet(absolute) or switchToMouse(relative) command.
@@ -1025,8 +1025,8 @@
 		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%dx%d\n",
-			aiptek->inputdev.absmax[ABS_X] + 1,
-			aiptek->inputdev.absmax[ABS_Y] + 1);
+			aiptek->inputdev->absmax[ABS_X] + 1,
+			aiptek->inputdev->absmax[ABS_Y] + 1);
 }
 
 /* These structs define the sysfs files, param #1 is the name of the
@@ -1048,7 +1048,7 @@
 		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "0x%04x\n",
-			aiptek->inputdev.id.product);
+			aiptek->inputdev->id.product);
 }
 
 static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
@@ -1063,7 +1063,7 @@
 	if (aiptek == NULL)
 		return 0;
 
-	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev.id.vendor);
+	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
 }
 
 static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
@@ -1977,7 +1977,6 @@
 	struct input_dev *inputdev;
 	struct input_handle *inputhandle;
 	struct list_head *node, *next;
-	char path[64 + 1];
 	int i;
 	int speeds[] = { 0,
 		AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1996,24 +1995,26 @@
 	 */
 	speeds[0] = programmableDelay;
 
-	if ((aiptek = kmalloc(sizeof(struct aiptek), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-	memset(aiptek, 0, sizeof(struct aiptek));
+	aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
+	inputdev = input_allocate_device();
+	if (!aiptek || !inputdev)
+		goto fail1;
 
 	aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
 					SLAB_ATOMIC, &aiptek->data_dma);
-	if (aiptek->data == NULL) {
-		kfree(aiptek);
-		return -ENOMEM;
-	}
+	if (!aiptek->data)
+		goto fail1;
 
 	aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (aiptek->urb == NULL) {
-		usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
-				aiptek->data_dma);
-		kfree(aiptek);
-		return -ENOMEM;
-	}
+	if (!aiptek->urb)
+		goto fail2;
+
+	aiptek->inputdev = inputdev;
+	aiptek->usbdev = usbdev;
+	aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
+	aiptek->inDelay = 0;
+	aiptek->endDelay = 0;
+	aiptek->previousJitterable = 0;
 
 	/* Set up the curSettings struct. Said struct contains the current
 	 * programmable parameters. The newSetting struct contains changes
@@ -2036,31 +2037,48 @@
 
 	/* Both structs should have equivalent settings
 	 */
-	memcpy(&aiptek->newSetting, &aiptek->curSetting,
-	       sizeof(struct aiptek_settings));
+	aiptek->newSetting = aiptek->curSetting;
+
+	/* Determine the usb devices' physical path.
+	 * Asketh not why we always pretend we're using "../input0",
+	 * but I suspect this will have to be refactored one
+	 * day if a single USB device can be a keyboard & a mouse
+	 * & a tablet, and the inputX number actually will tell
+	 * us something...
+	 */
+	usb_make_path(usbdev, aiptek->features.usbPath,
+			sizeof(aiptek->features.usbPath));
+	strlcat(aiptek->features.usbPath, "/input0",
+		sizeof(aiptek->features.usbPath));
+
+	/* Set up client data, pointers to open and close routines
+	 * for the input device.
+	 */
+	inputdev->name = "Aiptek";
+	inputdev->phys = aiptek->features.usbPath;
+	usb_to_input_id(usbdev, &inputdev->id);
+	inputdev->cdev.dev = &intf->dev;
+	inputdev->private = aiptek;
+	inputdev->open = aiptek_open;
+	inputdev->close = aiptek_close;
 
 	/* Now program the capacities of the tablet, in terms of being
 	 * an input device.
 	 */
-	aiptek->inputdev.evbit[0] |= BIT(EV_KEY)
+	inputdev->evbit[0] |= BIT(EV_KEY)
 	    | BIT(EV_ABS)
 	    | BIT(EV_REL)
 	    | BIT(EV_MSC);
 
-	aiptek->inputdev.absbit[0] |=
-	    (BIT(ABS_X) |
-	     BIT(ABS_Y) |
-	     BIT(ABS_PRESSURE) |
-	     BIT(ABS_TILT_X) |
-	     BIT(ABS_TILT_Y) | BIT(ABS_WHEEL) | BIT(ABS_MISC));
+	inputdev->absbit[0] |= BIT(ABS_MISC);
 
-	aiptek->inputdev.relbit[0] |=
+	inputdev->relbit[0] |=
 	    (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
 
-	aiptek->inputdev.keybit[LONG(BTN_LEFT)] |=
+	inputdev->keybit[LONG(BTN_LEFT)] |=
 	    (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
 
-	aiptek->inputdev.keybit[LONG(BTN_DIGI)] |=
+	inputdev->keybit[LONG(BTN_DIGI)] |=
 	    (BIT(BTN_TOOL_PEN) |
 	     BIT(BTN_TOOL_RUBBER) |
 	     BIT(BTN_TOOL_PENCIL) |
@@ -2070,70 +2088,26 @@
 	     BIT(BTN_TOOL_LENS) |
 	     BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
 
-	aiptek->inputdev.mscbit[0] = BIT(MSC_SERIAL);
+	inputdev->mscbit[0] = BIT(MSC_SERIAL);
 
 	/* Programming the tablet macro keys needs to be done with a for loop
 	 * as the keycodes are discontiguous.
 	 */
 	for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
-		set_bit(macroKeyEvents[i], aiptek->inputdev.keybit);
+		set_bit(macroKeyEvents[i], inputdev->keybit);
 
-	/* Set up client data, pointers to open and close routines
-	 * for the input device.
-	 */
-	aiptek->inputdev.private = aiptek;
-	aiptek->inputdev.open = aiptek_open;
-	aiptek->inputdev.close = aiptek_close;
-
-	/* Determine the usb devices' physical path.
-	 * Asketh not why we always pretend we're using "../input0",
-	 * but I suspect this will have to be refactored one
-	 * day if a single USB device can be a keyboard & a mouse
-	 * & a tablet, and the inputX number actually will tell
-	 * us something...
-	 */
-	if (usb_make_path(usbdev, path, 64) > 0)
-		sprintf(aiptek->features.usbPath, "%s/input0", path);
-
-	/* Program the input device coordinate capacities. We do not yet
+	/*
+	 * Program the input device coordinate capacities. We do not yet
 	 * know what maximum X, Y, and Z values are, so we're putting fake
 	 * values in. Later, we'll ask the tablet to put in the correct
 	 * values.
 	 */
-	aiptek->inputdev.absmin[ABS_X] = 0;
-	aiptek->inputdev.absmax[ABS_X] = 2999;
-	aiptek->inputdev.absmin[ABS_Y] = 0;
-	aiptek->inputdev.absmax[ABS_Y] = 2249;
-	aiptek->inputdev.absmin[ABS_PRESSURE] = 0;
-	aiptek->inputdev.absmax[ABS_PRESSURE] = 511;
-	aiptek->inputdev.absmin[ABS_TILT_X] = AIPTEK_TILT_MIN;
-	aiptek->inputdev.absmax[ABS_TILT_X] = AIPTEK_TILT_MAX;
-	aiptek->inputdev.absmin[ABS_TILT_Y] = AIPTEK_TILT_MIN;
-	aiptek->inputdev.absmax[ABS_TILT_Y] = AIPTEK_TILT_MAX;
-	aiptek->inputdev.absmin[ABS_WHEEL] = AIPTEK_WHEEL_MIN;
-	aiptek->inputdev.absmax[ABS_WHEEL] = AIPTEK_WHEEL_MAX - 1;
-	aiptek->inputdev.absfuzz[ABS_X] = 0;
-	aiptek->inputdev.absfuzz[ABS_Y] = 0;
-	aiptek->inputdev.absfuzz[ABS_PRESSURE] = 0;
-	aiptek->inputdev.absfuzz[ABS_TILT_X] = 0;
-	aiptek->inputdev.absfuzz[ABS_TILT_Y] = 0;
-	aiptek->inputdev.absfuzz[ABS_WHEEL] = 0;
-	aiptek->inputdev.absflat[ABS_X] = 0;
-	aiptek->inputdev.absflat[ABS_Y] = 0;
-	aiptek->inputdev.absflat[ABS_PRESSURE] = 0;
-	aiptek->inputdev.absflat[ABS_TILT_X] = 0;
-	aiptek->inputdev.absflat[ABS_TILT_Y] = 0;
-	aiptek->inputdev.absflat[ABS_WHEEL] = 0;
-	aiptek->inputdev.name = "Aiptek";
-	aiptek->inputdev.phys = aiptek->features.usbPath;
-	usb_to_input_id(usbdev, &aiptek->inputdev.id);
-	aiptek->inputdev.dev = &intf->dev;
-
-	aiptek->usbdev = usbdev;
-	aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
-	aiptek->inDelay = 0;
-	aiptek->endDelay = 0;
-	aiptek->previousJitterable = 0;
+	input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0);
+	input_set_abs_params(inputdev, ABS_X, 0, 2249, 0, 0);
+	input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0);
+	input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+	input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
+	input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
 
 	endpoint = &intf->altsetting[0].endpoint[0].desc;
 
@@ -2150,28 +2124,6 @@
 	aiptek->urb->transfer_dma = aiptek->data_dma;
 	aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	/* Register the tablet as an Input Device
-	 */
-	input_register_device(&aiptek->inputdev);
-
-	/* We now will look for the evdev device which is mapped to
-	 * the tablet. The partial name is kept in the link list of
-	 * input_handles associated with this input device.
-	 * What identifies an evdev input_handler is that it begins
-	 * with 'event', continues with a digit, and that in turn
-	 * is mapped to /{devfs}/input/eventN.
-	 */
-	inputdev = &aiptek->inputdev;
-	list_for_each_safe(node, next, &inputdev->h_list) {
-		inputhandle = to_handle(node);
-		if (strncmp(inputhandle->name, "event", 5) == 0) {
-			strcpy(aiptek->features.inputPath, inputhandle->name);
-			break;
-		}
-	}
-
-	info("input: Aiptek on %s (%s)\n", path, aiptek->features.inputPath);
-
 	/* Program the tablet. This sets the tablet up in the mode
 	 * specified in newSetting, and also queries the tablet's
 	 * physical capacities.
@@ -2186,13 +2138,32 @@
 	for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
 		aiptek->curSetting.programmableDelay = speeds[i];
 		(void)aiptek_program_tablet(aiptek);
-		if (aiptek->inputdev.absmax[ABS_X] > 0) {
+		if (aiptek->inputdev->absmax[ABS_X] > 0) {
 			info("input: Aiptek using %d ms programming speed\n",
 			     aiptek->curSetting.programmableDelay);
 			break;
 		}
 	}
 
+	/* Register the tablet as an Input Device
+	 */
+	input_register_device(aiptek->inputdev);
+
+	/* We now will look for the evdev device which is mapped to
+	 * the tablet. The partial name is kept in the link list of
+	 * input_handles associated with this input device.
+	 * What identifies an evdev input_handler is that it begins
+	 * with 'event', continues with a digit, and that in turn
+	 * is mapped to input/eventN.
+	 */
+	list_for_each_safe(node, next, &inputdev->h_list) {
+		inputhandle = to_handle(node);
+		if (strncmp(inputhandle->name, "event", 5) == 0) {
+			strcpy(aiptek->features.inputPath, inputhandle->name);
+			break;
+		}
+	}
+
 	/* Associate this driver's struct with the usb interface.
 	 */
 	usb_set_intfdata(intf, aiptek);
@@ -2207,6 +2178,12 @@
 		info("aiptek: error loading 'evdev' module");
 
 	return 0;
+
+fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
+			aiptek->data_dma);
+fail1:	input_free_device(inputdev);
+	kfree(aiptek);
+	return -ENOMEM;
 }
 
 /* Forward declaration */
@@ -2234,7 +2211,7 @@
 		/* Free & unhook everything from the system.
 		 */
 		usb_kill_urb(aiptek->urb);
-		input_unregister_device(&aiptek->inputdev);
+		input_unregister_device(aiptek->inputdev);
 		aiptek_delete_files(&intf->dev);
 		usb_free_urb(aiptek->urb);
 		usb_buffer_free(interface_to_usbdev(intf),
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index e03c1c5..15840db 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -39,7 +39,7 @@
 #define APPLE_VENDOR_ID		0x05AC
 
 #define ATP_DEVICE(prod)					\
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |   		\
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
 		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
 		       USB_DEVICE_ID_MATCH_INT_PROTOCOL,	\
 	.idVendor = APPLE_VENDOR_ID,				\
@@ -78,9 +78,9 @@
  * We try to keep the touchpad aspect ratio while still doing only simple
  * arithmetics.
  * The factors below give coordinates like:
- * 	0 <= x <  960 on 12" and 15" Powerbooks
- * 	0 <= x < 1600 on 17" Powerbooks
- * 	0 <= y <  646
+ *	0 <= x <  960 on 12" and 15" Powerbooks
+ *	0 <= x < 1600 on 17" Powerbooks
+ *	0 <= y <  646
  */
 #define ATP_XFACT	64
 #define ATP_YFACT	43
@@ -93,11 +93,12 @@
 
 /* Structure to hold all of our device specific stuff */
 struct atp {
+	char			phys[64];
 	struct usb_device *	udev;		/* usb device */
 	struct urb *		urb;		/* usb request block */
 	signed char *		data;		/* transferred data */
 	int			open;		/* non-zero if opened */
-	struct input_dev	input;		/* input dev */
+	struct input_dev	*input;		/* input dev */
 	int			valid;		/* are the sensors valid ? */
 	int			x_old;		/* last reported x/y, */
 	int			y_old;		/* used for smoothing */
@@ -114,11 +115,11 @@
 		int i;							\
 		printk("appletouch: %s %lld", msg, (long long)jiffies); \
 		for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++)	\
-			printk(" %02x", tab[i]); 			\
-		printk("\n"); 						\
+			printk(" %02x", tab[i]);			\
+		printk("\n");						\
 	}
 
-#define dprintk(format, a...) 						\
+#define dprintk(format, a...)						\
 	do {								\
 		if (debug) printk(format, ##a);				\
 	} while (0)
@@ -219,8 +220,8 @@
 		for (i = 16; i < ATP_XSENSORS; i++)
 			if (dev->xy_cur[i]) {
 				printk("appletouch: 17\" model detected.\n");
-				input_set_abs_params(&dev->input, ABS_X, 0,
-				     		     (ATP_XSENSORS - 1) *
+				input_set_abs_params(dev->input, ABS_X, 0,
+						     (ATP_XSENSORS - 1) *
 						     ATP_XFACT - 1,
 						     ATP_FUZZ, 0);
 				break;
@@ -260,12 +261,12 @@
 				       "Xz: %3d Yz: %3d\n",
 				       x, y, x_z, y_z);
 
-			input_report_key(&dev->input, BTN_TOUCH, 1);
-			input_report_abs(&dev->input, ABS_X, x);
-			input_report_abs(&dev->input, ABS_Y, y);
-			input_report_abs(&dev->input, ABS_PRESSURE,
+			input_report_key(dev->input, BTN_TOUCH, 1);
+			input_report_abs(dev->input, ABS_X, x);
+			input_report_abs(dev->input, ABS_Y, y);
+			input_report_abs(dev->input, ABS_PRESSURE,
 					 min(ATP_PRESSURE, x_z + y_z));
-			atp_report_fingers(&dev->input, max(x_f, y_f));
+			atp_report_fingers(dev->input, max(x_f, y_f));
 		}
 		dev->x_old = x;
 		dev->y_old = y;
@@ -273,17 +274,17 @@
 	else if (!x && !y) {
 
 		dev->x_old = dev->y_old = -1;
-		input_report_key(&dev->input, BTN_TOUCH, 0);
-		input_report_abs(&dev->input, ABS_PRESSURE, 0);
-		atp_report_fingers(&dev->input, 0);
+		input_report_key(dev->input, BTN_TOUCH, 0);
+		input_report_abs(dev->input, ABS_PRESSURE, 0);
+		atp_report_fingers(dev->input, 0);
 
 		/* reset the accumulator on release */
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
 	}
 
-	input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+	input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
 
-	input_sync(&dev->input);
+	input_sync(dev->input);
 
 exit:
 	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -314,21 +315,14 @@
 
 static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
 {
-	struct atp *dev = NULL;
+	struct atp *dev;
+	struct input_dev *input_dev;
+	struct usb_device *udev = interface_to_usbdev(iface);
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	int int_in_endpointAddr = 0;
 	int i, retval = -ENOMEM;
 
-	/* allocate memory for our device state and initialize it */
-	dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
-	if (dev == NULL) {
-		err("Out of memory");
-		goto err_kmalloc;
-	}
-	memset(dev, 0, sizeof(struct atp));
-
-	dev->udev = interface_to_usbdev(iface);
 
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
@@ -345,70 +339,82 @@
 		}
 	}
 	if (!int_in_endpointAddr) {
-		retval = -EIO;
 		err("Could not find int-in endpoint");
-		goto err_endpoint;
+		return -EIO;
 	}
 
-	/* save our data pointer in this interface device */
-	usb_set_intfdata(iface, dev);
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(struct atp), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!dev || !input_dev) {
+		err("Out of memory");
+		goto err_free_devs;
+	}
+
+	dev->udev = udev;
+	dev->input = input_dev;
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
 		retval = -ENOMEM;
-		goto err_usballoc;
+		goto err_free_devs;
 	}
+
 	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
-		goto err_usbbufalloc;
+		goto err_free_urb;
 	}
-	usb_fill_int_urb(dev->urb, dev->udev,
-			 usb_rcvintpipe(dev->udev, int_in_endpointAddr),
+
+	usb_fill_int_urb(dev->urb, udev,
+			 usb_rcvintpipe(udev, int_in_endpointAddr),
 			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
 
-	init_input_dev(&dev->input);
-	dev->input.name = "appletouch";
-	dev->input.dev = &iface->dev;
-	dev->input.private = dev;
-	dev->input.open = atp_open;
-	dev->input.close = atp_close;
+	usb_make_path(udev, dev->phys, sizeof(dev->phys));
+	strlcat(dev->phys, "/input0", sizeof(dev->phys));
 
-	usb_to_input_id(dev->udev, &dev->input.id);
+	input_dev->name = "appletouch";
+	input_dev->phys = dev->phys;
+	usb_to_input_id(dev->udev, &input_dev->id);
+	input_dev->cdev.dev = &iface->dev;
 
-	set_bit(EV_ABS, dev->input.evbit);
+	input_dev->private = dev;
+	input_dev->open = atp_open;
+	input_dev->close = atp_close;
+
+	set_bit(EV_ABS, input_dev->evbit);
 
 	/*
 	 * 12" and 15" Powerbooks only have 16 x sensors,
 	 * 17" models are detected later.
 	 */
-	input_set_abs_params(&dev->input, ABS_X, 0,
+	input_set_abs_params(input_dev, ABS_X, 0,
 			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(&dev->input, ABS_Y, 0,
+	input_set_abs_params(input_dev, ABS_Y, 0,
 			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
-	set_bit(EV_KEY, dev->input.evbit);
-	set_bit(BTN_TOUCH, dev->input.keybit);
-	set_bit(BTN_TOOL_FINGER, dev->input.keybit);
-	set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
-	set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
-	set_bit(BTN_LEFT, dev->input.keybit);
+	set_bit(EV_KEY, input_dev->evbit);
+	set_bit(BTN_TOUCH, input_dev->keybit);
+	set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+	set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+	set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+	set_bit(BTN_LEFT, input_dev->keybit);
 
-	input_register_device(&dev->input);
+	input_register_device(dev->input);
 
-	printk(KERN_INFO "input: appletouch connected\n");
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(iface, dev);
 
 	return 0;
 
-err_usbbufalloc:
+ err_free_urb:
 	usb_free_urb(dev->urb);
-err_usballoc:
+ err_free_devs:
 	usb_set_intfdata(iface, NULL);
-err_endpoint:
 	kfree(dev);
-err_kmalloc:
+	input_free_device(input_dev);
 	return retval;
 }
 
@@ -419,7 +425,7 @@
 	usb_set_intfdata(iface, NULL);
 	if (dev) {
 		usb_kill_urb(dev->urb);
-		input_unregister_device(&dev->input);
+		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
 		usb_buffer_free(dev->udev, ATP_DATASIZE,
 				dev->data, dev->urb->transfer_dma);
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index fd99681..9a2a47d 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -112,7 +112,6 @@
 
 #define NAME_BUFSIZE      80    /* size of product name, path buffers */
 #define DATA_BUFSIZE      63    /* size of URB data buffers */
-#define ATI_INPUTNUM      1     /* Which input device to register as */
 
 static unsigned long channel_mask;
 module_param(channel_mask, ulong, 0444);
@@ -162,7 +161,7 @@
 static DECLARE_MUTEX(disconnect_sem);
 
 struct ati_remote {
-	struct input_dev idev;
+	struct input_dev *idev;
 	struct usb_device *udev;
 	struct usb_interface *interface;
 
@@ -198,15 +197,13 @@
 #define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
 
 /* Translation table from hardware messages to input events. */
-static struct
-{
+static struct {
 	short kind;
 	unsigned char data1, data2;
 	int type;
 	unsigned int code;
 	int value;
-}  ati_remote_tbl[] =
-{
+}  ati_remote_tbl[] = {
 	/* Directional control pad axes */
 	{KIND_ACCEL,   0x35, 0x70, EV_REL, REL_X, -1},	 /* left */
 	{KIND_ACCEL,   0x36, 0x71, EV_REL, REL_X, 1},    /* right */
@@ -286,7 +283,6 @@
 
 /* Local function prototypes */
 static void ati_remote_dump		(unsigned char *data, unsigned int actual_length);
-static void ati_remote_delete		(struct ati_remote *dev);
 static int ati_remote_open		(struct input_dev *inputdev);
 static void ati_remote_close		(struct input_dev *inputdev);
 static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
@@ -428,7 +424,7 @@
 {
 	struct ati_remote *ati_remote = urb->context;
 	unsigned char *data= ati_remote->inbuf;
-	struct input_dev *dev = &ati_remote->idev;
+	struct input_dev *dev = ati_remote->idev;
 	int index, acc;
 	int remote_num;
 
@@ -587,17 +583,42 @@
 }
 
 /*
- *	ati_remote_delete
+ *	ati_remote_alloc_buffers
  */
-static void ati_remote_delete(struct ati_remote *ati_remote)
+static int ati_remote_alloc_buffers(struct usb_device *udev,
+				    struct ati_remote *ati_remote)
+{
+	ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+					     &ati_remote->inbuf_dma);
+	if (!ati_remote->inbuf)
+		return -1;
+
+	ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+					      &ati_remote->outbuf_dma);
+	if (!ati_remote->outbuf)
+		return -1;
+
+	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->irq_urb)
+		return -1;
+
+	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->out_urb)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *	ati_remote_free_buffers
+ */
+static void ati_remote_free_buffers(struct ati_remote *ati_remote)
 {
 	if (ati_remote->irq_urb)
-		usb_kill_urb(ati_remote->irq_urb);
+		usb_free_urb(ati_remote->irq_urb);
 
 	if (ati_remote->out_urb)
-		usb_kill_urb(ati_remote->out_urb);
-
-	input_unregister_device(&ati_remote->idev);
+		usb_free_urb(ati_remote->out_urb);
 
 	if (ati_remote->inbuf)
 		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
@@ -605,20 +626,12 @@
 
 	if (ati_remote->outbuf)
 		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
-				ati_remote->outbuf, ati_remote->outbuf_dma);
-
-	if (ati_remote->irq_urb)
-		usb_free_urb(ati_remote->irq_urb);
-
-	if (ati_remote->out_urb)
-		usb_free_urb(ati_remote->out_urb);
-
-	kfree(ati_remote);
+				ati_remote->inbuf, ati_remote->outbuf_dma);
 }
 
 static void ati_remote_input_init(struct ati_remote *ati_remote)
 {
-	struct input_dev *idev = &(ati_remote->idev);
+	struct input_dev *idev = ati_remote->idev;
 	int i;
 
 	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
@@ -637,7 +650,7 @@
 	idev->phys = ati_remote->phys;
 
 	usb_to_input_id(ati_remote->udev, &idev->id);
-	idev->dev = &ati_remote->udev->dev;
+	idev->cdev.dev = &ati_remote->udev->dev;
 }
 
 static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -674,7 +687,7 @@
 	    (ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
 		dev_err(&ati_remote->interface->dev,
 			 "Initializing ati_remote hardware failed.\n");
-		return 1;
+		return -EIO;
 	}
 
 	return 0;
@@ -686,95 +699,83 @@
 static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct ati_remote *ati_remote = NULL;
-	struct usb_host_interface *iface_host;
-	int retval = -ENOMEM;
-	char path[64];
+	struct usb_host_interface *iface_host = interface->cur_altsetting;
+	struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
+	struct ati_remote *ati_remote;
+	struct input_dev *input_dev;
+	int err = -ENOMEM;
 
-	/* Allocate and clear an ati_remote struct */
-	if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
-		return -ENOMEM;
-	memset(ati_remote, 0x00, sizeof (struct ati_remote));
-
-	iface_host = interface->cur_altsetting;
 	if (iface_host->desc.bNumEndpoints != 2) {
 		err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
-		retval = -ENODEV;
-		goto error;
+		return -ENODEV;
 	}
 
-	ati_remote->endpoint_in = &(iface_host->endpoint[0].desc);
-	ati_remote->endpoint_out = &(iface_host->endpoint[1].desc);
-	ati_remote->udev = udev;
-	ati_remote->interface = interface;
+	endpoint_in = &iface_host->endpoint[0].desc;
+	endpoint_out = &iface_host->endpoint[1].desc;
 
-	if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) {
+	if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) {
 		err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
-		retval = -ENODEV;
-		goto error;
+		return -ENODEV;
 	}
-	if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) {
+	if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
 		err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
-		retval = -ENODEV;
-		goto error;
+		return -ENODEV;
 	}
-	if (le16_to_cpu(ati_remote->endpoint_in->wMaxPacketSize) == 0) {
+	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
 		err("%s: endpoint_in message size==0? \n", __FUNCTION__);
-		retval = -ENODEV;
-		goto error;
+		return -ENODEV;
 	}
 
+	ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ati_remote || !input_dev)
+		goto fail1;
+
 	/* Allocate URB buffers, URBs */
-	ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
-					     &ati_remote->inbuf_dma);
-	if (!ati_remote->inbuf)
-		goto error;
+	if (ati_remote_alloc_buffers(udev, ati_remote))
+		goto fail2;
 
-	ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
-					      &ati_remote->outbuf_dma);
-	if (!ati_remote->outbuf)
-		goto error;
+	ati_remote->endpoint_in = endpoint_in;
+	ati_remote->endpoint_out = endpoint_out;
+	ati_remote->udev = udev;
+	ati_remote->idev = input_dev;
+	ati_remote->interface = interface;
 
-	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ati_remote->irq_urb)
-		goto error;
+	usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
+	strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
 
-	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ati_remote->out_urb)
-		goto error;
-
-	usb_make_path(udev, path, NAME_BUFSIZE);
-	sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM);
 	if (udev->manufacturer)
-		strcat(ati_remote->name, udev->manufacturer);
+		strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
 
 	if (udev->product)
-		sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product);
+		snprintf(ati_remote->name, sizeof(ati_remote->name),
+			 "%s %s", ati_remote->name, udev->product);
 
 	if (!strlen(ati_remote->name))
-		sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
+		snprintf(ati_remote->name, sizeof(ati_remote->name),
+			DRIVER_DESC "(%04x,%04x)",
 			le16_to_cpu(ati_remote->udev->descriptor.idVendor),
 			le16_to_cpu(ati_remote->udev->descriptor.idProduct));
 
+	ati_remote_input_init(ati_remote);
+
 	/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
-	retval = ati_remote_initialize(ati_remote);
-	if (retval)
-		goto error;
+	err = ati_remote_initialize(ati_remote);
+	if (err)
+		goto fail3;
 
 	/* Set up and register input device */
-	ati_remote_input_init(ati_remote);
-	input_register_device(&ati_remote->idev);
-
-	dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n",
-		 ati_remote->name, path);
+	input_register_device(ati_remote->idev);
 
 	usb_set_intfdata(interface, ati_remote);
+	return 0;
 
-error:
-	if (retval)
-		ati_remote_delete(ati_remote);
-
-	return retval;
+fail3:	usb_kill_urb(ati_remote->irq_urb);
+	usb_kill_urb(ati_remote->out_urb);
+fail2:	ati_remote_free_buffers(ati_remote);
+fail1:	input_free_device(input_dev);
+	kfree(ati_remote);
+	return err;
 }
 
 /*
@@ -791,7 +792,11 @@
 		return;
 	}
 
-	ati_remote_delete(ati_remote);
+	usb_kill_urb(ati_remote->irq_urb);
+	usb_kill_urb(ati_remote->out_urb);
+	input_unregister_device(ati_remote->idev);
+	ati_remote_free_buffers(ati_remote);
+	kfree(ati_remote);
 }
 
 /*
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 41f92b9..79ddce4 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1619,8 +1619,8 @@
 	struct hid_descriptor *hdesc;
 	struct hid_device *hid;
 	unsigned quirks = 0, rsize = 0;
-	char *buf, *rdesc;
-	int n, insize = 0;
+	char *rdesc;
+	int n, len, insize = 0;
 
 	for (n = 0; hid_blacklist[n].idVendor; n++)
 		if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1630,10 +1630,11 @@
 	if (quirks & HID_QUIRK_IGNORE)
 		return NULL;
 
-	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->desc.bNumEndpoints) ||
-		usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
-			dbg("class descriptor not present\n");
-			return NULL;
+	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
+	    (!interface->desc.bNumEndpoints ||
+	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
+		dbg("class descriptor not present\n");
+		return NULL;
 	}
 
 	for (n = 0; n < hdesc->bNumDescriptors; n++)
@@ -1749,38 +1750,43 @@
 
 	hid->name[0] = 0;
 
-	if (!(buf = kmalloc(64, GFP_KERNEL)))
-		goto fail;
+	if (dev->manufacturer)
+		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
 
-	if (dev->manufacturer) {
-		strcat(hid->name, dev->manufacturer);
-		if (dev->product)
-			snprintf(hid->name, 64, "%s %s", hid->name, dev->product);
-	} else if (dev->product) {
-			snprintf(hid->name, 128, "%s", dev->product);
-	} else
-		snprintf(hid->name, 128, "%04x:%04x",
-			le16_to_cpu(dev->descriptor.idVendor),
-			le16_to_cpu(dev->descriptor.idProduct));
+	if (dev->product) {
+		if (dev->manufacturer)
+			strlcat(hid->name, " ", sizeof(hid->name));
+		strlcat(hid->name, dev->product, sizeof(hid->name));
+	}
 
-	usb_make_path(dev, buf, 64);
-	snprintf(hid->phys, 64, "%s/input%d", buf,
-			intf->altsetting[0].desc.bInterfaceNumber);
+	if (!strlen(hid->name))
+		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+			 le16_to_cpu(dev->descriptor.idVendor),
+			 le16_to_cpu(dev->descriptor.idProduct));
+
+	usb_make_path(dev, hid->phys, sizeof(hid->phys));
+	strlcat(hid->phys, "/input", sizeof(hid->phys));
+	len = strlen(hid->phys);
+	if (len < sizeof(hid->phys) - 1)
+		snprintf(hid->phys + len, sizeof(hid->phys) - len,
+			 "%d", intf->altsetting[0].desc.bInterfaceNumber);
 
 	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
 		hid->uniq[0] = 0;
 
-	kfree(buf);
-
 	hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
 	if (!hid->urbctrl)
 		goto fail;
+
 	usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
 			     hid->ctrlbuf, 1, hid_ctrl, hid);
 	hid->urbctrl->setup_dma = hid->cr_dma;
 	hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
 	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
+	/* May be needed for some devices */
+	usb_clear_halt(hid->dev, hid->urbin->pipe);
+
 	return hid;
 
 fail:
@@ -1884,7 +1890,6 @@
 	struct hid_device *hid = usb_get_intfdata (intf);
 
 	usb_kill_urb(hid->urbin);
-	intf->dev.power.power_state = PMSG_SUSPEND;
 	dev_dbg(&intf->dev, "suspend\n");
 	return 0;
 }
@@ -1894,7 +1899,6 @@
 	struct hid_device *hid = usb_get_intfdata (intf);
 	int status;
 
-	intf->dev.power.power_state = PMSG_ON;
 	if (hid->open)
 		status = usb_submit_urb(hid->urbin, GFP_NOIO);
 	else
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 0b64522..9ff25eb 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -76,8 +76,8 @@
 static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
 				     struct hid_usage *usage)
 {
-	struct input_dev *input = &hidinput->input;
-	struct hid_device *device = hidinput->input.private;
+	struct input_dev *input = hidinput->input;
+	struct hid_device *device = input->private;
 	int max = 0, code;
 	unsigned long *bit = NULL;
 
@@ -461,7 +461,8 @@
 
 	if (!field->hidinput)
 		return;
-	input = &field->hidinput->input;
+
+	input = field->hidinput->input;
 
 	input_regs(input, regs);
 
@@ -533,13 +534,10 @@
 
 void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
 {
-	struct list_head *lh;
 	struct hid_input *hidinput;
 
-	list_for_each (lh, &hid->inputs) {
-		hidinput = list_entry(lh, struct hid_input, list);
-		input_sync(&hidinput->input);
-	}
+	list_for_each_entry(hidinput, &hid->inputs, list)
+		input_sync(hidinput->input);
 }
 
 static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
@@ -604,6 +602,7 @@
 	struct usb_device *dev = hid->dev;
 	struct hid_report *report;
 	struct hid_input *hidinput = NULL;
+	struct input_dev *input_dev;
 	int i, j, k;
 
 	INIT_LIST_HEAD(&hid->inputs);
@@ -624,25 +623,28 @@
 				continue;
 
 			if (!hidinput) {
-				hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
-				if (!hidinput) {
+				hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
+				input_dev = input_allocate_device();
+				if (!hidinput || !input_dev) {
+					kfree(hidinput);
+					input_free_device(input_dev);
 					err("Out of memory during hid input probe");
 					return -1;
 				}
-				memset(hidinput, 0, sizeof(*hidinput));
 
+				input_dev->private = hid;
+				input_dev->event = hidinput_input_event;
+				input_dev->open = hidinput_open;
+				input_dev->close = hidinput_close;
+
+				input_dev->name = hid->name;
+				input_dev->phys = hid->phys;
+				input_dev->uniq = hid->uniq;
+				usb_to_input_id(dev, &input_dev->id);
+				input_dev->cdev.dev = &hid->intf->dev;
+
+				hidinput->input = input_dev;
 				list_add_tail(&hidinput->list, &hid->inputs);
-
-				hidinput->input.private = hid;
-				hidinput->input.event = hidinput_input_event;
-				hidinput->input.open = hidinput_open;
-				hidinput->input.close = hidinput_close;
-
-				hidinput->input.name = hid->name;
-				hidinput->input.phys = hid->phys;
-				hidinput->input.uniq = hid->uniq;
-				usb_to_input_id(dev, &hidinput->input.id);
-				hidinput->input.dev = &hid->intf->dev;
 			}
 
 			for (i = 0; i < report->maxfield; i++)
@@ -657,7 +659,7 @@
 				 * UGCI) cram a lot of unrelated inputs into the
 				 * same interface. */
 				hidinput->report = report;
-				input_register_device(&hidinput->input);
+				input_register_device(hidinput->input);
 				hidinput = NULL;
 			}
 		}
@@ -667,7 +669,7 @@
 	 * only useful in this case, and not for multi-input quirks. */
 	if (hidinput) {
 		hid_ff_init(hid);
-		input_register_device(&hidinput->input);
+		input_register_device(hidinput->input);
 	}
 
 	return 0;
@@ -675,13 +677,11 @@
 
 void hidinput_disconnect(struct hid_device *hid)
 {
-	struct list_head *lh, *next;
-	struct hid_input *hidinput;
+	struct hid_input *hidinput, *next;
 
-	list_for_each_safe(lh, next, &hid->inputs) {
-		hidinput = list_entry(lh, struct hid_input, list);
-		input_unregister_device(&hidinput->input);
+	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
 		list_del(&hidinput->list);
+		input_unregister_device(hidinput->input);
 		kfree(hidinput);
 	}
 }
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 0c4c77a..f82c9c9 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -255,22 +255,19 @@
 	u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor);
 	u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct);
 	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+	struct input_dev *input_dev = hidinput->input;
 
 	while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct))
 		dev++;
 
-	ff = dev->ff;
+	for (ff = dev->ff; *ff >= 0; ff++)
+		set_bit(*ff, input_dev->ffbit);
 
-	while (*ff >= 0) {
-		set_bit(*ff, hidinput->input.ffbit);
-		++ff;
-	}
+	input_dev->upload_effect = hid_lgff_upload_effect;
+	input_dev->flush = hid_lgff_flush;
 
-	hidinput->input.upload_effect = hid_lgff_upload_effect;
-	hidinput->input.flush = hid_lgff_flush;
-
-	set_bit(EV_FF, hidinput->input.evbit);
-	hidinput->input.ff_effects_max = LGFF_EFFECTS;
+	set_bit(EV_FF, input_dev->evbit);
+	input_dev->ff_effects_max = LGFF_EFFECTS;
 }
 
 static void hid_lgff_exit(struct hid_device* hid)
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c
index 8f6a0a6..023fd5a 100644
--- a/drivers/usb/input/hid-tmff.c
+++ b/drivers/usb/input/hid-tmff.c
@@ -111,6 +111,7 @@
 	struct tmff_device *private;
 	struct list_head *pos;
 	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+	struct input_dev *input_dev = hidinput->input;
 
 	private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL);
 	if (!private)
@@ -155,7 +156,7 @@
 					private->report = report;
 					private->rumble = field;
 
-					set_bit(FF_RUMBLE, hidinput->input.ffbit);
+					set_bit(FF_RUMBLE, input_dev->ffbit);
 					break;
 
 				default:
@@ -164,11 +165,11 @@
 			}
 
 			/* Fallthrough to here only when a valid usage is found */
-			hidinput->input.upload_effect = hid_tmff_upload_effect;
-			hidinput->input.flush = hid_tmff_flush;
+			input_dev->upload_effect = hid_tmff_upload_effect;
+			input_dev->flush = hid_tmff_flush;
 
-			set_bit(EV_FF, hidinput->input.evbit);
-			hidinput->input.ff_effects_max = TMFF_EFFECTS;
+			set_bit(EV_FF, input_dev->evbit);
+			input_dev->ff_effects_max = TMFF_EFFECTS;
 		}
 	}
 
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index ec2412c..ee48a22 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -371,7 +371,7 @@
 struct hid_input {
 	struct list_head list;
 	struct hid_report *report;
-	struct input_dev input;
+	struct input_dev *input;
 };
 
 struct hid_device {							/* device report descriptor */
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index d324278..440377c 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -732,9 +732,8 @@
 };
 
 static struct usb_class_driver hiddev_class = {
-	.name =		"usb/hid/hiddev%d",
+	.name =		"hiddev%d",
 	.fops =		&hiddev_fops,
-	.mode =		S_IFCHR | S_IRUGO | S_IWUSR,
 	.minor_base =	HIDDEV_MINOR_BASE,
 };
 
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index becb87e..3b58185 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -73,7 +73,7 @@
 
 struct itmtouch_dev {
 	struct usb_device	*usbdev; /* usb device */
-	struct input_dev	inputdev; /* input device */
+	struct input_dev	*inputdev; /* input device */
 	struct urb		*readurb; /* urb */
 	char			rbuf[ITM_BUFSIZE]; /* data */
 	int			users;
@@ -88,9 +88,9 @@
 
 static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
 {
-	struct itmtouch_dev * itmtouch = urb->context;
+	struct itmtouch_dev *itmtouch = urb->context;
 	unsigned char *data = urb->transfer_buffer;
-	struct input_dev *dev = &itmtouch->inputdev;
+	struct input_dev *dev = itmtouch->inputdev;
 	int retval;
 
 	switch (urb->status) {
@@ -156,49 +156,62 @@
 static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct itmtouch_dev *itmtouch;
+	struct input_dev *input_dev;
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	unsigned int pipe;
 	unsigned int maxp;
-	char path[PATH_SIZE];
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
 
-	if (!(itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL))) {
+	itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!itmtouch || !input_dev) {
 		err("%s - Out of memory.", __FUNCTION__);
-		return -ENOMEM;
+		goto fail;
 	}
 
 	itmtouch->usbdev = udev;
+	itmtouch->inputdev = input_dev;
 
-	itmtouch->inputdev.private = itmtouch;
-	itmtouch->inputdev.open = itmtouch_open;
-	itmtouch->inputdev.close = itmtouch_close;
+	if (udev->manufacturer)
+		strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
 
-	usb_make_path(udev, path, PATH_SIZE);
-
-	itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-	itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-	itmtouch->inputdev.name = itmtouch->name;
-	itmtouch->inputdev.phys = itmtouch->phys;
-	usb_to_input_id(udev, &itmtouch->inputdev.id);
-	itmtouch->inputdev.dev = &intf->dev;
+	if (udev->product) {
+		if (udev->manufacturer)
+			strlcat(itmtouch->name, " ", sizeof(itmtouch->name));
+		strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name));
+	}
 
 	if (!strlen(itmtouch->name))
 		sprintf(itmtouch->name, "USB ITM touchscreen");
 
+	usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys));
+	strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys));
+
+	input_dev->name = itmtouch->name;
+	input_dev->phys = itmtouch->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = itmtouch;
+
+	input_dev->open = itmtouch_open;
+	input_dev->close = itmtouch_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
 	/* device limits */
 	/* as specified by the ITM datasheet, X and Y are 12bit,
 	 * Z (pressure) is 8 bit. However, the fields are defined up
 	 * to 14 bits for future possible expansion.
 	 */
-	input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0);
-	input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0);
-	input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0);
+	input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0);
 
 	/* initialise the URB so we can read from the transport stream */
 	pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
@@ -208,22 +221,23 @@
 		maxp = ITM_BUFSIZE;
 
 	itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
-
 	if (!itmtouch->readurb) {
 		dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
-		kfree(itmtouch);
-		return -ENOMEM;
+		goto fail;
 	}
 
 	usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
 			 maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
 
-	input_register_device(&itmtouch->inputdev);
+	input_register_device(itmtouch->inputdev);
 
-	printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path);
 	usb_set_intfdata(intf, itmtouch);
 
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(itmtouch);
+	return -ENOMEM;
 }
 
 static void itmtouch_disconnect(struct usb_interface *intf)
@@ -233,7 +247,7 @@
 	usb_set_intfdata(intf, NULL);
 
 	if (itmtouch) {
-		input_unregister_device(&itmtouch->inputdev);
+		input_unregister_device(itmtouch->inputdev);
 		usb_kill_urb(itmtouch->readurb);
 		usb_free_urb(itmtouch->readurb);
 		kfree(itmtouch);
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index b6f6ac8..a248664 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -34,7 +34,7 @@
 struct kbtab {
 	signed char *data;
 	dma_addr_t data_dma;
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct usb_device *usbdev;
 	struct urb *irq;
 	int x, y;
@@ -48,7 +48,7 @@
 {
 	struct kbtab *kbtab = urb->context;
 	unsigned char *data = kbtab->data;
-	struct input_dev *dev = &kbtab->dev;
+	struct input_dev *dev = kbtab->dev;
 	int retval;
 
 	switch (urb->status) {
@@ -124,53 +124,43 @@
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_endpoint_descriptor *endpoint;
 	struct kbtab *kbtab;
-	char path[64];
+	struct input_dev *input_dev;
 
-	if (!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL)))
-		return -ENOMEM;
-	memset(kbtab, 0, sizeof(struct kbtab));
+	kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!kbtab || !input_dev)
+		goto fail1;
 
 	kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
-	if (!kbtab->data) {
-		kfree(kbtab);
-		return -ENOMEM;
-	}
+	if (!kbtab->data)
+		goto fail1;
 
 	kbtab->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!kbtab->irq) {
-		usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
-		kfree(kbtab);
-		return -ENOMEM;
-	}
+	if (!kbtab->irq)
+		goto fail2;
 
-	kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
-	kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-
-	kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-
-	kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
-
-	kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL);
-
-	kbtab->dev.absmax[ABS_X] = 0x2000;
-	kbtab->dev.absmax[ABS_Y] = 0x1750;
-	kbtab->dev.absmax[ABS_PRESSURE] = 0xff;
-
-	kbtab->dev.absfuzz[ABS_X] = 4;
-	kbtab->dev.absfuzz[ABS_Y] = 4;
-
-	kbtab->dev.private = kbtab;
-	kbtab->dev.open = kbtab_open;
-	kbtab->dev.close = kbtab_close;
-
-	usb_make_path(dev, path, 64);
-	sprintf(kbtab->phys, "%s/input0", path);
-
-	kbtab->dev.name = "KB Gear Tablet";
-	kbtab->dev.phys = kbtab->phys;
-	usb_to_input_id(dev, &kbtab->dev.id);
-	kbtab->dev.dev = &intf->dev;
 	kbtab->usbdev = dev;
+	kbtab->dev = input_dev;
+
+	usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys));
+	strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys));
+
+	input_dev->name = "KB Gear Tablet";
+	input_dev->phys = kbtab->phys;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = kbtab;
+
+	input_dev->open = kbtab_open;
+	input_dev->close = kbtab_close;
+
+	input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
+	input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+	input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0);
+	input_set_abs_params(input_dev, ABS_X, 0, 0x1750, 4, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
 
 	endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
@@ -181,23 +171,25 @@
 	kbtab->irq->transfer_dma = kbtab->data_dma;
 	kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(&kbtab->dev);
-
-	printk(KERN_INFO "input: KB Gear Tablet on %s\n",  path);
+	input_register_device(kbtab->dev);
 
 	usb_set_intfdata(intf, kbtab);
-
 	return 0;
+
+fail2:	usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
+fail1:	input_free_device(input_dev);
+	kfree(kbtab);
+	return -ENOMEM;
 }
 
 static void kbtab_disconnect(struct usb_interface *intf)
 {
-	struct kbtab *kbtab = usb_get_intfdata (intf);
+	struct kbtab *kbtab = usb_get_intfdata(intf);
 
 	usb_set_intfdata(intf, NULL);
 	if (kbtab) {
 		usb_kill_urb(kbtab->irq);
-		input_unregister_device(&kbtab->dev);
+		input_unregister_device(kbtab->dev);
 		usb_free_urb(kbtab->irq);
 		usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma);
 		kfree(kbtab);
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 99de1b3..5b8d65f 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -20,6 +20,7 @@
 #include <linux/moduleparam.h>
 #include <linux/input.h>
 #include <linux/usb.h>
+#include <linux/usb_input.h>
 
 #define DRIVER_VERSION	"v0.1"
 #define DRIVER_AUTHOR	"Michael Downey <downey@zymeta.com>"
@@ -75,7 +76,7 @@
 	char				name[128];
 	char				phys[64];
 	struct usb_device*		udev;
-	struct input_dev		input;
+	struct input_dev		*input;
 	struct usb_interface*		interface;
 	struct usb_endpoint_descriptor* in_endpoint;
 	struct urb*			irq_urb;
@@ -136,12 +137,11 @@
  */
 static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/
 {
-	char codes[4*RECV_SIZE];
+	char codes[4 * RECV_SIZE];
 	int i;
 
-	for (i = 0; i < RECV_SIZE; i++) {
-		snprintf(codes+i*3, 4, "%02x ", dev->in_buffer[i]);
-	}
+	for (i = 0; i < RECV_SIZE; i++)
+		snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]);
 
 	dev_info(&dev->udev->dev, "%s\n", codes);
 }
@@ -153,7 +153,7 @@
 static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
 {
 	if (dev->data.bits_left >= bits_needed)
-		return(0);
+		return 0;
 
 	/*
 	 * Somehow we've missed the last message. The message will be repeated
@@ -162,7 +162,7 @@
 	if (dev->data.pos >= dev->data.len) {
 		dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n",
 			__FUNCTION__, dev->data.pos, dev->data.len);
-		return(-1);
+		return -1;
 	}
 
 	/* Load as much as we can into the tester. */
@@ -172,7 +172,7 @@
 		dev->data.bits_left += 8;
 	}
 
-	return(0);
+	return 0;
 }
 
 /*
@@ -311,10 +311,10 @@
 			__FUNCTION__, message.system, message.button, message.toggle);
 
 		if (message.toggle != remote->toggle) {
-			input_regs(&remote->input, regs);
-			input_report_key(&remote->input, keyspan_key_table[message.button], 1);
-			input_report_key(&remote->input, keyspan_key_table[message.button], 0);
-			input_sync(&remote->input);
+			input_regs(remote->input, regs);
+			input_report_key(remote->input, keyspan_key_table[message.button], 1);
+			input_report_key(remote->input, keyspan_key_table[message.button], 0);
+			input_sync(remote->input);
 			remote->toggle = message.toggle;
 		}
 
@@ -397,14 +397,9 @@
 {
 	struct usb_keyspan *remote = dev->private;
 
-	if (remote->open++)
-		return 0;
-
 	remote->irq_urb->dev = remote->udev;
-	if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) {
-		remote->open--;
+	if (usb_submit_urb(remote->irq_urb, GFP_KERNEL))
 		return -EIO;
-	}
 
 	return 0;
 }
@@ -413,8 +408,26 @@
 {
 	struct usb_keyspan *remote = dev->private;
 
-	if (!--remote->open)
-		usb_kill_urb(remote->irq_urb);
+	usb_kill_urb(remote->irq_urb);
+}
+
+static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface)
+{
+
+	struct usb_endpoint_descriptor *endpoint;
+	int i;
+
+	for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
+		endpoint = &iface->endpoint[i].desc;
+
+		if ((endpoint->bEndpointAddress & USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+			/* we found our interrupt in endpoint */
+			return endpoint;
+		}
+	}
+
+	return NULL;
 }
 
 /*
@@ -422,110 +435,78 @@
  */
 static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-	int i;
-	int retval = -ENOMEM;
-	char path[64];
-	char *buf;
-	struct usb_keyspan *remote = NULL;
-	struct usb_host_interface *iface_desc;
+	struct usb_device *udev = interface_to_usbdev(interface);
 	struct usb_endpoint_descriptor *endpoint;
-	struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
+	struct usb_keyspan *remote;
+	struct input_dev *input_dev;
+	int i, retval;
 
-	/* allocate memory for our device state and initialize it */
-	remote = kmalloc(sizeof(*remote), GFP_KERNEL);
-	if (remote == NULL) {
-		err("Out of memory\n");
-		goto error;
+	endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
+	if (!endpoint)
+		return -ENODEV;
+
+	remote = kzalloc(sizeof(*remote), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!remote || !input_dev) {
+		retval = -ENOMEM;
+		goto fail1;
 	}
-	memset(remote, 0x00, sizeof(*remote));
 
 	remote->udev = udev;
+	remote->input = input_dev;
 	remote->interface = interface;
+	remote->in_endpoint = endpoint;
 	remote->toggle = -1;	/* Set to -1 so we will always not match the toggle from the first remote message. */
 
-	/* set up the endpoint information */
-	/* use only the first in interrupt endpoint */
-	iface_desc = interface->cur_altsetting;
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-
-		if (!remote->in_endpoint &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
-			/* we found our interrupt in endpoint */
-			remote->in_endpoint = endpoint;
-
-			remote->in_buffer = usb_buffer_alloc(remote->udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
-			if (!remote->in_buffer) {
-				retval = -ENOMEM;
-				goto error;
-			}
-		}
-	}
-
-	if (!remote->in_endpoint) {
-		err("Could not find interrupt input endpoint.\n");
-		retval = -ENODEV;
-		goto error;
+	remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
+	if (!remote->in_buffer) {
+		retval = -ENOMEM;
+		goto fail1;
 	}
 
 	remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!remote->irq_urb) {
-		err("Failed to allocate urb.\n");
 		retval = -ENOMEM;
-		goto error;
+		goto fail2;
 	}
 
-	retval = keyspan_setup(remote->udev);
+	retval = keyspan_setup(udev);
 	if (retval) {
-		err("Failed to setup device.\n");
 		retval = -ENODEV;
-		goto error;
+		goto fail3;
 	}
 
-	/*
-	 * Setup the input system with the bits we are going to be reporting
-	 */
-	remote->input.evbit[0] = BIT(EV_KEY);		/* We will only report KEY events. */
-	for (i = 0; i < 32; ++i) {
-		if (keyspan_key_table[i] != KEY_RESERVED) {
-			set_bit(keyspan_key_table[i], remote->input.keybit);
-		}
+	if (udev->manufacturer)
+		strlcpy(remote->name, udev->manufacturer, sizeof(remote->name));
+
+	if (udev->product) {
+		if (udev->manufacturer)
+			strlcat(remote->name, " ", sizeof(remote->name));
+		strlcat(remote->name, udev->product, sizeof(remote->name));
 	}
 
-	remote->input.private = remote;
-	remote->input.open = keyspan_open;
-	remote->input.close = keyspan_close;
-
-	usb_make_path(remote->udev, path, 64);
-	sprintf(remote->phys, "%s/input0", path);
-
-	remote->input.name = remote->name;
-	remote->input.phys = remote->phys;
-	remote->input.id.bustype = BUS_USB;
-	remote->input.id.vendor = le16_to_cpu(remote->udev->descriptor.idVendor);
-	remote->input.id.product = le16_to_cpu(remote->udev->descriptor.idProduct);
-	remote->input.id.version = le16_to_cpu(remote->udev->descriptor.bcdDevice);
-
-	if (!(buf = kmalloc(63, GFP_KERNEL))) {
-		usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
-		kfree(remote);
-		return -ENOMEM;
-	}
-
-	if (remote->udev->descriptor.iManufacturer &&
-	    usb_string(remote->udev, remote->udev->descriptor.iManufacturer, buf, 63) > 0)
-		strcat(remote->name, buf);
-
-	if (remote->udev->descriptor.iProduct &&
-	    usb_string(remote->udev, remote->udev->descriptor.iProduct, buf, 63) > 0)
-		sprintf(remote->name, "%s %s", remote->name, buf);
-
 	if (!strlen(remote->name))
-		sprintf(remote->name, "USB Keyspan Remote %04x:%04x",
-			remote->input.id.vendor, remote->input.id.product);
+		snprintf(remote->name, sizeof(remote->name),
+			 "USB Keyspan Remote %04x:%04x",
+			 le16_to_cpu(udev->descriptor.idVendor),
+			 le16_to_cpu(udev->descriptor.idProduct));
 
-	kfree(buf);
+	usb_make_path(udev, remote->phys, sizeof(remote->phys));
+	strlcat(remote->phys, "/input0", sizeof(remote->phys));
+
+	input_dev->name = remote->name;
+	input_dev->phys = remote->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &interface->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY);		/* We will only report KEY events. */
+	for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
+		if (keyspan_key_table[i] != KEY_RESERVED)
+			set_bit(keyspan_key_table[i], input_dev->keybit);
+
+	input_dev->private = remote;
+	input_dev->open = keyspan_open;
+	input_dev->close = keyspan_close;
 
 	/*
 	 * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open()
@@ -538,27 +519,17 @@
 	remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* we can register the device now, as it is ready */
-	input_register_device(&remote->input);
+	input_register_device(remote->input);
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(interface, remote);
 
-	/* let the user know what node this device is now attached to */
-	info("connected: %s on %s", remote->name, path);
 	return 0;
 
-error:
-	/*
-	 * In case of error we need to clean up any allocated buffers
-	 */
-	if (remote->irq_urb)
-		usb_free_urb(remote->irq_urb);
-
-	if (remote->in_buffer)
-		usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
-
-	if (remote)
-		kfree(remote);
+ fail3:	usb_free_urb(remote->irq_urb);
+ fail2:	usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
+ fail1:	kfree(remote);
+	input_free_device(input_dev);
 
 	return retval;
 }
@@ -570,23 +541,16 @@
 {
 	struct usb_keyspan *remote;
 
-	/* prevent keyspan_open() from racing keyspan_disconnect() */
-	lock_kernel();
-
 	remote = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
 	if (remote) {	/* We have a valid driver structure so clean up everything we allocated. */
-		input_unregister_device(&remote->input);
+		input_unregister_device(remote->input);
 		usb_kill_urb(remote->irq_urb);
 		usb_free_urb(remote->irq_urb);
-		usb_buffer_free(interface_to_usbdev(interface), RECV_SIZE, remote->in_buffer, remote->in_dma);
+		usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma);
 		kfree(remote);
 	}
-
-	unlock_kernel();
-
-	info("USB Keyspan now disconnected");
 }
 
 /*
diff --git a/drivers/usb/input/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h
index 52ff27f..a424094 100644
--- a/drivers/usb/input/map_to_7segment.h
+++ b/drivers/usb/input/map_to_7segment.h
@@ -79,7 +79,7 @@
 
 static inline int map_to_seg7(struct seg7_conversion_map *map, int c)
 {
-	return c & 0x7f ? map->table[c] : -EINVAL;
+	return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL;
 }
 
 #define SEG7_CONVERSION_MAP(_name, _map)	\
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index ff92750..7fce526 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -98,7 +98,7 @@
 	dma_addr_t data_dma;
 	struct urb *irq;
 	struct usb_device *udev;
-	struct input_dev input;
+	struct input_dev *input;
 	char name[128];
 	char phys[64];
 };
@@ -135,14 +135,14 @@
 		goto exit;
 	}
 
-	input_regs(&mtouch->input, regs);
-	input_report_key(&mtouch->input, BTN_TOUCH,
+	input_regs(mtouch->input, regs);
+	input_report_key(mtouch->input, BTN_TOUCH,
 			 MTOUCHUSB_GET_TOUCHED(mtouch->data));
-	input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
-	input_report_abs(&mtouch->input, ABS_Y,
+	input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
+	input_report_abs(mtouch->input, ABS_Y,
 			 (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
 			 - MTOUCHUSB_GET_YC(mtouch->data));
-	input_sync(&mtouch->input);
+	input_sync(mtouch->input);
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -195,10 +195,10 @@
 static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct mtouch_usb *mtouch;
+	struct input_dev *input_dev;
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *udev = interface_to_usbdev(intf);
-	char path[64];
 	int nRet;
 
 	dbg("%s - called", __FUNCTION__);
@@ -209,57 +209,55 @@
 	dbg("%s - setting endpoint", __FUNCTION__);
 	endpoint = &interface->endpoint[0].desc;
 
-	if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) {
+	mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!mtouch || !input_dev) {
 		err("%s - Out of memory.", __FUNCTION__);
-		return -ENOMEM;
+		goto fail1;
 	}
 
-	memset(mtouch, 0, sizeof(struct mtouch_usb));
-	mtouch->udev = udev;
-
 	dbg("%s - allocating buffers", __FUNCTION__);
-	if (mtouchusb_alloc_buffers(udev, mtouch)) {
-		mtouchusb_free_buffers(udev, mtouch);
-		kfree(mtouch);
-		return -ENOMEM;
-	}
+	if (mtouchusb_alloc_buffers(udev, mtouch))
+		goto fail2;
 
-	mtouch->input.private = mtouch;
-	mtouch->input.open = mtouchusb_open;
-	mtouch->input.close = mtouchusb_close;
-
-	usb_make_path(udev, path, 64);
-	sprintf(mtouch->phys, "%s/input0", path);
-
-	mtouch->input.name = mtouch->name;
-	mtouch->input.phys = mtouch->phys;
-	usb_to_input_id(udev, &mtouch->input.id);
-	mtouch->input.dev = &intf->dev;
-
-	mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-	mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-	/* Used to Scale Compensated Data and Flip Y */
-	mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC;
-	mtouch->input.absmax[ABS_X] = raw_coordinates ?
-					MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC;
-	mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
-	mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
-	mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC;
-	mtouch->input.absmax[ABS_Y] = raw_coordinates ?
-					MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC;
-	mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
-	mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
+	mtouch->udev = udev;
+	mtouch->input = input_dev;
 
 	if (udev->manufacturer)
-		strcat(mtouch->name, udev->manufacturer);
-	if (udev->product)
-		sprintf(mtouch->name, "%s %s", mtouch->name, udev->product);
+		strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name));
+
+	if (udev->product) {
+		if (udev->manufacturer)
+			strlcat(mtouch->name, " ", sizeof(mtouch->name));
+		strlcat(mtouch->name, udev->product, sizeof(mtouch->name));
+	}
 
 	if (!strlen(mtouch->name))
-		sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
-			mtouch->input.id.vendor, mtouch->input.id.product);
+		snprintf(mtouch->name, sizeof(mtouch->name),
+			"USB Touchscreen %04x:%04x",
+			le16_to_cpu(udev->descriptor.idVendor),
+			le16_to_cpu(udev->descriptor.idProduct));
+
+	usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys));
+	strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys));
+
+	input_dev->name = mtouch->name;
+	input_dev->phys = mtouch->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = mtouch;
+
+	input_dev->open = mtouchusb_open;
+	input_dev->close = mtouchusb_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC,
+		raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC,
+				MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT);
+	input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC,
+		raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC,
+		MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT);
 
 	nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
 			       MTOUCHUSB_RESET,
@@ -272,9 +270,7 @@
 	mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
 	if (!mtouch->irq) {
 		dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
-		mtouchusb_free_buffers(udev, mtouch);
-		kfree(mtouch);
-		return -ENOMEM;
+		goto fail2;
 	}
 
 	dbg("%s - usb_fill_int_urb", __FUNCTION__);
@@ -284,7 +280,7 @@
 			 mtouchusb_irq, mtouch, endpoint->bInterval);
 
 	dbg("%s - input_register_device", __FUNCTION__);
-	input_register_device(&mtouch->input);
+	input_register_device(mtouch->input);
 
 	nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
 			       MTOUCHUSB_ASYNC_REPORT,
@@ -293,10 +289,13 @@
 	dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
 	    __FUNCTION__, nRet);
 
-	printk(KERN_INFO "input: %s on %s\n", mtouch->name, path);
 	usb_set_intfdata(intf, mtouch);
-
 	return 0;
+
+fail2:	mtouchusb_free_buffers(udev, mtouch);
+fail1:	input_free_device(input_dev);
+	kfree(mtouch);
+	return -ENOMEM;
 }
 
 static void mtouchusb_disconnect(struct usb_interface *intf)
@@ -308,7 +307,7 @@
 	if (mtouch) {
 		dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
 		usb_kill_urb(mtouch->irq);
-		input_unregister_device(&mtouch->input);
+		input_unregister_device(mtouch->input);
 		usb_free_urb(mtouch->irq);
 		mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
 		kfree(mtouch);
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index acc71ec..dca5ee9 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -198,7 +198,7 @@
 		}
 
 		effect->id = id;
-		dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id);
+		dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d.\n", id);
 		pid_private->effects[id].owner = current->pid;
 		pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED);
 		spin_unlock_irqrestore(&pid_private->lock, flags);
@@ -262,6 +262,7 @@
 {
 	struct hid_ff_pid *private;
 	struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
+	struct input_dev *input_dev = hidinput->input;
 
 	private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
 	if (!private)
@@ -281,11 +282,12 @@
 	usb_fill_control_urb(private->urbffout, hid->dev, 0,
 			     (void *)&private->ffcr, private->ctrl_buffer, 8,
 			     hid_pid_ctrl_out, hid);
-	hidinput->input.upload_effect = hid_pid_upload_effect;
-	hidinput->input.flush = hid_pid_flush;
-	hidinput->input.ff_effects_max = 8;	// A random default
-	set_bit(EV_FF, hidinput->input.evbit);
-	set_bit(EV_FF_STATUS, hidinput->input.evbit);
+
+	input_dev->upload_effect = hid_pid_upload_effect;
+	input_dev->flush = hid_pid_flush;
+	input_dev->ff_effects_max = 8;	// A random default
+	set_bit(EV_FF, input_dev->evbit);
+	set_bit(EV_FF_STATUS, input_dev->evbit);
 
 	spin_lock_init(&private->lock);
 
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index ad4afe7..b747623 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -68,7 +68,7 @@
 	struct usb_ctrlrequest *configcr;
 	dma_addr_t configcr_dma;
 	struct usb_device *udev;
-	struct input_dev input;
+	struct input_dev *input;
 	spinlock_t lock;
 	int static_brightness;
 	int pulse_speed;
@@ -106,10 +106,10 @@
 	}
 
 	/* handle updates to device state */
-	input_regs(&pm->input, regs);
-	input_report_key(&pm->input, BTN_0, pm->data[0] & 0x01);
-	input_report_rel(&pm->input, REL_DIAL, pm->data[1]);
-	input_sync(&pm->input);
+	input_regs(pm->input, regs);
+	input_report_key(pm->input, BTN_0, pm->data[0] & 0x01);
+	input_report_rel(pm->input, REL_DIAL, pm->data[1]);
+	input_sync(pm->input);
 
 exit:
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -153,10 +153,10 @@
 
 		   Only values of 'arg' quite close to 255 are particularly useful/spectacular.
 		*/
-		if (pm->pulse_speed < 255){
+		if (pm->pulse_speed < 255) {
 			op = 0;                   // divide
 			arg = 255 - pm->pulse_speed;
-		} else if (pm->pulse_speed > 255){
+		} else if (pm->pulse_speed > 255) {
 			op = 2;                   // multiply
 			arg = pm->pulse_speed - 255;
 		} else {
@@ -166,11 +166,11 @@
 		pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE );
 		pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op );
 		pm->requires_update &= ~UPDATE_PULSE_MODE;
-	}else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS){
+	} else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) {
 		pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS );
 		pm->configcr->wIndex = cpu_to_le16( pm->static_brightness );
 		pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS;
-	}else{
+	} else {
 		printk(KERN_ERR "powermate: unknown update required");
 		pm->requires_update = 0; /* fudge the bug */
 		return;
@@ -228,19 +228,19 @@
 	spin_lock_irqsave(&pm->lock, flags);
 
 	/* mark state updates which are required */
-	if (static_brightness != pm->static_brightness){
+	if (static_brightness != pm->static_brightness) {
 		pm->static_brightness = static_brightness;
 		pm->requires_update |= UPDATE_STATIC_BRIGHTNESS;
 	}
-	if (pulse_asleep != pm->pulse_asleep){
+	if (pulse_asleep != pm->pulse_asleep) {
 		pm->pulse_asleep = pulse_asleep;
 		pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS);
 	}
-	if (pulse_awake != pm->pulse_awake){
+	if (pulse_awake != pm->pulse_awake) {
 		pm->pulse_awake = pulse_awake;
 		pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS);
 	}
-	if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table){
+	if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) {
 		pm->pulse_speed = pulse_speed;
 		pm->pulse_table = pulse_table;
 		pm->requires_update |= UPDATE_PULSE_MODE;
@@ -283,6 +283,7 @@
 				    SLAB_ATOMIC, &pm->data_dma);
 	if (!pm->data)
 		return -1;
+
 	pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
 					SLAB_ATOMIC, &pm->configcr_dma);
 	if (!pm->configcr)
@@ -308,8 +309,9 @@
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct powermate_device *pm;
+	struct input_dev *input_dev;
 	int pipe, maxp;
-	char path[64];
+	int err = -ENOMEM;
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
@@ -323,42 +325,61 @@
 		0, interface->desc.bInterfaceNumber, NULL, 0,
 		USB_CTRL_SET_TIMEOUT);
 
-	if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL)))
-		return -ENOMEM;
+	pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!pm || !input_dev)
+		goto fail1;
 
-	memset(pm, 0, sizeof(struct powermate_device));
-	pm->udev = udev;
-
-	if (powermate_alloc_buffers(udev, pm)) {
-		powermate_free_buffers(udev, pm);
-		kfree(pm);
-		return -ENOMEM;
-	}
+	if (powermate_alloc_buffers(udev, pm))
+		goto fail2;
 
 	pm->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!pm->irq) {
-		powermate_free_buffers(udev, pm);
-		kfree(pm);
-		return -ENOMEM;
-	}
+	if (!pm->irq)
+		goto fail2;
 
 	pm->config = usb_alloc_urb(0, GFP_KERNEL);
-	if (!pm->config) {
-		usb_free_urb(pm->irq);
-		powermate_free_buffers(udev, pm);
-		kfree(pm);
-		return -ENOMEM;
-	}
+	if (!pm->config)
+		goto fail3;
+
+	pm->udev = udev;
+	pm->input = input_dev;
+
+	usb_make_path(udev, pm->phys, sizeof(pm->phys));
+	strlcpy(pm->phys, "/input0", sizeof(pm->phys));
 
 	spin_lock_init(&pm->lock);
-	init_input_dev(&pm->input);
+
+	switch (le16_to_cpu(udev->descriptor.idProduct)) {
+	case POWERMATE_PRODUCT_NEW:
+		input_dev->name = pm_name_powermate;
+		break;
+	case POWERMATE_PRODUCT_OLD:
+		input_dev->name = pm_name_soundknob;
+		break;
+	default:
+		input_dev->name = pm_name_soundknob;
+		printk(KERN_WARNING "powermate: unknown product id %04x\n",
+		       le16_to_cpu(udev->descriptor.idProduct));
+	}
+
+	input_dev->phys = pm->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = pm;
+
+	input_dev->event = powermate_input_event;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
+	input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+	input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
+	input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
 
 	/* get a handle to the interrupt data pipe */
 	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
 
-	if(maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX){
-		printk("powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
+	if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) {
+		printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
 			POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp);
 		maxp = POWERMATE_PAYLOAD_SIZE_MAX;
 	}
@@ -371,35 +392,11 @@
 
 	/* register our interrupt URB with the USB system */
 	if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
-		powermate_free_buffers(udev, pm);
-		kfree(pm);
-		return -EIO; /* failure */
+		err = -EIO;
+		goto fail4;
 	}
 
-	switch (le16_to_cpu(udev->descriptor.idProduct)) {
-	case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break;
-	case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break;
-	default:
-		pm->input.name = pm_name_soundknob;
-		printk(KERN_WARNING "powermate: unknown product id %04x\n",
-		       le16_to_cpu(udev->descriptor.idProduct));
-	}
-
-	pm->input.private = pm;
-	pm->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC);
-	pm->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
-	pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
-	pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
-	usb_to_input_id(udev, &pm->input.id);
-	pm->input.event = powermate_input_event;
-	pm->input.dev = &intf->dev;
-	pm->input.phys = pm->phys;
-
-	input_register_device(&pm->input);
-
-	usb_make_path(udev, path, 64);
-	snprintf(pm->phys, 64, "%s/input0", path);
-	printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys);
+	input_register_device(pm->input);
 
 	/* force an update of everything */
 	pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -407,6 +404,13 @@
 
 	usb_set_intfdata(intf, pm);
 	return 0;
+
+fail4:	usb_free_urb(pm->config);
+fail3:	usb_free_urb(pm->irq);
+fail2:	powermate_free_buffers(udev, pm);
+fail1:	input_free_device(input_dev);
+	kfree(pm);
+	return err;
 }
 
 /* Called when a USB device we've accepted ownership of is removed */
@@ -418,7 +422,7 @@
 	if (pm) {
 		pm->requires_update = 0;
 		usb_kill_urb(pm->irq);
-		input_unregister_device(&pm->input);
+		input_unregister_device(pm->input);
 		usb_free_urb(pm->irq);
 		usb_free_urb(pm->config);
 		powermate_free_buffers(interface_to_usbdev(intf), pm);
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 4276c24..0043e6e 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -68,14 +68,16 @@
 	dma_addr_t data_dma;
 	struct urb *irq;
 	struct usb_device *udev;
-	struct input_dev input;
+	struct input_dev *input;
 	char name[128];
 	char phys[64];
 };
 
 static struct usb_device_id touchkit_devices[] = {
 	{USB_DEVICE(0x3823, 0x0001)},
+	{USB_DEVICE(0x0123, 0x0001)},
 	{USB_DEVICE(0x0eef, 0x0001)},
+	{USB_DEVICE(0x0eef, 0x0002)},
 	{}
 };
 
@@ -115,12 +117,12 @@
 		y = TOUCHKIT_GET_Y(touchkit->data);
 	}
 
-	input_regs(&touchkit->input, regs);
-	input_report_key(&touchkit->input, BTN_TOUCH,
+	input_regs(touchkit->input, regs);
+	input_report_key(touchkit->input, BTN_TOUCH,
 	                 TOUCHKIT_GET_TOUCHED(touchkit->data));
-	input_report_abs(&touchkit->input, ABS_X, x);
-	input_report_abs(&touchkit->input, ABS_Y, y);
-	input_sync(&touchkit->input);
+	input_report_abs(touchkit->input, ABS_X, x);
+	input_report_abs(touchkit->input, ABS_Y, y);
+	input_sync(touchkit->input);
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -171,87 +173,81 @@
 static int touchkit_probe(struct usb_interface *intf,
 			  const struct usb_device_id *id)
 {
-	int ret;
 	struct touchkit_usb *touchkit;
+	struct input_dev *input_dev;
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *udev = interface_to_usbdev(intf);
-	char path[64];
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
 
-	touchkit = kmalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
-	if (!touchkit)
-		return -ENOMEM;
-
-	memset(touchkit, 0, sizeof(struct touchkit_usb));
-	touchkit->udev = udev;
-
-	if (touchkit_alloc_buffers(udev, touchkit)) {
-		ret = -ENOMEM;
+	touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!touchkit || !input_dev)
 		goto out_free;
-	}
 
-	touchkit->input.private = touchkit;
-	touchkit->input.open = touchkit_open;
-	touchkit->input.close = touchkit_close;
-
-	usb_make_path(udev, path, 64);
-	sprintf(touchkit->phys, "%s/input0", path);
-
-	touchkit->input.name = touchkit->name;
-	touchkit->input.phys = touchkit->phys;
-	usb_to_input_id(udev, &touchkit->input.id);
-	touchkit->input.dev = &intf->dev;
-
-	touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-	touchkit->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
-	touchkit->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-	/* Used to Scale Compensated Data */
-	touchkit->input.absmin[ABS_X] = TOUCHKIT_MIN_XC;
-	touchkit->input.absmax[ABS_X] = TOUCHKIT_MAX_XC;
-	touchkit->input.absfuzz[ABS_X] = TOUCHKIT_XC_FUZZ;
-	touchkit->input.absflat[ABS_X] = TOUCHKIT_XC_FLAT;
-	touchkit->input.absmin[ABS_Y] = TOUCHKIT_MIN_YC;
-	touchkit->input.absmax[ABS_Y] = TOUCHKIT_MAX_YC;
-	touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ;
-	touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT;
-
-	if (udev->manufacturer)
-		strcat(touchkit->name, udev->manufacturer);
-	if (udev->product)
-		sprintf(touchkit->name, "%s %s", touchkit->name, udev->product);
-
-	if (!strlen(touchkit->name))
-		sprintf(touchkit->name, "USB Touchscreen %04x:%04x",
-		        touchkit->input.id.vendor, touchkit->input.id.product);
+	if (touchkit_alloc_buffers(udev, touchkit))
+		goto out_free;
 
 	touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
 	if (!touchkit->irq) {
 		dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
-		ret = -ENOMEM;
 		goto out_free_buffers;
 	}
 
+	touchkit->udev = udev;
+	touchkit->input = input_dev;
+
+	if (udev->manufacturer)
+		strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name));
+
+	if (udev->product) {
+		if (udev->manufacturer)
+			strlcat(touchkit->name, " ", sizeof(touchkit->name));
+		strlcat(touchkit->name, udev->product, sizeof(touchkit->name));
+	}
+
+	if (!strlen(touchkit->name))
+		snprintf(touchkit->name, sizeof(touchkit->name),
+			"USB Touchscreen %04x:%04x",
+			 le16_to_cpu(udev->descriptor.idVendor),
+			 le16_to_cpu(udev->descriptor.idProduct));
+
+	usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys));
+	strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys));
+
+	input_dev->name = touchkit->name;
+	input_dev->phys = touchkit->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = touchkit;
+	input_dev->open = touchkit_open;
+	input_dev->close = touchkit_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC,
+				TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT);
+	input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC,
+				TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT);
+
 	usb_fill_int_urb(touchkit->irq, touchkit->udev,
-	                 usb_rcvintpipe(touchkit->udev, 0x81),
-	                 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
-	                 touchkit_irq, touchkit, endpoint->bInterval);
+			 usb_rcvintpipe(touchkit->udev, 0x81),
+			 touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
+			 touchkit_irq, touchkit, endpoint->bInterval);
 
-	input_register_device(&touchkit->input);
+	input_register_device(touchkit->input);
 
-	printk(KERN_INFO "input: %s on %s\n", touchkit->name, path);
 	usb_set_intfdata(intf, touchkit);
-
 	return 0;
 
 out_free_buffers:
 	touchkit_free_buffers(udev, touchkit);
 out_free:
+	input_free_device(input_dev);
 	kfree(touchkit);
-	return ret;
+	return -ENOMEM;
 }
 
 static void touchkit_disconnect(struct usb_interface *intf)
@@ -265,8 +261,8 @@
 
 	dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__);
 	usb_set_intfdata(intf, NULL);
-	input_unregister_device(&touchkit->input);
 	usb_kill_urb(touchkit->irq);
+	input_unregister_device(touchkit->input);
 	usb_free_urb(touchkit->irq);
 	touchkit_free_buffers(interface_to_usbdev(intf), touchkit);
 	kfree(touchkit);
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 28987f1..226b6f9 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -66,7 +66,7 @@
 };
 
 struct usb_kbd {
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct usb_device *usbdev;
 	unsigned char old[8];
 	struct urb *irq, *led;
@@ -99,29 +99,29 @@
 		goto resubmit;
 	}
 
-	input_regs(&kbd->dev, regs);
+	input_regs(kbd->dev, regs);
 
 	for (i = 0; i < 8; i++)
-		input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
+		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
 
 	for (i = 2; i < 8; i++) {
 
 		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
 			if (usb_kbd_keycode[kbd->old[i]])
-				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
+				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
 			else
 				info("Unknown key (scancode %#x) released.", kbd->old[i]);
 		}
 
 		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
 			if (usb_kbd_keycode[kbd->new[i]])
-				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
+				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
 			else
 				info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
 		}
 	}
 
-	input_sync(&kbd->dev);
+	input_sync(kbd->dev);
 
 	memcpy(kbd->old, kbd->new, 8);
 
@@ -227,12 +227,12 @@
 static int usb_kbd_probe(struct usb_interface *iface,
 			 const struct usb_device_id *id)
 {
-	struct usb_device * dev = interface_to_usbdev(iface);
+	struct usb_device *dev = interface_to_usbdev(iface);
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_kbd *kbd;
+	struct input_dev *input_dev;
 	int i, pipe, maxp;
-	char path[64];
 
 	interface = iface->cur_altsetting;
 
@@ -240,37 +240,59 @@
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80))
+	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
 		return -ENODEV;
-	if ((endpoint->bmAttributes & 3) != 3)
+	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-	if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL)))
-		return -ENOMEM;
-	memset(kbd, 0, sizeof(struct usb_kbd));
+	kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!kbd || !input_dev)
+		goto fail1;
 
-	if (usb_kbd_alloc_mem(dev, kbd)) {
-		usb_kbd_free_mem(dev, kbd);
-		kfree(kbd);
-		return -ENOMEM;
-	}
+	if (usb_kbd_alloc_mem(dev, kbd))
+		goto fail2;
 
 	kbd->usbdev = dev;
+	kbd->dev = input_dev;
 
-	kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-	kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
+	if (dev->manufacturer)
+		strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
+
+	if (dev->product) {
+		if (dev->manufacturer)
+			strlcat(kbd->name, " ", sizeof(kbd->name));
+		strlcat(kbd->name, dev->product, sizeof(kbd->name));
+	}
+
+	if (!strlen(kbd->name))
+		snprintf(kbd->name, sizeof(kbd->name),
+			 "USB HIDBP Keyboard %04x:%04x",
+			 le16_to_cpu(dev->descriptor.idVendor),
+			 le16_to_cpu(dev->descriptor.idProduct));
+
+	usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
+	strlcpy(kbd->phys, "/input0", sizeof(kbd->phys));
+
+	input_dev->name = kbd->name;
+	input_dev->phys = kbd->phys;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->cdev.dev = &iface->dev;
+	input_dev->private = kbd;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+	input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
 
 	for (i = 0; i < 255; i++)
-		set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
-	clear_bit(0, kbd->dev.keybit);
+		set_bit(usb_kbd_keycode[i], input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
 
-	kbd->dev.private = kbd;
-	kbd->dev.event = usb_kbd_event;
-	kbd->dev.open = usb_kbd_open;
-	kbd->dev.close = usb_kbd_close;
+	input_dev->event = usb_kbd_event;
+	input_dev->open = usb_kbd_open;
+	input_dev->close = usb_kbd_close;
 
 	usb_fill_int_urb(kbd->irq, dev, pipe,
 			 kbd->new, (maxp > 8 ? 8 : maxp),
@@ -284,37 +306,22 @@
 	kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
 	kbd->cr->wLength = cpu_to_le16(1);
 
-	usb_make_path(dev, path, 64);
-	sprintf(kbd->phys, "%s/input0", path);
-
-	kbd->dev.name = kbd->name;
-	kbd->dev.phys = kbd->phys;
-	usb_to_input_id(dev, &kbd->dev.id);
-	kbd->dev.dev = &iface->dev;
-
-	if (dev->manufacturer)
-		strcat(kbd->name, dev->manufacturer);
-	if (dev->product)
-		sprintf(kbd->name, "%s %s", kbd->name, dev->product);
-
-	if (!strlen(kbd->name))
-		sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
-			kbd->dev.id.vendor, kbd->dev.id.product);
-
 	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
 			     (void *) kbd->cr, kbd->leds, 1,
 			     usb_kbd_led, kbd);
 	kbd->led->setup_dma = kbd->cr_dma;
 	kbd->led->transfer_dma = kbd->leds_dma;
-	kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
-				| URB_NO_SETUP_DMA_MAP);
+	kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
-	input_register_device(&kbd->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
+	input_register_device(kbd->dev);
 
 	usb_set_intfdata(iface, kbd);
 	return 0;
+
+fail2:	usb_kbd_free_mem(dev, kbd);
+fail1:	input_free_device(input_dev);
+	kfree(kbd);
+	return -ENOMEM;
 }
 
 static void usb_kbd_disconnect(struct usb_interface *intf)
@@ -324,7 +331,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (kbd) {
 		usb_kill_urb(kbd->irq);
-		input_unregister_device(&kbd->dev);
+		input_unregister_device(kbd->dev);
 		usb_kbd_free_mem(interface_to_usbdev(intf), kbd);
 		kfree(kbd);
 	}
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 4104dec..230f6b1 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -50,7 +50,7 @@
 	char name[128];
 	char phys[64];
 	struct usb_device *usbdev;
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct urb *irq;
 
 	signed char *data;
@@ -61,7 +61,7 @@
 {
 	struct usb_mouse *mouse = urb->context;
 	signed char *data = mouse->data;
-	struct input_dev *dev = &mouse->dev;
+	struct input_dev *dev = mouse->dev;
 	int status;
 
 	switch (urb->status) {
@@ -115,14 +115,14 @@
 	usb_kill_urb(mouse->irq);
 }
 
-static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
+static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
-	struct usb_device * dev = interface_to_usbdev(intf);
+	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_mouse *mouse;
+	struct input_dev *input_dev;
 	int pipe, maxp;
-	char path[64];
 
 	interface = intf->cur_altsetting;
 
@@ -130,59 +130,62 @@
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80))
+	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
 		return -ENODEV;
-	if ((endpoint->bmAttributes & 3) != 3)
+	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL)))
-		return -ENOMEM;
-	memset(mouse, 0, sizeof(struct usb_mouse));
+	mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!mouse || !input_dev)
+		goto fail1;
 
 	mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
-	if (!mouse->data) {
-		kfree(mouse);
-		return -ENOMEM;
-	}
+	if (!mouse->data)
+		goto fail1;
 
 	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!mouse->irq) {
-		usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
-		kfree(mouse);
-		return -ENODEV;
-	}
+	if (!mouse->irq)
+		goto fail2;
 
 	mouse->usbdev = dev;
-
-	mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-	mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-	mouse->dev.relbit[0] |= BIT(REL_WHEEL);
-
-	mouse->dev.private = mouse;
-	mouse->dev.open = usb_mouse_open;
-	mouse->dev.close = usb_mouse_close;
-
-	usb_make_path(dev, path, 64);
-	sprintf(mouse->phys, "%s/input0", path);
-
-	mouse->dev.name = mouse->name;
-	mouse->dev.phys = mouse->phys;
-	usb_to_input_id(dev, &mouse->dev.id);
-	mouse->dev.dev = &intf->dev;
+	mouse->dev = input_dev;
 
 	if (dev->manufacturer)
-		strcat(mouse->name, dev->manufacturer);
-	if (dev->product)
-		sprintf(mouse->name, "%s %s", mouse->name, dev->product);
+		strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
+
+	if (dev->product) {
+		if (dev->manufacturer)
+			strlcat(mouse->name, " ", sizeof(mouse->name));
+		strlcat(mouse->name, dev->product, sizeof(mouse->name));
+	}
 
 	if (!strlen(mouse->name))
-		sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
-			mouse->dev.id.vendor, mouse->dev.id.product);
+		snprintf(mouse->name, sizeof(mouse->name),
+			 "USB HIDBP Mouse %04x:%04x",
+			 le16_to_cpu(dev->descriptor.idVendor),
+			 le16_to_cpu(dev->descriptor.idProduct));
+
+	usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
+	strlcat(mouse->phys, "/input0", sizeof(mouse->phys));
+
+	input_dev->name = mouse->name;
+	input_dev->phys = mouse->phys;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+	input_dev->relbit[0] |= BIT(REL_WHEEL);
+
+	input_dev->private = mouse;
+	input_dev->open = usb_mouse_open;
+	input_dev->close = usb_mouse_close;
 
 	usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
 			 (maxp > 8 ? 8 : maxp),
@@ -190,11 +193,15 @@
 	mouse->irq->transfer_dma = mouse->data_dma;
 	mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(&mouse->dev);
-	printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
+	input_register_device(mouse->dev);
 
 	usb_set_intfdata(intf, mouse);
 	return 0;
+
+fail2:	usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
+fail1:	input_free_device(input_dev);
+	kfree(mouse);
+	return -ENOMEM;
 }
 
 static void usb_mouse_disconnect(struct usb_interface *intf)
@@ -204,7 +211,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (mouse) {
 		usb_kill_urb(mouse->irq);
-		input_unregister_device(&mouse->dev);
+		input_unregister_device(mouse->dev);
 		usb_free_urb(mouse->irq);
 		usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
 		kfree(mouse);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index 3b266af..ea0f757 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -111,7 +111,7 @@
 struct wacom {
 	signed char *data;
 	dma_addr_t data_dma;
-	struct input_dev dev;
+	struct input_dev *dev;
 	struct usb_device *usbdev;
 	struct urb *irq;
 	struct wacom_features *features;
@@ -135,7 +135,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	int prox, pressure;
 	int retval;
 
@@ -225,7 +225,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	int retval;
 
 	switch (urb->status) {
@@ -275,7 +275,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	int retval;
 
 	switch (urb->status) {
@@ -318,7 +318,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	int x, y;
 	int retval;
 
@@ -397,7 +397,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	int idx;
 
 	/* tool number */
@@ -479,7 +479,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	unsigned int t;
 
 	/* general pen packet */
@@ -509,7 +509,7 @@
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
+	struct input_dev *dev = wacom->dev;
 	unsigned int t;
 	int idx;
 	int retval;
@@ -738,95 +738,83 @@
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_endpoint_descriptor *endpoint;
-	char rep_data[2] = {0x02, 0x02};
 	struct wacom *wacom;
-	char path[64];
+	struct input_dev *input_dev;
+	char rep_data[2] = {0x02, 0x02};
 
-	if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL)))
-		return -ENOMEM;
-	memset(wacom, 0, sizeof(struct wacom));
+	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!wacom || !input_dev)
+		goto fail1;
 
 	wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
-	if (!wacom->data) {
-		kfree(wacom);
-		return -ENOMEM;
-	}
+	if (!wacom->data)
+		goto fail1;
 
 	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!wacom->irq) {
-		usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
-		kfree(wacom);
-		return -ENOMEM;
-	}
+	if (!wacom->irq)
+		goto fail2;
+
+	wacom->usbdev = dev;
+	wacom->dev = input_dev;
+	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
 	wacom->features = wacom_features + (id - wacom_ids);
+	if (wacom->features->pktlen > 10)
+		BUG();
 
-	wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
-	wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-	wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+	input_dev->name = wacom->features->name;
+	usb_to_input_id(dev, &input_dev->id);
+
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = wacom;
+	input_dev->open = wacom_open;
+	input_dev->close = wacom_close;
+
+	input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+	input_set_abs_params(input_dev, ABS_X, 0, wacom->features->y_max, 4, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
 
 	switch (wacom->features->type) {
 		case GRAPHIRE:
-			wacom->dev.evbit[0] |= BIT(EV_REL);
-			wacom->dev.relbit[0] |= BIT(REL_WHEEL);
-			wacom->dev.absbit[0] |= BIT(ABS_DISTANCE);
-			wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+			input_dev->evbit[0] |= BIT(EV_REL);
+			input_dev->relbit[0] |= BIT(REL_WHEEL);
+			input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+			input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
 			break;
 
 		case INTUOS3:
 		case CINTIQ:
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-			wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
-			wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY);
+			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+			input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+			input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+			input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
 			/* fall through */
 
 		case INTUOS:
-			wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
-			wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
-			wacom->dev.relbit[0] |= BIT(REL_WHEEL);
-			wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE)	| BIT(BTN_TOOL_BRUSH)
+			input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
+			input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+			input_dev->relbit[0] |= BIT(REL_WHEEL);
+			input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE)	| BIT(BTN_TOOL_BRUSH)
 							  | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
-			wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE);
+			input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+			input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+			input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+			input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+			input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
 			break;
 
 		case PL:
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
 			break;
 	}
 
-	wacom->dev.absmax[ABS_X] = wacom->features->x_max;
-	wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
-	wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
-	wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
-	wacom->dev.absmax[ABS_TILT_X] = 127;
-	wacom->dev.absmax[ABS_TILT_Y] = 127;
-	wacom->dev.absmax[ABS_WHEEL] = 1023;
-
-	wacom->dev.absmax[ABS_RX] = 4097;
-	wacom->dev.absmax[ABS_RY] = 4097;
-	wacom->dev.absmin[ABS_RZ] = -900;
-	wacom->dev.absmax[ABS_RZ] = 899;
-	wacom->dev.absmin[ABS_THROTTLE] = -1023;
-	wacom->dev.absmax[ABS_THROTTLE] = 1023;
-
-	wacom->dev.absfuzz[ABS_X] = 4;
-	wacom->dev.absfuzz[ABS_Y] = 4;
-
-	wacom->dev.private = wacom;
-	wacom->dev.open = wacom_open;
-	wacom->dev.close = wacom_close;
-
-	usb_make_path(dev, path, 64);
-	sprintf(wacom->phys, "%s/input0", path);
-
-	wacom->dev.name = wacom->features->name;
-	wacom->dev.phys = wacom->phys;
-	usb_to_input_id(dev, &wacom->dev.id);
-	wacom->dev.dev = &intf->dev;
-	wacom->usbdev = dev;
-
 	endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
 	if (wacom->features->pktlen > 10)
@@ -839,18 +827,20 @@
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	input_register_device(&wacom->dev);
+	input_register_device(wacom->dev);
 
 	/* ask the tablet to report tablet data */
 	usb_set_report(intf, 3, 2, rep_data, 2);
 	/* repeat once (not sure why the first call often fails) */
 	usb_set_report(intf, 3, 2, rep_data, 2);
 
-	printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
-
 	usb_set_intfdata(intf, wacom);
-
 	return 0;
+
+fail2:	usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
+fail1:	input_free_device(input_dev);
+	kfree(wacom);
+	return -ENOMEM;
 }
 
 static void wacom_disconnect(struct usb_interface *intf)
@@ -860,7 +850,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (wacom) {
 		usb_kill_urb(wacom->irq);
-		input_unregister_device(&wacom->dev);
+		input_unregister_device(wacom->dev);
 		usb_free_urb(wacom->irq);
 		usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma);
 		kfree(wacom);
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 18125e0..43112f0 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -103,7 +103,7 @@
 MODULE_DEVICE_TABLE (usb, xpad_table);
 
 struct usb_xpad {
-	struct input_dev dev;			/* input device interface */
+	struct input_dev *dev;			/* input device interface */
 	struct usb_device *udev;		/* usb device */
 
 	struct urb *irq_in;			/* urb for interrupt in report */
@@ -125,7 +125,7 @@
 
 static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, struct pt_regs *regs)
 {
-	struct input_dev *dev = &xpad->dev;
+	struct input_dev *dev = xpad->dev;
 
 	input_regs(dev, regs);
 
@@ -214,9 +214,9 @@
 static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev (intf);
-	struct usb_xpad *xpad = NULL;
+	struct usb_xpad *xpad;
+	struct input_dev *input_dev;
 	struct usb_endpoint_descriptor *ep_irq_in;
-	char path[64];
 	int i;
 
 	for (i = 0; xpad_device[i].idVendor; i++) {
@@ -225,29 +225,63 @@
 			break;
 	}
 
-	if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) {
-		err("cannot allocate memory for new pad");
-		return -ENOMEM;
-	}
-	memset(xpad, 0, sizeof(struct usb_xpad));
+	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!xpad || !input_dev)
+		goto fail1;
 
 	xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
 				       SLAB_ATOMIC, &xpad->idata_dma);
-	if (!xpad->idata) {
-		kfree(xpad);
-		return -ENOMEM;
-	}
+	if (!xpad->idata)
+		goto fail1;
 
 	xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
-        if (!xpad->irq_in) {
-		err("cannot allocate memory for new pad irq urb");
-		usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
-                kfree(xpad);
-		return -ENOMEM;
-        }
+	if (!xpad->irq_in)
+		goto fail2;
+
+	xpad->udev = udev;
+	xpad->dev = input_dev;
+	usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+	strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
+
+	input_dev->name = xpad_device[i].name;
+	input_dev->phys = xpad->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = xpad;
+	input_dev->open = xpad_open;
+	input_dev->close = xpad_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	for (i = 0; xpad_btn[i] >= 0; i++)
+		set_bit(xpad_btn[i], input_dev->keybit);
+
+	for (i = 0; xpad_abs[i] >= 0; i++) {
+
+		signed short t = xpad_abs[i];
+
+		set_bit(t, input_dev->absbit);
+
+		switch (t) {
+			case ABS_X:
+			case ABS_Y:
+			case ABS_RX:
+			case ABS_RY:	/* the two sticks */
+				input_set_abs_params(input_dev, t, -32768, 32767, 16, 128);
+				break;
+			case ABS_Z:
+			case ABS_RZ:	/* the triggers */
+				input_set_abs_params(input_dev, t, 0, 255, 0, 0);
+				break;
+			case ABS_HAT0X:
+			case ABS_HAT0Y:	/* the d-pad */
+				input_set_abs_params(input_dev, t, -1, 1, 0, 0);
+				break;
+		}
+	}
 
 	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
-
 	usb_fill_int_urb(xpad->irq_in, udev,
 			 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
 			 xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
@@ -255,59 +289,16 @@
 	xpad->irq_in->transfer_dma = xpad->idata_dma;
 	xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	xpad->udev = udev;
-
-	usb_to_input_id(udev, &xpad->dev.id);
-	xpad->dev.dev = &intf->dev;
-	xpad->dev.private = xpad;
-	xpad->dev.name = xpad_device[i].name;
-	xpad->dev.phys = xpad->phys;
-	xpad->dev.open = xpad_open;
-	xpad->dev.close = xpad_close;
-
-	usb_make_path(udev, path, 64);
-	snprintf(xpad->phys, 64,  "%s/input0", path);
-
-	xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-
-	for (i = 0; xpad_btn[i] >= 0; i++)
-		set_bit(xpad_btn[i], xpad->dev.keybit);
-
-	for (i = 0; xpad_abs[i] >= 0; i++) {
-
-		signed short t = xpad_abs[i];
-
-		set_bit(t, xpad->dev.absbit);
-
-		switch (t) {
-			case ABS_X:
-			case ABS_Y:
-			case ABS_RX:
-			case ABS_RY:	/* the two sticks */
-				xpad->dev.absmax[t] =  32767;
-				xpad->dev.absmin[t] = -32768;
-				xpad->dev.absflat[t] = 128;
-				xpad->dev.absfuzz[t] = 16;
-				break;
-			case ABS_Z:
-			case ABS_RZ:	/* the triggers */
-				xpad->dev.absmax[t] = 255;
-				xpad->dev.absmin[t] = 0;
-				break;
-			case ABS_HAT0X:
-			case ABS_HAT0Y:	/* the d-pad */
-				xpad->dev.absmax[t] =  1;
-				xpad->dev.absmin[t] = -1;
-				break;
-		}
-	}
-
-	input_register_device(&xpad->dev);
-
-	printk(KERN_INFO "input: %s on %s", xpad->dev.name, path);
+	input_register_device(xpad->dev);
 
 	usb_set_intfdata(intf, xpad);
 	return 0;
+
+fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+fail1:	input_free_device(input_dev);
+	kfree(xpad);
+	return -ENOMEM;
+
 }
 
 static void xpad_disconnect(struct usb_interface *intf)
@@ -317,7 +308,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (xpad) {
 		usb_kill_urb(xpad->irq_in);
-		input_unregister_device(&xpad->dev);
+		input_unregister_device(xpad->dev);
 		usb_free_urb(xpad->irq_in);
 		usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
 		kfree(xpad);
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 58a176e..f526aeb 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -54,6 +54,7 @@
 #include <linux/module.h>
 #include <linux/rwsem.h>
 #include <linux/usb.h>
+#include <linux/usb_input.h>
 
 #include "map_to_7segment.h"
 #include "yealink.h"
@@ -101,12 +102,12 @@
 };
 
 struct yealink_dev {
-	struct input_dev idev;		/* input device */
+	struct input_dev *idev;		/* input device */
 	struct usb_device *udev;	/* usb device */
 
 	/* irq input channel */
 	struct yld_ctl_packet	*irq_data;
-	dma_addr_t 		irq_dma;
+	dma_addr_t		irq_dma;
 	struct urb		*urb_irq;
 
 	/* control output channel */
@@ -237,7 +238,7 @@
  */
 static void report_key(struct yealink_dev *yld, int key, struct pt_regs *regs)
 {
-	struct input_dev *idev = &yld->idev;
+	struct input_dev *idev = yld->idev;
 
 	input_regs(idev, regs);
 	if (yld->key_code >= 0) {
@@ -809,8 +810,12 @@
 	}
         if (yld->urb_ctl)
 		usb_free_urb(yld->urb_ctl);
-        if (yld->idev.dev)
-		input_unregister_device(&yld->idev);
+        if (yld->idev) {
+		if (err)
+			input_free_device(yld->idev);
+		else
+			input_unregister_device(yld->idev);
+	}
 	if (yld->ctl_req)
 		usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)),
 				yld->ctl_req, yld->ctl_req_dma);
@@ -857,7 +862,7 @@
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct yealink_dev *yld;
-	char path[64];
+	struct input_dev *input_dev;
 	int ret, pipe, i;
 
 	i = usb_match(udev);
@@ -866,17 +871,21 @@
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80))
+	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
 		return -EIO;
-	if ((endpoint->bmAttributes & 3) != 3)
+	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
 		return -EIO;
 
-	if ((yld = kmalloc(sizeof(struct yealink_dev), GFP_KERNEL)) == NULL)
+	yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
+	if (!yld)
 		return -ENOMEM;
 
-	memset(yld, 0, sizeof(*yld));
 	yld->udev = udev;
 
+	yld->idev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return usb_cleanup(yld, -ENOMEM);
+
 	/* allocate usb buffers */
 	yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
 					SLAB_ATOMIC, &yld->irq_dma);
@@ -935,42 +944,37 @@
 	yld->urb_ctl->dev = udev;
 
 	/* find out the physical bus location */
-	if (usb_make_path(udev, path, sizeof(path)) > 0)
-		snprintf(yld->phys, sizeof(yld->phys)-1,  "%s/input0", path);
+	usb_make_path(udev, yld->phys, sizeof(yld->phys));
+	strlcat(yld->phys,  "/input0", sizeof(yld->phys));
 
 	/* register settings for the input device */
-	init_input_dev(&yld->idev);
-	yld->idev.private	= yld;
-	yld->idev.id.bustype	= BUS_USB;
-	yld->idev.id.vendor	= le16_to_cpu(udev->descriptor.idVendor);
-	yld->idev.id.product	= le16_to_cpu(udev->descriptor.idProduct);
-	yld->idev.id.version	= le16_to_cpu(udev->descriptor.bcdDevice);
-	yld->idev.dev		= &intf->dev;
-	yld->idev.name		= yld_device[i].name;
-	yld->idev.phys		= yld->phys;
-	/* yld->idev.event		= input_ev;	TODO */
-	yld->idev.open		= input_open;
-	yld->idev.close		= input_close;
+	input_dev->name = yld_device[i].name;
+	input_dev->phys = yld->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+
+	input_dev->private = yld;
+	input_dev->open = input_open;
+	input_dev->close = input_close;
+	/* input_dev->event = input_ev;	TODO */
 
 	/* register available key events */
-	yld->idev.evbit[0] = BIT(EV_KEY);
+	input_dev->evbit[0] = BIT(EV_KEY);
 	for (i = 0; i < 256; i++) {
 		int k = map_p1k_to_key(i);
 		if (k >= 0) {
-			set_bit(k & 0xff, yld->idev.keybit);
+			set_bit(k & 0xff, input_dev->keybit);
 			if (k >> 8)
-				set_bit(k >> 8, yld->idev.keybit);
+				set_bit(k >> 8, input_dev->keybit);
 		}
 	}
 
-	printk(KERN_INFO "input: %s on %s\n", yld->idev.name, path);
-
-	input_register_device(&yld->idev);
+	input_register_device(yld->idev);
 
 	usb_set_intfdata(intf, yld);
 
 	/* clear visible elements */
-	for (i=0; i<ARRAY_SIZE(lcdMap); i++)
+	for (i = 0; i < ARRAY_SIZE(lcdMap); i++)
 		setChar(yld, i, ' ');
 
 	/* display driver version on LCD line 3 */
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 6ca2fae..27b23c5 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -707,9 +707,8 @@
 };
 
 static struct usb_class_driver dabusb_class = {
-	.name =		"usb/dabusb%d",
+	.name =		"dabusb%d",
 	.fops =		&dabusb_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
 	.minor_base =	DABUSB_MINOR,
 };
 
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 20ac9e1..9fe2c27 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -119,7 +119,7 @@
 	int yplanesz;		/* Number of bytes in the Y plane */
 	unsigned int buttonsts:1;
 #ifdef CONFIG_INPUT
-	struct input_dev input;
+	struct input_dev *input;
 	char input_physname[64];
 #endif
 };
@@ -218,6 +218,57 @@
 	konicawc_camera_on(uvd);
 }
 
+#ifdef CONFIG_INPUT
+
+static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev)
+{
+	struct input_dev *input_dev;
+
+	usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
+	strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
+
+	cam->input = input_dev = input_allocate_device();
+	if (!input_dev) {
+		warn("Not enough memory for camera's input device\n");
+		return;
+	}
+
+	input_dev->name = "Konicawc snapshot button";
+	input_dev->phys = cam->input_physname;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->cdev.dev = &dev->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY);
+	input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+	input_dev->private = cam;
+
+	input_register_device(cam->input);
+}
+
+static void konicawc_unregister_input(struct konicawc *cam)
+{
+	if (cam->input) {
+		input_unregister_device(cam->input);
+		cam->input = NULL;
+	}
+}
+
+static void konicawc_report_buttonstat(struct konicawc *cam)
+{
+	if (cam->input) {
+		input_report_key(cam->input, BTN_0, cam->buttonsts);
+		input_sync(cam->input);
+	}
+}
+
+#else
+
+static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { }
+static inline void konicawc_unregister_input(struct konicawc *cam) { }
+static inline void konicawc_report_buttonstat(struct konicawc *cam) { }
+
+#endif /* CONFIG_INPUT */
 
 static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb)
 {
@@ -273,10 +324,7 @@
 		if(button != cam->buttonsts) {
 			DEBUG(2, "button: %sclicked", button ? "" : "un");
 			cam->buttonsts = button;
-#ifdef CONFIG_INPUT
-			input_report_key(&cam->input, BTN_0, cam->buttonsts);
-			input_sync(&cam->input);
-#endif
+			konicawc_report_buttonstat(cam);
 		}
 
 		if(sts == 0x01) { /* drop frame */
@@ -645,9 +693,9 @@
 	RingQueue_Flush(&uvd->dp);
 	cam->lastframe = -2;
 	if(uvd->curframe != -1) {
-	  uvd->frame[uvd->curframe].curline = 0;
-	  uvd->frame[uvd->curframe].seqRead_Length = 0;
-	  uvd->frame[uvd->curframe].seqRead_Index = 0;
+		uvd->frame[uvd->curframe].curline = 0;
+		uvd->frame[uvd->curframe].seqRead_Length = 0;
+		uvd->frame[uvd->curframe].seqRead_Index = 0;
 	}
 
 	konicawc_start_data(uvd);
@@ -718,7 +766,6 @@
 	DEBUG(1, "setting initial values");
 }
 
-
 static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -839,21 +886,8 @@
 			err("usbvideo_RegisterVideoDevice() failed.");
 			uvd = NULL;
 		}
-#ifdef CONFIG_INPUT
-		/* Register input device for button */
-		memset(&cam->input, 0, sizeof(struct input_dev));
-		cam->input.name = "Konicawc snapshot button";
-		cam->input.private = cam;
-		cam->input.evbit[0] = BIT(EV_KEY);
-		cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
-		usb_to_input_id(dev, &cam->input.id);
-		input_register_device(&cam->input);
-		
-		usb_make_path(dev, cam->input_physname, 56);
-		strcat(cam->input_physname, "/input0");
-		cam->input.phys = cam->input_physname;
-		info("konicawc: %s on %s\n", cam->input.name, cam->input.phys);
-#endif
+
+		konicawc_register_input(cam, dev);
 	}
 
 	if (uvd) {
@@ -869,10 +903,9 @@
 	int i;
 	struct konicawc *cam = (struct konicawc *)uvd->user_data;
 
-#ifdef CONFIG_INPUT
-	input_unregister_device(&cam->input);
-#endif
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+	konicawc_unregister_input(cam);
+
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 		usb_free_urb(cam->sts_urb[i]);
 		cam->sts_urb[i] = NULL;
 	}
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index ae4681f..5f33f7c 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -1873,9 +1873,8 @@
 };
 
 static struct usb_class_driver auerswald_class = {
-	.name =		"usb/auer%d",
+	.name =		"auer%d",
 	.fops =		&auerswald_fops,
-	.mode =		S_IFCHR | S_IRUGO | S_IWUGO,
 	.minor_base =	AUER_MINOR_BASE,
 };
 
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 733acc2..1dc3e0f 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -105,11 +105,10 @@
 	.release = idmouse_release,
 };
 
-/* class driver information for devfs */
+/* class driver information */
 static struct usb_class_driver idmouse_class = {
-	.name = "usb/idmouse%d",
+	.name = "idmouse%d",
 	.fops = &idmouse_fops,
-	.mode = S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, /* filemode (char, 444) */
 	.minor_base = USB_IDMOUSE_MINOR_BASE,
 };
 
@@ -320,20 +319,8 @@
 		return -ENODEV;
 	}
 
-	if (*ppos >= IMGSIZE) {
-		up (&dev->sem);
-		return 0;
-	}
-
-	count = min ((loff_t)count, IMGSIZE - (*ppos));
-
-	if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) {
-		result = -EFAULT;
-	} else {
-		result = count;
-		*ppos += count;
-	}
-
+	result = simple_read_from_buffer(buffer, count, ppos,
+					dev->bulk_in_buffer, IMGSIZE);
 	/* unlock the device */
 	up(&dev->sem);
 	return result;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 7d06105..2703e20 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -271,12 +271,11 @@
 
 /*
  * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
+ * and to have the device registered with the driver core
  */
 static struct usb_class_driver tower_class = {
-	.name =		"usb/legousbtower%d",
+	.name =		"legousbtower%d",
 	.fops =		&tower_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
 	.minor_base =	LEGO_USB_TOWER_MINOR_BASE,
 };
 
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 26f77e2..7d02d8e 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -443,9 +443,8 @@
 };
 
 static struct usb_class_driver usb_rio_class = {
-	.name =		"usb/rio500%d",
+	.name =		"rio500%d",
 	.fops =		&usb_rio_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
 	.minor_base =	RIO_MINOR,
 };
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 39db315..c946c9a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2440,7 +2440,7 @@
 sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
 {
 	int ret = 0, slot = sisusb->font_slot, i;
-	struct font_desc *myfont;
+	const struct font_desc *myfont;
 	u8 *tempbuf;
 	u16 *tempbufb;
 	size_t written;
@@ -3239,12 +3239,7 @@
 };
 
 static struct usb_class_driver usb_sisusb_class = {
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
-	.name =		"usb/sisusbvga%d",
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-#else
 	.name =		"sisusbvga%d",
-#endif
 	.fops =		&usb_sisusb_fops,
 	.minor_base =	SISUSB_MINOR
 };
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 096ab30..85f3725 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -251,13 +251,12 @@
 };
 
 /*
- *  * usb class driver info in order to get a minor number from the usb core,
- *   * and to have the device registered with devfs and the driver core
- *    */
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
 static struct usb_class_driver lcd_class = {
-        .name =         "usb/lcd%d",
+        .name =         "lcd%d",
         .fops =         &lcd_fops,
-        .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
         .minor_base =   USBLCD_MINOR,
 };
 
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 54799eb..2997f55 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -9,7 +9,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 
 #include <linux/usb.h>
 
@@ -381,7 +381,6 @@
 	sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL);
 	if (!sg)
 		return NULL;
-	memset (sg, 0, nents * sizeof *sg);
 
 	for (i = 0; i < nents; i++) {
 		char		*buf;
@@ -394,9 +393,7 @@
 		memset (buf, 0, size);
 
 		/* kmalloc pages are always physically contiguous! */
-		sg [i].page = virt_to_page (buf);
-		sg [i].offset = offset_in_page (buf);
-		sg [i].length = size;
+		sg_init_one(&sg[i], buf, size);
 
 		if (vary) {
 			size += vary;
@@ -983,6 +980,7 @@
 		reqp->number = i % NUM_SUBCASES;
 		reqp->expected = expected;
 		u->setup_packet = (char *) &reqp->setup;
+		u->transfer_flags |= URB_NO_SETUP_DMA_MAP;
 
 		u->context = &context;
 		u->complete = ctrl_complete;
@@ -1948,21 +1946,11 @@
 
 static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
 {
-	struct usbtest_dev	*dev = usb_get_intfdata (intf);
-
-	down (&dev->sem);
-	intf->dev.power.power_state = PMSG_SUSPEND;
-	up (&dev->sem);
 	return 0;
 }
 
 static int usbtest_resume (struct usb_interface *intf)
 {
-	struct usbtest_dev	*dev = usb_get_intfdata (intf);
-
-	down (&dev->sem);
-	intf->dev.power.power_state = PMSG_ON;
-	up (&dev->sem);
 	return 0;
 }
 
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 03fb70e..0592cb5 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -137,7 +137,7 @@
 
 static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
 							 __u8 request, __u8 requesttype, __u16 value, __u16 index,
-							 unsigned int mem_flags)
+							 gfp_t mem_flags)
 {
 	struct usb_device *usbdev;
 	struct uss720_async_request *rq;
@@ -204,7 +204,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, gfp_t mem_flags)
 {
 	struct parport_uss720_private *priv;
 	struct uss720_async_request *rq;
@@ -238,7 +238,7 @@
 	return -EIO;
 }
 
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, gfp_t mem_flags)
 {
 	struct parport_uss720_private *priv;
 	struct uss720_async_request *rq;
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 508a210..c34944c 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -11,6 +11,7 @@
 #include <linux/usb.h>
 #include <linux/debugfs.h>
 #include <linux/smp_lock.h>
+#include <linux/notifier.h>
 
 #include "usb_mon.h"
 #include "../core/hcd.h"
@@ -205,6 +206,23 @@
 	up(&mon_lock);
 }
 
+static int mon_notify(struct notifier_block *self, unsigned long action,
+		      void *dev)
+{
+	switch (action) {
+	case USB_BUS_ADD:
+		mon_bus_add(dev);
+		break;
+	case USB_BUS_REMOVE:
+		mon_bus_remove(dev);
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block mon_nb = {
+	.notifier_call = 	mon_notify,
+};
+
 /*
  * Ops
  */
@@ -212,8 +230,6 @@
 	.urb_submit =	mon_submit,
 	.urb_submit_error = mon_submit_error,
 	.urb_complete =	mon_complete,
-	.bus_add =	mon_bus_add,
-	.bus_remove =	mon_bus_remove,
 };
 
 /*
@@ -329,6 +345,8 @@
 	}
 	// MOD_INC_USE_COUNT(which_module?);
 
+	usb_register_notify(&mon_nb);
+
 	down(&usb_bus_list_lock);
 	list_for_each_entry (ubus, &usb_bus_list, bus_list) {
 		mon_bus_init(mondir, ubus);
@@ -342,6 +360,7 @@
 	struct mon_bus *mbus;
 	struct list_head *p;
 
+	usb_unregister_notify(&mon_nb);
 	usb_mon_deregister();
 
 	down(&mon_lock);
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index 8c010bb..efd6ca7 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -294,7 +294,7 @@
 	  This also supports some related device firmware, as used in some
 	  PDAs from Olympus and some cell phones from Motorola.
 
-	  If you install an alternate ROM image, such as the Linux 2.6 based
+	  If you install an alternate image, such as the Linux 2.6 based
 	  versions of OpenZaurus, you should no longer need to support this
 	  protocol.  Only the "eth-fd" or "net_fd" drivers in these devices
 	  really need this non-conformant variant of CDC Ethernet (or in
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 861f00a..252a34f 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -753,7 +753,7 @@
 }
 
 static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-					unsigned flags)
+					gfp_t flags)
 {
 	int padlen;
 	int headroom = skb_headroom(skb);
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index c8763ae..c0f263b 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -301,7 +301,7 @@
 }
 
 static struct sk_buff *
-genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
 	int 	padlen;
 	int	length = skb->len;
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index e04b0ce..6bef1be 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -469,7 +469,7 @@
 				0,
 				KAWETH_CONTROL_TIMEOUT);
 
-	udelay(10000);
+	mdelay(10);
 
 	kaweth_dbg("kaweth_reset() returns %d.",result);
 
@@ -477,13 +477,13 @@
 }
 
 static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
-static int kaweth_resubmit_rx_urb(struct kaweth_device *, unsigned);
+static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
 
 /****************************************************************
 	int_callback
 *****************************************************************/
 
-static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, int mf)
+static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
 {
 	int status;
 
@@ -550,7 +550,7 @@
  *     kaweth_resubmit_rx_urb
  ****************************************************************/
 static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
-						unsigned mem_flags)
+						gfp_t mem_flags)
 {
 	int result;
 
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index a4309c4..cee55f8 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -500,7 +500,7 @@
 }
 
 static struct sk_buff *
-net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
 	int			padlen;
 	struct sk_buff		*skb2;
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 6a4ffe6..537eb18 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -1384,7 +1384,6 @@
 		usb_kill_urb(pegasus->rx_urb);
 		usb_kill_urb(pegasus->intr_urb);
 	}
-	intf->dev.power.power_state = PMSG_SUSPEND;
 	return 0;
 }
 
@@ -1392,7 +1391,6 @@
 {
 	struct pegasus *pegasus = usb_get_intfdata(intf);
 
-	intf->dev.power.power_state = PMSG_ON;
 	netif_device_attach (pegasus->net);
 	if (netif_running(pegasus->net)) {
 		pegasus->rx_urb->status = 0;
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index b98f2a8..9fbd59b 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -181,6 +181,8 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
 		VENDOR_ADMTEK, 0x8511,
 		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 2ed2e5f..b5a925d 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -517,7 +517,7 @@
 }
 
 static struct sk_buff *
-rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
 	struct rndis_data_hdr	*hdr;
 	struct sk_buff		*skb2;
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index c3d4e35..787dd35 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -909,6 +909,7 @@
 	usb_set_intfdata(intf, NULL);
 	if (dev) {
 		set_bit(RTL8150_UNPLUG, &dev->flags);
+		tasklet_disable(&dev->tl);
 		unregister_netdev(dev->netdev);
 		unlink_all_urbs(dev);
 		free_all_urbs(dev);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 6c46091..74f05c9 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -288,7 +288,7 @@
 
 static void rx_complete (struct urb *urb, struct pt_regs *regs);
 
-static void rx_submit (struct usbnet *dev, struct urb *urb, unsigned flags)
+static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
 {
 	struct sk_buff		*skb;
 	struct skb_data		*entry;
@@ -1185,7 +1185,6 @@
 	netif_device_detach (dev->net);
 	(void) unlink_urbs (dev, &dev->rxq);
 	(void) unlink_urbs (dev, &dev->txq);
-	intf->dev.power.power_state = PMSG_SUSPEND;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_suspend);
@@ -1194,7 +1193,6 @@
 {
 	struct usbnet		*dev = usb_get_intfdata(intf);
 
-	intf->dev.power.power_state = PMSG_ON;
 	netif_device_attach (dev->net);
 	tasklet_schedule (&dev->bh);
 	return 0;
diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h
index 7aa0abd..89fc495 100644
--- a/drivers/usb/net/usbnet.h
+++ b/drivers/usb/net/usbnet.h
@@ -107,7 +107,7 @@
 
 	/* fixup tx packet (add framing) */
 	struct sk_buff	*(*tx_fixup)(struct usbnet *dev,
-				struct sk_buff *skb, unsigned flags);
+				struct sk_buff *skb, gfp_t flags);
 
 	/* for new devices, use the descriptor-reading code instead */
 	int		in;		/* rx endpoint */
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index ee3b892..5d4b7d5 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -62,7 +62,7 @@
  */
 
 static struct sk_buff *
-zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
 	int			padlen;
 	struct sk_buff		*skb2;
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index c4e479e..2f52261 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -521,7 +521,7 @@
 	int reqlen;
 	char seq=0;
 	struct urb *urb;
-	unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+	gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
 
 	len += 4;			/* first 4 are for header */
 
diff --git a/drivers/usb/serial/ChangeLog.old b/drivers/usb/serial/ChangeLog.old
new file mode 100644
index 0000000..c1b2799
--- /dev/null
+++ b/drivers/usb/serial/ChangeLog.old
@@ -0,0 +1,730 @@
+This is the contents of some of the drivers/usb/serial/ files that had  old
+changelog comments.  They were quite old, and out of date, and we don't keep
+them anymore, so I've put them here, away from the source files, in case
+people still care to see them.
+
+- Greg Kroah-Hartman <greg@kroah.com> October 20, 2005
+
+-----------------------------------------------------------------------
+usb-serial.h Change Log comments:
+
+ (03/26/2002) gkh
+	removed the port->tty check from port_paranoia_check() due to serial
+	consoles not having a tty device assigned to them.
+
+ (12/03/2001) gkh
+	removed active from the port structure.
+	added documentation to the usb_serial_device_type structure
+
+ (10/10/2001) gkh
+	added vendor and product to serial structure.  Needed to determine device
+	owner when the device is disconnected.
+
+ (05/30/2001) gkh
+	added sem to port structure and removed port_lock
+
+ (10/05/2000) gkh
+	Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
+	fix bug with urb->dev not being set properly, now that the usb core
+	needs it.
+
+ (09/11/2000) gkh
+	Added usb_serial_debug_data function to help get rid of #DEBUG in the
+	drivers.
+
+ (08/28/2000) gkh
+	Added port_lock to port structure.
+
+ (08/08/2000) gkh
+	Added open_count to port structure.
+
+ (07/23/2000) gkh
+	Added bulk_out_endpointAddress to port structure.
+
+ (07/19/2000) gkh, pberger, and borchers
+	Modifications to allow usb-serial drivers to be modules.
+
+-----------------------------------------------------------------------
+usb-serial.c Change Log comments:
+
+ (12/10/2002) gkh
+	Split the ports off into their own struct device, and added a
+	usb-serial bus driver.
+
+ (11/19/2002) gkh
+	removed a few #ifdefs for the generic code and cleaned up the failure
+	logic in initialization.
+
+ (10/02/2002) gkh
+	moved the console code to console.c and out of this file.
+
+ (06/05/2002) gkh
+	moved location of startup() call in serial_probe() until after all
+	of the port information and endpoints are initialized.  This makes
+	things easier for some drivers.
+
+ (04/10/2002) gkh
+	added serial_read_proc function which creates a
+	/proc/tty/driver/usb-serial file.
+
+ (03/27/2002) gkh
+	Got USB serial console code working properly and merged into the main
+	version of the tree.  Thanks to Randy Dunlap for the initial version
+	of this code, and for pushing me to finish it up.
+	The USB serial console works with any usb serial driver device.
+
+ (03/21/2002) gkh
+	Moved all manipulation of port->open_count into the core.  Now the
+	individual driver's open and close functions are called only when the
+	first open() and last close() is called.  Making the drivers a bit
+	smaller and simpler.
+	Fixed a bug if a driver didn't have the owner field set.
+
+ (02/26/2002) gkh
+	Moved all locking into the main serial_* functions, instead of having
+	the individual drivers have to grab the port semaphore.  This should
+	reduce races.
+	Reworked the MOD_INC logic a bit to always increment and decrement, even
+	if the generic driver is being used.
+
+ (10/10/2001) gkh
+	usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
+	help prevent child drivers from accessing the device since it is now
+	gone.
+
+ (09/13/2001) gkh
+	Moved generic driver initialize after we have registered with the USB
+	core.  Thanks to Randy Dunlap for pointing this problem out.
+
+ (07/03/2001) gkh
+	Fixed module paramater size.  Thanks to John Brockmeyer for the pointer.
+	Fixed vendor and product getting defined through the MODULE_PARM macro
+	if the Generic driver wasn't compiled in.
+	Fixed problem with generic_shutdown() not being called for drivers that
+	don't have a shutdown() function.
+
+ (06/06/2001) gkh
+	added evil hack that is needed for the prolific pl2303 device due to the
+	crazy way its endpoints are set up.
+
+ (05/30/2001) gkh
+	switched from using spinlock to a semaphore, which fixes lots of problems.
+
+ (04/08/2001) gb
+	Identify version on module load.
+
+ 2001_02_05 gkh
+	Fixed buffer overflows bug with the generic serial driver.  Thanks to
+	Todd Squires <squirest@ct0.com> for fixing this.
+
+ (01/10/2001) gkh
+	Fixed bug where the generic serial adaptor grabbed _any_ device that was
+	offered to it.
+
+ (12/12/2000) gkh
+	Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
+	moved them to the serial_open and serial_close functions.
+	Also fixed bug with there not being a MOD_DEC for the generic driver
+	(thanks to Gary Brubaker for finding this.)
+
+ (11/29/2000) gkh
+	Small NULL pointer initialization cleanup which saves a bit of disk image
+
+ (11/01/2000) Adam J. Richter
+	instead of using idVendor/idProduct pairs, usb serial drivers
+	now identify their hardware interest with usb_device_id tables,
+	which they usually have anyhow for use with MODULE_DEVICE_TABLE.
+
+ (10/05/2000) gkh
+	Fixed bug with urb->dev not being set properly, now that the usb
+	core needs it.
+
+ (09/11/2000) gkh
+	Removed DEBUG #ifdefs with call to usb_serial_debug_data
+
+ (08/28/2000) gkh
+	Added port_lock to port structure.
+	Added locks for SMP safeness to generic driver
+	Fixed the ability to open a generic device's port more than once.
+
+ (07/23/2000) gkh
+	Added bulk_out_endpointAddress to port structure.
+
+ (07/19/2000) gkh, pberger, and borchers
+	Modifications to allow usb-serial drivers to be modules.
+
+ (07/03/2000) gkh
+	Added more debugging to serial_ioctl call
+
+ (06/25/2000) gkh
+	Changed generic_write_bulk_callback to not call wake_up_interruptible
+	directly, but to have port_softint do it at a safer time.
+
+ (06/23/2000) gkh
+	Cleaned up debugging statements in a quest to find UHCI timeout bug.
+
+ (05/22/2000) gkh
+	Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
+	removed from the individual device source files.
+
+ (05/03/2000) gkh
+	Added the Digi Acceleport driver from Al Borchers and Peter Berger.
+
+ (05/02/2000) gkh
+	Changed devfs and tty register code to work properly now. This was based on
+	the ACM driver changes by Vojtech Pavlik.
+
+ (04/27/2000) Ryan VanderBijl
+ 	Put calls to *_paranoia_checks into one function.
+
+ (04/23/2000) gkh
+	Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
+	Moved when the startup code printed out the devices that are supported.
+
+ (04/19/2000) gkh
+	Added driver for ZyXEL omni.net lcd plus ISDN TA
+	Made startup info message specify which drivers were compiled in.
+
+ (04/03/2000) gkh
+	Changed the probe process to remove the module unload races.
+	Changed where the tty layer gets initialized to have devfs work nicer.
+	Added initial devfs support.
+
+ (03/26/2000) gkh
+	Split driver up into device specific pieces.
+
+ (03/19/2000) gkh
+	Fixed oops that could happen when device was removed while a program
+	was talking to the device.
+	Removed the static urbs and now all urbs are created and destroyed
+	dynamically.
+	Reworked the internal interface. Now everything is based on the
+	usb_serial_port structure instead of the larger usb_serial structure.
+	This fixes the bug that a multiport device could not have more than
+	one port open at one time.
+
+ (03/17/2000) gkh
+	Added config option for debugging messages.
+	Added patch for keyspan pda from Brian Warner.
+
+ (03/06/2000) gkh
+	Added the keyspan pda code from Brian Warner <warner@lothar.com>
+	Moved a bunch of the port specific stuff into its own structure. This
+	is in anticipation of the true multiport devices (there's a bug if you
+	try to access more than one port of any multiport device right now)
+
+ (02/21/2000) gkh
+	Made it so that any serial devices only have to specify which functions
+	they want to overload from the generic function calls (great,
+	inheritance in C, in a driver, just what I wanted...)
+	Added support for set_termios and ioctl function calls. No drivers take
+	advantage of this yet.
+	Removed the #ifdef MODULE, now there is no module specific code.
+	Cleaned up a few comments in usb-serial.h that were wrong (thanks again
+	to Miles Lott).
+	Small fix to get_free_serial.
+
+ (02/14/2000) gkh
+	Removed the Belkin and Peracom functionality from the driver due to
+	the lack of support from the vendor, and me not wanting people to
+	accidenatly buy the device, expecting it to work with Linux.
+	Added read_bulk_callback and write_bulk_callback to the type structure
+	for the needs of the FTDI and WhiteHEAT driver.
+	Changed all reverences to FTDI to FTDI_SIO at the request of Bill
+	Ryder.
+	Changed the output urb size back to the max endpoint size to make
+	the ftdi_sio driver have it easier, and due to the fact that it didn't
+	really increase the speed any.
+
+ (02/11/2000) gkh
+	Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
+	patch from Miles Lott (milos@insync.net).
+	Fixed bug with not restoring the minor range that a device grabs, if
+	the startup function fails (thanks Miles for finding this).
+
+ (02/05/2000) gkh
+	Added initial framework for the Keyspan PDA serial converter so that
+	Brian Warner has a place to put his code.
+	Made the ezusb specific functions generic enough that different
+	devices can use them (whiteheat and keyspan_pda both need them).
+	Split out a whole bunch of structure and other stuff to a separate
+	usb-serial.h file.
+	Made the Visor connection messages a little more understandable, now
+	that Miles Lott (milos@insync.net) has gotten the Generic channel to
+	work. Also made them always show up in the log file.
+
+ (01/25/2000) gkh
+	Added initial framework for FTDI serial converter so that Bill Ryder
+	has a place to put his code.
+	Added the vendor specific info from Handspring. Now we can print out
+	informational debug messages as well as understand what is happening.
+
+ (01/23/2000) gkh
+	Fixed problem of crash when trying to open a port that didn't have a
+	device assigned to it. Made the minor node finding a little smarter,
+	now it looks to find a continuous space for the new device.
+
+ (01/21/2000) gkh
+	Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
+	Fixed get_serial_by_minor which was all messed up for multi port
+	devices. Fixed multi port problem for generic devices. Now the number
+	of ports is determined by the number of bulk out endpoints for the
+	generic device.
+
+ (01/19/2000) gkh
+	Removed lots of cruft that was around from the old (pre urb) driver
+	interface.
+	Made the serial_table dynamic. This should save lots of memory when
+	the number of minor nodes goes up to 256.
+	Added initial support for devices that have more than one port.
+	Added more debugging comments for the Visor, and added a needed
+	set_configuration call.
+
+ (01/17/2000) gkh
+	Fixed the WhiteHEAT firmware (my processing tool had a bug)
+	and added new debug loader firmware for it.
+	Removed the put_char function as it isn't really needed.
+	Added visor startup commands as found by the Win98 dump.
+
+ (01/13/2000) gkh
+	Fixed the vendor id for the generic driver to the one I meant it to be.
+
+ (01/12/2000) gkh
+	Forget the version numbering...that's pretty useless...
+	Made the driver able to be compiled so that the user can select which
+	converter they want to use. This allows people who only want the Visor
+	support to not pay the memory size price of the WhiteHEAT.
+	Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
+	grabbed the root hub. Not good.
+
+ version 0.4.0 (01/10/2000) gkh
+	Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
+	device. Added startup function to allow firmware to be downloaded to
+	a device if it needs to be.
+	Added firmware download logic to the WhiteHEAT device.
+	Started to add #defines to split up the different drivers for potential
+	configuration option.
+
+ version 0.3.1 (12/30/99) gkh
+      Fixed problems with urb for bulk out.
+      Added initial support for multiple sets of endpoints. This enables
+      the Handspring Visor to be attached successfully. Only the first
+      bulk in / bulk out endpoint pair is being used right now.
+
+ version 0.3.0 (12/27/99) gkh
+	Added initial support for the Handspring Visor based on a patch from
+	Miles Lott (milos@sneety.insync.net)
+	Cleaned up the code a bunch and converted over to using urbs only.
+
+ version 0.2.3 (12/21/99) gkh
+	Added initial support for the Connect Tech WhiteHEAT converter.
+	Incremented the number of ports in expectation of getting the
+	WhiteHEAT to work properly (4 ports per connection).
+	Added notification on insertion and removal of what port the
+	device is/was connected to (and what kind of device it was).
+
+ version 0.2.2 (12/16/99) gkh
+	Changed major number to the new allocated number. We're legal now!
+
+ version 0.2.1 (12/14/99) gkh
+	Fixed bug that happens when device node is opened when there isn't a
+	device attached to it. Thanks to marek@webdesign.no for noticing this.
+
+ version 0.2.0 (11/10/99) gkh
+	Split up internals to make it easier to add different types of serial
+	converters to the code.
+	Added a "generic" driver that gets it's vendor and product id
+	from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
+	for the idea and sample code (from the usb scanner driver.)
+	Cleared up any licensing questions by releasing it under the GNU GPL.
+
+ version 0.1.2 (10/25/99) gkh
+ 	Fixed bug in detecting device.
+
+ version 0.1.1 (10/05/99) gkh
+ 	Changed the major number to not conflict with anything else.
+
+ version 0.1 (09/28/99) gkh
+ 	Can recognize the two different devices and start up a read from
+	device when asked to. Writes also work. No control signals yet, this
+	all is vendor specific data (i.e. no spec), also no control for
+	different baud rates or other bit settings.
+	Currently we are using the same devid as the acm driver. This needs
+	to change.
+
+-----------------------------------------------------------------------
+visor.c Change Log comments:
+
+ (06/03/2003) Judd Montgomery <judd at jpilot.org>
+     Added support for module parameter options for untested/unknown
+     devices.
+
+ (03/09/2003) gkh
+	Added support for the Sony Clie NZ90V device.  Thanks to Martin Brachtl
+	<brachtl@redgrep.cz> for the information.
+
+ (03/05/2003) gkh
+	Think Treo support is now working.
+
+ (04/03/2002) gkh
+	Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
+	<hiro@zob.ne.jp> for the information.
+
+ (03/27/2002) gkh
+	Removed assumptions that port->tty was always valid (is not true
+	for usb serial console devices.)
+
+ (03/23/2002) gkh
+	Added support for the Palm i705 device, thanks to Thomas Riemer
+	<tom@netmech.com> for the information.
+
+ (03/21/2002) gkh
+	Added support for the Palm m130 device, thanks to Udo Eisenbarth
+	<udo.eisenbarth@web.de> for the information.
+
+ (02/27/2002) gkh
+	Reworked the urb handling logic.  We have no more pool, but dynamically
+	allocate the urb and the transfer buffer on the fly.  In testing this
+	does not incure any measurable overhead.  This also relies on the fact
+	that we have proper reference counting logic for urbs.
+
+ (02/21/2002) SilaS
+  Added initial support for the Palm m515 devices.
+
+ (02/14/2002) gkh
+	Added support for the Clie S-360 device.
+
+ (12/18/2001) gkh
+	Added better Clie support for 3.5 devices.  Thanks to Geoffrey Levand
+	for the patch.
+
+ (11/11/2001) gkh
+	Added support for the m125 devices, and added check to prevent oopses
+	for Clié devices that lie about the number of ports they have.
+
+ (08/30/2001) gkh
+	Added support for the Clie devices, both the 3.5 and 4.0 os versions.
+	Many thanks to Daniel Burke, and Bryan Payne for helping with this.
+
+ (08/23/2001) gkh
+	fixed a few potential bugs pointed out by Oliver Neukum.
+
+ (05/30/2001) gkh
+	switched from using spinlock to a semaphore, which fixes lots of problems.
+
+ (05/28/2000) gkh
+	Added initial support for the Palm m500 and Palm m505 devices.
+
+ (04/08/2001) gb
+	Identify version on module load.
+
+ (01/21/2000) gkh
+	Added write_room and chars_in_buffer, as they were previously using the
+	generic driver versions which is all wrong now that we are using an urb
+	pool.  Thanks to Wolfgang Grandegger for pointing this out to me.
+	Removed count assignment in the write function, which was not needed anymore
+	either.  Thanks to Al Borchers for pointing this out.
+
+ (12/12/2000) gkh
+	Moved MOD_DEC to end of visor_close to be nicer, as the final write
+	message can sleep.
+
+ (11/12/2000) gkh
+	Fixed bug with data being dropped on the floor by forcing tty->low_latency
+	to be on.  Hopefully this fixes the OHCI issue!
+
+ (11/01/2000) Adam J. Richter
+	usb_device_id table support
+
+ (10/05/2000) gkh
+	Fixed bug with urb->dev not being set properly, now that the usb
+	core needs it.
+
+ (09/11/2000) gkh
+	Got rid of always calling kmalloc for every urb we wrote out to the
+	device.
+	Added visor_read_callback so we can keep track of bytes in and out for
+	those people who like to know the speed of their device.
+	Removed DEBUG #ifdefs with call to usb_serial_debug_data
+
+ (09/06/2000) gkh
+	Fixed oops in visor_exit.  Need to uncomment usb_unlink_urb call _after_
+	the host controller drivers set urb->dev = NULL when the urb is finished.
+
+ (08/28/2000) gkh
+	Added locks for SMP safeness.
+
+ (08/08/2000) gkh
+	Fixed endian problem in visor_startup.
+	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+	than once.
+
+ (07/23/2000) gkh
+	Added pool of write urbs to speed up transfers to the visor.
+
+ (07/19/2000) gkh
+	Added module_init and module_exit functions to handle the fact that this
+	driver is a loadable module now.
+
+ (07/03/2000) gkh
+	Added visor_set_ioctl and visor_set_termios functions (they don't do much
+	of anything, but are good for debugging.)
+
+ (06/25/2000) gkh
+	Fixed bug in visor_unthrottle that should help with the disconnect in PPP
+	bug that people have been reporting.
+
+ (06/23/2000) gkh
+	Cleaned up debugging statements in a quest to find UHCI timeout bug.
+
+ (04/27/2000) Ryan VanderBijl
+ 	Fixed memory leak in visor_close
+
+ (03/26/2000) gkh
+	Split driver up into device specific pieces.
+
+-----------------------------------------------------------------------
+pl2303.c Change Log comments:
+
+ 2002_Mar_26 gkh
+	allowed driver to work properly if there is no tty assigned to a port
+	(this happens for serial console devices.)
+
+ 2001_Oct_06 gkh
+	Added RTS and DTR line control.  Thanks to joe@bndlg.de for parts of it.
+
+ 2001_Sep_19 gkh
+	Added break support.
+
+ 2001_Aug_30 gkh
+	fixed oops in write_bulk_callback.
+
+ 2001_Aug_28 gkh
+	reworked buffer logic to be like other usb-serial drivers.  Hopefully
+	removing some reported problems.
+
+ 2001_Jun_06 gkh
+	finished porting to 2.4 format.
+
+
+-----------------------------------------------------------------------
+io_edgeport.c Change Log comments:
+
+ 2003_04_03 al borchers
+  - fixed a bug (that shows up with dosemu) where the tty struct is
+    used in a callback after it has been freed
+
+ 2.3 2002_03_08 greg kroah-hartman
+	- fixed bug when multiple devices were attached at the same time.
+
+ 2.2 2001_11_14 greg kroah-hartman
+	- fixed bug in edge_close that kept the port from being used more
+	  than once.
+	- fixed memory leak on device removal.
+	- fixed potential double free of memory when command urb submitting
+	  failed.
+	- other small cleanups when the device is removed
+
+ 2.1 2001_07_09 greg kroah-hartman
+	- added support for TIOCMBIS and TIOCMBIC.
+
+     (04/08/2001) gb
+	- Identify version on module load.
+
+ 2.0 2001_03_05 greg kroah-hartman
+	- reworked entire driver to fit properly in with the other usb-serial
+	  drivers.  Occasional oopses still happen, but it's a good start.
+
+ 1.2.3 (02/23/2001) greg kroah-hartman
+	- changed device table to work properly for 2.4.x final format.
+	- fixed problem with dropping data at high data rates.
+
+ 1.2.2 (11/27/2000) greg kroah-hartman
+	- cleaned up more NTisms.
+	- Added device table for 2.4.0-test11
+
+ 1.2.1 (11/08/2000) greg kroah-hartman
+	- Started to clean up NTisms.
+	- Fixed problem with dev field of urb for kernels >= 2.4.0-test9
+
+ 1.2 (10/17/2000) David Iacovelli
+ 	Remove all EPIC code and GPL source
+  Fix RELEVANT_IFLAG macro to include flow control
+  changes port configuration changes.
+  Fix redefinition of SERIAL_MAGIC
+  Change all timeout values to 5 seconds
+  Tried to fix the UHCI multiple urb submission, but failed miserably.
+  it seems to work fine with OHCI.
+  ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must
+    find a way to work arount this UHCI bug )
+
+ 1.1 (10/11/2000) David Iacovelli
+  Fix XON/XOFF flow control to support both IXON and IXOFF
+
+ 0.9.27 (06/30/2000) David Iacovelli
+  Added transmit queue and now allocate urb for command writes.
+
+ 0.9.26 (06/29/2000) David Iacovelli
+  Add support for 80251 based edgeport
+
+ 0.9.25 (06/27/2000) David Iacovelli
+  Do not close the port if it has multiple opens.
+
+ 0.9.24 (05/26/2000) David Iacovelli
+  Add IOCTLs to support RXTX and JAVA POS
+  and first cut at running BlackBox Demo
+
+ 0.9.23 (05/24/2000) David Iacovelli
+  Add IOCTLs to support RXTX and JAVA POS
+
+ 0.9.22 (05/23/2000) David Iacovelli
+  fixed bug in enumeration.  If epconfig turns on mapping by
+  path after a device is already plugged in, we now update
+  the mapping correctly
+
+ 0.9.21 (05/16/2000) David Iacovelli
+  Added BlockUntilChaseResp() to also wait for txcredits
+  Updated the way we allocate and handle write URBs
+	Add debug code to dump buffers
+
+ 0.9.20 (05/01/2000) David Iacovelli
+	change driver to use usb/tts/
+
+ 0.9.19 (05/01/2000) David Iacovelli
+  Update code to compile if DEBUG is off
+
+ 0.9.18 (04/28/2000) David Iacovelli
+  cleanup and test tty_register with devfs
+
+ 0.9.17 (04/27/2000) greg kroah-hartman
+ 	changed tty_register around to be like the way it
+ 	was before, but now it works properly with devfs.
+
+ 0.9.16 (04/26/2000) david iacovelli
+  Fixed bug in GetProductInfo()
+
+ 0.9.15 (04/25/2000) david iacovelli
+	Updated enumeration
+
+ 0.9.14 (04/24/2000) david iacovelli
+  Removed all config/status IOCTLS and
+  converted to using /proc/edgeport
+  still playing with devfs
+
+ 0.9.13 (04/24/2000) david iacovelli
+  Removed configuration based on ttyUSB0
+  Added support for configuration using /prod/edgeport
+  first attempt at using devfs (not working yet!)
+  Added IOCTL to GetProductInfo()
+  Added support for custom baud rates
+	Add support for random port numbers
+
+ 0.9.12 (04/18/2000) david iacovelli
+	added additional configuration IOCTLs
+  use ttyUSB0 for configuration
+
+ 0.9.11 (04/17/2000) greg kroah-hartman
+	fixed module initialization race conditions.
+	made all urbs dynamically allocated.
+	made driver devfs compatible. now it only registers the tty device
+	when the device is actually plugged in.
+
+ 0.9.10 (04/13/2000) greg kroah-hartman
+	added proc interface framework.
+
+ 0.9.9 (04/13/2000) david iacovelli
+	added enumeration code and ioctls to configure the device
+
+ 0.9.8 (04/12/2000) david iacovelli
+  Change interrupt read start when device is plugged in
+  and stop when device is removed
+	process interrupt reads when all ports are closed
+  (keep value of rxBytesAvail consistent with the edgeport)
+  set the USB_BULK_QUEUE flag so that we can shove a bunch
+  of urbs at once down the pipe
+
+ 0.9.7 (04/10/2000) david iacovelli
+ 	start to add enumeration code.
+  generate serial number for epic devices
+  add support for kdb
+
+ 0.9.6 (03/30/2000) david iacovelli
+  add IOCTL to get string, manufacture, and boot descriptors
+
+ 0.9.5 (03/14/2000) greg kroah-hartman
+	more error checking added to SerialOpen to try to fix UHCI open problem
+
+ 0.9.4 (03/09/2000) greg kroah-hartman
+	added more error checking to handle oops when data is hanging
+	around and tty is abruptly closed.
+
+ 0.9.3 (03/09/2000) david iacovelli
+	Add epic support for xon/xoff chars
+	play with performance
+
+ 0.9.2 (03/08/2000) greg kroah-hartman
+	changed most "info" calls to "dbg"
+	implemented flow control properly in the termios call
+
+ 0.9.1 (03/08/2000) david iacovelli
+	added EPIC support
+	enabled bootloader update
+
+ 0.9 (03/08/2000) greg kroah-hartman
+	Release to IO networks.
+	Integrated changes that David made
+  made getting urbs for writing SMP safe
+
+ 0.8 (03/07/2000) greg kroah-hartman
+	Release to IO networks.
+	Fixed problems that were seen in code by David.
+  Now both Edgeport/4 and Edgeport/2 works properly.
+  Changed most of the functions to use port instead of serial.
+
+ 0.7 (02/27/2000) greg kroah-hartman
+	Milestone 3 release.
+	Release to IO Networks
+	ioctl for waiting on line change implemented.
+	ioctl for getting statistics implemented.
+	multiport support working.
+	lsr and msr registers are now handled properly.
+	change break now hooked up and working.
+	support for all known Edgeport devices.
+
+ 0.6 (02/22/2000) greg kroah-hartman
+	Release to IO networks.
+	CHASE is implemented correctly when port is closed.
+	SerialOpen now blocks correctly until port is fully opened.
+
+ 0.5 (02/20/2000) greg kroah-hartman
+	Release to IO networks.
+	Known problems:
+		modem status register changes are not sent on to the user
+		CHASE is not implemented when the port is closed.
+
+ 0.4 (02/16/2000) greg kroah-hartman
+	Second cut at the CeBit demo.
+	Doesn't leak memory on every write to the port
+	Still small leaks on startup.
+	Added support for Edgeport/2 and Edgeport/8
+
+ 0.3 (02/15/2000) greg kroah-hartman
+	CeBit demo release.
+	Force the line settings to 4800, 8, 1, e for the demo.
+	Warning! This version leaks memory like crazy!
+
+ 0.2 (01/30/2000) greg kroah-hartman
+	Milestone 1 release.
+	Device is found by USB subsystem, enumerated, fimware is downloaded
+	and the descriptors are printed to the debug log, config is set, and
+	green light starts to blink. Open port works, and data can be sent
+	and received at the default settings of the UART. Loopback connector
+	and debug log confirms this.
+
+ 0.1 (01/23/2000) greg kroah-hartman
+	Initial release to help IO Networks try to set up their test system.
+	Edgeport4 is recognized, firmware is downloaded, config is set so
+	device blinks green light every 3 sec. Port is bound, but opening,
+	closing, and sending data do not work properly.
+
+
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 9438909..7b5e8e4 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -394,6 +394,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mct_u232.
 
+config USB_SERIAL_NOKIA_DKU2
+	tristate "USB Nokia DKU2 Driver"
+	depends on USB_SERIAL
+	help
+	  Say Y here if you want to use a Nokia DKU2 device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called nokia_dku2.
+
 config USB_SERIAL_PL2303
 	tristate "USB Prolific 2303 Single Port Serial Driver"
 	depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 6c7cdcc..55fd461 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -31,6 +31,7 @@
 obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)		+= kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)		+= mct_u232.o
+obj-$(CONFIG_USB_SERIAL_NOKIA_DKU2)		+= nokia_dku2.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)		+= omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)			+= option.o
 obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 926d4c2..1f29d88 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -30,9 +30,11 @@
 	.id_table =	id_table,
 };
 
-static struct usb_serial_device_type airprime_device = {
-	.owner =		THIS_MODULE,
-	.name =			"airprime",
+static struct usb_serial_driver airprime_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"airprime",
+	},
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index abb1b2c..84bc0ee 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -121,10 +121,12 @@
 };
 
 /* All of the device info needed for the serial converters */
-static struct usb_serial_device_type belkin_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Belkin / Peracom / GoHubs USB Serial Adapter",
-	.short_name =		"belkin",
+static struct usb_serial_driver belkin_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"belkin",
+	},
+	.description =		"Belkin / Peracom / GoHubs USB Serial Adapter",
 	.id_table =		id_table_combined,
 	.num_interrupt_in =	1,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 2f612c2..664139a 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -18,7 +18,7 @@
 
 static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
 {
-	struct usb_serial_device_type *driver;
+	struct usb_serial_driver *driver;
 	const struct usb_serial_port *port;
 
 	/*
@@ -44,7 +44,7 @@
 
 static int usb_serial_device_probe (struct device *dev)
 {
-	struct usb_serial_device_type *driver;
+	struct usb_serial_driver *driver;
 	struct usb_serial_port *port;
 	int retval = 0;
 	int minor;
@@ -57,13 +57,13 @@
 
 	driver = port->serial->type;
 	if (driver->port_probe) {
-		if (!try_module_get(driver->owner)) {
+		if (!try_module_get(driver->driver.owner)) {
 			dev_err(dev, "module get failed, exiting\n");
 			retval = -EIO;
 			goto exit;
 		}
 		retval = driver->port_probe (port);
-		module_put(driver->owner);
+		module_put(driver->driver.owner);
 		if (retval)
 			goto exit;
 	}
@@ -72,7 +72,7 @@
 	tty_register_device (usb_serial_tty_driver, minor, dev);
 	dev_info(&port->serial->dev->dev, 
 		 "%s converter now attached to ttyUSB%d\n",
-		 driver->name, minor);
+		 driver->description, minor);
 
 exit:
 	return retval;
@@ -80,7 +80,7 @@
 
 static int usb_serial_device_remove (struct device *dev)
 {
-	struct usb_serial_device_type *driver;
+	struct usb_serial_driver *driver;
 	struct usb_serial_port *port;
 	int retval = 0;
 	int minor;
@@ -92,43 +92,38 @@
 
 	driver = port->serial->type;
 	if (driver->port_remove) {
-		if (!try_module_get(driver->owner)) {
+		if (!try_module_get(driver->driver.owner)) {
 			dev_err(dev, "module get failed, exiting\n");
 			retval = -EIO;
 			goto exit;
 		}
 		retval = driver->port_remove (port);
-		module_put(driver->owner);
+		module_put(driver->driver.owner);
 	}
 exit:
 	minor = port->number;
 	tty_unregister_device (usb_serial_tty_driver, minor);
 	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
-		 driver->name, minor);
+		 driver->description, minor);
 
 	return retval;
 }
 
-int usb_serial_bus_register(struct usb_serial_device_type *device)
+int usb_serial_bus_register(struct usb_serial_driver *driver)
 {
 	int retval;
 
-	if (device->short_name)
-		device->driver.name = (char *)device->short_name;
-	else
-		device->driver.name = (char *)device->name;
-	device->driver.bus = &usb_serial_bus_type;
-	device->driver.probe = usb_serial_device_probe;
-	device->driver.remove = usb_serial_device_remove;
-	device->driver.owner = device->owner;
+	driver->driver.bus = &usb_serial_bus_type;
+	driver->driver.probe = usb_serial_device_probe;
+	driver->driver.remove = usb_serial_device_remove;
 
-	retval = driver_register(&device->driver);
+	retval = driver_register(&driver->driver);
 
 	return retval;
 }
 
-void usb_serial_bus_deregister(struct usb_serial_device_type *device)
+void usb_serial_bus_deregister(struct usb_serial_driver *driver)
 {
-	driver_unregister (&device->driver);
+	driver_unregister(&driver->driver);
 }
 
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 97c78c2..c5334dd 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -67,15 +67,17 @@
 
 static struct usb_driver cp2101_driver = {
 	.owner		= THIS_MODULE,
-	.name		= "CP2101",
+	.name		= "cp2101",
 	.probe		= usb_serial_probe,
 	.disconnect	= usb_serial_disconnect,
 	.id_table	= id_table,
 };
 
-static struct usb_serial_device_type cp2101_device = {
-	.owner			= THIS_MODULE,
-	.name			= "CP2101",
+static struct usb_serial_driver cp2101_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name = 	"cp2101",
+	},
 	.id_table		= id_table,
 	.num_interrupt_in	= 0,
 	.num_bulk_in		= 0,
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index b5b4310..e581e4a 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -83,10 +83,12 @@
 	.id_table =	id_table,
 };
 
-static struct usb_serial_device_type cyberjack_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Reiner SCT Cyberjack USB card reader",
-	.short_name =		"cyberjack",
+static struct usb_serial_driver cyberjack_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"cyberjack",
+	},
+	.description =		"Reiner SCT Cyberjack USB card reader",
 	.id_table =		id_table,
 	.num_interrupt_in =	1,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 9ee1aaf..af9290e 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -176,10 +176,12 @@
 static unsigned int	  cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
 
 
-static struct usb_serial_device_type cypress_earthmate_device = {
-	.owner =			THIS_MODULE,
-	.name =				"DeLorme Earthmate USB",
-	.short_name =			"earthmate",
+static struct usb_serial_driver cypress_earthmate_device = {
+	.driver = {
+		.owner =		THIS_MODULE,
+		.name =			"earthmate",
+	},
+	.description =			"DeLorme Earthmate USB",
 	.id_table =			id_table_earthmate,
 	.num_interrupt_in = 		1,
 	.num_interrupt_out =		1,
@@ -203,10 +205,12 @@
 	.write_int_callback =		cypress_write_int_callback,
 };
 
-static struct usb_serial_device_type cypress_hidcom_device = {
-	.owner =			THIS_MODULE,
-	.name =				"HID->COM RS232 Adapter",
-	.short_name =			"cyphidcom",
+static struct usb_serial_driver cypress_hidcom_device = {
+	.driver = {
+		.owner =		THIS_MODULE,
+		.name =			"cyphidcom",
+	},
+	.description =			"HID->COM RS232 Adapter",
 	.id_table =			id_table_cyphidcomrs232,
 	.num_interrupt_in =		1,
 	.num_interrupt_out =		1,
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index a19a47f..dc74644 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -503,10 +503,12 @@
 
 /* device info needed for the Digi serial converter */
 
-static struct usb_serial_device_type digi_acceleport_2_device = {
-	.owner =			THIS_MODULE,
-	.name =				"Digi 2 port USB adapter",
-	.short_name =			"digi_2",
+static struct usb_serial_driver digi_acceleport_2_device = {
+	.driver = {
+		.owner =		THIS_MODULE,
+		.name =			"digi_2",
+	},
+	.description =			"Digi 2 port USB adapter",
 	.id_table =			id_table_2,
 	.num_interrupt_in =		0,
 	.num_bulk_in =			4,
@@ -530,10 +532,12 @@
 	.shutdown =			digi_shutdown,
 };
 
-static struct usb_serial_device_type digi_acceleport_4_device = {
-	.owner =			THIS_MODULE,
-	.name =				"Digi 4 port USB adapter",
-	.short_name =			"digi_4",
+static struct usb_serial_driver digi_acceleport_4_device = {
+	.driver = {
+		.owner =		THIS_MODULE,
+		.name =			"digi_4",
+	},
+	.description =			"Digi 4 port USB adapter",
 	.id_table =			id_table_4,
 	.num_interrupt_in =		0,
 	.num_bulk_in =			5,
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 8d562ab..0b0546d 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -112,9 +112,11 @@
 	.id_table =	id_table,
 };
 
-static struct usb_serial_device_type empeg_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Empeg",
+static struct usb_serial_driver empeg_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"empeg",
+	},
 	.id_table =		id_table,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 5a8631c..61204bf 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -411,6 +411,8 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
 	/*
 	 * These will probably use user-space drivers.  Uncomment them if
 	 * you need them or use the user-specified vendor/product module
@@ -428,7 +430,6 @@
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
-	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
 	/* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
@@ -471,6 +472,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
 	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -558,10 +562,12 @@
 static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
 static __u32 ftdi_232bm_baud_to_divisor (int baud);
 
-static struct usb_serial_device_type ftdi_sio_device = {
-	.owner =		THIS_MODULE,
-	.name =			"FTDI USB Serial Device",
-	.short_name =		"ftdi_sio",
+static struct usb_serial_driver ftdi_sio_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"ftdi_sio",
+	},
+	.description =		"FTDI USB Serial Device",
 	.id_table =		id_table_combined,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 2c35d74..ddb63df 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -199,6 +199,19 @@
 #define FTDI_PIEGROUP_PID	0xF208	/* Product Id */
 
 /*
+ * Definitions for Artemis astronomical USB based cameras
+ * Check it at http://www.artemisccd.co.uk/
+ */
+#define FTDI_ARTEMIS_PID	0xDF28	/* All Artemis Cameras */
+
+/*
+ * Definitions for ATIK Instruments astronomical USB based cameras
+ * Check it at http://www.atik-instruments.com/
+ */
+#define FTDI_ATIK_ATK16_PID	0xDF30	/* ATIK ATK-16 Camera */
+#define FTDI_ATIK_ATK16HR_PID	0xDF31	/* ATIK ATK-16HR Camera */
+
+/*
  * Protego product ids
  */
 #define PROTEGO_SPECIAL_1	0xFC70	/* special/unknown device */
@@ -329,6 +342,9 @@
 #define EVOLUTION_VID		0xDEEE	/* Vendor ID */
 #define EVOLUTION_ER1_PID	0x0300	/* ER1 Control Module */
 
+/* Pyramid Computer GmbH */
+#define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 2ef614d..35820bd 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1468,16 +1468,13 @@
 }
 
 
-
-
-
-
-
 /* All of the device info needed */
-static struct usb_serial_device_type garmin_device = {
-	.owner               = THIS_MODULE,
-	.name                = "Garmin GPS usb/tty",
-	.short_name          = "garmin_gps",
+static struct usb_serial_driver garmin_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"garmin_gps",
+	},
+	.description =		"Garmin GPS usb/tty",
 	.id_table            = id_table,
 	.num_interrupt_in    = 1,
 	.num_bulk_in         = 1,
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 5f7d319..8909208 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -36,10 +36,11 @@
 static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
 
 /* All of the device info needed for the Generic Serial Converter */
-struct usb_serial_device_type usb_serial_generic_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Generic",
-	.short_name =		"generic",
+struct usb_serial_driver usb_serial_generic_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"generic",
+	},
 	.id_table =		generic_device_ids,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 64d55fb..8eadfb7 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -38,15 +38,17 @@
 
 static struct usb_driver hp49gp_driver = {
 	.owner =	THIS_MODULE,
-	.name =		"HP4X",
+	.name =		"hp4X",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
 };
 
-static struct usb_serial_device_type hp49gp_device = {
-	.owner =		THIS_MODULE,
-	.name =			"HP4X",
+static struct usb_serial_driver hp49gp_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"hp4X",
+	},
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 04bfe27..dc4c498 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -27,225 +27,6 @@
  * Networks technical support, or Peter Berger <pberger@brimson.com>,
  * or Al Borchers <alborchers@steinerpoint.com>.
  *
- * Version history:
- * 
- * 2003_04_03 al borchers
- *  - fixed a bug (that shows up with dosemu) where the tty struct is
- *    used in a callback after it has been freed
- *
- * 2.3 2002_03_08 greg kroah-hartman
- *	- fixed bug when multiple devices were attached at the same time.
- *
- * 2.2 2001_11_14 greg kroah-hartman
- *	- fixed bug in edge_close that kept the port from being used more
- *	  than once.
- *	- fixed memory leak on device removal.
- *	- fixed potential double free of memory when command urb submitting
- *	  failed.
- *	- other small cleanups when the device is removed
- *	
- * 2.1 2001_07_09 greg kroah-hartman
- *	- added support for TIOCMBIS and TIOCMBIC.
- *
- *     (04/08/2001) gb
- *	- Identify version on module load.
- *
- * 2.0 2001_03_05 greg kroah-hartman
- *	- reworked entire driver to fit properly in with the other usb-serial
- *	  drivers.  Occasional oopses still happen, but it's a good start.
- *
- * 1.2.3 (02/23/2001) greg kroah-hartman
- *	- changed device table to work properly for 2.4.x final format.
- *	- fixed problem with dropping data at high data rates.
- *
- * 1.2.2 (11/27/2000) greg kroah-hartman
- *	- cleaned up more NTisms.
- *	- Added device table for 2.4.0-test11
- *
- * 1.2.1 (11/08/2000) greg kroah-hartman
- *	- Started to clean up NTisms.
- *	- Fixed problem with dev field of urb for kernels >= 2.4.0-test9
- *
- * 1.2 (10/17/2000) David Iacovelli
- * 	Remove all EPIC code and GPL source
- *  Fix RELEVANT_IFLAG macro to include flow control 
- *  changes port configuration changes.
- *  Fix redefinition of SERIAL_MAGIC
- *  Change all timeout values to 5 seconds
- *  Tried to fix the UHCI multiple urb submission, but failed miserably.
- *  it seems to work fine with OHCI.
- *  ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must 
- *    find a way to work arount this UHCI bug )
- *
- * 1.1 (10/11/2000) David Iacovelli
- *  Fix XON/XOFF flow control to support both IXON and IXOFF
- *
- * 0.9.27 (06/30/2000) David Iacovelli
- *  Added transmit queue and now allocate urb for command writes.
- *
- * 0.9.26 (06/29/2000) David Iacovelli
- *  Add support for 80251 based edgeport
- *
- * 0.9.25 (06/27/2000) David Iacovelli
- *  Do not close the port if it has multiple opens.
- *
- * 0.9.24 (05/26/2000) David Iacovelli
- *  Add IOCTLs to support RXTX and JAVA POS 
- *  and first cut at running BlackBox Demo
- *
- * 0.9.23 (05/24/2000) David Iacovelli
- *  Add IOCTLs to support RXTX and JAVA POS
- *
- * 0.9.22 (05/23/2000) David Iacovelli
- *  fixed bug in enumeration.  If epconfig turns on mapping by
- *  path after a device is already plugged in, we now update
- *  the mapping correctly
- *
- * 0.9.21 (05/16/2000) David Iacovelli
- *  Added BlockUntilChaseResp() to also wait for txcredits
- *  Updated the way we allocate and handle write URBs 
- *	Add debug code to dump buffers
- *
- * 0.9.20 (05/01/2000) David Iacovelli
- *	change driver to use usb/tts/
- *
- * 0.9.19 (05/01/2000) David Iacovelli
- *  Update code to compile if DEBUG is off
- *
- * 0.9.18 (04/28/2000) David Iacovelli
- *  cleanup and test tty_register with devfs
- *
- * 0.9.17 (04/27/2000) greg kroah-hartman
- * 	changed tty_register around to be like the way it
- * 	was before, but now it works properly with devfs.
- *
- * 0.9.16 (04/26/2000) david iacovelli
- *  Fixed bug in GetProductInfo()
- *
- * 0.9.15 (04/25/2000) david iacovelli
- *	Updated enumeration
- *
- * 0.9.14 (04/24/2000) david iacovelli
- *  Removed all config/status IOCTLS and 
- *  converted to using /proc/edgeport
- *  still playing with devfs
- *
- * 0.9.13 (04/24/2000) david iacovelli
- *  Removed configuration based on ttyUSB0
- *  Added support for configuration using /prod/edgeport
- *  first attempt at using devfs (not working yet!)
- *  Added IOCTL to GetProductInfo()
- *  Added support for custom baud rates
- *	Add support for random port numbers
- *
- * 0.9.12 (04/18/2000) david iacovelli
- *	added additional configuration IOCTLs
- *  use ttyUSB0 for configuration
- *
- * 0.9.11 (04/17/2000) greg kroah-hartman
- *	fixed module initialization race conditions.
- *	made all urbs dynamically allocated.
- *	made driver devfs compatible. now it only registers the tty device
- *	when the device is actually plugged in.
- *
- * 0.9.10 (04/13/2000) greg kroah-hartman
- *	added proc interface framework.
- *
- * 0.9.9 (04/13/2000) david iacovelli
- *	added enumeration code and ioctls to configure the device
- *
- * 0.9.8 (04/12/2000) david iacovelli
- *  Change interrupt read start when device is plugged in
- *  and stop when device is removed
- *	process interrupt reads when all ports are closed 
- *  (keep value of rxBytesAvail consistent with the edgeport)
- *  set the USB_BULK_QUEUE flag so that we can shove a bunch 
- *  of urbs at once down the pipe 
- *
- * 0.9.7 (04/10/2000) david iacovelli
- * 	start to add enumeration code.
- *  generate serial number for epic devices
- *  add support for kdb
- *
- * 0.9.6 (03/30/2000) david iacovelli
- *  add IOCTL to get string, manufacture, and boot descriptors
- *
- * 0.9.5 (03/14/2000) greg kroah-hartman
- *	more error checking added to SerialOpen to try to fix UHCI open problem
- *
- * 0.9.4 (03/09/2000) greg kroah-hartman
- *	added more error checking to handle oops when data is hanging
- *	around and tty is abruptly closed.
- *
- * 0.9.3 (03/09/2000) david iacovelli
- *	Add epic support for xon/xoff chars
- *	play with performance
- *
- * 0.9.2 (03/08/2000) greg kroah-hartman
- *	changed most "info" calls to "dbg"
- *	implemented flow control properly in the termios call
- *
- * 0.9.1 (03/08/2000) david iacovelli
- *	added EPIC support
- *	enabled bootloader update
- *
- * 0.9 (03/08/2000) greg kroah-hartman
- *	Release to IO networks.
- *	Integrated changes that David made
- *  made getting urbs for writing SMP safe
- *
- * 0.8 (03/07/2000) greg kroah-hartman
- *	Release to IO networks.
- *	Fixed problems that were seen in code by David.
- *  Now both Edgeport/4 and Edgeport/2 works properly.
- *  Changed most of the functions to use port instead of serial.
- *
- * 0.7 (02/27/2000) greg kroah-hartman
- *	Milestone 3 release.
- *	Release to IO Networks
- *	ioctl for waiting on line change implemented.
- *	ioctl for getting statistics implemented.
- *	multiport support working.
- *	lsr and msr registers are now handled properly.
- *	change break now hooked up and working.
- *	support for all known Edgeport devices.
- *
- * 0.6 (02/22/2000) greg kroah-hartman
- *	Release to IO networks.
- *	CHASE is implemented correctly when port is closed.
- *	SerialOpen now blocks correctly until port is fully opened.
- *
- * 0.5 (02/20/2000) greg kroah-hartman
- *	Release to IO networks.
- *	Known problems:
- *		modem status register changes are not sent on to the user
- *		CHASE is not implemented when the port is closed.
- *
- * 0.4 (02/16/2000) greg kroah-hartman
- *	Second cut at the CeBit demo.
- *	Doesn't leak memory on every write to the port
- *	Still small leaks on startup.
- *	Added support for Edgeport/2 and Edgeport/8
- *
- * 0.3 (02/15/2000) greg kroah-hartman
- *	CeBit demo release.
- *	Force the line settings to 4800, 8, 1, e for the demo.
- *	Warning! This version leaks memory like crazy!
- *
- * 0.2 (01/30/2000) greg kroah-hartman
- *	Milestone 1 release.
- *	Device is found by USB subsystem, enumerated, fimware is downloaded
- *	and the descriptors are printed to the debug log, config is set, and
- *	green light starts to blink. Open port works, and data can be sent
- *	and received at the default settings of the UART. Loopback connector
- *	and debug log confirms this.
- * 
- * 0.1 (01/23/2000) greg kroah-hartman
- *	Initial release to help IO Networks try to set up their test system. 
- *	Edgeport4 is recognized, firmware is downloaded, config is set so 
- *	device blinks green light every 3 sec. Port is bound, but opening,
- *	closing, and sending data do not work properly.
- * 
  */
 
 #include <linux/config.h>
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index e7ffe02..fad561c 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -75,10 +75,12 @@
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
-static struct usb_serial_device_type edgeport_2port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport 2 port adapter",
-	.short_name		= "edgeport_2",
+static struct usb_serial_driver edgeport_2port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "edgeport_2",
+	},
+	.description		= "Edgeport 2 port adapter",
 	.id_table		= edgeport_2port_id_table,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 1,
@@ -103,10 +105,12 @@
 	.write_bulk_callback	= edge_bulk_out_data_callback,
 };
 
-static struct usb_serial_device_type edgeport_4port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport 4 port adapter",
-	.short_name		= "edgeport_4",
+static struct usb_serial_driver edgeport_4port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "edgeport_4",
+	},
+	.description		= "Edgeport 4 port adapter",
 	.id_table		= edgeport_4port_id_table,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 1,
@@ -131,10 +135,12 @@
 	.write_bulk_callback	= edge_bulk_out_data_callback,
 };
 
-static struct usb_serial_device_type edgeport_8port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport 8 port adapter",
-	.short_name		= "edgeport_8",
+static struct usb_serial_driver edgeport_8port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "edgeport_8",
+	},
+	.description		= "Edgeport 8 port adapter",
 	.id_table		= edgeport_8port_id_table,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 1,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index ebf9967..832b6d6 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2982,10 +2982,12 @@
 }
 
 
-static struct usb_serial_device_type edgeport_1port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport TI 1 port adapter",
-	.short_name		= "edgeport_ti_1",
+static struct usb_serial_driver edgeport_1port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "edgeport_ti_1",
+	},
+	.description		= "Edgeport TI 1 port adapter",
 	.id_table		= edgeport_1port_id_table,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 1,
@@ -3010,10 +3012,12 @@
 	.write_bulk_callback	= edge_bulk_out_callback,
 };
 
-static struct usb_serial_device_type edgeport_2port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport TI 2 port adapter",
-	.short_name		= "edgeport_ti_2",
+static struct usb_serial_driver edgeport_2port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "edgeport_ti_2",
+	},
+	.description		= "Edgeport TI 2 port adapter",
 	.id_table		= edgeport_2port_id_table,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 2,
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index c05c2a2..d5d0664 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -92,24 +92,7 @@
 static struct usb_device_id ipaq_id_table [] = {
 	/* The first entry is a placeholder for the insmod-specified device */
 	{ USB_DEVICE(0x049F, 0x0003) },
-	{ USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */
-	{ USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */
-	{ USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */
-	{ USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */
-	{ USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */
-	{ USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */
-	{ USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */
-	{ USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */
-	{ USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */
-	{ USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */
-	{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
 	{ USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */
 	{ USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */
 	{ USB_DEVICE(0x03F0, 0x1216) }, /* HP USB Sync 1612 */
@@ -125,7 +108,13 @@
 	{ USB_DEVICE(0x03F0, 0x5016) }, /* HP USB Sync 1650 */
 	{ USB_DEVICE(0x03F0, 0x5116) }, /* HP USB Sync 1651 */
 	{ USB_DEVICE(0x03F0, 0x5216) }, /* HP USB Sync 1652 */
-	{ USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */
+	{ USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */
+	{ USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */
+	{ USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */
+	{ USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */
+	{ USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */
+	{ USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */
+	{ USB_DEVICE(0x045E, 0x00CE) }, /* Microsoft USB Sync */
 	{ USB_DEVICE(0x045E, 0x0400) }, /* Windows Powered Pocket PC 2002 */
 	{ USB_DEVICE(0x045E, 0x0401) }, /* Windows Powered Pocket PC 2002 */
 	{ USB_DEVICE(0x045E, 0x0402) }, /* Windows Powered Pocket PC 2002 */
@@ -251,17 +240,81 @@
 	{ USB_DEVICE(0x045E, 0x04E8) }, /* Windows Powered Smartphone 2003 */
 	{ USB_DEVICE(0x045E, 0x04E9) }, /* Windows Powered Smartphone 2003 */
 	{ USB_DEVICE(0x045E, 0x04EA) }, /* Windows Powered Smartphone 2003 */
-	{ USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */
-	{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
-	{ USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
+	{ USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */
+	{ USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */
+	{ USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */
+	{ USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
+	{ USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
+	{ USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
+	{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
+	{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
+	{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
+	{ USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
+	{ USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
+	{ USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
+	{ USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */
+	{ USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */
+	{ USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */
+	{ USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */
+	{ USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */
+	{ USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */
+	{ USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */
+	{ USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */
+	{ USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */
+	{ USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */
+	{ USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */
+	{ USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */
+	{ USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */
+	{ USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */
+	{ USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */
+	{ USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */
+	{ USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */
+	{ USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */
+	{ USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */
+	{ USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */
+	{ USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */
+	{ USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */
+	{ USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */
+	{ USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */
+	{ USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */
+	{ USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */
+	{ USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */
+	{ USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */
+	{ USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */
+	{ USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */
+	{ USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */
+	{ USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */
+	{ USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */
 	{ USB_DEVICE(0x0930, 0x0700) }, /* TOSHIBA USB Sync 0700 */
 	{ USB_DEVICE(0x0930, 0x0705) }, /* TOSHIBA Pocket PC e310 */
+	{ USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
 	{ USB_DEVICE(0x0930, 0x0707) }, /* TOSHIBA Pocket PC e330 Series */
 	{ USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */
-	{ USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */
 	{ USB_DEVICE(0x0930, 0x0709) }, /* TOSHIBA Pocket PC e750 Series */
 	{ USB_DEVICE(0x0930, 0x070A) }, /* TOSHIBA Pocket PC e400 Series */
 	{ USB_DEVICE(0x0930, 0x070B) }, /* TOSHIBA Pocket PC e800 Series */
+	{ USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */
+	{ USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */
+	{ USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */
+	{ USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */
+	{ USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */
+	{ USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */
+	{ USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */
+	{ USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */
+	{ USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */
+	{ USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */
+	{ USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */
+	{ USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */
+	{ USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x00CE) }, /* HTC USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x0A01) }, /* PocketPC USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x0A02) }, /* PocketPC USB Sync */
@@ -422,116 +475,67 @@
 	{ USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */
 	{ USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */
-	{ USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */
-	{ USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */
-	{ USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */
-	{ USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */
-	{ USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */
-	{ USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */
 	{ USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */
-	{ USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
-	{ USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */
-	{ USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */
-	{ USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */
-	{ USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */
-	{ USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */
-	{ USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */
-	{ USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */
-	{ USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */
-	{ USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */
-	{ USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */
-	{ USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */
-	{ USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
-	{ USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */
-	{ USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */
-	{ USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */
-	{ USB_DEVICE(0x1066, 0x0300) }, /* E-TEN P3XX Pocket PC */
-	{ USB_DEVICE(0x1066, 0x0500) }, /* E-TEN P5XX Pocket PC */
-	{ USB_DEVICE(0x1066, 0x0600) }, /* E-TEN P6XX Pocket PC */
-	{ USB_DEVICE(0x1066, 0x0700) }, /* E-TEN P7XX Pocket PC */
-	{ USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */
-	{ USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
-	{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
-	{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
-	{ USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */
-	{ USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */
-	{ USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */
-	{ USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */
-	{ USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */
-	{ USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */
-	{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
-	{ USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */
-	{ USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */
-	{ USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */
-	{ USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */
-	{ USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */
-	{ USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */
-	{ USB_DEVICE(0x3340, 0x0326) }, /* Mio DigiWalker 338 */
-	{ USB_DEVICE(0x3340, 0x0426) }, /* Mio DigiWalker 338 */
-	{ USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
-	{ USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */
-	{ USB_DEVICE(0x3340, 0x043A) }, /* Mio DigiWalker USB Sync */
-	{ USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */
-	{ USB_DEVICE(0x3340, 0x051C) }, /* MiTAC USB Sync 528 */
-	{ USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */
-	{ USB_DEVICE(0x3340, 0x191C) }, /* YAKUMO USB Sync */
-	{ USB_DEVICE(0x4113, 0x0210) }, /* Mobile Media Technology USB Sync */
-	{ USB_DEVICE(0x4113, 0x0211) }, /* Mobile Media Technology USB Sync */
-	{ USB_DEVICE(0x4113, 0x0400) }, /* Mobile Media Technology USB Sync */
-	{ USB_DEVICE(0x4113, 0x0410) }, /* Mobile Media Technology USB Sync */
-	{ USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
 	{ USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */
-	{ USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
-	{ USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
-	{ USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
-	{ USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */
-	{ USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */
-	{ USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */
-	{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
-	{ USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */
-	{ USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */
-	{ USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */
-	{ USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */
-	{ USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */
-	{ USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */
-	{ USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */
-	{ USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */
-	{ USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */
-	{ USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */
-	{ USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */
-	{ USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */
-	{ USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */
-	{ USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */
-	{ USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */
-	{ USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */
-	{ USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */
-	{ USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */
-	{ USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */
-	{ USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */
-	{ USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */
-	{ USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */
-	{ USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */
+	{ USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */
+	{ USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */
+	{ USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */
+	{ USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */
 	{ USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */
 	{ USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */
 	{ USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */
 	{ USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */
-	{ USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */
+	{ USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */
+	{ USB_DEVICE(0x1066, 0x0300) }, /* E-TEN P3XX Pocket PC */
+	{ USB_DEVICE(0x1066, 0x0500) }, /* E-TEN P5XX Pocket PC */
+	{ USB_DEVICE(0x1066, 0x0600) }, /* E-TEN P6XX Pocket PC */
+	{ USB_DEVICE(0x1066, 0x0700) }, /* E-TEN P7XX Pocket PC */
+	{ USB_DEVICE(0x1114, 0x0001) }, /* Psion Teklogix Sync 753x */
+	{ USB_DEVICE(0x1114, 0x0004) }, /* Psion Teklogix Sync netBookPro */
+	{ USB_DEVICE(0x1114, 0x0006) }, /* Psion Teklogix Sync 7525 */
+	{ USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */
 	{ USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */
+	{ USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */
+	{ USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */
+	{ USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */
+	{ USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */
 	{ USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */
 	{ USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */
 	{ USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */
 	{ USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */
 	{ USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */
-	{ USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */
-	{ USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */
+	{ USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */
+	{ USB_DEVICE(0x3340, 0x0326) }, /* Mio DigiWalker 338 */
+	{ USB_DEVICE(0x3340, 0x0426) }, /* Mio DigiWalker 338 */
+	{ USB_DEVICE(0x3340, 0x043A) }, /* Mio DigiWalker USB Sync */
+	{ USB_DEVICE(0x3340, 0x051C) }, /* MiTAC USB Sync 528 */
+	{ USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */
+	{ USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */
+	{ USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */
+	{ USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */
+	{ USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */
+	{ USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */
+	{ USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */
+	{ USB_DEVICE(0x3340, 0x191C) }, /* YAKUMO USB Sync */
+	{ USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */
+	{ USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */
+	{ USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */
+	{ USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */
+	{ USB_DEVICE(0x4113, 0x0210) }, /* Mobile Media Technology USB Sync */
+	{ USB_DEVICE(0x4113, 0x0211) }, /* Mobile Media Technology USB Sync */
+	{ USB_DEVICE(0x4113, 0x0400) }, /* Mobile Media Technology USB Sync */
+	{ USB_DEVICE(0x4113, 0x0410) }, /* Mobile Media Technology USB Sync */
+	{ USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
+	{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
+	{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
 	{ }                             /* Terminating entry */
 };
 
@@ -547,9 +551,12 @@
 
 
 /* All of the device info needed for the Compaq iPAQ */
-static struct usb_serial_device_type ipaq_device = {
-	.owner =		THIS_MODULE,
-	.name =			"PocketPC PDA",
+static struct usb_serial_driver ipaq_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"ipaq",
+	},
+	.description =		"PocketPC PDA",
 	.id_table =		ipaq_id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 85e2424..a02fada 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -443,10 +443,12 @@
 	return 0;
 }
 
-static struct usb_serial_device_type ipw_device = {
-	.owner =		THIS_MODULE,
-	.name =			"IPWireless converter",
-	.short_name =		"ipw",
+static struct usb_serial_driver ipw_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"ipw",
+	},
+	.description =		"IPWireless converter",
 	.id_table =		usb_ipw_ids,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 937b2fd..19f329e 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -133,9 +133,12 @@
 };
 
 
-static struct usb_serial_device_type ir_device = {
-	.owner =		THIS_MODULE,
-	.name =			"IR Dongle",
+static struct usb_serial_driver ir_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"ir-usb",
+	},
+	.description =		"IR Dongle",
 	.id_table =		id_table,
 	.num_interrupt_in =	1,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index e9b45b7..5cfc13b 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -570,10 +570,12 @@
 };
 
 /* Structs for the devices, pre and post renumeration. */
-static struct usb_serial_device_type keyspan_pre_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Keyspan - (without firmware)",
-	.short_name		= "keyspan_no_firm",
+static struct usb_serial_driver keyspan_pre_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "keyspan_no_firm",
+	},
+	.description		= "Keyspan - (without firmware)",
 	.id_table		= keyspan_pre_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= NUM_DONT_CARE,
@@ -582,10 +584,12 @@
 	.attach			= keyspan_fake_startup,
 };
 
-static struct usb_serial_device_type keyspan_1port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Keyspan 1 port adapter",
-	.short_name		= "keyspan_1",
+static struct usb_serial_driver keyspan_1port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "keyspan_1",
+	},
+	.description		= "Keyspan 1 port adapter",
 	.id_table		= keyspan_1port_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= NUM_DONT_CARE,
@@ -607,10 +611,12 @@
 	.shutdown		= keyspan_shutdown,
 };
 
-static struct usb_serial_device_type keyspan_2port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Keyspan 2 port adapter",
-	.short_name		= "keyspan_2",
+static struct usb_serial_driver keyspan_2port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "keyspan_2",
+	},
+	.description		= "Keyspan 2 port adapter",
 	.id_table		= keyspan_2port_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= NUM_DONT_CARE,
@@ -632,10 +638,12 @@
 	.shutdown		= keyspan_shutdown,
 };
 
-static struct usb_serial_device_type keyspan_4port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Keyspan 4 port adapter",
-	.short_name		= "keyspan_4",
+static struct usb_serial_driver keyspan_4port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "keyspan_4",
+	},
+	.description		= "Keyspan 4 port adapter",
 	.id_table		= keyspan_4port_ids,
 	.num_interrupt_in	= NUM_DONT_CARE,
 	.num_bulk_in		= 5,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 635c384..cd4f48b 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -783,10 +783,12 @@
 }
 
 #ifdef KEYSPAN
-static struct usb_serial_device_type keyspan_pda_fake_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Keyspan PDA - (prerenumeration)",
-	.short_name =		"keyspan_pda_pre",
+static struct usb_serial_driver keyspan_pda_fake_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"keyspan_pda_pre",
+	},
+	.description =		"Keyspan PDA - (prerenumeration)",
 	.id_table =		id_table_fake,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
@@ -797,10 +799,12 @@
 #endif
 
 #ifdef XIRCOM
-static struct usb_serial_device_type xircom_pgs_fake_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Xircom / Entregra PGS - (prerenumeration)",
-	.short_name =		"xircom_no_firm",
+static struct usb_serial_driver xircom_pgs_fake_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"xircom_no_firm",
+	},
+	.description =		"Xircom / Entregra PGS - (prerenumeration)",
 	.id_table =		id_table_fake_xircom,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
@@ -810,10 +814,12 @@
 };
 #endif
 
-static struct usb_serial_device_type keyspan_pda_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Keyspan PDA",
-	.short_name =		"keyspan_pda",
+static struct usb_serial_driver keyspan_pda_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"keyspan_pda",
+	},
+	.description =		"Keyspan PDA",
 	.id_table =		id_table_std,
 	.num_interrupt_in =	1,
 	.num_bulk_in =		0,
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index a11e829..a8951c0 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -123,10 +123,12 @@
 	.id_table =	id_table,
 };
 
-static struct usb_serial_device_type kl5kusb105d_device = {
-	.owner =             THIS_MODULE,
-	.name =		     "KL5KUSB105D / PalmConnect",
-	.short_name =	     "kl5kusb105d",
+static struct usb_serial_driver kl5kusb105d_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"kl5kusb105d",
+	},
+	.description =	     "KL5KUSB105D / PalmConnect",
 	.id_table =	     id_table,
 	.num_interrupt_in =  1,
 	.num_bulk_in =	     1,
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index fe4c98a..9456dd9 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -105,9 +105,12 @@
 };
 
 
-static struct usb_serial_device_type kobil_device = {
-	.owner =		THIS_MODULE,
-	.name =			"KOBIL USB smart card terminal",
+static struct usb_serial_driver kobil_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"kobil",
+	},
+	.description =		"KOBIL USB smart card terminal",
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		0,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 50b63696..ca5dbad 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -132,10 +132,12 @@
 	.id_table =	id_table_combined,
 };
 
-static struct usb_serial_device_type mct_u232_device = {
-	.owner =	     THIS_MODULE,
-	.name =		     "MCT U232",
-	.short_name =	     "mct_u232",
+static struct usb_serial_driver mct_u232_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"mct_u232",
+	},
+	.description =	     "MCT U232",
 	.id_table =	     id_table_combined,
 	.num_interrupt_in =  2,
 	.num_bulk_in =	     0,
diff --git a/drivers/usb/serial/nokia_dku2.c b/drivers/usb/serial/nokia_dku2.c
new file mode 100644
index 0000000..fad01be
--- /dev/null
+++ b/drivers/usb/serial/nokia_dku2.c
@@ -0,0 +1,142 @@
+/*
+ *  Nokia DKU2 USB driver
+ *
+ *  Copyright (C) 2004
+ *  Author: C Kemp
+ *
+ *  This program is largely derived from work by the linux-usb group
+ *  and associated source files.  Please see the usb/serial files for
+ *  individual credits and copyrights.
+ *
+ *  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.
+ *
+ *  20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de>
+ *  Added short name to device structure to make driver load into kernel 2.6.13
+ *
+ *  20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de>
+ *  Added usb_deregister to exit code - to allow remove and reinsert of module
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+
+#define NOKIA_VENDOR_ID		0x0421
+#define NOKIA7600_PRODUCT_ID	0x0400
+#define NOKIA6230_PRODUCT_ID	0x040f
+#define NOKIA6170_PRODUCT_ID	0x0416
+#define NOKIA6670_PRODUCT_ID	0x041d
+#define NOKIA6680_PRODUCT_ID	0x041e
+#define NOKIA6230i_PRODUCT_ID	0x0428
+
+#define NOKIA_AT_PORT	0x82
+#define NOKIA_FBUS_PORT	0x86
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION	"v0.2"
+#define DRIVER_AUTHOR	"C Kemp"
+#define DRIVER_DESC	"Nokia DKU2 Driver"
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(NOKIA_VENDOR_ID, NOKIA7600_PRODUCT_ID) },
+	{ USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230_PRODUCT_ID) },
+	{ USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6170_PRODUCT_ID) },
+	{ USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6670_PRODUCT_ID) },
+	{ USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6680_PRODUCT_ID) },
+	{ USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230i_PRODUCT_ID) },
+	{ }			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* The only thing which makes this device different from a generic
+ * device is that we have to set an alternative configuration to make
+ * the relevant endpoints available. In 2.6 this is really easy... */
+static int nokia_probe(struct usb_serial *serial,
+		       const struct usb_device_id *id)
+{
+	int retval = -ENODEV;
+
+	if (serial->interface->altsetting[0].endpoint[0].desc.bEndpointAddress == NOKIA_AT_PORT) {
+		/* the AT port */
+		dev_info(&serial->dev->dev, "Nokia AT Port:\n");
+		retval = 0;
+	} else if (serial->interface->num_altsetting == 2 &&
+		   serial->interface->altsetting[1].endpoint[0].desc.bEndpointAddress == NOKIA_FBUS_PORT) {
+		/* the FBUS port */
+		dev_info(&serial->dev->dev, "Nokia FBUS Port:\n");
+		usb_set_interface(serial->dev, 10, 1);
+		retval = 0;
+	}
+
+	return retval;
+}
+
+static struct usb_driver nokia_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"nokia_dku2",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
+static struct usb_serial_driver nokia_serial_driver = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name = 	"nokia_dku2",
+	},
+	.description =		"Nokia 7600/6230(i)/6170/66x0 DKU2 driver",
+	.id_table =		id_table,
+	.num_interrupt_in =	1,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.probe =		nokia_probe,
+};
+
+static int __init nokia_init(void)
+{
+        int retval;
+
+	retval = usb_serial_register(&nokia_serial_driver);
+	if (retval)
+		return retval;
+
+	retval = usb_register(&nokia_driver);
+	if (retval) {
+	        usb_serial_deregister(&nokia_serial_driver);
+		return retval;
+	}
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
+	return retval;
+}
+
+static void __exit nokia_exit(void)
+{
+	usb_deregister(&nokia_driver);
+	usb_serial_deregister(&nokia_serial_driver);
+}
+
+module_init(nokia_init);
+module_exit(nokia_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 6a99ae1..3caf970 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -88,10 +88,12 @@
 };
 
 
-static struct usb_serial_device_type zyxel_omninet_device = {
-	.owner =		THIS_MODULE,
-	.name =			"ZyXEL - omni.net lcd plus usb",
-	.short_name =		"omninet",
+static struct usb_serial_driver zyxel_omninet_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"omninet",
+	},
+	.description =		"ZyXEL - omni.net lcd plus usb",
 	.id_table =		id_table,
 	.num_interrupt_in =	1,
 	.num_bulk_in =		1,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 4989e57..7716000 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -105,10 +105,12 @@
 /* The card has three separate interfaces, wich the serial driver
  * recognizes separately, thus num_port=1.
  */
-static struct usb_serial_device_type option_3port_device = {
-	.owner             = THIS_MODULE,
-	.name              = "Option 3G data card",
-	.short_name        = "option",
+static struct usb_serial_driver option_3port_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"option",
+	},
+	.description       = "Option 3G data card",
 	.id_table          = option_ids,
 	.num_interrupt_in  = NUM_DONT_CARE,
 	.num_bulk_in       = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 3cf245b..165c119 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -8,31 +8,10 @@
  *
  *	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 Free Software Foundation; either version 2 of the License.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * 2002_Mar_26 gkh
- *	allowed driver to work properly if there is no tty assigned to a port
- *	(this happens for serial console devices.)
- *
- * 2001_Oct_06 gkh
- *	Added RTS and DTR line control.  Thanks to joe@bndlg.de for parts of it.
- *
- * 2001_Sep_19 gkh
- *	Added break support.
- *
- * 2001_Aug_30 gkh
- *	fixed oops in write_bulk_callback.
- *
- * 2001_Aug_28 gkh
- *	reworked buffer logic to be like other usb-serial drivers.  Hopefully
- *	removing some reported problems.
- *
- * 2001_Jun_06 gkh
- *	finished porting to 2.4 format.
- * 
  */
 
 #include <linux/config.h>
@@ -55,7 +34,6 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.12"
 #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
 
 static int debug;
@@ -175,9 +153,11 @@
 
 
 /* All of the device info needed for the PL2303 SIO serial converter */
-static struct usb_serial_device_type pl2303_device = {
-	.owner =		THIS_MODULE,
-	.name =			"PL-2303",
+static struct usb_serial_driver pl2303_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"pl2303",
+	},
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		1,
@@ -1195,7 +1175,7 @@
 	retval = usb_register(&pl2303_driver);
 	if (retval)
 		goto failed_usb_register;
-	info(DRIVER_DESC " " DRIVER_VERSION);
+	info(DRIVER_DESC);
 	return 0;
 failed_usb_register:
 	usb_serial_deregister(&pl2303_device);
@@ -1215,7 +1195,6 @@
 module_exit(pl2303_exit);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 96a1756..c22bdc0 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -92,7 +92,7 @@
 MODULE_LICENSE("GPL");
 
 #if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT)
-#abort "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
+#error "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
 #endif
 
 #if ! defined(CONFIG_USBD_SAFE_SERIAL_VENDOR)
@@ -397,9 +397,11 @@
 	return 0;
 }
 
-static struct usb_serial_device_type safe_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Safe",
+static struct usb_serial_driver safe_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"safe_serial",
+	},
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 59c88de..205dbf7 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -255,9 +255,12 @@
 	.id_table		= ti_id_table_combined,
 };
 
-static struct usb_serial_device_type ti_1port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "TI USB 3410 1 port adapter",
+static struct usb_serial_driver ti_1port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "ti_usb_3410_5052_1",
+	},
+	.description		= "TI USB 3410 1 port adapter",
 	.id_table		= ti_id_table_3410,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 1,
@@ -282,9 +285,12 @@
 	.write_bulk_callback	= ti_bulk_out_callback,
 };
 
-static struct usb_serial_device_type ti_2port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "TI USB 5052 2 port adapter",
+static struct usb_serial_driver ti_2port_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "ti_usb_3410_5052_2",
+	},
+	.description		= "TI USB 5052 2 port adapter",
 	.id_table		= ti_id_table_5052,
 	.num_interrupt_in	= 1,
 	.num_bulk_in		= 2,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index e77fbdf..0c4881d 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- * Copyright (C) 1999 - 2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
  * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
  *
@@ -9,316 +9,11 @@
  *	modify it under the terms of the GNU General Public License version
  *	2 as published by the Free Software Foundation.
  *
- * This driver was originally based on the ACM driver by Armin Fuerst (which was 
+ * This driver was originally based on the ACM driver by Armin Fuerst (which was
  * based on a driver by Brad Keryan)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * (12/10/2002) gkh
- *	Split the ports off into their own struct device, and added a
- *	usb-serial bus driver.
- *
- * (11/19/2002) gkh
- *	removed a few #ifdefs for the generic code and cleaned up the failure
- *	logic in initialization.
- *
- * (10/02/2002) gkh
- *	moved the console code to console.c and out of this file.
- *
- * (06/05/2002) gkh
- *	moved location of startup() call in serial_probe() until after all
- *	of the port information and endpoints are initialized.  This makes
- *	things easier for some drivers.
- *
- * (04/10/2002) gkh
- *	added serial_read_proc function which creates a
- *	/proc/tty/driver/usb-serial file.
- *
- * (03/27/2002) gkh
- *	Got USB serial console code working properly and merged into the main
- *	version of the tree.  Thanks to Randy Dunlap for the initial version
- *	of this code, and for pushing me to finish it up.
- *	The USB serial console works with any usb serial driver device.
- *
- * (03/21/2002) gkh
- *	Moved all manipulation of port->open_count into the core.  Now the
- *	individual driver's open and close functions are called only when the
- *	first open() and last close() is called.  Making the drivers a bit
- *	smaller and simpler.
- *	Fixed a bug if a driver didn't have the owner field set.
- *
- * (02/26/2002) gkh
- *	Moved all locking into the main serial_* functions, instead of having 
- *	the individual drivers have to grab the port semaphore.  This should
- *	reduce races.
- *	Reworked the MOD_INC logic a bit to always increment and decrement, even
- *	if the generic driver is being used.
- *
- * (10/10/2001) gkh
- *	usb_serial_disconnect() now sets the serial->dev pointer is to NULL to
- *	help prevent child drivers from accessing the device since it is now
- *	gone.
- *
- * (09/13/2001) gkh
- *	Moved generic driver initialize after we have registered with the USB
- *	core.  Thanks to Randy Dunlap for pointing this problem out.
- *
- * (07/03/2001) gkh
- *	Fixed module paramater size.  Thanks to John Brockmeyer for the pointer.
- *	Fixed vendor and product getting defined through the MODULE_PARM macro
- *	if the Generic driver wasn't compiled in.
- *	Fixed problem with generic_shutdown() not being called for drivers that
- *	don't have a shutdown() function.
- *
- * (06/06/2001) gkh
- *	added evil hack that is needed for the prolific pl2303 device due to the
- *	crazy way its endpoints are set up.
- *
- * (05/30/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (04/08/2001) gb
- *	Identify version on module load.
- *
- * 2001_02_05 gkh
- *	Fixed buffer overflows bug with the generic serial driver.  Thanks to
- *	Todd Squires <squirest@ct0.com> for fixing this.
- *
- * (01/10/2001) gkh
- *	Fixed bug where the generic serial adaptor grabbed _any_ device that was
- *	offered to it.
- *
- * (12/12/2000) gkh
- *	Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
- *	moved them to the serial_open and serial_close functions.
- *	Also fixed bug with there not being a MOD_DEC for the generic driver
- *	(thanks to Gary Brubaker for finding this.)
- *
- * (11/29/2000) gkh
- *	Small NULL pointer initialization cleanup which saves a bit of disk image
- *
- * (11/01/2000) Adam J. Richter
- *	instead of using idVendor/idProduct pairs, usb serial drivers
- *	now identify their hardware interest with usb_device_id tables,
- *	which they usually have anyhow for use with MODULE_DEVICE_TABLE.
- *
- * (10/05/2000) gkh
- *	Fixed bug with urb->dev not being set properly, now that the usb
- *	core needs it.
- * 
- * (09/11/2000) gkh
- *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (08/28/2000) gkh
- *	Added port_lock to port structure.
- *	Added locks for SMP safeness to generic driver
- *	Fixed the ability to open a generic device's port more than once.
- *
- * (07/23/2000) gkh
- *	Added bulk_out_endpointAddress to port structure.
- *
- * (07/19/2000) gkh, pberger, and borchers
- *	Modifications to allow usb-serial drivers to be modules.
- *
- * (07/03/2000) gkh
- *	Added more debugging to serial_ioctl call
- * 
- * (06/25/2000) gkh
- *	Changed generic_write_bulk_callback to not call wake_up_interruptible
- *	directly, but to have port_softint do it at a safer time.
- *
- * (06/23/2000) gkh
- *	Cleaned up debugging statements in a quest to find UHCI timeout bug.
- *
- * (05/22/2000) gkh
- *	Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be 
- *	removed from the individual device source files.
- *
- * (05/03/2000) gkh
- *	Added the Digi Acceleport driver from Al Borchers and Peter Berger.
- * 
- * (05/02/2000) gkh
- *	Changed devfs and tty register code to work properly now. This was based on
- *	the ACM driver changes by Vojtech Pavlik.
- *
- * (04/27/2000) Ryan VanderBijl
- * 	Put calls to *_paranoia_checks into one function.
- * 
- * (04/23/2000) gkh
- *	Fixed bug that Randy Dunlap found for Generic devices with no bulk out ports.
- *	Moved when the startup code printed out the devices that are supported.
- *
- * (04/19/2000) gkh
- *	Added driver for ZyXEL omni.net lcd plus ISDN TA
- *	Made startup info message specify which drivers were compiled in.
- *
- * (04/03/2000) gkh
- *	Changed the probe process to remove the module unload races.
- *	Changed where the tty layer gets initialized to have devfs work nicer.
- *	Added initial devfs support.
- *
- * (03/26/2000) gkh
- *	Split driver up into device specific pieces.
- * 
- * (03/19/2000) gkh
- *	Fixed oops that could happen when device was removed while a program
- *	was talking to the device.
- *	Removed the static urbs and now all urbs are created and destroyed
- *	dynamically.
- *	Reworked the internal interface. Now everything is based on the 
- *	usb_serial_port structure instead of the larger usb_serial structure.
- *	This fixes the bug that a multiport device could not have more than
- *	one port open at one time.
- *
- * (03/17/2000) gkh
- *	Added config option for debugging messages.
- *	Added patch for keyspan pda from Brian Warner.
- *
- * (03/06/2000) gkh
- *	Added the keyspan pda code from Brian Warner <warner@lothar.com>
- *	Moved a bunch of the port specific stuff into its own structure. This
- *	is in anticipation of the true multiport devices (there's a bug if you
- *	try to access more than one port of any multiport device right now)
- *
- * (02/21/2000) gkh
- *	Made it so that any serial devices only have to specify which functions
- *	they want to overload from the generic function calls (great, 
- *	inheritance in C, in a driver, just what I wanted...)
- *	Added support for set_termios and ioctl function calls. No drivers take
- *	advantage of this yet.
- *	Removed the #ifdef MODULE, now there is no module specific code.
- *	Cleaned up a few comments in usb-serial.h that were wrong (thanks again
- *	to Miles Lott).
- *	Small fix to get_free_serial.
- *
- * (02/14/2000) gkh
- *	Removed the Belkin and Peracom functionality from the driver due to
- *	the lack of support from the vendor, and me not wanting people to 
- *	accidenatly buy the device, expecting it to work with Linux.
- *	Added read_bulk_callback and write_bulk_callback to the type structure
- *	for the needs of the FTDI and WhiteHEAT driver.
- *	Changed all reverences to FTDI to FTDI_SIO at the request of Bill
- *	Ryder.
- *	Changed the output urb size back to the max endpoint size to make
- *	the ftdi_sio driver have it easier, and due to the fact that it didn't
- *	really increase the speed any.
- *
- * (02/11/2000) gkh
- *	Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
- *	patch from Miles Lott (milos@insync.net).
- *	Fixed bug with not restoring the minor range that a device grabs, if
- *	the startup function fails (thanks Miles for finding this).
- *
- * (02/05/2000) gkh
- *	Added initial framework for the Keyspan PDA serial converter so that
- *	Brian Warner has a place to put his code.
- *	Made the ezusb specific functions generic enough that different
- *	devices can use them (whiteheat and keyspan_pda both need them).
- *	Split out a whole bunch of structure and other stuff to a separate
- *	usb-serial.h file.
- *	Made the Visor connection messages a little more understandable, now
- *	that Miles Lott (milos@insync.net) has gotten the Generic channel to
- *	work. Also made them always show up in the log file.
- * 
- * (01/25/2000) gkh
- *	Added initial framework for FTDI serial converter so that Bill Ryder
- *	has a place to put his code.
- *	Added the vendor specific info from Handspring. Now we can print out
- *	informational debug messages as well as understand what is happening.
- *
- * (01/23/2000) gkh
- *	Fixed problem of crash when trying to open a port that didn't have a
- *	device assigned to it. Made the minor node finding a little smarter,
- *	now it looks to find a continuous space for the new device.
- *
- * (01/21/2000) gkh
- *	Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
- *	Fixed get_serial_by_minor which was all messed up for multi port 
- *	devices. Fixed multi port problem for generic devices. Now the number
- *	of ports is determined by the number of bulk out endpoints for the
- *	generic device.
- *
- * (01/19/2000) gkh
- *	Removed lots of cruft that was around from the old (pre urb) driver 
- *	interface.
- *	Made the serial_table dynamic. This should save lots of memory when
- *	the number of minor nodes goes up to 256.
- *	Added initial support for devices that have more than one port. 
- *	Added more debugging comments for the Visor, and added a needed 
- *	set_configuration call.
- *
- * (01/17/2000) gkh
- *	Fixed the WhiteHEAT firmware (my processing tool had a bug)
- *	and added new debug loader firmware for it.
- *	Removed the put_char function as it isn't really needed.
- *	Added visor startup commands as found by the Win98 dump.
- * 
- * (01/13/2000) gkh
- *	Fixed the vendor id for the generic driver to the one I meant it to be.
- *
- * (01/12/2000) gkh
- *	Forget the version numbering...that's pretty useless...
- *	Made the driver able to be compiled so that the user can select which
- *	converter they want to use. This allows people who only want the Visor
- *	support to not pay the memory size price of the WhiteHEAT.
- *	Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
- *	grabbed the root hub. Not good.
- * 
- * version 0.4.0 (01/10/2000) gkh
- *	Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
- *	device. Added startup function to allow firmware to be downloaded to
- *	a device if it needs to be.
- *	Added firmware download logic to the WhiteHEAT device.
- *	Started to add #defines to split up the different drivers for potential
- *	configuration option.
- *	
- * version 0.3.1 (12/30/99) gkh
- *      Fixed problems with urb for bulk out.
- *      Added initial support for multiple sets of endpoints. This enables
- *      the Handspring Visor to be attached successfully. Only the first
- *      bulk in / bulk out endpoint pair is being used right now.
- *
- * version 0.3.0 (12/27/99) gkh
- *	Added initial support for the Handspring Visor based on a patch from
- *	Miles Lott (milos@sneety.insync.net)
- *	Cleaned up the code a bunch and converted over to using urbs only.
- *
- * version 0.2.3 (12/21/99) gkh
- *	Added initial support for the Connect Tech WhiteHEAT converter.
- *	Incremented the number of ports in expectation of getting the
- *	WhiteHEAT to work properly (4 ports per connection).
- *	Added notification on insertion and removal of what port the
- *	device is/was connected to (and what kind of device it was).
- *
- * version 0.2.2 (12/16/99) gkh
- *	Changed major number to the new allocated number. We're legal now!
- *
- * version 0.2.1 (12/14/99) gkh
- *	Fixed bug that happens when device node is opened when there isn't a
- *	device attached to it. Thanks to marek@webdesign.no for noticing this.
- *
- * version 0.2.0 (11/10/99) gkh
- *	Split up internals to make it easier to add different types of serial 
- *	converters to the code.
- *	Added a "generic" driver that gets it's vendor and product id
- *	from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
- *	for the idea and sample code (from the usb scanner driver.)
- *	Cleared up any licensing questions by releasing it under the GNU GPL.
- *
- * version 0.1.2 (10/25/99) gkh
- * 	Fixed bug in detecting device.
- *
- * version 0.1.1 (10/05/99) gkh
- * 	Changed the major number to not conflict with anything else.
- *
- * version 0.1 (09/28/99) gkh
- * 	Can recognize the two different devices and start up a read from
- *	device when asked to. Writes also work. No control signals yet, this
- *	all is vendor specific data (i.e. no spec), also no control for
- *	different baud rates or other bit settings.
- *	Currently we are using the same devid as the acm driver. This needs
- *	to change.
- * 
  */
 
 #include <linux/config.h>
@@ -342,7 +37,6 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.0"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
 #define DRIVER_DESC "USB Serial Driver core"
 
@@ -427,7 +121,7 @@
 
 	serial = to_usb_serial(kref);
 
-	dbg ("%s - %s", __FUNCTION__, serial->type->name);
+	dbg("%s - %s", __FUNCTION__, serial->type->description);
 
 	serial->type->shutdown(serial);
 
@@ -507,7 +201,7 @@
 		/* lock this module before we call it
 		 * this may fail, which means we must bail out,
 		 * safe because we are called with BKL held */
-		if (!try_module_get(serial->type->owner)) {
+		if (!try_module_get(serial->type->driver.owner)) {
 			retval = -ENODEV;
 			goto bailout_kref_put;
 		}
@@ -522,7 +216,7 @@
 	return 0;
 
 bailout_module_put:
-	module_put(serial->type->owner);
+	module_put(serial->type->driver.owner);
 bailout_kref_put:
 	kref_put(&serial->kref, destroy_serial);
 	port->open_count = 0;
@@ -553,7 +247,7 @@
 			port->tty = NULL;
 		}
 
-		module_put(port->serial->type->owner);
+		module_put(port->serial->type->driver.owner);
 	}
 
 	kref_put(&port->serial->kref, destroy_serial);
@@ -711,16 +405,16 @@
 	char tmp[40];
 
 	dbg("%s", __FUNCTION__);
-	length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);
+	length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
 	for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
 		serial = usb_serial_get_by_index(i);
 		if (serial == NULL)
 			continue;
 
 		length += sprintf (page+length, "%d:", i);
-		if (serial->type->owner)
-			length += sprintf (page+length, " module:%s", module_name(serial->type->owner));
-		length += sprintf (page+length, " name:\"%s\"", serial->type->name);
+		if (serial->type->driver.owner)
+			length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
+		length += sprintf (page+length, " name:\"%s\"", serial->type->description);
 		length += sprintf (page+length, " vendor:%04x product:%04x", 
 				   le16_to_cpu(serial->dev->descriptor.idVendor), 
 				   le16_to_cpu(serial->dev->descriptor.idProduct));
@@ -823,7 +517,7 @@
 
 static struct usb_serial * create_serial (struct usb_device *dev, 
 					  struct usb_interface *interface,
-					  struct usb_serial_device_type *type)
+					  struct usb_serial_driver *driver)
 {
 	struct usb_serial *serial;
 
@@ -834,22 +528,22 @@
 	}
 	memset (serial, 0, sizeof(*serial));
 	serial->dev = usb_get_dev(dev);
-	serial->type = type;
+	serial->type = driver;
 	serial->interface = interface;
 	kref_init(&serial->kref);
 
 	return serial;
 }
 
-static struct usb_serial_device_type *search_serial_device(struct usb_interface *iface)
+static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
 {
 	struct list_head *p;
 	const struct usb_device_id *id;
-	struct usb_serial_device_type *t;
+	struct usb_serial_driver *t;
 
 	/* List trough know devices and see if the usb id matches */
 	list_for_each(p, &usb_serial_driver_list) {
-		t = list_entry(p, struct usb_serial_device_type, driver_list);
+		t = list_entry(p, struct usb_serial_driver, driver_list);
 		id = usb_match_id(iface, t->id_table);
 		if (id != NULL) {
 			dbg("descriptor matches");
@@ -872,7 +566,7 @@
 	struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
 	struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
 	struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
-	struct usb_serial_device_type *type = NULL;
+	struct usb_serial_driver *type = NULL;
 	int retval;
 	int minor;
 	int buffer_size;
@@ -900,7 +594,7 @@
 	if (type->probe) {
 		const struct usb_device_id *id;
 
-		if (!try_module_get(type->owner)) {
+		if (!try_module_get(type->driver.owner)) {
 			dev_err(&interface->dev, "module get failed, exiting\n");
 			kfree (serial);
 			return -EIO;
@@ -908,7 +602,7 @@
 
 		id = usb_match_id(interface, type->id_table);
 		retval = type->probe(serial, id);
-		module_put(type->owner);
+		module_put(type->driver.owner);
 
 		if (retval) {
 			dbg ("sub driver rejected device");
@@ -992,7 +686,7 @@
 #endif
 
 	/* found all that we need */
-	dev_info(&interface->dev, "%s converter detected\n", type->name);
+	dev_info(&interface->dev, "%s converter detected\n", type->description);
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	if (type == &usb_serial_generic_device) {
@@ -1007,13 +701,13 @@
 	if (!num_ports) {
 		/* if this device type has a calc_num_ports function, call it */
 		if (type->calc_num_ports) {
-			if (!try_module_get(type->owner)) {
+			if (!try_module_get(type->driver.owner)) {
 				dev_err(&interface->dev, "module get failed, exiting\n");
 				kfree (serial);
 				return -EIO;
 			}
 			num_ports = type->calc_num_ports (serial);
-			module_put(type->owner);
+			module_put(type->driver.owner);
 		}
 		if (!num_ports)
 			num_ports = type->num_ports;
@@ -1158,12 +852,12 @@
 	
 	/* if this device type has an attach function, call it */
 	if (type->attach) {
-		if (!try_module_get(type->owner)) {
+		if (!try_module_get(type->driver.owner)) {
 			dev_err(&interface->dev, "module get failed, exiting\n");
 			goto probe_error;
 		}
 		retval = type->attach (serial);
-		module_put(type->owner);
+		module_put(type->driver.owner);
 		if (retval < 0)
 			goto probe_error;
 		if (retval > 0) {
@@ -1330,7 +1024,7 @@
 		goto exit_generic;
 	}
 
-	info(DRIVER_DESC " " DRIVER_VERSION);
+	info(DRIVER_DESC);
 
 	return result;
 
@@ -1375,7 +1069,7 @@
 			}						\
 	} while (0)
 
-static void fixup_generic(struct usb_serial_device_type *device)
+static void fixup_generic(struct usb_serial_driver *device)
 {
 	set_to_generic_if_null(device, open);
 	set_to_generic_if_null(device, write);
@@ -1387,30 +1081,33 @@
 	set_to_generic_if_null(device, shutdown);
 }
 
-int usb_serial_register(struct usb_serial_device_type *new_device)
+int usb_serial_register(struct usb_serial_driver *driver)
 {
 	int retval;
 
-	fixup_generic(new_device);
+	fixup_generic(driver);
+
+	if (!driver->description)
+		driver->description = driver->driver.name;
 
 	/* Add this device to our list of devices */
-	list_add(&new_device->driver_list, &usb_serial_driver_list);
+	list_add(&driver->driver_list, &usb_serial_driver_list);
 
-	retval = usb_serial_bus_register(new_device);
+	retval = usb_serial_bus_register(driver);
 	if (retval) {
-		err("problem %d when registering driver %s", retval, new_device->name);
-		list_del(&new_device->driver_list);
+		err("problem %d when registering driver %s", retval, driver->description);
+		list_del(&driver->driver_list);
 	}
 	else
-		info("USB Serial support registered for %s", new_device->name);
+		info("USB Serial support registered for %s", driver->description);
 
 	return retval;
 }
 
 
-void usb_serial_deregister(struct usb_serial_device_type *device)
+void usb_serial_deregister(struct usb_serial_driver *device)
 {
-	info("USB Serial deregistering driver %s", device->name);
+	info("USB Serial deregistering driver %s", device->description);
 	list_del(&device->driver_list);
 	usb_serial_bus_deregister(device);
 }
@@ -1429,7 +1126,6 @@
 /* Module information */
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 57f92f0..238a5a8 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -1,53 +1,13 @@
 /*
  * USB Serial Converter driver
  *
- *	Copyright (C) 1999 - 2004
+ *	Copyright (C) 1999 - 2005
  *	    Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
+ *	the Free Software Foundation; either version 2 of the License.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
- * (03/26/2002) gkh
- *	removed the port->tty check from port_paranoia_check() due to serial
- *	consoles not having a tty device assigned to them.
- *
- * (12/03/2001) gkh
- *	removed active from the port structure.
- *	added documentation to the usb_serial_device_type structure
- *
- * (10/10/2001) gkh
- *	added vendor and product to serial structure.  Needed to determine device
- *	owner when the device is disconnected.
- *
- * (05/30/2001) gkh
- *	added sem to port structure and removed port_lock
- *
- * (10/05/2000) gkh
- *	Added interrupt_in_endpointAddress and bulk_in_endpointAddress to help
- *	fix bug with urb->dev not being set properly, now that the usb core
- *	needs it.
- * 
- * (09/11/2000) gkh
- *	Added usb_serial_debug_data function to help get rid of #DEBUG in the
- *	drivers.
- *
- * (08/28/2000) gkh
- *	Added port_lock to port structure.
- *
- * (08/08/2000) gkh
- *	Added open_count to port structure.
- *
- * (07/23/2000) gkh
- *	Added bulk_out_endpointAddress to port structure.
- *
- * (07/19/2000) gkh, pberger, and borchers
- *	Modifications to allow usb-serial drivers to be modules.
- *
- * 
  */
 
 
@@ -143,7 +103,7 @@
 /**
  * usb_serial - structure used by the usb-serial core for a device
  * @dev: pointer to the struct usb_device for this device
- * @type: pointer to the struct usb_serial_device_type for this device
+ * @type: pointer to the struct usb_serial_driver for this device
  * @interface: pointer to the struct usb_interface for this device
  * @minor: the starting minor number for this device
  * @num_ports: the number of ports this device has
@@ -159,7 +119,7 @@
  */
 struct usb_serial {
 	struct usb_device *		dev;
-	struct usb_serial_device_type *	type;
+	struct usb_serial_driver *	type;
 	struct usb_interface *		interface;
 	unsigned char			minor;
 	unsigned char			num_ports;
@@ -188,13 +148,9 @@
 }
 
 /**
- * usb_serial_device_type - a structure that defines a usb serial device
- * @owner: pointer to the module that owns this device.
- * @name: pointer to a string that describes this device.  This string used
+ * usb_serial_driver - describes a usb serial driver
+ * @description: pointer to a string that describes this driver.  This string used
  *	in the syslog messages when a device is inserted or removed.
- * @short_name: a pointer to a string that describes this device in
- *	KOBJ_NAME_LEN characters or less.  This is used for the sysfs interface
- *	to describe the driver.
  * @id_table: pointer to a list of usb_device_id structures that define all
  *	of the devices this structure can support.
  * @num_interrupt_in: the number of interrupt in endpoints this device will
@@ -221,16 +177,19 @@
  * @shutdown: pointer to the driver's shutdown function.  This will be
  *	called when the device is removed from the system.
  *
- * This structure is defines a USB Serial device.  It provides all of
+ * This structure is defines a USB Serial driver.  It provides all of
  * the information that the USB serial core code needs.  If the function
  * pointers are defined, then the USB serial core code will call them when
  * the corresponding tty port functions are called.  If they are not
  * called, the generic serial function will be used instead.
+ *
+ * The driver.owner field should be set to the module owner of this driver.
+ * The driver.name field should be set to the name of this driver (remember
+ * it will show up in sysfs, so it needs to be short and to the point.
+ * Useing the module name is a good idea.)
  */
-struct usb_serial_device_type {
-	struct module *owner;
-	char	*name;
-	char	*short_name;
+struct usb_serial_driver {
+	const char *description;
 	const struct usb_device_id *id_table;
 	char	num_interrupt_in;
 	char	num_interrupt_out;
@@ -269,10 +228,10 @@
 	void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
 	void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
 };
-#define to_usb_serial_driver(d) container_of(d, struct usb_serial_device_type, driver)
+#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
 
-extern int  usb_serial_register(struct usb_serial_device_type *new_device);
-extern void usb_serial_deregister(struct usb_serial_device_type *device);
+extern int  usb_serial_register(struct usb_serial_driver *driver);
+extern void usb_serial_deregister(struct usb_serial_driver *driver);
 extern void usb_serial_port_softint(void *private);
 
 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
@@ -303,10 +262,10 @@
 extern int usb_serial_generic_register (int debug);
 extern void usb_serial_generic_deregister (void);
 
-extern int usb_serial_bus_register (struct usb_serial_device_type *device);
-extern void usb_serial_bus_deregister (struct usb_serial_device_type *device);
+extern int usb_serial_bus_register (struct usb_serial_driver *device);
+extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
 
-extern struct usb_serial_device_type usb_serial_generic_device;
+extern struct usb_serial_driver usb_serial_generic_device;
 extern struct bus_type usb_serial_bus_type;
 extern struct tty_driver *usb_serial_tty_driver;
 
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 31c57ad..a473c1c 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -7,139 +7,10 @@
  *
  *	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 Free Software Foundation; either version 2 of the License.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
- * (06/03/2003) Judd Montgomery <judd at jpilot.org>
- *     Added support for module parameter options for untested/unknown
- *     devices.
- *
- * (03/09/2003) gkh
- *	Added support for the Sony Clie NZ90V device.  Thanks to Martin Brachtl
- *	<brachtl@redgrep.cz> for the information.
- *
- * (03/05/2003) gkh
- *	Think Treo support is now working.
- *
- * (04/03/2002) gkh
- *	Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
- *	<hiro@zob.ne.jp> for the information.
- *
- * (03/27/2002) gkh
- *	Removed assumptions that port->tty was always valid (is not true
- *	for usb serial console devices.)
- *
- * (03/23/2002) gkh
- *	Added support for the Palm i705 device, thanks to Thomas Riemer
- *	<tom@netmech.com> for the information.
- *
- * (03/21/2002) gkh
- *	Added support for the Palm m130 device, thanks to Udo Eisenbarth
- *	<udo.eisenbarth@web.de> for the information.
- *
- * (02/27/2002) gkh
- *	Reworked the urb handling logic.  We have no more pool, but dynamically
- *	allocate the urb and the transfer buffer on the fly.  In testing this
- *	does not incure any measurable overhead.  This also relies on the fact
- *	that we have proper reference counting logic for urbs.
- *
- * (02/21/2002) SilaS
- *  Added initial support for the Palm m515 devices.
- *
- * (02/14/2002) gkh
- *	Added support for the Clie S-360 device.
- *
- * (12/18/2001) gkh
- *	Added better Clie support for 3.5 devices.  Thanks to Geoffrey Levand
- *	for the patch.
- *
- * (11/11/2001) gkh
- *	Added support for the m125 devices, and added check to prevent oopses
- *	for Clié devices that lie about the number of ports they have.
- *
- * (08/30/2001) gkh
- *	Added support for the Clie devices, both the 3.5 and 4.0 os versions.
- *	Many thanks to Daniel Burke, and Bryan Payne for helping with this.
- *
- * (08/23/2001) gkh
- *	fixed a few potential bugs pointed out by Oliver Neukum.
- *
- * (05/30/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (05/28/2000) gkh
- *	Added initial support for the Palm m500 and Palm m505 devices.
- *
- * (04/08/2001) gb
- *	Identify version on module load.
- *
- * (01/21/2000) gkh
- *	Added write_room and chars_in_buffer, as they were previously using the
- *	generic driver versions which is all wrong now that we are using an urb
- *	pool.  Thanks to Wolfgang Grandegger for pointing this out to me.
- *	Removed count assignment in the write function, which was not needed anymore
- *	either.  Thanks to Al Borchers for pointing this out.
- *
- * (12/12/2000) gkh
- *	Moved MOD_DEC to end of visor_close to be nicer, as the final write 
- *	message can sleep.
- * 
- * (11/12/2000) gkh
- *	Fixed bug with data being dropped on the floor by forcing tty->low_latency
- *	to be on.  Hopefully this fixes the OHCI issue!
- *
- * (11/01/2000) Adam J. Richter
- *	usb_device_id table support
- * 
- * (10/05/2000) gkh
- *	Fixed bug with urb->dev not being set properly, now that the usb
- *	core needs it.
- * 
- * (09/11/2000) gkh
- *	Got rid of always calling kmalloc for every urb we wrote out to the
- *	device.
- *	Added visor_read_callback so we can keep track of bytes in and out for
- *	those people who like to know the speed of their device.
- *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (09/06/2000) gkh
- *	Fixed oops in visor_exit.  Need to uncomment usb_unlink_urb call _after_
- *	the host controller drivers set urb->dev = NULL when the urb is finished.
- *
- * (08/28/2000) gkh
- *	Added locks for SMP safeness.
- *
- * (08/08/2000) gkh
- *	Fixed endian problem in visor_startup.
- *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
- *	than once.
- * 
- * (07/23/2000) gkh
- *	Added pool of write urbs to speed up transfers to the visor.
- * 
- * (07/19/2000) gkh
- *	Added module_init and module_exit functions to handle the fact that this
- *	driver is a loadable module now.
- *
- * (07/03/2000) gkh
- *	Added visor_set_ioctl and visor_set_termios functions (they don't do much
- *	of anything, but are good for debugging.)
- * 
- * (06/25/2000) gkh
- *	Fixed bug in visor_unthrottle that should help with the disconnect in PPP
- *	bug that people have been reporting.
- *
- * (06/23/2000) gkh
- *	Cleaned up debugging statements in a quest to find UHCI timeout bug.
- *
- * (04/27/2000) Ryan VanderBijl
- * 	Fixed memory leak in visor_close
- *
- * (03/26/2000) gkh
- *	Split driver up into device specific pieces.
- * 
  */
 
 #include <linux/config.h>
@@ -161,7 +32,6 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
 
@@ -311,10 +181,12 @@
 };
 
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
-static struct usb_serial_device_type handspring_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Handspring Visor / Palm OS",
-	.short_name =		"visor",
+static struct usb_serial_driver handspring_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"visor",
+	},
+	.description =		"Handspring Visor / Palm OS",
 	.id_table =		id_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		2,
@@ -339,10 +211,12 @@
 };
 
 /* All of the device info needed for the Clie UX50, TH55 Palm 5.0 devices */
-static struct usb_serial_device_type clie_5_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Sony Clie 5.0",
-	.short_name =		"clie_5",
+static struct usb_serial_driver clie_5_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"clie_5",
+	},
+	.description =		"Sony Clie 5.0",
 	.id_table =		clie_id_5_table,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		2,
@@ -367,10 +241,12 @@
 };
 
 /* device info for the Sony Clie OS version 3.5 */
-static struct usb_serial_device_type clie_3_5_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Sony Clie 3.5",
-	.short_name =		"clie_3.5",
+static struct usb_serial_driver clie_3_5_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"clie_3.5",
+	},
+	.description =		"Sony Clie 3.5",
 	.id_table =		clie_id_3_5_table,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
@@ -782,7 +658,7 @@
 					break;
 			}
 			dev_info(dev, "%s: port %d, is for %s use\n",
-				serial->type->name,
+				serial->type->description,
 				connection_info->connections[i].port, string);
 		}
 	}
@@ -791,11 +667,11 @@
 	*/
 	if (num_ports == 0 || num_ports > 2) {
 		dev_warn (dev, "%s: No valid connect info available\n",
-			serial->type->name);
+			serial->type->description);
 		num_ports = 2;
 	}
   
-	dev_info(dev, "%s: Number of ports: %d\n", serial->type->name,
+	dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
 		num_ports);
 
 	/*
@@ -1125,7 +1001,7 @@
 	retval = usb_register(&visor_driver);
 	if (retval) 
 		goto failed_usb_register;
-	info(DRIVER_DESC " " DRIVER_VERSION);
+	info(DRIVER_DESC);
 
 	return 0;
 failed_usb_register:
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index cf3bc30..18c3183 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -156,10 +156,12 @@
 static void whiteheat_read_callback	(struct urb *urb, struct pt_regs *regs);
 static void whiteheat_write_callback	(struct urb *urb, struct pt_regs *regs);
 
-static struct usb_serial_device_type whiteheat_fake_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Connect Tech - WhiteHEAT - (prerenumeration)",
-	.short_name =		"whiteheatnofirm",
+static struct usb_serial_driver whiteheat_fake_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"whiteheatnofirm",
+	},
+	.description =		"Connect Tech - WhiteHEAT - (prerenumeration)",
 	.id_table =		id_table_prerenumeration,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
@@ -169,10 +171,12 @@
 	.attach =		whiteheat_firmware_attach,
 };
 
-static struct usb_serial_device_type whiteheat_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Connect Tech - WhiteHEAT",
-	.short_name =		"whiteheat",
+static struct usb_serial_driver whiteheat_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"whiteheat",
+	},
+	.description =		"Connect Tech - WhiteHEAT",
 	.id_table =		id_table_std,
 	.num_interrupt_in =	NUM_DONT_CARE,
 	.num_bulk_in =		NUM_DONT_CARE,
@@ -382,10 +386,10 @@
 	usb_clear_halt(serial->dev, pipe);
 	ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
 	if (ret) {
-		err("%s: Couldn't send command [%d]", serial->type->name, ret);
+		err("%s: Couldn't send command [%d]", serial->type->description, ret);
 		goto no_firmware;
 	} else if (alen != sizeof(command)) {
-		err("%s: Send command incomplete [%d]", serial->type->name, alen);
+		err("%s: Send command incomplete [%d]", serial->type->description, alen);
 		goto no_firmware;
 	}
 
@@ -394,19 +398,19 @@
 	usb_clear_halt(serial->dev, pipe);
 	ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
 	if (ret) {
-		err("%s: Couldn't get results [%d]", serial->type->name, ret);
+		err("%s: Couldn't get results [%d]", serial->type->description, ret);
 		goto no_firmware;
 	} else if (alen != sizeof(result)) {
-		err("%s: Get results incomplete [%d]", serial->type->name, alen);
+		err("%s: Get results incomplete [%d]", serial->type->description, alen);
 		goto no_firmware;
 	} else if (result[0] != command[0]) {
-		err("%s: Command failed [%d]", serial->type->name, result[0]);
+		err("%s: Command failed [%d]", serial->type->description, result[0]);
 		goto no_firmware;
 	}
 
 	hw_info = (struct whiteheat_hw_info *)&result[1];
 
-	info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
+	info("%s: Driver %s: Firmware v%d.%02d", serial->type->description,
 	     DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
 	for (i = 0; i < serial->num_ports; i++) {
@@ -414,7 +418,7 @@
 
 		info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
 		if (info == NULL) {
-			err("%s: Out of memory for port structures\n", serial->type->name);
+			err("%s: Out of memory for port structures\n", serial->type->description);
 			goto no_private;
 		}
 
@@ -484,7 +488,7 @@
 
 	command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
 	if (command_info == NULL) {
-		err("%s: Out of memory for port structures\n", serial->type->name);
+		err("%s: Out of memory for port structures\n", serial->type->description);
 		goto no_command_private;
 	}
 
@@ -501,9 +505,9 @@
 
 no_firmware:
 	/* Firmware likely not running */
-	err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
-	err("%s: If the firmware is not running (status led not blinking)\n", serial->type->name);
-	err("%s: please contact support@connecttech.com\n", serial->type->name);
+	err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
+	err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
+	err("%s: please contact support@connecttech.com\n", serial->type->description);
 	return -ENODEV;
 
 no_command_private:
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index bb9819c..1a9679f 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -2,7 +2,8 @@
 # USB Storage driver configuration
 #
 
-comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information"
+comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'"
+comment "may also be needed; see USB_STORAGE Help for more information"
 	depends on USB
 
 config USB_STORAGE
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 2c9402d..89401a5 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -5,7 +5,7 @@
  *	Copyright (c) 2005 Nick Sillik <n.sillik@temple.edu>
  *
  * Initial work by:
- * 	Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
+ *	Copyright (c) 2003 Erik Thyren <erth7411@student.uu.se>
  *
  * Based on usbmouse.c (Vojtech Pavlik) and xpad.c (Marko Friedemann)
  *
@@ -46,7 +46,7 @@
 struct usb_onetouch {
 	char name[128];
 	char phys[64];
-	struct input_dev dev;	/* input device interface */
+	struct input_dev *dev;	/* input device interface */
 	struct usb_device *udev;	/* usb device */
 
 	struct urb *irq;	/* urb for interrupt in report */
@@ -58,7 +58,7 @@
 {
 	struct usb_onetouch *onetouch = urb->context;
 	signed char *data = onetouch->data;
-	struct input_dev *dev = &onetouch->dev;
+	struct input_dev *dev = onetouch->dev;
 	int status;
 
 	switch (urb->status) {
@@ -74,11 +74,9 @@
 	}
 
 	input_regs(dev, regs);
-
-	input_report_key(&onetouch->dev, ONETOUCH_BUTTON,
-			 data[0] & 0x02);
-
+	input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02);
 	input_sync(dev);
+
 resubmit:
 	status = usb_submit_urb (urb, SLAB_ATOMIC);
 	if (status)
@@ -113,8 +111,8 @@
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_onetouch *onetouch;
+	struct input_dev *input_dev;
 	int pipe, maxp;
-	char path[64];
 
 	interface = ss->pusb_intf->cur_altsetting;
 
@@ -122,62 +120,62 @@
 		return -ENODEV;
 
 	endpoint = &interface->endpoint[2].desc;
-	if(!(endpoint->bEndpointAddress & USB_DIR_IN))
+	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
 		return -ENODEV;
-	if((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 			!= USB_ENDPOINT_XFER_INT)
 		return -ENODEV;
 
 	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
 
-	if (!(onetouch = kcalloc(1, sizeof(struct usb_onetouch), GFP_KERNEL)))
-		return -ENOMEM;
+	onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!onetouch || !input_dev)
+		goto fail1;
 
 	onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
 					  SLAB_ATOMIC, &onetouch->data_dma);
-	if (!onetouch->data){
-		kfree(onetouch);
-		return -ENOMEM;
-	}
+	if (!onetouch->data)
+		goto fail1;
 
 	onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!onetouch->irq){
-		kfree(onetouch);
-		usb_buffer_free(udev, ONETOUCH_PKT_LEN,
-				onetouch->data, onetouch->data_dma);
-		return -ENODEV;
-	}
-
+	if (!onetouch->irq)
+		goto fail2;
 
 	onetouch->udev = udev;
-
-	set_bit(EV_KEY, onetouch->dev.evbit);
-	set_bit(ONETOUCH_BUTTON, onetouch->dev.keybit);
-	clear_bit(0, onetouch->dev.keybit);
-
-	onetouch->dev.private = onetouch;
-	onetouch->dev.open = usb_onetouch_open;
-	onetouch->dev.close = usb_onetouch_close;
-
-	usb_make_path(udev, path, sizeof(path));
-	sprintf(onetouch->phys, "%s/input0", path);
-
-	onetouch->dev.name = onetouch->name;
-	onetouch->dev.phys = onetouch->phys;
-
-	usb_to_input_id(udev, &onetouch->dev.id);
-
-	onetouch->dev.dev = &udev->dev;
+	onetouch->dev = input_dev;
 
 	if (udev->manufacturer)
-		strcat(onetouch->name, udev->manufacturer);
-	if (udev->product)
-		sprintf(onetouch->name, "%s %s", onetouch->name,
-			udev->product);
+		strlcpy(onetouch->name, udev->manufacturer,
+			sizeof(onetouch->name));
+	if (udev->product) {
+		if (udev->manufacturer)
+			strlcat(onetouch->name, " ", sizeof(onetouch->name));
+		strlcat(onetouch->name, udev->product, sizeof(onetouch->name));
+	}
+
 	if (!strlen(onetouch->name))
-		sprintf(onetouch->name, "Maxtor Onetouch %04x:%04x",
-			onetouch->dev.id.vendor, onetouch->dev.id.product);
+		snprintf(onetouch->name, sizeof(onetouch->name),
+			 "Maxtor Onetouch %04x:%04x",
+			 le16_to_cpu(udev->descriptor.idVendor),
+			 le16_to_cpu(udev->descriptor.idProduct));
+
+	usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys));
+	strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys));
+
+	input_dev->name = onetouch->name;
+	input_dev->phys = onetouch->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &udev->dev;
+
+	set_bit(EV_KEY, input_dev->evbit);
+	set_bit(ONETOUCH_BUTTON, input_dev->keybit);
+	clear_bit(0, input_dev->keybit);
+
+	input_dev->private = onetouch;
+	input_dev->open = usb_onetouch_open;
+	input_dev->close = usb_onetouch_close;
 
 	usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
 			 (maxp > 8 ? 8 : maxp),
@@ -188,10 +186,15 @@
 	ss->extra_destructor = onetouch_release_input;
 	ss->extra = onetouch;
 
-	input_register_device(&onetouch->dev);
-	printk(KERN_INFO "usb-input: %s on %s\n", onetouch->dev.name, path);
+	input_register_device(onetouch->dev);
 
 	return 0;
+
+ fail2:	usb_buffer_free(udev, ONETOUCH_PKT_LEN,
+			onetouch->data, onetouch->data_dma);
+ fail1:	kfree(onetouch);
+	input_free_device(input_dev);
+	return -ENOMEM;
 }
 
 void onetouch_release_input(void *onetouch_)
@@ -200,11 +203,9 @@
 
 	if (onetouch) {
 		usb_kill_urb(onetouch->irq);
-		input_unregister_device(&onetouch->dev);
+		input_unregister_device(onetouch->dev);
 		usb_free_urb(onetouch->irq);
 		usb_buffer_free(onetouch->udev, ONETOUCH_PKT_LEN,
 				onetouch->data, onetouch->data_dma);
-		printk(KERN_INFO "usb-input: deregistering %s\n",
-				onetouch->dev.name);
 	}
 }
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 356342c..33c55a6 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,4 +1,4 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
+/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
  *
  * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
  *
@@ -67,10 +67,10 @@
 static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 /*
- * Convenience function to produce an ATAPI read/write sectors command
+ * Convenience function to produce an ATA read/write sectors command
  * Use cmd=0x20 for read, cmd=0x30 for write
  */
-static void usbat_pack_atapi_sector_cmd(unsigned char *buf,
+static void usbat_pack_ata_sector_cmd(unsigned char *buf,
 					unsigned char thistime,
 					u32 sector, unsigned char cmd)
 {
@@ -196,10 +196,12 @@
 	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
 
-	if (*reply & 0x01 && *reply != 0x51) // error/check condition (0x51 is ok)
+	/* error/check condition (0x51 is ok) */
+	if (*reply & 0x01 && *reply != 0x51)
 		return USB_STOR_TRANSPORT_FAILED;
 
-	if (*reply & 0x20) // device fault
+	/* device fault */
+	if (*reply & 0x20)
 		return USB_STOR_TRANSPORT_FAILED;
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -222,29 +224,39 @@
 	command[0] = 0x40;
 	command[1] = USBAT_CMD_SET_FEAT;
 
-	// The only bit relevant to ATA access is bit 6
-	// which defines 8 bit data access (set) or 16 bit (unset)
+	/*
+	 * The only bit relevant to ATA access is bit 6
+	 * which defines 8 bit data access (set) or 16 bit (unset)
+	 */
 	command[2] = epp_control;
 
-	// If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
-	// ET1 and ET2 define an external event to be checked for on event of a
-	// _read_blocks or _write_blocks operation. The read/write will not take
-	// place unless the defined trigger signal is active.
+	/*
+	 * If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
+	 * ET1 and ET2 define an external event to be checked for on event of a
+	 * _read_blocks or _write_blocks operation. The read/write will not take
+	 * place unless the defined trigger signal is active.
+	 */
 	command[3] = external_trigger;
 
-	// The resultant byte of the mask operation (see mask_byte) is compared for
-	// equivalence with this test pattern. If equal, the read/write will take
-	// place.
+	/*
+	 * The resultant byte of the mask operation (see mask_byte) is compared for
+	 * equivalence with this test pattern. If equal, the read/write will take
+	 * place.
+	 */
 	command[4] = test_pattern;
 
-	// This value is logically ANDed with the status register field specified
-	// in the read/write command.
+	/*
+	 * This value is logically ANDed with the status register field specified
+	 * in the read/write command.
+	 */
 	command[5] = mask_byte;
 
-	// If ALQ is set in the qualifier, this field contains the address of the
-	// registers where the byte count should be read for transferring the data.
-	// If ALQ is not set, then this field contains the number of bytes to be
-	// transferred.
+	/*
+	 * If ALQ is set in the qualifier, this field contains the address of the
+	 * registers where the byte count should be read for transferring the data.
+	 * If ALQ is not set, then this field contains the number of bytes to be
+	 * transferred.
+	 */
 	command[6] = subcountL;
 	command[7] = subcountH;
 
@@ -273,26 +285,26 @@
 
 		if (result!=USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
-		if (*status & 0x01) { // check condition
+		if (*status & 0x01) { /* check condition */
 			result = usbat_read(us, USBAT_ATA, 0x10, status);
 			return USB_STOR_TRANSPORT_FAILED;
 		}
-		if (*status & 0x20) // device fault
+		if (*status & 0x20) /* device fault */
 			return USB_STOR_TRANSPORT_FAILED;
 
-		if ((*status & 0x80)==0x00) { // not busy
+		if ((*status & 0x80)==0x00) { /* not busy */
 			US_DEBUGP("Waited not busy for %d steps\n", i);
 			return USB_STOR_TRANSPORT_GOOD;
 		}
 
 		if (i<500)
-			msleep(10); // 5 seconds
+			msleep(10); /* 5 seconds */
 		else if (i<700)
-			msleep(50); // 10 seconds
+			msleep(50); /* 10 seconds */
 		else if (i<1200)
-			msleep(100); // 50 seconds
+			msleep(100); /* 50 seconds */
 		else
-			msleep(1000); // X minutes
+			msleep(1000); /* X minutes */
 	}
 
 	US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
@@ -412,9 +424,12 @@
 
 		if (i==0) {
 			cmdlen = 16;
-			// Write to multiple registers
-			// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
-			// but that's what came out of the trace every single time.
+			/*
+			 * Write to multiple registers
+			 * Not really sure the 0x07, 0x17, 0xfc, 0xe7 is
+			 * necessary here, but that's what came out of the
+			 * trace every single time.
+			 */
 			command[0] = 0x40;
 			command[1] = access | USBAT_CMD_WRITE_REGS;
 			command[2] = 0x07;
@@ -426,7 +441,7 @@
 		} else
 			cmdlen = 8;
 
-		// Conditionally read or write blocks
+		/* Conditionally read or write blocks */
 		command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
 		command[cmdlen-7] = access |
 				(direction==DMA_TO_DEVICE ?
@@ -456,11 +471,6 @@
 
 		}
 
-
-		//US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
-		//	direction == DMA_TO_DEVICE ? "out" : "in",
-		//	len, use_sg);
-
 		result = usb_stor_bulk_transfer_sg(us,
 			pipe, content, len, use_sg, NULL);
 
@@ -508,9 +518,9 @@
 
 			if (result!=USB_STOR_XFER_GOOD)
 				return USB_STOR_TRANSPORT_ERROR;
-			if (*status & 0x01) // check condition
+			if (*status & 0x01) /* check condition */
 				return USB_STOR_TRANSPORT_FAILED;
-			if (*status & 0x20) // device fault
+			if (*status & 0x20) /* device fault */
 				return USB_STOR_TRANSPORT_FAILED;
 
 			US_DEBUGP("Redoing %s\n",
@@ -547,32 +557,32 @@
 
 	BUG_ON(num_registers > US_IOBUF_SIZE/2);
 
-	// Write to multiple registers, ATA access
+	/* Write to multiple registers, ATA access */
 	command[0] = 0x40;
 	command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS;
 
-	// No relevance
+	/* No relevance */
 	command[2] = 0;
 	command[3] = 0;
 	command[4] = 0;
 	command[5] = 0;
 
-	// Number of bytes to be transferred (incl. addresses and data)
+	/* Number of bytes to be transferred (incl. addresses and data) */
 	command[6] = LSB_of(num_registers*2);
 	command[7] = MSB_of(num_registers*2);
 
-	// The setup command
+	/* The setup command */
 	result = usbat_execute_command(us, command, 8);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	// Create the reg/data, reg/data sequence
+	/* Create the reg/data, reg/data sequence */
 	for (i=0; i<num_registers; i++) {
 		data[i<<1] = registers[i];
 		data[1+(i<<1)] = data_out[i];
 	}
 
-	// Send the data
+	/* Send the data */
 	result = usbat_bulk_write(us, data, num_registers*2);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -606,17 +616,17 @@
 	command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK;
 	command[2] = USBAT_ATA_DATA;
 	command[3] = USBAT_ATA_STATUS;
-	command[4] = 0xFD; // Timeout (ms);
+	command[4] = 0xFD; /* Timeout (ms); */
 	command[5] = USBAT_QUAL_FCQ;
 	command[6] = LSB_of(len);
 	command[7] = MSB_of(len);
 
-	// Multiple block read setup command
+	/* Multiple block read setup command */
 	result = usbat_execute_command(us, command, 8);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
 	
-	// Read the blocks we just asked for
+	/* Read the blocks we just asked for */
 	result = usbat_bulk_read(us, buffer, len);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
@@ -647,17 +657,17 @@
 	command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK;
 	command[2] = USBAT_ATA_DATA;
 	command[3] = USBAT_ATA_STATUS;
-	command[4] = 0xFD; // Timeout (ms)
+	command[4] = 0xFD; /* Timeout (ms) */
 	command[5] = USBAT_QUAL_FCQ;
 	command[6] = LSB_of(len);
 	command[7] = MSB_of(len);
 
-	// Multiple block write setup command
+	/* Multiple block write setup command */
 	result = usbat_execute_command(us, command, 8);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
 	
-	// Write the data
+	/* Write the data */
 	result = usbat_bulk_write(us, buffer, len);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
@@ -711,16 +721,20 @@
 {
 	int rc;
 
-	// Reset peripheral, enable peripheral control signals
-	// (bring reset signal up)
+	/*
+	 * Reset peripheral, enable peripheral control signals
+	 * (bring reset signal up)
+	 */
 	rc = usbat_write_user_io(us,
 							 USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
 							 USBAT_UIO_EPAD | USBAT_UIO_1);
 	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 			
-	// Enable peripheral control signals
-	// (bring reset signal down)
+	/*
+	 * Enable peripheral control signals
+	 * (bring reset signal down)
+	 */
 	rc = usbat_write_user_io(us,
 							 USBAT_UIO_OE1  | USBAT_UIO_OE0,
 							 USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -737,7 +751,7 @@
 {
 	int rc;
 
-	// Enable peripheral control signals and card detect
+	/* Enable peripheral control signals and card detect */
 	rc = usbat_write_user_io(us,
 							 USBAT_UIO_ACKD | USBAT_UIO_OE1  | USBAT_UIO_OE0,
 							 USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -786,7 +800,7 @@
 	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	// Check for media existence
+	/* Check for media existence */
 	rc = usbat_flash_check_media_present(uio);
 	if (rc == USBAT_FLASH_MEDIA_NONE) {
 		info->sense_key = 0x02;
@@ -795,11 +809,11 @@
 		return USB_STOR_TRANSPORT_FAILED;
 	}
 
-	// Check for media change
+	/* Check for media change */
 	rc = usbat_flash_check_media_changed(uio);
 	if (rc == USBAT_FLASH_MEDIA_CHANGED) {
 
-		// Reset and re-enable card detect
+		/* Reset and re-enable card detect */
 		rc = usbat_device_reset(us);
 		if (rc != USB_STOR_TRANSPORT_GOOD)
 			return rc;
@@ -855,15 +869,15 @@
  	if (rc != USB_STOR_XFER_GOOD)
  		return USB_STOR_TRANSPORT_ERROR;
 
-	// Check for error bit
-	if (status & 0x01) {
-		 // Device is a CompactFlash reader/writer
-		US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
-		info->devicetype = USBAT_DEV_FLASH;
-	} else {
-		// Device is HP 8200
+	/* Check for error bit, or if the command 'fell through' */
+	if (status == 0xA1 || !(status & 0x01)) {
+		/* Device is HP 8200 */
 		US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
 		info->devicetype = USBAT_DEV_HP8200;
+	} else {
+		/* Device is a CompactFlash reader/writer */
+		US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+		info->devicetype = USBAT_DEV_FLASH;
 	}
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -916,7 +930,7 @@
 	if (!reply)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	// ATAPI command : IDENTIFY DEVICE
+	/* ATA command : IDENTIFY DEVICE */
 	rc = usbat_multiple_write(us, registers, command, 3);
 	if (rc != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
@@ -924,7 +938,7 @@
 		goto leave;
 	}
 
-	// Read device status
+	/* Read device status */
 	if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {
 		rc = USB_STOR_TRANSPORT_ERROR;
 		goto leave;
@@ -932,7 +946,7 @@
 
 	msleep(100);
 
-	// Read the device identification data
+	/* Read the device identification data */
 	rc = usbat_read_block(us, reply, 512);
 	if (rc != USB_STOR_TRANSPORT_GOOD)
 		goto leave;
@@ -977,19 +991,23 @@
 	if (result != USB_STOR_TRANSPORT_GOOD)
 		return result;
 
-	// we're working in LBA mode.  according to the ATA spec,
-	// we can support up to 28-bit addressing.  I don't know if Jumpshot
-	// supports beyond 24-bit addressing.  It's kind of hard to test
-	// since it requires > 8GB CF card.
+	/*
+	 * we're working in LBA mode.  according to the ATA spec,
+	 * we can support up to 28-bit addressing.  I don't know if Jumpshot
+	 * supports beyond 24-bit addressing.  It's kind of hard to test
+	 * since it requires > 8GB CF card.
+	 */
 
 	if (sector > 0x0FFFFFFF)
 		return USB_STOR_TRANSPORT_ERROR;
 
 	totallen = sectors * info->ssize;
 
-	// Since we don't read more than 64 KB at a time, we have to create
-	// a bounce buffer and move the data a piece at a time between the
-	// bounce buffer and the actual transfer buffer.
+	/*
+	 * Since we don't read more than 64 KB at a time, we have to create
+	 * a bounce buffer and move the data a piece at a time between the
+	 * bounce buffer and the actual transfer buffer.
+	 */
 
 	alloclen = min(totallen, 65536u);
 	buffer = kmalloc(alloclen, GFP_NOIO);
@@ -997,27 +1015,29 @@
 		return USB_STOR_TRANSPORT_ERROR;
 
 	do {
-		// loop, never allocate or transfer more than 64k at once
-		// (min(128k, 255*info->ssize) is the real limit)
+		/*
+		 * loop, never allocate or transfer more than 64k at once
+		 * (min(128k, 255*info->ssize) is the real limit)
+		 */
 		len = min(totallen, alloclen);
 		thistime = (len / info->ssize) & 0xff;
  
-		// ATAPI command 0x20 (READ SECTORS)
-		usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x20);
+		/* ATA command 0x20 (READ SECTORS) */
+		usbat_pack_ata_sector_cmd(command, thistime, sector, 0x20);
 
-		// Write/execute ATAPI read command
+		/* Write/execute ATA read command */
 		result = usbat_multiple_write(us, registers, command, 7);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			goto leave;
 
-		// Read the data we just requested
+		/* Read the data we just requested */
 		result = usbat_read_blocks(us, buffer, len);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			goto leave;
   	 
 		US_DEBUGP("usbat_flash_read_data:  %d bytes\n", len);
 	
-		// Store the data in the transfer buffer
+		/* Store the data in the transfer buffer */
 		usb_stor_access_xfer_buf(buffer, len, us->srb,
 					 &sg_idx, &sg_offset, TO_XFER_BUF);
 
@@ -1061,19 +1081,23 @@
 	if (result != USB_STOR_TRANSPORT_GOOD)
 		return result;
 
-	// we're working in LBA mode.  according to the ATA spec,
-	// we can support up to 28-bit addressing.  I don't know if Jumpshot
-	// supports beyond 24-bit addressing.  It's kind of hard to test
-	// since it requires > 8GB CF card.
+	/*
+	 * we're working in LBA mode.  according to the ATA spec,
+	 * we can support up to 28-bit addressing.  I don't know if the device
+	 * supports beyond 24-bit addressing.  It's kind of hard to test
+	 * since it requires > 8GB media.
+	 */
 
 	if (sector > 0x0FFFFFFF)
 		return USB_STOR_TRANSPORT_ERROR;
 
 	totallen = sectors * info->ssize;
 
-	// Since we don't write more than 64 KB at a time, we have to create
-	// a bounce buffer and move the data a piece at a time between the
-	// bounce buffer and the actual transfer buffer.
+	/*
+	 * Since we don't write more than 64 KB at a time, we have to create
+	 * a bounce buffer and move the data a piece at a time between the
+	 * bounce buffer and the actual transfer buffer.
+	 */
 
 	alloclen = min(totallen, 65536u);
 	buffer = kmalloc(alloclen, GFP_NOIO);
@@ -1081,24 +1105,26 @@
 		return USB_STOR_TRANSPORT_ERROR;
 
 	do {
-		// loop, never allocate or transfer more than 64k at once
-		// (min(128k, 255*info->ssize) is the real limit)
+		/*
+		 * loop, never allocate or transfer more than 64k at once
+		 * (min(128k, 255*info->ssize) is the real limit)
+		 */
 		len = min(totallen, alloclen);
 		thistime = (len / info->ssize) & 0xff;
 
-		// Get the data from the transfer buffer
+		/* Get the data from the transfer buffer */
 		usb_stor_access_xfer_buf(buffer, len, us->srb,
 					 &sg_idx, &sg_offset, FROM_XFER_BUF);
 
-		// ATAPI command 0x30 (WRITE SECTORS)
-		usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x30);		
+		/* ATA command 0x30 (WRITE SECTORS) */
+		usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30);
 
-		// Write/execute ATAPI write command
+		/* Write/execute ATA write command */
 		result = usbat_multiple_write(us, registers, command, 7);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			goto leave;
 
-		// Write the data
+		/* Write the data */
 		result = usbat_write_blocks(us, buffer, len);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			goto leave;
@@ -1169,42 +1195,44 @@
 			srb->transfersize);
 	}
 
-	// Since we only read in one block at a time, we have to create
-	// a bounce buffer and move the data a piece at a time between the
-	// bounce buffer and the actual transfer buffer.
+	/*
+	 * Since we only read in one block at a time, we have to create
+	 * a bounce buffer and move the data a piece at a time between the
+	 * bounce buffer and the actual transfer buffer.
+	 */
 
 	len = (65535/srb->transfersize) * srb->transfersize;
 	US_DEBUGP("Max read is %d bytes\n", len);
 	len = min(len, srb->request_bufflen);
 	buffer = kmalloc(len, GFP_NOIO);
-	if (buffer == NULL) // bloody hell!
+	if (buffer == NULL) /* bloody hell! */
 		return USB_STOR_TRANSPORT_FAILED;
 	sector = short_pack(data[7+3], data[7+2]);
 	sector <<= 16;
 	sector |= short_pack(data[7+5], data[7+4]);
 	transferred = 0;
 
-	sg_segment = 0; // for keeping track of where we are in
-	sg_offset = 0;  // the scatter/gather list
+	sg_segment = 0; /* for keeping track of where we are in */
+	sg_offset = 0;  /* the scatter/gather list */
 
 	while (transferred != srb->request_bufflen) {
 
 		if (len > srb->request_bufflen - transferred)
 			len = srb->request_bufflen - transferred;
 
-		data[3] = len&0xFF; 	  // (cylL) = expected length (L)
-		data[4] = (len>>8)&0xFF;  // (cylH) = expected length (H)
+		data[3] = len&0xFF; 	  /* (cylL) = expected length (L) */
+		data[4] = (len>>8)&0xFF;  /* (cylH) = expected length (H) */
 
-		// Fix up the SCSI command sector and num sectors
+		/* Fix up the SCSI command sector and num sectors */
 
-		data[7+2] = MSB_of(sector>>16); // SCSI command sector
+		data[7+2] = MSB_of(sector>>16); /* SCSI command sector */
 		data[7+3] = LSB_of(sector>>16);
 		data[7+4] = MSB_of(sector&0xFFFF);
 		data[7+5] = LSB_of(sector&0xFFFF);
 		if (data[7+0] == GPCMD_READ_CD)
 			data[7+6] = 0;
-		data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
-		data[7+8] = LSB_of(len / srb->transfersize); // num sectors
+		data[7+7] = MSB_of(len / srb->transfersize); /* SCSI command */
+		data[7+8] = LSB_of(len / srb->transfersize); /* num sectors */
 
 		result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
@@ -1217,16 +1245,16 @@
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			break;
 
-		// Store the data in the transfer buffer
+		/* Store the data in the transfer buffer */
 		usb_stor_access_xfer_buf(buffer, len, srb,
 				 &sg_segment, &sg_offset, TO_XFER_BUF);
 
-		// Update the amount transferred and the sector number
+		/* Update the amount transferred and the sector number */
 
 		transferred += len;
 		sector += len / srb->transfersize;
 
-	} // while transferred != srb->request_bufflen
+	} /* while transferred != srb->request_bufflen */
 
 	kfree(buffer);
 	return result;
@@ -1237,7 +1265,7 @@
 	int selector;
 	unsigned char *status = us->iobuf;
 
-	// try device = master, then device = slave.
+	/* try device = master, then device = slave. */
 	for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
 		if (usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
 				USB_STOR_XFER_GOOD)
@@ -1298,7 +1326,7 @@
 	memset(us->extra, 0, sizeof(struct usbat_info));
 	info = (struct usbat_info *) (us->extra);
 
-	// Enable peripheral control signals
+	/* Enable peripheral control signals */
 	rc = usbat_write_user_io(us,
 				 USBAT_UIO_OE1 | USBAT_UIO_OE0,
 				 USBAT_UIO_EPAD | USBAT_UIO_1);
@@ -1337,7 +1365,7 @@
 
 	US_DEBUGP("INIT 5\n");
 
-	// Enable peripheral control signals and card detect
+	/* Enable peripheral control signals and card detect */
 	rc = usbat_device_enable_cdt(us);
 	if (rc != USB_STOR_TRANSPORT_GOOD)
 		return rc;
@@ -1364,7 +1392,7 @@
 
 	US_DEBUGP("INIT 9\n");
 
-	// At this point, we need to detect which device we are using
+	/* At this point, we need to detect which device we are using */
 	if (usbat_set_transport(us, info))
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -1414,10 +1442,10 @@
 	data[0] = 0x00;
 	data[1] = 0x00;
 	data[2] = 0x00;
-	data[3] = len&0xFF; 		// (cylL) = expected length (L)
-	data[4] = (len>>8)&0xFF; 	// (cylH) = expected length (H)
-	data[5] = 0xB0; 		// (device sel) = slave
-	data[6] = 0xA0; 		// (command) = ATA PACKET COMMAND
+	data[3] = len&0xFF; 		/* (cylL) = expected length (L) */
+	data[4] = (len>>8)&0xFF; 	/* (cylH) = expected length (H) */
+	data[5] = 0xB0; 		/* (device sel) = slave */
+	data[6] = 0xA0; 		/* (command) = ATA PACKET COMMAND */
 
 	for (i=7; i<19; i++) {
 		registers[i] = 0x10;
@@ -1466,13 +1494,15 @@
 		return result;
 	}
 
-	// Write the 12-byte command header.
-
-	// If the command is BLANK then set the timer for 75 minutes.
-	// Otherwise set it for 10 minutes.
-
-	// NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
-	// AT SPEED 4 IS UNRELIABLE!!!
+	/*
+	 * Write the 12-byte command header.
+	 *
+	 * If the command is BLANK then set the timer for 75 minutes.
+	 * Otherwise set it for 10 minutes.
+	 *
+	 * NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
+	 * AT SPEED 4 IS UNRELIABLE!!!
+	 */
 
 	if ( (result = usbat_write_block(us, 
 			USBAT_ATA, srb->cmnd, 12,
@@ -1481,19 +1511,18 @@
 		return result;
 	}
 
-	// If there is response data to be read in 
-	// then do it here.
+	/* If there is response data to be read in then do it here. */
 
 	if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) {
 
-		// How many bytes to read in? Check cylL register
+		/* How many bytes to read in? Check cylL register */
 
 		if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != 
 		    	USB_STOR_XFER_GOOD) {
 			return USB_STOR_TRANSPORT_ERROR;
 		}
 
-		if (len > 0xFF) { // need to read cylH also
+		if (len > 0xFF) { /* need to read cylH also */
 			len = *status;
 			if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) !=
 				    USB_STOR_XFER_GOOD) {
@@ -1556,13 +1585,16 @@
 		if (rc != USB_STOR_TRANSPORT_GOOD)
 			return rc;
 
-		info->ssize = 0x200;  // hard coded 512 byte sectors as per ATA spec
+		/* hard coded 512 byte sectors as per ATA spec */
+		info->ssize = 0x200;
 		US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
 			  info->sectors, info->ssize);
 
-		// build the reply
-		// note: must return the sector number of the last sector,
-		// *not* the total number of sectors
+		/*
+		 * build the reply
+		 * note: must return the sector number of the last sector,
+		 * *not* the total number of sectors
+		 */
 		((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
 		((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
@@ -1586,7 +1618,9 @@
 	}
 
 	if (srb->cmnd[0] == READ_12) {
-		// I don't think we'll ever see a READ_12 but support it anyway...
+		/*
+		 * I don't think we'll ever see a READ_12 but support it anyway
+		 */
 		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
 		        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 
@@ -1608,7 +1642,9 @@
 	}
 
 	if (srb->cmnd[0] == WRITE_12) {
-		// I don't think we'll ever see a WRITE_12 but support it anyway...
+		/*
+		 * I don't think we'll ever see a WRITE_12 but support it anyway
+		 */
 		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
 		        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
 
@@ -1645,8 +1681,10 @@
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
-		// sure.  whatever.  not like we can stop the user from popping
-		// the media out of the device (no locking doors, etc)
+		/*
+		 * sure.  whatever.  not like we can stop the user from popping
+		 * the media out of the device (no locking doors, etc)
+		 */
 		return USB_STOR_TRANSPORT_GOOD;
 	}
 
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 5b8e867..25e7d8b 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -55,8 +55,8 @@
 #define USBAT_UIO_WRITE	0
 
 /* Qualifier bits */
-#define USBAT_QUAL_FCQ	0x20 // full compare
-#define USBAT_QUAL_ALQ	0x10 // auto load subcount
+#define USBAT_QUAL_FCQ	0x20	/* full compare */
+#define USBAT_QUAL_ALQ	0x10	/* auto load subcount */
 
 /* USBAT Flash Media status types */
 #define USBAT_FLASH_MEDIA_NONE	0
@@ -67,39 +67,39 @@
 #define USBAT_FLASH_MEDIA_CHANGED	1
 
 /* USBAT ATA registers */
-#define USBAT_ATA_DATA      0x10  // read/write data (R/W)
-#define USBAT_ATA_FEATURES  0x11  // set features (W)
-#define USBAT_ATA_ERROR     0x11  // error (R)
-#define USBAT_ATA_SECCNT    0x12  // sector count (R/W)
-#define USBAT_ATA_SECNUM    0x13  // sector number (R/W)
-#define USBAT_ATA_LBA_ME    0x14  // cylinder low (R/W)
-#define USBAT_ATA_LBA_HI    0x15  // cylinder high (R/W)
-#define USBAT_ATA_DEVICE    0x16  // head/device selection (R/W)
-#define USBAT_ATA_STATUS    0x17  // device status (R)
-#define USBAT_ATA_CMD       0x17  // device command (W)
-#define USBAT_ATA_ALTSTATUS 0x0E  // status (no clear IRQ) (R)
+#define USBAT_ATA_DATA      0x10  /* read/write data (R/W) */
+#define USBAT_ATA_FEATURES  0x11  /* set features (W) */
+#define USBAT_ATA_ERROR     0x11  /* error (R) */
+#define USBAT_ATA_SECCNT    0x12  /* sector count (R/W) */
+#define USBAT_ATA_SECNUM    0x13  /* sector number (R/W) */
+#define USBAT_ATA_LBA_ME    0x14  /* cylinder low (R/W) */
+#define USBAT_ATA_LBA_HI    0x15  /* cylinder high (R/W) */
+#define USBAT_ATA_DEVICE    0x16  /* head/device selection (R/W) */
+#define USBAT_ATA_STATUS    0x17  /* device status (R) */
+#define USBAT_ATA_CMD       0x17  /* device command (W) */
+#define USBAT_ATA_ALTSTATUS 0x0E  /* status (no clear IRQ) (R) */
 
 /* USBAT User I/O Data registers */
-#define USBAT_UIO_EPAD		0x80 // Enable Peripheral Control Signals
-#define USBAT_UIO_CDT		0x40 // Card Detect (Read Only)
-				     // CDT = ACKD & !UI1 & !UI0
-#define USBAT_UIO_1		0x20 // I/O 1
-#define USBAT_UIO_0		0x10 // I/O 0
-#define USBAT_UIO_EPP_ATA	0x08 // 1=EPP mode, 0=ATA mode
-#define USBAT_UIO_UI1		0x04 // Input 1
-#define USBAT_UIO_UI0		0x02 // Input 0
-#define USBAT_UIO_INTR_ACK	0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
+#define USBAT_UIO_EPAD		0x80 /* Enable Peripheral Control Signals */
+#define USBAT_UIO_CDT		0x40 /* Card Detect (Read Only) */
+				     /* CDT = ACKD & !UI1 & !UI0 */
+#define USBAT_UIO_1		0x20 /* I/O 1 */
+#define USBAT_UIO_0		0x10 /* I/O 0 */
+#define USBAT_UIO_EPP_ATA	0x08 /* 1=EPP mode, 0=ATA mode */
+#define USBAT_UIO_UI1		0x04 /* Input 1 */
+#define USBAT_UIO_UI0		0x02 /* Input 0 */
+#define USBAT_UIO_INTR_ACK	0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */
 
 /* USBAT User I/O Enable registers */
-#define USBAT_UIO_DRVRST	0x80 // Reset Peripheral
-#define USBAT_UIO_ACKD		0x40 // Enable Card Detect
-#define USBAT_UIO_OE1		0x20 // I/O 1 set=output/clr=input
-				     // If ACKD=1, set OE1 to 1 also.
-#define USBAT_UIO_OE0		0x10 // I/O 0 set=output/clr=input
-#define USBAT_UIO_ADPRST	0x01 // Reset SCM chip
+#define USBAT_UIO_DRVRST	0x80 /* Reset Peripheral */
+#define USBAT_UIO_ACKD		0x40 /* Enable Card Detect */
+#define USBAT_UIO_OE1		0x20 /* I/O 1 set=output/clr=input */
+				     /* If ACKD=1, set OE1 to 1 also. */
+#define USBAT_UIO_OE0		0x10 /* I/O 0 set=output/clr=input */
+#define USBAT_UIO_ADPRST	0x01 /* Reset SCM chip */
 
 /* USBAT Features */
-#define USBAT_FEAT_ETEN	0x80 // External trigger enable
+#define USBAT_FEAT_ETEN	0x80	/* External trigger enable */
 #define USBAT_FEAT_U1	0x08
 #define USBAT_FEAT_U0	0x04
 #define USBAT_FEAT_ET1	0x02
@@ -112,12 +112,12 @@
 	int devicetype;
 
 	/* Used for Flash readers only */
-	unsigned long sectors;     // total sector count
-	unsigned long ssize;       // sector size in bytes
+	unsigned long sectors;     /* total sector count */
+	unsigned long ssize;       /* sector size in bytes */
 
 	unsigned char sense_key;
-	unsigned long sense_asc;   // additional sense code
-	unsigned long sense_ascq;  // additional sense code qualifier
+	unsigned long sense_asc;   /* additional sense code */
+	unsigned long sense_ascq;  /* additional sense code qualifier */
 };
 
 #endif
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index c1ba530..7ca896a 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -636,11 +636,11 @@
 
 		/* use the new buffer we have */
 		old_request_buffer = srb->request_buffer;
-		srb->request_buffer = srb->sense_buffer;
+		srb->request_buffer = us->sensebuf;
 
 		/* set the buffer length for transfer */
 		old_request_bufflen = srb->request_bufflen;
-		srb->request_bufflen = 18;
+		srb->request_bufflen = US_SENSE_SIZE;
 
 		/* set up for no scatter-gather use */
 		old_sg = srb->use_sg;
@@ -652,6 +652,7 @@
 		temp_result = us->transport(us->srb, us);
 
 		/* let's clean up right away */
+		memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE);
 		srb->resid = old_resid;
 		srb->request_buffer = old_request_buffer;
 		srb->request_bufflen = old_request_bufflen;
@@ -923,6 +924,7 @@
 	int result;
 
 	/* issue the command */
+	us->iobuf[0] = 0;
 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
 				 US_BULK_GET_MAX_LUN, 
 				 USB_DIR_IN | USB_TYPE_CLASS | 
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 8d9e066..0a362cc 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -50,7 +50,7 @@
 #define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
 #define US_PR_BULK	0x50		/* bulk only */
 #ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_SCM_ATAPI	0x80		/* SCM-ATAPI bridge */
+#define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
 #endif
 #ifdef CONFIG_USB_STORAGE_SDDR09
 #define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index b79dad1..9e926a8 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -71,12 +71,12 @@
 UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), 
+		US_SC_8070, US_PR_USBAT, init_usbat, 0),
 
 UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ CD-4e",
-		US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), 
+		US_SC_8070, US_PR_USBAT, init_usbat, 0),
 #endif
 
 /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
@@ -106,6 +106,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Reported by Stefan Werner <dustbln@gmx.de> */
+UNUSUAL_DEV(  0x0419, 0xaaf6, 0x0100, 0x0100,
+		"TrekStor",
+		"i.Beat Joy 2.0",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
 UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
 		"SMSC",
@@ -244,6 +251,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
+/* Reported by Simeon Simeonov <simeonov_2000@yahoo.com> */
+UNUSUAL_DEV(  0x04da, 0x2373, 0x0000, 0x9999,
+		"LEICA",
+		"D-LUX Camera",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
+
 /* Most of the following entries were developed with the help of
  * Shuttle/SCM directly.
  */
@@ -333,9 +347,9 @@
 
 #ifdef CONFIG_USB_STORAGE_USBAT
 UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
-		"SCM",
-		"SCM USBAT-02",
-		US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
+		"Shuttle/SCM",
+		"USBAT-02",
+		US_SC_SCSI, US_PR_USBAT, init_usbat,
 		US_FL_SINGLE_LUN),
 #endif
 
@@ -598,6 +612,16 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
+/*
+ * Reported by Tyson Vinson <lornoss@gmail.com>
+ * This particular productId is the iPod Nano
+ */
+UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999,
+		"Apple",
+		"iPod",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 #ifdef CONFIG_USB_STORAGE_JUMPSHOT
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
 		"Lexar",
@@ -702,6 +726,14 @@
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
+#ifdef CONFIG_USB_STORAGE_USBAT
+UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
+		"Sandisk",
+		"ImageMate SDDR-05b",
+		US_SC_SCSI, US_PR_USBAT, init_usbat,
+		US_FL_SINGLE_LUN ),
+#endif
+
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
 		"ImageMate SDDR-12",
@@ -724,7 +756,7 @@
 #endif
 
 /* Reported by Eero Volotinen <eero@ping-viini.org> */
-UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0406, 0x0406,
+UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
 		"Freecom Technologies",
 		"FHD-Classic",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index f9a9bfa..3847ebe 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -54,6 +54,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -111,11 +112,6 @@
 static DECLARE_COMPLETION(threads_gone);
 
 
-static int storage_probe(struct usb_interface *iface,
-			 const struct usb_device_id *id);
-
-static void storage_disconnect(struct usb_interface *iface);
-
 /* The entries in this table, except for final ones here
  * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
  * line for line with the entries of us_unsuaul_dev_list[].
@@ -233,13 +229,40 @@
 	{ NULL }
 };
 
-static struct usb_driver usb_storage_driver = {
-	.owner =	THIS_MODULE,
-	.name =		"usb-storage",
-	.probe =	storage_probe,
-	.disconnect =	storage_disconnect,
-	.id_table =	storage_usb_ids,
-};
+
+#ifdef CONFIG_PM	/* Minimal support for suspend and resume */
+
+static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+{
+	struct us_data *us = usb_get_intfdata(iface);
+
+	/* Wait until no command is running */
+	down(&us->dev_semaphore);
+
+	US_DEBUGP("%s\n", __FUNCTION__);
+	iface->dev.power.power_state.event = message.event;
+
+	/* When runtime PM is working, we'll set a flag to indicate
+	 * whether we should autoresume when a SCSI request arrives. */
+
+	up(&us->dev_semaphore);
+	return 0;
+}
+
+static int storage_resume(struct usb_interface *iface)
+{
+	struct us_data *us = usb_get_intfdata(iface);
+
+	down(&us->dev_semaphore);
+
+	US_DEBUGP("%s\n", __FUNCTION__);
+	iface->dev.power.power_state.event = PM_EVENT_ON;
+
+	up(&us->dev_semaphore);
+	return 0;
+}
+
+#endif /* CONFIG_PM */
 
 /*
  * fill_inquiry_response takes an unsigned char array (which must
@@ -288,22 +311,7 @@
 	struct us_data *us = (struct us_data *)__us;
 	struct Scsi_Host *host = us_to_host(us);
 
-	lock_kernel();
-
-	/*
-	 * This thread doesn't need any user-level access,
-	 * so get rid of all our resources.
-	 */
-	daemonize("usb-storage");
 	current->flags |= PF_NOFREEZE;
-	unlock_kernel();
-
-	/* acquire a reference to the host, so it won't be deallocated
-	 * until we're ready to exit */
-	scsi_host_get(host);
-
-	/* signal that we've started the thread */
-	complete(&(us->notify));
 
 	for(;;) {
 		US_DEBUGP("*** thread sleeping.\n");
@@ -467,6 +475,12 @@
 		US_DEBUGP("I/O buffer allocation failed\n");
 		return -ENOMEM;
 	}
+
+	us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);
+	if (!us->sensebuf) {
+		US_DEBUGP("Sense buffer allocation failed\n");
+		return -ENOMEM;
+	}
 	return 0;
 }
 
@@ -555,8 +569,8 @@
 		break;
 
 #ifdef CONFIG_USB_STORAGE_USBAT
-	case US_PR_SCM_ATAPI:
-		us->transport_name = "SCM/ATAPI";
+	case US_PR_USBAT:
+		us->transport_name = "Shuttle USBAT";
 		us->transport = usbat_transport;
 		us->transport_reset = usb_stor_CB_reset;
 		us->max_lun = 1;
@@ -740,6 +754,7 @@
 static int usb_stor_acquire_resources(struct us_data *us)
 {
 	int p;
+	struct task_struct *th;
 
 	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!us->current_urb) {
@@ -747,38 +762,28 @@
 		return -ENOMEM;
 	}
 
-	/* Lock the device while we carry out the next two operations */
-	down(&us->dev_semaphore);
-
-	/* For bulk-only devices, determine the max LUN value */
-	if (us->protocol == US_PR_BULK) {
-		p = usb_stor_Bulk_max_lun(us);
-		if (p < 0) {
-			up(&us->dev_semaphore);
-			return p;
-		}
-		us->max_lun = p;
-	}
-
 	/* Just before we start our control thread, initialize
 	 * the device if it needs initialization */
-	if (us->unusual_dev->initFunction)
-		us->unusual_dev->initFunction(us);
-
-	up(&us->dev_semaphore);
+	if (us->unusual_dev->initFunction) {
+		p = us->unusual_dev->initFunction(us);
+		if (p)
+			return p;
+	}
 
 	/* Start up our control thread */
-	p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
-	if (p < 0) {
+	th = kthread_create(usb_stor_control_thread, us, "usb-storage");
+	if (IS_ERR(th)) {
 		printk(KERN_WARNING USB_STORAGE 
 		       "Unable to start control thread\n");
-		return p;
+		return PTR_ERR(th);
 	}
-	us->pid = p;
-	atomic_inc(&total_threads);
 
-	/* Wait for the thread to start */
-	wait_for_completion(&(us->notify));
+	/* Take a reference to the host for the control thread and
+	 * count it among all the threads we have launched.  Then
+	 * start it up. */
+	scsi_host_get(us_to_host(us));
+	atomic_inc(&total_threads);
+	wake_up_process(th);
 
 	return 0;
 }
@@ -812,6 +817,8 @@
 {
 	US_DEBUGP("-- %s\n", __FUNCTION__);
 
+	kfree(us->sensebuf);
+
 	/* Free the device-related DMA-mapped buffers */
 	if (us->cr)
 		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
@@ -872,21 +879,6 @@
 {
 	struct us_data *us = (struct us_data *)__us;
 
-	/*
-	 * This thread doesn't need any user-level access,
-	 * so get rid of all our resources.
-	 */
-	lock_kernel();
-	daemonize("usb-stor-scan");
-	unlock_kernel();
-
-	/* Acquire a reference to the host, so it won't be deallocated
-	 * until we're ready to exit */
-	scsi_host_get(us_to_host(us));
-
-	/* Signal that we've started the thread */
-	complete(&(us->notify));
-
 	printk(KERN_DEBUG
 		"usb-storage: device found at %d\n", us->pusb_dev->devnum);
 
@@ -904,6 +896,14 @@
 
 	/* If the device is still connected, perform the scanning */
 	if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+
+		/* For bulk-only devices, determine the max LUN value */
+		if (us->protocol == US_PR_BULK &&
+				!(us->flags & US_FL_SINGLE_LUN)) {
+			down(&us->dev_semaphore);
+			us->max_lun = usb_stor_Bulk_max_lun(us);
+			up(&us->dev_semaphore);
+		}
 		scsi_scan_host(us_to_host(us));
 		printk(KERN_DEBUG "usb-storage: device scan complete\n");
 
@@ -923,6 +923,7 @@
 	struct us_data *us;
 	const int id_index = id - storage_usb_ids; 
 	int result;
+	struct task_struct *th;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
 
@@ -1003,17 +1004,21 @@
 	}
 
 	/* Start up the thread for delayed SCSI-device scanning */
-	result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM);
-	if (result < 0) {
+	th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
+	if (IS_ERR(th)) {
 		printk(KERN_WARNING USB_STORAGE 
 		       "Unable to start the device-scanning thread\n");
 		quiesce_and_remove_host(us);
+		result = PTR_ERR(th);
 		goto BadDevice;
 	}
-	atomic_inc(&total_threads);
 
-	/* Wait for the thread to start */
-	wait_for_completion(&(us->notify));
+	/* Take a reference to the host for the scanning thread and
+	 * count it among all the threads we have launched.  Then
+	 * start it up. */
+	scsi_host_get(us_to_host(us));
+	atomic_inc(&total_threads);
+	wake_up_process(th);
 
 	return 0;
 
@@ -1038,6 +1043,18 @@
  * Initialization and registration
  ***********************************************************************/
 
+static struct usb_driver usb_storage_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"usb-storage",
+	.probe =	storage_probe,
+	.disconnect =	storage_disconnect,
+#ifdef CONFIG_PM
+	.suspend =	storage_suspend,
+	.resume =	storage_resume,
+#endif
+	.id_table =	storage_usb_ids,
+};
+
 static int __init usb_stor_init(void)
 {
 	int retval;
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index a195ada..98b0971 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -117,6 +117,7 @@
  */
 
 #define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
+#define US_SENSE_SIZE		18	/* Size of the autosense data buffer */
 
 typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
@@ -160,14 +161,12 @@
 	struct scsi_cmnd	*srb;		 /* current srb		*/
 	unsigned int		tag;		 /* current dCBWTag	*/
 
-	/* thread information */
-	int			pid;		 /* control thread	 */
-
 	/* control and bulk communications data */
 	struct urb		*current_urb;	 /* USB requests	 */
 	struct usb_ctrlrequest	*cr;		 /* control requests	 */
 	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */
 	unsigned char		*iobuf;		 /* I/O buffer		 */
+	unsigned char		*sensebuf;	 /* sense data buffer	 */
 	dma_addr_t		cr_dma;		 /* buffer DMA addresses */
 	dma_addr_t		iobuf_dma;
 
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 353f24d..6c3a53f 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -223,9 +223,8 @@
  * and to have the device registered with devfs and the driver core
  */
 static struct usb_class_driver skel_class = {
-	.name =		"usb/skel%d",
+	.name =		"skel%d",
 	.fops =		&skel_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
 	.minor_base =	USB_SKEL_MINOR_BASE,
 };
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 1cd942a..7192b77 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -494,7 +494,7 @@
 
 config FB_VESA
 	bool "VESA VGA graphics support"
-	depends on (FB = y) && (X86 || X86_64)
+	depends on (FB = y) && X86
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -712,7 +712,7 @@
 
 config FB_I810
 	tristate "Intel 810/815 support (EXPERIMENTAL)"
-	depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+	depends on FB && EXPERIMENTAL && PCI && X86_32
 	select AGP
 	select AGP_INTEL
 	select FB_MODE_HELPERS
@@ -761,7 +761,7 @@
 
 config FB_INTEL
 	tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
-	depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+	depends on FB && EXPERIMENTAL && PCI && X86_32
 	select AGP
 	select AGP_INTEL
 	select FB_MODE_HELPERS
@@ -1376,7 +1376,7 @@
 
 config FB_PMAG_AA
 	bool "PMAG-AA TURBOchannel framebuffer support"
-	depends on (FB = y) && MACH_DECSTATION && TC
+	depends on (FB = y) && TC
  	select FB_CFB_FILLRECT
  	select FB_CFB_COPYAREA
  	select FB_CFB_IMAGEBLIT
@@ -1387,7 +1387,7 @@
 
 config FB_PMAG_BA
 	bool "PMAG-BA TURBOchannel framebuffer support"
-	depends on (FB = y) && MACH_DECSTATION && TC
+	depends on (FB = y) && TC
  	select FB_CFB_FILLRECT
  	select FB_CFB_COPYAREA
  	select FB_CFB_IMAGEBLIT
@@ -1398,7 +1398,7 @@
 
 config FB_PMAGB_B
 	bool "PMAGB-B TURBOchannel framebuffer support"
-	depends on (FB = y) && MACH_DECSTATION && TC
+	depends on (FB = y) && TC
  	select FB_CFB_FILLRECT
  	select FB_CFB_COPYAREA
  	select FB_CFB_IMAGEBLIT
@@ -1410,7 +1410,7 @@
 
 config FB_MAXINE
 	bool "Maxine (Personal DECstation) onboard framebuffer support"
-	depends on (FB = y) && MACH_DECSTATION && TC
+	depends on (FB = y) && MACH_DECSTATION
  	select FB_CFB_FILLRECT
  	select FB_CFB_COPYAREA
  	select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 1fff29f..97c5d03 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -86,7 +86,7 @@
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
 obj-$(CONFIG_FB_PXA)		  += pxafb.o
 obj-$(CONFIG_FB_W100)		  += w100fb.o
-obj-$(CONFIG_FB_AU1100)		  += au1100fb.o fbgen.o
+obj-$(CONFIG_FB_AU1100)		  += au1100fb.o
 obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
 obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
 obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 321dbe9..cde6fd8 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -22,6 +22,7 @@
 #include <linux/ioport.h>
 #include <linux/list.h>
 
+#include <asm/sizes.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/clock.h>
 
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index b6fe30c..a512980 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -2,6 +2,11 @@
  * BRIEF MODULE DESCRIPTION
  *	Au1100 LCD Driver.
  *
+ * Rewritten for 2.6 by Embedded Alley Solutions
+ * 	<source@embeddedalley.com>, based on submissions by
+ *  	Karl Lessard <klessard@sunrisetelecom.com>
+ *  	<c.pellegrin@exadron.com>
+ *
  * Copyright 2002 MontaVista Software
  * Author: MontaVista Software, Inc.
  *		ppopov@mvista.com or source@mvista.com
@@ -33,298 +38,253 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
 
-#include <asm/au1000.h>
-#include <asm/pb1100.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#define DEBUG 0
+
 #include "au1100fb.h"
 
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon-cfb2.h>
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
 /*
  * Sanity check. If this is a new Au1100 based board, search for
  * the PB1100 ifdefs to make sure you modify the code accordingly.
  */
-#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3)
+#if defined(CONFIG_MIPS_PB1100)
+  #include <asm/mach-pb1x00/pb1100.h>
+#elif defined(CONFIG_MIPS_DB1100)
+  #include <asm/mach-db1x00/db1x00.h>
 #else
-error Unknown Au1100 board
+  #error "Unknown Au1100 board, Au1100 FB driver not supported"
 #endif
 
-#define CMAPSIZE 16
+#define DRIVER_NAME "au1100fb"
+#define DRIVER_DESC "LCD controller driver for AU1100 processors"
 
-static int my_lcd_index; /* default is zero */
-struct known_lcd_panels *p_lcd;
-AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR;
+#define to_au1100fb_device(_info) \
+	  (_info ? container_of(_info, struct au1100fb_device, info) : NULL);
 
-struct au1100fb_info {
-	struct fb_info_gen gen;
-	unsigned long fb_virt_start;
-	unsigned long fb_size;
-	unsigned long fb_phys;
-	int mmaped;
-	int nohwcursor;
-
-	struct { unsigned red, green, blue, pad; } palette[256];
-
-#if defined(FBCON_HAS_CFB16)
-	u16 fbcon_cmap16[16];
-#endif
-};
-
-
-struct au1100fb_par {
-        struct fb_var_screeninfo var;
-
-	int line_length;  // in bytes
-	int cmap_len;     // color-map length
-};
-
-
-static struct au1100fb_info fb_info;
-static struct au1100fb_par current_par;
-static struct display disp;
-
-int au1100fb_init(void);
-void au1100fb_setup(char *options, int *ints);
-static int au1100fb_mmap(struct fb_info *fb, struct file *file,
-		struct vm_area_struct *vma);
-static int au1100_blank(int blank_mode, struct fb_info_gen *info);
-static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-			  u_long arg, int con, struct fb_info *info);
-
-void au1100_nocursor(struct display *p, int mode, int xx, int yy){};
-
-static struct fb_ops au1100fb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_get_fix	= fbgen_get_fix,
-	.fb_get_var	= fbgen_get_var,
-	.fb_set_var	= fbgen_set_var,
-	.fb_get_cmap	= fbgen_get_cmap,
-	.fb_set_cmap	= fbgen_set_cmap,
-	.fb_pan_display	= fbgen_pan_display,
-        .fb_ioctl	= au1100fb_ioctl,
-	.fb_mmap	= au1100fb_mmap,
-};
-
-static void au1100_detect(void)
+/* Bitfields format supported by the controller. Note that the order of formats
+ * SHOULD be the same as in the LCD_CONTROL_SBPPF field, so we can retrieve the
+ * right pixel format by doing rgb_bitfields[LCD_CONTROL_SBPPF_XXX >> LCD_CONTROL_SBPPF]
+ */
+struct fb_bitfield rgb_bitfields[][4] =
 {
-	/*
-	 *  This function should detect the current video mode settings
-	 *  and store it as the default video mode
+  	/*     Red, 	   Green, 	 Blue, 	     Transp   */
+	{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+	{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+	{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+	{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+	{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+	/* The last is used to describe 12bpp format */
+	{ { 8, 4, 0 },  { 4, 4, 0 }, { 0, 4, 0 }, { 0, 0, 0 } },
+};
+
+static struct fb_fix_screeninfo au1100fb_fix __initdata = {
+	.id		= "AU1100 FB",
+	.xpanstep 	= 1,
+	.ypanstep 	= 1,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo au1100fb_var __initdata = {
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.vmode		= FB_VMODE_NONINTERLACED,
+};
+
+static struct au1100fb_drv_info drv_info;
+
+/*
+ * Set hardware with var settings. This will enable the controller with a specific
+ * mode, normally validated with the fb_check_var method
 	 */
-
-	/*
-	 * Yeh, well, we're not going to change any settings so we're
-	 * always stuck with the default ...
-	 */
-
-}
-
-static int au1100_encode_fix(struct fb_fix_screeninfo *fix,
-		const void *_par, struct fb_info_gen *_info)
+int au1100fb_setmode(struct au1100fb_device *fbdev)
 {
-        struct au1100fb_info *info = (struct au1100fb_info *) _info;
-        struct au1100fb_par *par = (struct au1100fb_par *) _par;
-	struct fb_var_screeninfo *var = &par->var;
+	struct fb_info *info = &fbdev->info;
+	u32 words;
+	int index;
 
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	if (!fbdev)
+		return -EINVAL;
 
-	fix->smem_start = info->fb_phys;
-	fix->smem_len = info->fb_size;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-        fix->visual = (var->bits_per_pixel == 8) ?
-	       	FB_VISUAL_PSEUDOCOLOR	: FB_VISUAL_TRUECOLOR;
-	fix->ywrapstep = 0;
-	fix->xpanstep = 1;
-	fix->ypanstep = 1;
-	fix->line_length = current_par.line_length;
+	/* Update var-dependent FB info */
+	if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) {
+		if (info->var.bits_per_pixel <= 8) {
+			/* palettized */
+			info->var.red.offset    = 0;
+			info->var.red.length    = info->var.bits_per_pixel;
+			info->var.red.msb_right = 0;
+
+			info->var.green.offset  = 0;
+			info->var.green.length  = info->var.bits_per_pixel;
+			info->var.green.msb_right = 0;
+
+			info->var.blue.offset   = 0;
+			info->var.blue.length   = info->var.bits_per_pixel;
+			info->var.blue.msb_right = 0;
+
+			info->var.transp.offset = 0;
+			info->var.transp.length = 0;
+			info->var.transp.msb_right = 0;
+
+			info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+			info->fix.line_length = info->var.xres_virtual /
+							(8/info->var.bits_per_pixel);
+		} else {
+			/* non-palettized */
+			index = (fbdev->panel->control_base & LCD_CONTROL_SBPPF_MASK) >> LCD_CONTROL_SBPPF_BIT;
+			info->var.red = rgb_bitfields[index][0];
+			info->var.green = rgb_bitfields[index][1];
+			info->var.blue = rgb_bitfields[index][2];
+			info->var.transp = rgb_bitfields[index][3];
+
+			info->fix.visual = FB_VISUAL_TRUECOLOR;
+			info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */
+	}
+	} else {
+		/* mono */
+		info->fix.visual = FB_VISUAL_MONO10;
+		info->fix.line_length = info->var.xres_virtual / 8;
+	}
+
+	info->screen_size = info->fix.line_length * info->var.yres_virtual;
+
+	/* Determine BPP mode and format */
+	fbdev->regs->lcd_control = fbdev->panel->control_base |
+			    ((info->var.rotate/90) << LCD_CONTROL_SM_BIT);
+
+	fbdev->regs->lcd_intenable = 0;
+	fbdev->regs->lcd_intstatus = 0;
+
+	fbdev->regs->lcd_horztiming = fbdev->panel->horztiming;
+
+	fbdev->regs->lcd_verttiming = fbdev->panel->verttiming;
+
+	fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base;
+
+	fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys);
+
+	if (panel_is_dual(fbdev->panel)) {
+		/* Second panel display seconf half of screen if possible,
+		 * otherwise display the same as the first panel */
+		if (info->var.yres_virtual >= (info->var.yres << 1)) {
+			fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys +
+							  (info->fix.line_length *
+						          (info->var.yres_virtual >> 1)));
+		} else {
+			fbdev->regs->lcd_dmaaddr1 = LCD_DMA_SA_N(fbdev->fb_phys);
+		}
+	}
+
+	words = info->fix.line_length / sizeof(u32);
+	if (!info->var.rotate || (info->var.rotate == 180)) {
+		words *= info->var.yres_virtual;
+		if (info->var.rotate /* 180 */) {
+			words -= (words % 8); /* should be divisable by 8 */
+		}
+	}
+	fbdev->regs->lcd_words = LCD_WRD_WRDS_N(words);
+
+	fbdev->regs->lcd_pwmdiv = 0;
+	fbdev->regs->lcd_pwmhi = 0;
+
+	/* Resume controller */
+	fbdev->regs->lcd_control |= LCD_CONTROL_GO;
+
 	return 0;
 }
 
-static void set_color_bitfields(struct fb_var_screeninfo *var)
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
 {
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case 16:	/* RGB 565 */
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	}
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+	u32 *palette = fbdev->regs->lcd_pallettebase;
+	u32 value;
 
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-}
-
-static int au1100_decode_var(const struct fb_var_screeninfo *var,
-		void *_par, struct fb_info_gen *_info)
-{
-
-	struct au1100fb_par *par = (struct au1100fb_par *)_par;
-
-	/*
-	 * Don't allow setting any of these yet: xres and yres don't
-	 * make sense for LCD panels.
-	 */
-	if (var->xres != p_lcd->xres ||
-	    var->yres != p_lcd->yres ||
-	    var->xres != p_lcd->xres ||
-	    var->yres != p_lcd->yres) {
+	if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
 		return -EINVAL;
-	}
-	if(var->bits_per_pixel != p_lcd->bpp) {
-		return -EINVAL;
+
+	if (fbi->var.grayscale) {
+		/* Convert color to grayscale */
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
 	}
 
-	memset(par, 0, sizeof(struct au1100fb_par));
-	par->var = *var;
-
-	/* FIXME */
-	switch (var->bits_per_pixel) {
-		case 8:
-			par->var.bits_per_pixel = 8;
-			break;
-		case 16:
-			par->var.bits_per_pixel = 16;
-			break;
-		default:
-			printk("color depth %d bpp not supported\n",
-					var->bits_per_pixel);
+	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+		/* Place color in the pseudopalette */
+		if (regno > 16)
 			return -EINVAL;
 
-	}
-	set_color_bitfields(&par->var);
-	par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
-	return 0;
-}
+		palette = (u32*)fbi->pseudo_palette;
 
-static int au1100_encode_var(struct fb_var_screeninfo *var,
-		const void *par, struct fb_info_gen *_info)
-{
+		red   >>= (16 - fbi->var.red.length);
+		green >>= (16 - fbi->var.green.length);
+		blue  >>= (16 - fbi->var.blue.length);
 
-	*var = ((struct au1100fb_par *)par)->var;
-	return 0;
-}
+		value = (red   << fbi->var.red.offset) 	|
+			(green << fbi->var.green.offset)|
+			(blue  << fbi->var.blue.offset);
+		value &= 0xFFFF;
 
-static void
-au1100_get_par(void *_par, struct fb_info_gen *_info)
-{
-	*(struct au1100fb_par *)_par = current_par;
-}
+	} else if (panel_is_active(fbdev->panel)) {
+		/* COLOR TFT PALLETTIZED (use RGB 565) */
+		value = (red & 0xF800)|((green >> 5) & 0x07E0)|((blue >> 11) & 0x001F);
+		value &= 0xFFFF;
 
-static void au1100_set_par(const void *par, struct fb_info_gen *info)
-{
-	/* nothing to do: we don't change any settings */
-}
-
-static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			 unsigned *blue, unsigned *transp,
-			 struct fb_info *info)
-{
-
-	struct au1100fb_info* i = (struct au1100fb_info*)info;
-
-	if (regno > 255)
-		return 1;
-
-	*red    = i->palette[regno].red;
-	*green  = i->palette[regno].green;
-	*blue   = i->palette[regno].blue;
-	*transp = 0;
-
-	return 0;
-}
-
-static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green,
-			 unsigned blue, unsigned transp,
-			 struct fb_info *info)
-{
-	struct au1100fb_info* i = (struct au1100fb_info *)info;
-	u32 rgbcol;
-
-	if (regno > 255)
-		return 1;
-
-	i->palette[regno].red    = red;
-	i->palette[regno].green  = green;
-	i->palette[regno].blue   = blue;
-
-	switch(p_lcd->bpp) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		red >>= 10;
-		green >>= 10;
-		blue >>= 10;
-		p_lcd_reg->lcd_pallettebase[regno] = (blue&0x1f) |
-			((green&0x3f)<<5) | ((red&0x1f)<<11);
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		i->fbcon_cmap16[regno] =
-			((red & 0xf800) >> 0) |
-			((green & 0xfc00) >> 5) |
-			((blue & 0xf800) >> 11);
-		break;
-#endif
-	default:
-		break;
+	} else if (panel_is_color(fbdev->panel)) {
+		/* COLOR STN MODE */
+		value = (((panel_swap_rgb(fbdev->panel) ? blue : red) >> 12) & 0x000F) |
+			((green >> 8) & 0x00F0) |
+			(((panel_swap_rgb(fbdev->panel) ? red : blue) >> 4) & 0x0F00);
+		value &= 0xFFF;
+	} else {
+		/* MONOCHROME MODE */
+		value = (green >> 12) & 0x000F;
+		value &= 0xF;
 	}
 
+	palette[regno] = value;
+
 	return 0;
 }
 
-
-static int  au1100_blank(int blank_mode, struct fb_info_gen *_info)
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
 {
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+	print_dbg("fb_blank %d %p", blank_mode, fbi);
 
 	switch (blank_mode) {
+
 	case VESA_NO_BLANKING:
-		/* turn on panel */
-		//printk("turn on panel\n");
+			/* Turn on panel */
+			fbdev->regs->lcd_control |= LCD_CONTROL_GO;
 #ifdef CONFIG_MIPS_PB1100
-		p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
-		au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
+			if (drv_info.panel_idx == 1) {
+				au_writew(au_readw(PB1100_G_CONTROL)
+					  | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
 			PB1100_G_CONTROL);
-#endif
-#ifdef CONFIG_MIPS_HYDROGEN3
-		/*  Turn controller & power supply on,  GPIO213 */
-		au_writel(0x20002000, 0xB1700008);
-		au_writel(0x00040000, 0xB1900108);
-		au_writel(0x01000100, 0xB1700008);
+			}
 #endif
 		au_sync();
 		break;
@@ -332,12 +292,14 @@
 	case VESA_VSYNC_SUSPEND:
 	case VESA_HSYNC_SUSPEND:
 	case VESA_POWERDOWN:
-		/* turn off panel */
-		//printk("turn off panel\n");
+			/* Turn off panel */
+			fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
 #ifdef CONFIG_MIPS_PB1100
-		au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight,
+			if (drv_info.panel_idx == 1) {
+				au_writew(au_readw(PB1100_G_CONTROL)
+				  	  & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
 			PB1100_G_CONTROL);
-		p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO;
+			}
 #endif
 		au_sync();
 		break;
@@ -348,49 +310,87 @@
 	return 0;
 }
 
-static void au1100_set_disp(const void *unused, struct display *disp,
-			 struct fb_info_gen *info)
+/* fb_pan_display
+ * Pan display in x and/or y as specified
+ */
+int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
 {
-	disp->screen_base = (char *)fb_info.fb_virt_start;
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+	int dy;
 
-	switch (disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		disp->dispsw = &fbcon_cfb8;
-		if (fb_info.nohwcursor)
-			fbcon_cfb8.cursor = au1100_nocursor;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		disp->dispsw = &fbcon_cfb16;
-		disp->dispsw_data = fb_info.fbcon_cmap16;
-		if (fb_info.nohwcursor)
-			fbcon_cfb16.cursor = au1100_nocursor;
-		break;
-#endif
-	default:
-		disp->dispsw = &fbcon_dummy;
-		disp->dispsw_data = NULL;
-		break;
+	print_dbg("fb_pan_display %p %p", var, fbi);
+
+	if (!var || !fbdev) {
+		return -EINVAL;
+	}
+
+	if (var->xoffset - fbi->var.xoffset) {
+		/* No support for X panning for now! */
+		return -EINVAL;
+	}
+
+	print_dbg("fb_pan_display 2 %p %p", var, fbi);
+	dy = var->yoffset - fbi->var.yoffset;
+	if (dy) {
+
+		u32 dmaaddr;
+
+		print_dbg("Panning screen of %d lines", dy);
+
+		dmaaddr = fbdev->regs->lcd_dmaaddr0;
+		dmaaddr += (fbi->fix.line_length * dy);
+
+		/* TODO: Wait for current frame to finished */
+		fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
+
+		if (panel_is_dual(fbdev->panel)) {
+			dmaaddr = fbdev->regs->lcd_dmaaddr1;
+			dmaaddr += (fbi->fix.line_length * dy);
+			fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(dmaaddr);
+	}
+	}
+	print_dbg("fb_pan_display 3 %p %p", var, fbi);
+
+	return 0;
+}
+
+/* fb_rotate
+ * Rotate the display of this angle. This doesn't seems to be used by the core,
+ * but as our hardware supports it, so why not implementing it...
+ */
+void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
+{
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+
+	print_dbg("fb_rotate %p %d", fbi, angle);
+
+	if (fbdev && (angle > 0) && !(angle % 90)) {
+
+		fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
+
+		fbdev->regs->lcd_control &= ~(LCD_CONTROL_SM_MASK);
+		fbdev->regs->lcd_control |= ((angle/90) << LCD_CONTROL_SM_BIT);
+
+		fbdev->regs->lcd_control |= LCD_CONTROL_GO;
 	}
 }
 
-static int
-au1100fb_mmap(struct fb_info *_fb,
-	     struct file *file,
-	     struct vm_area_struct *vma)
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap method mainly
+ * to allow the use of the TLB streaming flag (CCA=6)
+ */
+int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma)
 {
+	struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
 	unsigned int len;
 	unsigned long start=0, off;
-	struct au1100fb_info *fb = (struct au1100fb_info *)_fb;
 
 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
 		return -EINVAL;
 	}
 
-	start = fb_info.fb_phys & PAGE_MASK;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size);
+	start = fbdev->fb_phys & PAGE_MASK;
+	len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
 
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
@@ -401,276 +401,309 @@
 	off += start;
 	vma->vm_pgoff = off >> PAGE_SHIFT;
 
-	pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
-	//pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
 
-	/* This is an IO map - tell maydump to skip this VMA */
 	vma->vm_flags |= VM_IO;
 
-	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+	if (io_remap_page_range(vma, vma->vm_start, off,
 				vma->vm_end - vma->vm_start,
 				vma->vm_page_prot)) {
 		return -EAGAIN;
 	}
 
-	fb->mmaped = 1;
 	return 0;
 }
 
-int au1100_pan_display(const struct fb_var_screeninfo *var,
-		       struct fb_info_gen *info)
+static struct fb_ops au1100fb_ops =
 {
-	return 0;
-}
-
-static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-			  u_long arg, int con, struct fb_info *info)
-{
-	/* nothing to do yet */
-	return -EINVAL;
-}
-
-static struct fbgen_hwswitch au1100_switch = {
-	au1100_detect,
-	au1100_encode_fix,
-	au1100_decode_var,
-	au1100_encode_var,
-	au1100_get_par,
-	au1100_set_par,
-	au1100_getcolreg,
-	au1100_setcolreg,
-	au1100_pan_display,
-	au1100_blank,
-	au1100_set_disp
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= au1100fb_fb_setcolreg,
+	.fb_blank		= au1100fb_fb_blank,
+	.fb_pan_display		= au1100fb_fb_pan_display,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_rotate		= au1100fb_fb_rotate,
+	.fb_mmap		= au1100fb_fb_mmap,
 };
 
 
-int au1100_setmode(void)
+/*-------------------------------------------------------------------------*/
+
+/* AU1100 LCD controller device driver */
+
+int au1100fb_drv_probe(struct device *dev)
 {
-	int words;
-
-	/* FIXME Need to accomodate for swivel mode and 12bpp, <8bpp*/
-	switch (p_lcd->mode_control & LCD_CONTROL_SM)
-	{
-		case LCD_CONTROL_SM_0:
-		case LCD_CONTROL_SM_180:
-		words = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 32;
-			break;
-		case LCD_CONTROL_SM_90:
-		case LCD_CONTROL_SM_270:
-			/* is this correct? */
-		words = (p_lcd->xres * p_lcd->bpp) / 8;
-			break;
-		default:
-			printk("mode_control reg not initialized\n");
-			return -EINVAL;
-	}
-
-	/*
-	 * Setup LCD controller
-	 */
-
-	p_lcd_reg->lcd_control = p_lcd->mode_control;
-	p_lcd_reg->lcd_intstatus = 0;
-	p_lcd_reg->lcd_intenable = 0;
-	p_lcd_reg->lcd_horztiming = p_lcd->mode_horztiming;
-	p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming;
-	p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol;
-	p_lcd_reg->lcd_words = words - 1;
-	p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys;
-
-	/* turn on panel */
-#ifdef CONFIG_MIPS_PB1100
-	au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
-			PB1100_G_CONTROL);
-#endif
-#ifdef CONFIG_MIPS_HYDROGEN3
-	/*  Turn controller & power supply on,  GPIO213 */
-	au_writel(0x20002000, 0xB1700008);
-	au_writel(0x00040000, 0xB1900108);
-	au_writel(0x01000100, 0xB1700008);
-#endif
-
-	p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
-
-	return 0;
-}
-
-
-int __init au1100fb_init(void)
-{
-	uint32 sys_clksrc;
+	struct au1100fb_device *fbdev = NULL;
+	struct resource *regs_res;
 	unsigned long page;
+	u32 sys_clksrc;
 
-	/*
-	* Get the panel information/display mode and update the registry
-	*/
-	p_lcd = &panels[my_lcd_index];
+	if (!dev)
+			return -EINVAL;
 
-	switch (p_lcd->mode_control & LCD_CONTROL_SM)
-	{
-		case LCD_CONTROL_SM_0:
-		case LCD_CONTROL_SM_180:
-		p_lcd->xres =
-			(p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1;
-		p_lcd->yres =
-			(p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1;
-			break;
-		case LCD_CONTROL_SM_90:
-		case LCD_CONTROL_SM_270:
-		p_lcd->yres =
-			(p_lcd->mode_horztiming & LCD_HORZTIMING_PPL) + 1;
-		p_lcd->xres =
-			(p_lcd->mode_verttiming & LCD_VERTTIMING_LPP) + 1;
-			break;
-	}
-
-	/*
-	 * Panel dimensions x bpp must be divisible by 32
-	 */
-	if (((p_lcd->yres * p_lcd->bpp) % 32) != 0)
-		printk("VERT %% 32\n");
-	if (((p_lcd->xres * p_lcd->bpp) % 32) != 0)
-		printk("HORZ %% 32\n");
-
-	/*
-	 * Allocate LCD framebuffer from system memory
-	 */
-	fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8;
-
-	current_par.var.xres = p_lcd->xres;
-	current_par.var.xres_virtual = p_lcd->xres;
-	current_par.var.yres = p_lcd->yres;
-	current_par.var.yres_virtual = p_lcd->yres;
-	current_par.var.bits_per_pixel = p_lcd->bpp;
-
-	/* FIX!!! only works for 8/16 bpp */
-	current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */
-	fb_info.fb_virt_start = (unsigned long )
-		__get_free_pages(GFP_ATOMIC | GFP_DMA,
-				get_order(fb_info.fb_size + 0x1000));
-	if (!fb_info.fb_virt_start) {
-		printk("Unable to allocate fb memory\n");
+	/* Allocate new device private */
+	if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
+		print_err("fail to allocate device private record");
 		return -ENOMEM;
 	}
-	fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start);
+	memset((void*)fbdev, 0, sizeof(struct au1100fb_device));
+
+	fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
+
+	dev_set_drvdata(dev, (void*)fbdev);
+
+	/* Allocate region for our registers and map them */
+	if (!(regs_res = platform_get_resource(to_platform_device(dev),
+					IORESOURCE_MEM, 0))) {
+		print_err("fail to retrieve registers resource");
+		return -EFAULT;
+	}
+
+	au1100fb_fix.mmio_start = regs_res->start;
+	au1100fb_fix.mmio_len = regs_res->end - regs_res->start + 1;
+
+	if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len,
+				DRIVER_NAME)) {
+		print_err("fail to lock memory region at 0x%08x",
+				au1100fb_fix.mmio_start);
+		return -EBUSY;
+	}
+
+	fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(au1100fb_fix.mmio_start);
+
+	print_dbg("Register memory map at %p", fbdev->regs);
+	print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
+
+
+
+	/* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
+	fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
+		  	(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
+
+	fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len),
+					&fbdev->fb_phys, GFP_KERNEL);
+	if (!fbdev->fb_mem) {
+		print_err("fail to allocate frambuffer (size: %dK))",
+			  fbdev->fb_len / 1024);
+		return -ENOMEM;
+	}
+
+	au1100fb_fix.smem_start = fbdev->fb_phys;
+	au1100fb_fix.smem_len = fbdev->fb_len;
 
 	/*
 	 * Set page reserved so that mmap will work. This is necessary
 	 * since we'll be remapping normal memory.
 	 */
-	for (page = fb_info.fb_virt_start;
-	     page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size);
+	for (page = (unsigned long)fbdev->fb_mem;
+	     page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
 	     page += PAGE_SIZE) {
+#if CONFIG_DMA_NONCOHERENT
+		SetPageReserved(virt_to_page(CAC_ADDR(page)));
+#else
 		SetPageReserved(virt_to_page(page));
+#endif
 	}
 
-	memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size);
+	print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+	print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
 
-	/* set freqctrl now to allow more time to stabilize */
-	/* zero-out out LCD bits */
-	sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0;
-	sys_clksrc |= p_lcd->mode_toyclksrc;
-	au_writel(sys_clksrc, SYS_CLKSRC);
+	/* Setup LCD clock to AUX (48 MHz) */
+	sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL);
+	au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC);
 
-	/* FIXME add check to make sure auxpll is what is expected! */
-	au1100_setmode();
+	/* load the panel info into the var struct */
+	au1100fb_var.bits_per_pixel = fbdev->panel->bpp;
+	au1100fb_var.xres = fbdev->panel->xres;
+	au1100fb_var.xres_virtual = au1100fb_var.xres;
+	au1100fb_var.yres = fbdev->panel->yres;
+	au1100fb_var.yres_virtual = au1100fb_var.yres;
 
-	fb_info.gen.parsize = sizeof(struct au1100fb_par);
-	fb_info.gen.fbhw = &au1100_switch;
+	fbdev->info.screen_base = fbdev->fb_mem;
+	fbdev->info.fbops = &au1100fb_ops;
+	fbdev->info.fix = au1100fb_fix;
 
-	strcpy(fb_info.gen.info.modename, "Au1100 LCD");
-	fb_info.gen.info.changevar = NULL;
-	fb_info.gen.info.node = -1;
+	if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) {
+		return -ENOMEM;
+	}
+	memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16);
 
-	fb_info.gen.info.fbops = &au1100fb_ops;
-	fb_info.gen.info.disp = &disp;
-	fb_info.gen.info.switch_con = &fbgen_switch;
-	fb_info.gen.info.updatevar = &fbgen_update_var;
-	fb_info.gen.info.blank = &fbgen_blank;
-	fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+	if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+		print_err("Fail to allocate colormap (%d entries)",
+			   AU1100_LCD_NBR_PALETTE_ENTRIES);
+		kfree(fbdev->info.pseudo_palette);
+		return -EFAULT;
+	}
 
-	/* This should give a reasonable default video mode */
-	fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
-	fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
-	fbgen_set_disp(-1, &fb_info.gen);
-	fbgen_install_cmap(0, &fb_info.gen);
-	if (register_framebuffer(&fb_info.gen.info) < 0)
-		return -EINVAL;
-	printk(KERN_INFO "fb%d: %s frame buffer device\n",
-			GET_FB_IDX(fb_info.gen.info.node),
-			fb_info.gen.info.modename);
+	fbdev->info.var = au1100fb_var;
+
+	/* Set h/w registers */
+	au1100fb_setmode(fbdev);
+
+	/* Register new framebuffer */
+	if (register_framebuffer(&fbdev->info) < 0) {
+		print_err("cannot register new framebuffer");
+		goto failed;
+	}
+
+	return 0;
+
+failed:
+	if (fbdev->regs) {
+		release_mem_region(fbdev->regs_phys, fbdev->regs_len);
+	}
+	if (fbdev->fb_mem) {
+		dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys);
+	}
+	if (fbdev->info.cmap.len != 0) {
+		fb_dealloc_cmap(&fbdev->info.cmap);
+	}
+	kfree(fbdev);
+	dev_set_drvdata(dev, NULL);
 
 	return 0;
 }
 
-
-void au1100fb_cleanup(struct fb_info *info)
+int au1100fb_drv_remove(struct device *dev)
 {
-	unregister_framebuffer(info);
+	struct au1100fb_device *fbdev = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	fbdev = (struct au1100fb_device*) dev_get_drvdata(dev);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
+#endif
+	fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
+
+	/* Clean up all probe data */
+	unregister_framebuffer(&fbdev->info);
+
+	release_mem_region(fbdev->regs_phys, fbdev->regs_len);
+
+	dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys);
+
+	fb_dealloc_cmap(&fbdev->info.cmap);
+	kfree(fbdev->info.pseudo_palette);
+	kfree((void*)fbdev);
+
+	return 0;
 }
 
+int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+	/* TODO */
+	return 0;
+}
 
-void au1100fb_setup(char *options, int *ints)
+int au1100fb_drv_resume(struct device *dev, u32 level)
+{
+	/* TODO */
+	return 0;
+}
+
+static struct device_driver au1100fb_driver = {
+	.name		= "au1100-lcd",
+	.bus		= &platform_bus_type,
+
+	.probe		= au1100fb_drv_probe,
+        .remove		= au1100fb_drv_remove,
+	.suspend	= au1100fb_drv_suspend,
+        .resume		= au1100fb_drv_resume,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Kernel driver */
+
+int au1100fb_setup(char *options)
 {
 	char* this_opt;
-	int i;
-	int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels);
+	int num_panels = ARRAY_SIZE(known_lcd_panels);
+	char* mode = NULL;
+	int panel_idx = 0;
 
-
-	if (!options || !*options)
-		return;
-
-	for(this_opt=strtok(options, ","); this_opt;
-	    this_opt=strtok(NULL, ",")) {
-		if (!strncmp(this_opt, "panel:", 6)) {
-#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
-			/* Read Pb1100 Switch S10 ? */
-			if (!strncmp(this_opt+6, "s10", 3))
-			{
-				int panel;
-				panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */
-				panel >>= 8;
-				panel &= 0x0F;
-				if (panel >= num_panels) panel = 0;
-				my_lcd_index = panel;
+	if (num_panels <= 0) {
+		print_err("No LCD panels supported by driver!");
+		return -EFAULT;
 			}
-			else
-#endif
-			/* Get the panel name, everything else if fixed */
-			for (i=0; i<num_panels; i++) {
-				if (!strncmp(this_opt+6, panels[i].panel_name,
+
+	if (options) {
+		while ((this_opt = strsep(&options,",")) != NULL) {
+			/* Panel option */
+		if (!strncmp(this_opt, "panel:", 6)) {
+				int i;
+				this_opt += 6;
+				for (i = 0; i < num_panels; i++) {
+					if (!strncmp(this_opt,
+					      	     known_lcd_panels[i].name,
 							strlen(this_opt))) {
-					my_lcd_index = i;
+						panel_idx = i;
 					break;
 				}
 			}
+				if (i >= num_panels) {
+ 					print_warn("Panel %s not supported!", this_opt);
+				}
+			}
+			/* Mode option (only option that start with digit) */
+			else if (isdigit(this_opt[0])) {
+				mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL);
+				strncpy(mode, this_opt, strlen(this_opt) + 1);
+			}
+			/* Unsupported option */
+			else {
+				print_warn("Unsupported option \"%s\"", this_opt);
 		}
-		else if (!strncmp(this_opt, "nohwcursor", 10)) {
-			printk("nohwcursor\n");
-			fb_info.nohwcursor = 1;
 		}
 	}
 
-	printk("au1100fb: Panel %d %s\n", my_lcd_index,
-		panels[my_lcd_index].panel_name);
+	drv_info.panel_idx = panel_idx;
+	drv_info.opt_mode = mode;
+
+	print_info("Panel=%s Mode=%s",
+			known_lcd_panels[drv_info.panel_idx].name,
+		      	drv_info.opt_mode ? drv_info.opt_mode : "default");
+
+	return 0;
 }
 
+int __init au1100fb_init(void)
+{
+	char* options;
+	int ret;
 
+	print_info("" DRIVER_DESC "");
 
-#ifdef MODULE
+	memset(&drv_info, 0, sizeof(drv_info));
+
+	if (fb_get_options(DRIVER_NAME, &options))
+		return -ENODEV;
+
+	/* Setup driver with options */
+	ret = au1100fb_setup(options);
+	if (ret < 0) {
+		print_err("Fail to setup driver");
+		return ret;
+	}
+
+	return driver_register(&au1100fb_driver);
+}
+
+void __exit au1100fb_cleanup(void)
+{
+	driver_unregister(&au1100fb_driver);
+
+	if (drv_info.opt_mode)
+		kfree(drv_info.opt_mode);
+}
+
+module_init(au1100fb_init);
+module_exit(au1100fb_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-int init_module(void)
-{
-	return au1100fb_init();
-}
-
-void cleanup_module(void)
-{
-	au1100fb_cleanup(void);
-}
-
-MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
-MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver");
-#endif /* MODULE */
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h
index 657c560..2855534 100644
--- a/drivers/video/au1100fb.h
+++ b/drivers/video/au1100fb.h
@@ -30,352 +30,352 @@
 #ifndef _AU1100LCD_H
 #define _AU1100LCD_H
 
-/********************************************************************/
-#define uint32 unsigned long
-typedef volatile struct
-{
-	uint32	lcd_control;
-	uint32	lcd_intstatus;
-	uint32	lcd_intenable;
-	uint32	lcd_horztiming;
-	uint32	lcd_verttiming;
-	uint32	lcd_clkcontrol;
-	uint32	lcd_dmaaddr0;
-	uint32	lcd_dmaaddr1;
-	uint32	lcd_words;
-	uint32	lcd_pwmdiv;
-	uint32	lcd_pwmhi;
-	uint32	reserved[(0x0400-0x002C)/4];
-	uint32	lcd_pallettebase[256];
+#include <asm/mach-au1x00/au1000.h>
 
-} AU1100_LCD;
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
 
-/********************************************************************/
-
-#define AU1100_LCD_ADDR		0xB5000000
-
-/*
- * Register bit definitions
- */
-
-/* lcd_control */
-#define LCD_CONTROL_SBPPF		(7<<18)
-#define LCD_CONTROL_SBPPF_655	(0<<18)
-#define LCD_CONTROL_SBPPF_565	(1<<18)
-#define LCD_CONTROL_SBPPF_556	(2<<18)
-#define LCD_CONTROL_SBPPF_1555	(3<<18)
-#define LCD_CONTROL_SBPPF_5551	(4<<18)
-#define LCD_CONTROL_WP			(1<<17)
-#define LCD_CONTROL_WD			(1<<16)
-#define LCD_CONTROL_C			(1<<15)
-#define LCD_CONTROL_SM			(3<<13)
-#define LCD_CONTROL_SM_0		(0<<13)
-#define LCD_CONTROL_SM_90		(1<<13)
-#define LCD_CONTROL_SM_180		(2<<13)
-#define LCD_CONTROL_SM_270		(3<<13)
-#define LCD_CONTROL_DB			(1<<12)
-#define LCD_CONTROL_CCO			(1<<11)
-#define LCD_CONTROL_DP			(1<<10)
-#define LCD_CONTROL_PO			(3<<8)
-#define LCD_CONTROL_PO_00		(0<<8)
-#define LCD_CONTROL_PO_01		(1<<8)
-#define LCD_CONTROL_PO_10		(2<<8)
-#define LCD_CONTROL_PO_11		(3<<8)
-#define LCD_CONTROL_MPI			(1<<7)
-#define LCD_CONTROL_PT			(1<<6)
-#define LCD_CONTROL_PC			(1<<5)
-#define LCD_CONTROL_BPP			(7<<1)
-#define LCD_CONTROL_BPP_1		(0<<1)
-#define LCD_CONTROL_BPP_2		(1<<1)
-#define LCD_CONTROL_BPP_4		(2<<1)
-#define LCD_CONTROL_BPP_8		(3<<1)
-#define LCD_CONTROL_BPP_12		(4<<1)
-#define LCD_CONTROL_BPP_16		(5<<1)
-#define LCD_CONTROL_GO			(1<<0)
-
-/* lcd_intstatus, lcd_intenable */
-#define LCD_INT_SD				(1<<7)
-#define LCD_INT_OF				(1<<6)
-#define LCD_INT_UF				(1<<5)
-#define LCD_INT_SA				(1<<3)
-#define LCD_INT_SS				(1<<2)
-#define LCD_INT_S1				(1<<1)
-#define LCD_INT_S0				(1<<0)
-
-/* lcd_horztiming */
-#define LCD_HORZTIMING_HN2		(255<<24)
-#define LCD_HORZTIMING_HN2_N(N)	(((N)-1)<<24)
-#define LCD_HORZTIMING_HN1		(255<<16)
-#define LCD_HORZTIMING_HN1_N(N)	(((N)-1)<<16)
-#define LCD_HORZTIMING_HPW		(63<<10)
-#define LCD_HORZTIMING_HPW_N(N)	(((N)-1)<<10)
-#define LCD_HORZTIMING_PPL		(1023<<0)
-#define LCD_HORZTIMING_PPL_N(N)	(((N)-1)<<0)
-
-/* lcd_verttiming */
-#define LCD_VERTTIMING_VN2		(255<<24)
-#define LCD_VERTTIMING_VN2_N(N)	(((N)-1)<<24)
-#define LCD_VERTTIMING_VN1		(255<<16)
-#define LCD_VERTTIMING_VN1_N(N)	(((N)-1)<<16)
-#define LCD_VERTTIMING_VPW		(63<<10)
-#define LCD_VERTTIMING_VPW_N(N)	(((N)-1)<<10)
-#define LCD_VERTTIMING_LPP		(1023<<0)
-#define LCD_VERTTIMING_LPP_N(N)	(((N)-1)<<0)
-
-/* lcd_clkcontrol */
-#define LCD_CLKCONTROL_IB		(1<<18)
-#define LCD_CLKCONTROL_IC		(1<<17)
-#define LCD_CLKCONTROL_IH		(1<<16)
-#define LCD_CLKCONTROL_IV		(1<<15)
-#define LCD_CLKCONTROL_BF		(31<<10)
-#define LCD_CLKCONTROL_BF_N(N)	(((N)-1)<<10)
-#define LCD_CLKCONTROL_PCD		(1023<<0)
-#define LCD_CLKCONTROL_PCD_N(N)	((N)<<0)
-
-/* lcd_pwmdiv */
-#define LCD_PWMDIV_EN			(1<<12)
-#define LCD_PWMDIV_PWMDIV		(2047<<0)
-#define LCD_PWMDIV_PWMDIV_N(N)	(((N)-1)<<0)
-
-/* lcd_pwmhi */
-#define LCD_PWMHI_PWMHI1		(2047<<12)
-#define LCD_PWMHI_PWMHI1_N(N)	((N)<<12)
-#define LCD_PWMHI_PWMHI0		(2047<<0)
-#define LCD_PWMHI_PWMHI0_N(N)	((N)<<0)
-
-/* lcd_pallettebase - MONOCHROME */
-#define LCD_PALLETTE_MONO_MI		(15<<0)
-#define LCD_PALLETTE_MONO_MI_N(N)	((N)<<0)
-
-/* lcd_pallettebase - COLOR */
-#define LCD_PALLETTE_COLOR_BI		(15<<8)
-#define LCD_PALLETTE_COLOR_BI_N(N)	((N)<<8)
-#define LCD_PALLETTE_COLOR_GI		(15<<4)
-#define LCD_PALLETTE_COLOR_GI_N(N)	((N)<<4)
-#define LCD_PALLETTE_COLOR_RI		(15<<0)
-#define LCD_PALLETTE_COLOR_RI_N(N)	((N)<<0)
-
-/* lcd_palletebase - COLOR TFT PALLETIZED */
-#define LCD_PALLETTE_TFT_DC			(65535<<0)
-#define LCD_PALLETTE_TFT_DC_N(N)	((N)<<0)
-
-/********************************************************************/
-
-struct known_lcd_panels
-{
-	uint32 xres;
-	uint32 yres;
-	uint32 bpp;
-	unsigned char  panel_name[256];
-	uint32 mode_control;
-	uint32 mode_horztiming;
-	uint32 mode_verttiming;
-	uint32 mode_clkcontrol;
-	uint32 mode_pwmdiv;
-	uint32 mode_pwmhi;
-	uint32 mode_toyclksrc;
-	uint32 mode_backlight;
-
-};
-
-#if defined(__BIG_ENDIAN)
-#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_11
+#if DEBUG
+#define print_dbg(f, arg...) printk(__FILE__ ": " f "\n", ## arg)
 #else
-#define LCD_DEFAULT_PIX_FORMAT LCD_CONTROL_PO_00
+#define print_dbg(f, arg...) do {} while (0)
 #endif
 
-/*
- * The fb driver assumes that AUX PLL is at 48MHz.  That can
- * cover up to 800x600 resolution; if you need higher resolution,
- * you should modify the driver as needed, not just this structure.
- */
-struct known_lcd_panels panels[] =
-{
-	{ /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */
-		320, /* xres */
-		240, /* yres */
-		16,  /* bpp  */
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
 
-		"Sharp_320x240_16",
-		/* mode_control */
+/********************************************************************/
+
+/* LCD controller restrictions */
+#define AU1100_LCD_MAX_XRES	800
+#define AU1100_LCD_MAX_YRES	600
+#define AU1100_LCD_MAX_BPP	16
+#define AU1100_LCD_MAX_CLK	48000000
+#define AU1100_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1100FB_NBR_VIDEO_BUFFERS 4
+
+/********************************************************************/
+
+struct au1100fb_panel
+{
+	const char name[25];		/* Full name <vendor>_<model> */
+
+	u32   	control_base;		/* Mode-independent control values */
+	u32	clkcontrol_base;	/* Panel pixclock preferences */
+
+	u32	horztiming;
+	u32	verttiming;
+
+	u32	xres;		/* Maximum horizontal resolution */
+	u32 	yres;		/* Maximum vertical resolution */
+	u32 	bpp;		/* Maximum depth supported */
+};
+
+struct au1100fb_regs
+{
+	u32  lcd_control;
+	u32  lcd_intstatus;
+	u32  lcd_intenable;
+	u32  lcd_horztiming;
+	u32  lcd_verttiming;
+	u32  lcd_clkcontrol;
+	u32  lcd_dmaaddr0;
+	u32  lcd_dmaaddr1;
+	u32  lcd_words;
+	u32  lcd_pwmdiv;
+	u32  lcd_pwmhi;
+	u32  reserved[(0x0400-0x002C)/4];
+	u32  lcd_pallettebase[256];
+};
+
+struct au1100fb_device {
+
+	struct fb_info info;			/* FB driver info record */
+
+	struct au1100fb_panel 	*panel;		/* Panel connected to this device */
+
+	struct au1100fb_regs* 	regs;		/* Registers memory map */
+	size_t       		regs_len;
+	unsigned int 		regs_phys;
+
+	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
+	size_t	      		fb_len;
+	dma_addr_t    		fb_phys;
+};
+
+/********************************************************************/
+
+#define LCD_CONTROL                (AU1100_LCD_BASE + 0x0)
+  #define LCD_CONTROL_SBB_BIT      21
+  #define LCD_CONTROL_SBB_MASK     (0x3 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_1        (0 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_2        (1 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_3        (2 << LCD_CONTROL_SBB_BIT)
+    #define LCD_CONTROL_SBB_4        (3 << LCD_CONTROL_SBB_BIT)
+  #define LCD_CONTROL_SBPPF_BIT    18
+  #define LCD_CONTROL_SBPPF_MASK   (0x7 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_655    (0 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_565    (1 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_556    (2 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_1555   (3 << LCD_CONTROL_SBPPF_BIT)
+    #define LCD_CONTROL_SBPPF_5551   (4 << LCD_CONTROL_SBPPF_BIT)
+  #define LCD_CONTROL_WP           (1<<17)
+  #define LCD_CONTROL_WD           (1<<16)
+  #define LCD_CONTROL_C            (1<<15)
+  #define LCD_CONTROL_SM_BIT       13
+  #define LCD_CONTROL_SM_MASK      (0x3 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_0         (0 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_90        (1 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_180       (2 << LCD_CONTROL_SM_BIT)
+    #define LCD_CONTROL_SM_270       (3 << LCD_CONTROL_SM_BIT)
+  #define LCD_CONTROL_DB           (1<<12)
+  #define LCD_CONTROL_CCO          (1<<11)
+  #define LCD_CONTROL_DP           (1<<10)
+  #define LCD_CONTROL_PO_BIT       8
+  #define LCD_CONTROL_PO_MASK      (0x3 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_00        (0 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_01        (1 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_10        (2 << LCD_CONTROL_PO_BIT)
+    #define LCD_CONTROL_PO_11        (3 << LCD_CONTROL_PO_BIT)
+  #define LCD_CONTROL_MPI          (1<<7)
+  #define LCD_CONTROL_PT           (1<<6)
+  #define LCD_CONTROL_PC           (1<<5)
+  #define LCD_CONTROL_BPP_BIT      1
+  #define LCD_CONTROL_BPP_MASK     (0x7 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_1        (0 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_2        (1 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_4        (2 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_8        (3 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_12       (4 << LCD_CONTROL_BPP_BIT)
+    #define LCD_CONTROL_BPP_16       (5 << LCD_CONTROL_BPP_BIT)
+  #define LCD_CONTROL_GO           (1<<0)
+
+#define LCD_INTSTATUS              (AU1100_LCD_BASE + 0x4)
+#define LCD_INTENABLE              (AU1100_LCD_BASE + 0x8)
+  #define LCD_INT_SD               (1<<7)
+  #define LCD_INT_OF               (1<<6)
+  #define LCD_INT_UF               (1<<5)
+  #define LCD_INT_SA               (1<<3)
+  #define LCD_INT_SS               (1<<2)
+  #define LCD_INT_S1               (1<<1)
+  #define LCD_INT_S0               (1<<0)
+
+#define LCD_HORZTIMING             (AU1100_LCD_BASE + 0xC)
+  #define LCD_HORZTIMING_HN2_BIT   24
+  #define LCD_HORZTIMING_HN2_MASK  (0xFF << LCD_HORZTIMING_HN2_BIT)
+  #define LCD_HORZTIMING_HN2_N(N)  ((((N)-1) << LCD_HORZTIMING_HN2_BIT) & LCD_HORZTIMING_HN2_MASK)
+  #define LCD_HORZTIMING_HN1_BIT   16
+  #define LCD_HORZTIMING_HN1_MASK  (0xFF << LCD_HORZTIMING_HN1_BIT)
+  #define LCD_HORZTIMING_HN1_N(N)  ((((N)-1) << LCD_HORZTIMING_HN1_BIT) & LCD_HORZTIMING_HN1_MASK)
+  #define LCD_HORZTIMING_HPW_BIT   10
+  #define LCD_HORZTIMING_HPW_MASK  (0x3F << LCD_HORZTIMING_HPW_BIT)
+  #define LCD_HORZTIMING_HPW_N(N)  ((((N)-1) << LCD_HORZTIMING_HPW_BIT) & LCD_HORZTIMING_HPW_MASK)
+  #define LCD_HORZTIMING_PPL_BIT   0
+  #define LCD_HORZTIMING_PPL_MASK  (0x3FF << LCD_HORZTIMING_PPL_BIT)
+  #define LCD_HORZTIMING_PPL_N(N)  ((((N)-1) << LCD_HORZTIMING_PPL_BIT) & LCD_HORZTIMING_PPL_MASK)
+
+#define LCD_VERTTIMING             (AU1100_LCD_BASE + 0x10)
+  #define LCD_VERTTIMING_VN2_BIT   24
+  #define LCD_VERTTIMING_VN2_MASK  (0xFF << LCD_VERTTIMING_VN2_BIT)
+  #define LCD_VERTTIMING_VN2_N(N)  ((((N)-1) << LCD_VERTTIMING_VN2_BIT) & LCD_VERTTIMING_VN2_MASK)
+  #define LCD_VERTTIMING_VN1_BIT   16
+  #define LCD_VERTTIMING_VN1_MASK  (0xFF << LCD_VERTTIMING_VN1_BIT)
+  #define LCD_VERTTIMING_VN1_N(N)  ((((N)-1) << LCD_VERTTIMING_VN1_BIT) & LCD_VERTTIMING_VN1_MASK)
+  #define LCD_VERTTIMING_VPW_BIT   10
+  #define LCD_VERTTIMING_VPW_MASK  (0x3F << LCD_VERTTIMING_VPW_BIT)
+  #define LCD_VERTTIMING_VPW_N(N)  ((((N)-1) << LCD_VERTTIMING_VPW_BIT) & LCD_VERTTIMING_VPW_MASK)
+  #define LCD_VERTTIMING_LPP_BIT   0
+  #define LCD_VERTTIMING_LPP_MASK  (0x3FF << LCD_VERTTIMING_LPP_BIT)
+  #define LCD_VERTTIMING_LPP_N(N)  ((((N)-1) << LCD_VERTTIMING_LPP_BIT) & LCD_VERTTIMING_LPP_MASK)
+
+#define LCD_CLKCONTROL             (AU1100_LCD_BASE + 0x14)
+  #define LCD_CLKCONTROL_IB        (1<<18)
+  #define LCD_CLKCONTROL_IC        (1<<17)
+  #define LCD_CLKCONTROL_IH        (1<<16)
+  #define LCD_CLKCONTROL_IV        (1<<15)
+  #define LCD_CLKCONTROL_BF_BIT    10
+  #define LCD_CLKCONTROL_BF_MASK   (0x1F << LCD_CLKCONTROL_BF_BIT)
+  #define LCD_CLKCONTROL_BF_N(N)   ((((N)-1) << LCD_CLKCONTROL_BF_BIT) & LCD_CLKCONTROL_BF_MASK)
+  #define LCD_CLKCONTROL_PCD_BIT   0
+  #define LCD_CLKCONTROL_PCD_MASK  (0x3FF << LCD_CLKCONTROL_PCD_BIT)
+  #define LCD_CLKCONTROL_PCD_N(N)  (((N) << LCD_CLKCONTROL_PCD_BIT) & LCD_CLKCONTROL_PCD_MASK)
+
+#define LCD_DMAADDR0               (AU1100_LCD_BASE + 0x18)
+#define LCD_DMAADDR1               (AU1100_LCD_BASE + 0x1C)
+  #define LCD_DMA_SA_BIT           5
+  #define LCD_DMA_SA_MASK          (0x7FFFFFF << LCD_DMA_SA_BIT)
+  #define LCD_DMA_SA_N(N)          ((N) & LCD_DMA_SA_MASK)
+
+#define LCD_WORDS                  (AU1100_LCD_BASE + 0x20)
+  #define LCD_WRD_WRDS_BIT         0
+  #define LCD_WRD_WRDS_MASK        (0xFFFFFFFF << LCD_WRD_WRDS_BIT)
+  #define LCD_WRD_WRDS_N(N)        ((((N)-1) << LCD_WRD_WRDS_BIT) & LCD_WRD_WRDS_MASK)
+
+#define LCD_PWMDIV                 (AU1100_LCD_BASE + 0x24)
+  #define LCD_PWMDIV_EN            (1<<12)
+  #define LCD_PWMDIV_PWMDIV_BIT    0
+  #define LCD_PWMDIV_PWMDIV_MASK   (0xFFF << LCD_PWMDIV_PWMDIV_BIT)
+  #define LCD_PWMDIV_PWMDIV_N(N)   ((((N)-1) << LCD_PWMDIV_PWMDIV_BIT) & LCD_PWMDIV_PWMDIV_MASK)
+
+#define LCD_PWMHI                  (AU1100_LCD_BASE + 0x28)
+  #define LCD_PWMHI_PWMHI1_BIT     12
+  #define LCD_PWMHI_PWMHI1_MASK    (0xFFF << LCD_PWMHI_PWMHI1_BIT)
+  #define LCD_PWMHI_PWMHI1_N(N)    (((N) << LCD_PWMHI_PWMHI1_BIT) & LCD_PWMHI_PWMHI1_MASK)
+  #define LCD_PWMHI_PWMHI0_BIT     0
+  #define LCD_PWMHI_PWMHI0_MASK    (0xFFF << LCD_PWMHI_PWMHI0_BIT)
+  #define LCD_PWMHI_PWMHI0_N(N)    (((N) << LCD_PWMHI_PWMHI0_BIT) & LCD_PWMHI_PWMHI0_MASK)
+
+#define LCD_PALLETTEBASE                (AU1100_LCD_BASE + 0x400)
+  #define LCD_PALLETTE_MONO_MI_BIT      0
+  #define LCD_PALLETTE_MONO_MI_MASK     (0xF << LCD_PALLETTE_MONO_MI_BIT)
+  #define LCD_PALLETTE_MONO_MI_N(N)     (((N)<< LCD_PALLETTE_MONO_MI_BIT) & LCD_PALLETTE_MONO_MI_MASK)
+
+  #define LCD_PALLETTE_COLOR_RI_BIT     8
+  #define LCD_PALLETTE_COLOR_RI_MASK    (0xF << LCD_PALLETTE_COLOR_RI_BIT)
+  #define LCD_PALLETTE_COLOR_RI_N(N)    (((N)<< LCD_PALLETTE_COLOR_RI_BIT) & LCD_PALLETTE_COLOR_RI_MASK)
+  #define LCD_PALLETTE_COLOR_GI_BIT     4
+  #define LCD_PALLETTE_COLOR_GI_MASK    (0xF << LCD_PALLETTE_COLOR_GI_BIT)
+  #define LCD_PALLETTE_COLOR_GI_N(N)    (((N)<< LCD_PALLETTE_COLOR_GI_BIT) & LCD_PALLETTE_COLOR_GI_MASK)
+  #define LCD_PALLETTE_COLOR_BI_BIT     0
+  #define LCD_PALLETTE_COLOR_BI_MASK    (0xF << LCD_PALLETTE_COLOR_BI_BIT)
+  #define LCD_PALLETTE_COLOR_BI_N(N)    (((N)<< LCD_PALLETTE_COLOR_BI_BIT) & LCD_PALLETTE_COLOR_BI_MASK)
+
+  #define LCD_PALLETTE_TFT_DC_BIT       0
+  #define LCD_PALLETTE_TFT_DC_MASK      (0xFFFF << LCD_PALLETTE_TFT_DC_BIT)
+  #define LCD_PALLETTE_TFT_DC_N(N)      (((N)<< LCD_PALLETTE_TFT_DC_BIT) & LCD_PALLETTE_TFT_DC_MASK)
+
+/********************************************************************/
+
+/* List of panels known to work with the AU1100 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
+ */
+static struct au1100fb_panel known_lcd_panels[] =
+{
+	/* 800x600x16bpp CRT */
+	[0] = {
+		.name = "CRT_800x600_16",
+		.xres = 800,
+		.yres = 600,
+		.bpp = 16,
+		.control_base =	0x0004886A |
+			LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF |
+			LCD_CONTROL_BPP_16,
+		.clkcontrol_base = 0x00020000,
+		.horztiming = 0x005aff1f,
+		.verttiming = 0x16000e57,
+	},
+	/* just the standard LCD */
+	[1] = {
+		.name = "WWPC LCD",
+		.xres = 240,
+		.yres = 320,
+		.bpp = 16,
+		.control_base = 0x0006806A,
+		.horztiming = 0x0A1010EF,
+		.verttiming = 0x0301013F,
+		.clkcontrol_base = 0x00018001,
+	},
+	/* Sharp 320x240 TFT panel */
+	[2] = {
+		.name = "Sharp_LQ038Q5DR01",
+		.xres = 320,
+		.yres = 240,
+		.bpp = 16,
+		.control_base =
 		( LCD_CONTROL_SBPPF_565
-		/*LCD_CONTROL_WP*/
-		/*LCD_CONTROL_WD*/
 		| LCD_CONTROL_C
 		| LCD_CONTROL_SM_0
-		/*LCD_CONTROL_DB*/
-		/*LCD_CONTROL_CCO*/
-		/*LCD_CONTROL_DP*/
-		| LCD_DEFAULT_PIX_FORMAT
-		/*LCD_CONTROL_MPI*/
+			| LCD_CONTROL_DEFAULT_PO
 		| LCD_CONTROL_PT
 		| LCD_CONTROL_PC
 		| LCD_CONTROL_BPP_16 ),
-
-		/* mode_horztiming */
+		.horztiming =
 		( LCD_HORZTIMING_HN2_N(8)
 		| LCD_HORZTIMING_HN1_N(60)
 		| LCD_HORZTIMING_HPW_N(12)
 		| LCD_HORZTIMING_PPL_N(320) ),
-
-		/* mode_verttiming */
+		.verttiming =
 		( LCD_VERTTIMING_VN2_N(5)
 		| LCD_VERTTIMING_VN1_N(17)
 		| LCD_VERTTIMING_VPW_N(1)
 		| LCD_VERTTIMING_LPP_N(240) ),
-
-		/* mode_clkcontrol */
-		( 0
-		/*LCD_CLKCONTROL_IB*/
-		/*LCD_CLKCONTROL_IC*/
-		/*LCD_CLKCONTROL_IH*/
-		/*LCD_CLKCONTROL_IV*/
-		| LCD_CLKCONTROL_PCD_N(1) ),
-
-		/* mode_pwmdiv */
-		0,
-
-		/* mode_pwmhi */
-		0,
-
-		/* mode_toyclksrc */
-		((1<<7) | (1<<6) | (1<<5)),
-
-		/* mode_backlight */
-		6
+		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
 	},
 
-	{ /* 1: Pb1100 LCDC 640x480 TFT panel */
-		640, /* xres */
-		480, /* yres */
-		16,  /* bpp  */
-
-		"Generic_640x480_16",
-
-		/* mode_control */
-		0x004806a | LCD_DEFAULT_PIX_FORMAT,
-
-		/* mode_horztiming */
-		0x3434d67f,
-
-		/* mode_verttiming */
-		0x0e0e39df,
-
-		/* mode_clkcontrol */
-		( 0
-		/*LCD_CLKCONTROL_IB*/
-		/*LCD_CLKCONTROL_IC*/
-		/*LCD_CLKCONTROL_IH*/
-		/*LCD_CLKCONTROL_IV*/
-		| LCD_CLKCONTROL_PCD_N(1) ),
-
-		/* mode_pwmdiv */
-		0,
-
-		/* mode_pwmhi */
-		0,
-
-		/* mode_toyclksrc */
-		((1<<7) | (1<<6) | (0<<5)),
-
-		/* mode_backlight */
-		7
+	/* Hitachi SP14Q005 and possibly others */
+	[3] = {
+		.name = "Hitachi_SP14Qxxx",
+		.xres = 320,
+		.yres = 240,
+		.bpp = 4,
+		.control_base =
+			( LCD_CONTROL_C
+			| LCD_CONTROL_BPP_4 ),
+		.horztiming =
+			( LCD_HORZTIMING_HN2_N(1)
+			| LCD_HORZTIMING_HN1_N(1)
+			| LCD_HORZTIMING_HPW_N(1)
+			| LCD_HORZTIMING_PPL_N(320) ),
+		.verttiming =
+			( LCD_VERTTIMING_VN2_N(1)
+			| LCD_VERTTIMING_VN1_N(1)
+			| LCD_VERTTIMING_VPW_N(1)
+			| LCD_VERTTIMING_LPP_N(240) ),
+		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(4),
 	},
 
-	{ /* 2: Pb1100 LCDB 640x480 PrimeView TFT panel */
-		640, /* xres */
-		480, /* yres */
-		16,  /* bpp  */
-
-		"PrimeView_640x480_16",
-
-		/* mode_control */
-		0x0004886a | LCD_DEFAULT_PIX_FORMAT,
-
-		/* mode_horztiming */
-		0x0e4bfe7f,
-
-		/* mode_verttiming */
-		0x210805df,
-
-		/* mode_clkcontrol */
-		0x00038001,
-
-		/* mode_pwmdiv */
-		0,
-
-		/* mode_pwmhi */
-		0,
-
-		/* mode_toyclksrc */
-		((1<<7) | (1<<6) | (0<<5)),
-
-		/* mode_backlight */
-		7
+	/* Generic 640x480 TFT panel */
+	[4] = {
+		.name = "TFT_640x480_16",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.control_base = 0x004806a | LCD_CONTROL_DEFAULT_PO,
+		.horztiming = 0x3434d67f,
+		.verttiming = 0x0e0e39df,
+		.clkcontrol_base = LCD_CLKCONTROL_PCD_N(1),
 	},
 
-	{ /* 3: Pb1100 800x600x16bpp NEON CRT */
-		800, /* xres */
-		600, /* yres */
-		16,  /* bpp */
-
-		"NEON_800x600_16",
-
-		/* mode_control */
-		0x0004886A | LCD_DEFAULT_PIX_FORMAT,
-
-		/* mode_horztiming */
-		0x005AFF1F,
-
-		/* mode_verttiming */
-		0x16000E57,
-
-		/* mode_clkcontrol */
-		0x00020000,
-
-		/* mode_pwmdiv */
-		0,
-
-		/* mode_pwmhi */
-		0,
-
-		/* mode_toyclksrc */
-		((1<<7) | (1<<6) | (0<<5)),
-
-		/* mode_backlight */
-		7
-	},
-
-	{ /* 4: Pb1100 640x480x16bpp NEON CRT */
-		640, /* xres */
-		480, /* yres */
-		16,  /* bpp */
-
-		"NEON_640x480_16",
-
-		/* mode_control */
-		0x0004886A | LCD_DEFAULT_PIX_FORMAT,
-
-		/* mode_horztiming */
-		0x0052E27F,
-
-		/* mode_verttiming */
-		0x18000DDF,
-
-		/* mode_clkcontrol */
-		0x00020000,
-
-		/* mode_pwmdiv */
-		0,
-
-		/* mode_pwmhi */
-		0,
-
-		/* mode_toyclksrc */
-		((1<<7) | (1<<6) | (0<<5)),
-
-		/* mode_backlight */
-		7
+	 /* Pb1100 LCDB 640x480 PrimeView TFT panel */
+	[5] = {
+		.name = "PrimeView_640x480_16",
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.control_base = 0x0004886a | LCD_CONTROL_DEFAULT_PO,
+		.horztiming = 0x0e4bfe7f,
+		.verttiming = 0x210805df,
+		.clkcontrol_base = 0x00038001,
 	},
 };
+
+struct au1100fb_drv_info {
+	int	panel_idx;
+	char 	*opt_mode;
+};
+
+/********************************************************************/
+
+/* Inline helpers */
+
+#define panel_is_dual(panel)  (panel->control_base & LCD_CONTROL_DP)
+#define panel_is_active(panel)(panel->control_base & LCD_CONTROL_PT)
+#define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC)
+#define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO)
+
 #endif /* _AU1100LCD_H */
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 3c72c62..1991fdb 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -73,17 +73,15 @@
 }
 
 #ifdef CONFIG_PM
-static int corgibl_suspend(struct device *dev, pm_message_t state, u32 level)
+static int corgibl_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN)
-		corgibl_blank(FB_BLANK_POWERDOWN);
+	corgibl_blank(FB_BLANK_POWERDOWN);
 	return 0;
 }
 
-static int corgibl_resume(struct device *dev, u32 level)
+static int corgibl_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON)
-		corgibl_blank(FB_BLANK_UNBLANK);
+	corgibl_blank(FB_BLANK_UNBLANK);
 	return 0;
 }
 #else
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index a304042..3a26f9c 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -275,20 +275,20 @@
 
 #ifdef CONFIG_PCI
 #define CHIP(id, btype) \
-	{ PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_##id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
+	{ PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
 
 static struct pci_device_id cirrusfb_pci_table[] = {
-	CHIP( CIRRUS_5436,	BT_ALPINE ),
-	CHIP( CIRRUS_5434_8,	BT_ALPINE ),
-	CHIP( CIRRUS_5434_4,	BT_ALPINE ),
-	CHIP( CIRRUS_5430,	BT_ALPINE ), /* GD-5440 has identical id */
-	CHIP( CIRRUS_7543,	BT_ALPINE ),
-	CHIP( CIRRUS_7548,	BT_ALPINE ),
-	CHIP( CIRRUS_5480,	BT_GD5480 ), /* MacPicasso probably */
-	CHIP( CIRRUS_5446,	BT_PICASSO4 ), /* Picasso 4 is a GD5446 */
-	CHIP( CIRRUS_5462,	BT_LAGUNA ), /* CL Laguna */
-	CHIP( CIRRUS_5464,	BT_LAGUNA ), /* CL Laguna 3D */
-	CHIP( CIRRUS_5465,	BT_LAGUNA ), /* CL Laguna 3DA*/
+	CHIP( PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE ),
+	CHIP( PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE ),
+	CHIP( PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE ),
+	CHIP( PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE ), /* GD-5440 is same id */
+	CHIP( PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE ),
+	CHIP( PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE ),
+	CHIP( PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480 ), /* MacPicasso likely */
+	CHIP( PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4 ), /* Picasso 4 is 5446 */
+	CHIP( PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA ), /* CL Laguna */
+	CHIP( PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA ), /* CL Laguna 3D */
+	CHIP( PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA ), /* CL Laguna 3DA*/
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index eb83a78..6a9ae2b 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -28,7 +28,7 @@
 
 config VIDEO_SELECT
 	bool "Video mode selection support"
-	depends on  (X86 || X86_64) && VGA_CONSOLE
+	depends on  X86 && VGA_CONSOLE
 	---help---
 	  This enables support for text mode selection on kernel startup. If
 	  you want to take advantage of some high-resolution text mode your
@@ -110,7 +110,7 @@
 
 config FONTS
 	bool "Select compiled-in fonts"
-	depends on FRAMEBUFFER_CONSOLE
+	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
 	help
 	  Say Y here if you would like to use fonts other than the default
 	  your frame buffer console usually use.
@@ -123,7 +123,7 @@
 
 config FONT_8x8
 	bool "VGA 8x8 font" if FONTS
-	depends on FRAMEBUFFER_CONSOLE
+	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
 	default y if !SPARC32 && !SPARC64 && !FONTS
 	help
 	  This is the "high resolution" font for the VGA frame buffer (the one
@@ -137,7 +137,7 @@
 
 config FONT_8x16
 	bool "VGA 8x16 font" if FONTS
-	depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
+	depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || STI_CONSOLE || USB_SISUSBVGA_CON 
 	default y if !SPARC32 && !SPARC64 && !FONTS
 	help
 	  This is the "high resolution" font for the VGA frame buffer (the one
@@ -147,7 +147,7 @@
 
 config FONT_6x11
 	bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
-	depends on FRAMEBUFFER_CONSOLE
+	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
 	default y if !SPARC32 && !SPARC64 && !FONTS && MAC
 	help
 	  Small console font with Macintosh-style high-half glyphs.  Some Mac
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index e793ffd..762c7a5 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -32,7 +32,6 @@
 #include <linux/font.h>
 
 
-extern struct font_desc font_vga_8x16;
 extern unsigned long sgi_gfxaddr;
 
 #define FONT_DATA ((unsigned char *)font_vga_8x16.data)
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index d940f60..a7bcd17 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -511,12 +511,12 @@
 	struct sti_cooked_font *cooked_font;
 	
 	if (!fbfont_name || !strlen(fbfont_name))
-	    return NULL;
+		return NULL;
 	fbfont = find_font(fbfont_name);
 	if (!fbfont)
-	    fbfont = get_default_font(1024,768);
+		fbfont = get_default_font(1024,768);
 	if (!fbfont)
-	    return NULL;
+		return NULL;
 
 	DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n",
 			fbfont->width, fbfont->height, fbfont->name));
@@ -527,7 +527,7 @@
 
 	nf = kmalloc(size, GFP_KERNEL);
 	if (!nf)
-	    return NULL;
+		return NULL;
 	memset(nf, 0, size);
 
 	nf->first_char = 0;
@@ -546,8 +546,8 @@
 
 	cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL);
 	if (!cooked_font) {
-	    kfree(nf);
-	    return NULL;
+		kfree(nf);
+		return NULL;
 	}
 	
 	cooked_font->raw = nf;
@@ -595,7 +595,7 @@
 static void __init 
 sti_dump_rom(struct sti_rom *rom)
 {
-        printk(KERN_INFO "    id %04x-%04x, conforms to spec rev. %d.%02x\n",
+	printk(KERN_INFO "    id %04x-%04x, conforms to spec rev. %d.%02x\n",
 		rom->graphics_id[0], 
 		rom->graphics_id[1],
 		rom->revno[0] >> 4, 
@@ -651,15 +651,16 @@
 	struct sti_cooked_font *font;
 	int i = 0;
 	
-	for(font = rom->font_start; font; font = font->next_font, i++) {
-	    if((font->raw->width == width) && (font->raw->height == height))
+	for (font = rom->font_start; font; font = font->next_font, i++) {
+		if ((font->raw->width == width) &&
+		    (font->raw->height == height))
 			return i;
 	}
 	return 0;
 }
 
-#define BMODE_RELOCATE(offset)        offset = (offset) / 4;
-#define BMODE_LAST_ADDR_OFFS          0x50
+#define BMODE_RELOCATE(offset)		offset = (offset) / 4;
+#define BMODE_LAST_ADDR_OFFS		0x50
 
 static void * __init
 sti_bmode_font_raw(struct sti_cooked_font *f)
@@ -700,35 +701,35 @@
 {
 	struct sti_rom *raw;
 	u32 size;
-        struct sti_rom_font *raw_font, *font_start;
-    
+	struct sti_rom_font *raw_font, *font_start;
+
 	sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size);
-    
-        size = (size+3) / 4;
+
+	size = (size+3) / 4;
 	raw = kmalloc(size, GFP_KERNEL);
 	if (raw) {
-	    sti_bmode_rom_copy(address, size, raw);
-	    memmove (&raw->res004, &raw->type[0], 0x3c);
-    	    raw->type[3] = raw->res004;
+		sti_bmode_rom_copy(address, size, raw);
+		memmove (&raw->res004, &raw->type[0], 0x3c);
+		raw->type[3] = raw->res004;
 
-	    BMODE_RELOCATE (raw->region_list);
-	    BMODE_RELOCATE (raw->font_start);
+		BMODE_RELOCATE (raw->region_list);
+		BMODE_RELOCATE (raw->font_start);
 
-	    BMODE_RELOCATE (raw->init_graph);
-	    BMODE_RELOCATE (raw->state_mgmt);
-	    BMODE_RELOCATE (raw->font_unpmv);
-	    BMODE_RELOCATE (raw->block_move);
-	    BMODE_RELOCATE (raw->inq_conf);
+		BMODE_RELOCATE (raw->init_graph);
+		BMODE_RELOCATE (raw->state_mgmt);
+		BMODE_RELOCATE (raw->font_unpmv);
+		BMODE_RELOCATE (raw->block_move);
+		BMODE_RELOCATE (raw->inq_conf);
 
-	    raw_font = ((void *)raw) + raw->font_start;
-	    font_start = raw_font;
+		raw_font = ((void *)raw) + raw->font_start;
+		font_start = raw_font;
 		
-	    while (raw_font->next_font) {
-		    BMODE_RELOCATE (raw_font->next_font);
-		    raw_font = ((void *)font_start) + raw_font->next_font;
-	    }
+		while (raw_font->next_font) {
+			BMODE_RELOCATE (raw_font->next_font);
+			raw_font = ((void *)font_start) + raw_font->next_font;
+		}
 	}
-        return raw;
+	return raw;
 }
 
 struct sti_rom * __init
@@ -736,15 +737,15 @@
 {
 	struct sti_rom *raw;
 	unsigned long size;
-    
+
 	/* read the ROM size directly from the struct in ROM */ 
 	size = gsc_readl(address + offsetof(struct sti_rom,last_addr));
 
 	raw = kmalloc(size, GFP_KERNEL);
-	if(raw)
-	        sti_rom_copy(address, size, raw);
+	if (raw)
+		sti_rom_copy(address, size, raw);
 
-        return raw;
+	return raw;
 }
 
 int __init
@@ -757,14 +758,14 @@
 	if (!cooked)
 		goto out_err;
 
-        if (wordmode)
-                raw = sti_get_wmode_rom (address);
-        else
-	        raw = sti_get_bmode_rom (address);
+	if (wordmode)
+		raw = sti_get_wmode_rom (address);
+	else
+		raw = sti_get_bmode_rom (address);
 
-        if (!raw)
-	        goto out_err;
-    
+	if (!raw)
+		goto out_err;
+
 	if (!sti_cook_fonts(cooked, raw)) {
 		printk(KERN_ERR "No font found for STI at %08lx\n", address);
 		goto out_err;
@@ -787,7 +788,7 @@
 	sti->font_width = sti->font->raw->width;
 	sti->font_height = sti->font->raw->height;
 	if (!wordmode)
-	        sti->font->raw = sti_bmode_font_raw(sti->font);
+		sti->font->raw = sti_bmode_font_raw(sti->font);
 
 	sti->sti_mem_request = raw->sti_mem_req;
 	sti->graphics_id[0] = raw->graphics_id[0];
@@ -811,16 +812,16 @@
 	u32 sig;
 
 	if (num_sti_roms >= MAX_STI_ROMS) {
-	    printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
-	    return NULL;
+		printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
+		return NULL;
 	}
 	
 	sti = kmalloc(sizeof(*sti), GFP_KERNEL);
 	if (!sti) {
-	    printk(KERN_ERR "Not enough memory !\n");
-	    return NULL;
+		printk(KERN_ERR "Not enough memory !\n");
+		return NULL;
 	}
-		    
+
 	memset(sti, 0, sizeof(*sti));
 	spin_lock_init(&sti->lock);
 
@@ -932,28 +933,21 @@
  */
 static int __init sticore_pa_init(struct parisc_device *dev)
 {
-	unsigned long rom = 0;
 	char pa_path[21];
 	struct sti_struct *sti = NULL;
-	
-	if(dev->num_addrs) {
-		rom = dev->addr[0];
-	}
-	if (!rom) {
-		rom = dev->hpa;
-		DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
-		sti = sti_try_rom_generic(rom, dev->hpa, NULL);
-		rom = PAGE0->proc_sti;
-	}
-	if (!sti) {
-		DPRINTK((KERN_DEBUG "Trying STI ROM at %08lx, hpa at %08lx\n", rom, dev->hpa));
-		sti = sti_try_rom_generic(rom, dev->hpa, NULL);
-	}
+	int hpa = dev->hpa.start;
+
+	if (dev->num_addrs && dev->addr[0])
+		sti = sti_try_rom_generic(dev->addr[0], hpa, NULL);
+	if (!sti)
+		sti = sti_try_rom_generic(hpa, hpa, NULL);
+	if (!sti)
+		sti = sti_try_rom_generic(PAGE0->proc_sti, hpa, NULL);
 	if (!sti)
 		return 1;
-	
+
 	print_pa_hwpath(dev, pa_path);
-	sticore_check_for_default_sti (sti, pa_path);
+	sticore_check_for_default_sti(sti, pa_path);
 	return 0;
 }
 
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 809fee2..56cd199 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -579,6 +579,7 @@
 {
 	int i, j;
 
+	vga_w(state.vgabase, VGA_PEL_MSK, 0xff);
 	for (i = j = 0; i < 16; i++) {
 		vga_w(state.vgabase, VGA_PEL_IW, table[i]);
 		vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
@@ -721,6 +722,7 @@
 {
 	int i;
 
+	vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
 	for (i = 0; i < 16; i++) {
 		vga_w(state->vgabase, VGA_PEL_IW, i);
 		vga_w(state->vgabase, VGA_PEL_D, 0);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ca02aa2..e2667dd 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1031,7 +1031,7 @@
 			break;
 	fb_info->node = i;
 
-	fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i),
+	fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
 				    fb_info->device, "fb%d", i);
 	if (IS_ERR(fb_info->class_device)) {
 		/* Not fatal */
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index d3c1922..485604c 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1126,7 +1126,7 @@
 	gbefb_setup(options);
 #endif
 
-	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
+	if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
 		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
 		ret = -EBUSY;
 		goto out_release_framebuffer;
@@ -1152,12 +1152,24 @@
 	if (gbe_mem_phys) {
 		/* memory was allocated at boot time */
 		gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
+		if (!gbe_mem) {
+			printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
+			ret = -ENOMEM;
+			goto out_tiles_free;
+		}
+
 		gbe_dma_addr = 0;
 	} else {
 		/* try to allocate memory with the classical allocator
 		 * this has high chance to fail on low memory machines */
 		gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
 					     GFP_KERNEL);
+		if (!gbe_mem) {
+			printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
+			ret = -ENOMEM;
+			goto out_tiles_free;
+		}
+
 		gbe_mem_phys = (unsigned long) gbe_dma_addr;
 	}
 
@@ -1165,12 +1177,6 @@
 	mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
 #endif
 
-	if (!gbe_mem) {
-		printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
-		ret = -ENXIO;
-		goto out_tiles_free;
-	}
-
 	/* map framebuffer memory into tiles table */
 	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
 		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 1d54d3d..0b9301f 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -424,23 +424,21 @@
  * Power management hooks.  Note that we won't be called from IRQ context,
  * unlike the blank functions above, so we may sleep.
  */
-static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int imxfb_suspend(struct device *dev, pm_message_t state)
 {
 	struct imxfb_info *fbi = dev_get_drvdata(dev);
 	pr_debug("%s\n",__FUNCTION__);
 
-	if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
-		imxfb_disable_controller(fbi);
+	imxfb_disable_controller(fbi);
 	return 0;
 }
 
-static int imxfb_resume(struct device *dev, u32 level)
+static int imxfb_resume(struct device *dev)
 {
 	struct imxfb_info *fbi = dev_get_drvdata(dev);
 	pr_debug("%s\n",__FUNCTION__);
 
-	if (level == RESUME_ENABLE)
-		imxfb_enable_controller(fbi);
+	imxfb_enable_controller(fbi);
 	return 0;
 }
 #else
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 194eed0..6206da9 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -981,21 +981,19 @@
  * Power management hooks.  Note that we won't be called from IRQ context,
  * unlike the blank functions above, so we may sleep.
  */
-static int pxafb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int pxafb_suspend(struct device *dev, pm_message_t state)
 {
 	struct pxafb_info *fbi = dev_get_drvdata(dev);
 
-	if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
-		set_ctrlr_state(fbi, C_DISABLE_PM);
+	set_ctrlr_state(fbi, C_DISABLE_PM);
 	return 0;
 }
 
-static int pxafb_resume(struct device *dev, u32 level)
+static int pxafb_resume(struct device *dev)
 {
 	struct pxafb_info *fbi = dev_get_drvdata(dev);
 
-	if (level == RESUME_ENABLE)
-		set_ctrlr_state(fbi, C_ENABLE_PM);
+	set_ctrlr_state(fbi, C_ENABLE_PM);
 	return 0;
 }
 #else
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index fa98d91..cb2f7a1 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -655,7 +655,7 @@
 }
 
 #ifdef CONFIG_PM
-static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s1d13xxxfb_suspend(struct device *dev, pm_message_t state)
 {
 	struct fb_info *info = dev_get_drvdata(dev);
 	struct s1d13xxxfb_par *s1dfb = info->par;
@@ -702,15 +702,12 @@
 		return 0;
 }
 
-static int s1d13xxxfb_resume(struct device *dev, u32 level)
+static int s1d13xxxfb_resume(struct device *dev)
 {
 	struct fb_info *info = dev_get_drvdata(dev);
 	struct s1d13xxxfb_par *s1dfb = info->par;
 	struct s1d13xxxfb_pdata *pdata = NULL;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	/* awaken the chip */
 	s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
 
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 5ab79af..3862d3c 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -847,37 +847,32 @@
 
 /* suspend and resume support for the lcd controller */
 
-static int s3c2410fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int s3c2410fb_suspend(struct device *dev, pm_message_t state)
 {
 	struct fb_info	   *fbinfo = dev_get_drvdata(dev);
 	struct s3c2410fb_info *info = fbinfo->par;
 
-	if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) {
-		s3c2410fb_stop_lcd();
+	s3c2410fb_stop_lcd();
 
-		/* sleep before disabling the clock, we need to ensure
-		 * the LCD DMA engine is not going to get back on the bus
-		 * before the clock goes off again (bjd) */
+	/* sleep before disabling the clock, we need to ensure
+	 * the LCD DMA engine is not going to get back on the bus
+	 * before the clock goes off again (bjd) */
 
-		msleep(1);
-		clk_disable(info->clk);
-	}
+	msleep(1);
+	clk_disable(info->clk);
 
 	return 0;
 }
 
-static int s3c2410fb_resume(struct device *dev, u32 level)
+static int s3c2410fb_resume(struct device *dev)
 {
 	struct fb_info	   *fbinfo = dev_get_drvdata(dev);
 	struct s3c2410fb_info *info = fbinfo->par;
 
-	if (level == RESUME_ENABLE) {
-		clk_enable(info->clk);
-		msleep(1);
+	clk_enable(info->clk);
+	msleep(1);
 
-		s3c2410fb_init_registers(info);
-
-	}
+	s3c2410fb_init_registers(info);
 
 	return 0;
 }
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 8000890..78e5f19 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1309,21 +1309,19 @@
  * Power management hooks.  Note that we won't be called from IRQ context,
  * unlike the blank functions above, so we may sleep.
  */
-static int sa1100fb_suspend(struct device *dev, pm_message_t state, u32 level)
+static int sa1100fb_suspend(struct device *dev, pm_message_t state)
 {
 	struct sa1100fb_info *fbi = dev_get_drvdata(dev);
 
-	if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
-		set_ctrlr_state(fbi, C_DISABLE_PM);
+	set_ctrlr_state(fbi, C_DISABLE_PM);
 	return 0;
 }
 
-static int sa1100fb_resume(struct device *dev, u32 level)
+static int sa1100fb_resume(struct device *dev)
 {
 	struct sa1100fb_info *fbi = dev_get_drvdata(dev);
 
-	if (level == RESUME_ENABLE)
-		set_ctrlr_state(fbi, C_ENABLE_PM);
+	set_ctrlr_state(fbi, C_ENABLE_PM);
 	return 0;
 }
 #else
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 0030c07..752bf88 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -438,36 +438,34 @@
 	}
 }
 
-static int w100fb_suspend(struct device *dev, pm_message_t state, uint32_t level)
+static int w100fb_suspend(struct device *dev, pm_message_t state)
 {
-	if (level == SUSPEND_POWER_DOWN) {
-		struct fb_info *info = dev_get_drvdata(dev);
-		struct w100fb_par *par=info->par;
-		struct w100_tg_info *tg = par->mach->tg;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+	struct w100_tg_info *tg = par->mach->tg;
 
-		w100fb_save_vidmem(par);
-		if(tg && tg->suspend)
-			tg->suspend(par);
-		w100_suspend(W100_SUSPEND_ALL);
-		par->blanked = 1;
-	}
+	w100fb_save_vidmem(par);
+	if(tg && tg->suspend)
+		tg->suspend(par);
+	w100_suspend(W100_SUSPEND_ALL);
+	par->blanked = 1;
+
 	return 0;
 }
 
-static int w100fb_resume(struct device *dev, uint32_t level)
+static int w100fb_resume(struct device *dev)
 {
-	if (level == RESUME_POWER_ON) {
-		struct fb_info *info = dev_get_drvdata(dev);
-		struct w100fb_par *par=info->par;
-		struct w100_tg_info *tg = par->mach->tg;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct w100fb_par *par=info->par;
+	struct w100_tg_info *tg = par->mach->tg;
 
-		w100_hw_init(par);
-		w100fb_activate_var(par);
-		w100fb_restore_vidmem(par);
-		if(tg && tg->resume)
-			tg->resume(par);
-		par->blanked = 0;
-	}
+	w100_hw_init(par);
+	w100fb_activate_var(par);
+	w100fb_restore_vidmem(par);
+	if(tg && tg->resume)
+		tg->resume(par);
+	par->blanked = 0;
+
 	return 0;
 }
 #else
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index 88c517a..9e293e1 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -21,6 +21,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/sched.h>	/* schedule_timeout() */
 #include <linux/delay.h>
 
 #include "w1_family.h"
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 04ca884..87c29d7 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/zorro.h>
 #include <linux/stat.h>
+#include <linux/string.h>
 
 #include "zorro.h"
 
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index d3c05df..0f2b406 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -16,6 +16,8 @@
 #include <linux/init.h>
 #include <linux/zorro.h>
 #include <linux/bitops.h>
+#include <linux/string.h>
+
 #include <asm/setup.h>
 #include <asm/amigahw.h>
 
diff --git a/fs/Kconfig b/fs/Kconfig
index 48f5422..01a2952 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -810,7 +810,7 @@
 
 config HUGETLBFS
 	bool "HugeTLB file system support"
-	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN
+	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
 
 config HUGETLB_PAGE
 	def_bool HUGETLBFS
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 434c19d..175b2e8 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -57,7 +57,7 @@
 
 config BINFMT_AOUT
 	tristate "Kernel support for a.out and ECOFF binaries"
-	depends on (X86 && !X86_64) || ALPHA || ARM || M68K || SPARC32
+	depends on X86_32 || ALPHA || ARM || M68K || SPARC32
 	---help---
 	  A.out (Assembler.OUTput) is a set of formats for libraries and
 	  executables used in the earliest versions of UNIX.  Linux used
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 23c1251..4975c9c 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -29,7 +29,7 @@
 
 static int afs_file_readpage(struct file *file, struct page *page);
 static int afs_file_invalidatepage(struct page *page, unsigned long offset);
-static int afs_file_releasepage(struct page *page, int gfp_flags);
+static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
 
 static ssize_t afs_file_write(struct file *file, const char __user *buf,
 			      size_t size, loff_t *off);
@@ -279,7 +279,7 @@
 /*
  * release a page and cleanup its private data
  */
-static int afs_file_releasepage(struct page *page, int gfp_flags)
+static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
 {
 	struct cachefs_page *pageio;
 
@@ -291,8 +291,8 @@
 		cachefs_uncache_page(vnode->cache, page);
 #endif
 
-		pageio = (struct cachefs_page *) page->private;
-		page->private = 0;
+		pageio = (struct cachefs_page *) page_private(page);
+		set_page_private(page, 0);
 		ClearPagePrivate(page);
 
 		if (pageio)
diff --git a/fs/attr.c b/fs/attr.c
index b1796fb..67bcd9b 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -117,9 +117,6 @@
 	struct timespec now;
 	unsigned int ia_valid = attr->ia_valid;
 
-	if (!inode)
-		BUG();
-
 	mode = inode->i_mode;
 	now = current_fs_time(inode->i_sb);
 
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index dd9baab..7201182 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -318,7 +318,6 @@
 	current->mm->free_area_cache = current->mm->mmap_base;
 	current->mm->cached_hole_size = 0;
 
-	set_mm_counter(current->mm, rss, 0);
 	current->mm->mmap = NULL;
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d4b1557..6fa6adc 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -773,7 +773,6 @@
 
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
-	set_mm_counter(current->mm, rss, 0);
 	current->mm->free_area_cache = current->mm->mmap_base;
 	current->mm->cached_hole_size = 0;
 	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
@@ -1503,9 +1502,7 @@
 	fill_psinfo(psinfo, current->group_leader, current->mm);
 	fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
 	
-	fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current);
-  
-	numnote = 3;
+	numnote = 2;
 
 	auxv = (elf_addr_t *) current->mm->saved_auxv;
 
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 134c9c0..dda87c4 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -294,14 +294,7 @@
 				  &interp_params,
 				  &current->mm->start_stack,
 				  &current->mm->start_brk);
-#endif
 
-	/* do this so that we can load the interpreter, if need be
-	 * - we will change some of these later
-	 */
-	set_mm_counter(current->mm, rss, 0);
-
-#ifdef CONFIG_MMU
 	retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 7974efa..9d66258 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -650,7 +650,6 @@
 		current->mm->start_brk = datapos + data_len + bss_len;
 		current->mm->brk = (current->mm->start_brk + 3) & ~3;
 		current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
-		set_mm_counter(current->mm, rss, 0);
 	}
 
 	if (flags & FLAT_FLAG_KTRACE)
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index 227a268..00a91dc 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -259,7 +259,6 @@
 	create_som_tables(bprm);
 
 	current->mm->start_stack = bprm->p;
-	set_mm_counter(current->mm, rss, 0);
 
 #if 0
 	printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk);
diff --git a/fs/bio.c b/fs/bio.c
index 7d81a93..460554b 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -778,7 +778,7 @@
 
 
 static struct bio *__bio_map_kern(request_queue_t *q, void *data,
-				  unsigned int len, unsigned int gfp_mask)
+				  unsigned int len, gfp_t gfp_mask)
 {
 	unsigned long kaddr = (unsigned long)data;
 	unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -825,7 +825,7 @@
  *	device. Returns an error pointer in case of error.
  */
 struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len,
-			 unsigned int gfp_mask)
+			 gfp_t gfp_mask)
 {
 	struct bio *bio;
 
diff --git a/fs/buffer.c b/fs/buffer.c
index 1216c0d..35fa349 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -96,7 +96,7 @@
 __clear_page_buffers(struct page *page)
 {
 	ClearPagePrivate(page);
-	page->private = 0;
+	set_page_private(page, 0);
 	page_cache_release(page);
 }
 
@@ -502,7 +502,7 @@
 	yield();
 
 	for_each_pgdat(pgdat) {
-		zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
+		zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
 		if (*zones)
 			try_to_free_pages(zones, GFP_NOFS);
 	}
@@ -1478,8 +1478,10 @@
 void __breadahead(struct block_device *bdev, sector_t block, int size)
 {
 	struct buffer_head *bh = __getblk(bdev, block, size);
-	ll_rw_block(READA, 1, &bh);
-	brelse(bh);
+	if (likely(bh)) {
+		ll_rw_block(READA, 1, &bh);
+		brelse(bh);
+	}
 }
 EXPORT_SYMBOL(__breadahead);
 
@@ -1497,7 +1499,7 @@
 {
 	struct buffer_head *bh = __getblk(bdev, block, size);
 
-	if (!buffer_uptodate(bh))
+	if (likely(bh) && !buffer_uptodate(bh))
 		bh = __bread_slow(bh);
 	return bh;
 }
@@ -1571,7 +1573,7 @@
  *
  * NOTE: @gfp_mask may go away, and this function may become non-blocking.
  */
-int try_to_release_page(struct page *page, int gfp_mask)
+int try_to_release_page(struct page *page, gfp_t gfp_mask)
 {
 	struct address_space * const mapping = page->mapping;
 
@@ -1637,6 +1639,15 @@
 }
 EXPORT_SYMBOL(block_invalidatepage);
 
+int do_invalidatepage(struct page *page, unsigned long offset)
+{
+	int (*invalidatepage)(struct page *, unsigned long);
+	invalidatepage = page->mapping->a_ops->invalidatepage;
+	if (invalidatepage == NULL)
+		invalidatepage = block_invalidatepage;
+	return (*invalidatepage)(page, offset);
+}
+
 /*
  * We attach and possibly dirty the buffers atomically wrt
  * __set_page_dirty_buffers() via private_lock.  try_to_free_buffers
@@ -2696,7 +2707,7 @@
 		 * they may have been added in ext3_writepage().  Make them
 		 * freeable here, so the page does not leak.
 		 */
-		block_invalidatepage(page, 0);
+		do_invalidatepage(page, 0);
 		unlock_page(page);
 		return 0; /* don't care */
 	}
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 3d1cce3..6a3df88 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -370,8 +370,8 @@
 	}		
 	devfs_mk_dir ("coda");
 	for (i = 0; i < MAX_CODADEVS; i++) {
-		class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
-				NULL, "cfs%d", i);
+		class_device_create(coda_psdev_class, NULL,
+				MKDEV(CODA_PSDEV_MAJOR,i), NULL, "cfs%d", i);
 		err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
 				S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
 		if (err)
diff --git a/fs/compat.c b/fs/compat.c
index a719e15..8e71cdb 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1490,7 +1490,6 @@
 		/* execve success */
 		security_bprm_free(bprm);
 		acct_update_integrals(current);
-		update_mem_hiwater(current);
 		kfree(bprm);
 		return retval;
 	}
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index e28a742..43dbcb0 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -3046,10 +3046,15 @@
 /* Serial */
 HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl)
 HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
+#ifdef TIOCGLTC
+COMPATIBLE_IOCTL(TIOCGLTC)
+COMPATIBLE_IOCTL(TIOCSLTC)
+#endif
 /* Usbdevfs */
 HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
 HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
 HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+COMPATIBLE_IOCTL(USBDEVFS_IOCTL32)
 /* i2c */
 HANDLE_IOCTL(I2C_FUNCS, w_long)
 HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl)
diff --git a/fs/dcache.c b/fs/dcache.c
index fb10386..e90512e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -689,7 +689,7 @@
  *
  * In this case we return -1 to tell the caller that we baled.
  */
-static int shrink_dcache_memory(int nr, unsigned int gfp_mask)
+static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
 {
 	if (nr) {
 		if (!(gfp_mask & __GFP_FS))
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 0d06097..3931e7f 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -162,6 +162,7 @@
 	up_read(&current->mm->mmap_sem);
 
 	if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) {
+		struct page *page = ZERO_PAGE(dio->curr_user_address);
 		/*
 		 * A memory fault, but the filesystem has some outstanding
 		 * mapped blocks.  We need to use those blocks up to avoid
@@ -169,7 +170,8 @@
 		 */
 		if (dio->page_errors == 0)
 			dio->page_errors = ret;
-		dio->pages[0] = ZERO_PAGE(dio->curr_user_address);
+		page_cache_get(page);
+		dio->pages[0] = page;
 		dio->head = 0;
 		dio->tail = 1;
 		ret = 0;
diff --git a/fs/dquot.c b/fs/dquot.c
index b973233..ea76442 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -500,7 +500,7 @@
  * more memory
  */
 
-static int shrink_dqcache_memory(int nr, unsigned int gfp_mask)
+static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
 {
 	if (nr) {
 		spin_lock(&dq_list_lock);
@@ -662,7 +662,7 @@
 restart:
 	file_list_lock();
 	list_for_each(p, &sb->s_files) {
-		struct file *filp = list_entry(p, struct file, f_list);
+		struct file *filp = list_entry(p, struct file, f_u.fu_list);
 		struct inode *inode = filp->f_dentry->d_inode;
 		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
 			struct dentry *dentry = dget(filp->f_dentry);
diff --git a/fs/exec.c b/fs/exec.c
index a04a575..10d493f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -126,8 +126,7 @@
 	struct nameidata nd;
 	int error;
 
-	nd.intent.open.flags = FMODE_READ;
-	error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
+	error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ);
 	if (error)
 		goto out;
 
@@ -139,7 +138,7 @@
 	if (error)
 		goto exit;
 
-	file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+	file = nameidata_to_filp(&nd, O_RDONLY);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
 		goto out;
@@ -167,6 +166,7 @@
 out:
   	return error;
 exit:
+	release_open_intent(&nd);
 	path_release(&nd);
 	goto out;
 }
@@ -309,40 +309,36 @@
 	pud_t * pud;
 	pmd_t * pmd;
 	pte_t * pte;
+	spinlock_t *ptl;
 
 	if (unlikely(anon_vma_prepare(vma)))
-		goto out_sig;
+		goto out;
 
 	flush_dcache_page(page);
 	pgd = pgd_offset(mm, address);
-
-	spin_lock(&mm->page_table_lock);
 	pud = pud_alloc(mm, pgd, address);
 	if (!pud)
 		goto out;
 	pmd = pmd_alloc(mm, pud, address);
 	if (!pmd)
 		goto out;
-	pte = pte_alloc_map(mm, pmd, address);
+	pte = pte_alloc_map_lock(mm, pmd, address, &ptl);
 	if (!pte)
 		goto out;
 	if (!pte_none(*pte)) {
-		pte_unmap(pte);
+		pte_unmap_unlock(pte, ptl);
 		goto out;
 	}
-	inc_mm_counter(mm, rss);
+	inc_mm_counter(mm, anon_rss);
 	lru_cache_add_active(page);
 	set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
 					page, vma->vm_page_prot))));
 	page_add_anon_rmap(page, vma, address);
-	pte_unmap(pte);
-	spin_unlock(&mm->page_table_lock);
+	pte_unmap_unlock(pte, ptl);
 
 	/* no need for flush_tlb */
 	return;
 out:
-	spin_unlock(&mm->page_table_lock);
-out_sig:
 	__free_page(page);
 	force_sig(SIGKILL, current);
 }
@@ -490,8 +486,7 @@
 	int err;
 	struct file *file;
 
-	nd.intent.open.flags = FMODE_READ;
-	err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
+	err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ);
 	file = ERR_PTR(err);
 
 	if (!err) {
@@ -504,7 +499,7 @@
 				err = -EACCES;
 			file = ERR_PTR(err);
 			if (!err) {
-				file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+				file = nameidata_to_filp(&nd, O_RDONLY);
 				if (!IS_ERR(file)) {
 					err = deny_write_access(file);
 					if (err) {
@@ -516,6 +511,7 @@
 				return file;
 			}
 		}
+		release_open_intent(&nd);
 		path_release(&nd);
 	}
 	goto out;
@@ -634,10 +630,9 @@
 	/*
 	 * Account for the thread group leader hanging around:
 	 */
-	count = 2;
-	if (thread_group_leader(current))
-		count = 1;
-	else {
+	count = 1;
+	if (!thread_group_leader(current)) {
+		count = 2;
 		/*
 		 * The SIGALRM timer survives the exec, but needs to point
 		 * at us as the new group leader now.  We have a race with
@@ -646,8 +641,10 @@
 		 * before we can safely let the old group leader die.
 		 */
 		sig->real_timer.data = (unsigned long)current;
+		spin_unlock_irq(lock);
 		if (del_timer_sync(&sig->real_timer))
 			add_timer(&sig->real_timer);
+		spin_lock_irq(lock);
 	}
 	while (atomic_read(&sig->count) > count) {
 		sig->group_exit_task = current;
@@ -659,7 +656,6 @@
 	}
 	sig->group_exit_task = NULL;
 	sig->notify_count = 0;
-	sig->real_timer.data = (unsigned long)current;
 	spin_unlock_irq(lock);
 
 	/*
@@ -1207,7 +1203,6 @@
 		/* execve success */
 		security_bprm_free(bprm);
 		acct_update_integrals(current);
-		update_mem_hiwater(current);
 		kfree(bprm);
 		return retval;
 	}
@@ -1422,19 +1417,16 @@
 static void coredump_wait(struct mm_struct *mm)
 {
 	DECLARE_COMPLETION(startup_done);
+	int core_waiters;
 
-	mm->core_waiters++; /* let other threads block */
 	mm->core_startup_done = &startup_done;
 
-	/* give other threads a chance to run: */
-	yield();
-
 	zap_threads(mm);
-	if (--mm->core_waiters) {
-		up_write(&mm->mmap_sem);
+	core_waiters = mm->core_waiters;
+	up_write(&mm->mmap_sem);
+
+	if (core_waiters)
 		wait_for_completion(&startup_done);
-	} else
-		up_write(&mm->mmap_sem);
 	BUG_ON(mm->core_waiters);
 }
 
@@ -1468,11 +1460,21 @@
 		current->fsuid = 0;	/* Dump root private */
 	}
 	mm->dumpable = 0;
-	init_completion(&mm->core_done);
+
+	retval = -EAGAIN;
 	spin_lock_irq(&current->sighand->siglock);
-	current->signal->flags = SIGNAL_GROUP_EXIT;
-	current->signal->group_exit_code = exit_code;
+	if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
+		current->signal->flags = SIGNAL_GROUP_EXIT;
+		current->signal->group_exit_code = exit_code;
+		retval = 0;
+	}
 	spin_unlock_irq(&current->sighand->siglock);
+	if (retval) {
+		up_write(&mm->mmap_sem);
+		goto fail;
+	}
+
+	init_completion(&mm->core_done);
 	coredump_wait(mm);
 
 	/*
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index fdba4d1..e7d3f05 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -440,6 +440,10 @@
 		 * the pointer to new one, then send parent to disk.
 		 */
 		bh = sb_getblk(inode->i_sb, parent);
+		if (!bh) {
+			err = -EIO;
+			break;
+		}
 		lock_buffer(bh);
 		memset(bh->b_data, 0, blocksize);
 		branch[n].bh = bh;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 0213db4..7992d21 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -20,6 +20,8 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 
+#include "bitmap.h"
+
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
@@ -1010,7 +1012,7 @@
  * allocation within the reservation window.
  *
  * This will avoid keeping on searching the reservation list again and
- * again when someboday is looking for a free block (without
+ * again when somebody is looking for a free block (without
  * reservation), and there are lots of free blocks, but they are all
  * being reserved.
  *
@@ -1416,12 +1418,12 @@
 	unsigned long bitmap_count, x;
 	struct buffer_head *bitmap_bh = NULL;
 
-	lock_super(sb);
 	es = EXT3_SB(sb)->s_es;
 	desc_count = 0;
 	bitmap_count = 0;
 	gdp = NULL;
 
+	smp_rmb();
 	for (i = 0; i < ngroups; i++) {
 		gdp = ext3_get_group_desc(sb, i, NULL);
 		if (!gdp)
@@ -1440,7 +1442,6 @@
 	brelse(bitmap_bh);
 	printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n",
 	       le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
-	unlock_super(sb);
 	return bitmap_count;
 #else
 	desc_count = 0;
diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c
index 6c419b9..5b4ba3e 100644
--- a/fs/ext3/bitmap.c
+++ b/fs/ext3/bitmap.c
@@ -8,7 +8,7 @@
  */
 
 #include <linux/buffer_head.h>
-
+#include "bitmap.h"
 
 static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
 
diff --git a/fs/ext3/bitmap.h b/fs/ext3/bitmap.h
new file mode 100644
index 0000000..6ee503a
--- /dev/null
+++ b/fs/ext3/bitmap.h
@@ -0,0 +1,8 @@
+/*  linux/fs/ext3/bitmap.c
+ *
+ * Copyright (C) 2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+*/
+
+extern unsigned long ext3_count_free (struct buffer_head *, unsigned int );
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 6549945..df3f517 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -26,6 +26,7 @@
 
 #include <asm/byteorder.h>
 
+#include "bitmap.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -704,7 +705,6 @@
 	unsigned long bitmap_count, x;
 	struct buffer_head *bitmap_bh = NULL;
 
-	lock_super (sb);
 	es = EXT3_SB(sb)->s_es;
 	desc_count = 0;
 	bitmap_count = 0;
@@ -727,7 +727,6 @@
 	brelse(bitmap_bh);
 	printk("ext3_count_free_inodes: stored = %u, computed = %lu, %lu\n",
 		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
-	unlock_super(sb);
 	return desc_count;
 #else
 	desc_count = 0;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index b5177c9..5d9b00e 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -491,7 +491,7 @@
  *	the same format as ext3_get_branch() would do. We are calling it after
  *	we had read the existing part of chain and partial points to the last
  *	triple of that (one with zero ->key). Upon the exit we have the same
- *	picture as after the successful ext3_get_block(), excpet that in one
+ *	picture as after the successful ext3_get_block(), except that in one
  *	place chain is disconnected - *branch->p is still zero (we did not
  *	set the last link), but branch->key contains the number that should
  *	be placed into *branch->p to fill that gap.
@@ -523,7 +523,6 @@
 			if (!nr)
 				break;
 			branch[n].key = cpu_to_le32(nr);
-			keys = n+1;
 
 			/*
 			 * Get buffer_head for parent block, zero it out
@@ -531,6 +530,9 @@
 			 * parent to disk.  
 			 */
 			bh = sb_getblk(inode->i_sb, parent);
+			if (!bh)
+				break;
+			keys = n+1;
 			branch[n].bh = bh;
 			lock_buffer(bh);
 			BUFFER_TRACE(bh, "call get_create_access");
@@ -864,6 +866,10 @@
 	if (!*errp && buffer_mapped(&dummy)) {
 		struct buffer_head *bh;
 		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
+		if (!bh) {
+			*errp = -EIO;
+			goto err;
+		}
 		if (buffer_new(&dummy)) {
 			J_ASSERT(create != 0);
 			J_ASSERT(handle != 0);
@@ -896,6 +902,7 @@
 		}
 		return bh;
 	}
+err:
 	return NULL;
 }
 
@@ -1434,7 +1441,7 @@
 	return journal_invalidatepage(journal, page, offset);
 }
 
-static int ext3_releasepage(struct page *page, int wait)
+static int ext3_releasepage(struct page *page, gfp_t wait)
 {
 	journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 50378d8..b3c690a 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -36,6 +36,8 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
+
+#include "namei.h"
 #include "xattr.h"
 #include "acl.h"
 
diff --git a/fs/ext3/namei.h b/fs/ext3/namei.h
new file mode 100644
index 0000000..f2ce2b0
--- /dev/null
+++ b/fs/ext3/namei.h
@@ -0,0 +1,8 @@
+/*  linux/fs/ext3/namei.h
+ *
+ * Copyright (C) 2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+*/
+
+extern struct dentry *ext3_get_parent(struct dentry *child);
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 57f7910..1be78b4b 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -118,6 +118,8 @@
 	int err;
 
 	bh = sb_getblk(sb, blk);
+	if (!bh)
+		return ERR_PTR(-EIO);
 	if ((err = ext3_journal_get_write_access(handle, bh))) {
 		brelse(bh);
 		bh = ERR_PTR(err);
@@ -202,6 +204,10 @@
 		ext3_debug("update backup group %#04lx (+%d)\n", block, bit);
 
 		gdb = sb_getblk(sb, block);
+		if (!gdb) {
+			err = -EIO;
+			goto exit_bh;
+		}
 		if ((err = ext3_journal_get_write_access(handle, gdb))) {
 			brelse(gdb);
 			goto exit_bh;
@@ -643,6 +649,10 @@
 			break;
 
 		bh = sb_getblk(sb, group * bpg + blk_off);
+		if (!bh) {
+			err = -EIO;
+			break;
+		}
 		ext3_debug("update metadata backup %#04lx\n",
 			  (unsigned long)bh->b_blocknr);
 		if ((err = ext3_journal_get_write_access(handle, bh)))
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9e24ceb..f594989 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -36,9 +36,12 @@
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
+
 #include <asm/uaccess.h>
+
 #include "xattr.h"
 #include "acl.h"
+#include "namei.h"
 
 static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
 static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
@@ -510,19 +513,11 @@
 	kfree(rsv);
 }
 
-static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
 {
-	struct super_block *sb = vfs->mnt_sb;
+#if defined(CONFIG_QUOTA)
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 
-	if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
-		seq_puts(seq, ",data=journal");
-	else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
-		seq_puts(seq, ",data=ordered");
-	else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
-		seq_puts(seq, ",data=writeback");
-
-#if defined(CONFIG_QUOTA)
 	if (sbi->s_jquota_fmt)
 		seq_printf(seq, ",jqfmt=%s",
 		(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
@@ -539,6 +534,20 @@
 	if (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)
 		seq_puts(seq, ",grpquota");
 #endif
+}
+
+static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+	struct super_block *sb = vfs->mnt_sb;
+
+	if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
+		seq_puts(seq, ",data=journal");
+	else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
+		seq_puts(seq, ",data=ordered");
+	else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
+		seq_puts(seq, ",data=writeback");
+
+	ext3_show_quota_options(seq, sb);
 
 	return 0;
 }
@@ -609,7 +618,6 @@
 #endif
 };
 
-struct dentry *ext3_get_parent(struct dentry *child);
 static struct export_operations ext3_export_ops = {
 	.get_parent = ext3_get_parent,
 };
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 269c7b9..430de9f 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -210,7 +210,7 @@
 	return cmp ? -ENODATA : 0;
 }
 
-int
+static int
 ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
 		     void *buffer, size_t buffer_size)
 {
@@ -354,7 +354,7 @@
 	return buffer_size - rest;
 }
 
-int
+static int
 ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
 {
 	struct buffer_head *bh = NULL;
@@ -626,7 +626,7 @@
 	struct buffer_head *bh;
 };
 
-int
+static int
 ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i,
 		      struct ext3_xattr_block_find *bs)
 {
@@ -859,7 +859,7 @@
 	struct ext3_iloc iloc;
 };
 
-int
+static int
 ext3_xattr_ibody_find(struct inode *inode, struct ext3_xattr_info *i,
 		      struct ext3_xattr_ibody_find *is)
 {
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 895049b..ba82496 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -222,6 +222,80 @@
 	return len;
 }
 
+enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, };
+
+/**
+ * fat_parse_long - Parse extended directory entry.
+ *
+ * This function returns zero on success, negative value on error, or one of
+ * the following:
+ *
+ * %PARSE_INVALID - Directory entry is invalid.
+ * %PARSE_NOT_LONGNAME - Directory entry does not contain longname.
+ * %PARSE_EOF - Directory has no more entries.
+ */
+static int fat_parse_long(struct inode *dir, loff_t *pos,
+			  struct buffer_head **bh, struct msdos_dir_entry **de,
+			  wchar_t **unicode, unsigned char *nr_slots)
+{
+	struct msdos_dir_slot *ds;
+	unsigned char id, slot, slots, alias_checksum;
+
+	if (!*unicode) {
+		*unicode = (wchar_t *)__get_free_page(GFP_KERNEL);
+		if (!*unicode) {
+			brelse(*bh);
+			return -ENOMEM;
+		}
+	}
+parse_long:
+	slots = 0;
+	ds = (struct msdos_dir_slot *)*de;
+	id = ds->id;
+	if (!(id & 0x40))
+		return PARSE_INVALID;
+	slots = id & ~0x40;
+	if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */
+		return PARSE_INVALID;
+	*nr_slots = slots;
+	alias_checksum = ds->alias_checksum;
+
+	slot = slots;
+	while (1) {
+		int offset;
+
+		slot--;
+		offset = slot * 13;
+		fat16_towchar(*unicode + offset, ds->name0_4, 5);
+		fat16_towchar(*unicode + offset + 5, ds->name5_10, 6);
+		fat16_towchar(*unicode + offset + 11, ds->name11_12, 2);
+
+		if (ds->id & 0x40)
+			(*unicode)[offset + 13] = 0;
+		if (fat_get_entry(dir, pos, bh, de) < 0)
+			return PARSE_EOF;
+		if (slot == 0)
+			break;
+		ds = (struct msdos_dir_slot *)*de;
+		if (ds->attr != ATTR_EXT)
+			return PARSE_NOT_LONGNAME;
+		if ((ds->id & ~0x40) != slot)
+			goto parse_long;
+		if (ds->alias_checksum != alias_checksum)
+			goto parse_long;
+	}
+	if ((*de)->name[0] == DELETED_FLAG)
+		return PARSE_INVALID;
+	if ((*de)->attr == ATTR_EXT)
+		goto parse_long;
+	if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME))
+		return PARSE_INVALID;
+	if (fat_checksum((*de)->name) != alias_checksum)
+		*nr_slots = 0;
+
+	return 0;
+}
+
 /*
  * Return values: negative -> error, 0 -> not found, positive -> found,
  * value is the total amount of slots, including the shortname entry.
@@ -259,68 +333,16 @@
 		if (de->attr != ATTR_EXT && IS_FREE(de->name))
 			continue;
 		if (de->attr == ATTR_EXT) {
-			struct msdos_dir_slot *ds;
-			unsigned char id;
-			unsigned char slot;
-			unsigned char slots;
-			unsigned char sum;
-			unsigned char alias_checksum;
-
-			if (!unicode) {
-				unicode = (wchar_t *)
-					__get_free_page(GFP_KERNEL);
-				if (!unicode) {
-					brelse(bh);
-					return -ENOMEM;
-				}
-			}
-parse_long:
-			slots = 0;
-			ds = (struct msdos_dir_slot *) de;
-			id = ds->id;
-			if (!(id & 0x40))
+			int status = fat_parse_long(inode, &cpos, &bh, &de,
+						    &unicode, &nr_slots);
+			if (status < 0)
+				return status;
+			else if (status == PARSE_INVALID)
 				continue;
-			slots = id & ~0x40;
-			if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */
-				continue;
-			nr_slots = slots;
-			alias_checksum = ds->alias_checksum;
-
-			slot = slots;
-			while (1) {
-				int offset;
-
-				slot--;
-				offset = slot * 13;
-				fat16_towchar(unicode + offset, ds->name0_4, 5);
-				fat16_towchar(unicode + offset + 5, ds->name5_10, 6);
-				fat16_towchar(unicode + offset + 11, ds->name11_12, 2);
-
-				if (ds->id & 0x40) {
-					unicode[offset + 13] = 0;
-				}
-				if (fat_get_entry(inode, &cpos, &bh, &de) < 0)
-					goto EODir;
-				if (slot == 0)
-					break;
-				ds = (struct msdos_dir_slot *) de;
-				if (ds->attr !=  ATTR_EXT)
-					goto parse_record;
-				if ((ds->id & ~0x40) != slot)
-					goto parse_long;
-				if (ds->alias_checksum != alias_checksum)
-					goto parse_long;
-			}
-			if (de->name[0] == DELETED_FLAG)
-				continue;
-			if (de->attr ==  ATTR_EXT)
-				goto parse_long;
-			if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))
-				continue;
-			for (sum = 0, i = 0; i < 11; i++)
-				sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
-			if (sum != alias_checksum)
-				nr_slots = 0;
+			else if (status == PARSE_NOT_LONGNAME)
+				goto parse_record;
+			else if (status == PARSE_EOF)
+				goto EODir;
 		}
 
 		memcpy(work, de->name, sizeof(de->name));
@@ -408,8 +430,8 @@
 	int short_len;
 };
 
-static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
-			filldir_t filldir, int short_only, int both)
+static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
+			 filldir_t filldir, int short_only, int both)
 {
 	struct super_block *sb = inode->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -458,9 +480,10 @@
 
 	bh = NULL;
 GetNew:
-	long_slots = 0;
 	if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
 		goto EODir;
+parse_record:
+	long_slots = 0;
 	/* Check for long filename entry */
 	if (isvfat) {
 		if (de->name[0] == DELETED_FLAG)
@@ -475,69 +498,18 @@
 	}
 
 	if (isvfat && de->attr == ATTR_EXT) {
-		struct msdos_dir_slot *ds;
-		unsigned char id;
-		unsigned char slot;
-		unsigned char slots;
-		unsigned char sum;
-		unsigned char alias_checksum;
-
-		if (!unicode) {
-			unicode = (wchar_t *)__get_free_page(GFP_KERNEL);
-			if (!unicode) {
-				filp->f_pos = cpos;
-				brelse(bh);
-				ret = -ENOMEM;
-				goto out;
-			}
-		}
-ParseLong:
-		slots = 0;
-		ds = (struct msdos_dir_slot *) de;
-		id = ds->id;
-		if (!(id & 0x40))
+		int status = fat_parse_long(inode, &cpos, &bh, &de,
+					    &unicode, &long_slots);
+		if (status < 0) {
+			filp->f_pos = cpos;
+			ret = status;
+			goto out;
+		} else if (status == PARSE_INVALID)
 			goto RecEnd;
-		slots = id & ~0x40;
-		if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */
-			goto RecEnd;
-		long_slots = slots;
-		alias_checksum = ds->alias_checksum;
-
-		slot = slots;
-		while (1) {
-			int offset;
-
-			slot--;
-			offset = slot * 13;
-			fat16_towchar(unicode + offset, ds->name0_4, 5);
-			fat16_towchar(unicode + offset + 5, ds->name5_10, 6);
-			fat16_towchar(unicode + offset + 11, ds->name11_12, 2);
-
-			if (ds->id & 0x40) {
-				unicode[offset + 13] = 0;
-			}
-			if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
-				goto EODir;
-			if (slot == 0)
-				break;
-			ds = (struct msdos_dir_slot *) de;
-			if (ds->attr !=  ATTR_EXT)
-				goto RecEnd;	/* XXX */
-			if ((ds->id & ~0x40) != slot)
-				goto ParseLong;
-			if (ds->alias_checksum != alias_checksum)
-				goto ParseLong;
-		}
-		if (de->name[0] == DELETED_FLAG)
-			goto RecEnd;
-		if (de->attr ==  ATTR_EXT)
-			goto ParseLong;
-		if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))
-			goto RecEnd;
-		for (sum = 0, i = 0; i < 11; i++)
-			sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
-		if (sum != alias_checksum)
-			long_slots = 0;
+		else if (status == PARSE_NOT_LONGNAME)
+			goto parse_record;
+		else if (status == PARSE_EOF)
+			goto EODir;
 	}
 
 	if (sbi->options.dotsOK) {
@@ -671,7 +643,7 @@
 static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
-	return fat_readdirx(inode, filp, dirent, filldir, 0, 0);
+	return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
 }
 
 static int fat_ioctl_filldir(void *__buf, const char *name, int name_len,
@@ -760,8 +732,8 @@
 	down(&inode->i_sem);
 	ret = -ENOENT;
 	if (!IS_DEADDIR(inode)) {
-		ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir,
-				   short_only, both);
+		ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir,
+				    short_only, both);
 	}
 	up(&inode->i_sem);
 	if (ret >= 0)
diff --git a/fs/file_table.c b/fs/file_table.c
index 86ec8ae..4dc2055 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -56,13 +56,13 @@
 
 static inline void file_free_rcu(struct rcu_head *head)
 {
-	struct file *f =  container_of(head, struct file, f_rcuhead);
+	struct file *f =  container_of(head, struct file, f_u.fu_rcuhead);
 	kmem_cache_free(filp_cachep, f);
 }
 
 static inline void file_free(struct file *f)
 {
-	call_rcu(&f->f_rcuhead, file_free_rcu);
+	call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
 }
 
 /* Find an unused file structure and return a pointer to it.
@@ -95,7 +95,7 @@
 	f->f_gid = current->fsgid;
 	rwlock_init(&f->f_owner.lock);
 	/* f->f_version: 0 */
-	INIT_LIST_HEAD(&f->f_list);
+	INIT_LIST_HEAD(&f->f_u.fu_list);
 	return f;
 
 over:
@@ -225,15 +225,15 @@
 	if (!list)
 		return;
 	file_list_lock();
-	list_move(&file->f_list, list);
+	list_move(&file->f_u.fu_list, list);
 	file_list_unlock();
 }
 
 void file_kill(struct file *file)
 {
-	if (!list_empty(&file->f_list)) {
+	if (!list_empty(&file->f_u.fu_list)) {
 		file_list_lock();
-		list_del_init(&file->f_list);
+		list_del_init(&file->f_u.fu_list);
 		file_list_unlock();
 	}
 }
@@ -245,7 +245,7 @@
 	/* Check that no files are currently opened for writing. */
 	file_list_lock();
 	list_for_each(p, &sb->s_files) {
-		struct file *file = list_entry(p, struct file, f_list);
+		struct file *file = list_entry(p, struct file, f_u.fu_list);
 		struct inode *inode = file->f_dentry->d_inode;
 
 		/* File with pending delete? */
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 44082bf..9f10728 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -12,6 +12,7 @@
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/sched.h>	/* for 'current' */
 #include <asm/uaccess.h>
 
 /*
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index e94ab39..ffab478 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -230,7 +230,6 @@
 			 * The inode is clean, unused
 			 */
 			list_move(&inode->i_list, &inode_unused);
-			inodes_stat.nr_unused++;
 		}
 	}
 	wake_up_inode(inode);
@@ -238,14 +237,20 @@
 }
 
 /*
- * Write out an inode's dirty pages.  Called under inode_lock.
+ * Write out an inode's dirty pages.  Called under inode_lock.  Either the
+ * caller has ref on the inode (either via __iget or via syscall against an fd)
+ * or the inode has I_WILL_FREE set (via generic_forget_inode)
  */
 static int
-__writeback_single_inode(struct inode *inode,
-			struct writeback_control *wbc)
+__writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	wait_queue_head_t *wqh;
 
+	if (!atomic_read(&inode->i_count))
+		WARN_ON(!(inode->i_state & I_WILL_FREE));
+	else
+		WARN_ON(inode->i_state & I_WILL_FREE);
+
 	if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) {
 		list_move(&inode->i_list, &inode->i_sb->s_dirty);
 		return 0;
@@ -259,11 +264,9 @@
 
 		wqh = bit_waitqueue(&inode->i_state, __I_LOCK);
 		do {
-			__iget(inode);
 			spin_unlock(&inode_lock);
 			__wait_on_bit(wqh, &wq, inode_wait,
 							TASK_UNINTERRUPTIBLE);
-			iput(inode);
 			spin_lock(&inode_lock);
 		} while (inode->i_state & I_LOCK);
 	}
@@ -541,14 +544,15 @@
 }
 
 /**
- *	write_inode_now	-	write an inode to disk
- *	@inode: inode to write to disk
- *	@sync: whether the write should be synchronous or not
+ * write_inode_now	-	write an inode to disk
+ * @inode: inode to write to disk
+ * @sync: whether the write should be synchronous or not
  *
- *	This function commits an inode to disk immediately if it is
- *	dirty. This is primarily needed by knfsd.
+ * This function commits an inode to disk immediately if it is dirty. This is
+ * primarily needed by knfsd.
+ *
+ * The caller must either have a ref on the inode or must have set I_WILL_FREE.
  */
- 
 int write_inode_now(struct inode *inode, int sync)
 {
 	int ret;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index d4c869c..a6f90a6 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -151,9 +151,9 @@
 /*
  * This function is called when a request is finished.  Either a reply
  * has arrived or it was interrupted (and not yet sent) or some error
- * occured during communication with userspace, or the device file was
- * closed.  It decreases the referece count for the request.  In case
- * of a background request the referece to the stored objects are
+ * occurred during communication with userspace, or the device file was
+ * closed.  It decreases the reference count for the request.  In case
+ * of a background request the reference to the stored objects are
  * released.  The requester thread is woken up (if still waiting), and
  * finally the request is either freed or put on the unused_list
  *
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 29f1e9f..70dba72 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -741,13 +741,14 @@
 	if (inode && S_ISDIR(inode->i_mode)) {
 		/* Don't allow creating an alias to a directory  */
 		struct dentry *alias = d_find_alias(inode);
-		if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
+		if (alias) {
 			dput(alias);
 			iput(inode);
 			return ERR_PTR(-EIO);
 		}
 	}
-	return d_splice_alias(inode, entry);
+	d_add(entry, inode);
+	return NULL;
 }
 
 static int fuse_setxattr(struct dentry *entry, const char *name,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 24d7615..5cb456f5 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -349,22 +349,22 @@
 		      int isdir);
 
 /**
- * Initialise file operations on a regular file
+ * Initialize file operations on a regular file
  */
 void fuse_init_file_inode(struct inode *inode);
 
 /**
- * Initialise inode operations on regular files and special files
+ * Initialize inode operations on regular files and special files
  */
 void fuse_init_common(struct inode *inode);
 
 /**
- * Initialise inode and file operations on a directory
+ * Initialize inode and file operations on a directory
  */
 void fuse_init_dir(struct inode *inode);
 
 /**
- * Initialise inode operations on a symlink
+ * Initialize inode operations on a symlink
  */
 void fuse_init_symlink(struct inode *inode);
 
@@ -411,7 +411,7 @@
 
 /**
  * Decrement reference count of a request.  If count goes to zero put
- * on unused list (preallocated) or free reqest (not preallocated).
+ * on unused list (preallocated) or free request (not preallocated).
  */
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
 
@@ -431,7 +431,7 @@
 void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
 
 /**
- * Release inodes and file assiciated with background request
+ * Release inodes and file associated with background request
  */
 void fuse_release_background(struct fuse_req *req);
 
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index f1570b9..3f680c5 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -46,7 +46,7 @@
 	return generic_block_bmap(mapping, block, hfs_get_block);
 }
 
-static int hfs_releasepage(struct page *page, int mask)
+static int hfs_releasepage(struct page *page, gfp_t mask)
 {
 	struct inode *inode = page->mapping->host;
 	struct super_block *sb = inode->i_sb;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index d564270..f205773 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -40,7 +40,7 @@
 	return generic_block_bmap(mapping, block, hfsplus_get_block);
 }
 
-static int hfsplus_releasepage(struct page *page, int mask)
+static int hfsplus_releasepage(struct page *page, gfp_t mask)
 {
 	struct inode *inode = page->mapping->host;
 	struct super_block *sb = inode->i_sb;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 3a9b6d1..e026c80 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -45,10 +45,58 @@
 
 int sysctl_hugetlb_shm_group;
 
+static void huge_pagevec_release(struct pagevec *pvec)
+{
+	int i;
+
+	for (i = 0; i < pagevec_count(pvec); ++i)
+		put_page(pvec->pages[i]);
+
+	pagevec_reinit(pvec);
+}
+
+/*
+ * huge_pages_needed tries to determine the number of new huge pages that
+ * will be required to fully populate this VMA.  This will be equal to
+ * the size of the VMA in huge pages minus the number of huge pages
+ * (covered by this VMA) that are found in the page cache.
+ *
+ * Result is in bytes to be compatible with is_hugepage_mem_enough()
+ */
+unsigned long
+huge_pages_needed(struct address_space *mapping, struct vm_area_struct *vma)
+{
+	int i;
+	struct pagevec pvec;
+	unsigned long start = vma->vm_start;
+	unsigned long end = vma->vm_end;
+	unsigned long hugepages = (end - start) >> HPAGE_SHIFT;
+	pgoff_t next = vma->vm_pgoff;
+	pgoff_t endpg = next + ((end - start) >> PAGE_SHIFT);
+
+	pagevec_init(&pvec, 0);
+	while (next < endpg) {
+		if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE))
+			break;
+		for (i = 0; i < pagevec_count(&pvec); i++) {
+			struct page *page = pvec.pages[i];
+			if (page->index > next)
+				next = page->index;
+			if (page->index >= endpg)
+				break;
+			next++;
+			hugepages--;
+		}
+		huge_pagevec_release(&pvec);
+	}
+	return hugepages << HPAGE_SHIFT;
+}
+
 static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
+	unsigned long bytes;
 	loff_t len, vma_len;
 	int ret;
 
@@ -67,6 +115,10 @@
 	if (vma->vm_end - vma->vm_start < HPAGE_SIZE)
 		return -EINVAL;
 
+	bytes = huge_pages_needed(mapping, vma);
+	if (!is_hugepage_mem_enough(bytes))
+		return -ENOMEM;
+
 	vma_len = (loff_t)(vma->vm_end - vma->vm_start);
 
 	down(&inode->i_sem);
@@ -79,10 +131,8 @@
 	if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size)
 		goto out;
 
-	ret = hugetlb_prefault(mapping, vma);
-	if (ret)
-		goto out;
-
+	ret = 0;
+	hugetlb_prefault_arch_hook(vma->vm_mm);
 	if (inode->i_size < len)
 		inode->i_size = len;
 out:
@@ -92,7 +142,7 @@
 }
 
 /*
- * Called under down_write(mmap_sem), page_table_lock is not held
+ * Called under down_write(mmap_sem).
  */
 
 #ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
@@ -171,16 +221,6 @@
 	return -EINVAL;
 }
 
-static void huge_pagevec_release(struct pagevec *pvec)
-{
-	int i;
-
-	for (i = 0; i < pagevec_count(pvec); ++i)
-		put_page(pvec->pages[i]);
-
-	pagevec_reinit(pvec);
-}
-
 static void truncate_huge_page(struct page *page)
 {
 	clear_page_dirty(page);
@@ -224,52 +264,35 @@
 
 static void hugetlbfs_delete_inode(struct inode *inode)
 {
-	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(inode->i_sb);
-
-	hlist_del_init(&inode->i_hash);
-	list_del_init(&inode->i_list);
-	list_del_init(&inode->i_sb_list);
-	inode->i_state |= I_FREEING;
-	inodes_stat.nr_inodes--;
-	spin_unlock(&inode_lock);
-
 	if (inode->i_data.nrpages)
 		truncate_hugepages(&inode->i_data, 0);
-
-	security_inode_delete(inode);
-
-	if (sbinfo->free_inodes >= 0) {
-		spin_lock(&sbinfo->stat_lock);
-		sbinfo->free_inodes++;
-		spin_unlock(&sbinfo->stat_lock);
-	}
-
 	clear_inode(inode);
-	destroy_inode(inode);
 }
 
 static void hugetlbfs_forget_inode(struct inode *inode)
 {
-	struct super_block *super_block = inode->i_sb;
-	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(super_block);
+	struct super_block *sb = inode->i_sb;
 
-	if (hlist_unhashed(&inode->i_hash))
-		goto out_truncate;
-
-	if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
-		list_del(&inode->i_list);
-		list_add(&inode->i_list, &inode_unused);
-	}
-	inodes_stat.nr_unused++;
-	if (!super_block || (super_block->s_flags & MS_ACTIVE)) {
+	if (!hlist_unhashed(&inode->i_hash)) {
+		if (!(inode->i_state & (I_DIRTY|I_LOCK)))
+			list_move(&inode->i_list, &inode_unused);
+		inodes_stat.nr_unused++;
+		if (!sb || (sb->s_flags & MS_ACTIVE)) {
+			spin_unlock(&inode_lock);
+			return;
+		}
+		inode->i_state |= I_WILL_FREE;
 		spin_unlock(&inode_lock);
-		return;
+		/*
+		 * write_inode_now is a noop as we set BDI_CAP_NO_WRITEBACK
+		 * in our backing_dev_info.
+		 */
+		write_inode_now(inode, 1);
+		spin_lock(&inode_lock);
+		inode->i_state &= ~I_WILL_FREE;
+		inodes_stat.nr_unused--;
+		hlist_del_init(&inode->i_hash);
 	}
-
-	/* write_inode_now() ? */
-	inodes_stat.nr_unused--;
-	hlist_del_init(&inode->i_hash);
-out_truncate:
 	list_del_init(&inode->i_list);
 	list_del_init(&inode->i_sb_list);
 	inode->i_state |= I_FREEING;
@@ -277,13 +300,6 @@
 	spin_unlock(&inode_lock);
 	if (inode->i_data.nrpages)
 		truncate_hugepages(&inode->i_data, 0);
-
-	if (sbinfo->free_inodes >= 0) {
-		spin_lock(&sbinfo->stat_lock);
-		sbinfo->free_inodes++;
-		spin_unlock(&sbinfo->stat_lock);
-	}
-
 	clear_inode(inode);
 	destroy_inode(inode);
 }
@@ -291,7 +307,7 @@
 static void hugetlbfs_drop_inode(struct inode *inode)
 {
 	if (!inode->i_nlink)
-		hugetlbfs_delete_inode(inode);
+		generic_delete_inode(inode);
 	else
 		hugetlbfs_forget_inode(inode);
 }
@@ -308,7 +324,6 @@
 
 	vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) {
 		unsigned long h_vm_pgoff;
-		unsigned long v_length;
 		unsigned long v_offset;
 
 		h_vm_pgoff = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT);
@@ -319,11 +334,8 @@
 		if (h_vm_pgoff >= h_pgoff)
 			v_offset = 0;
 
-		v_length = vma->vm_end - vma->vm_start;
-
-		zap_hugepage_range(vma,
-				vma->vm_start + v_offset,
-				v_length - v_offset);
+		unmap_hugepage_range(vma,
+				vma->vm_start + v_offset, vma->vm_end);
 	}
 }
 
@@ -379,17 +391,6 @@
 					gid_t gid, int mode, dev_t dev)
 {
 	struct inode *inode;
-	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb);
-
-	if (sbinfo->free_inodes >= 0) {
-		spin_lock(&sbinfo->stat_lock);
-		if (!sbinfo->free_inodes) {
-			spin_unlock(&sbinfo->stat_lock);
-			return NULL;
-		}
-		sbinfo->free_inodes--;
-		spin_unlock(&sbinfo->stat_lock);
-	}
 
 	inode = new_inode(sb);
 	if (inode) {
@@ -531,29 +532,51 @@
 	}
 }
 
+static inline int hugetlbfs_dec_free_inodes(struct hugetlbfs_sb_info *sbinfo)
+{
+	if (sbinfo->free_inodes >= 0) {
+		spin_lock(&sbinfo->stat_lock);
+		if (unlikely(!sbinfo->free_inodes)) {
+			spin_unlock(&sbinfo->stat_lock);
+			return 0;
+		}
+		sbinfo->free_inodes--;
+		spin_unlock(&sbinfo->stat_lock);
+	}
+
+	return 1;
+}
+
+static void hugetlbfs_inc_free_inodes(struct hugetlbfs_sb_info *sbinfo)
+{
+	if (sbinfo->free_inodes >= 0) {
+		spin_lock(&sbinfo->stat_lock);
+		sbinfo->free_inodes++;
+		spin_unlock(&sbinfo->stat_lock);
+	}
+}
+
+
 static kmem_cache_t *hugetlbfs_inode_cachep;
 
 static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
 {
+	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb);
 	struct hugetlbfs_inode_info *p;
 
-	p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL);
-	if (!p)
+	if (unlikely(!hugetlbfs_dec_free_inodes(sbinfo)))
 		return NULL;
+	p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL);
+	if (unlikely(!p)) {
+		hugetlbfs_inc_free_inodes(sbinfo);
+		return NULL;
+	}
 	return &p->vfs_inode;
 }
 
-static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
-{
-	struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;
-
-	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-	    SLAB_CTOR_CONSTRUCTOR)
-		inode_init_once(&ei->vfs_inode);
-}
-
 static void hugetlbfs_destroy_inode(struct inode *inode)
 {
+	hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb));
 	mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy);
 	kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));
 }
@@ -565,6 +588,16 @@
 	.set_page_dirty	= hugetlbfs_set_page_dirty,
 };
 
+
+static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
+{
+	struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+
 struct file_operations hugetlbfs_file_operations = {
 	.mmap			= hugetlbfs_file_mmap,
 	.fsync			= simple_sync_file,
@@ -592,6 +625,7 @@
 	.alloc_inode    = hugetlbfs_alloc_inode,
 	.destroy_inode  = hugetlbfs_destroy_inode,
 	.statfs		= hugetlbfs_statfs,
+	.delete_inode	= hugetlbfs_delete_inode,
 	.drop_inode	= hugetlbfs_drop_inode,
 	.put_super	= hugetlbfs_put_super,
 };
diff --git a/fs/inode.c b/fs/inode.c
index f80a79f..d8d04bd 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -475,7 +475,7 @@
  * This function is passed the number of inodes to scan, and it returns the
  * total number of remaining possibly-reclaimable inodes.
  */
-static int shrink_icache_memory(int nr, unsigned int gfp_mask)
+static int shrink_icache_memory(int nr, gfp_t gfp_mask)
 {
 	if (nr) {
 		/*
@@ -1088,6 +1088,7 @@
 	if (inode->i_data.nrpages)
 		truncate_inode_pages(&inode->i_data, 0);
 	clear_inode(inode);
+	wake_up_inode(inode);
 	destroy_inode(inode);
 }
 
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 7ae2c4f..e4b516a 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -1606,7 +1606,7 @@
  * Simple support for retrying memory allocations.  Introduced to help to
  * debug different VM deadlock avoidance strategies. 
  */
-void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry)
+void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
 {
 	return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0));
 }
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 49bbc2b..13cb05b 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1621,7 +1621,7 @@
  * while the data is part of a transaction.  Yes?
  */
 int journal_try_to_free_buffers(journal_t *journal, 
-				struct page *page, int unused_gfp_mask)
+				struct page *page, gfp_t unused_gfp_mask)
 {
 	struct buffer_head *head;
 	struct buffer_head *bh;
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 0f22438..8210ac1 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -15,6 +15,7 @@
 #include <linux/jffs2.h>
 #include <linux/mtd/mtd.h>
 #include <linux/completion.h>
+#include <linux/sched.h>
 #include "nodelist.h"
 
 
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 996d922..316133c 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -18,6 +18,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/crc32.h>
 #include <linux/mtd/nand.h>
+#include <linux/jiffies.h>
+
 #include "nodelist.h"
 
 /* For testing write failures */
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index eadf319..68000a5 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -74,7 +74,7 @@
 static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
 			int nblocks);
 static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval);
-static void dbBackSplit(dmtree_t * tp, int leafno);
+static int dbBackSplit(dmtree_t * tp, int leafno);
 static int dbJoin(dmtree_t * tp, int leafno, int newval);
 static void dbAdjTree(dmtree_t * tp, int leafno, int newval);
 static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc,
@@ -305,7 +305,6 @@
 	filemap_fdatawrite(ipbmap->i_mapping);
 	filemap_fdatawait(ipbmap->i_mapping);
 
-	ipbmap->i_state |= I_DIRTY;
 	diWriteSpecial(ipbmap, 0);
 
 	return (0);
@@ -2467,7 +2466,9 @@
 		 * that it is at the front of a binary buddy system.
 		 */
 		if (oldval == NOFREE) {
-			dbBackSplit((dmtree_t *) dcp, leafno);
+			rc = dbBackSplit((dmtree_t *) dcp, leafno);
+			if (rc)
+				return rc;
 			oldval = dcp->stree[ti];
 		}
 		dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval);
@@ -2627,7 +2628,7 @@
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
-static void dbBackSplit(dmtree_t * tp, int leafno)
+static int dbBackSplit(dmtree_t * tp, int leafno)
 {
 	int budsz, bud, w, bsz, size;
 	int cursz;
@@ -2662,7 +2663,10 @@
 		 */
 		for (w = leafno, bsz = budsz;; bsz <<= 1,
 		     w = (w < bud) ? w : bud) {
-			assert(bsz < le32_to_cpu(tp->dmt_nleafs));
+			if (bsz >= le32_to_cpu(tp->dmt_nleafs)) {
+				jfs_err("JFS: block map error in dbBackSplit");
+				return -EIO;
+			}
 
 			/* determine the buddy.
 			 */
@@ -2681,7 +2685,11 @@
 		}
 	}
 
-	assert(leaf[leafno] == size);
+	if (leaf[leafno] != size) {
+		jfs_err("JFS: wrong leaf value in dbBackSplit");
+		return -EIO;
+	}
+	return 0;
 }
 
 
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 4021d46..28201b1 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -57,6 +57,12 @@
 #include "jfs_debug.h"
 
 /*
+ * __mark_inode_dirty expects inodes to be hashed.  Since we don't want
+ * special inodes in the fileset inode space, we hash them to a dummy head
+ */
+static HLIST_HEAD(aggregate_hash);
+
+/*
  * imap locks
  */
 /* iag free list lock */
@@ -491,6 +497,8 @@
 	/* release the page */
 	release_metapage(mp);
 
+	hlist_add_head(&ip->i_hash, &aggregate_hash);
+
 	return (ip);
 }
 
@@ -514,8 +522,6 @@
 	ino_t inum = ip->i_ino;
 	struct metapage *mp;
 
-	ip->i_state &= ~I_DIRTY;
-
 	if (secondary)
 		address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage;
 	else
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 13d7e3f..8a53981 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -86,7 +86,7 @@
 	atomic_t io_count;
 	struct metapage *mp[MPS_PER_PAGE];
 };
-#define mp_anchor(page) ((struct meta_anchor *)page->private)
+#define mp_anchor(page) ((struct meta_anchor *)page_private(page))
 
 static inline struct metapage *page_to_mp(struct page *page, uint offset)
 {
@@ -108,7 +108,7 @@
 		if (!a)
 			return -ENOMEM;
 		memset(a, 0, sizeof(struct meta_anchor));
-		page->private = (unsigned long)a;
+		set_page_private(page, (unsigned long)a);
 		SetPagePrivate(page);
 		kmap(page);
 	}
@@ -136,7 +136,7 @@
 	a->mp[index] = NULL;
 	if (--a->mp_count == 0) {
 		kfree(a);
-		page->private = 0;
+		set_page_private(page, 0);
 		ClearPagePrivate(page);
 		kunmap(page);
 	}
@@ -156,13 +156,13 @@
 #else
 static inline struct metapage *page_to_mp(struct page *page, uint offset)
 {
-	return PagePrivate(page) ? (struct metapage *)page->private : NULL;
+	return PagePrivate(page) ? (struct metapage *)page_private(page) : NULL;
 }
 
 static inline int insert_metapage(struct page *page, struct metapage *mp)
 {
 	if (mp) {
-		page->private = (unsigned long)mp;
+		set_page_private(page, (unsigned long)mp);
 		SetPagePrivate(page);
 		kmap(page);
 	}
@@ -171,7 +171,7 @@
 
 static inline void remove_metapage(struct page *page, struct metapage *mp)
 {
-	page->private = 0;
+	set_page_private(page, 0);
 	ClearPagePrivate(page);
 	kunmap(page);
 }
@@ -198,7 +198,7 @@
 	}
 }
 
-static inline struct metapage *alloc_metapage(unsigned int gfp_mask)
+static inline struct metapage *alloc_metapage(gfp_t gfp_mask)
 {
 	return mempool_alloc(metapage_mempool, gfp_mask);
 }
@@ -395,6 +395,12 @@
 
 		if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) {
 			redirty = 1;
+			/*
+			 * Make sure this page isn't blocked indefinitely.
+			 * If the journal isn't undergoing I/O, push it
+			 */
+			if (mp->log && !(mp->log->cflag & logGC_PAGEOUT))
+				jfs_flush_journal(mp->log, 0);
 			continue;
 		}
 
@@ -534,7 +540,7 @@
 	return -EIO;
 }
 
-static int metapage_releasepage(struct page *page, int gfp_mask)
+static int metapage_releasepage(struct page *page, gfp_t gfp_mask)
 {
 	struct metapage *mp;
 	int busy = 0;
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 9b71ed2..b660c93 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -2396,7 +2396,6 @@
 	 */
 	if (tblk->xflag & COMMIT_CREATE) {
 		diUpdatePMap(ipimap, tblk->ino, FALSE, tblk);
-		ipimap->i_state |= I_DIRTY;
 		/* update persistent block allocation map
 		 * for the allocation of inode extent;
 		 */
@@ -2407,7 +2406,6 @@
 	} else if (tblk->xflag & COMMIT_DELETE) {
 		ip = tblk->u.ip;
 		diUpdatePMap(ipimap, ip->i_ino, TRUE, tblk);
-		ipimap->i_state |= I_DIRTY;
 		iput(ip);
 	}
 }
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index a7fe2f2..e72f4eb 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -3516,16 +3516,10 @@
 	/* process entries backward from last index */
 	index = le16_to_cpu(p->header.nextindex) - 1;
 
-	if (p->header.flag & BT_INTERNAL)
-		goto getChild;
 
-	/*
-	 *      leaf page
-	 */
-
-	/* Since this is the rightmost leaf, and we may have already freed
-	 * a page that was formerly to the right, let's make sure that the
-	 * next pointer is zero.
+	/* Since this is the rightmost page at this level, and we may have
+	 * already freed a page that was formerly to the right, let's make
+	 * sure that the next pointer is zero.
 	 */
 	if (p->header.next) {
 		if (log)
@@ -3539,6 +3533,12 @@
 		p->header.next = 0;
 	}
 
+	if (p->header.flag & BT_INTERNAL)
+		goto getChild;
+
+	/*
+	 *      leaf page
+	 */
 	freed = 0;
 
 	/* does region covered by leaf page precede Teof ? */
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 71bc34b..4226af3 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -442,6 +442,7 @@
 	inode->i_nlink = 1;
 	inode->i_size = sb->s_bdev->bd_inode->i_size;
 	inode->i_mapping->a_ops = &jfs_metapage_aops;
+	insert_inode_hash(inode);
 	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
 
 	sbi->direct_inode = inode;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 82c77df..c4c8601 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -173,11 +173,10 @@
 
 	/* If we've already created an RPC client, check whether
 	 * RPC rebind is required
-	 * Note: why keep rebinding if we're on a tcp connection?
 	 */
 	if ((clnt = host->h_rpcclnt) != NULL) {
 		xprt = clnt->cl_xprt;
-		if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) {
+		if (time_after_eq(jiffies, host->h_nextrebind)) {
 			clnt->cl_port = 0;
 			host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 			dprintk("lockd: next rebind in %ld jiffies\n",
@@ -189,7 +188,6 @@
 			goto forgetit;
 
 		xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
-		xprt->nocong = 1;	/* No congestion control for NLM */
 		xprt->resvport = 1;	/* NLM requires a reserved port */
 
 		/* Existing NLM servers accept AUTH_UNIX only */
diff --git a/fs/locks.c b/fs/locks.c
index f7daa5f..a1e8b22 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -316,21 +316,22 @@
 	/* POSIX-1996 leaves the case l->l_len < 0 undefined;
 	   POSIX-2001 defines it. */
 	start += l->l_start;
-	end = start + l->l_len - 1;
-	if (l->l_len < 0) {
-		end = start - 1;
-		start += l->l_len;
-	}
-
 	if (start < 0)
 		return -EINVAL;
-	if (l->l_len > 0 && end < 0)
-		return -EOVERFLOW;
-
+	fl->fl_end = OFFSET_MAX;
+	if (l->l_len > 0) {
+		end = start + l->l_len - 1;
+		fl->fl_end = end;
+	} else if (l->l_len < 0) {
+		end = start - 1;
+		fl->fl_end = end;
+		start += l->l_len;
+		if (start < 0)
+			return -EINVAL;
+	}
 	fl->fl_start = start;	/* we record the absolute position */
-	fl->fl_end = end;
-	if (l->l_len == 0)
-		fl->fl_end = OFFSET_MAX;
+	if (fl->fl_end < fl->fl_start)
+		return -EOVERFLOW;
 	
 	fl->fl_owner = current->files;
 	fl->fl_pid = current->tgid;
@@ -362,14 +363,21 @@
 		return -EINVAL;
 	}
 
-	if (((start += l->l_start) < 0) || (l->l_len < 0))
+	start += l->l_start;
+	if (start < 0)
 		return -EINVAL;
-	fl->fl_end = start + l->l_len - 1;
-	if (l->l_len > 0 && fl->fl_end < 0)
-		return -EOVERFLOW;
+	fl->fl_end = OFFSET_MAX;
+	if (l->l_len > 0) {
+		fl->fl_end = start + l->l_len - 1;
+	} else if (l->l_len < 0) {
+		fl->fl_end = start - 1;
+		start += l->l_len;
+		if (start < 0)
+			return -EINVAL;
+	}
 	fl->fl_start = start;	/* we record the absolute position */
-	if (l->l_len == 0)
-		fl->fl_end = OFFSET_MAX;
+	if (fl->fl_end < fl->fl_start)
+		return -EOVERFLOW;
 	
 	fl->fl_owner = current->files;
 	fl->fl_pid = current->tgid;
@@ -829,12 +837,16 @@
 		/* Detect adjacent or overlapping regions (if same lock type)
 		 */
 		if (request->fl_type == fl->fl_type) {
+			/* In all comparisons of start vs end, use
+			 * "start - 1" rather than "end + 1". If end
+			 * is OFFSET_MAX, end + 1 will become negative.
+			 */
 			if (fl->fl_end < request->fl_start - 1)
 				goto next_lock;
 			/* If the next lock in the list has entirely bigger
 			 * addresses than the new one, insert the lock here.
 			 */
-			if (fl->fl_start > request->fl_end + 1)
+			if (fl->fl_start - 1 > request->fl_end)
 				break;
 
 			/* If we come here, the new and old lock are of the
diff --git a/fs/mbcache.c b/fs/mbcache.c
index b002a08..298997f 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -116,7 +116,7 @@
  * What the mbcache registers as to get shrunk dynamically.
  */
 
-static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask);
+static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask);
 
 
 static inline int
@@ -140,7 +140,7 @@
 
 
 static inline void
-__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
+__mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
 {
 	struct mb_cache *cache = ce->e_cache;
 
@@ -193,7 +193,7 @@
  * Returns the number of objects which are present in the cache.
  */
 static int
-mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
+mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask)
 {
 	LIST_HEAD(free_list);
 	struct list_head *l, *ltmp;
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 154f511..626a367 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -454,10 +454,10 @@
 {
 	struct buffer_head *dotdot_bh;
 	struct msdos_dir_entry *dotdot_de;
-	loff_t dotdot_i_pos;
 	struct inode *old_inode, *new_inode;
 	struct fat_slot_info old_sinfo, sinfo;
 	struct timespec ts;
+	loff_t dotdot_i_pos, new_i_pos;
 	int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
 
 	old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
@@ -516,28 +516,24 @@
 	if (new_inode) {
 		if (err)
 			goto out;
-		if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
-			/* WTF??? Cry and fail. */
-			printk(KERN_WARNING "msdos_rename: fs corrupted\n");
-			goto out;
-		}
-
 		if (is_dir) {
 			err = fat_dir_empty(new_inode);
 			if (err)
 				goto out;
 		}
+		new_i_pos = MSDOS_I(new_inode)->i_pos;
 		fat_detach(new_inode);
 	} else {
 		err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
 				      &ts, &sinfo);
 		if (err)
 			goto out;
+		new_i_pos = sinfo.i_pos;
 	}
 	new_dir->i_version++;
 
 	fat_detach(old_inode);
-	fat_attach(old_inode, sinfo.i_pos);
+	fat_attach(old_inode, new_i_pos);
 	if (is_hid)
 		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
 	else
@@ -604,7 +600,7 @@
 	fat_attach(old_inode, old_sinfo.i_pos);
 	MSDOS_I(old_inode)->i_attrs = old_attrs;
 	if (new_inode) {
-		fat_attach(new_inode, sinfo.i_pos);
+		fat_attach(new_inode, new_i_pos);
 		if (corrupt)
 			corrupt |= fat_sync_inode(new_inode);
 	} else {
diff --git a/fs/namei.c b/fs/namei.c
index aa62dbd..c5769c4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -28,6 +28,7 @@
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
+#include <linux/file.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -317,6 +318,18 @@
 	mntput_no_expire(nd->mnt);
 }
 
+/**
+ * release_open_intent - free up open intent resources
+ * @nd: pointer to nameidata
+ */
+void release_open_intent(struct nameidata *nd)
+{
+	if (nd->intent.open.file->f_dentry == NULL)
+		put_filp(nd->intent.open.file);
+	else
+		fput(nd->intent.open.file);
+}
+
 /*
  * Internal lookup() using the new generic dcache.
  * SMP-safe
@@ -750,6 +763,7 @@
 		struct qstr this;
 		unsigned int c;
 
+		nd->flags |= LOOKUP_CONTINUE;
 		err = exec_permission_lite(inode, nd);
 		if (err == -EAGAIN) { 
 			err = permission(inode, MAY_EXEC, nd);
@@ -802,7 +816,6 @@
 			if (err < 0)
 				break;
 		}
-		nd->flags |= LOOKUP_CONTINUE;
 		/* This does the actual lookups.. */
 		err = do_lookup(nd, &this, &next);
 		if (err)
@@ -1052,6 +1065,70 @@
 	return retval;
 }
 
+static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags,
+		struct nameidata *nd, int open_flags, int create_mode)
+{
+	struct file *filp = get_empty_filp();
+	int err;
+
+	if (filp == NULL)
+		return -ENFILE;
+	nd->intent.open.file = filp;
+	nd->intent.open.flags = open_flags;
+	nd->intent.open.create_mode = create_mode;
+	err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd);
+	if (IS_ERR(nd->intent.open.file)) {
+		if (err == 0) {
+			err = PTR_ERR(nd->intent.open.file);
+			path_release(nd);
+		}
+	} else if (err != 0)
+		release_open_intent(nd);
+	return err;
+}
+
+/**
+ * path_lookup_open - lookup a file path with open intent
+ * @name: pointer to file name
+ * @lookup_flags: lookup intent flags
+ * @nd: pointer to nameidata
+ * @open_flags: open intent flags
+ */
+int path_lookup_open(const char *name, unsigned int lookup_flags,
+		struct nameidata *nd, int open_flags)
+{
+	return __path_lookup_intent_open(name, lookup_flags, nd,
+			open_flags, 0);
+}
+
+/**
+ * path_lookup_create - lookup a file path with open + create intent
+ * @name: pointer to file name
+ * @lookup_flags: lookup intent flags
+ * @nd: pointer to nameidata
+ * @open_flags: open intent flags
+ * @create_mode: create intent flags
+ */
+int path_lookup_create(const char *name, unsigned int lookup_flags,
+		struct nameidata *nd, int open_flags, int create_mode)
+{
+	return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd,
+			open_flags, create_mode);
+}
+
+int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
+		struct nameidata *nd, int open_flags)
+{
+	char *tmp = getname(name);
+	int err = PTR_ERR(tmp);
+
+	if (!IS_ERR(tmp)) {
+		err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0);
+		putname(tmp);
+	}
+	return err;
+}
+
 /*
  * Restricted form of lookup. Doesn't follow links, single-component only,
  * needs parent already locked. Doesn't follow mounts.
@@ -1234,9 +1311,6 @@
 }
 
 /* 
- * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
- * reasons.
- *
  * O_DIRECTORY translates into forcing a directory lookup.
  */
 static inline int lookup_flags(unsigned int f)
@@ -1246,9 +1320,6 @@
 	if (f & O_NOFOLLOW)
 		retval &= ~LOOKUP_FOLLOW;
 	
-	if ((f & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
-		retval &= ~LOOKUP_FOLLOW;
-	
 	if (f & O_DIRECTORY)
 		retval |= LOOKUP_DIRECTORY;
 
@@ -1416,27 +1487,27 @@
  */
 int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
 {
-	int acc_mode, error = 0;
+	int acc_mode, error;
 	struct path path;
 	struct dentry *dir;
 	int count = 0;
 
 	acc_mode = ACC_MODE(flag);
 
+	/* O_TRUNC implies we need access checks for write permissions */
+	if (flag & O_TRUNC)
+		acc_mode |= MAY_WRITE;
+
 	/* Allow the LSM permission hook to distinguish append 
 	   access from general write access. */
 	if (flag & O_APPEND)
 		acc_mode |= MAY_APPEND;
 
-	/* Fill in the open() intent data */
-	nd->intent.open.flags = flag;
-	nd->intent.open.create_mode = mode;
-
 	/*
 	 * The simplest case - just a plain lookup.
 	 */
 	if (!(flag & O_CREAT)) {
-		error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd);
+		error = path_lookup_open(pathname, lookup_flags(flag), nd, flag);
 		if (error)
 			return error;
 		goto ok;
@@ -1445,7 +1516,7 @@
 	/*
 	 * Create - we need to know the parent.
 	 */
-	error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd);
+	error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode);
 	if (error)
 		return error;
 
@@ -1520,6 +1591,8 @@
 exit_dput:
 	dput_path(&path, nd);
 exit:
+	if (!IS_ERR(nd->intent.open.file))
+		release_open_intent(nd);
 	path_release(nd);
 	return error;
 
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 4a36839..44135af 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -142,7 +142,7 @@
 /*
  * Basic procedure for returning a delegation to the server
  */
-int nfs_inode_return_delegation(struct inode *inode)
+int __nfs_inode_return_delegation(struct inode *inode)
 {
 	struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
 	struct nfs_inode *nfsi = NFS_I(inode);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 3f6c45a..8017846 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -25,7 +25,7 @@
 
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int nfs_inode_return_delegation(struct inode *inode);
+int __nfs_inode_return_delegation(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 
 struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle);
@@ -47,11 +47,25 @@
 		return 1;
 	return 0;
 }
+
+static inline int nfs_inode_return_delegation(struct inode *inode)
+{
+	int err = 0;
+
+	if (NFS_I(inode)->delegation != NULL)
+		err = __nfs_inode_return_delegation(inode);
+	return err;
+}
 #else
 static inline int nfs_have_delegation(struct inode *inode, int flags)
 {
 	return 0;
 }
+
+static inline int nfs_inode_return_delegation(struct inode *inode)
+{
+	return 0;
+}
 #endif
 
 #endif
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 2df639f..8272ed3 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -532,6 +532,7 @@
 	my_entry.eof = 0;
 	my_entry.fh = &fh;
 	my_entry.fattr = &fattr;
+	nfs_fattr_init(&fattr);
 	desc->entry = &my_entry;
 
 	while(!desc->entry->eof) {
@@ -565,8 +566,6 @@
 		}
 	}
 	unlock_kernel();
-	if (desc->error < 0)
-		return desc->error;
 	if (res < 0)
 		return res;
 	return 0;
@@ -803,6 +802,7 @@
  */
 static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 {
+	nfs_inode_return_delegation(inode);
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 		lock_kernel();
 		inode->i_nlink--;
@@ -853,12 +853,6 @@
 	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
 
 	lock_kernel();
-	/* Revalidate parent directory attribute cache */
-	error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
-	if (error < 0) {
-		res = ERR_PTR(error);
-		goto out_unlock;
-	}
 
 	/* If we're doing an exclusive create, optimize away the lookup */
 	if (nfs_is_exclusive_create(dir, nd))
@@ -916,7 +910,6 @@
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct dentry *res = NULL;
-	struct inode *inode = NULL;
 	int error;
 
 	/* Check that we are indeed trying to open this file */
@@ -930,8 +923,10 @@
 	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
 
 	/* Let vfs_create() deal with O_EXCL */
-	if (nd->intent.open.flags & O_EXCL)
-		goto no_entry;
+	if (nd->intent.open.flags & O_EXCL) {
+		d_add(dentry, NULL);
+		goto out;
+	}
 
 	/* Open the file on the server */
 	lock_kernel();
@@ -945,32 +940,30 @@
 
 	if (nd->intent.open.flags & O_CREAT) {
 		nfs_begin_data_update(dir);
-		inode = nfs4_atomic_open(dir, dentry, nd);
+		res = nfs4_atomic_open(dir, dentry, nd);
 		nfs_end_data_update(dir);
 	} else
-		inode = nfs4_atomic_open(dir, dentry, nd);
+		res = nfs4_atomic_open(dir, dentry, nd);
 	unlock_kernel();
-	if (IS_ERR(inode)) {
-		error = PTR_ERR(inode);
+	if (IS_ERR(res)) {
+		error = PTR_ERR(res);
 		switch (error) {
 			/* Make a negative dentry */
 			case -ENOENT:
-				inode = NULL;
-				break;
+				res = NULL;
+				goto out;
 			/* This turned out not to be a regular file */
+			case -EISDIR:
+			case -ENOTDIR:
+				goto no_open;
 			case -ELOOP:
 				if (!(nd->intent.open.flags & O_NOFOLLOW))
 					goto no_open;
-			/* case -EISDIR: */
 			/* case -EINVAL: */
 			default:
-				res = ERR_PTR(error);
 				goto out;
 		}
-	}
-no_entry:
-	res = d_add_unique(dentry, inode);
-	if (res != NULL)
+	} else if (res != NULL)
 		dentry = res;
 	nfs_renew_times(dentry);
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -1014,7 +1007,7 @@
 	 */
 	lock_kernel();
 	verifier = nfs_save_change_attribute(dir);
-	ret = nfs4_open_revalidate(dir, dentry, openflags);
+	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
 	if (!ret)
 		nfs_set_verifier(dentry, verifier);
 	unlock_kernel();
@@ -1137,7 +1130,7 @@
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
 	nfs_end_data_update(dir);
 	if (error != 0)
 		goto out_err;
@@ -1332,6 +1325,7 @@
 
 	nfs_begin_data_update(dir);
 	if (inode != NULL) {
+		nfs_inode_return_delegation(inode);
 		nfs_begin_data_update(inode);
 		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
 		/* The VFS may want to delete this inode */
@@ -1438,17 +1432,14 @@
 		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	/*
-	 * Drop the dentry in advance to force a new lookup.
-	 * Since nfs_proc_link doesn't return a file handle,
-	 * we can't use the existing dentry.
-	 */
 	lock_kernel();
-	d_drop(dentry);
-
 	nfs_begin_data_update(dir);
 	nfs_begin_data_update(inode);
 	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
+	if (error == 0) {
+		atomic_inc(&inode->i_count);
+		d_instantiate(dentry, inode);
+	}
 	nfs_end_data_update(inode);
 	nfs_end_data_update(dir);
 	unlock_kernel();
@@ -1512,9 +1503,11 @@
 	 */
 	if (!new_inode)
 		goto go_ahead;
-	if (S_ISDIR(new_inode->i_mode))
-		goto out;
-	else if (atomic_read(&new_dentry->d_count) > 2) {
+	if (S_ISDIR(new_inode->i_mode)) {
+		error = -EISDIR;
+		if (!S_ISDIR(old_inode->i_mode))
+			goto out;
+	} else if (atomic_read(&new_dentry->d_count) > 2) {
 		int err;
 		/* copy the target dentry's name */
 		dentry = d_alloc(new_dentry->d_parent,
@@ -1539,7 +1532,8 @@
 #endif
 			goto out;
 		}
-	}
+	} else
+		new_inode->i_nlink--;
 
 go_ahead:
 	/*
@@ -1549,6 +1543,7 @@
 		nfs_wb_all(old_inode);
 		shrink_dcache_parent(old_dentry);
 	}
+	nfs_inode_return_delegation(old_inode);
 
 	if (new_inode)
 		d_delete(new_dentry);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 6bdcfa9..57d3e77 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -205,8 +205,8 @@
 	if (!status) {
 		status = ctx->error;
 		ctx->error = 0;
-		if (!status && !nfs_have_delegation(inode, FMODE_READ))
-			__nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		if (!status)
+			nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	}
 	unlock_kernel();
 	return status;
@@ -376,22 +376,31 @@
 
 static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
 {
+	struct file_lock *cfl;
 	struct inode *inode = filp->f_mapping->host;
 	int status = 0;
 
 	lock_kernel();
-	/* Use local locking if mounted with "-onolock" */
-	if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
-		status = NFS_PROTO(inode)->lock(filp, cmd, fl);
-	else {
-		struct file_lock *cfl = posix_test_lock(filp, fl);
-
-		fl->fl_type = F_UNLCK;
-		if (cfl != NULL)
-			memcpy(fl, cfl, sizeof(*fl));
+	/* Try local locking first */
+	cfl = posix_test_lock(filp, fl);
+	if (cfl != NULL) {
+		locks_copy_lock(fl, cfl);
+		goto out;
 	}
+
+	if (nfs_have_delegation(inode, FMODE_READ))
+		goto out_noconflict;
+
+	if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)
+		goto out_noconflict;
+
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+out:
 	unlock_kernel();
 	return status;
+out_noconflict:
+	fl->fl_type = F_UNLCK;
+	goto out;
 }
 
 static int do_vfs_lock(struct file *file, struct file_lock *fl)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d4eadee..fc0f12b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -358,6 +358,35 @@
 	return no_root_error;
 }
 
+static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
+{
+	to->to_initval = timeo * HZ / 10;
+	to->to_retries = retrans;
+	if (!to->to_retries)
+		to->to_retries = 2;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		if (!to->to_initval)
+			to->to_initval = 60 * HZ;
+		if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
+			to->to_initval = NFS_MAX_TCP_TIMEOUT;
+		to->to_increment = to->to_initval;
+		to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
+		to->to_exponential = 0;
+		break;
+	case IPPROTO_UDP:
+	default:
+		if (!to->to_initval)
+			to->to_initval = 11 * HZ / 10;
+		if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
+			to->to_initval = NFS_MAX_UDP_TIMEOUT;
+		to->to_maxval = NFS_MAX_UDP_TIMEOUT;
+		to->to_exponential = 1;
+		break;
+	}
+}
+
 /*
  * Create an RPC client handle.
  */
@@ -367,22 +396,12 @@
 	struct rpc_timeout	timeparms;
 	struct rpc_xprt		*xprt = NULL;
 	struct rpc_clnt		*clnt = NULL;
-	int			tcp   = (data->flags & NFS_MOUNT_TCP);
+	int			proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
 
-	/* Initialize timeout values */
-	timeparms.to_initval = data->timeo * HZ / 10;
-	timeparms.to_retries = data->retrans;
-	timeparms.to_maxval  = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
-	timeparms.to_exponential = 1;
-
-	if (!timeparms.to_initval)
-		timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
-	if (!timeparms.to_retries)
-		timeparms.to_retries = 5;
+	nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
 
 	/* create transport and client */
-	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
-				 &server->addr, &timeparms);
+	xprt = xprt_create_proto(proto, &server->addr, &timeparms);
 	if (IS_ERR(xprt)) {
 		dprintk("%s: cannot create RPC transport. Error = %ld\n",
 				__FUNCTION__, PTR_ERR(xprt));
@@ -576,7 +595,6 @@
 		{ NFS_MOUNT_SOFT, ",soft", ",hard" },
 		{ NFS_MOUNT_INTR, ",intr", "" },
 		{ NFS_MOUNT_POSIX, ",posix", "" },
-		{ NFS_MOUNT_TCP, ",tcp", ",udp" },
 		{ NFS_MOUNT_NOCTO, ",nocto", "" },
 		{ NFS_MOUNT_NOAC, ",noac", "" },
 		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
@@ -585,6 +603,8 @@
 	};
 	struct proc_nfs_info *nfs_infop;
 	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+	char buf[12];
+	char *proto;
 
 	seq_printf(m, ",v%d", nfss->rpc_ops->version);
 	seq_printf(m, ",rsize=%d", nfss->rsize);
@@ -603,6 +623,18 @@
 		else
 			seq_puts(m, nfs_infop->nostr);
 	}
+	switch (nfss->client->cl_xprt->prot) {
+		case IPPROTO_TCP:
+			proto = "tcp";
+			break;
+		case IPPROTO_UDP:
+			proto = "udp";
+			break;
+		default:
+			snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
+			proto = buf;
+	}
+	seq_printf(m, ",proto=%s", proto);
 	seq_puts(m, ",addr=");
 	seq_escape(m, nfss->hostname, " \t\n\\");
 	return 0;
@@ -753,7 +785,8 @@
 		else
 			init_special_inode(inode, inode->i_mode, fattr->rdev);
 
-		nfsi->read_cache_jiffies = fattr->timestamp;
+		nfsi->read_cache_jiffies = fattr->time_start;
+		nfsi->last_updated = jiffies;
 		inode->i_atime = fattr->atime;
 		inode->i_mtime = fattr->mtime;
 		inode->i_ctime = fattr->ctime;
@@ -821,6 +854,11 @@
 			filemap_fdatawait(inode->i_mapping);
 		nfs_wb_all(inode);
 	}
+	/*
+	 * Return any delegations if we're going to change ACLs
+	 */
+	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
+		nfs_inode_return_delegation(inode);
 	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
 	if (error == 0)
 		nfs_refresh_inode(inode, &fattr);
@@ -1019,15 +1057,11 @@
 	ctx->mode = filp->f_mode;
 	nfs_file_set_open_context(filp, ctx);
 	put_nfs_open_context(ctx);
-	if ((filp->f_mode & FMODE_WRITE) != 0)
-		nfs_begin_data_update(inode);
 	return 0;
 }
 
 int nfs_release(struct inode *inode, struct file *filp)
 {
-	if ((filp->f_mode & FMODE_WRITE) != 0)
-		nfs_end_data_update(inode);
 	nfs_file_clear_open_context(filp);
 	return 0;
 }
@@ -1083,14 +1117,15 @@
 		goto out;
 	}
 
+	spin_lock(&inode->i_lock);
 	status = nfs_update_inode(inode, &fattr, verifier);
 	if (status) {
+		spin_unlock(&inode->i_lock);
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
 			 inode->i_sb->s_id,
 			 (long long)NFS_FILEID(inode), status);
 		goto out;
 	}
-	spin_lock(&inode->i_lock);
 	cache_validity = nfsi->cache_validity;
 	nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
 
@@ -1098,7 +1133,7 @@
 	 * We may need to keep the attributes marked as invalid if
 	 * we raced with nfs_end_attr_update().
 	 */
-	if (verifier == nfsi->cache_change_attribute)
+	if (time_after_eq(verifier, nfsi->cache_change_attribute))
 		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
 	spin_unlock(&inode->i_lock);
 
@@ -1165,7 +1200,7 @@
 		if (S_ISDIR(inode->i_mode)) {
 			memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
 			/* This ensures we revalidate child dentries */
-			nfsi->cache_change_attribute++;
+			nfsi->cache_change_attribute = jiffies;
 		}
 		spin_unlock(&inode->i_lock);
 
@@ -1197,20 +1232,19 @@
 	struct nfs_inode *nfsi = NFS_I(inode);
 
 	if (!nfs_have_delegation(inode, FMODE_READ)) {
-		/* Mark the attribute cache for revalidation */
-		spin_lock(&inode->i_lock);
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
-		/* Directories and symlinks: invalidate page cache too */
-		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+		/* Directories and symlinks: invalidate page cache */
+		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
+			spin_lock(&inode->i_lock);
 			nfsi->cache_validity |= NFS_INO_INVALID_DATA;
-		spin_unlock(&inode->i_lock);
+			spin_unlock(&inode->i_lock);
+		}
 	}
-	nfsi->cache_change_attribute ++;
+	nfsi->cache_change_attribute = jiffies;
 	atomic_dec(&nfsi->data_updates);
 }
 
 /**
- * nfs_refresh_inode - verify consistency of the inode attribute cache
+ * nfs_check_inode_attributes - verify consistency of the inode attribute cache
  * @inode - pointer to inode
  * @fattr - updated attributes
  *
@@ -1218,13 +1252,12 @@
  * so that fattr carries weak cache consistency data, then it may
  * also update the ctime/mtime/change_attribute.
  */
-int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	loff_t cur_size, new_isize;
 	int data_unstable;
 
-	spin_lock(&inode->i_lock);
 
 	/* Are we in the process of updating data on the server? */
 	data_unstable = nfs_caches_unstable(inode);
@@ -1241,14 +1274,12 @@
 	}
 
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0) {
-		spin_unlock(&inode->i_lock);
 		return 0;
 	}
 
 	/* Has the inode gone and changed behind our back? */
 	if (nfsi->fileid != fattr->fileid
 			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
-		spin_unlock(&inode->i_lock);
 		return -EIO;
 	}
 
@@ -1288,11 +1319,67 @@
 	if (!timespec_equal(&inode->i_atime, &fattr->atime))
 		nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
 
-	nfsi->read_cache_jiffies = fattr->timestamp;
-	spin_unlock(&inode->i_lock);
+	nfsi->read_cache_jiffies = fattr->time_start;
 	return 0;
 }
 
+/**
+ * nfs_refresh_inode - try to update the inode attribute cache
+ * @inode - pointer to inode
+ * @fattr - updated attributes
+ *
+ * Check that an RPC call that returned attributes has not overlapped with
+ * other recent updates of the inode metadata, then decide whether it is
+ * safe to do a full update of the inode attributes, or whether just to
+ * call nfs_check_inode_attributes.
+ */
+int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int status;
+
+	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+		return 0;
+	spin_lock(&inode->i_lock);
+	nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
+	if (nfs_verify_change_attribute(inode, fattr->time_start))
+		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+	if (time_after(fattr->time_start, nfsi->last_updated))
+		status = nfs_update_inode(inode, fattr, fattr->time_start);
+	else
+		status = nfs_check_inode_attributes(inode, fattr);
+
+	spin_unlock(&inode->i_lock);
+	return status;
+}
+
+/**
+ * nfs_post_op_update_inode - try to update the inode attribute cache
+ * @inode - pointer to inode
+ * @fattr - updated attributes
+ *
+ * After an operation that has changed the inode metadata, mark the
+ * attribute cache as being invalid, then try to update it.
+ */
+int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int status = 0;
+
+	spin_lock(&inode->i_lock);
+	if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) {
+		nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+		goto out;
+	}
+	status = nfs_update_inode(inode, fattr, fattr->time_start);
+	if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute))
+		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
+	nfsi->cache_change_attribute = jiffies;
+out:
+	spin_unlock(&inode->i_lock);
+	return status;
+}
+
 /*
  * Many nfs protocol calls return the new file attributes after
  * an operation.  Here we update the inode to reflect the state
@@ -1328,20 +1415,17 @@
 		goto out_err;
 	}
 
-	spin_lock(&inode->i_lock);
-
 	/*
 	 * Make sure the inode's type hasn't changed.
 	 */
-	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
-		spin_unlock(&inode->i_lock);
+	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 		goto out_changed;
-	}
 
 	/*
 	 * Update the read time so we don't revalidate too often.
 	 */
-	nfsi->read_cache_jiffies = fattr->timestamp;
+	nfsi->read_cache_jiffies = fattr->time_start;
+	nfsi->last_updated = jiffies;
 
 	/* Are we racing with known updates of the metadata on the server? */
 	data_unstable = ! (nfs_verify_change_attribute(inode, verifier) ||
@@ -1354,7 +1438,7 @@
 		/* Do we perhaps have any outstanding writes? */
 		if (nfsi->npages == 0) {
 			/* No, but did we race with nfs_end_data_update()? */
-			if (verifier  ==  nfsi->cache_change_attribute) {
+			if (time_after_eq(verifier,  nfsi->cache_change_attribute)) {
 				inode->i_size = new_isize;
 				invalid |= NFS_INO_INVALID_DATA;
 			}
@@ -1430,7 +1514,6 @@
 	if (!nfs_have_delegation(inode, FMODE_READ))
 		nfsi->cache_validity |= invalid;
 
-	spin_unlock(&inode->i_lock);
 	return 0;
  out_changed:
 	/*
@@ -1639,8 +1722,7 @@
 	struct nfs_inode *nfsi = NFS_I(inode);
 
 	/* If we are holding a delegation, return it! */
-	if (nfsi->delegation != NULL)
-		nfs_inode_return_delegation(inode);
+	nfs_inode_return_delegation(inode);
 	/* First call standard NFS clear_inode() code */
 	nfs_clear_inode(inode);
 	/* Now clear out any remaining state */
@@ -1669,7 +1751,7 @@
 	struct rpc_clnt *clnt = NULL;
 	struct rpc_timeout timeparms;
 	rpc_authflavor_t authflavour;
-	int proto, err = -EIO;
+	int err = -EIO;
 
 	sb->s_blocksize_bits = 0;
 	sb->s_blocksize = 0;
@@ -1687,30 +1769,8 @@
 	server->acdirmax = data->acdirmax*HZ;
 
 	server->rpc_ops = &nfs_v4_clientops;
-	/* Initialize timeout values */
 
-	timeparms.to_initval = data->timeo * HZ / 10;
-	timeparms.to_retries = data->retrans;
-	timeparms.to_exponential = 1;
-	if (!timeparms.to_retries)
-		timeparms.to_retries = 5;
-
-	proto = data->proto;
-	/* Which IP protocol do we use? */
-	switch (proto) {
-	case IPPROTO_TCP:
-		timeparms.to_maxval  = RPC_MAX_TCP_TIMEOUT;
-		if (!timeparms.to_initval)
-			timeparms.to_initval = 600 * HZ / 10;
-		break;
-	case IPPROTO_UDP:
-		timeparms.to_maxval  = RPC_MAX_UDP_TIMEOUT;
-		if (!timeparms.to_initval)
-			timeparms.to_initval = 11 * HZ / 10;
-		break;
-	default:
-		return -EINVAL;
-	}
+	nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
 
 	clp = nfs4_get_client(&server->addr.sin_addr);
 	if (!clp) {
@@ -1735,7 +1795,7 @@
 
 	down_write(&clp->cl_sem);
 	if (IS_ERR(clp->cl_rpcclient)) {
-		xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+		xprt = xprt_create_proto(data->proto, &server->addr, &timeparms);
 		if (IS_ERR(xprt)) {
 			up_write(&clp->cl_sem);
 			err = PTR_ERR(xprt);
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index d91b690..59049e8 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -143,7 +143,6 @@
 		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
 		fattr->rdev = 0;
 	}
-	fattr->timestamp = jiffies;
 	return p;
 }
 
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index edc9551..92c870d 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -78,7 +78,7 @@
 	int	status;
 
 	dprintk("%s: call  fsinfo\n", __FUNCTION__);
-	info->fattr->valid = 0;
+	nfs_fattr_init(info->fattr);
 	status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
 	dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status);
 	if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
@@ -98,7 +98,7 @@
 	int	status;
 
 	dprintk("NFS call  getattr\n");
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call(server->client, NFS3PROC_GETATTR,
 			  fhandle, fattr, 0);
 	dprintk("NFS reply getattr: %d\n", status);
@@ -117,7 +117,7 @@
 	int	status;
 
 	dprintk("NFS call  setattr\n");
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
 	if (status == 0)
 		nfs_setattr_update_inode(inode, sattr);
@@ -143,8 +143,8 @@
 	int			status;
 
 	dprintk("NFS call  lookup %s\n", name->name);
-	dir_attr.valid = 0;
-	fattr->valid = 0;
+	nfs_fattr_init(&dir_attr);
+	nfs_fattr_init(fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
 	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
 		status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
@@ -174,7 +174,6 @@
 	int status;
 
 	dprintk("NFS call  access\n");
-	fattr.valid = 0;
 
 	if (mode & MAY_READ)
 		arg.access |= NFS3_ACCESS_READ;
@@ -189,6 +188,7 @@
 		if (mode & MAY_EXEC)
 			arg.access |= NFS3_ACCESS_EXECUTE;
 	}
+	nfs_fattr_init(&fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	nfs_refresh_inode(inode, &fattr);
 	if (status == 0) {
@@ -217,7 +217,7 @@
 	int			status;
 
 	dprintk("NFS call  readlink\n");
-	fattr.valid = 0;
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
 			  &args, &fattr, 0);
 	nfs_refresh_inode(inode, &fattr);
@@ -240,7 +240,7 @@
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -263,10 +263,10 @@
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
 	if (status >= 0)
-		nfs_refresh_inode(inode, fattr);
+		nfs_post_op_update_inode(inode, fattr);
 	dprintk("NFS reply write: %d\n", status);
 	return status < 0? status : wdata->res.count;
 }
@@ -285,10 +285,10 @@
 
 	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
 			(long long) cdata->args.offset);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	if (status >= 0)
-		nfs_refresh_inode(inode, fattr);
+		nfs_post_op_update_inode(inode, fattr);
 	dprintk("NFS reply commit: %d\n", status);
 	return status;
 }
@@ -299,7 +299,7 @@
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		 int flags)
+		 int flags, struct nameidata *nd)
 {
 	struct nfs_fh		fhandle;
 	struct nfs_fattr	fattr;
@@ -329,10 +329,10 @@
 	sattr->ia_mode &= ~current->fs->umask;
 
 again:
-	dir_attr.valid = 0;
-	fattr.valid = 0;
+	nfs_fattr_init(&dir_attr);
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr);
 
 	/* If the server doesn't support the exclusive creation semantics,
 	 * try again with simple 'guarded' mode. */
@@ -401,9 +401,9 @@
 	int			status;
 
 	dprintk("NFS call  remove %s\n", name->name);
-	dir_attr.valid = 0;
+	nfs_fattr_init(&dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr);
 	dprintk("NFS reply remove: %d\n", status);
 	return status;
 }
@@ -422,7 +422,7 @@
 	ptr->arg.fh = NFS_FH(dir->d_inode);
 	ptr->arg.name = name->name;
 	ptr->arg.len = name->len;
-	ptr->res.valid = 0;
+	nfs_fattr_init(&ptr->res);
 	msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
 	msg->rpc_argp = &ptr->arg;
 	msg->rpc_resp = &ptr->res;
@@ -439,7 +439,7 @@
 		return 1;
 	if (msg->rpc_argp) {
 		dir_attr = (struct nfs_fattr*)msg->rpc_resp;
-		nfs_refresh_inode(dir->d_inode, dir_attr);
+		nfs_post_op_update_inode(dir->d_inode, dir_attr);
 		kfree(msg->rpc_argp);
 	}
 	return 0;
@@ -465,11 +465,11 @@
 	int			status;
 
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
-	old_dir_attr.valid = 0;
-	new_dir_attr.valid = 0;
+	nfs_fattr_init(&old_dir_attr);
+	nfs_fattr_init(&new_dir_attr);
 	status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
-	nfs_refresh_inode(old_dir, &old_dir_attr);
-	nfs_refresh_inode(new_dir, &new_dir_attr);
+	nfs_post_op_update_inode(old_dir, &old_dir_attr);
+	nfs_post_op_update_inode(new_dir, &new_dir_attr);
 	dprintk("NFS reply rename: %d\n", status);
 	return status;
 }
@@ -491,11 +491,11 @@
 	int			status;
 
 	dprintk("NFS call  link %s\n", name->name);
-	dir_attr.valid = 0;
-	fattr.valid = 0;
+	nfs_fattr_init(&dir_attr);
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
-	nfs_refresh_inode(dir, &dir_attr);
-	nfs_refresh_inode(inode, &fattr);
+	nfs_post_op_update_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(inode, &fattr);
 	dprintk("NFS reply link: %d\n", status);
 	return status;
 }
@@ -524,10 +524,10 @@
 	if (path->len > NFS3_MAXPATHLEN)
 		return -ENAMETOOLONG;
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
-	dir_attr.valid = 0;
-	fattr->valid = 0;
+	nfs_fattr_init(&dir_attr);
+	nfs_fattr_init(fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr);
 	dprintk("NFS reply symlink: %d\n", status);
 	return status;
 }
@@ -552,13 +552,13 @@
 	int status;
 
 	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
-	dir_attr.valid = 0;
-	fattr.valid = 0;
 
 	sattr->ia_mode &= ~current->fs->umask;
 
+	nfs_fattr_init(&dir_attr);
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr);
 	if (status != 0)
 		goto out;
 	status = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -582,9 +582,9 @@
 	int			status;
 
 	dprintk("NFS call  rmdir %s\n", name->name);
-	dir_attr.valid = 0;
+	nfs_fattr_init(&dir_attr);
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr);
 	dprintk("NFS reply rmdir: %d\n", status);
 	return status;
 }
@@ -634,7 +634,7 @@
 	dprintk("NFS call  readdir%s %d\n",
 			plus? "plus" : "", (unsigned int) cookie);
 
-	dir_attr.valid = 0;
+	nfs_fattr_init(&dir_attr);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	nfs_refresh_inode(dir, &dir_attr);
 	dprintk("NFS reply readdir: %d\n", status);
@@ -676,10 +676,10 @@
 
 	sattr->ia_mode &= ~current->fs->umask;
 
-	dir_attr.valid = 0;
-	fattr.valid = 0;
+	nfs_fattr_init(&dir_attr);
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
-	nfs_refresh_inode(dir, &dir_attr);
+	nfs_post_op_update_inode(dir, &dir_attr);
 	if (status != 0)
 		goto out;
 	status = nfs_instantiate(dentry, &fh, &fattr);
@@ -698,7 +698,7 @@
 	int	status;
 
 	dprintk("NFS call  fsstat\n");
-	stat->fattr->valid = 0;
+	nfs_fattr_init(stat->fattr);
 	status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0);
 	dprintk("NFS reply statfs: %d\n", status);
 	return status;
@@ -711,7 +711,7 @@
 	int	status;
 
 	dprintk("NFS call  fsinfo\n");
-	info->fattr->valid = 0;
+	nfs_fattr_init(info->fattr);
 	status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
 	dprintk("NFS reply fsinfo: %d\n", status);
 	return status;
@@ -724,7 +724,7 @@
 	int	status;
 
 	dprintk("NFS call  pathconf\n");
-	info->fattr->valid = 0;
+	nfs_fattr_init(info->fattr);
 	status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0);
 	dprintk("NFS reply pathconf: %d\n", status);
 	return status;
@@ -735,7 +735,7 @@
 static void
 nfs3_read_done(struct rpc_task *task)
 {
-	struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+	struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
 
 	if (nfs3_async_handle_jukebox(task))
 		return;
@@ -775,7 +775,7 @@
 		return;
 	data = (struct nfs_write_data *)task->tk_calldata;
 	if (task->tk_status >= 0)
-		nfs_refresh_inode(data->inode, data->res.fattr);
+		nfs_post_op_update_inode(data->inode, data->res.fattr);
 	nfs_writeback_done(task);
 }
 
@@ -819,7 +819,7 @@
 		return;
 	data = (struct nfs_write_data *)task->tk_calldata;
 	if (task->tk_status >= 0)
-		nfs_refresh_inode(data->inode, data->res.fattr);
+		nfs_post_op_update_inode(data->inode, data->res.fattr);
 	nfs_commit_done(task);
 }
 
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index db4a904..0498bd3 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -174,7 +174,6 @@
 
 	/* Update the mode bits */
 	fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
-	fattr->timestamp = jiffies;
 	return p;
 }
 
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ec1a22d..78a53f5 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -93,25 +93,50 @@
 };
 
 /*
+ * struct rpc_sequence ensures that RPC calls are sent in the exact
+ * order that they appear on the list.
+ */
+struct rpc_sequence {
+	struct rpc_wait_queue	wait;	/* RPC call delay queue */
+	spinlock_t lock;		/* Protects the list */
+	struct list_head list;		/* Defines sequence of RPC calls */
+};
+
+#define NFS_SEQID_CONFIRMED 1
+struct nfs_seqid_counter {
+	struct rpc_sequence *sequence;
+	int flags;
+	u32 counter;
+};
+
+struct nfs_seqid {
+	struct nfs_seqid_counter *sequence;
+	struct list_head list;
+};
+
+static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status)
+{
+	if (seqid_mutating_err(-status))
+		seqid->flags |= NFS_SEQID_CONFIRMED;
+}
+
+/*
  * NFS4 state_owners and lock_owners are simply labels for ordered
  * sequences of RPC calls. Their sole purpose is to provide once-only
  * semantics by allowing the server to identify replayed requests.
- *
- * The ->so_sema is held during all state_owner seqid-mutating operations:
- * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize
- * so_seqid.
  */
 struct nfs4_state_owner {
+	spinlock_t	     so_lock;
 	struct list_head     so_list;	 /* per-clientid list of state_owners */
 	struct nfs4_client   *so_client;
 	u32                  so_id;      /* 32-bit identifier, unique */
-	struct semaphore     so_sema;
-	u32                  so_seqid;   /* protected by so_sema */
 	atomic_t	     so_count;
 
 	struct rpc_cred	     *so_cred;	 /* Associated cred */
 	struct list_head     so_states;
 	struct list_head     so_delegations;
+	struct nfs_seqid_counter so_seqid;
+	struct rpc_sequence  so_sequence;
 };
 
 /*
@@ -132,7 +157,7 @@
 	fl_owner_t		ls_owner;	/* POSIX lock owner */
 #define NFS_LOCK_INITIALIZED 1
 	int			ls_flags;
-	u32			ls_seqid;
+	struct nfs_seqid_counter	ls_seqid;
 	u32			ls_id;
 	nfs4_stateid		ls_stateid;
 	atomic_t		ls_count;
@@ -153,7 +178,6 @@
 	struct inode *inode;		/* Pointer to the inode */
 
 	unsigned long flags;		/* Do we hold any locks? */
-	struct semaphore lock_sema;	/* Serializes file locking operations */
 	spinlock_t state_lock;		/* Protects the lock_states list */
 
 	nfs4_stateid stateid;
@@ -191,8 +215,8 @@
 extern int nfs4_proc_async_renew(struct nfs4_client *);
 extern int nfs4_proc_renew(struct nfs4_client *);
 extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
-extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
+extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
+extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 
 extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
 extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
@@ -224,12 +248,17 @@
 extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct nfs4_state *, mode_t);
 extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
-extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
 extern void nfs4_schedule_state_recovery(struct nfs4_client *);
+extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
-extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
 
+extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter);
+extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
+extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid);
+extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid);
+extern void nfs_free_seqid(struct nfs_seqid *seqid);
+
 extern const nfs4_stateid zero_stateid;
 
 /* nfs4xdr.c */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9701ca8..933e13b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -47,6 +47,7 @@
 #include <linux/nfs_page.h>
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
+#include <linux/mount.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
@@ -56,10 +57,11 @@
 #define NFS4_POLL_RETRY_MIN	(1*HZ)
 #define NFS4_POLL_RETRY_MAX	(15*HZ)
 
+static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
-static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
+static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
-static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
+static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
@@ -185,8 +187,26 @@
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
+	spin_lock(&inode->i_lock);
+	nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
 	if (cinfo->before == nfsi->change_attr && cinfo->atomic)
 		nfsi->change_attr = cinfo->after;
+	spin_unlock(&inode->i_lock);
+}
+
+/* Helper for asynchronous RPC calls */
+static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin,
+		rpc_action tk_exit, void *calldata)
+{
+	struct rpc_task *task;
+
+	if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC)))
+		return -ENOMEM;
+
+	task->tk_calldata = calldata;
+	task->tk_action = tk_begin;
+	rpc_execute(task);
+	return 0;
 }
 
 static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
@@ -195,6 +215,7 @@
 
 	open_flags &= (FMODE_READ|FMODE_WRITE);
 	/* Protect against nfs4_find_state() */
+	spin_lock(&state->owner->so_lock);
 	spin_lock(&inode->i_lock);
 	state->state |= open_flags;
 	/* NB! List reordering - see the reclaim code for why.  */
@@ -204,12 +225,12 @@
 		state->nreaders++;
 	memcpy(&state->stateid, stateid, sizeof(state->stateid));
 	spin_unlock(&inode->i_lock);
+	spin_unlock(&state->owner->so_lock);
 }
 
 /*
  * OPEN_RECLAIM:
  * 	reclaim state on the server after a reboot.
- * 	Assumes caller is holding the sp->so_sem
  */
 static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
 {
@@ -218,7 +239,6 @@
 	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
 	struct nfs_openargs o_arg = {
 		.fh = NFS_FH(inode),
-		.seqid = sp->so_seqid,
 		.id = sp->so_id,
 		.open_flags = state->state,
 		.clientid = server->nfs4_state->cl_clientid,
@@ -245,8 +265,13 @@
 		}
 		o_arg.u.delegation_type = delegation->type;
 	}
+	o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+	if (o_arg.seqid == NULL)
+		return -ENOMEM;
 	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-	nfs4_increment_seqid(status, sp);
+	/* Confirm the sequence as being established */
+	nfs_confirm_seqid(&sp->so_seqid, status);
+	nfs_increment_open_seqid(status, o_arg.seqid);
 	if (status == 0) {
 		memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
 		if (o_res.delegation_type != 0) {
@@ -256,6 +281,7 @@
 				nfs_async_inode_return_delegation(inode, &o_res.stateid);
 		}
 	}
+	nfs_free_seqid(o_arg.seqid);
 	clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	/* Ensure we update the inode attributes */
 	NFS_CACHEINV(inode);
@@ -302,23 +328,35 @@
 	};
 	int status = 0;
 
-	down(&sp->so_sema);
 	if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
 		goto out;
 	if (state->state == 0)
 		goto out;
-	arg.seqid = sp->so_seqid;
+	arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+	status = -ENOMEM;
+	if (arg.seqid == NULL)
+		goto out;
 	arg.open_flags = state->state;
 	memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
 	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-	nfs4_increment_seqid(status, sp);
+	nfs_increment_open_seqid(status, arg.seqid);
+	if (status != 0)
+		goto out_free;
+	if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
+		status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode),
+				sp, &res.stateid, arg.seqid);
+		if (status != 0)
+			goto out_free;
+	}
+	nfs_confirm_seqid(&sp->so_seqid, 0);
 	if (status >= 0) {
 		memcpy(state->stateid.data, res.stateid.data,
 				sizeof(state->stateid.data));
 		clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	}
+out_free:
+	nfs_free_seqid(arg.seqid);
 out:
-	up(&sp->so_sema);
 	dput(parent);
 	return status;
 }
@@ -345,11 +383,11 @@
 	return err;
 }
 
-static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid)
 {
 	struct nfs_open_confirmargs arg = {
 		.fh             = fh,
-		.seqid          = sp->so_seqid,
+		.seqid          = seqid,
 		.stateid	= *stateid,
 	};
 	struct nfs_open_confirmres res;
@@ -362,7 +400,9 @@
 	int status;
 
 	status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
-	nfs4_increment_seqid(status, sp);
+	/* Confirm the sequence as being established */
+	nfs_confirm_seqid(&sp->so_seqid, status);
+	nfs_increment_open_seqid(status, seqid);
 	if (status >= 0)
 		memcpy(stateid, &res.stateid, sizeof(*stateid));
 	return status;
@@ -380,21 +420,41 @@
 	int status;
 
 	/* Update sequence id. The caller must serialize! */
-	o_arg->seqid = sp->so_seqid;
 	o_arg->id = sp->so_id;
 	o_arg->clientid = sp->so_client->cl_clientid;
 
 	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-	nfs4_increment_seqid(status, sp);
+	if (status == 0) {
+		/* OPEN on anything except a regular file is disallowed in NFSv4 */
+		switch (o_res->f_attr->mode & S_IFMT) {
+			case S_IFREG:
+				break;
+			case S_IFLNK:
+				status = -ELOOP;
+				break;
+			case S_IFDIR:
+				status = -EISDIR;
+				break;
+			default:
+				status = -ENOTDIR;
+		}
+	}
+
+	nfs_increment_open_seqid(status, o_arg->seqid);
 	if (status != 0)
 		goto out;
-	update_changeattr(dir, &o_res->cinfo);
+	if (o_arg->open_flags & O_CREAT) {
+		update_changeattr(dir, &o_res->cinfo);
+		nfs_post_op_update_inode(dir, o_res->dir_attr);
+	} else
+		nfs_refresh_inode(dir, o_res->dir_attr);
 	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
 		status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
-				sp, &o_res->stateid);
+				sp, &o_res->stateid, o_arg->seqid);
 		if (status != 0)
 			goto out;
 	}
+	nfs_confirm_seqid(&sp->so_seqid, 0);
 	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
 		status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
 out:
@@ -441,9 +501,7 @@
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
-	struct nfs_fattr        f_attr = {
-		.valid = 0,
-	};
+	struct nfs_fattr f_attr, dir_attr;
 	struct nfs_openargs o_arg = {
 		.fh = NFS_FH(dir),
 		.open_flags = state->state,
@@ -453,6 +511,7 @@
 	};
 	struct nfs_openres o_res = {
 		.f_attr = &f_attr,
+		.dir_attr = &dir_attr,
 		.server = server,
 	};
 	int status = 0;
@@ -465,6 +524,12 @@
 		set_bit(NFS_DELEGATED_STATE, &state->flags);
 		goto out;
 	}
+	o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+	status = -ENOMEM;
+	if (o_arg.seqid == NULL)
+		goto out;
+	nfs_fattr_init(&f_attr);
+	nfs_fattr_init(&dir_attr);
 	status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
 	if (status != 0)
 		goto out_nodeleg;
@@ -490,6 +555,7 @@
 			nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
 	}
 out_nodeleg:
+	nfs_free_seqid(o_arg.seqid);
 	clear_bit(NFS_DELEGATED_STATE, &state->flags);
 out:
 	dput(parent);
@@ -564,7 +630,6 @@
 		dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
 		goto out_err;
 	}
-	down(&sp->so_sema);
 	state = nfs4_get_open_state(inode, sp);
 	if (state == NULL)
 		goto out_err;
@@ -589,7 +654,6 @@
 	set_bit(NFS_DELEGATED_STATE, &state->flags);
 	update_open_stateid(state, &delegation->stateid, open_flags);
 out_ok:
-	up(&sp->so_sema);
 	nfs4_put_state_owner(sp);
 	up_read(&nfsi->rwsem);
 	up_read(&clp->cl_sem);
@@ -600,11 +664,12 @@
 	if (sp != NULL) {
 		if (state != NULL)
 			nfs4_put_open_state(state);
-		up(&sp->so_sema);
 		nfs4_put_state_owner(sp);
 	}
 	up_read(&nfsi->rwsem);
 	up_read(&clp->cl_sem);
+	if (err != -EACCES)
+		nfs_inode_return_delegation(inode);
 	return err;
 }
 
@@ -635,9 +700,7 @@
 	struct nfs4_client *clp = server->nfs4_state;
 	struct inode *inode = NULL;
 	int                     status;
-	struct nfs_fattr        f_attr = {
-		.valid          = 0,
-	};
+	struct nfs_fattr f_attr, dir_attr;
 	struct nfs_openargs o_arg = {
 		.fh             = NFS_FH(dir),
 		.open_flags	= flags,
@@ -648,6 +711,7 @@
 	};
 	struct nfs_openres o_res = {
 		.f_attr         = &f_attr,
+		.dir_attr	= &dir_attr,
 		.server         = server,
 	};
 
@@ -665,8 +729,12 @@
 	} else
 		o_arg.u.attrs = sattr;
 	/* Serialization for the sequence id */
-	down(&sp->so_sema);
 
+	o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+	if (o_arg.seqid == NULL)
+		return -ENOMEM;
+	nfs_fattr_init(&f_attr);
+	nfs_fattr_init(&dir_attr);
 	status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
 	if (status != 0)
 		goto out_err;
@@ -681,7 +749,7 @@
 	update_open_stateid(state, &o_res.stateid, flags);
 	if (o_res.delegation_type != 0)
 		nfs_inode_set_delegation(inode, cred, &o_res);
-	up(&sp->so_sema);
+	nfs_free_seqid(o_arg.seqid);
 	nfs4_put_state_owner(sp);
 	up_read(&clp->cl_sem);
 	*res = state;
@@ -690,7 +758,7 @@
 	if (sp != NULL) {
 		if (state != NULL)
 			nfs4_put_open_state(state);
-		up(&sp->so_sema);
+		nfs_free_seqid(o_arg.seqid);
 		nfs4_put_state_owner(sp);
 	}
 	/* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
@@ -718,7 +786,7 @@
 		 * It is actually a sign of a bug on the client or on the server.
 		 *
 		 * If we receive a BAD_SEQID error in the particular case of
-		 * doing an OPEN, we assume that nfs4_increment_seqid() will
+		 * doing an OPEN, we assume that nfs_increment_open_seqid() will
 		 * have unhashed the old state_owner for us, and that we can
 		 * therefore safely retry using a new one. We should still warn
 		 * the user though...
@@ -728,6 +796,16 @@
 			exception.retry = 1;
 			continue;
 		}
+		/*
+		 * BAD_STATEID on OPEN means that the server cancelled our
+		 * state before it received the OPEN_CONFIRM.
+		 * Recover by retrying the request as per the discussion
+		 * on Page 181 of RFC3530.
+		 */
+		if (status == -NFS4ERR_BAD_STATEID) {
+			exception.retry = 1;
+			continue;
+		}
 		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
 					status, &exception));
 	} while (exception.retry);
@@ -755,7 +833,7 @@
         };
 	int status;
 
-        fattr->valid = 0;
+	nfs_fattr_init(fattr);
 
 	if (state != NULL) {
 		msg.rpc_cred = state->owner->so_cred;
@@ -787,19 +865,30 @@
 	struct nfs4_state *state;
 	struct nfs_closeargs arg;
 	struct nfs_closeres res;
+	struct nfs_fattr fattr;
 };
 
+static void nfs4_free_closedata(struct nfs4_closedata *calldata)
+{
+	struct nfs4_state *state = calldata->state;
+	struct nfs4_state_owner *sp = state->owner;
+
+	nfs4_put_open_state(calldata->state);
+	nfs_free_seqid(calldata->arg.seqid);
+	nfs4_put_state_owner(sp);
+	kfree(calldata);
+}
+
 static void nfs4_close_done(struct rpc_task *task)
 {
 	struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
 	struct nfs4_state *state = calldata->state;
-	struct nfs4_state_owner *sp = state->owner;
 	struct nfs_server *server = NFS_SERVER(calldata->inode);
 
         /* hmm. we are done with the inode, and in the process of freeing
 	 * the state_owner. we keep this around to process errors
 	 */
-	nfs4_increment_seqid(task->tk_status, sp);
+	nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
 	switch (task->tk_status) {
 		case 0:
 			memcpy(&state->stateid, &calldata->res.stateid,
@@ -816,25 +905,49 @@
 				return;
 			}
 	}
+	nfs_refresh_inode(calldata->inode, calldata->res.fattr);
 	state->state = calldata->arg.open_flags;
-	nfs4_put_open_state(state);
-	up(&sp->so_sema);
-	nfs4_put_state_owner(sp);
-	up_read(&server->nfs4_state->cl_sem);
-	kfree(calldata);
+	nfs4_free_closedata(calldata);
 }
 
-static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata *calldata)
+static void nfs4_close_begin(struct rpc_task *task)
 {
+	struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
+	struct nfs4_state *state = calldata->state;
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
 		.rpc_argp = &calldata->arg,
 		.rpc_resp = &calldata->res,
-		.rpc_cred = calldata->state->owner->so_cred,
+		.rpc_cred = state->owner->so_cred,
 	};
-	if (calldata->arg.open_flags != 0)
+	int mode = 0;
+	int status;
+
+	status = nfs_wait_on_sequence(calldata->arg.seqid, task);
+	if (status != 0)
+		return;
+	/* Don't reorder reads */
+	smp_rmb();
+	/* Recalculate the new open mode in case someone reopened the file
+	 * while we were waiting in line to be scheduled.
+	 */
+	if (state->nreaders != 0)
+		mode |= FMODE_READ;
+	if (state->nwriters != 0)
+		mode |= FMODE_WRITE;
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+		state->state = mode;
+	if (mode == state->state) {
+		nfs4_free_closedata(calldata);
+		task->tk_exit = NULL;
+		rpc_exit(task, 0);
+		return;
+	}
+	nfs_fattr_init(calldata->res.fattr);
+	if (mode != 0)
 		msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
-	return rpc_call_async(clnt, &msg, 0, nfs4_close_done, calldata);
+	calldata->arg.open_flags = mode;
+	rpc_call_setup(task, &msg, 0);
 }
 
 /* 
@@ -850,40 +963,57 @@
  */
 int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) 
 {
+	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_closedata *calldata;
-	int status;
+	int status = -ENOMEM;
 
-	/* Tell caller we're done */
-	if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
-		state->state = mode;
-		return 0;
-	}
-	calldata = (struct nfs4_closedata *)kmalloc(sizeof(*calldata), GFP_KERNEL);
+	calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
 	if (calldata == NULL)
-		return -ENOMEM;
+		goto out;
 	calldata->inode = inode;
 	calldata->state = state;
 	calldata->arg.fh = NFS_FH(inode);
+	calldata->arg.stateid = &state->stateid;
 	/* Serialization for the sequence id */
-	calldata->arg.seqid = state->owner->so_seqid;
-	calldata->arg.open_flags = mode;
-	memcpy(&calldata->arg.stateid, &state->stateid,
-			sizeof(calldata->arg.stateid));
-	status = nfs4_close_call(NFS_SERVER(inode)->client, calldata);
-	/*
-	 * Return -EINPROGRESS on success in order to indicate to the
-	 * caller that an asynchronous RPC call has been launched, and
-	 * that it will release the semaphores on completion.
-	 */
-	return (status == 0) ? -EINPROGRESS : status;
+	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
+	if (calldata->arg.seqid == NULL)
+		goto out_free_calldata;
+	calldata->arg.bitmask = server->attr_bitmask;
+	calldata->res.fattr = &calldata->fattr;
+	calldata->res.server = server;
+
+	status = nfs4_call_async(server->client, nfs4_close_begin,
+			nfs4_close_done, calldata);
+	if (status == 0)
+		goto out;
+
+	nfs_free_seqid(calldata->arg.seqid);
+out_free_calldata:
+	kfree(calldata);
+out:
+	return status;
 }
 
-struct inode *
+static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+{
+	struct file *filp;
+
+	filp = lookup_instantiate_filp(nd, dentry, NULL);
+	if (!IS_ERR(filp)) {
+		struct nfs_open_context *ctx;
+		ctx = (struct nfs_open_context *)filp->private_data;
+		ctx->state = state;
+	} else
+		nfs4_close_state(state, nd->intent.open.flags);
+}
+
+struct dentry *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct iattr attr;
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
+	struct dentry *res;
 
 	if (nd->flags & LOOKUP_CREATE) {
 		attr.ia_mode = nd->intent.open.create_mode;
@@ -897,16 +1027,23 @@
 
 	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
 	if (IS_ERR(cred))
-		return (struct inode *)cred;
+		return (struct dentry *)cred;
 	state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
 	put_rpccred(cred);
-	if (IS_ERR(state))
-		return (struct inode *)state;
-	return state->inode;
+	if (IS_ERR(state)) {
+		if (PTR_ERR(state) == -ENOENT)
+			d_add(dentry, NULL);
+		return (struct dentry *)state;
+	}
+	res = d_add_unique(dentry, state->inode);
+	if (res != NULL)
+		dentry = res;
+	nfs4_intent_set_file(nd, dentry, state);
+	return res;
 }
 
 int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
+nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
 {
 	struct rpc_cred *cred;
 	struct nfs4_state *state;
@@ -919,18 +1056,30 @@
 	if (IS_ERR(state))
 		state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
 	put_rpccred(cred);
-	if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0)
-		return 1;
-	if (IS_ERR(state))
-		return 0;
+	if (IS_ERR(state)) {
+		switch (PTR_ERR(state)) {
+			case -EPERM:
+			case -EACCES:
+			case -EDQUOT:
+			case -ENOSPC:
+			case -EROFS:
+				lookup_instantiate_filp(nd, (struct dentry *)state, NULL);
+				return 1;
+			case -ENOENT:
+				if (dentry->d_inode == NULL)
+					return 1;
+		}
+		goto out_drop;
+	}
 	inode = state->inode;
+	iput(inode);
 	if (inode == dentry->d_inode) {
-		iput(inode);
+		nfs4_intent_set_file(nd, dentry, state);
 		return 1;
 	}
-	d_drop(dentry);
 	nfs4_close_state(state, openflags);
-	iput(inode);
+out_drop:
+	d_drop(dentry);
 	return 0;
 }
 
@@ -974,13 +1123,12 @@
 static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
-	struct nfs_fattr *	fattr = info->fattr;
 	struct nfs4_lookup_root_arg args = {
 		.bitmask = nfs4_fattr_bitmap,
 	};
 	struct nfs4_lookup_res res = {
 		.server = server,
-		.fattr = fattr,
+		.fattr = info->fattr,
 		.fh = fhandle,
 	};
 	struct rpc_message msg = {
@@ -988,7 +1136,7 @@
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
-	fattr->valid = 0;
+	nfs_fattr_init(info->fattr);
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1051,7 +1199,7 @@
 		q.len = p - q.name;
 
 		do {
-			fattr->valid = 0;
+			nfs_fattr_init(fattr);
 			status = nfs4_handle_exception(server,
 					rpc_call_sync(server->client, &msg, 0),
 					&exception);
@@ -1088,7 +1236,7 @@
 		.rpc_resp = &res,
 	};
 	
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1130,7 +1278,7 @@
 	struct nfs4_state *state;
 	int status;
 
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	
 	cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
 	if (IS_ERR(cred))
@@ -1176,7 +1324,7 @@
 		.rpc_resp = &res,
 	};
 	
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	
 	dprintk("NFS call  lookup %s\n", name->name);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
@@ -1325,7 +1473,7 @@
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(server->client, &msg, flags);
 	if (!status)
 		renew_lease(server, timestamp);
@@ -1362,7 +1510,7 @@
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(server->client, &msg, rpcflags);
 	dprintk("NFS reply write: %d\n", status);
 	return status;
@@ -1396,7 +1544,7 @@
 	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
 			(long long) cdata->args.offset);
 
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(server->client, &msg, 0);
 	dprintk("NFS reply commit: %d\n", status);
 	return status;
@@ -1431,7 +1579,7 @@
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags)
+                 int flags, struct nameidata *nd)
 {
 	struct nfs4_state *state;
 	struct rpc_cred *cred;
@@ -1453,24 +1601,30 @@
 		struct nfs_fattr fattr;
 		status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
 		                     NFS_FH(state->inode), sattr, state);
-		if (status == 0) {
+		if (status == 0)
 			nfs_setattr_update_inode(state->inode, sattr);
-			goto out;
-		}
-	} else if (flags != 0)
-		goto out;
-	nfs4_close_state(state, flags);
+	}
+	if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
+		nfs4_intent_set_file(nd, dentry, state);
+	else
+		nfs4_close_state(state, flags);
 out:
 	return status;
 }
 
 static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 {
+	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs4_remove_arg args = {
 		.fh = NFS_FH(dir),
 		.name = name,
+		.bitmask = server->attr_bitmask,
 	};
-	struct nfs4_change_info	res;
+	struct nfs_fattr dir_attr;
+	struct nfs4_remove_res	res = {
+		.server = server,
+		.dir_attr = &dir_attr,
+	};
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
 		.rpc_argp	= &args,
@@ -1478,9 +1632,12 @@
 	};
 	int			status;
 
-	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	if (status == 0)
-		update_changeattr(dir, &res);
+	nfs_fattr_init(res.dir_attr);
+	status = rpc_call_sync(server->client, &msg, 0);
+	if (status == 0) {
+		update_changeattr(dir, &res.cinfo);
+		nfs_post_op_update_inode(dir, res.dir_attr);
+	}
 	return status;
 }
 
@@ -1498,12 +1655,14 @@
 
 struct unlink_desc {
 	struct nfs4_remove_arg	args;
-	struct nfs4_change_info	res;
+	struct nfs4_remove_res	res;
+	struct nfs_fattr dir_attr;
 };
 
 static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir,
 		struct qstr *name)
 {
+	struct nfs_server *server = NFS_SERVER(dir->d_inode);
 	struct unlink_desc *up;
 
 	up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL);
@@ -1512,6 +1671,9 @@
 	
 	up->args.fh = NFS_FH(dir->d_inode);
 	up->args.name = name;
+	up->args.bitmask = server->attr_bitmask;
+	up->res.server = server;
+	up->res.dir_attr = &up->dir_attr;
 	
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
 	msg->rpc_argp = &up->args;
@@ -1526,7 +1688,8 @@
 	
 	if (msg->rpc_resp != NULL) {
 		up = container_of(msg->rpc_resp, struct unlink_desc, res);
-		update_changeattr(dir->d_inode, &up->res);
+		update_changeattr(dir->d_inode, &up->res.cinfo);
+		nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr);
 		kfree(up);
 		msg->rpc_resp = NULL;
 		msg->rpc_argp = NULL;
@@ -1537,13 +1700,20 @@
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		struct inode *new_dir, struct qstr *new_name)
 {
+	struct nfs_server *server = NFS_SERVER(old_dir);
 	struct nfs4_rename_arg arg = {
 		.old_dir = NFS_FH(old_dir),
 		.new_dir = NFS_FH(new_dir),
 		.old_name = old_name,
 		.new_name = new_name,
+		.bitmask = server->attr_bitmask,
 	};
-	struct nfs4_rename_res res = { };
+	struct nfs_fattr old_fattr, new_fattr;
+	struct nfs4_rename_res res = {
+		.server = server,
+		.old_fattr = &old_fattr,
+		.new_fattr = &new_fattr,
+	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
 		.rpc_argp = &arg,
@@ -1551,11 +1721,15 @@
 	};
 	int			status;
 	
-	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+	nfs_fattr_init(res.old_fattr);
+	nfs_fattr_init(res.new_fattr);
+	status = rpc_call_sync(server->client, &msg, 0);
 
 	if (!status) {
 		update_changeattr(old_dir, &res.old_cinfo);
+		nfs_post_op_update_inode(old_dir, res.old_fattr);
 		update_changeattr(new_dir, &res.new_cinfo);
+		nfs_post_op_update_inode(new_dir, res.new_fattr);
 	}
 	return status;
 }
@@ -1576,22 +1750,34 @@
 
 static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
+	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_link_arg arg = {
 		.fh     = NFS_FH(inode),
 		.dir_fh = NFS_FH(dir),
 		.name   = name,
+		.bitmask = server->attr_bitmask,
 	};
-	struct nfs4_change_info	cinfo = { };
+	struct nfs_fattr fattr, dir_attr;
+	struct nfs4_link_res res = {
+		.server = server,
+		.fattr = &fattr,
+		.dir_attr = &dir_attr,
+	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
 		.rpc_argp = &arg,
-		.rpc_resp = &cinfo,
+		.rpc_resp = &res,
 	};
 	int			status;
 
-	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-	if (!status)
-		update_changeattr(dir, &cinfo);
+	nfs_fattr_init(res.fattr);
+	nfs_fattr_init(res.dir_attr);
+	status = rpc_call_sync(server->client, &msg, 0);
+	if (!status) {
+		update_changeattr(dir, &res.cinfo);
+		nfs_post_op_update_inode(dir, res.dir_attr);
+		nfs_refresh_inode(inode, res.fattr);
+	}
 
 	return status;
 }
@@ -1613,6 +1799,7 @@
 		struct nfs_fattr *fattr)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
+	struct nfs_fattr dir_fattr;
 	struct nfs4_create_arg arg = {
 		.dir_fh = NFS_FH(dir),
 		.server = server,
@@ -1625,6 +1812,7 @@
 		.server = server,
 		.fh = fhandle,
 		.fattr = fattr,
+		.dir_fattr = &dir_fattr,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
@@ -1636,11 +1824,13 @@
 	if (path->len > NFS4_MAXPATHLEN)
 		return -ENAMETOOLONG;
 	arg.u.symlink = path;
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
+	nfs_fattr_init(&dir_fattr);
 	
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
+	nfs_post_op_update_inode(dir, res.dir_fattr);
 	return status;
 }
 
@@ -1664,7 +1854,7 @@
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_fh fhandle;
-	struct nfs_fattr fattr;
+	struct nfs_fattr fattr, dir_fattr;
 	struct nfs4_create_arg arg = {
 		.dir_fh = NFS_FH(dir),
 		.server = server,
@@ -1677,6 +1867,7 @@
 		.server = server,
 		.fh = &fhandle,
 		.fattr = &fattr,
+		.dir_fattr = &dir_fattr,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1685,11 +1876,13 @@
 	};
 	int			status;
 
-	fattr.valid = 0;
+	nfs_fattr_init(&fattr);
+	nfs_fattr_init(&dir_fattr);
 	
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status) {
 		update_changeattr(dir, &res.dir_cinfo);
+		nfs_post_op_update_inode(dir, res.dir_fattr);
 		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	}
 	return status;
@@ -1762,7 +1955,7 @@
 {
 	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_fh fh;
-	struct nfs_fattr fattr;
+	struct nfs_fattr fattr, dir_fattr;
 	struct nfs4_create_arg arg = {
 		.dir_fh = NFS_FH(dir),
 		.server = server,
@@ -1774,6 +1967,7 @@
 		.server = server,
 		.fh = &fh,
 		.fattr = &fattr,
+		.dir_fattr = &dir_fattr,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1783,7 +1977,8 @@
 	int			status;
 	int                     mode = sattr->ia_mode;
 
-	fattr.valid = 0;
+	nfs_fattr_init(&fattr);
+	nfs_fattr_init(&dir_fattr);
 
 	BUG_ON(!(sattr->ia_valid & ATTR_MODE));
 	BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
@@ -1805,6 +2000,7 @@
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (status == 0) {
 		update_changeattr(dir, &res.dir_cinfo);
+		nfs_post_op_update_inode(dir, res.dir_fattr);
 		status = nfs_instantiate(dentry, &fh, &fattr);
 	}
 	return status;
@@ -1836,7 +2032,7 @@
 		.rpc_resp = fsstat,
 	};
 
-	fsstat->fattr->valid = 0;
+	nfs_fattr_init(fsstat->fattr);
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1883,7 +2079,7 @@
 
 static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
-	fsinfo->fattr->valid = 0;
+	nfs_fattr_init(fsinfo->fattr);
 	return nfs4_do_fsinfo(server, fhandle, fsinfo);
 }
 
@@ -1906,7 +2102,7 @@
 		return 0;
 	}
 
-	pathconf->fattr->valid = 0;
+	nfs_fattr_init(pathconf->fattr);
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
@@ -1973,8 +2169,10 @@
 		rpc_restart_call(task);
 		return;
 	}
-	if (task->tk_status >= 0)
+	if (task->tk_status >= 0) {
 		renew_lease(NFS_SERVER(inode), data->timestamp);
+		nfs_post_op_update_inode(inode, data->res.fattr);
+	}
 	/* Call back common NFS writeback processing */
 	nfs_writeback_done(task);
 }
@@ -1990,6 +2188,7 @@
 		.rpc_cred = data->cred,
 	};
 	struct inode *inode = data->inode;
+	struct nfs_server *server = NFS_SERVER(inode);
 	int stable;
 	int flags;
 	
@@ -2001,6 +2200,8 @@
 	} else
 		stable = NFS_UNSTABLE;
 	data->args.stable = stable;
+	data->args.bitmask = server->attr_bitmask;
+	data->res.server = server;
 
 	data->timestamp   = jiffies;
 
@@ -2022,6 +2223,8 @@
 		rpc_restart_call(task);
 		return;
 	}
+	if (task->tk_status >= 0)
+		nfs_post_op_update_inode(inode, data->res.fattr);
 	/* Call back common NFS writeback processing */
 	nfs_commit_done(task);
 }
@@ -2037,8 +2240,12 @@
 		.rpc_cred = data->cred,
 	};	
 	struct inode *inode = data->inode;
+	struct nfs_server *server = NFS_SERVER(inode);
 	int flags;
 	
+	data->args.bitmask = server->attr_bitmask;
+	data->res.server = server;
+
 	/* Set the initial flags for the task.  */
 	flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
 
@@ -2106,65 +2313,6 @@
 	return 0;
 }
 
-/*
- * We will need to arrange for the VFS layer to provide an atomic open.
- * Until then, this open method is prone to inefficiency and race conditions
- * due to the lookup, potential create, and open VFS calls from sys_open()
- * placed on the wire.
- */
-static int
-nfs4_proc_file_open(struct inode *inode, struct file *filp)
-{
-	struct dentry *dentry = filp->f_dentry;
-	struct nfs_open_context *ctx;
-	struct nfs4_state *state = NULL;
-	struct rpc_cred *cred;
-	int status = -ENOMEM;
-
-	dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n",
-	                       (int)dentry->d_parent->d_name.len,
-	                       dentry->d_parent->d_name.name,
-	                       (int)dentry->d_name.len, dentry->d_name.name);
-
-
-	/* Find our open stateid */
-	cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-	if (IS_ERR(cred))
-		return PTR_ERR(cred);
-	ctx = alloc_nfs_open_context(dentry, cred);
-	put_rpccred(cred);
-	if (unlikely(ctx == NULL))
-		return -ENOMEM;
-	status = -EIO; /* ERACE actually */
-	state = nfs4_find_state(inode, cred, filp->f_mode);
-	if (unlikely(state == NULL))
-		goto no_state;
-	ctx->state = state;
-	nfs4_close_state(state, filp->f_mode);
-	ctx->mode = filp->f_mode;
-	nfs_file_set_open_context(filp, ctx);
-	put_nfs_open_context(ctx);
-	if (filp->f_mode & FMODE_WRITE)
-		nfs_begin_data_update(inode);
-	return 0;
-no_state:
-	printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
-	put_nfs_open_context(ctx);
-	return status;
-}
-
-/*
- * Release our state
- */
-static int
-nfs4_proc_file_release(struct inode *inode, struct file *filp)
-{
-	if (filp->f_mode & FMODE_WRITE)
-		nfs_end_data_update(inode);
-	nfs_file_clear_open_context(filp);
-	return 0;
-}
-
 static inline int nfs4_server_supports_acls(struct nfs_server *server)
 {
 	return (server->caps & NFS_CAP_ACLS)
@@ -2285,7 +2433,7 @@
 			return -ENOMEM;
 		args.acl_pages[0] = localpage;
 		args.acl_pgbase = 0;
-		args.acl_len = PAGE_SIZE;
+		resp_len = args.acl_len = PAGE_SIZE;
 	} else {
 		resp_buf = buf;
 		buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
@@ -2345,6 +2493,7 @@
 
 	if (!nfs4_server_supports_acls(server))
 		return -EOPNOTSUPP;
+	nfs_inode_return_delegation(inode);
 	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
 	ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
 	if (ret == 0)
@@ -2353,7 +2502,7 @@
 }
 
 static int
-nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
+nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
 {
 	struct nfs4_client *clp = server->nfs4_state;
 
@@ -2431,7 +2580,7 @@
 /* This is the error handling routine for processes that are allowed
  * to sleep.
  */
-int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
+int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
 {
 	struct nfs4_client *clp = server->nfs4_state;
 	int ret = errorcode;
@@ -2632,7 +2781,6 @@
 
 	down_read(&clp->cl_sem);
 	nlo.clientid = clp->cl_clientid;
-	down(&state->lock_sema);
 	status = nfs4_set_lock_state(state, request);
 	if (status != 0)
 		goto out;
@@ -2659,7 +2807,6 @@
 		status = 0;
 	}
 out:
-	up(&state->lock_sema);
 	up_read(&clp->cl_sem);
 	return status;
 }
@@ -2696,67 +2843,125 @@
 	return res;
 }
 
-static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+struct nfs4_unlockdata {
+	struct nfs_lockargs arg;
+	struct nfs_locku_opargs luargs;
+	struct nfs_lockres res;
+	struct nfs4_lock_state *lsp;
+	struct nfs_open_context *ctx;
+	atomic_t refcount;
+	struct completion completion;
+};
+
+static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
 {
-	struct inode *inode = state->inode;
-	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs4_client *clp = server->nfs4_state;
-	struct nfs_lockargs arg = {
-		.fh = NFS_FH(inode),
-		.type = nfs4_lck_type(cmd, request),
-		.offset = request->fl_start,
-		.length = nfs4_lck_length(request),
-	};
-	struct nfs_lockres res = {
-		.server = server,
-	};
+	if (atomic_dec_and_test(&calldata->refcount)) {
+		nfs_free_seqid(calldata->luargs.seqid);
+		nfs4_put_lock_state(calldata->lsp);
+		put_nfs_open_context(calldata->ctx);
+		kfree(calldata);
+	}
+}
+
+static void nfs4_locku_complete(struct nfs4_unlockdata *calldata)
+{
+	complete(&calldata->completion);
+	nfs4_locku_release_calldata(calldata);
+}
+
+static void nfs4_locku_done(struct rpc_task *task)
+{
+	struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
+
+	nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
+	switch (task->tk_status) {
+		case 0:
+			memcpy(calldata->lsp->ls_stateid.data,
+					calldata->res.u.stateid.data,
+					sizeof(calldata->lsp->ls_stateid.data));
+			break;
+		case -NFS4ERR_STALE_STATEID:
+		case -NFS4ERR_EXPIRED:
+			nfs4_schedule_state_recovery(calldata->res.server->nfs4_state);
+			break;
+		default:
+			if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) {
+				rpc_restart_call(task);
+				return;
+			}
+	}
+	nfs4_locku_complete(calldata);
+}
+
+static void nfs4_locku_begin(struct rpc_task *task)
+{
+	struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
-		.rpc_argp       = &arg,
-		.rpc_resp       = &res,
-		.rpc_cred	= state->owner->so_cred,
+		.rpc_argp       = &calldata->arg,
+		.rpc_resp       = &calldata->res,
+		.rpc_cred	= calldata->lsp->ls_state->owner->so_cred,
 	};
-	struct nfs4_lock_state *lsp;
-	struct nfs_locku_opargs luargs;
 	int status;
-			
-	down_read(&clp->cl_sem);
-	down(&state->lock_sema);
-	status = nfs4_set_lock_state(state, request);
-	if (status != 0)
-		goto out;
-	lsp = request->fl_u.nfs4_fl.owner;
-	/* We might have lost the locks! */
-	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
-		goto out;
-	luargs.seqid = lsp->ls_seqid;
-	memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
-	arg.u.locku = &luargs;
-	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-	nfs4_increment_lock_seqid(status, lsp);
 
-	if (status == 0)
-		memcpy(&lsp->ls_stateid,  &res.u.stateid, 
-				sizeof(lsp->ls_stateid));
-out:
-	up(&state->lock_sema);
-	if (status == 0)
-		do_vfs_lock(request->fl_file, request);
-	up_read(&clp->cl_sem);
-	return status;
+	status = nfs_wait_on_sequence(calldata->luargs.seqid, task);
+	if (status != 0)
+		return;
+	if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
+		nfs4_locku_complete(calldata);
+		task->tk_exit = NULL;
+		rpc_exit(task, 0);
+		return;
+	}
+	rpc_call_setup(task, &msg, 0);
 }
 
 static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
-	struct nfs4_exception exception = { };
-	int err;
+	struct nfs4_unlockdata *calldata;
+	struct inode *inode = state->inode;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_lock_state *lsp;
+	int status;
 
-	do {
-		err = nfs4_handle_exception(NFS_SERVER(state->inode),
-				_nfs4_proc_unlck(state, cmd, request),
-				&exception);
-	} while (exception.retry);
-	return err;
+	status = nfs4_set_lock_state(state, request);
+	if (status != 0)
+		return status;
+	lsp = request->fl_u.nfs4_fl.owner;
+	/* We might have lost the locks! */
+	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
+		return 0;
+	calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
+	if (calldata == NULL)
+		return -ENOMEM;
+	calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
+	if (calldata->luargs.seqid == NULL) {
+		kfree(calldata);
+		return -ENOMEM;
+	}
+	calldata->luargs.stateid = &lsp->ls_stateid;
+	calldata->arg.fh = NFS_FH(inode);
+	calldata->arg.type = nfs4_lck_type(cmd, request);
+	calldata->arg.offset = request->fl_start;
+	calldata->arg.length = nfs4_lck_length(request);
+	calldata->arg.u.locku = &calldata->luargs;
+	calldata->res.server = server;
+	calldata->lsp = lsp;
+	atomic_inc(&lsp->ls_count);
+
+	/* Ensure we don't close file until we're done freeing locks! */
+	calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data);
+
+	atomic_set(&calldata->refcount, 2);
+	init_completion(&calldata->completion);
+
+	status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin,
+			nfs4_locku_done, calldata);
+	if (status == 0)
+		wait_for_completion_interruptible(&calldata->completion);
+	do_vfs_lock(request->fl_file, request);
+	nfs4_locku_release_calldata(calldata);
+	return status;
 }
 
 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
@@ -2764,11 +2969,23 @@
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
+	struct nfs_lock_opargs largs = {
+		.lock_stateid = &lsp->ls_stateid,
+		.open_stateid = &state->stateid,
+		.lock_owner = {
+			.clientid = server->nfs4_state->cl_clientid,
+			.id = lsp->ls_id,
+		},
+		.reclaim = reclaim,
+	};
 	struct nfs_lockargs arg = {
 		.fh = NFS_FH(inode),
 		.type = nfs4_lck_type(cmd, request),
 		.offset = request->fl_start,
 		.length = nfs4_lck_length(request),
+		.u = {
+			.lock = &largs,
+		},
 	};
 	struct nfs_lockres res = {
 		.server = server,
@@ -2779,53 +2996,39 @@
 		.rpc_resp       = &res,
 		.rpc_cred	= state->owner->so_cred,
 	};
-	struct nfs_lock_opargs largs = {
-		.reclaim = reclaim,
-		.new_lock_owner = 0,
-	};
-	int status;
+	int status = -ENOMEM;
 
-	if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
+	largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
+	if (largs.lock_seqid == NULL)
+		return -ENOMEM;
+	if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
 		struct nfs4_state_owner *owner = state->owner;
-		struct nfs_open_to_lock otl = {
-			.lock_owner = {
-				.clientid = server->nfs4_state->cl_clientid,
-			},
-		};
 
-		otl.lock_seqid = lsp->ls_seqid;
-		otl.lock_owner.id = lsp->ls_id;
-		memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid));
-		largs.u.open_lock = &otl;
+		largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid);
+		if (largs.open_seqid == NULL)
+			goto out;
 		largs.new_lock_owner = 1;
-		arg.u.lock = &largs;
-		down(&owner->so_sema);
-		otl.open_seqid = owner->so_seqid;
 		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-		/* increment open_owner seqid on success, and 
-		* seqid mutating errors */
-		nfs4_increment_seqid(status, owner);
-		up(&owner->so_sema);
-		if (status == 0) {
-			lsp->ls_flags |= NFS_LOCK_INITIALIZED;
-			lsp->ls_seqid++;
+		/* increment open seqid on success, and seqid mutating errors */
+		if (largs.new_lock_owner != 0) {
+			nfs_increment_open_seqid(status, largs.open_seqid);
+			if (status == 0)
+				nfs_confirm_seqid(&lsp->ls_seqid, 0);
 		}
-	} else {
-		struct nfs_exist_lock el = {
-			.seqid = lsp->ls_seqid,
-		};
-		memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
-		largs.u.exist_lock = &el;
-		arg.u.lock = &largs;
+		nfs_free_seqid(largs.open_seqid);
+	} else
 		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-		/* increment seqid on success, and * seqid mutating errors*/
-		nfs4_increment_lock_seqid(status, lsp);
-	}
+	/* increment lock seqid on success, and seqid mutating errors*/
+	nfs_increment_lock_seqid(status, largs.lock_seqid);
 	/* save the returned stateid. */
-	if (status == 0)
-		memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
-	else if (status == -NFS4ERR_DENIED)
+	if (status == 0) {
+		memcpy(lsp->ls_stateid.data, res.u.stateid.data,
+				sizeof(lsp->ls_stateid.data));
+		lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+	} else if (status == -NFS4ERR_DENIED)
 		status = -EAGAIN;
+out:
+	nfs_free_seqid(largs.lock_seqid);
 	return status;
 }
 
@@ -2865,11 +3068,9 @@
 	int status;
 
 	down_read(&clp->cl_sem);
-	down(&state->lock_sema);
 	status = nfs4_set_lock_state(state, request);
 	if (status == 0)
 		status = _nfs4_do_setlk(state, cmd, request, 0);
-	up(&state->lock_sema);
 	if (status == 0) {
 		/* Note: we always want to sleep here! */
 		request->fl_flags |= FL_SLEEP;
@@ -3024,8 +3225,8 @@
 	.read_setup	= nfs4_proc_read_setup,
 	.write_setup	= nfs4_proc_write_setup,
 	.commit_setup	= nfs4_proc_commit_setup,
-	.file_open      = nfs4_proc_file_open,
-	.file_release   = nfs4_proc_file_release,
+	.file_open      = nfs_open,
+	.file_release   = nfs_release,
 	.lock		= nfs4_proc_lock,
 	.clear_acl_cache = nfs4_zap_acl_attr,
 };
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index afe587d..2d5a6a2 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -264,13 +264,16 @@
 {
 	struct nfs4_state_owner *sp;
 
-	sp = kmalloc(sizeof(*sp),GFP_KERNEL);
+	sp = kzalloc(sizeof(*sp),GFP_KERNEL);
 	if (!sp)
 		return NULL;
-	init_MUTEX(&sp->so_sema);
-	sp->so_seqid = 0;                 /* arbitrary */
+	spin_lock_init(&sp->so_lock);
 	INIT_LIST_HEAD(&sp->so_states);
 	INIT_LIST_HEAD(&sp->so_delegations);
+	rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
+	sp->so_seqid.sequence = &sp->so_sequence;
+	spin_lock_init(&sp->so_sequence.lock);
+	INIT_LIST_HEAD(&sp->so_sequence.list);
 	atomic_set(&sp->so_count, 1);
 	return sp;
 }
@@ -359,7 +362,6 @@
 	memset(state->stateid.data, 0, sizeof(state->stateid.data));
 	atomic_set(&state->count, 1);
 	INIT_LIST_HEAD(&state->lock_states);
-	init_MUTEX(&state->lock_sema);
 	spin_lock_init(&state->state_lock);
 	return state;
 }
@@ -437,21 +439,23 @@
 	if (state)
 		goto out;
 	new = nfs4_alloc_open_state();
+	spin_lock(&owner->so_lock);
 	spin_lock(&inode->i_lock);
 	state = __nfs4_find_state_byowner(inode, owner);
 	if (state == NULL && new != NULL) {
 		state = new;
-		/* Caller *must* be holding owner->so_sem */
-		/* Note: The reclaim code dictates that we add stateless
-		 * and read-only stateids to the end of the list */
-		list_add_tail(&state->open_states, &owner->so_states);
 		state->owner = owner;
 		atomic_inc(&owner->so_count);
 		list_add(&state->inode_states, &nfsi->open_states);
 		state->inode = igrab(inode);
 		spin_unlock(&inode->i_lock);
+		/* Note: The reclaim code dictates that we add stateless
+		 * and read-only stateids to the end of the list */
+		list_add_tail(&state->open_states, &owner->so_states);
+		spin_unlock(&owner->so_lock);
 	} else {
 		spin_unlock(&inode->i_lock);
+		spin_unlock(&owner->so_lock);
 		if (new)
 			nfs4_free_open_state(new);
 	}
@@ -461,19 +465,21 @@
 
 /*
  * Beware! Caller must be holding exactly one
- * reference to clp->cl_sem and owner->so_sema!
+ * reference to clp->cl_sem!
  */
 void nfs4_put_open_state(struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
 
-	if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
+	if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
 		return;
+	spin_lock(&inode->i_lock);
 	if (!list_empty(&state->inode_states))
 		list_del(&state->inode_states);
-	spin_unlock(&inode->i_lock);
 	list_del(&state->open_states);
+	spin_unlock(&inode->i_lock);
+	spin_unlock(&owner->so_lock);
 	iput(inode);
 	BUG_ON (state->state != 0);
 	nfs4_free_open_state(state);
@@ -481,20 +487,17 @@
 }
 
 /*
- * Beware! Caller must be holding no references to clp->cl_sem!
- * of owner->so_sema!
+ * Close the current file.
  */
 void nfs4_close_state(struct nfs4_state *state, mode_t mode)
 {
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
-	struct nfs4_client *clp = owner->so_client;
 	int newstate;
 
 	atomic_inc(&owner->so_count);
-	down_read(&clp->cl_sem);
-	down(&owner->so_sema);
 	/* Protect against nfs4_find_state() */
+	spin_lock(&owner->so_lock);
 	spin_lock(&inode->i_lock);
 	if (mode & FMODE_READ)
 		state->nreaders--;
@@ -507,6 +510,7 @@
 		list_move_tail(&state->open_states, &owner->so_states);
 	}
 	spin_unlock(&inode->i_lock);
+	spin_unlock(&owner->so_lock);
 	newstate = 0;
 	if (state->state != 0) {
 		if (state->nreaders)
@@ -515,14 +519,16 @@
 			newstate |= FMODE_WRITE;
 		if (state->state == newstate)
 			goto out;
-		if (nfs4_do_close(inode, state, newstate) == -EINPROGRESS)
+		if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+			state->state = newstate;
+			goto out;
+		}
+		if (nfs4_do_close(inode, state, newstate) == 0)
 			return;
 	}
 out:
 	nfs4_put_open_state(state);
-	up(&owner->so_sema);
 	nfs4_put_state_owner(owner);
-	up_read(&clp->cl_sem);
 }
 
 /*
@@ -546,19 +552,16 @@
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
  *
- * The caller must be holding state->lock_sema
  */
 static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 {
 	struct nfs4_lock_state *lsp;
 	struct nfs4_client *clp = state->owner->so_client;
 
-	lsp = kmalloc(sizeof(*lsp), GFP_KERNEL);
+	lsp = kzalloc(sizeof(*lsp), GFP_KERNEL);
 	if (lsp == NULL)
 		return NULL;
-	lsp->ls_flags = 0;
-	lsp->ls_seqid = 0;	/* arbitrary */
-	memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
+	lsp->ls_seqid.sequence = &state->owner->so_sequence;
 	atomic_set(&lsp->ls_count, 1);
 	lsp->ls_owner = fl_owner;
 	spin_lock(&clp->cl_lock);
@@ -572,7 +575,7 @@
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
  *
- * The caller must be holding state->lock_sema and clp->cl_sem
+ * The caller must be holding clp->cl_sem
  */
 static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
 {
@@ -605,7 +608,7 @@
  * Release reference to lock_state, and free it if we see that
  * it is no longer in use
  */
-static void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
+void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
 {
 	struct nfs4_state *state;
 
@@ -673,29 +676,94 @@
 	nfs4_put_lock_state(lsp);
 }
 
-/*
-* Called with state->lock_sema and clp->cl_sem held.
-*/
-void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
+struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
 {
-	if (status == NFS_OK || seqid_mutating_err(-status))
-		lsp->ls_seqid++;
+	struct nfs_seqid *new;
+
+	new = kmalloc(sizeof(*new), GFP_KERNEL);
+	if (new != NULL) {
+		new->sequence = counter;
+		INIT_LIST_HEAD(&new->list);
+	}
+	return new;
+}
+
+void nfs_free_seqid(struct nfs_seqid *seqid)
+{
+	struct rpc_sequence *sequence = seqid->sequence->sequence;
+
+	if (!list_empty(&seqid->list)) {
+		spin_lock(&sequence->lock);
+		list_del(&seqid->list);
+		spin_unlock(&sequence->lock);
+	}
+	rpc_wake_up_next(&sequence->wait);
+	kfree(seqid);
 }
 
 /*
-* Called with sp->so_sema and clp->cl_sem held.
-*
-* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
-* failed with a seqid incrementing error -
-* see comments nfs_fs.h:seqid_mutating_error()
-*/
-void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
+ * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
+ * failed with a seqid incrementing error -
+ * see comments nfs_fs.h:seqid_mutating_error()
+ */
+static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
 {
-	if (status == NFS_OK || seqid_mutating_err(-status))
-		sp->so_seqid++;
-	/* If the server returns BAD_SEQID, unhash state_owner here */
-	if (status == -NFS4ERR_BAD_SEQID)
+	switch (status) {
+		case 0:
+			break;
+		case -NFS4ERR_BAD_SEQID:
+		case -NFS4ERR_STALE_CLIENTID:
+		case -NFS4ERR_STALE_STATEID:
+		case -NFS4ERR_BAD_STATEID:
+		case -NFS4ERR_BADXDR:
+		case -NFS4ERR_RESOURCE:
+		case -NFS4ERR_NOFILEHANDLE:
+			/* Non-seqid mutating errors */
+			return;
+	};
+	/*
+	 * Note: no locking needed as we are guaranteed to be first
+	 * on the sequence list
+	 */
+	seqid->sequence->counter++;
+}
+
+void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
+{
+	if (status == -NFS4ERR_BAD_SEQID) {
+		struct nfs4_state_owner *sp = container_of(seqid->sequence,
+				struct nfs4_state_owner, so_seqid);
 		nfs4_drop_state_owner(sp);
+	}
+	return nfs_increment_seqid(status, seqid);
+}
+
+/*
+ * Increment the seqid if the LOCK/LOCKU succeeded, or
+ * failed with a seqid incrementing error -
+ * see comments nfs_fs.h:seqid_mutating_error()
+ */
+void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
+{
+	return nfs_increment_seqid(status, seqid);
+}
+
+int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
+{
+	struct rpc_sequence *sequence = seqid->sequence->sequence;
+	int status = 0;
+
+	if (sequence->list.next == &seqid->list)
+		goto out;
+	spin_lock(&sequence->lock);
+	if (!list_empty(&sequence->list)) {
+		rpc_sleep_on(&sequence->wait, task, NULL, NULL);
+		status = -EAGAIN;
+	} else
+		list_add(&seqid->list, &sequence->list);
+	spin_unlock(&sequence->lock);
+out:
+	return status;
 }
 
 static int reclaimer(void *);
@@ -791,8 +859,6 @@
 		if (state->state == 0)
 			continue;
 		status = ops->recover_open(sp, state);
-		list_for_each_entry(lock, &state->lock_states, ls_locks)
-			lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
 		if (status >= 0) {
 			status = nfs4_reclaim_locks(ops, state);
 			if (status < 0)
@@ -831,6 +897,28 @@
 	return status;
 }
 
+static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
+{
+	struct nfs4_state_owner *sp;
+	struct nfs4_state *state;
+	struct nfs4_lock_state *lock;
+
+	/* Reset all sequence ids to zero */
+	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+		sp->so_seqid.counter = 0;
+		sp->so_seqid.flags = 0;
+		spin_lock(&sp->so_lock);
+		list_for_each_entry(state, &sp->so_states, open_states) {
+			list_for_each_entry(lock, &state->lock_states, ls_locks) {
+				lock->ls_seqid.counter = 0;
+				lock->ls_seqid.flags = 0;
+				lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
+			}
+		}
+		spin_unlock(&sp->so_lock);
+	}
+}
+
 static int reclaimer(void *ptr)
 {
 	struct reclaimer_args *args = (struct reclaimer_args *)ptr;
@@ -864,6 +952,7 @@
 		default:
 			ops = &nfs4_network_partition_recovery_ops;
 	};
+	nfs4_state_mark_reclaim(clp);
 	status = __nfs4_init_client(clp);
 	if (status)
 		goto out_error;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 6c564ef..fbbace8 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -95,6 +95,8 @@
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
 #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
+#define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
+#define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
 #define encode_fsinfo_maxsz	(op_encode_hdr_maxsz + 2)
 #define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + 11)
 #define encode_renew_maxsz	(op_encode_hdr_maxsz + 3)
@@ -157,16 +159,20 @@
 				op_decode_hdr_maxsz + 2)
 #define NFS4_enc_write_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
-				op_encode_hdr_maxsz + 8)
+				op_encode_hdr_maxsz + 8 + \
+				encode_getattr_maxsz)
 #define NFS4_dec_write_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
-				op_decode_hdr_maxsz + 4)
+				op_decode_hdr_maxsz + 4 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_commit_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
-				op_encode_hdr_maxsz + 3)
+				op_encode_hdr_maxsz + 3 + \
+				encode_getattr_maxsz)
 #define NFS4_dec_commit_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
-				op_decode_hdr_maxsz + 2)
+				op_decode_hdr_maxsz + 2 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_open_sz        (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 op_encode_hdr_maxsz + \
@@ -196,17 +202,21 @@
 #define NFS4_enc_open_downgrade_sz \
 				(compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + 7)
+                                op_encode_hdr_maxsz + 7 + \
+				encode_getattr_maxsz)
 #define NFS4_dec_open_downgrade_sz \
 				(compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4)
+                                op_decode_hdr_maxsz + 4 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_close_sz       (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + 5)
+                                op_encode_hdr_maxsz + 5 + \
+				encode_getattr_maxsz)
 #define NFS4_dec_close_sz       (compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4)
+                                op_decode_hdr_maxsz + 4 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_setattr_sz     (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 op_encode_hdr_maxsz + 4 + \
@@ -300,30 +310,44 @@
 				decode_getfh_maxsz)
 #define NFS4_enc_remove_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
-				encode_remove_maxsz)
+				encode_remove_maxsz + \
+				encode_getattr_maxsz)
 #define NFS4_dec_remove_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
-				op_decode_hdr_maxsz + 5)
+				op_decode_hdr_maxsz + 5 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_rename_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_savefh_maxsz + \
 				encode_putfh_maxsz + \
-				encode_rename_maxsz)
+				encode_rename_maxsz + \
+				encode_getattr_maxsz + \
+				encode_restorefh_maxsz + \
+				encode_getattr_maxsz)
 #define NFS4_dec_rename_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
 				decode_savefh_maxsz + \
 				decode_putfh_maxsz + \
-				decode_rename_maxsz)
+				decode_rename_maxsz + \
+				decode_getattr_maxsz + \
+				decode_restorefh_maxsz + \
+				decode_getattr_maxsz)
 #define NFS4_enc_link_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_savefh_maxsz + \
 				encode_putfh_maxsz + \
-				encode_link_maxsz)
+				encode_link_maxsz + \
+				decode_getattr_maxsz + \
+				encode_restorefh_maxsz + \
+				decode_getattr_maxsz)
 #define NFS4_dec_link_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
 				decode_savefh_maxsz + \
 				decode_putfh_maxsz + \
-				decode_link_maxsz)
+				decode_link_maxsz + \
+				decode_getattr_maxsz + \
+				decode_restorefh_maxsz + \
+				decode_getattr_maxsz)
 #define NFS4_enc_symlink_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_symlink_maxsz + \
@@ -336,14 +360,20 @@
 				decode_getfh_maxsz)
 #define NFS4_enc_create_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
+				encode_savefh_maxsz + \
 				encode_create_maxsz + \
+				encode_getfh_maxsz + \
 				encode_getattr_maxsz + \
-				encode_getfh_maxsz)
+				encode_restorefh_maxsz + \
+				encode_getattr_maxsz)
 #define NFS4_dec_create_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
+				decode_savefh_maxsz + \
 				decode_create_maxsz + \
+				decode_getfh_maxsz + \
 				decode_getattr_maxsz + \
-				decode_getfh_maxsz)
+				decode_restorefh_maxsz + \
+				decode_getattr_maxsz)
 #define NFS4_enc_pathconf_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_getattr_maxsz)
@@ -602,10 +632,10 @@
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(8+sizeof(arg->stateid.data));
+	RESERVE_SPACE(8+sizeof(arg->stateid->data));
 	WRITE32(OP_CLOSE);
-	WRITE32(arg->seqid);
-	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
+	WRITE32(arg->seqid->sequence->counter);
+	WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
 	
 	return 0;
 }
@@ -729,22 +759,18 @@
 	WRITE64(arg->length);
 	WRITE32(opargs->new_lock_owner);
 	if (opargs->new_lock_owner){
-		struct nfs_open_to_lock *ol = opargs->u.open_lock;
-
 		RESERVE_SPACE(40);
-		WRITE32(ol->open_seqid);
-		WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid));
-		WRITE32(ol->lock_seqid);
-		WRITE64(ol->lock_owner.clientid);
+		WRITE32(opargs->open_seqid->sequence->counter);
+		WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data));
+		WRITE32(opargs->lock_seqid->sequence->counter);
+		WRITE64(opargs->lock_owner.clientid);
 		WRITE32(4);
-		WRITE32(ol->lock_owner.id);
+		WRITE32(opargs->lock_owner.id);
 	}
 	else {
-		struct nfs_exist_lock *el = opargs->u.exist_lock;
-
 		RESERVE_SPACE(20);
-		WRITEMEM(&el->stateid, sizeof(el->stateid));
-		WRITE32(el->seqid);
+		WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data));
+		WRITE32(opargs->lock_seqid->sequence->counter);
 	}
 
 	return 0;
@@ -775,8 +801,8 @@
 	RESERVE_SPACE(44);
 	WRITE32(OP_LOCKU);
 	WRITE32(arg->type);
-	WRITE32(opargs->seqid);
-	WRITEMEM(&opargs->stateid, sizeof(opargs->stateid));
+	WRITE32(opargs->seqid->sequence->counter);
+	WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data));
 	WRITE64(arg->offset);
 	WRITE64(arg->length);
 
@@ -826,7 +852,7 @@
  */
 	RESERVE_SPACE(8);
 	WRITE32(OP_OPEN);
-	WRITE32(arg->seqid);
+	WRITE32(arg->seqid->sequence->counter);
 	encode_share_access(xdr, arg->open_flags);
 	RESERVE_SPACE(16);
 	WRITE64(arg->clientid);
@@ -941,7 +967,7 @@
 	RESERVE_SPACE(8+sizeof(arg->stateid.data));
 	WRITE32(OP_OPEN_CONFIRM);
 	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
-	WRITE32(arg->seqid);
+	WRITE32(arg->seqid->sequence->counter);
 
 	return 0;
 }
@@ -950,10 +976,10 @@
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(8+sizeof(arg->stateid.data));
+	RESERVE_SPACE(8+sizeof(arg->stateid->data));
 	WRITE32(OP_OPEN_DOWNGRADE);
-	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
-	WRITE32(arg->seqid);
+	WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
+	WRITE32(arg->seqid->sequence->counter);
 	encode_share_access(xdr, arg->open_flags);
 	return 0;
 }
@@ -1117,6 +1143,17 @@
 }
 
 static int
+encode_restorefh(struct xdr_stream *xdr)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	WRITE32(OP_RESTOREFH);
+
+	return 0;
+}
+
+static int
 encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
 {
 	uint32_t *p;
@@ -1296,14 +1333,18 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 2,
+		.nops = 3,
 	};
 	int status;
 
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_compound_hdr(&xdr, &hdr);
-	if ((status = encode_putfh(&xdr, args->fh)) == 0)
-		status = encode_remove(&xdr, args->name);
+	if ((status = encode_putfh(&xdr, args->fh)) != 0)
+		goto out;
+	if ((status = encode_remove(&xdr, args->name)) != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
+out:
 	return status;
 }
 
@@ -1314,7 +1355,7 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 4,
+		.nops = 7,
 	};
 	int status;
 
@@ -1326,7 +1367,13 @@
 		goto out;
 	if ((status = encode_putfh(&xdr, args->new_dir)) != 0)
 		goto out;
-	status = encode_rename(&xdr, args->old_name, args->new_name);
+	if ((status = encode_rename(&xdr, args->old_name, args->new_name)) != 0)
+		goto out;
+	if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+		goto out;
+	if ((status = encode_restorefh(&xdr)) != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1338,7 +1385,7 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 4,
+		.nops = 7,
 	};
 	int status;
 
@@ -1350,7 +1397,13 @@
 		goto out;
 	if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
 		goto out;
-	status = encode_link(&xdr, args->name);
+	if ((status = encode_link(&xdr, args->name)) != 0)
+		goto out;
+	if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+		goto out;
+	if ((status = encode_restorefh(&xdr)) != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1362,7 +1415,7 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 4,
+		.nops = 7,
 	};
 	int status;
 
@@ -1370,10 +1423,16 @@
 	encode_compound_hdr(&xdr, &hdr);
 	if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
 		goto out;
+	if ((status = encode_savefh(&xdr)) != 0)
+		goto out;
 	if ((status = encode_create(&xdr, args)) != 0)
 		goto out;
 	if ((status = encode_getfh(&xdr)) != 0)
 		goto out;
+	if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+		goto out;
+	if ((status = encode_restorefh(&xdr)) != 0)
+		goto out;
 	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
@@ -1412,7 +1471,7 @@
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr = {
-                .nops   = 2,
+                .nops   = 3,
         };
         int status;
 
@@ -1422,6 +1481,9 @@
         if(status)
                 goto out;
         status = encode_close(&xdr, args);
+	if (status != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
         return status;
 }
@@ -1433,15 +1495,21 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 4,
+		.nops = 7,
 	};
 	int status;
 
+	status = nfs_wait_on_sequence(args->seqid, req->rq_task);
+	if (status != 0)
+		goto out;
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_compound_hdr(&xdr, &hdr);
 	status = encode_putfh(&xdr, args->fh);
 	if (status)
 		goto out;
+	status = encode_savefh(&xdr);
+	if (status)
+		goto out;
 	status = encode_open(&xdr, args);
 	if (status)
 		goto out;
@@ -1449,6 +1517,12 @@
 	if (status)
 		goto out;
 	status = encode_getfattr(&xdr, args->bitmask);
+	if (status)
+		goto out;
+	status = encode_restorefh(&xdr);
+	if (status)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1464,6 +1538,9 @@
 	};
 	int status;
 
+	status = nfs_wait_on_sequence(args->seqid, req->rq_task);
+	if (status != 0)
+		goto out;
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_compound_hdr(&xdr, &hdr);
 	status = encode_putfh(&xdr, args->fh);
@@ -1485,6 +1562,9 @@
 	};
 	int status;
 
+	status = nfs_wait_on_sequence(args->seqid, req->rq_task);
+	if (status != 0)
+		goto out;
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_compound_hdr(&xdr, &hdr);
 	status = encode_putfh(&xdr, args->fh);
@@ -1502,7 +1582,7 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops	= 2,
+		.nops	= 3,
 	};
 	int status;
 
@@ -1512,6 +1592,9 @@
 	if (status)
 		goto out;
 	status = encode_open_downgrade(&xdr, args);
+	if (status != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1525,8 +1608,15 @@
 	struct compound_hdr hdr = {
 		.nops   = 2,
 	};
+	struct nfs_lock_opargs *opargs = args->u.lock;
 	int status;
 
+	status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task);
+	if (status != 0)
+		goto out;
+	/* Do we need to do an open_to_lock_owner? */
+	if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)
+		opargs->new_lock_owner = 0;
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_compound_hdr(&xdr, &hdr);
 	status = encode_putfh(&xdr, args->fh);
@@ -1713,7 +1803,7 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 2,
+		.nops = 3,
 	};
 	int status;
 
@@ -1723,6 +1813,9 @@
 	if (status)
 		goto out;
 	status = encode_write(&xdr, args);
+	if (status)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1734,7 +1827,7 @@
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops = 2,
+		.nops = 3,
 	};
 	int status;
 
@@ -1744,6 +1837,9 @@
 	if (status)
 		goto out;
 	status = encode_commit(&xdr, args);
+	if (status)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -2670,8 +2766,7 @@
 		goto xdr_error;
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-	if (status != 0)
-		printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+	dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
 	return status;
 }
 	
@@ -2704,8 +2799,7 @@
 
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-	if (status != 0)
-		printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+	dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
 	return status;
 }
 
@@ -2730,8 +2824,7 @@
 
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-	if (status != 0)
-		printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+	dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
 	return status;
 }
 
@@ -2787,13 +2880,10 @@
 		goto xdr_error;
 	if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
 		goto xdr_error;
-	if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) {
+	if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
 		fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
-		fattr->timestamp = jiffies;
-	}
 xdr_error:
-	if (status != 0)
-		printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+	dprintk("%s: xdr returned %d\n", __FUNCTION__, -status);
 	return status;
 }
 
@@ -2826,8 +2916,7 @@
 
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
-	if (status != 0)
-		printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
+	dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status);
 	return status;
 }
 
@@ -2890,8 +2979,8 @@
 
 	status = decode_op_hdr(xdr, OP_LOCK);
 	if (status == 0) {
-		READ_BUF(sizeof(nfs4_stateid));
-		COPYMEM(&res->u.stateid, sizeof(res->u.stateid));
+		READ_BUF(sizeof(res->u.stateid.data));
+		COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
 	} else if (status == -NFS4ERR_DENIED)
 		return decode_lock_denied(xdr, &res->u.denied);
 	return status;
@@ -2913,8 +3002,8 @@
 
 	status = decode_op_hdr(xdr, OP_LOCKU);
 	if (status == 0) {
-		READ_BUF(sizeof(nfs4_stateid));
-		COPYMEM(&res->u.stateid, sizeof(res->u.stateid));
+		READ_BUF(sizeof(res->u.stateid.data));
+		COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
 	}
 	return status;
 }
@@ -2994,7 +3083,7 @@
         p += bmlen;
 	return decode_delegation(xdr, res);
 xdr_error:
-	printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__);
+	dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
 	return -EIO;
 }
 
@@ -3208,6 +3297,12 @@
 	return decode_op_hdr(xdr, OP_RENEW);
 }
 
+static int
+decode_restorefh(struct xdr_stream *xdr)
+{
+	return decode_op_hdr(xdr, OP_RESTOREFH);
+}
+
 static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
 		size_t *acl_len)
 {
@@ -3243,7 +3338,8 @@
 		if (attrlen <= *acl_len)
 			xdr_read_pages(xdr, attrlen);
 		*acl_len = attrlen;
-	}
+	} else
+		status = -EOPNOTSUPP;
 
 out:
 	return status;
@@ -3352,6 +3448,9 @@
         if (status)
                 goto out;
         status = decode_open_downgrade(&xdr, res);
+	if (status != 0)
+		goto out;
+	decode_getfattr(&xdr, res->fattr, res->server);
 out:
         return status;
 }
@@ -3424,7 +3523,7 @@
 /*
  * Decode REMOVE response
  */
-static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
+static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_remove_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3433,8 +3532,11 @@
 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
 	if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
 		goto out;
-	if ((status = decode_putfh(&xdr)) == 0)
-		status = decode_remove(&xdr, cinfo);
+	if ((status = decode_putfh(&xdr)) != 0)
+		goto out;
+	if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
+		goto out;
+	decode_getfattr(&xdr, res->dir_attr, res->server);
 out:
 	return status;
 }
@@ -3457,7 +3559,14 @@
 		goto out;
 	if ((status = decode_putfh(&xdr)) != 0)
 		goto out;
-	status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo);
+	if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
+		goto out;
+	/* Current FH is target directory */
+	if (decode_getfattr(&xdr, res->new_fattr, res->server) != 0)
+		goto out;
+	if ((status = decode_restorefh(&xdr)) != 0)
+		goto out;
+	decode_getfattr(&xdr, res->old_fattr, res->server);
 out:
 	return status;
 }
@@ -3465,7 +3574,7 @@
 /*
  * Decode LINK response
  */
-static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
+static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -3480,7 +3589,17 @@
 		goto out;
 	if ((status = decode_putfh(&xdr)) != 0)
 		goto out;
-	status = decode_link(&xdr, cinfo);
+	if ((status = decode_link(&xdr, &res->cinfo)) != 0)
+		goto out;
+	/*
+	 * Note order: OP_LINK leaves the directory as the current
+	 *             filehandle.
+	 */
+	if (decode_getfattr(&xdr, res->dir_attr, res->server) != 0)
+		goto out;
+	if ((status = decode_restorefh(&xdr)) != 0)
+		goto out;
+	decode_getfattr(&xdr, res->fattr, res->server);
 out:
 	return status;
 }
@@ -3499,13 +3618,17 @@
 		goto out;
 	if ((status = decode_putfh(&xdr)) != 0)
 		goto out;
+	if ((status = decode_savefh(&xdr)) != 0)
+		goto out;
 	if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
 		goto out;
 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	status = decode_getfattr(&xdr, res->fattr, res->server);
-	if (status == NFS4ERR_DELAY)
-		status = 0;
+	if (decode_getfattr(&xdr, res->fattr, res->server) != 0)
+		goto out;
+	if ((status = decode_restorefh(&xdr)) != 0)
+		goto out;
+	decode_getfattr(&xdr, res->dir_fattr, res->server);
 out:
 	return status;
 }
@@ -3623,6 +3746,15 @@
         if (status)
                 goto out;
         status = decode_close(&xdr, res);
+	if (status != 0)
+		goto out;
+	/*
+	 * Note: Server may do delete on close for this file
+	 * 	in which case the getattr call will fail with
+	 * 	an ESTALE error. Shouldn't be a problem,
+	 * 	though, since fattr->valid will remain unset.
+	 */
+	decode_getfattr(&xdr, res->fattr, res->server);
 out:
         return status;
 }
@@ -3643,15 +3775,20 @@
         status = decode_putfh(&xdr);
         if (status)
                 goto out;
+        status = decode_savefh(&xdr);
+	if (status)
+		goto out;
         status = decode_open(&xdr, res);
         if (status)
                 goto out;
 	status = decode_getfh(&xdr, &res->fh);
         if (status)
 		goto out;
-	status = decode_getfattr(&xdr, res->f_attr, res->server);
-	if (status == NFS4ERR_DELAY)
-		status = 0;
+	if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
+		goto out;
+	if ((status = decode_restorefh(&xdr)) != 0)
+		goto out;
+	decode_getfattr(&xdr, res->dir_attr, res->server);
 out:
         return status;
 }
@@ -3869,6 +4006,9 @@
 	if (status)
 		goto out;
 	status = decode_write(&xdr, res);
+	if (status)
+		goto out;
+	decode_getfattr(&xdr, res->fattr, res->server);
 	if (!status)
 		status = res->count;
 out:
@@ -3892,6 +4032,9 @@
 	if (status)
 		goto out;
 	status = decode_commit(&xdr, res);
+	if (status)
+		goto out;
+	decode_getfattr(&xdr, res->fattr, res->server);
 out:
 	return status;
 }
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index be23c3f..a48a003 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -61,7 +61,7 @@
 	int status;
 
 	dprintk("%s: call getattr\n", __FUNCTION__);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0);
 	dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
 	if (status)
@@ -93,7 +93,7 @@
 	int	status;
 
 	dprintk("NFS call  getattr\n");
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call(server->client, NFSPROC_GETATTR,
 				fhandle, fattr, 0);
 	dprintk("NFS reply getattr: %d\n", status);
@@ -112,7 +112,7 @@
 	int	status;
 
 	dprintk("NFS call  setattr\n");
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
 	if (status == 0)
 		nfs_setattr_update_inode(inode, sattr);
@@ -136,7 +136,7 @@
 	int			status;
 
 	dprintk("NFS call  lookup %s\n", name->name);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
@@ -174,7 +174,7 @@
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
@@ -203,10 +203,10 @@
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0) {
-		nfs_refresh_inode(inode, fattr);
+		nfs_post_op_update_inode(inode, fattr);
 		wdata->res.count = wdata->args.count;
 		wdata->verf.committed = NFS_FILE_SYNC;
 	}
@@ -216,7 +216,7 @@
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		int flags)
+		int flags, struct nameidata *nd)
 {
 	struct nfs_fh		fhandle;
 	struct nfs_fattr	fattr;
@@ -232,7 +232,7 @@
 	};
 	int			status;
 
-	fattr.valid = 0;
+	nfs_fattr_init(&fattr);
 	dprintk("NFS call  create %s\n", dentry->d_name.name);
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
 	if (status == 0)
@@ -273,12 +273,13 @@
 		sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
 	}
 
-	fattr.valid = 0;
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+	nfs_mark_for_revalidate(dir);
 
 	if (status == -EINVAL && S_ISFIFO(mode)) {
 		sattr->ia_mode = mode;
-		fattr.valid = 0;
+		nfs_fattr_init(&fattr);
 		status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
 	}
 	if (status == 0)
@@ -305,6 +306,7 @@
 
 	dprintk("NFS call  remove %s\n", name->name);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	nfs_mark_for_revalidate(dir);
 
 	dprintk("NFS reply remove: %d\n", status);
 	return status;
@@ -331,8 +333,10 @@
 {
 	struct rpc_message *msg = &task->tk_msg;
 	
-	if (msg->rpc_argp)
+	if (msg->rpc_argp) {
+		nfs_mark_for_revalidate(dir->d_inode);
 		kfree(msg->rpc_argp);
+	}
 	return 0;
 }
 
@@ -352,6 +356,8 @@
 
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
 	status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0);
+	nfs_mark_for_revalidate(old_dir);
+	nfs_mark_for_revalidate(new_dir);
 	dprintk("NFS reply rename: %d\n", status);
 	return status;
 }
@@ -369,6 +375,7 @@
 
 	dprintk("NFS call  link %s\n", name->name);
 	status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0);
+	nfs_mark_for_revalidate(dir);
 	dprintk("NFS reply link: %d\n", status);
 	return status;
 }
@@ -391,9 +398,10 @@
 	if (path->len > NFS2_MAXPATHLEN)
 		return -ENAMETOOLONG;
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
-	fattr->valid = 0;
+	nfs_fattr_init(fattr);
 	fhandle->size = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
+	nfs_mark_for_revalidate(dir);
 	dprintk("NFS reply symlink: %d\n", status);
 	return status;
 }
@@ -416,8 +424,9 @@
 	int			status;
 
 	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
-	fattr.valid = 0;
+	nfs_fattr_init(&fattr);
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
+	nfs_mark_for_revalidate(dir);
 	if (status == 0)
 		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	dprintk("NFS reply mkdir: %d\n", status);
@@ -436,6 +445,7 @@
 
 	dprintk("NFS call  rmdir %s\n", name->name);
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0);
+	nfs_mark_for_revalidate(dir);
 	dprintk("NFS reply rmdir: %d\n", status);
 	return status;
 }
@@ -484,7 +494,7 @@
 	int	status;
 
 	dprintk("NFS call  statfs\n");
-	stat->fattr->valid = 0;
+	nfs_fattr_init(stat->fattr);
 	status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
 	dprintk("NFS reply statfs: %d\n", status);
 	if (status)
@@ -507,7 +517,7 @@
 	int	status;
 
 	dprintk("NFS call  fsinfo\n");
-	info->fattr->valid = 0;
+	nfs_fattr_init(info->fattr);
 	status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
 	dprintk("NFS reply fsinfo: %d\n", status);
 	if (status)
@@ -579,7 +589,7 @@
 	struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
 
 	if (task->tk_status >= 0)
-		nfs_refresh_inode(data->inode, data->res.fattr);
+		nfs_post_op_update_inode(data->inode, data->res.fattr);
 	nfs_writeback_done(task);
 }
 
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 9758ebd..43b03b1 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -215,6 +215,7 @@
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
 	data->res.eof     = 0;
+	nfs_fattr_init(&data->fattr);
 
 	NFS_PROTO(inode)->read_setup(data);
 
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 5130eda..819a65f 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -870,6 +870,7 @@
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
 	data->res.verf    = &data->verf;
+	nfs_fattr_init(&data->fattr);
 
 	NFS_PROTO(inode)->write_setup(data, how);
 
@@ -1237,6 +1238,7 @@
 	data->res.count   = 0;
 	data->res.fattr   = &data->fattr;
 	data->res.verf    = &data->verf;
+	nfs_fattr_init(&data->fattr);
 	
 	NFS_PROTO(inode)->commit_setup(data, how);
 
diff --git a/fs/open.c b/fs/open.c
index f0d90cf..8d06ec9 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -739,7 +739,8 @@
 }
 
 static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-					int flags, struct file *f)
+					int flags, struct file *f,
+					int (*open)(struct inode *, struct file *))
 {
 	struct inode *inode;
 	int error;
@@ -761,11 +762,14 @@
 	f->f_op = fops_get(inode->i_fop);
 	file_move(f, &inode->i_sb->s_files);
 
-	if (f->f_op && f->f_op->open) {
-		error = f->f_op->open(inode,f);
+	if (!open && f->f_op)
+		open = f->f_op->open;
+	if (open) {
+		error = open(inode, f);
 		if (error)
 			goto cleanup_all;
 	}
+
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
 	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
@@ -814,28 +818,75 @@
 {
 	int namei_flags, error;
 	struct nameidata nd;
-	struct file *f;
 
 	namei_flags = flags;
 	if ((namei_flags+1) & O_ACCMODE)
 		namei_flags++;
-	if (namei_flags & O_TRUNC)
-		namei_flags |= 2;
-
-	error = -ENFILE;
-	f = get_empty_filp();
-	if (f == NULL)
-		return ERR_PTR(error);
 
 	error = open_namei(filename, namei_flags, mode, &nd);
 	if (!error)
-		return __dentry_open(nd.dentry, nd.mnt, flags, f);
+		return nameidata_to_filp(&nd, flags);
 
-	put_filp(f);
 	return ERR_PTR(error);
 }
 EXPORT_SYMBOL(filp_open);
 
+/**
+ * lookup_instantiate_filp - instantiates the open intent filp
+ * @nd: pointer to nameidata
+ * @dentry: pointer to dentry
+ * @open: open callback
+ *
+ * Helper for filesystems that want to use lookup open intents and pass back
+ * a fully instantiated struct file to the caller.
+ * This function is meant to be called from within a filesystem's
+ * lookup method.
+ * Note that in case of error, nd->intent.open.file is destroyed, but the
+ * path information remains valid.
+ * If the open callback is set to NULL, then the standard f_op->open()
+ * filesystem callback is substituted.
+ */
+struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+		int (*open)(struct inode *, struct file *))
+{
+	if (IS_ERR(nd->intent.open.file))
+		goto out;
+	if (IS_ERR(dentry))
+		goto out_err;
+	nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt),
+					     nd->intent.open.flags - 1,
+					     nd->intent.open.file,
+					     open);
+out:
+	return nd->intent.open.file;
+out_err:
+	release_open_intent(nd);
+	nd->intent.open.file = (struct file *)dentry;
+	goto out;
+}
+EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+
+/**
+ * nameidata_to_filp - convert a nameidata to an open filp.
+ * @nd: pointer to nameidata
+ * @flags: open flags
+ *
+ * Note that this function destroys the original nameidata
+ */
+struct file *nameidata_to_filp(struct nameidata *nd, int flags)
+{
+	struct file *filp;
+
+	/* Pick up the filp from the open intent */
+	filp = nd->intent.open.file;
+	/* Has the filesystem initialised the file for us? */
+	if (filp->f_dentry == NULL)
+		filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
+	else
+		path_release(nd);
+	return filp;
+}
+
 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
 {
 	int error;
@@ -846,7 +897,7 @@
 	if (f == NULL)
 		return ERR_PTR(error);
 
-	return __dentry_open(dentry, mnt, flags, f);
+	return __dentry_open(dentry, mnt, flags, f, NULL);
 }
 EXPORT_SYMBOL(dentry_open);
 
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 77e178f..9c06c54 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -192,6 +192,7 @@
 struct part_attribute {
 	struct attribute attr;
 	ssize_t (*show)(struct hd_struct *,char *);
+	ssize_t (*store)(struct hd_struct *,const char *, size_t);
 };
 
 static ssize_t 
@@ -201,14 +202,33 @@
 	struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
 	ssize_t ret = 0;
 	if (part_attr->show)
-		ret = part_attr->show(p,page);
+		ret = part_attr->show(p, page);
+	return ret;
+}
+static ssize_t
+part_attr_store(struct kobject * kobj, struct attribute * attr,
+		const char *page, size_t count)
+{
+	struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
+	struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
+	ssize_t ret = 0;
+
+	if (part_attr->store)
+		ret = part_attr->store(p, page, count);
 	return ret;
 }
 
 static struct sysfs_ops part_sysfs_ops = {
 	.show	=	part_attr_show,
+	.store	=	part_attr_store,
 };
 
+static ssize_t part_uevent_store(struct hd_struct * p,
+				 const char *page, size_t count)
+{
+	kobject_hotplug(&p->kobj, KOBJ_ADD);
+	return count;
+}
 static ssize_t part_dev_read(struct hd_struct * p, char *page)
 {
 	struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
@@ -229,6 +249,10 @@
 		       p->reads, (unsigned long long)p->read_sectors,
 		       p->writes, (unsigned long long)p->write_sectors);
 }
+static struct part_attribute part_attr_uevent = {
+	.attr = {.name = "uevent", .mode = S_IWUSR },
+	.store	= part_uevent_store
+};
 static struct part_attribute part_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
 	.show	= part_dev_read
@@ -247,6 +271,7 @@
 };
 
 static struct attribute * default_attrs[] = {
+	&part_attr_uevent.attr,
 	&part_attr_dev.attr,
 	&part_attr_start.attr,
 	&part_attr_size.attr,
@@ -430,7 +455,7 @@
 	disk->flags &= ~GENHD_FL_UP;
 	unlink_gendisk(disk);
 	disk_stat_set_all(disk, 0);
-	disk->stamp = disk->stamp_idle = 0;
+	disk->stamp = 0;
 
 	devfs_remove_disk(disk);
 
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d84eeca..3e1239e 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -438,7 +438,7 @@
 		jiffies_to_clock_t(it_real_value),
 		start_time,
 		vsize,
-		mm ? get_mm_counter(mm, rss) : 0, /* you might want to shift this left 3 */
+		mm ? get_mm_rss(mm) : 0,
 	        rsslim,
 		mm ? mm->start_code : 0,
 		mm ? mm->end_code : 0,
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a8c344..b638fb5 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -533,7 +533,7 @@
 	 */
 	file_list_lock();
 	list_for_each(p, &sb->s_files) {
-		struct file * filp = list_entry(p, struct file, f_list);
+		struct file * filp = list_entry(p, struct file, f_u.fu_list);
 		struct dentry * dentry = filp->f_dentry;
 		struct inode * inode;
 		struct file_operations *fops;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index effa6c0..e6a818a 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -156,10 +156,13 @@
 
 	WARN_ON(de && de->deleted);
 
+	if (de != NULL && !try_module_get(de->owner))
+		goto out_mod;
+
 	inode = iget(sb, ino);
 	if (!inode)
-		goto out_fail;
-	
+		goto out_ino;
+
 	PROC_I(inode)->pde = de;
 	if (de) {
 		if (de->mode) {
@@ -171,20 +174,20 @@
 			inode->i_size = de->size;
 		if (de->nlink)
 			inode->i_nlink = de->nlink;
-		if (!try_module_get(de->owner))
-			goto out_fail;
 		if (de->proc_iops)
 			inode->i_op = de->proc_iops;
 		if (de->proc_fops)
 			inode->i_fop = de->proc_fops;
 	}
 
-out:
 	return inode;
 
-out_fail:
+out_ino:
+	if (de != NULL)
+		module_put(de->owner);
+out_mod:
 	de_put(de);
-	goto out;
+	return NULL;
 }			
 
 int proc_fill_super(struct super_block *s, void *data, int silent)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c7ef3e4..d2fa420 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -14,22 +14,41 @@
 char *task_mem(struct mm_struct *mm, char *buffer)
 {
 	unsigned long data, text, lib;
+	unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
+
+	/*
+	 * Note: to minimize their overhead, mm maintains hiwater_vm and
+	 * hiwater_rss only when about to *lower* total_vm or rss.  Any
+	 * collector of these hiwater stats must therefore get total_vm
+	 * and rss too, which will usually be the higher.  Barriers? not
+	 * worth the effort, such snapshots can always be inconsistent.
+	 */
+	hiwater_vm = total_vm = mm->total_vm;
+	if (hiwater_vm < mm->hiwater_vm)
+		hiwater_vm = mm->hiwater_vm;
+	hiwater_rss = total_rss = get_mm_rss(mm);
+	if (hiwater_rss < mm->hiwater_rss)
+		hiwater_rss = mm->hiwater_rss;
 
 	data = mm->total_vm - mm->shared_vm - mm->stack_vm;
 	text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
 	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
 	buffer += sprintf(buffer,
+		"VmPeak:\t%8lu kB\n"
 		"VmSize:\t%8lu kB\n"
 		"VmLck:\t%8lu kB\n"
+		"VmHWM:\t%8lu kB\n"
 		"VmRSS:\t%8lu kB\n"
 		"VmData:\t%8lu kB\n"
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
 		"VmLib:\t%8lu kB\n"
 		"VmPTE:\t%8lu kB\n",
-		(mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
+		hiwater_vm << (PAGE_SHIFT-10),
+		(total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
-		get_mm_counter(mm, rss) << (PAGE_SHIFT-10),
+		hiwater_rss << (PAGE_SHIFT-10),
+		total_rss << (PAGE_SHIFT-10),
 		data << (PAGE_SHIFT-10),
 		mm->stack_vm << (PAGE_SHIFT-10), text, lib,
 		(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
@@ -44,13 +63,11 @@
 int task_statm(struct mm_struct *mm, int *shared, int *text,
 	       int *data, int *resident)
 {
-	int rss = get_mm_counter(mm, rss);
-
-	*shared = rss - get_mm_counter(mm, anon_rss);
+	*shared = get_mm_counter(mm, file_rss);
 	*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
 								>> PAGE_SHIFT;
 	*data = mm->total_vm - mm->shared_vm;
-	*resident = rss;
+	*resident = *shared + get_mm_counter(mm, anon_rss);
 	return mm->total_vm;
 }
 
@@ -186,13 +203,14 @@
 				struct mem_size_stats *mss)
 {
 	pte_t *pte, ptent;
+	spinlock_t *ptl;
 	unsigned long pfn;
 	struct page *page;
 
-	pte = pte_offset_map(pmd, addr);
+	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	do {
 		ptent = *pte;
-		if (pte_none(ptent) || !pte_present(ptent))
+		if (!pte_present(ptent))
 			continue;
 
 		mss->resident += PAGE_SIZE;
@@ -213,8 +231,8 @@
 				mss->private_clean += PAGE_SIZE;
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
-	cond_resched_lock(&vma->vm_mm->page_table_lock);
+	pte_unmap_unlock(pte - 1, ptl);
+	cond_resched();
 }
 
 static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud,
@@ -268,17 +286,11 @@
 static int show_smap(struct seq_file *m, void *v)
 {
 	struct vm_area_struct *vma = v;
-	struct mm_struct *mm = vma->vm_mm;
 	struct mem_size_stats mss;
 
 	memset(&mss, 0, sizeof mss);
-
-	if (mm) {
-		spin_lock(&mm->page_table_lock);
+	if (vma->vm_mm)
 		smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss);
-		spin_unlock(&mm->page_table_lock);
-	}
-
 	return show_map_internal(m, v, &mss);
 }
 
@@ -407,7 +419,6 @@
 	for_each_node(i)
 		md->node[i] =0;
 
-	spin_lock(&mm->page_table_lock);
  	for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) {
 		page = follow_page(mm, vaddr, 0);
 		if (page) {
@@ -422,8 +433,8 @@
 				md->anon++;
 			md->node[page_to_nid(page)]++;
 		}
+		cond_resched();
 	}
-	spin_unlock(&mm->page_table_lock);
 	return md;
 }
 
@@ -469,7 +480,7 @@
 		seq_printf(m, " interleave={");
 		first = 1;
 		for_each_node(n) {
-			if (test_bit(n, pol->v.nodes)) {
+			if (node_isset(n, pol->v.nodes)) {
 				if (!first)
 					seq_putc(m,',');
 				else
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index 2706e2a..4582988 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -2022,7 +2022,7 @@
 }
 
 #ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, int flags, struct super_block *s)
+void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s)
 {
 	void *vp;
 	static size_t malloced;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d76ee6c..5f82352 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2842,7 +2842,7 @@
  * even in -o notail mode, we can't be sure an old mount without -o notail
  * didn't create files with tails.
  */
-static int reiserfs_releasepage(struct page *page, int unused_gfp_flags)
+static int reiserfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
 {
 	struct inode *inode = page->mapping->host;
 	struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 44b02fc..42afb5b 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1024,12 +1024,8 @@
 				strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
 				*mount_options |= 1 << REISERFS_QUOTA;
 			} else {
-				if (REISERFS_SB(s)->s_qf_names[qtype]) {
-					kfree(REISERFS_SB(s)->
-					      s_qf_names[qtype]);
-					REISERFS_SB(s)->s_qf_names[qtype] =
-					    NULL;
-				}
+				kfree(REISERFS_SB(s)->s_qf_names[qtype]);
+				REISERFS_SB(s)->s_qf_names[qtype] = NULL;
 			}
 		}
 		if (c == 'f') {
@@ -1158,11 +1154,10 @@
 	if (!reiserfs_parse_options
 	    (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) {
 #ifdef CONFIG_QUOTA
-		for (i = 0; i < MAXQUOTAS; i++)
-			if (REISERFS_SB(s)->s_qf_names[i]) {
-				kfree(REISERFS_SB(s)->s_qf_names[i]);
-				REISERFS_SB(s)->s_qf_names[i] = NULL;
-			}
+		for (i = 0; i < MAXQUOTAS; i++) {
+			kfree(REISERFS_SB(s)->s_qf_names[i]);
+			REISERFS_SB(s)->s_qf_names[i] = NULL;
+		}
 #endif
 		return -EINVAL;
 	}
@@ -1940,13 +1935,11 @@
 		brelse(SB_BUFFER_WITH_SB(s));
 #ifdef CONFIG_QUOTA
 	for (j = 0; j < MAXQUOTAS; j++) {
-		if (sbi->s_qf_names[j])
-			kfree(sbi->s_qf_names[j]);
+		kfree(sbi->s_qf_names[j]);
+		sbi->s_qf_names[j] = NULL;
 	}
 #endif
-	if (sbi != NULL) {
-		kfree(sbi);
-	}
+	kfree(sbi);
 
 	s->s_fs_info = NULL;
 	return errval;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 87ac9dc..72e1207 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -453,7 +453,7 @@
 	struct page *page;
 	/* We can deadlock if we try to free dentries,
 	   and an unlink/rmdir has just occured - GFP_NOFS avoids this */
-	mapping->flags = (mapping->flags & ~__GFP_BITS_MASK) | GFP_NOFS;
+	mapping_set_gfp_mask(mapping, GFP_NOFS);
 	page = read_cache_page(mapping, n,
 			       (filler_t *) mapping->a_ops->readpage, NULL);
 	if (!IS_ERR(page)) {
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 6703efa..a47ac9a 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -296,8 +296,7 @@
 		}
 	}
 
-	if (value)
-		kfree(value);
+	kfree(value);
 
 	if (!error) {
 		/* Release the old one */
diff --git a/fs/super.c b/fs/super.c
index 6e57ee2..f60155e 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -513,7 +513,7 @@
 	struct file *f;
 
 	file_list_lock();
-	list_for_each_entry(f, &sb->s_files, f_list) {
+	list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
 		if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f))
 			f->f_mode &= ~FMODE_WRITE;
 	}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 1c6f6b5..ef46939 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -621,8 +621,7 @@
 	}
 
 	/* build the entry of long file name */
-	for (cksum = i = 0; i < 11; i++)
-		cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
+	cksum = fat_checksum(msdos_name);
 
 	*nr_slots = usize / 13;
 	for (ps = slots, i = *nr_slots; i > 0; i--, ps++) {
@@ -888,10 +887,10 @@
 {
 	struct buffer_head *dotdot_bh;
 	struct msdos_dir_entry *dotdot_de;
-	loff_t dotdot_i_pos;
 	struct inode *old_inode, *new_inode;
 	struct fat_slot_info old_sinfo, sinfo;
 	struct timespec ts;
+	loff_t dotdot_i_pos, new_i_pos;
 	int err, is_dir, update_dotdot, corrupt = 0;
 
 	old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
@@ -914,31 +913,24 @@
 
 	ts = CURRENT_TIME_SEC;
 	if (new_inode) {
-		err = vfat_find(new_dir, &new_dentry->d_name, &sinfo);
-		if (err)
-			goto out;
-		if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
-			/* WTF??? Cry and fail. */
-			printk(KERN_WARNING "vfat_rename: fs corrupted\n");
-			goto out;
-		}
-
 		if (is_dir) {
 			err = fat_dir_empty(new_inode);
 			if (err)
 				goto out;
 		}
+		new_i_pos = MSDOS_I(new_inode)->i_pos;
 		fat_detach(new_inode);
 	} else {
 		err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
 				     &ts, &sinfo);
 		if (err)
 			goto out;
+		new_i_pos = sinfo.i_pos;
 	}
 	new_dir->i_version++;
 
 	fat_detach(old_inode);
-	fat_attach(old_inode, sinfo.i_pos);
+	fat_attach(old_inode, new_i_pos);
 	if (IS_DIRSYNC(new_dir)) {
 		err = fat_sync_inode(old_inode);
 		if (err)
@@ -1002,7 +994,7 @@
 	fat_detach(old_inode);
 	fat_attach(old_inode, old_sinfo.i_pos);
 	if (new_inode) {
-		fat_attach(new_inode, sinfo.i_pos);
+		fat_attach(new_inode, new_i_pos);
 		if (corrupt)
 			corrupt |= fat_sync_inode(new_inode);
 	} else {
diff --git a/fs/xattr.c b/fs/xattr.c
index 3f9c64b..f6e00c0 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -143,7 +143,7 @@
 	if (size) {
 		if (size > XATTR_SIZE_MAX)
 			size = XATTR_SIZE_MAX;
-		kvalue = kmalloc(size, GFP_KERNEL);
+		kvalue = kzalloc(size, GFP_KERNEL);
 		if (!kvalue)
 			return -ENOMEM;
 	}
@@ -154,11 +154,15 @@
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
 		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
-	else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
-			  sizeof XATTR_SECURITY_PREFIX - 1)) {
+
+	if (!strncmp(kname, XATTR_SECURITY_PREFIX,
+		     sizeof XATTR_SECURITY_PREFIX - 1)) {
 		const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
-		error = security_inode_getsecurity(d->d_inode, suffix, kvalue,
-						   size);
+		int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue,
+						    size, error);
+		/* Security module active: overwrite error value */
+		if (rv != -EOPNOTSUPP)
+			error = rv;
 	}
 	if (error > 0) {
 		if (size && copy_to_user(value, kvalue, error))
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index d2653b5..3c92162 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -45,11 +45,11 @@
 
 
 void *
-kmem_alloc(size_t size, gfp_t flags)
+kmem_alloc(size_t size, unsigned int __nocast flags)
 {
-	int		retries = 0;
-	unsigned int	lflags = kmem_flags_convert(flags);
-	void		*ptr;
+	int	retries = 0;
+	gfp_t	lflags = kmem_flags_convert(flags);
+	void	*ptr;
 
 	do {
 		if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
@@ -67,7 +67,7 @@
 }
 
 void *
-kmem_zalloc(size_t size, gfp_t flags)
+kmem_zalloc(size_t size, unsigned int __nocast flags)
 {
 	void	*ptr;
 
@@ -90,7 +90,7 @@
 
 void *
 kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
-	     gfp_t flags)
+	     unsigned int __nocast flags)
 {
 	void	*new;
 
@@ -105,11 +105,11 @@
 }
 
 void *
-kmem_zone_alloc(kmem_zone_t *zone, gfp_t flags)
+kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
 {
-	int		retries = 0;
-	unsigned int	lflags = kmem_flags_convert(flags);
-	void		*ptr;
+	int	retries = 0;
+	gfp_t	lflags = kmem_flags_convert(flags);
+	void	*ptr;
 
 	do {
 		ptr = kmem_cache_alloc(zone, lflags);
@@ -124,7 +124,7 @@
 }
 
 void *
-kmem_zone_zalloc(kmem_zone_t *zone, gfp_t flags)
+kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags)
 {
 	void	*ptr;
 
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index ee7010f..f4bb78c2 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -81,9 +81,9 @@
 	*(NSTATEP) = *(OSTATEP);	\
 } while (0)
 
-static __inline unsigned int kmem_flags_convert(gfp_t flags)
+static __inline gfp_t kmem_flags_convert(unsigned int __nocast flags)
 {
-	unsigned int	lflags = __GFP_NOWARN;	/* we'll report problems, if need be */
+	gfp_t lflags = __GFP_NOWARN;	/* we'll report problems, if need be */
 
 #ifdef DEBUG
 	if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) {
@@ -125,16 +125,16 @@
 		BUG();
 }
 
-extern void	    *kmem_zone_zalloc(kmem_zone_t *, gfp_t);
-extern void	    *kmem_zone_alloc(kmem_zone_t *, gfp_t);
+extern void	    *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
+extern void	    *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
 
-extern void	    *kmem_alloc(size_t, gfp_t);
-extern void	    *kmem_realloc(void *, size_t, size_t, gfp_t);
-extern void	    *kmem_zalloc(size_t, gfp_t);
+extern void	    *kmem_alloc(size_t, unsigned int __nocast);
+extern void	    *kmem_realloc(void *, size_t, size_t, unsigned int __nocast);
+extern void	    *kmem_zalloc(size_t, unsigned int __nocast);
 extern void         kmem_free(void *, size_t);
 
 typedef struct shrinker *kmem_shaker_t;
-typedef int (*kmem_shake_func_t)(int, unsigned int);
+typedef int (*kmem_shake_func_t)(int, gfp_t);
 
 static __inline kmem_shaker_t
 kmem_shake_register(kmem_shake_func_t sfunc)
@@ -149,7 +149,7 @@
 }
 
 static __inline int
-kmem_shake_allow(unsigned int gfp_mask)
+kmem_shake_allow(gfp_t gfp_mask)
 {
 	return (gfp_mask & __GFP_WAIT);
 }
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index c6c0779..7aa3987 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1296,7 +1296,7 @@
 STATIC int
 linvfs_release_page(
 	struct page		*page,
-	int			gfp_mask)
+	gfp_t			gfp_mask)
 {
 	struct inode		*inode = page->mapping->host;
 	int			dirty, delalloc, unmapped, unwritten;
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index e82cf72..4cd46ab 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -64,7 +64,7 @@
 
 STATIC kmem_cache_t *pagebuf_zone;
 STATIC kmem_shaker_t pagebuf_shake;
-STATIC int xfsbufd_wakeup(int, unsigned int);
+STATIC int xfsbufd_wakeup(int, gfp_t);
 STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
 
 STATIC struct workqueue_struct *xfslogd_workqueue;
@@ -181,8 +181,9 @@
 	size_t		offset,
 	size_t		length)
 {
-	page->private |= page_region_mask(offset, length);
-	if (page->private == ~0UL)
+	set_page_private(page,
+		page_private(page) | page_region_mask(offset, length));
+	if (page_private(page) == ~0UL)
 		SetPageUptodate(page);
 }
 
@@ -194,7 +195,7 @@
 {
 	unsigned long	mask = page_region_mask(offset, length);
 
-	return (mask && (page->private & mask) == mask);
+	return (mask && (page_private(page) & mask) == mask);
 }
 
 /*
@@ -383,7 +384,7 @@
 	size_t			blocksize = bp->pb_target->pbr_bsize;
 	size_t			size = bp->pb_count_desired;
 	size_t			nbytes, offset;
-	int			gfp_mask = pb_to_gfp(flags);
+	gfp_t			gfp_mask = pb_to_gfp(flags);
 	unsigned short		page_count, i;
 	pgoff_t			first;
 	loff_t			end;
@@ -1749,8 +1750,8 @@
 
 STATIC int
 xfsbufd_wakeup(
-	int			priority,
-	unsigned int		mask)
+	int		priority,
+	gfp_t		mask)
 {
 	if (xfsbufd_force_sleep)
 		return 0;
diff --git a/include/asm-alpha/barrier.h b/include/asm-alpha/barrier.h
index 229c83f..681ff58 100644
--- a/include/asm-alpha/barrier.h
+++ b/include/asm-alpha/barrier.h
@@ -1,6 +1,8 @@
 #ifndef __BARRIER_H
 #define __BARRIER_H
 
+#include <asm/compiler.h>
+
 #define mb() \
 __asm__ __volatile__("mb": : :"memory")
 
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index c675f28..680f7ec 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -31,7 +31,7 @@
 #else	/* no PCI - no IOMMU. */
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int gfp);
+			 dma_addr_t *dma_handle, gfp_t gfp);
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 	       enum dma_data_direction direction);
 
diff --git a/include/asm-alpha/rwsem.h b/include/asm-alpha/rwsem.h
index 8e058a6..fafdd4f 100644
--- a/include/asm-alpha/rwsem.h
+++ b/include/asm-alpha/rwsem.h
@@ -262,5 +262,10 @@
 #endif
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_RWSEM_H */
diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
index eb2cbd9..1a6295f 100644
--- a/include/asm-alpha/semaphore.h
+++ b/include/asm-alpha/semaphore.h
@@ -26,9 +26,6 @@
   	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
 }
 
-#define __MUTEX_INITIALIZER(name)			\
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count)		\
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h
index 0e9b7e1..0022279 100644
--- a/include/asm-arm/arch-aaec2000/aaec2000.h
+++ b/include/asm-arm/arch-aaec2000/aaec2000.h
@@ -17,6 +17,16 @@
 #error You must include hardware.h not this file
 #endif /* __ASM_ARCH_HARDWARE_H */
 
+/* Chip selects */
+#define AAEC_CS0	0x00000000
+#define AAEC_CS1	0x10000000
+#define AAEC_CS2	0x20000000
+#define AAEC_CS3	0x30000000
+
+/* Flash */
+#define AAEC_FLASH_BASE	AAEC_CS0
+#define AAEC_FLASH_SIZE	SZ_64M
+
 /* Interrupt controller */
 #define IRQ_BASE	__REG(0x80000500)
 #define IRQ_INTSR	__REG(0x80000500)	/* Int Status Register */
@@ -148,4 +158,50 @@
 #define POWER_STFCLR	__REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
 #define POWER_CLKSET	__REG(0x80000420) /* Clock Speed Control */
 
+/* GPIO Registers */
+#define AAEC_GPIO_PHYS	0x80000e00
+
+#define AAEC_GPIO_PADR		__REG(AAEC_GPIO_PHYS + 0x00)
+#define AAEC_GPIO_PBDR		__REG(AAEC_GPIO_PHYS + 0x04)
+#define AAEC_GPIO_PCDR		__REG(AAEC_GPIO_PHYS + 0x08)
+#define AAEC_GPIO_PDDR		__REG(AAEC_GPIO_PHYS + 0x0c)
+#define AAEC_GPIO_PADDR		__REG(AAEC_GPIO_PHYS + 0x10)
+#define AAEC_GPIO_PBDDR		__REG(AAEC_GPIO_PHYS + 0x14)
+#define AAEC_GPIO_PCDDR		__REG(AAEC_GPIO_PHYS + 0x18)
+#define AAEC_GPIO_PDDDR		__REG(AAEC_GPIO_PHYS + 0x1c)
+#define AAEC_GPIO_PEDR		__REG(AAEC_GPIO_PHYS + 0x20)
+#define AAEC_GPIO_PEDDR		__REG(AAEC_GPIO_PHYS + 0x24)
+#define AAEC_GPIO_KSCAN		__REG(AAEC_GPIO_PHYS + 0x28)
+#define AAEC_GPIO_PINMUX	__REG(AAEC_GPIO_PHYS + 0x2c)
+#define AAEC_GPIO_PFDR		__REG(AAEC_GPIO_PHYS + 0x30)
+#define AAEC_GPIO_PFDDR		__REG(AAEC_GPIO_PHYS + 0x34)
+#define AAEC_GPIO_PGDR		__REG(AAEC_GPIO_PHYS + 0x38)
+#define AAEC_GPIO_PGDDR		__REG(AAEC_GPIO_PHYS + 0x3c)
+#define AAEC_GPIO_PHDR		__REG(AAEC_GPIO_PHYS + 0x40)
+#define AAEC_GPIO_PHDDR		__REG(AAEC_GPIO_PHYS + 0x44)
+#define AAEC_GPIO_RAZ		__REG(AAEC_GPIO_PHYS + 0x48)
+#define AAEC_GPIO_INTTYPE1	__REG(AAEC_GPIO_PHYS + 0x4c)
+#define AAEC_GPIO_INTTYPE2	__REG(AAEC_GPIO_PHYS + 0x50)
+#define AAEC_GPIO_FEOI		__REG(AAEC_GPIO_PHYS + 0x54)
+#define AAEC_GPIO_INTEN		__REG(AAEC_GPIO_PHYS + 0x58)
+#define AAEC_GPIO_INTSTATUS	__REG(AAEC_GPIO_PHYS + 0x5c)
+#define AAEC_GPIO_RAWINTSTATUS	__REG(AAEC_GPIO_PHYS + 0x60)
+#define AAEC_GPIO_DB		__REG(AAEC_GPIO_PHYS + 0x64)
+#define AAEC_GPIO_PAPINDR	__REG(AAEC_GPIO_PHYS + 0x68)
+#define AAEC_GPIO_PBPINDR	__REG(AAEC_GPIO_PHYS + 0x6c)
+#define AAEC_GPIO_PCPINDR	__REG(AAEC_GPIO_PHYS + 0x70)
+#define AAEC_GPIO_PDPINDR	__REG(AAEC_GPIO_PHYS + 0x74)
+#define AAEC_GPIO_PEPINDR	__REG(AAEC_GPIO_PHYS + 0x78)
+#define AAEC_GPIO_PFPINDR	__REG(AAEC_GPIO_PHYS + 0x7c)
+#define AAEC_GPIO_PGPINDR	__REG(AAEC_GPIO_PHYS + 0x80)
+#define AAEC_GPIO_PHPINDR	__REG(AAEC_GPIO_PHYS + 0x84)
+
+#define AAEC_GPIO_PINMUX_PE0CON		(1 << 0)
+#define AAEC_GPIO_PINMUX_PD0CON		(1 << 1)
+#define AAEC_GPIO_PINMUX_CODECON	(1 << 2)
+#define AAEC_GPIO_PINMUX_UART3CON	(1 << 3)
+
+/* LCD Controller */
+#define AAEC_CLCD_PHYS	0x80003000
+
 #endif /* __ARM_ARCH_AAEC2000_H */
diff --git a/include/asm-arm/arch-aaec2000/aaed2000.h b/include/asm-arm/arch-aaec2000/aaed2000.h
new file mode 100644
index 0000000..bc76d2b
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/aaed2000.h
@@ -0,0 +1,40 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/aaed2000.h
+ *
+ *  AAED-2000 specific bits definition
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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.
+ */
+
+#ifndef __ASM_ARCH_AAED2000_H
+#define __ASM_ARCH_AAED2000_H
+
+/* External GPIOs. */
+
+#define EXT_GPIO_PBASE	AAEC_CS3
+#define EXT_GPIO_VBASE	0xf8100000
+#define EXT_GPIO_LENGTH	0x00001000
+
+#define __ext_gpio_p2v(x)	((x) - EXT_GPIO_PBASE + EXT_GPIO_VBASE)
+#define __ext_gpio_v2p(x)	((x) + EXT_GPIO_PBASE - EXT_GPIO_VBASE)
+
+#define __EXT_GPIO_REG(x)	(*((volatile u32 *)__ext_gpio_p2v(x)))
+#define __EXT_GPIO_PREG(x)	(__ext_gpio_v2p((u32)&(x)))
+
+#define AAED_EXT_GPIO	__EXT_GPIO_REG(EXT_GPIO_PBASE)
+
+#define AAED_EGPIO_KBD_SCAN	0x00003fff /* Keyboard scan data */
+#define AAED_EGPIO_PWR_INT	0x00008fff /* Smart battery charger interrupt */
+#define AAED_EGPIO_SWITCHED	0x000f0000 /* DIP Switches */
+#define AAED_EGPIO_USB_VBUS	0x00400000 /* USB Vbus sense */
+#define AAED_EGPIO_LCD_PWR_EN	0x02000000 /* LCD and backlight PWR enable */
+#define AAED_EGPIO_nLED0	0x20000000 /* LED 0 */
+#define AAED_EGPIO_nLED1	0x20000000 /* LED 1 */
+#define AAED_EGPIO_nLED2	0x20000000 /* LED 2 */
+
+
+#endif /* __ARM_ARCH_AAED2000_H */
diff --git a/include/asm-arm/arch-aaec2000/hardware.h b/include/asm-arm/arch-aaec2000/hardware.h
index 4c37219..153506f 100644
--- a/include/asm-arm/arch-aaec2000/hardware.h
+++ b/include/asm-arm/arch-aaec2000/hardware.h
@@ -11,7 +11,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
+#include <asm/sizes.h>
+#include <asm/arch/aaec2000.h>
 
 /* The kernel is loaded at physical address 0xf8000000.
  * We map the IO space a bit after
diff --git a/include/asm-arm/arch-aaec2000/io.h b/include/asm-arm/arch-aaec2000/io.h
index c58a8d1..8d67907 100644
--- a/include/asm-arm/arch-aaec2000/io.h
+++ b/include/asm-arm/arch-aaec2000/io.h
@@ -6,6 +6,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
index 79c9081..d8209f8 100644
--- a/include/asm-arm/arch-aaec2000/memory.h
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -13,7 +13,7 @@
 
 #include <linux/config.h>
 
-#define PHYS_OFFSET	(0xf0000000UL)
+#define PHYS_OFFSET	UL(0xf0000000)
 
 #define __virt_to_bus(x)	__virt_to_phys(x)
 #define __bus_to_virt(x)	__phys_to_virt(x)
diff --git a/include/asm-arm/arch-cl7500/io.h b/include/asm-arm/arch-cl7500/io.h
index f0113bc..89a3328 100644
--- a/include/asm-arm/arch-cl7500/io.h
+++ b/include/asm-arm/arch-cl7500/io.h
@@ -10,6 +10,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-cl7500/memory.h b/include/asm-arm/arch-cl7500/memory.h
index 9776bba..34f40a6 100644
--- a/include/asm-arm/arch-cl7500/memory.h
+++ b/include/asm-arm/arch-cl7500/memory.h
@@ -17,7 +17,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x10000000UL)
+#define PHYS_OFFSET	UL(0x10000000)
 
 /*
  * These are exactly the same on the RiscPC as the
diff --git a/include/asm-arm/arch-clps711x/hardware.h b/include/asm-arm/arch-clps711x/hardware.h
index 1386871..f864c36 100644
--- a/include/asm-arm/arch-clps711x/hardware.h
+++ b/include/asm-arm/arch-clps711x/hardware.h
@@ -235,4 +235,121 @@
 #define CEIVA_PB0_BLK_BTN	(1<<0)
 #endif // #if defined (CONFIG_ARCH_CEIVA)
 
+#if defined (CONFIG_MACH_MP1000)
+/* NOR FLASH */
+#define MP1000_NIO_BASE		0xf9000000	/* virtual */
+#define MP1000_NIO_START	CS0_PHYS_BASE	/* physical */
+#define MP1000_NIO_SIZE		0x00400000
+
+/* DSP Interface */
+#define MP1000_DSP_BASE		0xfa000000	/* virtual */
+#define MP1000_DSP_START	CS1_PHYS_BASE	/* physical */
+#define MP1000_DSP_SIZE		0x00100000
+
+/* LCD, DAA/DSP, RTC, DAA RW Reg all in CS2 */
+#define MP1000_LIO_BASE		0xfb000000	/* virtual */
+#define MP1000_LIO_START	CS2_PHYS_BASE	/* physical */
+#define MP1000_LIO_SIZE		0x00100000
+
+/* NAND FLASH */
+#define MP1000_FIO_BASE		0xfc000000	/* virtual */
+#define MP1000_FIO_START	CS3_PHYS_BASE	/* physical */
+#define MP1000_FIO_SIZE		0x00800000
+
+/* Ethernet */
+#define MP1000_EIO_BASE		0xfd000000	/* virtual 	*/
+#define MP1000_EIO_START	CS4_PHYS_BASE	/* physical 	*/
+#define MP1000_EIO_SIZE		0x00100000
+
+#define	MP1000_LCD_OFFSET	0x00000000	/* LCD offset in CS2 */
+#define	MP1000_DDD_OFFSET	0x00001000	/* DAA/DAI/DSP sft reset offst*/
+#define	MP1000_RTC_OFFSET	0x00002000	/* RTC offset in CS2 */
+#define	MP1000_DAA_OFFSET	0x00003000	/* DAA RW reg offset in CS2 */
+
+/* IDE */
+#define MP1000_IDE_BASE		0xfe000000      /* virtual */
+#define MP1000_IDE_START	CS5_PHYS_BASE      /* physical */
+#define MP1000_IDE_SIZE		0x00100000      /* actually it's only 0x1000 */
+
+#define IRQ_HARDDISK IRQ_EINT2
+
+/*
+ * IDE registers definition
+ */
+
+#define IDE_CONTROL_BASE		(MP1000_IDE_BASE + 0x1000)
+#define IDE_BASE_OFF			(MP1000_IDE_BASE)
+
+#define IDE_WRITE_DEVICE_DATA		(IDE_BASE_OFF + 0x0)
+#define IDE_FEATURES_REGISTER		(IDE_BASE_OFF + 0x2)
+#define IDE_SECTOR_COUNT_REGISTER	(IDE_BASE_OFF + 0x4)
+#define IDE_SECTOR_NUMBER_REGISTER	(IDE_BASE_OFF + 0x6)
+#define IDE_CYLINDER_LOW_REGISTER	(IDE_BASE_OFF + 0x8)
+#define IDE_CYLINDER_HIGH_REGISTER	(IDE_BASE_OFF + 0xa)
+#define IDE_DEVICE_HEAD_REGISTER	(IDE_BASE_OFF + 0xc)
+#define IDE_COMMAND_DATA_REGISTER	(IDE_BASE_OFF + 0xe)
+#define IDE_DEVICE_CONTROL_REGISTER	(IDE_CONTROL_BASE + 0xc)
+
+#define IDE_IRQ                      IRQ_EINT2
+
+
+#define RTC_PORT(x)	(MP1000_LIO_BASE+0x2000 + (x*2))
+#define RTC_ALWAYS_BCD	0
+
+/*
+// Definitions of the bit fields in the HwPortA register for the
+// MP1000 board.
+*/
+#define HwPortAKeyboardRow1                     0x00000001
+#define HwPortAKeyboardRow2                     0x00000002
+#define HwPortAKeyboardRow3                     0x00000004
+#define HwPortAKeyboardRow4                     0x00000008
+#define HwPortAKeyboardRow5                     0x00000010
+#define HwPortAKeyboardRow6                     0x00000020
+#define HwPortALCDEnable                        0x00000040
+#define HwPortAOffhook	                        0x00000080
+
+/*
+// Definitions of the bit fields in the HwPortB register for the
+// MP1000 board.
+*/
+#define HwPortBL3Mode                           0x00000001
+#define HwPortBL3Clk                            0x00000002
+#define HwPortBSClk                             0x00000001
+#define HwPortBSData                            0x00000002
+#define HwPortBL3Data                           0x00000004
+#define HwPortBMute                             0x00000008
+#define HwPortBQD0                              0x00000010
+#define HwPortBQD1                              0x00000020
+#define HwPortBQD2                              0x00000040
+#define HwPortBQD3                              0x00000080
+
+/*
+// Definitions of the bit fields in the HwPortD register for the
+// MP1000 board.
+*/
+#define HwPortDLED1                             0x00000001
+#define HwPortDLED2                             0x00000002
+#define HwPortDLED3                             0x00000004
+#define HwPortDLED4                             0x00000008
+#define HwPortDLED5                             0x00000010
+#define HwPortDEECS                             0x00000020
+#define HwPortBRTS                              0x00000040
+#define HwPortBRI                               0x00000080
+
+
+/*
+// Definitions of the bit fields in the HwPortE register for the
+// MP1000 board.
+*/
+
+#define HwPortECLE                              0x00000001
+#define HwPortESepromDOut                       0x00000001
+#define HwPortEALE                              0x00000002
+#define HwPortESepromDIn                        0x00000002
+#define HwPortENANDCS                           0x00000004
+#define HwPortESepromCLK                        0x00000004
+
+#endif // #if defined (CONFIG_MACH_MP1000)
+
 #endif
diff --git a/include/asm-arm/arch-clps711x/io.h b/include/asm-arm/arch-clps711x/io.h
index 14d7e8d..62613b0 100644
--- a/include/asm-arm/arch-clps711x/io.h
+++ b/include/asm-arm/arch-clps711x/io.h
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(a)			((void __iomem *)(a))
diff --git a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h
index bd97894..61d8717 100644
--- a/include/asm-arm/arch-clps711x/memory.h
+++ b/include/asm-arm/arch-clps711x/memory.h
@@ -25,7 +25,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	UL(0xc0000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-clps711x/mp1000-seprom.h b/include/asm-arm/arch-clps711x/mp1000-seprom.h
new file mode 100644
index 0000000..3e5566c
--- /dev/null
+++ b/include/asm-arm/arch-clps711x/mp1000-seprom.h
@@ -0,0 +1,77 @@
+#ifndef MP1000_SEPROM_H
+#define MP1000_SEPROM_H
+
+/*
+ * mp1000-seprom.h
+ *
+ *
+ *  This file contains the Serial EEPROM definitions for the MP1000 board
+ *
+ *  Copyright (C) 2005 Comdial 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define COMMAND_ERASE		(0x1C0)
+#define COMMAND_ERASE_ALL	(0x120)
+#define COMMAND_WRITE_DISABLE	(0x100)
+#define COMMAND_WRITE_ENABLE	(0x130)
+#define COMMAND_READ		(0x180)
+#define COMMAND_WRITE		(0x140)
+#define COMMAND_WRITE_ALL	(0x110)
+
+//
+// Serial EEPROM data format
+//
+
+#define PACKED __attribute__ ((packed))
+
+typedef struct _EEPROM {
+	union {
+		unsigned char eprom_byte_data[128];
+		unsigned short eprom_short_data[64];
+		struct {
+			unsigned char version PACKED;	// EEPROM Version "1" for now
+			unsigned char box_id PACKED; 	// Box ID (Standalone, SOHO, embedded, etc)
+			unsigned char major_hw_version PACKED;	// Major Hardware version (Hex)
+			unsigned char minor_hw_version PACKED;	// Minor Hardware Version (Hex)
+			unsigned char mfg_id[3] PACKED;	// Manufacturer ID (3 character Alphabetic)
+			unsigned char mfg_serial_number[10] PACKED;	// Manufacturer Serial number
+			unsigned char mfg_date[3] PACKED;	// Date of Mfg (Formatted YY:MM:DD)
+			unsigned char country PACKED;	// Country of deployment
+			unsigned char mac_Address[6] PACKED;	// MAC Address
+			unsigned char oem_string[20] PACKED;	// OEM ID string
+			unsigned short feature_bits1 PACKED;	// Feature Bits 1
+			unsigned short feature_bits2 PACKED;	// Feature Bits 2
+			unsigned char filler[75] PACKED;		// Unused/Undefined	“0” initialized
+			unsigned short checksum PACKED;		// byte accumulated short checksum
+		} eprom_struct;
+	} variant;
+}  eeprom_struct;
+
+/* These settings must be mutually exclusive */
+#define	FEATURE_BITS1_DRAMSIZE_16MEG	0x0001  /* 0 signifies 4 MEG system */
+#define	FEATURE_BITS1_DRAMSIZE_8MEG	0x0002  /* 1 in bit 1 = 8MEG system */
+#define	FEATURE_BITS1_DRAMSIZE_64MEG	0x0004  /* 1 in bit 2 = 64MEG system */
+
+#define FEATURE_BITS1_CPUIS90MEG     0x0010
+
+extern void seprom_init(void);
+extern eeprom_struct* get_seprom_ptr(void);
+extern unsigned char* get_eeprom_mac_address(void);
+
+#endif /* MP1000_SEPROM_H */
+
diff --git a/include/asm-arm/arch-ebsa110/memory.h b/include/asm-arm/arch-ebsa110/memory.h
index 5a9493e..02f1445 100644
--- a/include/asm-arm/arch-ebsa110/memory.h
+++ b/include/asm-arm/arch-ebsa110/memory.h
@@ -19,7 +19,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x00000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
 
 /*
  * We keep this 1:1 so that we don't interfere
diff --git a/include/asm-arm/arch-ebsa285/io.h b/include/asm-arm/arch-ebsa285/io.h
index 70576b1..776f9d3 100644
--- a/include/asm-arm/arch-ebsa285/io.h
+++ b/include/asm-arm/arch-ebsa285/io.h
@@ -14,6 +14,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffff
 
 /*
diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h
index d0466f9..09e335c 100644
--- a/include/asm-arm/arch-ebsa285/memory.h
+++ b/include/asm-arm/arch-ebsa285/memory.h
@@ -46,14 +46,14 @@
 #if defined(CONFIG_ARCH_FOOTBRIDGE)
 
 /* Task size and page offset at 3GB */
-#define TASK_SIZE		(0xbf000000UL)
-#define PAGE_OFFSET		(0xc0000000UL)
+#define TASK_SIZE		UL(0xbf000000)
+#define PAGE_OFFSET		UL(0xc0000000)
 
 #elif defined(CONFIG_ARCH_CO285)
 
 /* Task size and page offset at 1.5GB */
-#define TASK_SIZE		(0x5f000000UL)
-#define PAGE_OFFSET		(0x60000000UL)
+#define TASK_SIZE		UL(0x5f000000)
+#define PAGE_OFFSET		UL(0x60000000)
 
 #else
 
@@ -64,7 +64,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		(0x00000000UL)
+#define PHYS_OFFSET		UL(0x00000000)
 
 /*
  * This decides where the kernel will search for a free chunk of vm
diff --git a/include/asm-arm/arch-epxa10db/io.h b/include/asm-arm/arch-epxa10db/io.h
index 1f0afa2..9fe100c 100644
--- a/include/asm-arm/arch-epxa10db/io.h
+++ b/include/asm-arm/arch-epxa10db/io.h
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffff
 
 
diff --git a/include/asm-arm/arch-epxa10db/memory.h b/include/asm-arm/arch-epxa10db/memory.h
index 3f86bf7..999541b 100644
--- a/include/asm-arm/arch-epxa10db/memory.h
+++ b/include/asm-arm/arch-epxa10db/memory.h
@@ -23,7 +23,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x00000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-h720x/io.h b/include/asm-arm/arch-h720x/io.h
index 6881482..d3ccfd8 100644
--- a/include/asm-arm/arch-h720x/io.h
+++ b/include/asm-arm/arch-h720x/io.h
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 
 #define IO_SPACE_LIMIT 0xffffffff
 
diff --git a/include/asm-arm/arch-h720x/memory.h b/include/asm-arm/arch-h720x/memory.h
index 5633447..4a1bfd7 100644
--- a/include/asm-arm/arch-h720x/memory.h
+++ b/include/asm-arm/arch-h720x/memory.h
@@ -11,7 +11,7 @@
  * Page offset:
  *    ( 0xc0000000UL )
  */
-#define PHYS_OFFSET	(0x40000000UL)
+#define PHYS_OFFSET	UL(0x40000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-imx/io.h b/include/asm-arm/arch-imx/io.h
index 28a4cca..b191cdd 100644
--- a/include/asm-arm/arch-imx/io.h
+++ b/include/asm-arm/arch-imx/io.h
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(a)		((void __iomem *)(a))
diff --git a/include/asm-arm/arch-imx/memory.h b/include/asm-arm/arch-imx/memory.h
index 116a91f..d09ae32 100644
--- a/include/asm-arm/arch-imx/memory.h
+++ b/include/asm-arm/arch-imx/memory.h
@@ -21,7 +21,7 @@
 #ifndef __ASM_ARCH_MMU_H
 #define __ASM_ARCH_MMU_H
 
-#define PHYS_OFFSET	(0x08000000UL)
+#define PHYS_OFFSET	UL(0x08000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-integrator/hardware.h b/include/asm-arm/arch-integrator/hardware.h
index be2716e..6f0947b 100644
--- a/include/asm-arm/arch-integrator/hardware.h
+++ b/include/asm-arm/arch-integrator/hardware.h
@@ -33,15 +33,6 @@
 #define IO_SIZE			0x0B000000                 // How much?
 #define IO_START		INTEGRATOR_HDR_BASE        // PA of IO
 
-/*
- * Similar to above, but for PCI addresses (memory, IO, Config and the
- * V3 chip itself).  WARNING: this has to mirror definitions in platform.h
- */
-#define PCI_MEMORY_VADDR        0xe8000000
-#define PCI_CONFIG_VADDR        0xec000000
-#define PCI_V3_VADDR            0xed000000
-#define PCI_IO_VADDR            0xee000000
-
 #define PCIO_BASE		PCI_IO_VADDR
 #define PCIMEM_BASE		PCI_MEMORY_VADDR
 
diff --git a/include/asm-arm/arch-integrator/io.h b/include/asm-arm/arch-integrator/io.h
index fbea8be..31f2dea 100644
--- a/include/asm-arm/arch-integrator/io.h
+++ b/include/asm-arm/arch-integrator/io.h
@@ -22,6 +22,14 @@
 
 #define IO_SPACE_LIMIT 0xffff
 
+/*
+ * WARNING: this has to mirror definitions in platform.h
+ */
+#define PCI_MEMORY_VADDR        0xe8000000
+#define PCI_CONFIG_VADDR        0xec000000
+#define PCI_V3_VADDR            0xed000000
+#define PCI_IO_VADDR            0xee000000
+
 #define __io(a)			((void __iomem *)(PCI_IO_VADDR + (a)))
 #define __mem_pci(a)		(a)
 #define __mem_isa(a)		((a) + PCI_MEMORY_VADDR)
diff --git a/include/asm-arm/arch-integrator/memory.h b/include/asm-arm/arch-integrator/memory.h
index 2087ea7..1ab56d7 100644
--- a/include/asm-arm/arch-integrator/memory.h
+++ b/include/asm-arm/arch-integrator/memory.h
@@ -23,8 +23,8 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x00000000UL)
-#define BUS_OFFSET	(0x80000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
+#define BUS_OFFSET	UL(0x80000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-iop3xx/io.h b/include/asm-arm/arch-iop3xx/io.h
index 2761dfd..f39046a 100644
--- a/include/asm-arm/arch-iop3xx/io.h
+++ b/include/asm-arm/arch-iop3xx/io.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(p)			((void __iomem *)(p))
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
index 45351f5..bc62f4b 100644
--- a/include/asm-arm/arch-iop3xx/memory.h
+++ b/include/asm-arm/arch-iop3xx/memory.h
@@ -12,9 +12,9 @@
  * Physical DRAM offset.
  */
 #ifndef CONFIG_ARCH_IOP331
-#define PHYS_OFFSET	(0xa0000000UL)
+#define PHYS_OFFSET	UL(0xa0000000)
 #else
-#define PHYS_OFFSET	(0x00000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
 #endif
 
 /*
diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
index 3241cd6..7fbcdf9 100644
--- a/include/asm-arm/arch-ixp2000/io.h
+++ b/include/asm-arm/arch-ixp2000/io.h
@@ -15,6 +15,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT		0xffffffff
 #define __mem_pci(a)		(a)
 
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h
index b768009..c6d5142 100644
--- a/include/asm-arm/arch-ixp2000/ixdp2x01.h
+++ b/include/asm-arm/arch-ixp2000/ixdp2x01.h
@@ -22,7 +22,7 @@
 #define	IXDP2X01_CPLD_REGION_SIZE	0x00100000
 
 #define IXDP2X01_CPLD_VIRT_REG(reg) (volatile unsigned long*)(IXDP2X01_VIRT_CPLD_BASE | reg)
-#define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg)
+#define IXDP2X01_CPLD_PHYS_REG(reg) (IXDP2X01_PHYS_CPLD_BASE | reg)
 
 #define IXDP2X01_UART1_VIRT_BASE	IXDP2X01_CPLD_VIRT_REG(0x40)
 #define IXDP2X01_UART1_PHYS_BASE	IXDP2X01_CPLD_PHYS_REG(0x40)
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 32aece0..def089d 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -392,4 +392,47 @@
 #define	WDT_RESET_ENABLE		0x01000000
 
 
+/*
+ * MSF registers.  The IXP2400 and IXP2800 have somewhat different MSF
+ * units, but the registers that differ between the two don't overlap,
+ * so we can have one register list for both.
+ */
+#define IXP2000_MSF_REG(x)			((volatile unsigned long*)(IXP2000_MSF_VIRT_BASE + (x)))
+#define IXP2000_MSF_RX_CONTROL			IXP2000_MSF_REG(0x0000)
+#define IXP2000_MSF_TX_CONTROL			IXP2000_MSF_REG(0x0004)
+#define IXP2000_MSF_INTERRUPT_STATUS		IXP2000_MSF_REG(0x0008)
+#define IXP2000_MSF_INTERRUPT_ENABLE		IXP2000_MSF_REG(0x000c)
+#define IXP2000_MSF_CSIX_TYPE_MAP		IXP2000_MSF_REG(0x0010)
+#define IXP2000_MSF_FC_EGRESS_STATUS		IXP2000_MSF_REG(0x0014)
+#define IXP2000_MSF_FC_INGRESS_STATUS		IXP2000_MSF_REG(0x0018)
+#define IXP2000_MSF_HWM_CONTROL			IXP2000_MSF_REG(0x0024)
+#define IXP2000_MSF_FC_STATUS_OVERRIDE		IXP2000_MSF_REG(0x0028)
+#define IXP2000_MSF_CLOCK_CONTROL		IXP2000_MSF_REG(0x002c)
+#define IXP2000_MSF_RX_PORT_MAP			IXP2000_MSF_REG(0x0040)
+#define IXP2000_MSF_RBUF_ELEMENT_DONE		IXP2000_MSF_REG(0x0044)
+#define IXP2000_MSF_RX_MPHY_POLL_LIMIT		IXP2000_MSF_REG(0x0048)
+#define IXP2000_MSF_RX_CALENDAR_LENGTH		IXP2000_MSF_REG(0x0048)
+#define IXP2000_MSF_RX_THREAD_FREELIST_TIMEOUT_0	IXP2000_MSF_REG(0x0050)
+#define IXP2000_MSF_RX_THREAD_FREELIST_TIMEOUT_1	IXP2000_MSF_REG(0x0054)
+#define IXP2000_MSF_RX_THREAD_FREELIST_TIMEOUT_2	IXP2000_MSF_REG(0x0058)
+#define IXP2000_MSF_TX_SEQUENCE_0		IXP2000_MSF_REG(0x0060)
+#define IXP2000_MSF_TX_SEQUENCE_1		IXP2000_MSF_REG(0x0064)
+#define IXP2000_MSF_TX_SEQUENCE_2		IXP2000_MSF_REG(0x0068)
+#define IXP2000_MSF_TX_MPHY_POLL_LIMIT		IXP2000_MSF_REG(0x0070)
+#define IXP2000_MSF_TX_CALENDAR_LENGTH		IXP2000_MSF_REG(0x0070)
+#define IXP2000_MSF_RX_UP_CONTROL_0		IXP2000_MSF_REG(0x0080)
+#define IXP2000_MSF_RX_UP_CONTROL_1		IXP2000_MSF_REG(0x0084)
+#define IXP2000_MSF_RX_UP_CONTROL_2		IXP2000_MSF_REG(0x0088)
+#define IXP2000_MSF_RX_UP_CONTROL_3		IXP2000_MSF_REG(0x008c)
+#define IXP2000_MSF_TX_UP_CONTROL_0		IXP2000_MSF_REG(0x0090)
+#define IXP2000_MSF_TX_UP_CONTROL_1		IXP2000_MSF_REG(0x0094)
+#define IXP2000_MSF_TX_UP_CONTROL_2		IXP2000_MSF_REG(0x0098)
+#define IXP2000_MSF_TX_UP_CONTROL_3		IXP2000_MSF_REG(0x009c)
+#define IXP2000_MSF_TRAIN_DATA			IXP2000_MSF_REG(0x00a0)
+#define IXP2000_MSF_TRAIN_CALENDAR		IXP2000_MSF_REG(0x00a4)
+#define IXP2000_MSF_TRAIN_FLOW_CONTROL		IXP2000_MSF_REG(0x00a8)
+#define IXP2000_MSF_TX_CALENDAR_0		IXP2000_MSF_REG(0x1000)
+#define IXP2000_MSF_RX_PORT_CALENDAR_STATUS	IXP2000_MSF_REG(0x1400)
+
+
 #endif				/* _IXP2000_H_ */
diff --git a/include/asm-arm/arch-ixp2000/memory.h b/include/asm-arm/arch-ixp2000/memory.h
index d0f415c..21e1de5 100644
--- a/include/asm-arm/arch-ixp2000/memory.h
+++ b/include/asm-arm/arch-ixp2000/memory.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	(0x00000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index abdcf51..a66317a 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -15,40 +15,40 @@
 
 #ifndef __ASSEMBLY__
 
-/*
- * The IXP2400 B0 silicon contains an erratum (#66) that causes writes
- * to on-chip I/O register to not complete fully. What this means is
- * that if you have a write to on-chip I/O followed by a back-to-back
- * read or write, the first write will happen twice. OR...if it's
- * not a back-to-back transaction, the read or write will generate
- * incorrect data.
- *
- * The official work around for this is to set the on-chip I/O regions
- * as XCB=101 and then force a read-back from the register.
- *
- */
-#if defined(CONFIG_ARCH_ENP2611) || defined(CONFIG_ARCH_IXDP2400) || defined(CONFIG_ARCH_IXDP2401)
-
-#include <asm/system.h>		/* Pickup local_irq_ functions */
+static inline unsigned long ixp2000_reg_read(volatile void *reg)
+{
+	return *((volatile unsigned long *)reg);
+}
 
 static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
 {
+	*((volatile unsigned long *)reg) = val;
+}
+
+/*
+ * On the IXP2400, we can't use XCB=000 due to chip bugs.  We use
+ * XCB=101 instead, but that makes all I/O accesses bufferable.  This
+ * is not a problem in general, but we do have to be slightly more
+ * careful because I/O writes are no longer automatically flushed out
+ * of the write buffer.
+ *
+ * In cases where we want to make sure that a write has been flushed
+ * out of the write buffer before we proceed, for example when masking
+ * a device interrupt before re-enabling IRQs in CPSR, we can use this
+ * function, ixp2000_reg_wrb, which performs a write, a readback, and
+ * issues a dummy instruction dependent on the value of the readback
+ * (mov rX, rX) to make sure that the readback has completed before we
+ * continue.
+ */
+static inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
+{
 	unsigned long dummy;
-	unsigned long flags;
 
-	local_irq_save(flags);
 	*((volatile unsigned long *)reg) = val;
-	barrier();
+
 	dummy = *((volatile unsigned long *)reg);
-	local_irq_restore(flags);
+	__asm__ __volatile__("mov %0, %0" : "+r" (dummy));
 }
-#else
-static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
-{
-	*((volatile unsigned long *)reg) = val;
-}
-#endif	/* IXDP2400 || IXDP2401 */
-#define ixp2000_reg_read(reg)	(*((volatile unsigned long *)reg))
 
 /*
  * Boards may multiplex different devices on the 2nd channel of 
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index e350dcb..80d05ec 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -113,7 +113,7 @@
 }
 
 static inline void
-__ixp4xx_writesb(u32 bus_addr, u8 *vaddr, int count)
+__ixp4xx_writesb(u32 bus_addr, const u8 *vaddr, int count)
 {
 	while (count--)
 		writeb(*vaddr++, bus_addr);
@@ -136,7 +136,7 @@
 }
 
 static inline void
-__ixp4xx_writesw(u32 bus_addr, u16 *vaddr, int count)
+__ixp4xx_writesw(u32 bus_addr, const u16 *vaddr, int count)
 {
 	while (count--)
 		writew(*vaddr++, bus_addr);
@@ -154,7 +154,7 @@
 }
 
 static inline void
-__ixp4xx_writesl(u32 bus_addr, u32 *vaddr, int count)
+__ixp4xx_writesl(u32 bus_addr, const u32 *vaddr, int count)
 {
 	while (count--)
 		writel(*vaddr++, bus_addr);
diff --git a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
index 004696a..2b149ed 100644
--- a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
+++ b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
@@ -36,11 +36,11 @@
  *
  * 0x6000000	0x00004000	ioremap'd	QMgr
  *
- * 0xC0000000	0x00001000	0xffbfe000	PCI CFG 
+ * 0xC0000000	0x00001000	0xffbff000	PCI CFG
  *
- * 0xC4000000	0x00001000	0xffbfd000	EXP CFG 
+ * 0xC4000000	0x00001000	0xffbfe000	EXP CFG
  *
- * 0xC8000000	0x0000C000	0xffbf2000	On-Chip Peripherals
+ * 0xC8000000	0x00013000	0xffbeb000	On-Chip Peripherals
  */
 
 /*
@@ -52,22 +52,22 @@
  * Expansion BUS Configuration registers
  */
 #define IXP4XX_EXP_CFG_BASE_PHYS	(0xC4000000)
-#define IXP4XX_EXP_CFG_BASE_VIRT	(0xFFBFD000)
+#define IXP4XX_EXP_CFG_BASE_VIRT	(0xFFBFE000)
 #define IXP4XX_EXP_CFG_REGION_SIZE	(0x00001000)
 
 /*
  * PCI Config registers
  */
 #define IXP4XX_PCI_CFG_BASE_PHYS	(0xC0000000)
-#define	IXP4XX_PCI_CFG_BASE_VIRT	(0xFFBFE000)
+#define	IXP4XX_PCI_CFG_BASE_VIRT	(0xFFBFF000)
 #define IXP4XX_PCI_CFG_REGION_SIZE	(0x00001000)
 
 /*
  * Peripheral space
  */
 #define IXP4XX_PERIPHERAL_BASE_PHYS	(0xC8000000)
-#define IXP4XX_PERIPHERAL_BASE_VIRT	(0xFFBF2000)
-#define IXP4XX_PERIPHERAL_REGION_SIZE	(0x0000C000)
+#define IXP4XX_PERIPHERAL_BASE_VIRT	(0xFFBEB000)
+#define IXP4XX_PERIPHERAL_REGION_SIZE	(0x00013000)
 
 /*
  * Debug UART
@@ -115,25 +115,48 @@
 /*
  * Peripheral Space Register Region Base Addresses
  */
-#define IXP4XX_UART1_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x0000)
-#define IXP4XX_UART2_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x1000)
-#define IXP4XX_PMU_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x2000)
-#define IXP4XX_INTC_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x3000)
-#define IXP4XX_GPIO_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x4000)
-#define IXP4XX_TIMER_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x5000)
-#define IXP4XX_EthA_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x9000)
-#define IXP4XX_EthB_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0xA000)
-#define IXP4XX_USB_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0xB000)
+#define IXP4XX_UART1_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x0000)
+#define IXP4XX_UART2_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x1000)
+#define IXP4XX_PMU_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x2000)
+#define IXP4XX_INTC_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x3000)
+#define IXP4XX_GPIO_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x4000)
+#define IXP4XX_TIMER_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x5000)
+#define IXP4XX_NPEA_BASE_PHYS   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x6000)
+#define IXP4XX_NPEB_BASE_PHYS   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x7000)
+#define IXP4XX_NPEC_BASE_PHYS   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x8000)
+#define IXP4XX_EthB_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x9000)
+#define IXP4XX_EthC_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xA000)
+#define IXP4XX_USB_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xB000)
+/* ixp46X only */
+#define IXP4XX_EthA_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xC000)
+#define IXP4XX_EthB1_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xD000)
+#define IXP4XX_EthB2_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xE000)
+#define IXP4XX_EthB3_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xF000)
+#define IXP4XX_TIMESYNC_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x10000)
+#define IXP4XX_I2C_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x11000)
+#define IXP4XX_SSP_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x12000)
 
-#define IXP4XX_UART1_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x0000)
-#define IXP4XX_UART2_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000)
-#define IXP4XX_PMU_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000)
-#define IXP4XX_INTC_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000)
-#define IXP4XX_GPIO_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000)
-#define IXP4XX_TIMER_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000)
-#define IXP4XX_EthA_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x9000)
-#define IXP4XX_EthB_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0xA000)
-#define IXP4XX_USB_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0xB000)
+
+#define IXP4XX_UART1_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x0000)
+#define IXP4XX_UART2_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000)
+#define IXP4XX_PMU_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000)
+#define IXP4XX_INTC_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000)
+#define IXP4XX_GPIO_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000)
+#define IXP4XX_TIMER_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000)
+#define IXP4XX_NPEA_BASE_VIRT   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x6000)
+#define IXP4XX_NPEB_BASE_VIRT   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x7000)
+#define IXP4XX_NPEC_BASE_VIRT   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x8000)
+#define IXP4XX_EthB_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x9000)
+#define IXP4XX_EthC_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xA000)
+#define IXP4XX_USB_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xB000)
+/* ixp46X only */
+#define IXP4XX_EthA_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xC000)
+#define IXP4XX_EthB1_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xD000)
+#define IXP4XX_EthB2_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xE000)
+#define IXP4XX_EthB3_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xF000)
+#define IXP4XX_TIMESYNC_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x10000)
+#define IXP4XX_I2C_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x11000)
+#define IXP4XX_SSP_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x12000)
 
 /*
  * Constants to make it easy to access  Interrupt Controller registers
diff --git a/include/asm-arm/arch-ixp4xx/memory.h b/include/asm-arm/arch-ixp4xx/memory.h
index d348548..e024d0a 100644
--- a/include/asm-arm/arch-ixp4xx/memory.h
+++ b/include/asm-arm/arch-ixp4xx/memory.h
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x00000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-arm/arch-l7200/io.h b/include/asm-arm/arch-l7200/io.h
index fc012a3..cab8ad0 100644
--- a/include/asm-arm/arch-l7200/io.h
+++ b/include/asm-arm/arch-l7200/io.h
@@ -10,7 +10,7 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 
 #define IO_SPACE_LIMIT 0xffffffff
 
diff --git a/include/asm-arm/arch-l7200/memory.h b/include/asm-arm/arch-l7200/memory.h
index c5b9608..9e50a17 100644
--- a/include/asm-arm/arch-l7200/memory.h
+++ b/include/asm-arm/arch-l7200/memory.h
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset on the L7200 SDB.
  */
-#define PHYS_OFFSET     (0xf0000000UL)
+#define PHYS_OFFSET     UL(0xf0000000)
 
 #define __virt_to_bus(x) __virt_to_phys(x)
 #define __bus_to_virt(x) __phys_to_virt(x)
diff --git a/include/asm-arm/arch-lh7a40x/io.h b/include/asm-arm/arch-lh7a40x/io.h
index c13bdd9..bbcd433 100644
--- a/include/asm-arm/arch-lh7a40x/io.h
+++ b/include/asm-arm/arch-lh7a40x/io.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_IO_H
 #define __ASM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /* No ISA or PCI bus on this machine. */
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
index c650e6f..c92bcb8 100644
--- a/include/asm-arm/arch-lh7a40x/memory.h
+++ b/include/asm-arm/arch-lh7a40x/memory.h
@@ -17,7 +17,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	UL(0xc0000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
index 11fbf62..3d5bcd5 100644
--- a/include/asm-arm/arch-omap/io.h
+++ b/include/asm-arm/arch-omap/io.h
@@ -34,6 +34,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
index ef32d61..bf545b6 100644
--- a/include/asm-arm/arch-omap/memory.h
+++ b/include/asm-arm/arch-omap/memory.h
@@ -37,9 +37,9 @@
  * Physical DRAM offset.
  */
 #if defined(CONFIG_ARCH_OMAP1)
-#define PHYS_OFFSET		(0x10000000UL)
+#define PHYS_OFFSET		UL(0x10000000)
 #elif defined(CONFIG_ARCH_OMAP2)
-#define PHYS_OFFSET		(0x80000000UL)
+#define PHYS_OFFSET		UL(0x80000000)
 #endif
 
 /*
@@ -66,7 +66,7 @@
 /*
  * OMAP-1510 Local Bus address offset
  */
-#define OMAP1510_LB_OFFSET	(0x30000000UL)
+#define OMAP1510_LB_OFFSET	UL(0x30000000)
 
 #define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
 #define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index cf35721..3e70bd9 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -44,12 +44,12 @@
 
 #ifndef __ASSEMBLY__
 
-# define __REG(x)	(*((volatile unsigned long *)io_p2v(x)))
+# define __REG(x)	(*((volatile u32 *)io_p2v(x)))
 
 /* With indexed regs we don't want to feed the index through io_p2v()
    especially if it is a variable, otherwise horrible code will result. */
 # define __REG2(x,y)	\
-	(*(volatile unsigned long *)((unsigned long)&__REG(x) + (y)))
+	(*(volatile u32 *)((u32)&__REG(x) + (y)))
 
 # define __PREG(x)	(io_v2p((u32)&(x)))
 
diff --git a/include/asm-arm/arch-pxa/io.h b/include/asm-arm/arch-pxa/io.h
index c3bdbe4..eb2dd58 100644
--- a/include/asm-arm/arch-pxa/io.h
+++ b/include/asm-arm/arch-pxa/io.h
@@ -6,6 +6,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-pxa/irda.h b/include/asm-arm/arch-pxa/irda.h
new file mode 100644
index 0000000..748406f
--- /dev/null
+++ b/include/asm-arm/arch-pxa/irda.h
@@ -0,0 +1,17 @@
+#ifndef ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_OFF		1
+#define IR_SIRMODE	2
+#define IR_FIRMODE	4
+
+struct pxaficp_platform_data {
+	int transceiver_cap;
+	void (*transceiver_mode)(struct device *dev, int mode);
+};
+
+extern void pxa_set_ficp_info(struct pxaficp_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h
index 58bad97..eaf6d43 100644
--- a/include/asm-arm/arch-pxa/memory.h
+++ b/include/asm-arm/arch-pxa/memory.h
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0xa0000000UL)
+#define PHYS_OFFSET	UL(0xa0000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 3af7165..a75a247 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -326,6 +326,25 @@
 #define STDLL		__REG(0x40700000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
 #define STDLH		__REG(0x40700004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
 
+/* Hardware UART (HWUART) */
+#define HWUART		HWRBR
+#define HWRBR		__REG(0x41600000)  /* Receive Buffer Register (read only) */
+#define HWTHR		__REG(0x41600000)  /* Transmit Holding Register (write only) */
+#define HWIER		__REG(0x41600004)  /* Interrupt Enable Register (read/write) */
+#define HWIIR		__REG(0x41600008)  /* Interrupt ID Register (read only) */
+#define HWFCR		__REG(0x41600008)  /* FIFO Control Register (write only) */
+#define HWLCR		__REG(0x4160000C)  /* Line Control Register (read/write) */
+#define HWMCR		__REG(0x41600010)  /* Modem Control Register (read/write) */
+#define HWLSR		__REG(0x41600014)  /* Line Status Register (read only) */
+#define HWMSR		__REG(0x41600018)  /* Modem Status Register (read only) */
+#define HWSPR		__REG(0x4160001C)  /* Scratch Pad Register (read/write) */
+#define HWISR		__REG(0x41600020)  /* Infrared Selection Register (read/write) */
+#define HWFOR		__REG(0x41600024)  /* Receive FIFO Occupancy Register (read only) */
+#define HWABR		__REG(0x41600028)  /* Auto-Baud Control Register (read/write) */
+#define HWACR		__REG(0x4160002C)  /* Auto-Baud Count Register (read only) */
+#define HWDLL		__REG(0x41600000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define HWDLH		__REG(0x41600004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
 #define IER_DMAE	(1 << 7)	/* DMA Requests Enable */
 #define IER_UUE		(1 << 6)	/* UART Unit Enable */
 #define IER_NRZE	(1 << 5)	/* NRZ coding Enable */
@@ -1013,14 +1032,12 @@
 #define ICCR0_LBM	(1 << 1)	/* Loopback mode */
 #define ICCR0_ITR	(1 << 0)	/* IrDA transmission */
 
-#ifdef CONFIG_PXA27x
 #define ICCR2_RXP       (1 << 3)	/* Receive Pin Polarity select */
 #define ICCR2_TXP       (1 << 2)	/* Transmit Pin Polarity select */
 #define ICCR2_TRIG	(3 << 0)	/* Receive FIFO Trigger threshold */
 #define ICCR2_TRIG_8    (0 << 0)	/* 	>= 8 bytes */
 #define ICCR2_TRIG_16   (1 << 0)	/*	>= 16 bytes */
 #define ICCR2_TRIG_32   (2 << 0)	/*	>= 32 bytes */
-#endif
 
 #ifdef CONFIG_PXA27x
 #define ICSR0_EOC	(1 << 6)	/* DMA End of Descriptor Chain */
@@ -1250,9 +1267,13 @@
 #define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
 #define GPIO41_FFRTS		41	/* FFUART request to send */
 #define GPIO42_BTRXD		42	/* BTUART receive data */
+#define GPIO42_HWRXD		42	/* HWUART receive data */
 #define GPIO43_BTTXD		43	/* BTUART transmit data */
+#define GPIO43_HWTXD		43	/* HWUART transmit data */
 #define GPIO44_BTCTS		44	/* BTUART clear to send */
+#define GPIO44_HWCTS		44	/* HWUART clear to send */
 #define GPIO45_BTRTS		45	/* BTUART request to send */
+#define GPIO45_HWRTS		45	/* HWUART request to send */
 #define GPIO45_AC97_SYSCLK	45	/* AC97 System Clock */
 #define GPIO46_ICPRXD		46	/* ICP receive data */
 #define GPIO46_STRXD		46	/* STD_UART receive data */
@@ -1378,17 +1399,26 @@
 #define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
 #define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
 #define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
+#define GPIO42_HWRXD_MD		(42 | GPIO_ALT_FN_3_IN)
 #define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
+#define GPIO43_HWTXD_MD		(43 | GPIO_ALT_FN_3_OUT)
 #define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
+#define GPIO44_HWCTS_MD		(44 | GPIO_ALT_FN_3_IN)
 #define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
+#define GPIO45_HWRTS_MD		(45 | GPIO_ALT_FN_3_OUT)
 #define GPIO45_SYSCLK_AC97_MD		(45 | GPIO_ALT_FN_1_OUT)
 #define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
 #define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
 #define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
 #define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
 #define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
+#define GPIO48_HWTXD_MD         (48 | GPIO_ALT_FN_1_OUT)
+#define GPIO48_nPOE_MD          (48 | GPIO_ALT_FN_2_OUT)
+#define GPIO49_HWRXD_MD		(49 | GPIO_ALT_FN_1_IN)
 #define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
 #define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
+#define GPIO50_HWCTS_MD         (50 | GPIO_ALT_FN_1_IN)
+#define GPIO51_HWRTS_MD         (51 | GPIO_ALT_FN_1_OUT)
 #define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
 #define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
 #define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
@@ -1763,6 +1793,7 @@
 #define CKEN7_BTUART	(1 << 7)	/* BTUART Unit Clock Enable */
 #define CKEN6_FFUART	(1 << 6)	/* FFUART Unit Clock Enable */
 #define CKEN5_STUART	(1 << 5)	/* STUART Unit Clock Enable */
+#define CKEN4_HWUART	(1 << 4)	/* HWUART Unit Clock Enable */
 #define CKEN4_SSP3	(1 << 4)	/* SSP3 Unit Clock Enable */
 #define CKEN3_SSP	(1 << 3)	/* SSP Unit Clock Enable */
 #define CKEN3_SSP2	(1 << 3)	/* SSP2 Unit Clock Enable */
@@ -2282,4 +2313,11 @@
 
 #endif
 
+/* PWRMODE register M field values */
+
+#define PWRMODE_IDLE		0x1
+#define PWRMODE_STANDBY		0x2
+#define PWRMODE_SLEEP		0x3
+#define PWRMODE_DEEPSLEEP	0x7
+
 #endif
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
index 4428d3e..fe38090 100644
--- a/include/asm-arm/arch-pxa/uncompress.h
+++ b/include/asm-arm/arch-pxa/uncompress.h
@@ -12,6 +12,7 @@
 #define FFUART		((volatile unsigned long *)0x40100000)
 #define BTUART		((volatile unsigned long *)0x40200000)
 #define STUART		((volatile unsigned long *)0x40700000)
+#define HWUART		((volatile unsigned long *)0x41600000)
 
 #define UART		FFUART
 
diff --git a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
index 24453c4..b4da08d 100644
--- a/include/asm-arm/arch-rpc/io.h
+++ b/include/asm-arm/arch-rpc/io.h
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-rpc/memory.h b/include/asm-arm/arch-rpc/memory.h
index 33fc75c..0592cb3 100644
--- a/include/asm-arm/arch-rpc/memory.h
+++ b/include/asm-arm/arch-rpc/memory.h
@@ -21,7 +21,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x10000000UL)
+#define PHYS_OFFSET	UL(0x10000000)
 
 /*
  * These are exactly the same on the RiscPC as the
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
index ac57bc8..4790491 100644
--- a/include/asm-arm/arch-s3c2410/fb.h
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -13,6 +13,7 @@
  *	07-Sep-2004	RTP	Created file
  *	03-Nov-2004	BJD	Updated and minor cleanups
  *	03-Aug-2005     RTP     Renamed to fb.h
+ *	26-Oct-2005	BJD	Changed name of platdata init
 */
 
 #ifndef __ASM_ARM_FB_H
@@ -64,6 +65,6 @@
 	unsigned long	lpcsel;
 };
 
-void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info);
+extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
 
 #endif /* __ASM_ARM_FB_H */
diff --git a/include/asm-arm/arch-s3c2410/io.h b/include/asm-arm/arch-s3c2410/io.h
index 4bf272e..16fbc8a 100644
--- a/include/asm-arm/arch-s3c2410/io.h
+++ b/include/asm-arm/arch-s3c2410/io.h
@@ -15,6 +15,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-s3c2410/memory.h b/include/asm-arm/arch-s3c2410/memory.h
index 3380ab1..6ab834a 100644
--- a/include/asm-arm/arch-s3c2410/memory.h
+++ b/include/asm-arm/arch-s3c2410/memory.h
@@ -28,9 +28,9 @@
  * and at 0x0C000000 for S3C2400
  */
 #ifdef CONFIG_CPU_S3C2400
-#define PHYS_OFFSET	(0x0C000000UL)
+#define PHYS_OFFSET	UL(0x0C000000)
 #else
-#define PHYS_OFFSET	(0x30000000UL)
+#define PHYS_OFFSET	UL(0x30000000)
 #endif
 
 /*
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 2053cba..cb33d57 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -20,6 +20,7 @@
  *    18-11-2004     BJD     Added S3C2440 AC97 controls
  *    10-Mar-2005    LCVR    Changed S3C2410_VA to S3C24XX_VA
  *    28-Mar-2005    LCVR    Fixed definition of GPB10
+ *    26-Oct-2005    BJD     Added generic configuration types
 */
 
 
@@ -43,6 +44,11 @@
 /* general configuration options */
 
 #define S3C2410_GPIO_LEAVE   (0xFFFFFFFF)
+#define S3C2410_GPIO_INPUT   (0xFFFFFFF0)
+#define S3C2410_GPIO_OUTPUT  (0xFFFFFFF1)
+#define S3C2410_GPIO_IRQ     (0xFFFFFFF2)	/* not available for all */
+#define S3C2410_GPIO_SFN2    (0xFFFFFFF2)	/* not available on A */
+#define S3C2410_GPIO_SFN3    (0xFFFFFFF3)	/* not available on A */
 
 /* configure GPIO ports A..G */
 
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index 19c3b1e..28711aa 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -22,13 +22,6 @@
 
 
 /*
- * We requires absolute addresses i.e. (PCMCIA_IO_0_BASE + 0x3f8) for 
- * in*()/out*() macros to be usable for all cases.
- */
-#define PCIO_BASE		0
-
-
-/*
  * SA1100 internal I/O mappings
  *
  * We have the following mapping:
diff --git a/include/asm-arm/arch-sa1100/io.h b/include/asm-arm/arch-sa1100/io.h
index 7d969ff..9d4fe6c 100644
--- a/include/asm-arm/arch-sa1100/io.h
+++ b/include/asm-arm/arch-sa1100/io.h
@@ -10,13 +10,19 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
  * We don't actually have real ISA nor PCI buses, but there is so many 
  * drivers out there that might just work if we fake them...
  */
-#define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
+static inline void __iomem *__io(unsigned long addr)
+{
+	return (void __iomem *)addr;
+}
+#define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 #define __mem_isa(a)		(a)
 
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index 8743ff5..0fc555b 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -13,7 +13,7 @@
 /*
  * Physical DRAM offset is 0xc0000000 on the SA1100
  */
-#define PHYS_OFFSET	(0xc0000000UL)
+#define PHYS_OFFSET	UL(0xc0000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-arm/arch-sa1100/system.h b/include/asm-arm/arch-sa1100/system.h
index 6f52118..0f0612f 100644
--- a/include/asm-arm/arch-sa1100/system.h
+++ b/include/asm-arm/arch-sa1100/system.h
@@ -4,6 +4,7 @@
  * Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
  */
 #include <linux/config.h>
+#include <asm/hardware.h>
 
 static inline void arch_idle(void)
 {
diff --git a/include/asm-arm/arch-shark/io.h b/include/asm-arm/arch-shark/io.h
index 5e6ed00..87ffa27 100644
--- a/include/asm-arm/arch-shark/io.h
+++ b/include/asm-arm/arch-shark/io.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
+#include <asm/hardware.h>
+
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
diff --git a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h
index 8ff956d..95a29b4 100644
--- a/include/asm-arm/arch-shark/memory.h
+++ b/include/asm-arm/arch-shark/memory.h
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET     (0x08000000UL)
+#define PHYS_OFFSET     UL(0x08000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-arm/arch-versatile/memory.h b/include/asm-arm/arch-versatile/memory.h
index 7b8b7cc..a937097 100644
--- a/include/asm-arm/arch-versatile/memory.h
+++ b/include/asm-arm/arch-versatile/memory.h
@@ -23,7 +23,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	(0x00000000UL)
+#define PHYS_OFFSET	UL(0x00000000)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index d62ade4..e3e8541 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -70,7 +70,7 @@
  * device-viewed address.
  */
 extern void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp);
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
 
 /**
  * dma_free_coherent - free memory allocated by dma_alloc_coherent
@@ -117,7 +117,7 @@
  * device-viewed address.
  */
 extern void *
-dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, int gfp);
+dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
 
 #define dma_free_writecombine(dev,size,cpu_addr,handle) \
 	dma_free_coherent(dev,size,cpu_addr,handle)
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 5c4ae8f..2e67996 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
-#include <asm/arch/hardware.h>
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h
index 4fa9508..eb262e07 100644
--- a/include/asm-arm/mach/arch.h
+++ b/include/asm-arm/mach/arch.h
@@ -48,10 +48,11 @@
  * Set of macros to define architecture features.  This is built into
  * a table by the linker.
  */
-#define MACHINE_START(_type,_name)		\
-const struct machine_desc __mach_desc_##_type	\
+#define MACHINE_START(_type,_name)			\
+static const struct machine_desc __mach_desc_##_type	\
+ __attribute_used__					\
  __attribute__((__section__(".arch.info.init"))) = {	\
-	.nr		= MACH_TYPE_##_type,	\
+	.nr		= MACH_TYPE_##_type,		\
 	.name		= _name,
 
 #define MACHINE_END				\
diff --git a/include/asm-arm/mach/flash.h b/include/asm-arm/mach/flash.h
index a92887d..cd57436 100644
--- a/include/asm-arm/mach/flash.h
+++ b/include/asm-arm/mach/flash.h
@@ -14,6 +14,7 @@
 
 /*
  * map_name:	the map probe function name
+ * name:	flash device name (eg, as used with mtdparts=)
  * width:	width of mapped device
  * init:	method called at driver/device initialisation
  * exit:	method called at driver/device removal
@@ -23,6 +24,7 @@
  */
 struct flash_platform_data {
 	const char	*map_name;
+	const char	*name;
 	unsigned int	width;
 	int		(*init)(void);
 	void		(*exit)(void);
diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h
index 9ac47cf..b338936 100644
--- a/include/asm-arm/mach/map.h
+++ b/include/asm-arm/mach/map.h
@@ -11,7 +11,7 @@
  */
 struct map_desc {
 	unsigned long virtual;
-	unsigned long physical;
+	unsigned long pfn;
 	unsigned long length;
 	unsigned int type;
 };
@@ -27,6 +27,9 @@
 #define MT_ROM			6
 #define MT_IXP2000_DEVICE	7
 
+#define	__phys_to_pfn(paddr)	((paddr) >> PAGE_SHIFT)
+#define	__pfn_to_phys(pfn)	((pfn) << PAGE_SHIFT)
+
 extern void create_memmap_holes(struct meminfo *);
 extern void memtable_init(struct meminfo *);
 extern void iotable_init(struct map_desc *, int);
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index a8a933a..a547ee5 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -12,6 +12,16 @@
 #ifndef __ASM_ARM_MEMORY_H
 #define __ASM_ARM_MEMORY_H
 
+/*
+ * Allow for constants defined here to be used from assembly code
+ * by prepending the UL suffix only with actual C code compilation.
+ */
+#ifndef __ASSEMBLY__
+#define UL(x) (x##UL)
+#else
+#define UL(x) (x)
+#endif
+
 #include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/arch/memory.h>
@@ -21,20 +31,20 @@
  * TASK_SIZE - the maximum size of a user space task.
  * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
  */
-#define TASK_SIZE		(0xbf000000UL)
-#define TASK_UNMAPPED_BASE	(0x40000000UL)
+#define TASK_SIZE		UL(0xbf000000)
+#define TASK_UNMAPPED_BASE	UL(0x40000000)
 #endif
 
 /*
  * The maximum size of a 26-bit user space task.
  */
-#define TASK_SIZE_26		(0x04000000UL)
+#define TASK_SIZE_26		UL(0x04000000)
 
 /*
  * Page offset: 3GB
  */
 #ifndef PAGE_OFFSET
-#define PAGE_OFFSET		(0xc0000000UL)
+#define PAGE_OFFSET		UL(0xc0000000)
 #endif
 
 /*
@@ -58,6 +68,13 @@
 #error Top of user space clashes with start of module space
 #endif
 
+/*
+ * The XIP kernel gets mapped at the bottom of the module vm area.
+ * Since we use sections to map it, this macro replaces the physical address
+ * with its virtual address while keeping offset from the base section.
+ */
+#define XIP_VIRT_ADDR(physaddr)  (MODULE_START + ((physaddr) & 0x000fffff))
+
 #ifndef __ASSEMBLY__
 
 /*
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 366bafb..5a0d19b 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -397,9 +397,6 @@
 #define pgd_clear(pgdp)		do { } while (0)
 #define set_pgd(pgd,pgdp)	do { } while (0)
 
-#define page_pte_prot(page,prot)	mk_pte(page, prot)
-#define page_pte(page)		mk_pte(page, __pgprot(0))
-
 /* to find an entry in a page-table-directory */
 #define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
 
diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
index 60f33e6..71ca7d4 100644
--- a/include/asm-arm/semaphore.h
+++ b/include/asm-arm/semaphore.h
@@ -24,8 +24,6 @@
 	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
 }
 
-#define __MUTEX_INITIALIZER(name) __SEMAPHORE_INIT(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count)	\
 	struct semaphore name = __SEMAPHORE_INIT(name,count)
 
diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
index 9bb325c..f49bfb7 100644
--- a/include/asm-arm/tlb.h
+++ b/include/asm-arm/tlb.h
@@ -27,11 +27,7 @@
  */
 struct mmu_gather {
 	struct mm_struct	*mm;
-	unsigned int		freed;
 	unsigned int		fullmm;
-
-	unsigned int		flushes;
-	unsigned int		avoided_flushes;
 };
 
 DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -39,11 +35,9 @@
 static inline struct mmu_gather *
 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	int cpu = smp_processor_id();
-	struct mmu_gather *tlb = &per_cpu(mmu_gathers, cpu);
+	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
 
 	tlb->mm = mm;
-	tlb->freed = 0;
 	tlb->fullmm = full_mm_flush;
 
 	return tlb;
@@ -52,24 +46,13 @@
 static inline void
 tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
-	struct mm_struct *mm = tlb->mm;
-	unsigned long freed = tlb->freed;
-	int rss = get_mm_counter(mm, rss);
-
-	if (rss < freed)
-		freed = rss;
-	add_mm_counter(mm, rss, -freed);
-
 	if (tlb->fullmm)
-		flush_tlb_mm(mm);
+		flush_tlb_mm(tlb->mm);
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
-}
 
-static inline unsigned int tlb_is_full_mm(struct mmu_gather *tlb)
-{
-	return tlb->fullmm;
+	put_cpu_var(mmu_gathers);
 }
 
 #define tlb_remove_tlb_entry(tlb,ptep,address)	do { } while (0)
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index c49df63..d626e70 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -544,7 +544,6 @@
 asmlinkage int sys_fork(struct pt_regs *regs);
 asmlinkage int sys_vfork(struct pt_regs *regs);
 asmlinkage int sys_pipe(unsigned long *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index f602cf5..a590250 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -98,8 +98,6 @@
 #define pfn_pte(pfn,prot)	(__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 #define pages_to_mb(x)		((x) >> (20 - PAGE_SHIFT))
 #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
-#define page_pte_prot(page,prot)	mk_pte(page, prot)
-#define page_pte(page)		mk_pte(page, __pgprot(0))
 
 /*
  * Terminology: PGD = Page Directory, PMD = Page Middle Directory,
diff --git a/include/asm-arm26/semaphore.h b/include/asm-arm26/semaphore.h
index c1b6a1e..ccf15e7 100644
--- a/include/asm-arm26/semaphore.h
+++ b/include/asm-arm26/semaphore.h
@@ -25,9 +25,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INIT(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count)	\
 	struct semaphore name = __SEMAPHORE_INIT(name,count)
 
diff --git a/include/asm-arm26/tlb.h b/include/asm-arm26/tlb.h
index 1316352..08ddd85 100644
--- a/include/asm-arm26/tlb.h
+++ b/include/asm-arm26/tlb.h
@@ -10,24 +10,20 @@
  */
 struct mmu_gather {
         struct mm_struct        *mm;
-        unsigned int            freed;
-	unsigned int            fullmm;
-
-        unsigned int            flushes;
-        unsigned int            avoided_flushes;
+        unsigned int            need_flush;
+        unsigned int            fullmm;
 };
 
-extern struct mmu_gather mmu_gathers[NR_CPUS];
+DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 static inline struct mmu_gather *
 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
-        int cpu = smp_processor_id();
-        struct mmu_gather *tlb = &mmu_gathers[cpu];
+        struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
 
         tlb->mm = mm;
-        tlb->freed = 0;
-	tlb->fullmm = full_mm_flush;
+        tlb->need_flush = 0;
+        tlb->fullmm = full_mm_flush;
 
         return tlb;
 }
@@ -35,30 +31,13 @@
 static inline void
 tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
-        struct mm_struct *mm = tlb->mm;
-        unsigned long freed = tlb->freed;
-        int rss = get_mm_counter(mm, rss);
-
-        if (rss < freed)
-                freed = rss;
-        add_mm_counter(mm, rss, -freed);
-
-        if (freed) {
-                flush_tlb_mm(mm);
-                tlb->flushes++;
-        } else {
-                tlb->avoided_flushes++;
-        }
+        if (tlb->need_flush)
+                flush_tlb_mm(tlb->mm);
 
         /* keep the page table cache within bounds */
         check_pgt_cache();
-}
 
-
-static inline unsigned int
-tlb_is_full_mm(struct mmu_gather *tlb)
-{
-     return tlb->fullmm;
+        put_cpu_var(mmu_gathers);
 }
 
 #define tlb_remove_tlb_entry(tlb,ptep,address)  do { } while (0)
@@ -71,7 +50,13 @@
         } while (0)
 #define tlb_end_vma(tlb,vma)                    do { } while (0)
 
-#define tlb_remove_page(tlb,page)       free_page_and_swap_cache(page)
+static inline void
+tlb_remove_page(struct mmu_gather *tlb, struct page *page)
+{
+        tlb->need_flush = 1;
+        free_page_and_swap_cache(page);
+}
+
 #define pte_free_tlb(tlb,ptep)          pte_free(ptep)
 #define pmd_free_tlb(tlb,pmdp)          pmd_free(pmdp)
 
diff --git a/include/asm-arm26/unistd.h b/include/asm-arm26/unistd.h
index dfa0b0c..be4c2fb 100644
--- a/include/asm-arm26/unistd.h
+++ b/include/asm-arm26/unistd.h
@@ -480,7 +480,6 @@
 asmlinkage int sys_fork(struct pt_regs *regs);
 asmlinkage int sys_vfork(struct pt_regs *regs);
 asmlinkage int sys_pipe(unsigned long *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-cris/dma-mapping.h b/include/asm-cris/dma-mapping.h
index 0b5c3fd..8eff513 100644
--- a/include/asm-cris/dma-mapping.h
+++ b/include/asm-cris/dma-mapping.h
@@ -15,14 +15,14 @@
 
 #ifdef CONFIG_PCI
 void *dma_alloc_coherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, int flag);
+			   dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle);
 #else
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                   int flag)
+                   gfp_t flag)
 {
         BUG();
         return NULL;
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
index 8ed7636..39faf69 100644
--- a/include/asm-cris/semaphore.h
+++ b/include/asm-cris/semaphore.h
@@ -33,9 +33,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
 }
 
-#define __MUTEX_INITIALIZER(name) \
-        __SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
         struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 28232ad..156a34b 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -367,7 +367,6 @@
 asmlinkage int sys_vfork(long r10, long r11, long r12, long r13,
 			long mof, long srp, struct pt_regs *regs);
 asmlinkage int sys_pipe(unsigned long __user *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-frv/dma-mapping.h b/include/asm-frv/dma-mapping.h
index 0206ab3..5003e01 100644
--- a/include/asm-frv/dma-mapping.h
+++ b/include/asm-frv/dma-mapping.h
@@ -13,7 +13,7 @@
 extern unsigned long __nongprelbss dma_coherent_mem_start;
 extern unsigned long __nongprelbss dma_coherent_mem_end;
 
-void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int gfp);
+void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp);
 void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle);
 
 /*
diff --git a/include/asm-frv/pci.h b/include/asm-frv/pci.h
index b4efe5e..1168451 100644
--- a/include/asm-frv/pci.h
+++ b/include/asm-frv/pci.h
@@ -32,7 +32,7 @@
 extern void pcibios_penalize_isa_irq(int irq);
 
 #ifdef CONFIG_MMU
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle);
 extern void consistent_free(void *vaddr);
 extern void consistent_sync(void *vaddr, size_t size, int direction);
 extern void consistent_sync_page(struct page *page, unsigned long offset,
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 473fb4b..b247e99 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -436,8 +436,6 @@
 	return pte;
 }
 
-#define page_pte(page)	page_pte_prot((page), __pgprot(0))
-
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
 #define pgd_index_k(addr) pgd_index(addr)
diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
index 3935456..b183962 100644
--- a/include/asm-frv/semaphore.h
+++ b/include/asm-frv/semaphore.h
@@ -47,9 +47,6 @@
 #define __SEMAPHORE_INITIALIZER(name,count) \
 { count, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __SEM_DEBUG_INIT(name) }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-generic/4level-fixup.h b/include/asm-generic/4level-fixup.h
index c20ec25..68c6fea 100644
--- a/include/asm-generic/4level-fixup.h
+++ b/include/asm-generic/4level-fixup.h
@@ -10,14 +10,9 @@
 
 #define pud_t				pgd_t
 
-#define pmd_alloc(mm, pud, address)			\
-({	pmd_t *ret;					\
-	if (pgd_none(*pud))				\
- 		ret = __pmd_alloc(mm, pud, address);	\
- 	else						\
-		ret = pmd_offset(pud, address);		\
- 	ret;						\
-})
+#define pmd_alloc(mm, pud, address) \
+	((unlikely(pgd_none(*(pud))) && __pmd_alloc(mm, pud, address))? \
+ 		NULL: pmd_offset(pud, address))
 
 #define pud_alloc(mm, pgd, address)	(pgd)
 #define pud_offset(pgd, start)		(pgd)
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h
index fd9de95..a7f1a55 100644
--- a/include/asm-generic/dma-mapping-broken.h
+++ b/include/asm-generic/dma-mapping-broken.h
@@ -6,7 +6,7 @@
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   int flag)
+		   gfp_t flag)
 {
 	BUG();
 	return NULL;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index ff28c8b..7dca30a 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -8,7 +8,7 @@
  *  - update the page tables
  *  - inform the TLB about the new one
  *
- * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock.
+ * We hold the mm semaphore for reading, and the pte lock.
  *
  * Note: the old pte is known to not be writable, so we don't need to
  * worry about dirty bits etc getting lost.
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 7d02983..cdd4145 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -35,16 +35,13 @@
 #endif
 
 /* 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.  This structure
- * can be per-CPU or per-MM as the page table lock is held for the duration of
- * TLB shootdown.
+ * any data needed by arch specific code for tlb_remove_page.
  */
 struct mmu_gather {
 	struct mm_struct	*mm;
 	unsigned int		nr;	/* set to ~0U means fast mode */
 	unsigned int		need_flush;/* Really unmapped some ptes? */
 	unsigned int		fullmm; /* non-zero means full mm flush */
-	unsigned long		freed;
 	struct page *		pages[FREE_PTE_NR];
 };
 
@@ -57,7 +54,7 @@
 static inline struct mmu_gather *
 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	struct mmu_gather *tlb = &per_cpu(mmu_gathers, smp_processor_id());
+	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
 
 	tlb->mm = mm;
 
@@ -65,7 +62,6 @@
 	tlb->nr = num_online_cpus() > 1 ? 0U : ~0U;
 
 	tlb->fullmm = full_mm_flush;
-	tlb->freed = 0;
 
 	return tlb;
 }
@@ -85,28 +81,17 @@
 
 /* tlb_finish_mmu
  *	Called at the end of the shootdown operation to free up any resources
- *	that were required.  The page table lock is still held at this point.
+ *	that were required.
  */
 static inline void
 tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
-	int freed = tlb->freed;
-	struct mm_struct *mm = tlb->mm;
-	int rss = get_mm_counter(mm, rss);
-
-	if (rss < freed)
-		freed = rss;
-	add_mm_counter(mm, rss, -freed);
 	tlb_flush_mmu(tlb, start, end);
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
-}
 
-static inline unsigned int
-tlb_is_full_mm(struct mmu_gather *tlb)
-{
-	return tlb->fullmm;
+	put_cpu_var(mmu_gathers);
 }
 
 /* tlb_remove_page
diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
index fe6ef37..81bae2a 100644
--- a/include/asm-h8300/semaphore.h
+++ b/include/asm-h8300/semaphore.h
@@ -35,9 +35,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index 56a6401..56a4a56 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -528,7 +528,6 @@
 asmlinkage int sys_execve(char *name, char **argv, char **envp,
 			int dummy, ...);
 asmlinkage int sys_pipe(unsigned long *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 8c454aa..a515e2a 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -118,7 +118,8 @@
 extern void disable_timer_nmi_watchdog(void);
 extern void enable_timer_nmi_watchdog(void);
 extern void nmi_watchdog_tick (struct pt_regs * regs);
-extern int APIC_init_uniprocessor (void);
+extern int APIC_init(void);
+extern void APIC_late_time_init(void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 6df1a53..29b851a 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -17,6 +17,8 @@
 extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
 DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
 
+#define get_cpu_gdt_table(_cpu) (per_cpu(cpu_gdt_table,_cpu))
+
 DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
 
 struct Xgt_desc_struct {
@@ -60,7 +62,7 @@
 
 static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
 {
-	_set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[entry], (int)addr,
+	_set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
 		offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
 }
 
@@ -68,7 +70,7 @@
 
 static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
 {
-	_set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
+	_set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
 }
 
 #define LDT_entry_a(info) \
@@ -109,7 +111,7 @@
 
 static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 {
-#define C(i) per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
+#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
 	C(0); C(1); C(2);
 #undef C
 }
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 622815b..9139b89 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -55,6 +55,7 @@
 void FASTCALL(send_IPI_self(int vector));
 void init_VISWS_APIC_irqs(void);
 void setup_IO_APIC(void);
+void IO_APIC_late_time_init(void);
 void disable_IO_APIC(void);
 void print_IO_APIC(void);
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
diff --git a/include/asm-i386/mach-default/smpboot_hooks.h b/include/asm-i386/mach-default/smpboot_hooks.h
index 7f45f63..d7c70c1 100644
--- a/include/asm-i386/mach-default/smpboot_hooks.h
+++ b/include/asm-i386/mach-default/smpboot_hooks.h
@@ -1,11 +1,6 @@
 /* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
  * which needs to alter them. */
 
-static inline void smpboot_clear_io_apic_irqs(void)
-{
-	io_apic_irqs = 0;
-}
-
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
 	CMOS_WRITE(0xa, 0xf);
@@ -32,13 +27,3 @@
 
 	*((volatile long *) phys_to_virt(0x467)) = 0;
 }
-
-static inline void smpboot_setup_io_apic(void)
-{
-	/*
-	 * Here we can be sure that there is an IO-APIC in the system. Let's
-	 * go and set it up:
-	 */
-	if (!skip_ioapic_setup && nr_ioapics)
-		setup_IO_APIC();
-}
diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
index 28a84f6..4a0637a 100644
--- a/include/asm-i386/mach-es7000/mach_mpparse.h
+++ b/include/asm-i386/mach-es7000/mach_mpparse.h
@@ -16,7 +16,7 @@
 
 extern int parse_unisys_oem (char *oemptr);
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
-extern void setup_unisys();
+extern void setup_unisys(void);
 
 static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
 		char *productid)
diff --git a/include/asm-i386/mach-summit/mach_mpparse.h b/include/asm-i386/mach-summit/mach_mpparse.h
index 2b9e6d5..1cce2b9 100644
--- a/include/asm-i386/mach-summit/mach_mpparse.h
+++ b/include/asm-i386/mach-summit/mach_mpparse.h
@@ -22,7 +22,6 @@
 {
 }
 
-extern int usb_early_handoff;
 static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
 		char *productid)
 {
@@ -32,7 +31,6 @@
 			 || !strncmp(productid, "RUTHLESS SMP", 12))){
 		use_cyclone = 1; /*enable cyclone-timer*/
 		setup_summit();
-		usb_early_handoff = 1;
 		return 1;
 	}
 	return 0;
@@ -46,7 +44,6 @@
 	     || !strncmp(oem_table_id, "EXA", 3))){
 		use_cyclone = 1; /*enable cyclone-timer*/
 		setup_summit();
-		usb_early_handoff = 1;
 		return 1;
 	}
 	return 0;
diff --git a/include/asm-i386/mach-visws/smpboot_hooks.h b/include/asm-i386/mach-visws/smpboot_hooks.h
index d926471..14d8e03 100644
--- a/include/asm-i386/mach-visws/smpboot_hooks.h
+++ b/include/asm-i386/mach-visws/smpboot_hooks.h
@@ -11,14 +11,7 @@
 
 /* for visws do nothing for any of these */
 
-static inline void smpboot_clear_io_apic_irqs(void)
-{
-}
-
 static inline void smpboot_restore_warm_reset_vector(void)
 {
 }
 
-static inline void smpboot_setup_io_apic(void)
-{
-}
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 348fe3a..620a906 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -88,12 +88,6 @@
 	__pgdat->node_start_pfn + __pgdat->node_spanned_pages;		\
 })
 
-#define local_mapnr(kvaddr)						\
-({									\
-	unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT;		\
-	(__pfn - node_start_pfn(pfn_to_nid(__pfn)));			\
-})
-
 /* XXX: FIXME -- wli */
 #define kern_addr_valid(kaddr)	(0)
 
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index fa07bd6..74ef721 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -26,11 +26,6 @@
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
-#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
-
-#define pmd_page_kernel(pmd) \
-((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-
 /*
  * All present user pages are user-executable:
  */
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index 2e3f4a3..f1a8b45 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -74,11 +74,6 @@
  */
 static inline void pud_clear (pud_t * pud) { }
 
-#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
-
-#define pmd_page_kernel(pmd) \
-((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-
 #define pud_page(pud) \
 ((struct page *) __va(pud_val(pud) & PAGE_MASK))
 
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index d101ac4..03f3c8a 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -203,7 +203,8 @@
 #define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
-#define pmd_none(x)	(!pmd_val(x))
+/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
+#define pmd_none(x)	(!(unsigned long)pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
 #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
@@ -322,8 +323,6 @@
 	return pte;
 }
 
-#define page_pte(page) page_pte_prot(page, __pgprot(0))
-
 #define pmd_large(pmd) \
 ((pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT))
 
@@ -368,6 +367,11 @@
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
 
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+
+#define pmd_page_kernel(pmd) \
+		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
 /*
  * Helper function that returns the kernel pagetable entry controlling
  * the virtual address 'address'. NULL means no pagetable entry present.
diff --git a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h
index 7625a67..be4ab85 100644
--- a/include/asm-i386/rwsem.h
+++ b/include/asm-i386/rwsem.h
@@ -284,5 +284,10 @@
 	return tmp+delta;
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _I386_RWSEM_H */
diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
index ea563da..6a42b21 100644
--- a/include/asm-i386/semaphore.h
+++ b/include/asm-i386/semaphore.h
@@ -55,9 +55,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index acd5c26..97d52ac 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -167,6 +167,8 @@
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
 
+#ifdef CONFIG_X86_CMPXCHG64
+
 /*
  * The semantics of XCHGCMP8B are a bit strange, this is why
  * there is a loop and the loading of %%eax and %%edx has to
@@ -221,6 +223,8 @@
  __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
  __set_64bit(ptr, ll_low(value), ll_high(value)) )
 
+#endif
+
 /*
  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
  * Note 2: xchg has side effect, so that attribute volatile is necessary,
@@ -259,7 +263,6 @@
 
 #ifdef CONFIG_X86_CMPXCHG
 #define __HAVE_ARCH_CMPXCHG 1
-#endif
 
 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 				      unsigned long new, int size)
@@ -275,13 +278,13 @@
 	case 2:
 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
 				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
 				     : "memory");
 		return prev;
 	case 4:
 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
 				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
 				     : "memory");
 		return prev;
 	}
@@ -291,6 +294,30 @@
 #define cmpxchg(ptr,o,n)\
 	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
 					(unsigned long)(n),sizeof(*(ptr))))
+
+#endif
+
+#ifdef CONFIG_X86_CMPXCHG64
+
+static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
+				      unsigned long long new)
+{
+	unsigned long long prev;
+	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
+			     : "=A"(prev)
+			     : "b"((unsigned long)new),
+			       "c"((unsigned long)(new >> 32)),
+			       "m"(*__xg(ptr)),
+			       "0"(old)
+			     : "memory");
+	return prev;
+}
+
+#define cmpxchg64(ptr,o,n)\
+	((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
+					(unsigned long long)(n)))
+
+#endif
     
 #ifdef __KERNEL__
 struct alt_instr { 
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index fbaf90a..0f92e78 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -448,7 +448,6 @@
 asmlinkage int sys_fork(struct pt_regs regs);
 asmlinkage int sys_vfork(struct pt_regs regs);
 asmlinkage int sys_pipe(unsigned long __user *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 asmlinkage long sys_iopl(unsigned long unused);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index 79e89a7..ca5ea99 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -26,7 +26,7 @@
 typedef void ia64_mv_irq_init_t (void);
 typedef void ia64_mv_send_ipi_t (int, int, int, int);
 typedef void ia64_mv_timer_interrupt_t (int, void *, struct pt_regs *);
-typedef void ia64_mv_global_tlb_purge_t (unsigned long, unsigned long, unsigned long);
+typedef void ia64_mv_global_tlb_purge_t (struct mm_struct *, unsigned long, unsigned long, unsigned long);
 typedef void ia64_mv_tlb_migrate_finish_t (struct mm_struct *);
 typedef unsigned int ia64_mv_local_vector_to_irq (u8);
 typedef char *ia64_mv_pci_get_legacy_mem_t (struct pci_bus *);
@@ -37,7 +37,7 @@
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
-typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, int);
+typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, gfp_t);
 typedef void ia64_mv_dma_free_coherent (struct device *, size_t, void *, dma_addr_t);
 typedef dma_addr_t ia64_mv_dma_map_single (struct device *, void *, size_t, int);
 typedef void ia64_mv_dma_unmap_single (struct device *, dma_addr_t, size_t, int);
diff --git a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h
index daafe50..e90daf9 100644
--- a/include/asm-ia64/machvec_hpzx1.h
+++ b/include/asm-ia64/machvec_hpzx1.h
@@ -1,8 +1,7 @@
 #ifndef _ASM_IA64_MACHVEC_HPZX1_h
 #define _ASM_IA64_MACHVEC_HPZX1_h
 
-extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_setup_t			sba_setup;
+extern ia64_mv_setup_t			dig_setup;
 extern ia64_mv_dma_alloc_coherent	sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent	sba_free_coherent;
 extern ia64_mv_dma_map_single		sba_map_single;
@@ -19,15 +18,15 @@
  * platform's machvec structure.  When compiling a non-generic kernel,
  * the macros are used directly.
  */
-#define platform_name			"hpzx1"
-#define platform_setup			sba_setup
-#define platform_dma_init		machvec_noop
-#define platform_dma_alloc_coherent	sba_alloc_coherent
-#define platform_dma_free_coherent	sba_free_coherent
-#define platform_dma_map_single		sba_map_single
-#define platform_dma_unmap_single	sba_unmap_single
-#define platform_dma_map_sg		sba_map_sg
-#define platform_dma_unmap_sg		sba_unmap_sg
+#define platform_name				"hpzx1"
+#define platform_setup				dig_setup
+#define platform_dma_init			machvec_noop
+#define platform_dma_alloc_coherent		sba_alloc_coherent
+#define platform_dma_free_coherent		sba_free_coherent
+#define platform_dma_map_single			sba_map_single
+#define platform_dma_unmap_single		sba_unmap_single
+#define platform_dma_map_sg			sba_map_sg
+#define platform_dma_unmap_sg			sba_unmap_sg
 #define platform_dma_sync_single_for_cpu	machvec_dma_sync_single
 #define platform_dma_sync_sg_for_cpu		machvec_dma_sync_sg
 #define platform_dma_sync_single_for_device	machvec_dma_sync_single
diff --git a/include/asm-ia64/machvec_hpzx1_swiotlb.h b/include/asm-ia64/machvec_hpzx1_swiotlb.h
index 9924b1b..f00a34a 100644
--- a/include/asm-ia64/machvec_hpzx1_swiotlb.h
+++ b/include/asm-ia64/machvec_hpzx1_swiotlb.h
@@ -2,7 +2,6 @@
 #define _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h
 
 extern ia64_mv_setup_t				dig_setup;
-extern ia64_mv_dma_init				hwsw_init;
 extern ia64_mv_dma_alloc_coherent		hwsw_alloc_coherent;
 extern ia64_mv_dma_free_coherent		hwsw_free_coherent;
 extern ia64_mv_dma_map_single			hwsw_map_single;
@@ -26,7 +25,7 @@
 #define platform_name				"hpzx1_swiotlb"
 
 #define platform_setup				dig_setup
-#define platform_dma_init			hwsw_init
+#define platform_dma_init			machvec_noop
 #define platform_dma_alloc_coherent		hwsw_alloc_coherent
 #define platform_dma_free_coherent		hwsw_free_coherent
 #define platform_dma_map_single			hwsw_map_single
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index 1590dc6..46501b0 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -16,10 +16,11 @@
  * 	- initrd (optional)
  * 	- command line string
  * 	- kernel code & data
+ * 	- Kernel memory map built from EFI memory map
  *
  * More could be added if necessary
  */
-#define IA64_MAX_RSVD_REGIONS 5
+#define IA64_MAX_RSVD_REGIONS 6
 
 struct rsvd_region {
 	unsigned long start;	/* virtual address of beginning of element */
@@ -33,6 +34,7 @@
 extern void reserve_memory (void);
 extern void find_initrd (void);
 extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
+extern void efi_memmap_init(unsigned long *, unsigned long *);
 
 /*
  * For rounding an address to the next IA64_GRANULE_SIZE or order
@@ -41,7 +43,7 @@
 #define GRANULEROUNDUP(n)	(((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1))
 #define ORDERROUNDDOWN(n)	((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
   extern void call_pernode_memory (unsigned long start, unsigned long len, void *func);
 #else
 # define call_pernode_memory(start, len, func)	(*func)(start, len, 0)
diff --git a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
index d32f51e..34efe88 100644
--- a/include/asm-ia64/mmzone.h
+++ b/include/asm-ia64/mmzone.h
@@ -15,7 +15,7 @@
 #include <asm/page.h>
 #include <asm/meminit.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 
 static inline int pfn_to_nid(unsigned long pfn)
 {
@@ -31,6 +31,10 @@
 #endif
 }
 
+#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+extern int early_pfn_to_nid(unsigned long pfn);
+#endif
+
 #ifdef CONFIG_IA64_DIG /* DIG systems are small */
 # define MAX_PHYSNODE_ID	8
 # define NR_NODE_MEMBLKS	(MAX_NUMNODES * 8)
@@ -39,8 +43,8 @@
 # define NR_NODE_MEMBLKS	(MAX_NUMNODES * 4)
 #endif
 
-#else /* CONFIG_DISCONTIGMEM */
+#else /* CONFIG_NUMA */
 # define NR_NODE_MEMBLKS	(MAX_NUMNODES * 4)
-#endif /* CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_MMZONE_H */
diff --git a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h
index 6b0f3ed..9978c7c 100644
--- a/include/asm-ia64/nodedata.h
+++ b/include/asm-ia64/nodedata.h
@@ -17,7 +17,7 @@
 #include <asm/percpu.h>
 #include <asm/mmzone.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 
 /*
  * Node Data. One of these structures is located on each node of a NUMA system.
@@ -47,6 +47,6 @@
  */
 #define NODE_DATA(nid)		(local_node_data->pg_data_ptrs[nid])
 
-#endif /* CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_NODEDATA_H */
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 9edffad..ef436b9 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -102,15 +102,15 @@
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 extern int ia64_pfn_valid (unsigned long pfn);
-#else
+#elif defined(CONFIG_FLATMEM)
 # define ia64_pfn_valid(pfn) 1
 #endif
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 # define pfn_valid(pfn)		(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
 # define page_to_pfn(page)	((unsigned long) (page - mem_map))
 # define pfn_to_page(pfn)	(mem_map + (pfn))
-#else
+#elif defined(CONFIG_DISCONTIGMEM)
 extern struct page *vmem_map;
 extern unsigned long max_low_pfn;
 # define pfn_valid(pfn)		(((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 3339c7b..21e32a0 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -236,9 +236,6 @@
 #define pte_modify(_pte, newprot) \
 	(__pte((pte_val(_pte) & ~_PAGE_CHG_MASK) | (pgprot_val(newprot) & _PAGE_CHG_MASK)))
 
-#define page_pte_prot(page,prot)	mk_pte(page, prot)
-#define page_pte(page)			page_pte_prot(page, __pgprot(0))
-
 #define pte_none(pte) 			(!pte_val(pte))
 #define pte_present(pte)		(pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
 #define pte_clear(mm,addr,pte)		(pte_val(*(pte)) = 0UL)
diff --git a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h
index e18b5ab..1327c91 100644
--- a/include/asm-ia64/rwsem.h
+++ b/include/asm-ia64/rwsem.h
@@ -186,4 +186,9 @@
 #define rwsem_atomic_add(delta, sem)	atomic64_add(delta, (atomic64_t *)(&(sem)->count))
 #define rwsem_atomic_update(delta, sem)	atomic64_add_return(delta, (atomic64_t *)(&(sem)->count))
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* _ASM_IA64_RWSEM_H */
diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
index 3a2f0f3..bb89062 100644
--- a/include/asm-ia64/semaphore.h
+++ b/include/asm-ia64/semaphore.h
@@ -24,8 +24,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name)	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count)					\
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
 
diff --git a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h
index ab827d2..1a3831c 100644
--- a/include/asm-ia64/sn/arch.h
+++ b/include/asm-ia64/sn/arch.h
@@ -18,6 +18,32 @@
 #include <asm/sn/sn_cpuid.h>
 
 /*
+ * This is the maximum number of NUMALINK nodes that can be part of a single
+ * SSI kernel. This number includes C-brick, M-bricks, and TIOs. Nodes in
+ * remote partitions are NOT included in this number.
+ * The number of compact nodes cannot exceed size of a coherency domain.
+ * The purpose of this define is to specify a node count that includes
+ * all C/M/TIO nodes in an SSI system.
+ *
+ * SGI system can currently support up to 256 C/M nodes plus additional TIO nodes.
+ *
+ * 	Note: ACPI20 has an architectural limit of 256 nodes. When we upgrade
+ * 	to ACPI3.0, this limit will be removed. The notion of "compact nodes"
+ * 	should be deleted and TIOs should be included in MAX_NUMNODES.
+ */
+#define MAX_COMPACT_NODES	512
+
+/*
+ * Maximum number of nodes in all partitions and in all coherency domains.
+ * This is the total number of nodes accessible in the numalink fabric. It
+ * includes all C & M bricks, plus all TIOs.
+ *
+ * This value is also the value of the maximum number of NASIDs in the numalink
+ * fabric.
+ */
+#define MAX_NUMALINK_NODES	16384
+
+/*
  * The following defines attributes of the HUB chip. These attributes are
  * frequently referenced. They are kept in the per-cpu data areas of each cpu.
  * They are kept together in a struct to minimize cache misses.
@@ -41,15 +67,6 @@
 
 
 /*
- * This is the maximum number of nodes that can be part of a kernel.
- * Effectively, it's the maximum number of compact node ids (cnodeid_t).
- * This is not necessarily the same as MAX_NASIDS.
- */
-#define MAX_COMPACT_NODES	2048
-#define CPUS_PER_NODE		4
-
-
-/*
  * Compact node ID to nasid mappings kept in the per-cpu data areas of each
  * cpu.
  */
@@ -57,7 +74,6 @@
 #define sn_cnodeid_to_nasid	(&__get_cpu_var(__sn_cnodeid_to_nasid[0]))
 
 
-
 extern u8 sn_partition_id;
 extern u8 sn_system_size;
 extern u8 sn_sharing_domain_size;
diff --git a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
index 4220973..41c73a7 100644
--- a/include/asm-ia64/sn/io.h
+++ b/include/asm-ia64/sn/io.h
@@ -14,7 +14,7 @@
 extern void * sn_io_addr(unsigned long port) __attribute_const__; /* Forward definition */
 extern void __sn_mmiowb(void); /* Forward definition */
 
-extern int numionodes;
+extern int num_cnodes;
 
 #define __sn_mf_a()   ia64_mfa()
 
@@ -36,6 +36,15 @@
 #define __sn_readq_relaxed ___sn_readq_relaxed
 
 /*
+ * Convenience macros for setting/clearing bits using the above accessors
+ */
+
+#define __sn_setq_relaxed(addr, val) \
+	writeq((__sn_readq_relaxed(addr) | (val)), (addr))
+#define __sn_clrq_relaxed(addr, val) \
+	writeq((__sn_readq_relaxed(addr) & ~(val)), (addr))
+
+/*
  * The following routines are SN Platform specific, called when
  * a reference is made to inX/outX set macros.  SN Platform
  * inX set of macros ensures that Posted DMA writes on the
diff --git a/include/asm-ia64/sn/klconfig.h b/include/asm-ia64/sn/klconfig.h
index 9f920c7..bcbf209 100644
--- a/include/asm-ia64/sn/klconfig.h
+++ b/include/asm-ia64/sn/klconfig.h
@@ -208,19 +208,6 @@
 	klconf_off_t	brd_next_same;    /* Next BOARD with same nasid */
 } lboard_t;
 
-#define KLCF_NUM_COMPS(_brd)	((_brd)->brd_numcompts)
-#define NODE_OFFSET_TO_KLINFO(n,off)    ((klinfo_t*) TO_NODE_CAC(n,off))
-#define KLCF_NEXT(_brd)         \
-        ((_brd)->brd_next_same ?     \
-         (NODE_OFFSET_TO_LBOARD((_brd)->brd_next_same_host, (_brd)->brd_next_same)): NULL)
-#define KLCF_NEXT_ANY(_brd)         \
-        ((_brd)->brd_next_any ?     \
-         (NODE_OFFSET_TO_LBOARD(NASID_GET(_brd), (_brd)->brd_next_any)): NULL)
-#define KLCF_COMP(_brd, _ndx)   \
-                ((((_brd)->brd_compts[(_ndx)]) == 0) ? 0 : \
-			(NODE_OFFSET_TO_KLINFO(NASID_GET(_brd), (_brd)->brd_compts[(_ndx)])))
-
-
 /*
  * Generic info structure. This stores common info about a 
  * component.
@@ -249,24 +236,11 @@
 } klinfo_t ;
 
 
-static inline lboard_t *find_lboard_any(lboard_t * start, unsigned char brd_type)
+static inline lboard_t *find_lboard_next(lboard_t * brd)
 {
-        /* Search all boards stored on this node. */
-
-        while (start) {
-                if (start->brd_type == brd_type)
-                        return start;
-                start = KLCF_NEXT_ANY(start);
-        }
-        /* Didn't find it. */
-        return (lboard_t *) NULL;
+	if (brd && brd->brd_next_any)
+		return NODE_OFFSET_TO_LBOARD(NASID_GET(brd), brd->brd_next_any);
+        return NULL;
 }
 
-
-/* external declarations of Linux kernel functions. */
-
-extern lboard_t *root_lboard[];
-extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type);
-extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type);
-
 #endif /* _ASM_IA64_SN_KLCONFIG_H */
diff --git a/include/asm-ia64/sn/l1.h b/include/asm-ia64/sn/l1.h
index 2e5f0aa..e3b8191 100644
--- a/include/asm-ia64/sn/l1.h
+++ b/include/asm-ia64/sn/l1.h
@@ -35,4 +35,16 @@
 #define L1_BRICKTYPE_ATHENA	0x2b            /* + */
 #define L1_BRICKTYPE_DAYTONA	0x7a            /* z */
 
+/* board type response codes */
+#define L1_BOARDTYPE_IP69       0x0100          /* CA */
+#define L1_BOARDTYPE_IP63       0x0200          /* CB */
+#define L1_BOARDTYPE_BASEIO     0x0300          /* IB */
+#define L1_BOARDTYPE_PCIE2SLOT  0x0400          /* IC */
+#define L1_BOARDTYPE_PCIX3SLOT  0x0500          /* ID */
+#define L1_BOARDTYPE_PCIXPCIE4SLOT 0x0600       /* IE */
+#define L1_BOARDTYPE_ABACUS     0x0700          /* AB */
+#define L1_BOARDTYPE_DAYTONA    0x0800          /* AD */
+#define L1_BOARDTYPE_INVAL      (-1)            /* invalid brick type */
+
+
 #endif /* _ASM_IA64_SN_L1_H */
diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h
index 47bb810..6f6d69e 100644
--- a/include/asm-ia64/sn/nodepda.h
+++ b/include/asm-ia64/sn/nodepda.h
@@ -55,7 +55,6 @@
 	 */
 	struct phys_cpuid	phys_cpuid[NR_CPUS];
 	spinlock_t		ptc_lock ____cacheline_aligned_in_smp;
-	spinlock_t		bist_lock;
 };
 
 typedef struct nodepda_s nodepda_t;
diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
index d2c1d34..749deb2 100644
--- a/include/asm-ia64/sn/sn_cpuid.h
+++ b/include/asm-ia64/sn/sn_cpuid.h
@@ -105,7 +105,6 @@
 #define cpuid_to_nasid(cpuid)		(sn_nodepda->phys_cpuid[cpuid].nasid)
 #define cpuid_to_subnode(cpuid)		(sn_nodepda->phys_cpuid[cpuid].subnode)
 #define cpuid_to_slice(cpuid)		(sn_nodepda->phys_cpuid[cpuid].slice)
-#define cpuid_to_cnodeid(cpuid)		(physical_node_map[cpuid_to_nasid(cpuid)])
 
 
 /*
@@ -113,8 +112,6 @@
  * of potentially large tables.
  */
 extern int nasid_slice_to_cpuid(int, int);
-#define nasid_slice_to_cpu_physical_id(nasid, slice)			\
-	cpu_physical_id(nasid_slice_to_cpuid(nasid, slice))
 
 /*
  * cnodeid_to_nasid - convert a cnodeid to a NASID
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index fea35b3..3f7564d 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -47,6 +47,7 @@
 #define  SN_SAL_CONSOLE_PUTB			   0x02000028
 #define  SN_SAL_CONSOLE_XMIT_CHARS		   0x0200002a
 #define  SN_SAL_CONSOLE_READC			   0x0200002b
+#define  SN_SAL_SYSCTL_OP			   0x02000030
 #define  SN_SAL_SYSCTL_MODID_GET	           0x02000031
 #define  SN_SAL_SYSCTL_GET                         0x02000032
 #define  SN_SAL_SYSCTL_IOBRICK_MODULE_GET          0x02000033
@@ -67,7 +68,7 @@
 #define  SN_SAL_IOIF_INTERRUPT			   0x0200004a
 #define  SN_SAL_HWPERF_OP			   0x02000050   // lock
 #define  SN_SAL_IOIF_ERROR_INTERRUPT		   0x02000051
-
+#define  SN_SAL_IOIF_PCI_SAFE			   0x02000052
 #define  SN_SAL_IOIF_SLOT_ENABLE		   0x02000053
 #define  SN_SAL_IOIF_SLOT_DISABLE		   0x02000054
 #define  SN_SAL_IOIF_GET_HUBDEV_INFO		   0x02000055
@@ -101,6 +102,13 @@
 #define SAL_INTR_FREE		2
 
 /*
+ * operations available on the generic SN_SAL_SYSCTL_OP
+ * runtime service
+ */
+#define SAL_SYSCTL_OP_IOBOARD		0x0001  /*  retrieve board type */
+#define SAL_SYSCTL_OP_TIO_JLCK_RST      0x0002  /* issue TIO clock reset */
+
+/*
  * IRouter (i.e. generalized system controller) operations
  */
 #define SAL_IROUTER_OPEN	0	/* open a subchannel */
@@ -198,26 +206,16 @@
 	return ret_stuff.v0;
 }
 
-static inline char *
+static inline void *
 ia64_sn_get_klconfig_addr(nasid_t nasid)
 {
 	struct ia64_sal_retval ret_stuff;
-	int cnodeid;
 
-	cnodeid = nasid_to_cnodeid(nasid);
 	ret_stuff.status = 0;
 	ret_stuff.v0 = 0;
 	ret_stuff.v1 = 0;
 	ret_stuff.v2 = 0;
 	SAL_CALL(ret_stuff, SN_SAL_GET_KLCONFIG_ADDR, (u64)nasid, 0, 0, 0, 0, 0, 0);
-
-	/*
-	 * We should panic if a valid cnode nasid does not produce
-	 * a klconfig address.
-	 */
-	if (ret_stuff.status != 0) {
-		panic("ia64_sn_get_klconfig_addr: Returned error %lx\n", ret_stuff.status);
-	}
 	return ret_stuff.v0 ? __va(ret_stuff.v0) : NULL;
 }
 
@@ -694,12 +692,10 @@
 	unsigned long irq_flags;
 
 	cnodeid = nasid_to_cnodeid(get_node_number(paddr));
-	// spin_lock(&NODEPDA(cnodeid)->bist_lock);
 	local_irq_save(irq_flags);
 	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
 				(u64)nasid_array, perms, 0, 0, 0);
 	local_irq_restore(irq_flags);
-	// spin_unlock(&NODEPDA(cnodeid)->bist_lock);
 	return ret_stuff.status;
 }
 #define SN_MEMPROT_ACCESS_CLASS_0		0x14a080
@@ -873,6 +869,41 @@
         return (int) rv.v0;
 }
 
+/*
+ * Ask the system controller on the specified nasid to reset
+ * the CX corelet clock.  Only valid on TIO nodes.
+ */
+static inline int
+ia64_sn_sysctl_tio_clock_reset(nasid_t nasid)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_TIO_JLCK_RST,
+			nasid, 0, 0, 0, 0, 0);
+	if (rv.status != 0)
+		return (int)rv.status;
+	if (rv.v0 != 0)
+		return (int)rv.v0;
+
+	return 0;
+}
+
+/*
+ * Get the associated ioboard type for a given nasid.
+ */
+static inline int
+ia64_sn_sysctl_ioboard_get(nasid_t nasid)
+{
+        struct ia64_sal_retval rv;
+        SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_IOBOARD,
+                        nasid, 0, 0, 0, 0, 0);
+        if (rv.v0 != 0)
+                return (int)rv.v0;
+        if (rv.v1 != 0)
+                return (int)rv.v1;
+
+        return 0;
+}
+
 /**
  * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
  * @nasid: NASID of node to read
diff --git a/include/asm-ia64/sn/tioca_provider.h b/include/asm-ia64/sn/tioca_provider.h
index 5ccec60..b532ef6 100644
--- a/include/asm-ia64/sn/tioca_provider.h
+++ b/include/asm-ia64/sn/tioca_provider.h
@@ -182,11 +182,11 @@
 			 * touch every CL aligned GART entry.
 			 */
 
-			ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
-			ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
-			ca_base->ca_control2 |=
-			    (0x2ull << CA_GART_MEM_PARAM_SHFT);
-			tmp = ca_base->ca_control2;
+			__sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
+			__sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
+			__sn_setq_relaxed(&ca_base->ca_control2,
+			    (0x2ull << CA_GART_MEM_PARAM_SHFT));
+			tmp = __sn_readq_relaxed(&ca_base->ca_control2);
 		}
 
 		return;
@@ -196,8 +196,8 @@
 	 * Gart in uncached mode ... need an explicit flush.
 	 */
 
-	ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
-	tmp = ca_base->ca_control2;
+	__sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
+	tmp = __sn_readq_relaxed(&ca_base->ca_control2);
 }
 
 extern uint32_t	tioca_gart_found;
diff --git a/include/asm-ia64/sn/tiocx.h b/include/asm-ia64/sn/tiocx.h
index c5447a5..5699e75 100644
--- a/include/asm-ia64/sn/tiocx.h
+++ b/include/asm-ia64/sn/tiocx.h
@@ -19,6 +19,7 @@
 
 struct cx_dev {
 	struct cx_id_s cx_id;
+	int bt;				/* board/blade type */
 	void *soft;			/* driver specific */
 	struct hubdev_info *hubdev;
 	struct device dev;
@@ -59,7 +60,7 @@
 extern struct sn_irq_info *tiocx_irq_alloc(nasid_t, int, int, nasid_t, int);
 extern void tiocx_irq_free(struct sn_irq_info *);
 extern int cx_device_unregister(struct cx_dev *);
-extern int cx_device_register(nasid_t, int, int, struct hubdev_info *);
+extern int cx_device_register(nasid_t, int, int, struct hubdev_info *, int);
 extern int cx_driver_unregister(struct cx_drv *);
 extern int cx_driver_register(struct cx_drv *);
 extern uint64_t tiocx_dma_addr(uint64_t addr);
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 1df1c9f..49faf8f 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -49,7 +49,7 @@
  * C-brick nasids, thus the need for bitmaps which don't account for
  * odd-numbered (non C-brick) nasids.
  */
-#define XP_MAX_PHYSNODE_ID	(MAX_PHYSNODE_ID / 2)
+#define XP_MAX_PHYSNODE_ID	(MAX_NUMALINK_NODES / 2)
 #define XP_NASID_MASK_BYTES	((XP_MAX_PHYSNODE_ID + 7) / 8)
 #define XP_NASID_MASK_WORDS	((XP_MAX_PHYSNODE_ID + 63) / 64)
 
@@ -217,7 +217,17 @@
 	xpcInvalidPartid,	/* 42: invalid partition ID */
 	xpcLocalPartid,		/* 43: local partition ID */
 
-	xpcUnknownReason	/* 44: unknown reason -- must be last in list */
+	xpcOtherGoingDown,	/* 44: other side going down, reason unknown */
+	xpcSystemGoingDown,	/* 45: system is going down, reason unknown */
+	xpcSystemHalt,		/* 46: system is being halted */
+	xpcSystemReboot,	/* 47: system is being rebooted */
+	xpcSystemPoweroff,	/* 48: system is being powered off */
+
+	xpcDisconnecting,	/* 49: channel disconnecting (closing) */
+
+	xpcOpenCloseError,	/* 50: channel open/close protocol error */
+
+	xpcUnknownReason	/* 51: unknown reason -- must be last in list */
 };
 
 
@@ -342,7 +352,7 @@
  *
  * The 'func' field points to the function to call when aynchronous
  * notification is required for such events as: a connection established/lost,
- * or an incomming message received, or an error condition encountered. A
+ * or an incoming message received, or an error condition encountered. A
  * non-NULL 'func' field indicates that there is an active registration for
  * the channel.
  */
diff --git a/include/asm-ia64/sparsemem.h b/include/asm-ia64/sparsemem.h
new file mode 100644
index 0000000..67a7c40
--- /dev/null
+++ b/include/asm-ia64/sparsemem.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_IA64_SPARSEMEM_H
+#define _ASM_IA64_SPARSEMEM_H
+
+#ifdef CONFIG_SPARSEMEM
+/*
+ * SECTION_SIZE_BITS            2^N: how big each section will be
+ * MAX_PHYSMEM_BITS             2^N: how much memory we can have in that space
+ */
+
+#define SECTION_SIZE_BITS	(30)
+#define MAX_PHYSMEM_BITS	(50)
+#ifdef CONFIG_FORCE_MAX_ZONEORDER
+#if ((CONFIG_FORCE_MAX_ZONEORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS)
+#undef SECTION_SIZE_BITS
+#define SECTION_SIZE_BITS (CONFIG_FORCE_MAX_ZONEORDER - 1 + PAGE_SHIFT)
+#endif
+#endif
+
+#endif /* CONFIG_SPARSEMEM */
+#endif /* _ASM_IA64_SPARSEMEM_H */
diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
index 3a9a6d1..834370b 100644
--- a/include/asm-ia64/tlb.h
+++ b/include/asm-ia64/tlb.h
@@ -60,7 +60,6 @@
 	unsigned int		nr;		/* == ~0U => fast mode */
 	unsigned char		fullmm;		/* non-zero means full mm flush */
 	unsigned char		need_flush;	/* really unmapped some PTEs? */
-	unsigned long		freed;		/* number of pages freed */
 	unsigned long		start_addr;
 	unsigned long		end_addr;
 	struct page 		*pages[FREE_PTE_NR];
@@ -129,7 +128,7 @@
 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);
+	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
 
 	tlb->mm = mm;
 	/*
@@ -147,25 +146,17 @@
 	 */
 	tlb->nr = (num_online_cpus() == 1) ? ~0U : 0;
 	tlb->fullmm = full_mm_flush;
-	tlb->freed = 0;
 	tlb->start_addr = ~0UL;
 	return tlb;
 }
 
 /*
  * Called at the end of the shootdown operation to free up any resources that were
- * collected.  The page table lock is still held at this point.
+ * collected.
  */
 static inline void
 tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
-	unsigned long freed = tlb->freed;
-	struct mm_struct *mm = tlb->mm;
-	unsigned long rss = get_mm_counter(mm, rss);
-
-	if (rss < freed)
-		freed = rss;
-	add_mm_counter(mm, rss, -freed);
 	/*
 	 * Note: tlb->nr may be 0 at this point, so we can't rely on tlb->start_addr and
 	 * tlb->end_addr.
@@ -174,12 +165,8 @@
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
-}
 
-static inline unsigned int
-tlb_is_full_mm(struct mmu_gather *tlb)
-{
-     return tlb->fullmm;
+	put_cpu_var(mmu_gathers);
 }
 
 /*
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 3a0c695..6d96a67 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -383,8 +383,6 @@
 long sys_execve(char __user *filename, char __user * __user *argv,
 			   char __user * __user *envp, struct pt_regs *regs);
 asmlinkage long sys_pipe(void);
-asmlinkage long sys_ptrace(long request, pid_t pid,
-			   unsigned long addr, unsigned long data);
 asmlinkage long sys_rt_sigaction(int sig,
 				 const struct sigaction __user *act,
 				 struct sigaction __user *oact,
diff --git a/include/asm-m32r/dma-mapping.h b/include/asm-m32r/dma-mapping.h
index 3a2db28..a7fa030 100644
--- a/include/asm-m32r/dma-mapping.h
+++ b/include/asm-m32r/dma-mapping.h
@@ -8,7 +8,7 @@
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   int flag)
+		   gfp_t flag)
 {
 	return (void *)NULL;
 }
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
index d58878e..adc7970 100644
--- a/include/asm-m32r/mmzone.h
+++ b/include/asm-m32r/mmzone.h
@@ -21,12 +21,6 @@
 	__pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1;	\
 })
 
-#define local_mapnr(kvaddr)						\
-({									\
-	unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT;		\
-	(__pfn - node_start_pfn(pfn_to_nid(__pfn)));			\
-})
-
 #define pfn_to_page(pfn)						\
 ({									\
 	unsigned long __pfn = pfn;					\
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 388e5ee..1cd5fd4 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -324,8 +324,6 @@
 	return pte;
 }
 
-#define page_pte(page)	page_pte_prot(page, __pgprot(0))
-
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index 53e3c60..bf447c5 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -32,9 +32,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
index 7a6be77..0f58936 100644
--- a/include/asm-m32r/thread_info.h
+++ b/include/asm-m32r/thread_info.h
@@ -95,7 +95,7 @@
 }
 
 /* thread information allocation */
-#if CONFIG_DEBUG_STACK_USAGE
+#ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk)					\
 	({							\
 		struct thread_info *ret;			\
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index 8552d8f..ac399e1 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -452,7 +452,6 @@
 asmlinkage int sys_fork(struct pt_regs regs);
 asmlinkage int sys_vfork(struct pt_regs regs);
 asmlinkage int sys_pipe(unsigned long __user *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				 const struct sigaction __user *act,
diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
index ab94cf3..fd4c7cc 100644
--- a/include/asm-m68k/semaphore.h
+++ b/include/asm-m68k/semaphore.h
@@ -36,9 +36,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-m68k/sun3xflop.h b/include/asm-m68k/sun3xflop.h
index 1ed3b78..fda1ecc 100644
--- a/include/asm-m68k/sun3xflop.h
+++ b/include/asm-m68k/sun3xflop.h
@@ -27,10 +27,8 @@
 
 /* We don't need no stinkin' I/O port allocation crap. */
 #undef release_region
-#undef check_region
 #undef request_region
 #define release_region(X, Y)	do { } while(0)
-#define check_region(X, Y)	(0)
 #define request_region(X, Y, Z)	(1)
 
 struct sun3xflop_private {
diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
index cbabde4..c2554bc 100644
--- a/include/asm-m68k/unistd.h
+++ b/include/asm-m68k/unistd.h
@@ -444,7 +444,6 @@
 			unsigned long fd, unsigned long pgoff);
 asmlinkage int sys_execve(char *name, char **argv, char **envp);
 asmlinkage int sys_pipe(unsigned long *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct pt_regs;
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
diff --git a/include/asm-m68knommu/ide.h b/include/asm-m68knommu/ide.h
index b1cbf8b..836f072 100644
--- a/include/asm-m68knommu/ide.h
+++ b/include/asm-m68knommu/ide.h
@@ -163,13 +163,6 @@
 }
 
 
-static IDE_INLINE int
-ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return 0;
-}
-
-
 static IDE_INLINE void
 ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
 {
diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
index febe85a..17aee15 100644
--- a/include/asm-m68knommu/semaphore.h
+++ b/include/asm-m68knommu/semaphore.h
@@ -35,9 +35,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
index 84b6fa1..5373988 100644
--- a/include/asm-m68knommu/unistd.h
+++ b/include/asm-m68knommu/unistd.h
@@ -504,7 +504,6 @@
 			unsigned long fd, unsigned long pgoff);
 asmlinkage int sys_execve(char *name, char **argv, char **envp);
 asmlinkage int sys_pipe(unsigned long *fildes);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct pt_regs;
 int sys_request_irq(unsigned int,
 			irqreturn_t (*)(int, void *, struct pt_regs *),
diff --git a/include/asm-mips/abi.h b/include/asm-mips/abi.h
new file mode 100644
index 0000000..2e7e651
--- /dev/null
+++ b/include/asm-mips/abi.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 by Ralf Baechle
+ * Copyright (C) 2005 MIPS Technologies, Inc.
+ */
+#ifndef _ASM_ABI_H
+#define _ASM_ABI_H
+
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+
+struct mips_abi {
+	int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs);
+	int (* const setup_frame)(struct k_sigaction * ka,
+	                          struct pt_regs *regs, int signr,
+	                          sigset_t *set);
+	int (* const setup_rt_frame)(struct k_sigaction * ka,
+	                       struct pt_regs *regs, int signr,
+	                       sigset_t *set, siginfo_t *info);
+};
+
+#endif /* _ASM_ABI_H */
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 7dc2619..42520cc 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -20,10 +20,12 @@
 #define _ATYPE_
 #define _ATYPE32_
 #define _ATYPE64_
+#define _LLCONST_(x)	x
 #else
 #define _ATYPE_		__PTRDIFF_TYPE__
 #define _ATYPE32_	int
 #define _ATYPE64_	long long
+#define _LLCONST_(x)	x ## LL
 #endif
 
 /*
@@ -45,8 +47,9 @@
 /*
  * Returns the physical address of a CKSEGx / XKPHYS address
  */
-#define CPHYSADDR(a)		((_ACAST32_ (a)) & 0x1fffffff)
-#define XPHYSADDR(a)            ((_ACAST64_ (a)) & 0x000000ffffffffff)
+#define CPHYSADDR(a)		((_ACAST32_(a)) & 0x1fffffff)
+#define XPHYSADDR(a)            ((_ACAST64_(a)) &			\
+				 _LLCONST_(0x000000ffffffffff))
 
 #ifdef CONFIG_64BIT
 
@@ -55,14 +58,14 @@
  * The compatibility segments use the full 64-bit sign extended value.  Note
  * the R8000 doesn't have them so don't reference these in generic MIPS code.
  */
-#define XKUSEG			0x0000000000000000
-#define XKSSEG			0x4000000000000000
-#define XKPHYS			0x8000000000000000
-#define XKSEG			0xc000000000000000
-#define CKSEG0			0xffffffff80000000
-#define CKSEG1			0xffffffffa0000000
-#define CKSSEG			0xffffffffc0000000
-#define CKSEG3			0xffffffffe0000000
+#define XKUSEG			_LLCONST_(0x0000000000000000)
+#define XKSSEG			_LLCONST_(0x4000000000000000)
+#define XKPHYS			_LLCONST_(0x8000000000000000)
+#define XKSEG			_LLCONST_(0xc000000000000000)
+#define CKSEG0			_LLCONST_(0xffffffff80000000)
+#define CKSEG1			_LLCONST_(0xffffffffa0000000)
+#define CKSSEG			_LLCONST_(0xffffffffc0000000)
+#define CKSEG3			_LLCONST_(0xffffffffe0000000)
 
 #define CKSEG0ADDR(a)		(CPHYSADDR(a) | CKSEG0)
 #define CKSEG1ADDR(a)		(CPHYSADDR(a) | CKSEG1)
@@ -120,7 +123,8 @@
 #define PHYS_TO_XKSEG_UNCACHED(p)	PHYS_TO_XKPHYS(K_CALG_UNCACHED,(p))
 #define PHYS_TO_XKSEG_CACHED(p)		PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE,(p))
 #define XKPHYS_TO_PHYS(p)		((p) & TO_PHYS_MASK)
-#define PHYS_TO_XKPHYS(cm,a)		(0x8000000000000000 | ((cm)<<59) | (a))
+#define PHYS_TO_XKPHYS(cm,a)		(_LLCONST_(0x8000000000000000) | \
+					 ((cm)<<59) | (a))
 
 #if defined (CONFIG_CPU_R4300)						\
     || defined (CONFIG_CPU_R4X00)					\
@@ -128,46 +132,56 @@
     || defined (CONFIG_CPU_NEVADA)					\
     || defined (CONFIG_CPU_TX49XX)					\
     || defined (CONFIG_CPU_MIPS64)
-#define	KUSIZE			0x0000010000000000	/* 2^^40 */
-#define	KUSIZE_64		0x0000010000000000	/* 2^^40 */
-#define	K0SIZE			0x0000001000000000	/* 2^^36 */
-#define	K1SIZE			0x0000001000000000	/* 2^^36 */
-#define	K2SIZE			0x000000ff80000000
-#define	KSEGSIZE		0x000000ff80000000	/* max syssegsz */
-#define TO_PHYS_MASK		0x0000000fffffffff	/* 2^^36 - 1 */
+#define KUSIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define KUSIZE_64	_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K0SIZE		_LLCONST_(0x0000001000000000)	/* 2^^36 */
+#define K1SIZE		_LLCONST_(0x0000001000000000)	/* 2^^36 */
+#define K2SIZE		_LLCONST_(0x000000ff80000000)
+#define KSEGSIZE	_LLCONST_(0x000000ff80000000)	/* max syssegsz */
+#define TO_PHYS_MASK	_LLCONST_(0x0000000fffffffff)	/* 2^^36 - 1 */
 #endif
 
 #if defined (CONFIG_CPU_R8000)
 /* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define	KUSIZE			0x0000010000000000	/* 2^^40 */
-#define	KUSIZE_64		0x0000010000000000	/* 2^^40 */
-#define	K0SIZE			0x0000010000000000	/* 2^^40 */
-#define	K1SIZE			0x0000010000000000	/* 2^^40 */
-#define	K2SIZE			0x0001000000000000
-#define	KSEGSIZE		0x0000010000000000	/* max syssegsz */
-#define TO_PHYS_MASK		0x000000ffffffffff	/* 2^^40 - 1 */
+#define KUSIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define KUSIZE_64	_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K0SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K1SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K2SIZE		_LLCONST_(0x0001000000000000)
+#define KSEGSIZE	_LLCONST_(0x0000010000000000)	/* max syssegsz */
+#define TO_PHYS_MASK	_LLCONST_(0x000000ffffffffff)	/* 2^^40 - 1 */
 #endif
 
 #if defined (CONFIG_CPU_R10000)
-#define	KUSIZE			0x0000010000000000	/* 2^^40 */
-#define	KUSIZE_64		0x0000010000000000	/* 2^^40 */
-#define	K0SIZE			0x0000010000000000	/* 2^^40 */
-#define	K1SIZE			0x0000010000000000	/* 2^^40 */
-#define	K2SIZE			0x00000fff80000000
-#define	KSEGSIZE		0x00000fff80000000	/* max syssegsz */
-#define TO_PHYS_MASK		0x000000ffffffffff	/* 2^^40 - 1 */
+#define KUSIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define KUSIZE_64	_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K0SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K1SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
+#define K2SIZE		_LLCONST_(0x00000fff80000000)
+#define KSEGSIZE	_LLCONST_(0x00000fff80000000)	/* max syssegsz */
+#define TO_PHYS_MASK	_LLCONST_(0x000000ffffffffff)	/* 2^^40 - 1 */
+#endif
+
+#if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
+#define KUSIZE		_LLCONST_(0x0000100000000000)	/* 2^^44 */
+#define KUSIZE_64	_LLCONST_(0x0000100000000000)	/* 2^^44 */
+#define K0SIZE		_LLCONST_(0x0000100000000000)	/* 2^^44 */
+#define K1SIZE		_LLCONST_(0x0000100000000000)	/* 2^^44 */
+#define K2SIZE		_LLCONST_(0x0000ffff80000000)
+#define KSEGSIZE	_LLCONST_(0x0000ffff80000000)	/* max syssegsz */
+#define TO_PHYS_MASK	_LLCONST_(0x00000fffffffffff)	/* 2^^44 - 1 */
 #endif
 
 /*
  * Further names for SGI source compatibility.  These are stolen from
  * IRIX's <sys/mips_addrspace.h>.
  */
-#define KUBASE			0
-#define KUSIZE_32		0x0000000080000000	/* KUSIZE
+#define KUBASE		_LLCONST_(0)
+#define KUSIZE_32	_LLCONST_(0x0000000080000000)	/* KUSIZE
 							   for a 32 bit proc */
-#define K0BASE_EXL_WR		0xa800000000000000	/* exclusive on write */
-#define K0BASE_NONCOH		0x9800000000000000	/* noncoherent */
-#define K0BASE_EXL		0xa000000000000000	/* exclusive */
+#define K0BASE_EXL_WR	_LLCONST_(0xa800000000000000)	/* exclusive on write */
+#define K0BASE_NONCOH	_LLCONST_(0x9800000000000000)	/* noncoherent */
+#define K0BASE_EXL	_LLCONST_(0xa000000000000000)	/* exclusive */
 
 #ifndef CONFIG_CPU_R8000
 
@@ -176,7 +190,7 @@
  * in order to catch bugs in the source code.
  */
 
-#define COMPAT_K1BASE32		0xffffffffa0000000
+#define COMPAT_K1BASE32		_LLCONST_(0xffffffffa0000000)
 #define PHYS_TO_COMPATK1(x)	((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
 
 #endif
diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h
index f532377..4b090f3 100644
--- a/include/asm-mips/asm.h
+++ b/include/asm-mips/asm.h
@@ -107,6 +107,7 @@
 /*
  * Print formatted string
  */
+#ifdef CONFIG_PRINTK
 #define PRINT(string)                                   \
 		.set	push;				\
 		.set	reorder;                        \
@@ -114,6 +115,9 @@
 		jal	printk;                         \
 		.set	pop;				\
 		TEXT(string)
+#else
+#define PRINT(string)
+#endif
 
 #define	TEXT(msg)                                       \
 		.pushsection .data;			\
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index c0bd8d0..6202eb8 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -62,20 +62,24 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%0, %1		# atomic_add		\n"
 		"	addu	%0, %2					\n"
 		"	sc	%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else if (cpu_has_llsc) {
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%0, %1		# atomic_add		\n"
 		"	addu	%0, %2					\n"
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else {
@@ -100,20 +104,24 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%0, %1		# atomic_sub		\n"
 		"	subu	%0, %2					\n"
 		"	sc	%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else if (cpu_has_llsc) {
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%0, %1		# atomic_sub		\n"
 		"	subu	%0, %2					\n"
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else {
@@ -136,12 +144,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%1, %2		# atomic_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 		"	sc	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -149,12 +159,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%1, %2		# atomic_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 		"	sc	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -179,12 +191,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%1, %2		# atomic_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 		"	sc	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -192,12 +206,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%1, %2		# atomic_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 		"	sc	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -229,6 +245,7 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
@@ -236,6 +253,7 @@
 		"	beqzl	%0, 1b					\n"
 		"	sync						\n"
 		"1:							\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -243,6 +261,7 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
 		"	subu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
@@ -250,6 +269,7 @@
 		"	beqz	%0, 1b					\n"
 		"	sync						\n"
 		"1:							\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -367,20 +387,24 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_add		\n"
 		"	addu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else if (cpu_has_llsc) {
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_add		\n"
 		"	addu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else {
@@ -405,20 +429,24 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_sub		\n"
 		"	subu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else if (cpu_has_llsc) {
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_sub		\n"
 		"	subu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter));
 	} else {
@@ -441,12 +469,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -454,12 +484,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_add_return	\n"
 		"	addu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	addu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -484,12 +516,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -497,12 +531,14 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_sub_return	\n"
 		"	subu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqz	%0, 1b					\n"
 		"	subu	%0, %1, %3				\n"
 		"	sync						\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -534,6 +570,7 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
@@ -541,6 +578,7 @@
 		"	beqzl	%0, 1b					\n"
 		"	sync						\n"
 		"1:							\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
@@ -548,6 +586,7 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
 		"	dsubu	%0, %1, %3				\n"
 		"	bltz	%0, 1f					\n"
@@ -555,6 +594,7 @@
 		"	beqz	%0, 1b					\n"
 		"	sync						\n"
 		"1:							\n"
+		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
 		: "memory");
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index eb8d79d..5496f90 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -12,20 +12,21 @@
 #include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <asm/bug.h>
 #include <asm/byteorder.h>		/* sigh ... */
 #include <asm/cpu-features.h>
 
 #if (_MIPS_SZLONG == 32)
 #define SZLONG_LOG 5
 #define SZLONG_MASK 31UL
-#define __LL	"ll	"
-#define __SC	"sc	"
+#define __LL		"ll	"
+#define __SC		"sc	"
 #define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x))
 #elif (_MIPS_SZLONG == 64)
 #define SZLONG_LOG 6
 #define SZLONG_MASK 63UL
-#define __LL	"lld	"
-#define __SC	"scd	"
+#define __LL		"lld	"
+#define __SC		"scd	"
 #define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x))
 #endif
 
@@ -72,18 +73,22 @@
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1			# set_bit	\n"
 		"	or	%0, %2					\n"
-		"	"__SC	"%0, %1					\n"
+		"	" __SC	"%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1			# set_bit	\n"
 		"	or	%0, %2					\n"
-		"	"__SC	"%0, %1					\n"
+		"	" __SC	"%0, %1					\n"
 		"	beqz	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
 	} else {
@@ -132,18 +137,22 @@
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1			# clear_bit	\n"
 		"	and	%0, %2					\n"
 		"	" __SC "%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1			# clear_bit	\n"
 		"	and	%0, %2					\n"
 		"	" __SC "%0, %1					\n"
 		"	beqz	%0, 1b					\n"
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
 	} else {
@@ -191,10 +200,12 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3				\n"
 		"1:	" __LL "%0, %1		# change_bit	\n"
 		"	xor	%0, %2				\n"
-		"	"__SC	"%0, %1				\n"
+		"	" __SC	"%0, %1				\n"
 		"	beqzl	%0, 1b				\n"
+		"	.set	mips0				\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
 	} else if (cpu_has_llsc) {
@@ -202,10 +213,12 @@
 		unsigned long temp;
 
 		__asm__ __volatile__(
+		"	.set	mips3				\n"
 		"1:	" __LL "%0, %1		# change_bit	\n"
 		"	xor	%0, %2				\n"
-		"	"__SC	"%0, %1				\n"
+		"	" __SC	"%0, %1				\n"
 		"	beqz	%0, 1b				\n"
+		"	.set	mips0				\n"
 		: "=&r" (temp), "=m" (*m)
 		: "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
 	} else {
@@ -253,14 +266,16 @@
 		unsigned long temp, res;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	" __LL "%0, %1		# test_and_set_bit	\n"
 		"	or	%2, %0, %3				\n"
 		"	" __SC	"%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 #ifdef CONFIG_SMP
-		"sync							\n"
+		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "memory");
@@ -271,16 +286,18 @@
 		unsigned long temp, res;
 
 		__asm__ __volatile__(
-		"	.set	noreorder	# test_and_set_bit	\n"
-		"1:	" __LL "%0, %1					\n"
+		"	.set	push					\n"
+		"	.set	noreorder				\n"
+		"	.set	mips3					\n"
+		"1:	" __LL "%0, %1		# test_and_set_bit	\n"
 		"	or	%2, %0, %3				\n"
 		"	" __SC	"%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	 and	%2, %0, %3				\n"
 #ifdef CONFIG_SMP
-		"sync							\n"
+		"	sync						\n"
 #endif
-		".set\treorder"
+		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "memory");
@@ -343,15 +360,17 @@
 		unsigned long temp, res;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	" __LL	"%0, %1		# test_and_clear_bit	\n"
 		"	or	%2, %0, %3				\n"
 		"	xor	%2, %3					\n"
-			__SC 	"%2, %1					\n"
+		"	" __SC 	"%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "memory");
@@ -362,17 +381,19 @@
 		unsigned long temp, res;
 
 		__asm__ __volatile__(
-		"	.set	noreorder	# test_and_clear_bit	\n"
-		"1:	" __LL	"%0, %1					\n"
+		"	.set	push					\n"
+		"	.set	noreorder				\n"
+		"	.set	mips3					\n"
+		"1:	" __LL	"%0, %1		# test_and_clear_bit	\n"
 		"	or	%2, %0, %3				\n"
 		"	xor	%2, %3					\n"
-			__SC 	"%2, %1					\n"
+		"	" __SC 	"%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 		"	 and	%2, %0, %3				\n"
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
-		"	.set	reorder					\n"
+		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "memory");
@@ -435,14 +456,16 @@
 		unsigned long temp, res;
 
 		__asm__ __volatile__(
-		"1:	" __LL	" %0, %1	# test_and_change_bit	\n"
+		"	.set	mips3					\n"
+		"1:	" __LL	"%0, %1		# test_and_change_bit	\n"
 		"	xor	%2, %0, %3				\n"
-		"	"__SC	"%2, %1					\n"
+		"	" __SC	"%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "memory");
@@ -453,16 +476,18 @@
 		unsigned long temp, res;
 
 		__asm__ __volatile__(
-		"	.set	noreorder	# test_and_change_bit	\n"
-		"1:	" __LL	" %0, %1				\n"
+		"	.set	push					\n"
+		"	.set	noreorder				\n"
+		"	.set	mips3					\n"
+		"1:	" __LL	"%0, %1		# test_and_change_bit	\n"
 		"	xor	%2, %0, %3				\n"
-		"	"__SC	"\t%2, %1				\n"
+		"	" __SC	"\t%2, %1				\n"
 		"	beqz	%2, 1b					\n"
 		"	 and	%2, %0, %3				\n"
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
-		"	.set	reorder					\n"
+		"	.set	pop					\n"
 		: "=&r" (temp), "=m" (*m), "=&r" (res)
 		: "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
 		: "memory");
@@ -523,22 +548,60 @@
 }
 
 /*
- * ffz - find first zero in word.
+ * Return the bit position (0..63) of the most significant 1 bit in a word
+ * Returns -1 if no 1 bit exists
+ */
+static inline int __ilog2(unsigned long x)
+{
+	int lz;
+
+	if (sizeof(x) == 4) {
+		__asm__ (
+		"	.set	push					\n"
+		"	.set	mips32					\n"
+		"	clz	%0, %1					\n"
+		"	.set	pop					\n"
+		: "=r" (lz)
+		: "r" (x));
+
+		return 31 - lz;
+	}
+
+	BUG_ON(sizeof(x) != 8);
+
+	__asm__ (
+	"	.set	push						\n"
+	"	.set	mips64						\n"
+	"	dclz	%0, %1						\n"
+	"	.set	pop						\n"
+	: "=r" (lz)
+	: "r" (x));
+
+	return 63 - lz;
+}
+
+/*
+ * __ffs - find first bit in word.
  * @word: The word to search
  *
- * Undefined if no zero exists, so code should check against ~0UL first.
+ * Returns 0..SZLONG-1
+ * Undefined if no bit exists, so code should check against 0 first.
  */
-static inline unsigned long ffz(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return __ilog2(word & -word);
+#else
 	int b = 0, s;
 
-	word = ~word;
 #ifdef CONFIG_32BIT
 	s = 16; if (word << 16 != 0) s = 0; b += s; word >>= s;
 	s =  8; if (word << 24 != 0) s = 0; b += s; word >>= s;
 	s =  4; if (word << 28 != 0) s = 0; b += s; word >>= s;
 	s =  2; if (word << 30 != 0) s = 0; b += s; word >>= s;
 	s =  1; if (word << 31 != 0) s = 0; b += s;
+
+	return b;
 #endif
 #ifdef CONFIG_64BIT
 	s = 32; if (word << 32 != 0) s = 0; b += s; word >>= s;
@@ -547,27 +610,92 @@
 	s =  4; if (word << 60 != 0) s = 0; b += s; word >>= s;
 	s =  2; if (word << 62 != 0) s = 0; b += s; word >>= s;
 	s =  1; if (word << 63 != 0) s = 0; b += s;
-#endif
 
 	return b;
+#endif
+#endif
 }
 
 /*
- * __ffs - find first bit in word.
+ * ffs - find first bit set.
  * @word: The word to search
  *
- * Undefined if no bit exists, so code should check against 0 first.
+ * Returns 1..SZLONG
+ * Returns 0 if no bit exists
  */
-static inline unsigned long __ffs(unsigned long word)
+
+static inline unsigned long ffs(unsigned long word)
 {
-	return ffz(~word);
+	if (!word)
+		return 0;
+
+	return __ffs(word) + 1;
 }
 
 /*
- * fls: find last bit set.
+ * 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)
+{
+	return __ffs (~word);
+}
 
-#define fls(x) generic_fls(x)
+/*
+ * flz - find last zero in word.
+ * @word: The word to search
+ *
+ * Returns 0..SZLONG-1
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline unsigned long flz(unsigned long word)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return __ilog2(~word);
+#else
+#ifdef CONFIG_32BIT
+	int r = 31, s;
+	word = ~word;
+	s = 16; if ((word & 0xffff0000)) s = 0; r -= s; word <<= s;
+	s = 8;  if ((word & 0xff000000)) s = 0; r -= s; word <<= s;
+	s = 4;  if ((word & 0xf0000000)) s = 0; r -= s; word <<= s;
+	s = 2;  if ((word & 0xc0000000)) s = 0; r -= s; word <<= s;
+	s = 1;  if ((word & 0x80000000)) s = 0; r -= s;
+
+	return r;
+#endif
+#ifdef CONFIG_64BIT
+	int r = 63, s;
+	word = ~word;
+	s = 32; if ((word & 0xffffffff00000000UL)) s = 0; r -= s; word <<= s;
+	s = 16; if ((word & 0xffff000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 8;  if ((word & 0xff00000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 4;  if ((word & 0xf000000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 2;  if ((word & 0xc000000000000000UL)) s = 0; r -= s; word <<= s;
+	s = 1;  if ((word & 0x8000000000000000UL)) s = 0; r -= s;
+
+	return r;
+#endif
+#endif
+}
+
+/*
+ * fls - find last bit set.
+ * @word: The word to search
+ *
+ * Returns 1..SZLONG
+ * Returns 0 if no bit exists
+ */
+static inline unsigned long fls(unsigned long word)
+{
+	if (word == 0)
+		return 0;
+
+	return flz(~word) + 1;
+}
+
 
 /*
  * find_next_zero_bit - find the first zero bit in a memory region
@@ -704,17 +832,6 @@
 }
 
 /*
- * 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).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
  * hweightN - returns the hamming weight of a N-bit word
  * @x: the word to weigh
  *
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index b1e57d7..14fc88f 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -77,6 +77,7 @@
 #define  MACH_SGI_IP27		1	/* Origin 200, Origin 2000, Onyx 2 */
 #define  MACH_SGI_IP28		2	/* Indigo2 Impact		*/
 #define  MACH_SGI_IP32		3	/* O2				*/
+#define  MACH_SGI_IP30		4	/* Octane, Octane2              */
 
 /*
  * Valid machtype for group COBALT
@@ -136,6 +137,7 @@
 #define MACH_GROUP_PHILIPS     14
 #define  MACH_PHILIPS_NINO	0	/* Nino */
 #define  MACH_PHILIPS_VELO	1	/* Velo */
+#define  MACH_PHILIPS_JBS	2	/* JBS */
 
 /*
  * Valid machtype for group Globespan
@@ -159,6 +161,7 @@
 #define  MACH_TOSHIBA_JMR3927	3	/* JMR-TX3927 CPU/IO board */
 #define  MACH_TOSHIBA_RBTX4927	4
 #define  MACH_TOSHIBA_RBTX4937	5
+#define  MACH_TOSHIBA_RBTX4938	6
 
 #define GROUP_TOSHIBA_NAMES	{ "Pallas", "TopasCE", "JMR", "JMR TX3927", \
 				  "RBTX4927", "RBTX4937" }
@@ -177,6 +180,8 @@
 #define  MACH_MTX1		7       /* 4G MTX-1 Au1500-based board */
 #define  MACH_PB1550		8       /* Au1550-based eval board */
 #define  MACH_DB1550		9       /* Au1550-based eval board */
+#define  MACH_PB1200		10       /* Au1200-based eval board */
+#define  MACH_DB1200		11       /* Au1200-based eval board */
 
 /*
  * Valid machtype for group NEC_VR41XX
diff --git a/include/asm-mips/break.h b/include/asm-mips/break.h
index 2e6de78..25b980c 100644
--- a/include/asm-mips/break.h
+++ b/include/asm-mips/break.h
@@ -28,6 +28,7 @@
 #define BRK_NORLD	10	/* No rld found - not used by Linux/MIPS */
 #define _BRK_THREADBP	11	/* For threads, user bp (used by debuggers) */
 #define BRK_BUG		512	/* Used by BUG() */
+#define BRK_KDB		513	/* Used in KDB_ENTER() */
 #define BRK_MULOVF	1023	/* Multiply overflow */
 
 #endif /* __ASM_BREAK_H */
diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h
index 3f594b4..87d49a5 100644
--- a/include/asm-mips/bug.h
+++ b/include/asm-mips/bug.h
@@ -1,16 +1,21 @@
 #ifndef __ASM_BUG_H
 #define __ASM_BUG_H
 
-#include <asm/break.h>
+#include <linux/config.h>
 
 #ifdef CONFIG_BUG
-#define HAVE_ARCH_BUG
+
+#include <asm/break.h>
+
 #define BUG()								\
 do {									\
 	__asm__ __volatile__("break %0" : : "i" (BRK_BUG));		\
 } while (0)
+
+#define HAVE_ARCH_BUG
+
 #endif
 
 #include <asm-generic/bug.h>
 
-#endif
+#endif /* __ASM_BUG_H */
diff --git a/include/asm-mips/bugs.h b/include/asm-mips/bugs.h
index b14b961..cb2ea7c 100644
--- a/include/asm-mips/bugs.h
+++ b/include/asm-mips/bugs.h
@@ -8,12 +8,18 @@
 #define _ASM_BUGS_H
 
 #include <linux/config.h>
+#include <linux/delay.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
 
 extern void check_bugs32(void);
 extern void check_bugs64(void);
 
 static inline void check_bugs(void)
 {
+	unsigned int cpu = smp_processor_id();
+
+	cpu_data[cpu].udelay_val = loops_per_jiffy;
 	check_bugs32();
 #ifdef CONFIG_64BIT
 	check_bugs64();
diff --git a/include/asm-mips/cache.h b/include/asm-mips/cache.h
index 4517bdf..1a5d1a6 100644
--- a/include/asm-mips/cache.h
+++ b/include/asm-mips/cache.h
@@ -10,6 +10,7 @@
 #define _ASM_CACHE_H
 
 #include <linux/config.h>
+#include <kmalloc.h>
 
 #define L1_CACHE_SHIFT		CONFIG_MIPS_L1_CACHE_SHIFT
 #define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
@@ -18,6 +19,4 @@
 #define SMP_CACHE_SHIFT		L1_CACHE_SHIFT
 #define SMP_CACHE_BYTES		L1_CACHE_BYTES
 
-#define ARCH_KMALLOC_MINALIGN	8
-
 #endif /* _ASM_CACHE_H */
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index 635f1bf..a18ba2e 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -49,17 +49,29 @@
 
 extern void (*flush_icache_page)(struct vm_area_struct *vma,
 	struct page *page);
-extern void (*flush_icache_range)(unsigned long start, unsigned long end);
+extern void (*flush_icache_range)(unsigned long __user start,
+	unsigned long __user end);
 #define flush_cache_vmap(start, end)		flush_cache_all()
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
-#define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
-do {									\
-	memcpy(dst, (void *) src, len);					\
-	flush_icache_page(vma, page);					\
-} while (0)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len)		\
-	memcpy(dst, src, len)
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+	struct page *page, unsigned long vaddr, void *dst, const void *src,
+	unsigned long len)
+{
+	if (cpu_has_dc_aliases)
+		flush_cache_page(vma, vaddr, page_to_pfn(page));
+	memcpy(dst, src, len);
+	flush_icache_page(vma, page);
+}
+
+static inline void copy_from_user_page(struct vm_area_struct *vma,
+	struct page *page, unsigned long vaddr, void *dst, const void *src,
+	unsigned long len)
+{
+	if (cpu_has_dc_aliases)
+		flush_cache_page(vma, vaddr, page_to_pfn(page));
+	memcpy(dst, src, len);
+}
 
 extern void (*flush_cache_sigtramp)(unsigned long addr);
 extern void (*flush_icache_all)(void);
@@ -78,4 +90,7 @@
 #define ClearPageDcacheDirty(page)	\
 	clear_bit(PG_dcache_dirty, &(page)->flags)
 
+/* Run kernel code uncached, useful for cache probing functions. */
+unsigned long __init run_uncached(void *func);
+
 #endif /* _ASM_CACHEFLUSH_H */
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index c1ea5a8..b09f897 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -34,8 +34,9 @@
  * this is a new version of the above that records errors it finds in *errp,
  * but continues and zeros the rest of the buffer.
  */
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, int len,
-                                         unsigned int sum, int *errp);
+unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+					 unsigned char *dst, int len,
+					 unsigned int sum, int *errp);
 
 /*
  * Copy and checksum to user
@@ -70,14 +71,15 @@
 static inline unsigned short int csum_fold(unsigned int sum)
 {
 	__asm__(
-	".set\tnoat\t\t\t# csum_fold\n\t"
-	"sll\t$1,%0,16\n\t"
-	"addu\t%0,$1\n\t"
-	"sltu\t$1,%0,$1\n\t"
-	"srl\t%0,%0,16\n\t"
-	"addu\t%0,$1\n\t"
-	"xori\t%0,0xffff\n\t"
-	".set\tat"
+	"	.set	push		# csum_fold\n"
+	"	.set	noat		\n"
+	"	sll	$1, %0, 16	\n"
+	"	addu	%0, $1		\n"
+	"	sltu	$1, %0, $1	\n"
+	"	srl	%0, %0, 16	\n"
+	"	addu	%0, $1		\n"
+	"	xori	%0, 0xffff	\n"
+	"	.set	pop"
 	: "=r" (sum)
 	: "0" (sum));
 
@@ -127,29 +129,30 @@
 	unsigned int sum)
 {
 	__asm__(
-	".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t"
+	"	.set	push		# csum_tcpudp_nofold\n"
+	"	.set	noat		\n"
 #ifdef CONFIG_32BIT
-	"addu\t%0, %2\n\t"
-	"sltu\t$1, %0, %2\n\t"
-	"addu\t%0, $1\n\t"
+	"	addu	%0, %2		\n"
+	"	sltu	$1, %0, %2	\n"
+	"	addu	%0, $1		\n"
 
-	"addu\t%0, %3\n\t"
-	"sltu\t$1, %0, %3\n\t"
-	"addu\t%0, $1\n\t"
+	"	addu	%0, %3		\n"
+	"	sltu	$1, %0, %3	\n"
+	"	addu	%0, $1		\n"
 
-	"addu\t%0, %4\n\t"
-	"sltu\t$1, %0, %4\n\t"
-	"addu\t%0, $1\n\t"
+	"	addu	%0, %4		\n"
+	"	sltu	$1, %0, %4	\n"
+	"	addu	%0, $1		\n"
 #endif
 #ifdef CONFIG_64BIT
-	"daddu\t%0, %2\n\t"
-	"daddu\t%0, %3\n\t"
-	"daddu\t%0, %4\n\t"
-	"dsll32\t$1, %0, 0\n\t"
-	"daddu\t%0, $1\n\t"
-	"dsrl32\t%0, %0, 0\n\t"
+	"	daddu	%0, %2		\n"
+	"	daddu	%0, %3		\n"
+	"	daddu	%0, %4		\n"
+	"	dsll32	$1, %0, 0	\n"
+	"	daddu	%0, $1		\n"
+	"	dsra32	%0, %0, 0	\n"
 #endif
-	".set\tat"
+	"	.set	pop"
 	: "=r" (sum)
 	: "0" (daddr), "r"(saddr),
 #ifdef __MIPSEL__
@@ -192,57 +195,57 @@
 						     unsigned int sum)
 {
 	__asm__(
-	".set\tpush\t\t\t# csum_ipv6_magic\n\t"
-	".set\tnoreorder\n\t"
-	".set\tnoat\n\t"
-	"addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t"
-	"sltu\t$1, %0, %5\n\t"
-	"addu\t%0, $1\n\t"
+	"	.set	push		# csum_ipv6_magic\n"
+	"	.set	noreorder	\n"
+	"	.set	noat		\n"
+	"	addu	%0, %5		# proto (long in network byte order)\n"
+	"	sltu	$1, %0, %5	\n"
+	"	addu	%0, $1		\n"
 
-	"addu\t%0, %6\t\t\t# csum\n\t"
-	"sltu\t$1, %0, %6\n\t"
-	"lw\t%1, 0(%2)\t\t\t# four words source address\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	addu	%0, %6		# csum\n"
+	"	sltu	$1, %0, %6	\n"
+	"	lw	%1, 0(%2)	# four words source address\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 4(%2)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 4(%2)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 8(%2)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 8(%2)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 12(%2)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 12(%2)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 0(%3)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 0(%3)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 4(%3)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 4(%3)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 8(%3)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 8(%3)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"lw\t%1, 12(%3)\n\t"
-	"addu\t%0, $1\n\t"
-	"addu\t%0, %1\n\t"
-	"sltu\t$1, %0, %1\n\t"
+	"	lw	%1, 12(%3)	\n"
+	"	addu	%0, $1		\n"
+	"	addu	%0, %1		\n"
+	"	sltu	$1, %0, %1	\n"
 
-	"addu\t%0, $1\t\t\t# Add final carry\n\t"
-	".set\tpop"
+	"	addu	%0, $1		# Add final carry\n"
+	"	.set	pop"
 	: "=r" (sum), "=r" (proto)
 	: "r" (saddr), "r" (daddr),
 	  "0" (htonl(len)), "1" (htonl(proto)), "r" (sum));
diff --git a/include/asm-mips/cobalt/cobalt.h b/include/asm-mips/cobalt/cobalt.h
index ca1fbc0..78e1df2 100644
--- a/include/asm-mips/cobalt/cobalt.h
+++ b/include/asm-mips/cobalt/cobalt.h
@@ -19,18 +19,23 @@
  *     9  - PCI
  *    14  - IDE0
  *    15  - IDE1
- *
+ */
+#define COBALT_QUBE_SLOT_IRQ	9
+
+/*
  * CPU IRQs  are 16 ... 23
  */
-#define COBALT_TIMER_IRQ	18
-#define COBALT_SCC_IRQ          19		/* pre-production has 85C30 */
-#define COBALT_RAQ_SCSI_IRQ	19
-#define COBALT_ETH0_IRQ		19
-#define COBALT_ETH1_IRQ		20
-#define COBALT_SERIAL_IRQ	21
-#define COBALT_SCSI_IRQ         21
-#define COBALT_VIA_IRQ		22		/* Chained to VIA ISA bridge */
-#define COBALT_QUBE_SLOT_IRQ	23
+#define COBALT_CPU_IRQ		16
+
+#define COBALT_GALILEO_IRQ	(COBALT_CPU_IRQ + 2)
+#define COBALT_SCC_IRQ          (COBALT_CPU_IRQ + 3)	/* pre-production has 85C30 */
+#define COBALT_RAQ_SCSI_IRQ	(COBALT_CPU_IRQ + 3)
+#define COBALT_ETH0_IRQ		(COBALT_CPU_IRQ + 3)
+#define COBALT_QUBE1_ETH0_IRQ	(COBALT_CPU_IRQ + 4)
+#define COBALT_ETH1_IRQ		(COBALT_CPU_IRQ + 4)
+#define COBALT_SERIAL_IRQ	(COBALT_CPU_IRQ + 5)
+#define COBALT_SCSI_IRQ         (COBALT_CPU_IRQ + 5)
+#define COBALT_VIA_IRQ		(COBALT_CPU_IRQ + 6)	/* Chained to VIA ISA bridge */
 
 /*
  * PCI configuration space manifest constants.  These are wired into
@@ -69,16 +74,21 @@
  * Most of this really should go into a separate GT64111 header file.
  */
 #define GT64111_IO_BASE		0x10000000UL
+#define GT64111_IO_END		0x11ffffffUL
+#define GT64111_MEM_BASE	0x12000000UL
+#define GT64111_MEM_END		0x13ffffffUL
 #define GT64111_BASE		0x14000000UL
-#define GALILEO_REG(ofs)	(KSEG0 + GT64111_BASE + (unsigned long)(ofs))
+#define GALILEO_REG(ofs)	CKSEG1ADDR(GT64111_BASE + (unsigned long)(ofs))
 
 #define GALILEO_INL(port)	(*(volatile unsigned int *) GALILEO_REG(port))
 #define GALILEO_OUTL(val, port)						\
 do {									\
-	*(volatile unsigned int *) GALILEO_REG(port) = (port);		\
+	*(volatile unsigned int *) GALILEO_REG(port) = (val);		\
 } while (0)
 
-#define GALILEO_T0EXP		0x0100
+#define GALILEO_INTR_T0EXP	(1 << 8)
+#define GALILEO_INTR_RETRY_CTR	(1 << 20)
+
 #define GALILEO_ENTC0		0x01
 #define GALILEO_SELTC0		0x02
 
@@ -86,5 +96,21 @@
 	GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) |		\
 		(PCI_FUNC (devfn) << 8) | (where)), GT_PCI0_CFGADDR_OFS)
 
+#define COBALT_LED_PORT		(*(volatile unsigned char *) CKSEG1ADDR(0x1c000000))
+# define COBALT_LED_BAR_LEFT	(1 << 0)	/* Qube */
+# define COBALT_LED_BAR_RIGHT	(1 << 1)	/* Qube */
+# define COBALT_LED_WEB		(1 << 2)	/* RaQ */
+# define COBALT_LED_POWER_OFF	(1 << 3)	/* RaQ */
+# define COBALT_LED_RESET	0x0f
+
+#define COBALT_KEY_PORT		((~*(volatile unsigned int *) CKSEG1ADDR(0x1d000000) >> 24) & COBALT_KEY_MASK)
+# define COBALT_KEY_CLEAR	(1 << 1)
+# define COBALT_KEY_LEFT	(1 << 2)
+# define COBALT_KEY_UP		(1 << 3)
+# define COBALT_KEY_DOWN	(1 << 4)
+# define COBALT_KEY_RIGHT	(1 << 5)
+# define COBALT_KEY_ENTER	(1 << 6)
+# define COBALT_KEY_SELECT	(1 << 7)
+# define COBALT_KEY_MASK	0xfe
 
 #endif /* __ASM_COBALT_H */
diff --git a/include/asm-mips/cobalt/mach-gt64120.h b/include/asm-mips/cobalt/mach-gt64120.h
new file mode 100644
index 0000000..587fc43
--- /dev/null
+++ b/include/asm-mips/cobalt/mach-gt64120.h
@@ -0,0 +1 @@
+/* there's something here ... in the dark */
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 2c084cd..35d2604 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -15,10 +15,10 @@
 typedef s32		compat_suseconds_t;
 
 typedef s32		compat_pid_t;
-typedef u32		__compat_uid_t;
-typedef u32		__compat_gid_t;
-typedef u32		__compat_uid32_t;
-typedef u32		__compat_gid32_t;
+typedef s32		__compat_uid_t;
+typedef s32		__compat_gid_t;
+typedef __compat_uid_t	__compat_uid32_t;
+typedef __compat_gid_t	__compat_gid32_t;
 typedef u32		compat_mode_t;
 typedef u32		compat_ino_t;
 typedef u32		compat_dev_t;
@@ -54,8 +54,8 @@
 	compat_ino_t	st_ino;
 	compat_mode_t	st_mode;
 	compat_nlink_t	st_nlink;
-	__compat_uid32_t	st_uid;
-	__compat_gid32_t	st_gid;
+	__compat_uid_t	st_uid;
+	__compat_gid_t	st_gid;
 	compat_dev_t	st_rdev;
 	s32		st_pad2[2];
 	compat_off_t	st_size;
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 9a2de642..03627cfb 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -4,6 +4,7 @@
  * for more details.
  *
  * Copyright (C) 2003, 2004 Ralf Baechle
+ * Copyright (C) 2004  Maciej W. Rozycki
  */
 #ifndef __ASM_CPU_FEATURES_H
 #define __ASM_CPU_FEATURES_H
@@ -24,8 +25,19 @@
 #ifndef cpu_has_4kex
 #define cpu_has_4kex		(cpu_data[0].options & MIPS_CPU_4KEX)
 #endif
-#ifndef cpu_has_4ktlb
-#define cpu_has_4ktlb		(cpu_data[0].options & MIPS_CPU_4KTLB)
+#ifndef cpu_has_3k_cache
+#define cpu_has_3k_cache	(cpu_data[0].options & MIPS_CPU_3K_CACHE)
+#endif
+#define cpu_has_6k_cache	0
+#define cpu_has_8k_cache	0
+#ifndef cpu_has_4k_cache
+#define cpu_has_4k_cache	(cpu_data[0].options & MIPS_CPU_4K_CACHE)
+#endif
+#ifndef cpu_has_tx39_cache
+#define cpu_has_tx39_cache	(cpu_data[0].options & MIPS_CPU_TX39_CACHE)
+#endif
+#ifndef cpu_has_sb1_cache
+#define cpu_has_sb1_cache	(cpu_data[0].options & MIPS_CPU_SB1_CACHE)
 #endif
 #ifndef cpu_has_fpu
 #define cpu_has_fpu		(cpu_data[0].options & MIPS_CPU_FPU)
@@ -39,9 +51,6 @@
 #ifndef cpu_has_watch
 #define cpu_has_watch		(cpu_data[0].options & MIPS_CPU_WATCH)
 #endif
-#ifndef cpu_has_mips16
-#define cpu_has_mips16		(cpu_data[0].options & MIPS_CPU_MIPS16)
-#endif
 #ifndef cpu_has_divec
 #define cpu_has_divec		(cpu_data[0].options & MIPS_CPU_DIVEC)
 #endif
@@ -66,6 +75,18 @@
 #ifndef cpu_has_llsc
 #define cpu_has_llsc		(cpu_data[0].options & MIPS_CPU_LLSC)
 #endif
+#ifndef cpu_has_mips16
+#define cpu_has_mips16		(cpu_data[0].ases & MIPS_ASE_MIPS16)
+#endif
+#ifndef cpu_has_mdmx
+#define cpu_has_mdmx           (cpu_data[0].ases & MIPS_ASE_MDMX)
+#endif
+#ifndef cpu_has_mips3d
+#define cpu_has_mips3d         (cpu_data[0].ases & MIPS_ASE_MIPS3D)
+#endif
+#ifndef cpu_has_smartmips
+#define cpu_has_smartmips      (cpu_data[0].ases & MIPS_ASE_SMARTMIPS)
+#endif
 #ifndef cpu_has_vtag_icache
 #define cpu_has_vtag_icache	(cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
 #endif
@@ -95,15 +116,16 @@
 #endif
 #endif
 
-/*
- * Certain CPUs may throw bizarre exceptions if not the whole cacheline
- * contains valid instructions.  For these we ensure proper alignment of
- * signal trampolines and pad them to the size of a full cache lines with
- * nops.  This is also used in structure definitions so can't be a test macro
- * like the others.
- */
-#ifndef PLAT_TRAMPOLINE_STUFF_LINE
-#define PLAT_TRAMPOLINE_STUFF_LINE	0UL
+#ifndef cpu_has_dsp
+#define cpu_has_dsp		(cpu_data[0].ases & MIPS_ASE_DSP)
+#endif
+
+#ifdef CONFIG_MIPS_MT
+#ifndef cpu_has_mipsmt
+# define cpu_has_mipsmt		(cpu_data[0].ases & MIPS_ASE_MIPSMT)
+#endif
+#else
+# define cpu_has_mipsmt		0
 #endif
 
 #ifdef CONFIG_32BIT
@@ -142,6 +164,22 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_MIPSR2
+# if defined(CONFIG_CPU_MIPSR2_IRQ_VI) && !defined(cpu_has_vint)
+#  define cpu_has_vint		(cpu_data[0].options & MIPS_CPU_VINT)
+# else
+#  define cpu_has_vint			0
+# endif
+# if defined(CONFIG_CPU_MIPSR2_IRQ_EI) && !defined(cpu_has_veic)
+#  define cpu_has_veic		(cpu_data[0].options & MIPS_CPU_VEIC)
+# else
+#  define cpu_has_veic			0
+# endif
+#else
+# define cpu_has_vint			0
+# define cpu_has_veic			0
+#endif
+
 #ifndef cpu_has_subset_pcaches
 #define cpu_has_subset_pcaches	(cpu_data[0].options & MIPS_CPU_SUBSET_CACHES)
 #endif
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 20a35b1..d5cf519 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -7,6 +7,7 @@
  * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003 Ralf Baechle
  * Copyright (C) 1996 Paul M. Antoine
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2004  Maciej W. Rozycki
  */
 #ifndef __ASM_CPU_INFO_H
 #define __ASM_CPU_INFO_H
@@ -61,6 +62,7 @@
 	 * Capability and feature descriptor structure for MIPS CPU
 	 */
 	unsigned long		options;
+	unsigned long		ases;
 	unsigned int		processor_id;
 	unsigned int		fpu_id;
 	unsigned int		cputype;
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index dec060b..48eac296 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -3,6 +3,7 @@
  *        various MIPS cpu types.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 2004  Maciej W. Rozycki
  */
 #ifndef _ASM_CPU_H
 #define _ASM_CPU_H
@@ -22,12 +23,17 @@
    spec.
 */
 
-#define PRID_COMP_LEGACY       0x000000
-#define PRID_COMP_MIPS         0x010000
-#define PRID_COMP_BROADCOM     0x020000
-#define PRID_COMP_ALCHEMY      0x030000
-#define PRID_COMP_SIBYTE       0x040000
-#define PRID_COMP_SANDCRAFT    0x050000
+#define PRID_COMP_LEGACY	0x000000
+#define PRID_COMP_MIPS		0x010000
+#define PRID_COMP_BROADCOM	0x020000
+#define PRID_COMP_ALCHEMY	0x030000
+#define PRID_COMP_SIBYTE	0x040000
+#define PRID_COMP_SANDCRAFT	0x050000
+#define PRID_COMP_PHILIPS	0x060000
+#define PRID_COMP_TOSHIBA	0x070000
+#define PRID_COMP_LSI		0x080000
+#define PRID_COMP_LEXRA		0x0b0000
+
 
 /*
  * Assigned values for the product ID register.  In order to detect a
@@ -46,6 +52,7 @@
 #define PRID_IMP_VR41XX		0x0c00
 #define PRID_IMP_R12000		0x0e00
 #define PRID_IMP_R8000		0x1000
+#define PRID_IMP_PR4450		0x1200
 #define PRID_IMP_R4600		0x2000
 #define PRID_IMP_R4700		0x2100
 #define PRID_IMP_TX39		0x2200
@@ -60,6 +67,13 @@
 #define PRID_IMP_RM9000		0x3400
 #define PRID_IMP_R5432		0x5400
 #define PRID_IMP_R5500		0x5500
+
+#define PRID_IMP_UNKNOWN	0xff00
+
+/*
+ * These are the PRID's for when 23:16 == PRID_COMP_MIPS
+ */
+
 #define PRID_IMP_4KC		0x8000
 #define PRID_IMP_5KC		0x8100
 #define PRID_IMP_20KC		0x8200
@@ -71,14 +85,15 @@
 #define PRID_IMP_4KEMPR2	0x9100
 #define PRID_IMP_4KSD		0x9200
 #define PRID_IMP_24K		0x9300
-
-#define PRID_IMP_UNKNOWN	0xff00
+#define PRID_IMP_34K		0x9500
+#define PRID_IMP_24KE		0x9600
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
  */
 
 #define PRID_IMP_SB1            0x0100
+#define PRID_IMP_SB1A           0x1100
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SANDCRAFT
@@ -177,7 +192,11 @@
 #define CPU_VR4133		56
 #define CPU_AU1550		57
 #define CPU_24K			58
-#define CPU_LAST		58
+#define CPU_AU1200		59
+#define CPU_34K			60
+#define CPU_PR4450		61
+#define CPU_SB1A		62
+#define CPU_LAST		62
 
 /*
  * ISA Level encodings
@@ -200,23 +219,37 @@
  * CPU Option encodings
  */
 #define MIPS_CPU_TLB		0x00000001 /* CPU has TLB */
-/* Leave a spare bit for variant MMU types... */
-#define MIPS_CPU_4KEX		0x00000004 /* "R4K" exception model */
-#define MIPS_CPU_4KTLB		0x00000008 /* "R4K" TLB handler */
-#define MIPS_CPU_FPU		0x00000010 /* CPU has FPU */
-#define MIPS_CPU_32FPR		0x00000020 /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER	0x00000040 /* Cycle count/compare */
-#define MIPS_CPU_WATCH		0x00000080 /* watchpoint registers */
-#define MIPS_CPU_MIPS16		0x00000100 /* code compression */
-#define MIPS_CPU_DIVEC		0x00000200 /* dedicated interrupt vector */
-#define MIPS_CPU_VCE		0x00000400 /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P	0x00000800 /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S	0x00001000 /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK		0x00002000 /* Machine check exception */
-#define MIPS_CPU_EJTAG		0x00004000 /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX	0x00008000 /* no FPU exception */
-#define MIPS_CPU_LLSC		0x00010000 /* CPU has ll/sc instructions */
-#define MIPS_CPU_SUBSET_CACHES	0x00020000 /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH	0x00040000 /* CPU has usable prefetch */
+#define MIPS_CPU_4KEX		0x00000002 /* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE	0x00000004 /* R3000-style caches */
+#define MIPS_CPU_4K_CACHE	0x00000008 /* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE	0x00000010 /* TX3900-style caches */
+#define MIPS_CPU_SB1_CACHE	0x00000020 /* SB1-style caches */
+#define MIPS_CPU_FPU		0x00000040 /* CPU has FPU */
+#define MIPS_CPU_32FPR		0x00000080 /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER	0x00000100 /* Cycle count/compare */
+#define MIPS_CPU_WATCH		0x00000200 /* watchpoint registers */
+#define MIPS_CPU_DIVEC		0x00000400 /* dedicated interrupt vector */
+#define MIPS_CPU_VCE		0x00000800 /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P	0x00001000 /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S	0x00002000 /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK		0x00004000 /* Machine check exception */
+#define MIPS_CPU_EJTAG		0x00008000 /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX	0x00010000 /* no FPU exception */
+#define MIPS_CPU_LLSC		0x00020000 /* CPU has ll/sc instructions */
+#define MIPS_CPU_SUBSET_CACHES	0x00040000 /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH	0x00080000 /* CPU has usable prefetch */
+#define MIPS_CPU_VINT		0x00100000 /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC		0x00200000 /* CPU supports MIPSR2 external interrupt controller mode */
+
+/*
+ * CPU ASE encodings
+ */
+#define MIPS_ASE_MIPS16		0x00000001 /* code compression */
+#define MIPS_ASE_MDMX		0x00000002 /* MIPS digital media extension */
+#define MIPS_ASE_MIPS3D		0x00000004 /* MIPS-3D */
+#define MIPS_ASE_SMARTMIPS	0x00000008 /* SmartMIPS */
+#define MIPS_ASE_DSP		0x00000010 /* Signal Processing ASE */
+#define MIPS_ASE_MIPSMT		0x00000020 /* CPU supports MIPS MT */
+
 
 #endif /* _ASM_CPU_H */
diff --git a/include/asm-mips/dec/ecc.h b/include/asm-mips/dec/ecc.h
index 724908b..19495a4 100644
--- a/include/asm-mips/dec/ecc.h
+++ b/include/asm-mips/dec/ecc.h
@@ -49,7 +49,8 @@
 
 extern void dec_ecc_be_init(void);
 extern int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup);
-extern irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id,
+					struct pt_regs *regs);
 #endif
 
 #endif /* __ASM_MIPS_DEC_ECC_H */
diff --git a/include/asm-mips/dec/ioasic_addrs.h b/include/asm-mips/dec/ioasic_addrs.h
index 5e18a75..4cbc1f8 100644
--- a/include/asm-mips/dec/ioasic_addrs.h
+++ b/include/asm-mips/dec/ioasic_addrs.h
@@ -45,7 +45,8 @@
 
 
 /*
- * Offsets for I/O ASIC registers (relative to (system_base + IOASIC_IOCTL)).
+ * Offsets for I/O ASIC registers
+ * (relative to (dec_kn_slot_base + IOASIC_IOCTL)).
  */
 					/* all systems */
 #define IO_REG_SCSI_DMA_P	0x00	/* SCSI DMA Pointer */
diff --git a/include/asm-mips/dec/kn01.h b/include/asm-mips/dec/kn01.h
index 9469435..eb522aa 100644
--- a/include/asm-mips/dec/kn01.h
+++ b/include/asm-mips/dec/kn01.h
@@ -8,14 +8,12 @@
  *
  * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
  * are by courtesy of Chris Fraser.
- * Copyright (C) 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2005  Maciej W. Rozycki
  */
 #ifndef __ASM_MIPS_DEC_KN01_H
 #define __ASM_MIPS_DEC_KN01_H
 
-#include <asm/addrspace.h>
-
-#define KN01_SLOT_BASE	KSEG1ADDR(0x10000000)
+#define KN01_SLOT_BASE	0x10000000
 #define KN01_SLOT_SIZE	0x01000000
 
 /*
@@ -41,17 +39,9 @@
 
 
 /*
- * Some port addresses...
- */
-#define KN01_LANCE_BASE (KN01_SLOT_BASE + KN01_LANCE)	/* 0xB8000000 */
-#define KN01_DZ11_BASE	(KN01_SLOT_BASE + KN01_DZ11)	/* 0xBC000000 */
-#define KN01_RTC_BASE	(KN01_SLOT_BASE + KN01_RTC)	/* 0xBD000000 */
-
-
-/*
  * Frame buffer memory address.
  */
-#define KN01_VFB_MEM	KSEG1ADDR(0x0fc00000)
+#define KN01_VFB_MEM	0x0fc00000
 
 /*
  * CPU interrupt bits.
@@ -80,4 +70,22 @@
 #define KN01_CSR_VRGTRB		(1<<0)	/* red DAC voltage over blue (r/o) */
 #define KN01_CSR_LEDS		(0xff<<0) /* ~diagnostic LEDs (w/o) */
 
+
+#ifndef __ASSEMBLY__
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+struct pt_regs;
+
+extern u16 cached_kn01_csr;
+extern spinlock_t kn01_lock;
+
+extern void dec_kn01_be_init(void);
+extern int dec_kn01_be_handler(struct pt_regs *regs, int is_fixup);
+extern irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id,
+					 struct pt_regs *regs);
+#endif
+
 #endif /* __ASM_MIPS_DEC_KN01_H */
diff --git a/include/asm-mips/dec/kn02.h b/include/asm-mips/dec/kn02.h
index f797f70..8319ad7 100644
--- a/include/asm-mips/dec/kn02.h
+++ b/include/asm-mips/dec/kn02.h
@@ -8,21 +8,12 @@
  *
  * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
  * are by courtesy of Chris Fraser.
- * Copyright (C) 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2002, 2003, 2005  Maciej W. Rozycki
  */
 #ifndef __ASM_MIPS_DEC_KN02_H
 #define __ASM_MIPS_DEC_KN02_H
 
-#ifndef __ASSEMBLY__
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#endif
-
-#include <asm/addrspace.h>
-#include <asm/dec/ecc.h>
-
-
-#define KN02_SLOT_BASE	KSEG1ADDR(0x1fc00000)
+#define KN02_SLOT_BASE	0x1fc00000
 #define KN02_SLOT_SIZE	0x00080000
 
 /*
@@ -39,22 +30,14 @@
 
 
 /*
- * Some port addresses...
- */
-#define KN02_DZ11_BASE	(KN02_SLOT_BASE + KN02_DZ11)	/* DZ11 */
-#define KN02_RTC_BASE	(KN02_SLOT_BASE + KN02_RTC)	/* RTC */
-#define KN02_CSR_BASE	(KN02_SLOT_BASE + KN02_CSR)	/* CSR */
-
-
-/*
  * System Control & Status Register bits.
  */
 #define KN02_CSR_RES_28		(0xf<<28)	/* unused */
 #define KN02_CSR_PSU		(1<<27)		/* power supply unit warning */
 #define KN02_CSR_NVRAM		(1<<26)		/* ~NVRAM clear jumper */
 #define KN02_CSR_REFEVEN	(1<<25)		/* mem refresh bank toggle */
-#define KN03_CSR_NRMOD		(1<<24)		/* ~NRMOD manufact. jumper */
-#define KN03_CSR_IOINTEN	(0xff<<16)	/* IRQ mask bits */
+#define KN02_CSR_NRMOD		(1<<24)		/* ~NRMOD manufact. jumper */
+#define KN02_CSR_IOINTEN	(0xff<<16)	/* IRQ mask bits */
 #define KN02_CSR_DIAGCHK	(1<<15)		/* diagn/norml ECC reads */
 #define KN02_CSR_DIAGGEN	(1<<14)		/* diagn/norml ECC writes */
 #define KN02_CSR_CORRECT	(1<<13)		/* ECC correct/check */
@@ -63,8 +46,8 @@
 #define KN02_CSR_BNK32M		(1<<10)		/* 32M/8M stride */
 #define KN02_CSR_DIAGDN		(1<<9)		/* DIAGDN manufact. jumper */
 #define KN02_CSR_BAUD38		(1<<8)		/* DZ11 38/19kbps ext. rate */
-#define KN03_CSR_IOINT		(0xff<<0)	/* IRQ status bits (r/o) */
-#define KN03_CSR_LEDS		(0xff<<0)	/* ~diagnostic LEDs (w/o) */
+#define KN02_CSR_IOINT		(0xff<<0)	/* IRQ status bits (r/o) */
+#define KN02_CSR_LEDS		(0xff<<0)	/* ~diagnostic LEDs (w/o) */
 
 
 /*
@@ -98,6 +81,10 @@
 
 
 #ifndef __ASSEMBLY__
+
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
 extern u32 cached_kn02_csr;
 extern spinlock_t kn02_lock;
 extern void init_kn02_irqs(int base);
diff --git a/include/asm-mips/dec/kn02xa.h b/include/asm-mips/dec/kn02xa.h
index 648c4dc..a25f3d7 100644
--- a/include/asm-mips/dec/kn02xa.h
+++ b/include/asm-mips/dec/kn02xa.h
@@ -9,7 +9,7 @@
  *
  * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
  * are by courtesy of Chris Fraser.
- * Copyright (C) 2000, 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2000, 2002, 2003, 2005  Maciej W. Rozycki
  *
  * These are addresses which have to be known early in the boot process.
  * For other addresses refer to tc.h, ioasic_addrs.h and friends.
@@ -17,31 +17,23 @@
 #ifndef __ASM_MIPS_DEC_KN02XA_H
 #define __ASM_MIPS_DEC_KN02XA_H
 
-#include <asm/addrspace.h>
 #include <asm/dec/ioasic_addrs.h>
 
-#define KN02XA_SLOT_BASE	KSEG1ADDR(0x1c000000)
-
-/*
- * Some port addresses...
- */
-#define KN02XA_IOASIC_BASE    (KN02XA_SLOT_BASE + IOASIC_IOCTL)	/* I/O ASIC */
-#define KN02XA_RTC_BASE		(KN02XA_SLOT_BASE + IOASIC_TOY)	/* RTC */
-
+#define KN02XA_SLOT_BASE	0x1c000000
 
 /*
  * Memory control ASIC registers.
  */
-#define KN02XA_MER	KSEG1ADDR(0x0c400000)	/* memory error register */
-#define KN02XA_MSR	KSEG1ADDR(0x0c800000)	/* memory size register */
+#define KN02XA_MER		0x0c400000	/* memory error register */
+#define KN02XA_MSR		0x0c800000	/* memory size register */
 
 /*
  * CPU control ASIC registers.
  */
-#define KN02XA_MEM_CONF	KSEG1ADDR(0x0e000000)	/* write timeout config */
-#define KN02XA_EAR	KSEG1ADDR(0x0e000004)	/* error address register */
-#define KN02XA_BOOT0	KSEG1ADDR(0x0e000008)	/* boot 0 register */
-#define KN02XA_MEM_INTR	KSEG1ADDR(0x0e00000c)	/* write err IRQ stat & ack */
+#define KN02XA_MEM_CONF		0x0e000000	/* write timeout config */
+#define KN02XA_EAR		0x0e000004	/* error address register */
+#define KN02XA_BOOT0		0x0e000008	/* boot 0 register */
+#define KN02XA_MEM_INTR		0x0e00000c	/* write err IRQ stat & ack */
 
 /*
  * Memory Error Register bits, common definitions.
@@ -52,8 +44,13 @@
 #define KN02XA_MER_PAGERR	(1<<16)		/* 2k page boundary error */
 #define KN02XA_MER_TRANSERR	(1<<15)		/* transfer length error */
 #define KN02XA_MER_PARDIS	(1<<14)		/* parity error disable */
-#define KN02XA_MER_RES_12	(0x3<<12)	/* unused */
-#define KN02XA_MER_BYTERR	(0xf<<8)	/* byte lane error bitmask */
+#define KN02XA_MER_SIZE		(1<<13)		/* r/o mirror of MSR_SIZE */
+#define KN02XA_MER_RES_12	(1<<12)		/* unused */
+#define KN02XA_MER_BYTERR	(0xf<<8)	/* byte lane error bitmask: */
+#define KN02XA_MER_BYTERR_3	(0x8<<8)	/* byte lane #3 */
+#define KN02XA_MER_BYTERR_2	(0x4<<8)	/* byte lane #2 */
+#define KN02XA_MER_BYTERR_1	(0x2<<8)	/* byte lane #1 */
+#define KN02XA_MER_BYTERR_0	(0x1<<8)	/* byte lane #0 */
 #define KN02XA_MER_RES_0	(0xff<<0)	/* unused */
 
 /*
@@ -72,4 +69,17 @@
 #define KN02XA_EAR_ADDRESS	(0x7ffffff<<2)	/* address involved */
 #define KN02XA_EAR_RES_0	(0x3<<0)	/* unused */
 
+
+#ifndef __ASSEMBLY__
+
+#include <linux/interrupt.h>
+
+struct pt_regs;
+
+extern void dec_kn02xa_be_init(void);
+extern int dec_kn02xa_be_handler(struct pt_regs *regs, int is_fixup);
+extern irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id,
+					   struct pt_regs *regs);
+#endif
+
 #endif /* __ASM_MIPS_DEC_KN02XA_H */
diff --git a/include/asm-mips/dec/kn03.h b/include/asm-mips/dec/kn03.h
index 676abd1..edede92 100644
--- a/include/asm-mips/dec/kn03.h
+++ b/include/asm-mips/dec/kn03.h
@@ -10,24 +10,15 @@
  *
  * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
  * are by courtesy of Chris Fraser.
- * Copyright (C) 2000, 2002, 2003  Maciej W. Rozycki
+ * Copyright (C) 2000, 2002, 2003, 2005  Maciej W. Rozycki
  */
 #ifndef __ASM_MIPS_DEC_KN03_H
 #define __ASM_MIPS_DEC_KN03_H
 
-#include <asm/addrspace.h>
 #include <asm/dec/ecc.h>
 #include <asm/dec/ioasic_addrs.h>
 
-#define KN03_SLOT_BASE	KSEG1ADDR(0x1f800000)
-
-/*
- * Some port addresses...
- */
-#define KN03_IOASIC_BASE	(KN03_SLOT_BASE + IOASIC_IOCTL)	/* I/O ASIC */
-#define KN03_RTC_BASE		(KN03_SLOT_BASE + IOASIC_TOY)	/* RTC */
-#define KN03_MCR_BASE		(KN03_SLOT_BASE + IOASIC_MCR)	/* MCR */
-
+#define KN03_SLOT_BASE		0x1f800000
 
 /*
  * CPU interrupt bits.
diff --git a/include/asm-mips/dec/kn05.h b/include/asm-mips/dec/kn05.h
index b120362..15fe8f8 100644
--- a/include/asm-mips/dec/kn05.h
+++ b/include/asm-mips/dec/kn05.h
@@ -1,10 +1,12 @@
 /*
  *	include/asm-mips/dec/kn05.h
  *
- *	DECstation 5000/260 (4max+ or KN05) and DECsystem 5900/260
+ *	DECstation/DECsystem 5000/260 (4max+ or KN05), 5000/150 (4min
+ *	or KN04-BA), Personal DECstation/DECsystem 5000/50 (4maxine or
+ *	KN04-CA) and DECsystem 5900/260 (KN05) R4k CPU card MB ASIC
  *	definitions.
  *
- *	Copyright (C) 2002, 2003  Maciej W. Rozycki
+ *	Copyright (C) 2002, 2003, 2005  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -13,8 +15,8 @@
  *
  *	WARNING!  All this information is pure guesswork based on the
  *	ROM.  It is provided here in hope it will give someone some
- *	food for thought.  No documentation for the KN05 module has
- *	been located so far.
+ *	food for thought.  No documentation for the KN05 nor the KN04
+ *	module has been located so far.
  */
 #ifndef __ASM_MIPS_DEC_KN05_H
 #define __ASM_MIPS_DEC_KN05_H
@@ -24,48 +26,50 @@
 /*
  * The oncard MB (Memory Buffer) ASIC provides an additional address
  * decoder.  Certain address ranges within the "high" 16 slots are
- * passed to the I/O ASIC's decoder like with the KN03.  Others are
- * handled locally.  "Low" slots are always passed.
+ * passed to the I/O ASIC's decoder like with the KN03 or KN02-BA/CA.
+ * Others are handled locally.  "Low" slots are always passed.
  */
-#define KN05_MB_ROM	(16*IOASIC_SLOT_SIZE)	/* KN05 card ROM */
-#define KN05_IOCTL	(17*IOASIC_SLOT_SIZE)	/* I/O ASIC */
-#define KN05_ESAR	(18*IOASIC_SLOT_SIZE)	/* LANCE MAC address chip */
-#define KN05_LANCE	(19*IOASIC_SLOT_SIZE)	/* LANCE Ethernet */
-#define KN05_MB_INT	(20*IOASIC_SLOT_SIZE)	/* MB interrupt register */
-#define KN05_MB_EA	(21*IOASIC_SLOT_SIZE)	/* MB error address? */
-#define KN05_MB_EC	(22*IOASIC_SLOT_SIZE)	/* MB error ??? */
-#define KN05_MB_CSR	(23*IOASIC_SLOT_SIZE)	/* MB control & status */
-#define KN05_RES_24	(24*IOASIC_SLOT_SIZE)	/* unused? */
-#define KN05_RES_25	(25*IOASIC_SLOT_SIZE)	/* unused? */
-#define KN05_RES_26	(26*IOASIC_SLOT_SIZE)	/* unused? */
-#define KN05_RES_27	(27*IOASIC_SLOT_SIZE)	/* unused? */
-#define KN05_SCSI	(28*IOASIC_SLOT_SIZE)	/* ASC SCSI */
-#define KN05_RES_29	(29*IOASIC_SLOT_SIZE)	/* unused? */
-#define KN05_RES_30	(30*IOASIC_SLOT_SIZE)	/* unused? */
-#define KN05_RES_31	(31*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_SLOT_BASE	0x1fc00000
+
+#define KN4K_MB_ROM	(0*IOASIC_SLOT_SIZE)	/* KN05/KN04 card ROM */
+#define KN4K_IOCTL	(1*IOASIC_SLOT_SIZE)	/* I/O ASIC */
+#define KN4K_ESAR	(2*IOASIC_SLOT_SIZE)	/* LANCE MAC address chip */
+#define KN4K_LANCE	(3*IOASIC_SLOT_SIZE)	/* LANCE Ethernet */
+#define KN4K_MB_INT	(4*IOASIC_SLOT_SIZE)	/* MB interrupt register */
+#define KN4K_MB_EA	(5*IOASIC_SLOT_SIZE)	/* MB error address? */
+#define KN4K_MB_EC	(6*IOASIC_SLOT_SIZE)	/* MB error ??? */
+#define KN4K_MB_CSR	(7*IOASIC_SLOT_SIZE)	/* MB control & status */
+#define KN4K_RES_08	(8*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_RES_09	(9*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_RES_10	(10*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_RES_11	(11*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_SCSI	(12*IOASIC_SLOT_SIZE)	/* ASC SCSI */
+#define KN4K_RES_13	(13*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_RES_14	(14*IOASIC_SLOT_SIZE)	/* unused? */
+#define KN4K_RES_15	(15*IOASIC_SLOT_SIZE)	/* unused? */
 
 /*
  * Bits for the MB interrupt register.
  * The register appears read-only.
  */
-#define KN05_MB_INT_TC		(1<<0)		/* TURBOchannel? */
-#define KN05_MB_INT_RTC		(1<<1)		/* RTC? */
-#define KN05_MB_INT_MT		(1<<3)		/* ??? */
+#define KN4K_MB_INT_TC		(1<<0)		/* TURBOchannel? */
+#define KN4K_MB_INT_RTC		(1<<1)		/* RTC? */
+#define KN4K_MB_INT_MT		(1<<3)		/* ??? */
 
 /*
  * Bits for the MB control & status register.
  * Set to 0x00bf8001 on my system by the ROM.
  */
-#define KN05_MB_CSR_PF		(1<<0)		/* PreFetching enable? */
-#define KN05_MB_CSR_F		(1<<1)		/* ??? */
-#define KN05_MB_CSR_ECC		(0xff<<2)	/* ??? */
-#define KN05_MB_CSR_OD		(1<<10)		/* ??? */
-#define KN05_MB_CSR_CP		(1<<11)		/* ??? */
-#define KN05_MB_CSR_UNC		(1<<12)		/* ??? */
-#define KN05_MB_CSR_IM		(1<<13)		/* ??? */
-#define KN05_MB_CSR_NC		(1<<14)		/* ??? */
-#define KN05_MB_CSR_EE		(1<<15)		/* (bus) Exception Enable? */
-#define KN05_MB_CSR_MSK		(0x1f<<16)	/* ??? */
-#define KN05_MB_CSR_FW		(1<<21)		/* ??? */
+#define KN4K_MB_CSR_PF		(1<<0)		/* PreFetching enable? */
+#define KN4K_MB_CSR_F		(1<<1)		/* ??? */
+#define KN4K_MB_CSR_ECC		(0xff<<2)	/* ??? */
+#define KN4K_MB_CSR_OD		(1<<10)		/* ??? */
+#define KN4K_MB_CSR_CP		(1<<11)		/* ??? */
+#define KN4K_MB_CSR_UNC		(1<<12)		/* ??? */
+#define KN4K_MB_CSR_IM		(1<<13)		/* ??? */
+#define KN4K_MB_CSR_NC		(1<<14)		/* ??? */
+#define KN4K_MB_CSR_EE		(1<<15)		/* (bus) Exception Enable? */
+#define KN4K_MB_CSR_MSK		(0x1f<<16)	/* ??? */
+#define KN4K_MB_CSR_FW		(1<<21)		/* ??? */
 
 #endif /* __ASM_MIPS_DEC_KN05_H */
diff --git a/include/asm-mips/dec/prom.h b/include/asm-mips/dec/prom.h
index a05d6d3..1384dd0 100644
--- a/include/asm-mips/dec/prom.h
+++ b/include/asm-mips/dec/prom.h
@@ -24,7 +24,7 @@
  * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's.
  * Many of these will work for MIPSen as well!
  */
-#define VEC_RESET		(u64 *)KSEG1ADDR(0x1fc00000)
+#define VEC_RESET		(u64 *)CKSEG1ADDR(0x1fc00000)
 							/* Prom base address */
 
 #define PMAX_PROM_ENTRY(x)	(VEC_RESET + (x))	/* Prom jump table */
@@ -111,19 +111,21 @@
  * On MIPS64 we have to call PROM functions via a helper
  * dispatcher to accomodate ABI incompatibilities.
  */
-#define __DEC_PROM_O32 __attribute__((alias("call_o32")))
+#define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \
+				 __asm__(#fun " = call_o32")
 
-int _rex_bootinit(int (*)(void)) __DEC_PROM_O32;
-int _rex_bootread(int (*)(void)) __DEC_PROM_O32;
-int _rex_getbitmap(int (*)(memmap *), memmap *) __DEC_PROM_O32;
-unsigned long *_rex_slot_address(unsigned long *(*)(int), int) __DEC_PROM_O32;
-void *_rex_gettcinfo(void *(*)(void)) __DEC_PROM_O32;
-int _rex_getsysid(int (*)(void)) __DEC_PROM_O32;
-void _rex_clear_cache(void (*)(void)) __DEC_PROM_O32;
+int __DEC_PROM_O32(_rex_bootinit, (int (*)(void)));
+int __DEC_PROM_O32(_rex_bootread, (int (*)(void)));
+int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), memmap *));
+unsigned long *__DEC_PROM_O32(_rex_slot_address,
+			     (unsigned long *(*)(int), int));
+void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void)));
+int __DEC_PROM_O32(_rex_getsysid, (int (*)(void)));
+void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void)));
 
-int _prom_getchar(int (*)(void)) __DEC_PROM_O32;
-char *_prom_getenv(char *(*)(char *), char *) __DEC_PROM_O32;
-int _prom_printf(int (*)(char *, ...), char *, ...) __DEC_PROM_O32;
+int __DEC_PROM_O32(_prom_getchar, (int (*)(void)));
+char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), char *));
+int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), char *, ...));
 
 
 #define rex_bootinit()		_rex_bootinit(__rex_bootinit)
diff --git a/include/asm-mips/dec/system.h b/include/asm-mips/dec/system.h
new file mode 100644
index 0000000..78af51f
--- /dev/null
+++ b/include/asm-mips/dec/system.h
@@ -0,0 +1,18 @@
+/*
+ *	include/asm-mips/dec/system.h
+ *
+ *	Generic DECstation/DECsystem bits.
+ *
+ *	Copyright (C) 2005  Maciej W. Rozycki
+ *
+ *	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 __ASM_DEC_SYSTEM_H
+#define __ASM_DEC_SYSTEM_H
+
+extern unsigned long dec_kn_slot_base, dec_kn_slot_size;
+
+#endif /* __ASM_DEC_SYSTEM_H */
diff --git a/include/asm-mips/dec/tc.h b/include/asm-mips/dec/tc.h
index d7bba43..9cb51f2 100644
--- a/include/asm-mips/dec/tc.h
+++ b/include/asm-mips/dec/tc.h
@@ -7,10 +7,8 @@
  *
  * Copyright (c) 1998 Harald Koerfgen
  */
-#ifndef ASM_TC_H
-#define ASM_TC_H
-
-extern unsigned long system_base;
+#ifndef __ASM_DEC_TC_H
+#define __ASM_DEC_TC_H
 
 /*
  * Search for a TURBOchannel Option Module
@@ -36,8 +34,8 @@
  */
 extern unsigned long get_tc_irq_nr(int);
 /*
- * Return TURBOchannel clock frequency in hz
+ * Return TURBOchannel clock frequency in Hz
  */
 extern unsigned long get_tc_speed(void);
 
-#endif
+#endif /* __ASM_DEC_TC_H */
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
index a606dbe..85435a8 100644
--- a/include/asm-mips/delay.h
+++ b/include/asm-mips/delay.h
@@ -12,11 +12,9 @@
 
 #include <linux/config.h>
 #include <linux/param.h>
-
+#include <linux/smp.h>
 #include <asm/compiler.h>
 
-extern unsigned long loops_per_jiffy;
-
 static inline void __delay(unsigned long loops)
 {
 	if (sizeof(long) == 4)
@@ -82,11 +80,7 @@
 	__delay(usecs);
 }
 
-#ifdef CONFIG_SMP
 #define __udelay_val cpu_data[smp_processor_id()].udelay_val
-#else
-#define __udelay_val loops_per_jiffy
-#endif
 
 #define udelay(usecs) __udelay((usecs),__udelay_val)
 
diff --git a/include/asm-mips/dma-mapping.h b/include/asm-mips/dma-mapping.h
index af28dc8..4328863 100644
--- a/include/asm-mips/dma-mapping.h
+++ b/include/asm-mips/dma-mapping.h
@@ -5,13 +5,13 @@
 #include <asm/cache.h>
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, int flag);
+			   dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_noncoherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle);
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, int flag);
+			   dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle);
diff --git a/include/asm-mips/dsp.h b/include/asm-mips/dsp.h
new file mode 100644
index 0000000..50f556b
--- /dev/null
+++ b/include/asm-mips/dsp.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005 Mips Technologies
+ * Author: Chris Dearman, chris@mips.com derived from fpu.h
+ *
+ * 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 _ASM_DSP_H
+#define _ASM_DSP_H
+
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/hazards.h>
+#include <asm/mipsregs.h>
+
+#define DSP_DEFAULT	0x00000000
+#define DSP_MASK	0x1f
+
+#define __enable_dsp_hazard()						\
+do {									\
+	asm("_ehb");							\
+} while (0)
+
+static inline void __init_dsp(void)
+{
+	mthi1(0);
+	mtlo1(0);
+	mthi2(0);
+	mtlo2(0);
+	mthi3(0);
+	mtlo3(0);
+	wrdsp(DSP_DEFAULT, DSP_MASK);
+}
+
+static inline void init_dsp(void)
+{
+	if (cpu_has_dsp)
+		__init_dsp();
+}
+
+#define __save_dsp(tsk)							\
+do {									\
+	tsk->thread.dsp.dspr[0] = mfhi1();				\
+	tsk->thread.dsp.dspr[1] = mflo1();				\
+	tsk->thread.dsp.dspr[2] = mfhi2();				\
+	tsk->thread.dsp.dspr[3] = mflo2();				\
+	tsk->thread.dsp.dspr[4] = mfhi3();				\
+	tsk->thread.dsp.dspr[5] = mflo3();				\
+} while (0)
+
+#define save_dsp(tsk)							\
+do {									\
+	if (cpu_has_dsp)						\
+		__save_dsp(tsk);					\
+} while (0)
+
+#define __restore_dsp(tsk)						\
+do {									\
+	mthi1(tsk->thread.dsp.dspr[0]);					\
+	mtlo1(tsk->thread.dsp.dspr[1]);					\
+	mthi2(tsk->thread.dsp.dspr[2]);					\
+	mtlo2(tsk->thread.dsp.dspr[3]);					\
+	mthi3(tsk->thread.dsp.dspr[4]);					\
+	mtlo3(tsk->thread.dsp.dspr[5]);					\
+} while (0)
+
+#define restore_dsp(tsk)						\
+do {									\
+	if (cpu_has_dsp)						\
+		__restore_dsp(tsk);					\
+} while (0)
+
+#define __get_dsp_regs(tsk)						\
+({									\
+	if (tsk == current)						\
+		__save_dsp(current);					\
+									\
+	tsk->thread.dsp.dspr;						\
+})
+
+#endif /* _ASM_DSP_H */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index e488114..7420f12 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -2,6 +2,8 @@
  * 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.
+ *
+ * Much of this is taken from binutils and GNU libc ...
  */
 #ifndef _ASM_ELF_H
 #define _ASM_ELF_H
@@ -17,6 +19,8 @@
 #define EF_MIPS_ARCH_5		0x40000000	/* -mips5 code.  */
 #define EF_MIPS_ARCH_32		0x50000000	/* MIPS32 code.  */
 #define EF_MIPS_ARCH_64		0x60000000	/* MIPS64 code.  */
+#define EF_MIPS_ARCH_32R2	0x70000000	/* MIPS32 R2 code.  */
+#define EF_MIPS_ARCH_64R2	0x80000000	/* MIPS64 R2 code.  */
 
 /* The ABI of a file. */
 #define EF_MIPS_ABI_O32		0x00001000	/* O32 ABI.  */
@@ -105,7 +109,11 @@
 #define R_MIPS_LOVENDOR		100
 #define R_MIPS_HIVENDOR		127
 
-#define SHN_MIPS_ACCOMON	0xff00
+#define SHN_MIPS_ACCOMON	0xff00		/* Allocated common symbols */
+#define SHN_MIPS_TEXT		0xff01		/* Allocated test symbols.  */
+#define SHN_MIPS_DATA		0xff02		/* Allocated data symbols.  */
+#define SHN_MIPS_SCOMMON	0xff03		/* Small common symbols */
+#define SHN_MIPS_SUNDEFINED	0xff04		/* Small undefined symbols */
 
 #define SHT_MIPS_LIST		0x70000000
 #define SHT_MIPS_CONFLICT	0x70000002
@@ -193,50 +201,92 @@
 
 #ifdef __KERNEL__
 
+struct mips_abi;
+
+extern struct mips_abi mips_abi;
+extern struct mips_abi mips_abi_32;
+extern struct mips_abi mips_abi_n32;
+
 #ifdef CONFIG_32BIT
 
-#define SET_PERSONALITY(ex, ibcs2)			\
-do {							\
-	if (ibcs2)					\
-		set_personality(PER_SVR4);		\
-	set_personality(PER_LINUX);			\
+#define SET_PERSONALITY(ex, ibcs2)					\
+do {									\
+	if (ibcs2)							\
+		set_personality(PER_SVR4);				\
+	set_personality(PER_LINUX);					\
+									\
+	current->thread.abi = &mips_abi;				\
 } while (0)
 
 #endif /* CONFIG_32BIT */
 
 #ifdef CONFIG_64BIT
 
-#define SET_PERSONALITY(ex, ibcs2)				\
-do {	current->thread.mflags &= ~MF_ABI_MASK;			\
-	if ((ex).e_ident[EI_CLASS] == ELFCLASS32) {		\
-		if ((((ex).e_flags & EF_MIPS_ABI2) != 0) &&	\
-		     ((ex).e_flags & EF_MIPS_ABI) == 0)		\
-			current->thread.mflags |= MF_N32;	\
-		else						\
-			current->thread.mflags |= MF_O32;	\
-	} else							\
-		current->thread.mflags |= MF_N64;		\
-	if (ibcs2)						\
-		set_personality(PER_SVR4);			\
-	else if (current->personality != PER_LINUX32)		\
-		set_personality(PER_LINUX);			\
+#ifdef CONFIG_MIPS32_N32
+#define __SET_PERSONALITY32_N32()					\
+	do {								\
+		current->thread.mflags |= MF_N32;			\
+		current->thread.abi = &mips_abi_n32;			\
+	} while (0)
+#else
+#define __SET_PERSONALITY32_N32()					\
+	do { } while (0)
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+#define __SET_PERSONALITY32_O32()					\
+	do {								\
+		current->thread.mflags |= MF_O32;			\
+		current->thread.abi = &mips_abi_32;			\
+	} while (0)
+#else
+#define __SET_PERSONALITY32_O32()					\
+	do { } while (0)
+#endif
+
+#ifdef CONFIG_MIPS32_COMPAT
+#define __SET_PERSONALITY32(ex)						\
+do {									\
+	if ((((ex).e_flags & EF_MIPS_ABI2) != 0) &&			\
+	     ((ex).e_flags & EF_MIPS_ABI) == 0)				\
+		__SET_PERSONALITY32_N32();				\
+	else								\
+		__SET_PERSONALITY32_O32();				\
+} while (0)
+#else
+#define __SET_PERSONALITY32(ex)	do { } while (0)
+#endif
+
+#define SET_PERSONALITY(ex, ibcs2)					\
+do {									\
+	current->thread.mflags &= ~MF_ABI_MASK;				\
+	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)			\
+		__SET_PERSONALITY32(ex);				\
+	else {								\
+		current->thread.mflags |= MF_N64;			\
+		current->thread.abi = &mips_abi;			\
+	}								\
+									\
+	if (ibcs2)							\
+		set_personality(PER_SVR4);				\
+	else if (current->personality != PER_LINUX32)			\
+		set_personality(PER_LINUX);				\
 } while (0)
 
 #endif /* CONFIG_64BIT */
 
 extern void dump_regs(elf_greg_t *, struct pt_regs *regs);
+extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
 
 #define ELF_CORE_COPY_REGS(elf_regs, regs)			\
 	dump_regs((elf_greg_t *)&(elf_regs), regs);
+#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
 	dump_task_fpu(tsk, elf_fpregs)
 
 #endif /* __KERNEL__ */
 
-/* This one accepts IRIX binaries.  */
-#define irix_elf_check_arch(hdr)	((hdr)->e_flags & RHF_SGI_ONLY)
-
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h
index 3c0d840..9d3e6e7 100644
--- a/include/asm-mips/errno.h
+++ b/include/asm-mips/errno.h
@@ -119,6 +119,10 @@
 #define	EOWNERDEAD	165	/* Owner died */
 #define	ENOTRECOVERABLE	166	/* State not recoverable */
 
+/* for robust mutexes */
+#define	EOWNERDEAD	165	/* Owner died */
+#define	ENOTRECOVERABLE	166	/* State not recoverable */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 #ifdef __KERNEL__
diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h
index 06c5d13..43d047a 100644
--- a/include/asm-mips/fcntl.h
+++ b/include/asm-mips/fcntl.h
@@ -3,11 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 96, 97, 98, 99, 2003 Ralf Baechle
+ * Copyright (C) 1995, 96, 97, 98, 99, 2003, 05 Ralf Baechle
  */
 #ifndef _ASM_FCNTL_H
 #define _ASM_FCNTL_H
 
+#include <linux/config.h>
+
 #define O_APPEND	0x0008
 #define O_SYNC		0x0010
 #define O_NONBLOCK	0x0080
@@ -40,13 +42,13 @@
  * contain all the same fields as struct flock.
  */
 
-#ifndef __mips64
+#ifdef CONFIG_32BIT
 
 struct flock {
 	short	l_type;
 	short	l_whence;
-	__kernel_off_t l_start;
-	__kernel_off_t l_len;
+	off_t	l_start;
+	off_t	l_len;
 	long	l_sysid;
 	__kernel_pid_t l_pid;
 	long	pad[4];
@@ -54,13 +56,8 @@
 
 #define HAVE_ARCH_STRUCT_FLOCK
 
-#endif
+#endif /* CONFIG_32BIT */
 
 #include <asm-generic/fcntl.h>
 
-typedef struct flock flock_t;
-#ifndef __mips64
-typedef struct flock64 flock64_t;
-#endif
-
 #endif /* _ASM_FCNTL_H */
diff --git a/include/asm-mips/fixmap.h b/include/asm-mips/fixmap.h
index 26b6a90..73a3028 100644
--- a/include/asm-mips/fixmap.h
+++ b/include/asm-mips/fixmap.h
@@ -107,4 +107,11 @@
 	return __virt_to_fix(vaddr);
 }
 
+/*
+ * Called from pgtable_init()
+ */
+extern void fixrange_init(unsigned long start, unsigned long end,
+        pgd_t *pgd_base);
+
+
 #endif
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index ea24e73..9c828b1 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -80,9 +80,14 @@
 
 #define clear_fpu_owner()	clear_thread_flag(TIF_USEDFPU)
 
+static inline int __is_fpu_owner(void)
+{
+	return test_thread_flag(TIF_USEDFPU);
+}
+
 static inline int is_fpu_owner(void)
 {
-	return cpu_has_fpu && test_thread_flag(TIF_USEDFPU);
+	return cpu_has_fpu && __is_fpu_owner();
 }
 
 static inline void own_fpu(void)
@@ -127,7 +132,7 @@
 static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
 {
 	if (cpu_has_fpu) {
-		if ((tsk == current) && is_fpu_owner())
+		if ((tsk == current) && __is_fpu_owner())
 			_save_fp(current);
 		return tsk->thread.fpu.hard.fpr;
 	}
diff --git a/include/asm-mips/fpu_emulator.h b/include/asm-mips/fpu_emulator.h
index 46972ae..16cb4d1 100644
--- a/include/asm-mips/fpu_emulator.h
+++ b/include/asm-mips/fpu_emulator.h
@@ -23,16 +23,15 @@
 #ifndef _ASM_FPU_EMULATOR_H
 #define _ASM_FPU_EMULATOR_H
 
-struct mips_fpu_emulator_private {
-	unsigned int eir;
-	struct {
-		unsigned int emulated;
-		unsigned int loads;
-		unsigned int stores;
-		unsigned int cp1ops;
-		unsigned int cp1xops;
-		unsigned int errors;
-	} stats;
+struct mips_fpu_emulator_stats {
+	unsigned int emulated;
+	unsigned int loads;
+	unsigned int stores;
+	unsigned int cp1ops;
+	unsigned int cp1xops;
+	unsigned int errors;
 };
 
+extern struct mips_fpu_emulator_stats fpuemustats;
+
 #endif /* _ASM_FPU_EMULATOR_H */
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
index 9feff4c..2454c44 100644
--- a/include/asm-mips/futex.h
+++ b/include/asm-mips/futex.h
@@ -3,10 +3,45 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <linux/futex.h>
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_SMP
+#define __FUTEX_SMP_SYNC "	sync					\n"
+#else
+#define __FUTEX_SMP_SYNC
+#endif
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)		\
+{									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	.set	mips3					\n"	\
+	"1:	ll	%1, (%3)	# __futex_atomic_op1	\n"	\
+	"	.set	mips0					\n"	\
+	"	" insn	"					\n"	\
+	"	.set	mips3					\n"	\
+	"2:	sc	$1, (%3)				\n"	\
+	"	beqzl	$1, 1b					\n"	\
+	__FUTEX_SMP_SYNC						\
+	"3:							\n"	\
+	"	.set	pop					\n"	\
+	"	.set	mips0					\n"	\
+	"	.section .fixup,\"ax\"				\n"	\
+	"4:	li	%0, %5					\n"	\
+	"	j	2b					\n"	\
+	"	.previous					\n"	\
+	"	.section __ex_table,\"a\"			\n"	\
+	"	"__UA_ADDR "\t1b, 4b				\n"	\
+	"	"__UA_ADDR "\t2b, 4b				\n"	\
+	"	.previous					\n"	\
+	: "=r" (ret), "=r" (oldval)					\
+	: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));		\
+}
+
 static inline int
 futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 {
@@ -25,10 +60,25 @@
 
 	switch (op) {
 	case FUTEX_OP_SET:
+		__futex_atomic_op("move	$1, %z4", ret, oldval, uaddr, oparg);
+		break;
+
 	case FUTEX_OP_ADD:
+		__futex_atomic_op("addu	$1, %1, %z4",
+		                  ret, oldval, uaddr, oparg);
+		break;
 	case FUTEX_OP_OR:
+		__futex_atomic_op("or	$1, %1, %z4",
+		                  ret, oldval, uaddr, oparg);
+		break;
 	case FUTEX_OP_ANDN:
+		__futex_atomic_op("and	$1, %1, %z4",
+		                  ret, oldval, uaddr, ~oparg);
+		break;
 	case FUTEX_OP_XOR:
+		__futex_atomic_op("xor	$1, %1, %z4",
+		                  ret, oldval, uaddr, oparg);
+		break;
 	default:
 		ret = -ENOSYS;
 	}
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index f524eac..7517189 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -74,7 +74,8 @@
 #define irq_disable_hazard
 	_ehb
 
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
+      defined(CONFIG_CPU_SB1)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
@@ -107,6 +108,7 @@
 	"	.endm						\n\t");
 
 #ifdef CONFIG_CPU_RM9000
+
 /*
  * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
  * use of the JTLB for instructions should not occur for 4 cpu cycles and use
@@ -124,6 +126,9 @@
 		".set\tmips32\n\t"					\
 		"_ssnop; _ssnop; _ssnop; _ssnop\n\t"			\
 		".set\tmips0")
+
+#define back_to_back_c0_hazard()	do { } while (0)
+
 #else
 
 /*
@@ -144,15 +149,13 @@
 #endif
 
 /*
- * mtc0->mfc0 hazard
- * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
- * It is a MIPS32R2 processor so ehb will clear the hazard.
+ * Interrupt enable/disable hazards
+ * Some processors have hazards when modifying
+ * the status register to change the interrupt state
  */
 
 #ifdef CONFIG_CPU_MIPSR2
-/*
- * Use a macro for ehb unless explicit support for MIPSR2 is enabled
- */
+
 __asm__(
 	"	.macro\tirq_enable_hazard			\n\t"
 	"	_ehb						\n\t"
@@ -160,17 +163,26 @@
 	"							\n\t"
 	"	.macro\tirq_disable_hazard			\n\t"
 	"	_ehb						\n\t"
+	"	.endm						\n\t"
+	"							\n\t"
+	"	.macro\tback_to_back_c0_hazard			\n\t"
+	"	_ehb						\n\t"
 	"	.endm");
 
 #define irq_enable_hazard()						\
 	__asm__ __volatile__(						\
-	"_ehb\t\t\t\t# irq_enable_hazard")
+	"irq_enable_hazard")
 
 #define irq_disable_hazard()						\
 	__asm__ __volatile__(						\
-	"_ehb\t\t\t\t# irq_disable_hazard")
+	"irq_disable_hazard")
 
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
+#define back_to_back_c0_hazard()					\
+	__asm__ __volatile__(						\
+	"back_to_back_c0_hazard")
+
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
+      defined(CONFIG_CPU_SB1)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
@@ -186,6 +198,8 @@
 #define irq_enable_hazard()	do { } while (0)
 #define irq_disable_hazard()	do { } while (0)
 
+#define back_to_back_c0_hazard()	do { } while (0)
+
 #else
 
 /*
@@ -208,8 +222,30 @@
 #define irq_enable_hazard()	do { } while (0)
 #define irq_disable_hazard()						\
 	__asm__ __volatile__(						\
-	"_ssnop; _ssnop; _ssnop;\t\t# irq_disable_hazard")
+	"irq_disable_hazard")
 
+#define back_to_back_c0_hazard()					\
+	__asm__ __volatile__(						\
+	"	.set noreorder				\n"		\
+	"	nop; nop; nop				\n"		\
+	"	.set reorder				\n")
+
+#endif
+
+#ifdef CONFIG_CPU_MIPSR2
+#define instruction_hazard()						\
+do {									\
+__label__ __next;							\
+	__asm__ __volatile__(						\
+	"	jr.hb	%0					\n"	\
+	:								\
+	: "r" (&&__next));						\
+__next:									\
+	;								\
+} while (0)
+
+#else
+#define instruction_hazard() do { } while (0)
 #endif
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-mips/highmem.h b/include/asm-mips/highmem.h
index f49930d..8cf5984 100644
--- a/include/asm-mips/highmem.h
+++ b/include/asm-mips/highmem.h
@@ -75,6 +75,7 @@
 }
 
 static inline void kunmap_atomic(void *kvaddr, enum km_type type) { }
+#define kmap_atomic_pfn(pfn, idx)	page_address(pfn_to_page(pfn))
 
 #define kmap_atomic_to_page(ptr) virt_to_page(ptr)
 
@@ -86,6 +87,7 @@
 extern void __kunmap(struct page *page);
 extern void *__kmap_atomic(struct page *page, enum km_type type);
 extern void __kunmap_atomic(void *kvaddr, enum km_type type);
+extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
 extern struct page *__kmap_atomic_to_page(void *ptr);
 
 #define kmap			__kmap
diff --git a/include/asm-mips/inst.h b/include/asm-mips/inst.h
index 6ad5172..e0745f4 100644
--- a/include/asm-mips/inst.h
+++ b/include/asm-mips/inst.h
@@ -28,7 +28,7 @@
 	sdl_op, sdr_op, swr_op, cache_op,
 	ll_op, lwc1_op, lwc2_op, pref_op,
 	lld_op, ldc1_op, ldc2_op, ld_op,
-	sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */
+	sc_op, swc1_op, swc2_op, rdhwr_op,
 	scd_op, sdc1_op, sdc2_op, sd_op
 };
 
@@ -62,10 +62,10 @@
 	spimi_op, unused_rt_op_0x05, unused_rt_op_0x06, unused_rt_op_0x07,
 	tgei_op, tgeiu_op, tlti_op, tltiu_op,
 	teqi_op, unused_0x0d_rt_op, tnei_op, unused_0x0f_rt_op,
-	bltzal_op, bgezal_op, bltzall_op, bgezall_op
-	/*
-	 * The others (0x14 - 0x1f) are unused.
- 	 */
+	bltzal_op, bgezal_op, bltzall_op, bgezall_op,
+	rt_op_0x14, rt_op_0x15, rt_op_0x16, rt_op_0x17,
+	rt_op_0x18, rt_op_0x19, rt_op_0x1a, rt_op_0x1b,
+	bposge32_op, rt_op_0x1d, rt_op_0x1e, rt_op_0x1f
 };
 
 /*
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index e8357f5..a573576 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -11,20 +11,25 @@
 #ifndef _ASM_INTERRUPT_H
 #define _ASM_INTERRUPT_H
 
+#include <linux/config.h>
 #include <asm/hazards.h>
 
 __asm__ (
-	".macro\tlocal_irq_enable\n\t"
-	".set\tpush\n\t"
-	".set\treorder\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t$1,$12\n\t"
-	"ori\t$1,0x1f\n\t"
-	"xori\t$1,0x1e\n\t"
-	"mtc0\t$1,$12\n\t"
-	"irq_enable_hazard\n\t"
-	".set\tpop\n\t"
-	".endm");
+	"	.macro	local_irq_enable				\n"
+	"	.set	push						\n"
+	"	.set	reorder						\n"
+	"	.set	noat						\n"
+#ifdef CONFIG_CPU_MIPSR2
+	"	ei							\n"
+#else
+	"	mfc0	$1,$12						\n"
+	"	ori	$1,0x1f						\n"
+	"	xori	$1,0x1e						\n"
+	"	mtc0	$1,$12						\n"
+#endif
+	"	irq_enable_hazard					\n"
+	"	.set	pop						\n"
+	"	.endm");
 
 static inline void local_irq_enable(void)
 {
@@ -43,17 +48,21 @@
  * no nops at all.
  */
 __asm__ (
-	".macro\tlocal_irq_disable\n\t"
-	".set\tpush\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t$1,$12\n\t"
-	"ori\t$1,1\n\t"
-	"xori\t$1,1\n\t"
-	".set\tnoreorder\n\t"
-	"mtc0\t$1,$12\n\t"
-	"irq_disable_hazard\n\t"
-	".set\tpop\n\t"
-	".endm");
+	"	.macro	local_irq_disable\n"
+	"	.set	push						\n"
+	"	.set	noat						\n"
+#ifdef CONFIG_CPU_MIPSR2
+	"	di							\n"
+#else
+	"	mfc0	$1,$12						\n"
+	"	ori	$1,1						\n"
+	"	xori	$1,1						\n"
+	"	.set	noreorder					\n"
+	"	mtc0	$1,$12						\n"
+#endif
+	"	irq_disable_hazard					\n"
+	"	.set	pop						\n"
+	"	.endm							\n");
 
 static inline void local_irq_disable(void)
 {
@@ -65,12 +74,12 @@
 }
 
 __asm__ (
-	".macro\tlocal_save_flags flags\n\t"
-	".set\tpush\n\t"
-	".set\treorder\n\t"
-	"mfc0\t\\flags, $12\n\t"
-	".set\tpop\n\t"
-	".endm");
+	"	.macro	local_save_flags flags				\n"
+	"	.set	push						\n"
+	"	.set	reorder						\n"
+	"	mfc0	\\flags, $12					\n"
+	"	.set	pop						\n"
+	"	.endm							\n");
 
 #define local_save_flags(x)						\
 __asm__ __volatile__(							\
@@ -78,18 +87,22 @@
 	: "=r" (x))
 
 __asm__ (
-	".macro\tlocal_irq_save result\n\t"
-	".set\tpush\n\t"
-	".set\treorder\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t\\result, $12\n\t"
-	"ori\t$1, \\result, 1\n\t"
-	"xori\t$1, 1\n\t"
-	".set\tnoreorder\n\t"
-	"mtc0\t$1, $12\n\t"
-	"irq_disable_hazard\n\t"
-	".set\tpop\n\t"
-	".endm");
+	"	.macro	local_irq_save result				\n"
+	"	.set	push						\n"
+	"	.set	reorder						\n"
+	"	.set	noat						\n"
+#ifdef CONFIG_CPU_MIPSR2
+	"	di	\\result					\n"
+#else
+	"	mfc0	\\result, $12					\n"
+	"	ori	$1, \\result, 1					\n"
+	"	xori	$1, 1						\n"
+	"	.set	noreorder					\n"
+	"	mtc0	$1, $12						\n"
+#endif
+	"	irq_disable_hazard					\n"
+	"	.set	pop						\n"
+	"	.endm							\n");
 
 #define local_irq_save(x)						\
 __asm__ __volatile__(							\
@@ -99,19 +112,37 @@
 	: "memory")
 
 __asm__ (
-	".macro\tlocal_irq_restore flags\n\t"
-	".set\tnoreorder\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t$1, $12\n\t"
-	"andi\t\\flags, 1\n\t"
-	"ori\t$1, 1\n\t"
-	"xori\t$1, 1\n\t"
-	"or\t\\flags, $1\n\t"
-	"mtc0\t\\flags, $12\n\t"
-	"irq_disable_hazard\n\t"
-	".set\tat\n\t"
-	".set\treorder\n\t"
-	".endm");
+	"	.macro	local_irq_restore flags				\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+	/*
+	 * Slow, but doesn't suffer from a relativly unlikely race
+	 * condition we're having since days 1.
+	 */
+	"	beqz	\\flags, 1f					\n"
+	"	 di							\n"
+	"	ei							\n"
+	"1:								\n"
+#elif defined(CONFIG_CPU_MIPSR2)
+	/*
+	 * Fast, dangerous.  Life is fun, life is good.
+	 */
+	"	mfc0	$1, $12						\n"
+	"	ins	$1, \\flags, 0, 1				\n"
+	"	mtc0	$1, $12						\n"
+#else
+	"	mfc0	$1, $12						\n"
+	"	andi	\\flags, 1					\n"
+	"	ori	$1, 1						\n"
+	"	xori	$1, 1						\n"
+	"	or	\\flags, $1					\n"
+	"	mtc0	\\flags, $12					\n"
+#endif
+	"	irq_disable_hazard					\n"
+	"	.set	at						\n"
+	"	.set	reorder						\n"
+	"	.endm							\n");
 
 #define local_irq_restore(flags)					\
 do {									\
diff --git a/include/asm-mips/inventory.h b/include/asm-mips/inventory.h
index 4cd36fe..92d90f7 100644
--- a/include/asm-mips/inventory.h
+++ b/include/asm-mips/inventory.h
@@ -4,6 +4,8 @@
 #ifndef __ASM_INVENTORY_H
 #define __ASM_INVENTORY_H
 
+#include <linux/compiler.h>
+
 typedef struct inventory_s {
 	struct inventory_s *inv_next;
 	int    inv_class;
@@ -14,7 +16,9 @@
 } inventory_t;
 
 extern int inventory_items;
-void add_to_inventory (int class, int type, int controller, int unit, int state);
-int dump_inventory_to_user (void *userbuf, int size);
+
+extern void add_to_inventory (int class, int type, int controller, int unit, int state);
+extern int dump_inventory_to_user (void __user *userbuf, int size);
+extern int __init init_inventory(void);
 
 #endif /* __ASM_INVENTORY_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 039845f..3061870 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -25,7 +25,9 @@
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/processor.h>
+#include <asm/string.h>
 
+#include <ioremap.h>
 #include <mangle-port.h>
 
 /*
@@ -34,7 +36,7 @@
 #undef CONF_SLOWDOWN_IO
 
 /*
- * Raw operations are never swapped in software.  Otoh values that raw
+ * Raw operations are never swapped in software.  OTOH values that raw
  * operations are working on may or may not have been swapped by the bus
  * hardware.  An example use would be for flash memory that's used for
  * execute in place.
@@ -43,45 +45,53 @@
 # define __raw_ioswabw(x)	(x)
 # define __raw_ioswabl(x)	(x)
 # define __raw_ioswabq(x)	(x)
+# define ____raw_ioswabq(x)	(x)
 
 /*
  * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware;
  * less sane hardware forces software to fiddle with this...
+ *
+ * Regardless, if the host bus endianness mismatches that of PCI/ISA, then
+ * you can't have the numerical value of data and byte addresses within
+ * multibyte quantities both preserved at the same time.  Hence two
+ * variations of functions: non-prefixed ones that preserve the value
+ * and prefixed ones that preserve byte addresses.  The latters are
+ * typically used for moving raw data between a peripheral and memory (cf.
+ * string I/O functions), hence the "mem_" prefix.
  */
 #if defined(CONFIG_SWAP_IO_SPACE)
 
 # define ioswabb(x)		(x)
+# define mem_ioswabb(x)		(x)
 # ifdef CONFIG_SGI_IP22
 /*
  * IP22 seems braindead enough to swap 16bits values in hardware, but
  * not 32bits.  Go figure... Can't tell without documentation.
  */
 #  define ioswabw(x)		(x)
+#  define mem_ioswabw(x)	le16_to_cpu(x)
 # else
 #  define ioswabw(x)		le16_to_cpu(x)
+#  define mem_ioswabw(x)	(x)
 # endif
 # define ioswabl(x)		le32_to_cpu(x)
+# define mem_ioswabl(x)		(x)
 # define ioswabq(x)		le64_to_cpu(x)
+# define mem_ioswabq(x)		(x)
 
 #else
 
 # define ioswabb(x)		(x)
+# define mem_ioswabb(x)		(x)
 # define ioswabw(x)		(x)
+# define mem_ioswabw(x)		cpu_to_le16(x)
 # define ioswabl(x)		(x)
+# define mem_ioswabl(x)		cpu_to_le32(x)
 # define ioswabq(x)		(x)
+# define mem_ioswabq(x)		cpu_to_le32(x)
 
 #endif
 
-/*
- * Native bus accesses never swapped.
- */
-#define bus_ioswabb(x)		(x)
-#define bus_ioswabw(x)		(x)
-#define bus_ioswabl(x)		(x)
-#define bus_ioswabq(x)		(x)
-
-#define __bus_ioswabq		bus_ioswabq
-
 #define IO_SPACE_LIMIT 0xffff
 
 /*
@@ -194,12 +204,14 @@
  */
 #define page_to_phys(page)	((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
-extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags);
+extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags);
 extern void __iounmap(volatile void __iomem *addr);
 
-static inline void * __ioremap_mode(phys_t offset, unsigned long size,
+static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
 {
+#define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
+
 	if (cpu_has_64bit_addresses) {
 		u64 base = UNCAC_BASE;
 
@@ -209,10 +221,30 @@
 		 */
 		if (flags == _CACHE_UNCACHED)
 			base = (u64) IO_BASE;
-		return (void *) (unsigned long) (base + offset);
+		return (void __iomem *) (unsigned long) (base + offset);
+	} else if (__builtin_constant_p(offset) &&
+		   __builtin_constant_p(size) && __builtin_constant_p(flags)) {
+		phys_t phys_addr, last_addr;
+
+		phys_addr = fixup_bigphys_addr(offset, size);
+
+		/* Don't allow wraparound or zero size. */
+		last_addr = phys_addr + size - 1;
+		if (!size || last_addr < phys_addr)
+			return NULL;
+
+		/*
+		 * Map uncached objects in the low 512MB of address
+		 * space using KSEG1.
+		 */
+		if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) &&
+		    flags == _CACHE_UNCACHED)
+			return (void __iomem *)CKSEG1ADDR(phys_addr);
 	}
 
 	return __ioremap(offset, size, flags);
+
+#undef __IS_LOW512
 }
 
 /*
@@ -264,12 +296,16 @@
 
 static inline void iounmap(volatile void __iomem *addr)
 {
-	if (cpu_has_64bit_addresses)
+#define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
+
+	if (cpu_has_64bit_addresses ||
+	    (__builtin_constant_p(addr) && __IS_KSEG1(addr)))
 		return;
 
 	__iounmap(addr);
-}
 
+#undef __IS_KSEG1
+}
 
 #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq)			\
 									\
@@ -319,7 +355,8 @@
 	else if (cpu_has_64bits) {					\
 		unsigned long __flags;					\
 									\
-		local_irq_save(__flags);				\
+		if (irq)						\
+			local_irq_save(__flags);			\
 		__asm__ __volatile__(					\
 			".set	mips3"		"\t\t# __readq"	"\n\t"	\
 			"ld	%L0, %1"			"\n\t"	\
@@ -328,7 +365,8 @@
 			".set	mips0"				"\n"	\
 			: "=r" (__val)					\
 			: "m" (*__mem));				\
-		local_irq_restore(__flags);				\
+		if (irq)						\
+			local_irq_restore(__flags);			\
 	} else {							\
 		__val = 0;						\
 		BUG();							\
@@ -349,11 +387,11 @@
 									\
 	__val = pfx##ioswab##bwlq(val);					\
 									\
-	if (sizeof(type) != sizeof(u64)) {				\
-		*__addr = __val;					\
-		slow;							\
-	} else								\
-		BUILD_BUG();						\
+	/* Really, we want this to be atomic */				\
+	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
+									\
+	*__addr = __val;						\
+	slow;								\
 }									\
 									\
 static inline type pfx##in##bwlq##p(unsigned long port)			\
@@ -364,13 +402,10 @@
 	port = __swizzle_addr_##bwlq(port);				\
 	__addr = (void *)(mips_io_port_base + port);			\
 									\
-	if (sizeof(type) != sizeof(u64)) {				\
-		__val = *__addr;					\
-		slow;							\
-	} else {							\
-		__val = 0;						\
-		BUILD_BUG();						\
-	}								\
+	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
+									\
+	__val = *__addr;						\
+	slow;								\
 									\
 	return pfx##ioswab##bwlq(__val);				\
 }
@@ -379,27 +414,35 @@
 									\
 __BUILD_MEMORY_SINGLE(bus, bwlq, type, 1)
 
-#define __BUILD_IOPORT_PFX(bus, bwlq, type)				\
+#define BUILDIO_MEM(bwlq, type)						\
 									\
-__BUILD_IOPORT_SINGLE(bus, bwlq, type, ,)				\
-__BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO)
-
-#define BUILDIO(bwlq, type)						\
-									\
-__BUILD_MEMORY_PFX(, bwlq, type)					\
 __BUILD_MEMORY_PFX(__raw_, bwlq, type)					\
-__BUILD_MEMORY_PFX(bus_, bwlq, type)					\
-__BUILD_IOPORT_PFX(, bwlq, type)					\
-__BUILD_IOPORT_PFX(__raw_, bwlq, type)
+__BUILD_MEMORY_PFX(, bwlq, type)					\
+__BUILD_MEMORY_PFX(mem_, bwlq, type)					\
+
+BUILDIO_MEM(b, u8)
+BUILDIO_MEM(w, u16)
+BUILDIO_MEM(l, u32)
+BUILDIO_MEM(q, u64)
+
+#define __BUILD_IOPORT_PFX(bus, bwlq, type)				\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, ,)			\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO)
+
+#define BUILDIO_IOPORT(bwlq, type)					\
+	__BUILD_IOPORT_PFX(, bwlq, type)				\
+	__BUILD_IOPORT_PFX(mem_, bwlq, type)
+
+BUILDIO_IOPORT(b, u8)
+BUILDIO_IOPORT(w, u16)
+BUILDIO_IOPORT(l, u32)
+#ifdef CONFIG_64BIT
+BUILDIO_IOPORT(q, u64)
+#endif
 
 #define __BUILDIO(bwlq, type)						\
 									\
-__BUILD_MEMORY_SINGLE(__bus_, bwlq, type, 0)
-
-BUILDIO(b, u8)
-BUILDIO(w, u16)
-BUILDIO(l, u32)
-BUILDIO(q, u64)
+__BUILD_MEMORY_SINGLE(____raw_, bwlq, type, 0)
 
 __BUILDIO(q, u64)
 
@@ -422,7 +465,7 @@
 	volatile type *__addr = addr;					\
 									\
 	while (count--) {						\
-		__raw_write##bwlq(*__addr, mem);			\
+		mem_write##bwlq(*__addr, mem);				\
 		__addr++;						\
 	}								\
 }									\
@@ -433,20 +476,20 @@
 	volatile type *__addr = addr;					\
 									\
 	while (count--) {						\
-		*__addr = __raw_read##bwlq(mem);			\
+		*__addr = mem_read##bwlq(mem);				\
 		__addr++;						\
 	}								\
 }
 
 #define __BUILD_IOPORT_STRING(bwlq, type)				\
 									\
-static inline void outs##bwlq(unsigned long port, void *addr,		\
+static inline void outs##bwlq(unsigned long port, const void *addr,	\
 			      unsigned int count)			\
 {									\
-	volatile type *__addr = addr;					\
+	const volatile type *__addr = addr;				\
 									\
 	while (count--) {						\
-		__raw_out##bwlq(*__addr, port);				\
+		mem_out##bwlq(*__addr, port);				\
 		__addr++;						\
 	}								\
 }									\
@@ -457,7 +500,7 @@
 	volatile type *__addr = addr;					\
 									\
 	while (count--) {						\
-		*__addr = __raw_in##bwlq(port);				\
+		*__addr = mem_in##bwlq(port);				\
 		__addr++;						\
 	}								\
 }
@@ -470,15 +513,26 @@
 BUILDSTRING(b, u8)
 BUILDSTRING(w, u16)
 BUILDSTRING(l, u32)
+#ifdef CONFIG_64BIT
 BUILDSTRING(q, u64)
+#endif
 
 
 /* Depends on MIPS II instruction set */
 #define mmiowb() asm volatile ("sync" ::: "memory")
 
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
+static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+	memset((void __force *) addr, val, count);
+}
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
+{
+	memcpy(dst, (void __force *) src, count);
+}
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+	memcpy((void __force *) dst, src, count);
+}
 
 /*
  * Memory Mapped I/O
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 3f2470e..8a342cc 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -24,11 +24,9 @@
 
 struct pt_regs;
 
-#ifdef CONFIG_PREEMPT
-
 extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
 
-#else
+#ifdef CONFIG_PREEMPT
 
 /*
  * do_IRQ handles all normal device IRQ's (the special
diff --git a/include/asm-mips/jmr3927/jmr3927.h b/include/asm-mips/jmr3927/jmr3927.h
index 86df317..baf4129 100644
--- a/include/asm-mips/jmr3927/jmr3927.h
+++ b/include/asm-mips/jmr3927/jmr3927.h
@@ -202,20 +202,6 @@
 #endif /* !__ASSEMBLY__ */
 
 /*
- * UART defines for serial.h
- */
-
-/* use Pre-scaler T0 (1/2) */
-#define JMR3927_BASE_BAUD (JMR3927_IMCLK / 2 / 16)
-
-#define UART0_ADDR   0xfffef300
-#define UART1_ADDR   0xfffef400
-#define UART0_INT    JMR3927_IRQ_IRC_SIO0
-#define UART1_INT    JMR3927_IRQ_IRC_SIO1
-#define UART0_FLAGS  ASYNC_BOOT_AUTOCONF
-#define UART1_FLAGS  0
-
-/*
  * IRQ mappings
  */
 
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 148bae2..8327ec3 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -60,59 +60,36 @@
 	mdelay(ms);
 }
 
-void static inline au_writeb(u8 val, int reg)
+void static inline au_writeb(u8 val, unsigned long reg)
 {
 	*(volatile u8 *)(reg) = val;
 }
 
-void static inline au_writew(u16 val, int reg)
+void static inline au_writew(u16 val, unsigned long reg)
 {
 	*(volatile u16 *)(reg) = val;
 }
 
-void static inline au_writel(u32 val, int reg)
+void static inline au_writel(u32 val, unsigned long reg)
 {
 	*(volatile u32 *)(reg) = val;
 }
 
-static inline u8 au_readb(unsigned long port)
+static inline u8 au_readb(unsigned long reg)
 {
-	return (*(volatile u8 *)port);
+	return (*(volatile u8 *)reg);
 }
 
-static inline u16 au_readw(unsigned long port)
+static inline u16 au_readw(unsigned long reg)
 {
-	return (*(volatile u16 *)port);
+	return (*(volatile u16 *)reg);
 }
 
-static inline u32 au_readl(unsigned long port)
+static inline u32 au_readl(unsigned long reg)
 {
-	return (*(volatile u32 *)port);
+	return (*(volatile u32 *)reg);
 }
 
-/* These next three functions should be a generic part of the MIPS
- * kernel (with the 'au_' removed from the name) and selected for
- * processors that support the instructions.
- * Taken from PPC tree.  -- Dan
- */
-/* Return the bit position of the most significant 1 bit in a word */
-static __inline__ int __ilog2(unsigned int x)
-{
-	int lz;
-
-	asm volatile (
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		".set\tmips32\n\t"
-		"clz\t%0,%1\n\t"
-		".set\tmips0\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (lz)
-		: "r" (x));
-
-	return 31 - lz;
-}
 
 static __inline__ int au_ffz(unsigned int x)
 {
@@ -162,28 +139,293 @@
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 #endif
 
-/* SDRAM Controller */
+/*
+ * SDRAM Register Offsets
+ */
 #if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1100)
-#define MEM_SDMODE0                0xB4000000
-#define MEM_SDMODE1                0xB4000004
-#define MEM_SDMODE2                0xB4000008
+#define MEM_SDMODE0		(0x0000)
+#define MEM_SDMODE1		(0x0004)
+#define MEM_SDMODE2		(0x0008)
+#define MEM_SDADDR0		(0x000C)
+#define MEM_SDADDR1		(0x0010)
+#define MEM_SDADDR2		(0x0014)
+#define MEM_SDREFCFG	(0x0018)
+#define MEM_SDPRECMD	(0x001C)
+#define MEM_SDAUTOREF	(0x0020)
+#define MEM_SDWRMD0		(0x0024)
+#define MEM_SDWRMD1		(0x0028)
+#define MEM_SDWRMD2		(0x002C)
+#define MEM_SDSLEEP		(0x0030)
+#define MEM_SDSMCKE		(0x0034)
 
-#define MEM_SDADDR0                0xB400000C
-#define MEM_SDADDR1                0xB4000010
-#define MEM_SDADDR2                0xB4000014
+/*
+ * MEM_SDMODE register content definitions
+ */
+#define MEM_SDMODE_F		(1<<22)
+#define MEM_SDMODE_SR		(1<<21)
+#define MEM_SDMODE_BS		(1<<20)
+#define MEM_SDMODE_RS		(3<<18)
+#define MEM_SDMODE_CS		(7<<15)
+#define MEM_SDMODE_TRAS		(15<<11)
+#define MEM_SDMODE_TMRD		(3<<9)
+#define MEM_SDMODE_TWR		(3<<7)
+#define MEM_SDMODE_TRP		(3<<5)
+#define MEM_SDMODE_TRCD		(3<<3)
+#define MEM_SDMODE_TCL		(7<<0)
 
-#define MEM_SDREFCFG               0xB4000018
-#define MEM_SDPRECMD               0xB400001C
-#define MEM_SDAUTOREF              0xB4000020
+#define MEM_SDMODE_BS_2Bank	(0<<20)
+#define MEM_SDMODE_BS_4Bank	(1<<20)
+#define MEM_SDMODE_RS_11Row	(0<<18)
+#define MEM_SDMODE_RS_12Row	(1<<18)
+#define MEM_SDMODE_RS_13Row	(2<<18)
+#define MEM_SDMODE_RS_N(N)	((N)<<18)
+#define MEM_SDMODE_CS_7Col	(0<<15)
+#define MEM_SDMODE_CS_8Col	(1<<15)
+#define MEM_SDMODE_CS_9Col	(2<<15)
+#define MEM_SDMODE_CS_10Col	(3<<15)
+#define MEM_SDMODE_CS_11Col	(4<<15)
+#define MEM_SDMODE_CS_N(N)		((N)<<15)
+#define MEM_SDMODE_TRAS_N(N)	((N)<<11)
+#define MEM_SDMODE_TMRD_N(N)	((N)<<9)
+#define MEM_SDMODE_TWR_N(N)		((N)<<7)
+#define MEM_SDMODE_TRP_N(N)		((N)<<5)
+#define MEM_SDMODE_TRCD_N(N)	((N)<<3)
+#define MEM_SDMODE_TCL_N(N)		((N)<<0)
 
-#define MEM_SDWRMD0                0xB4000024
-#define MEM_SDWRMD1                0xB4000028
-#define MEM_SDWRMD2                0xB400002C
+/*
+ * MEM_SDADDR register contents definitions
+ */
+#define MEM_SDADDR_E			(1<<20)
+#define MEM_SDADDR_CSBA			(0x03FF<<10)
+#define MEM_SDADDR_CSMASK		(0x03FF<<0)
+#define MEM_SDADDR_CSBA_N(N)	((N)&(0x03FF<<22)>>12)
+#define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF<<22)>>22)
 
-#define MEM_SDSLEEP                0xB4000030
-#define MEM_SDSMCKE                0xB4000034
+/*
+ * MEM_SDREFCFG register content definitions
+ */
+#define MEM_SDREFCFG_TRC		(15<<28)
+#define MEM_SDREFCFG_TRPM		(3<<26)
+#define MEM_SDREFCFG_E			(1<<25)
+#define MEM_SDREFCFG_RE			(0x1ffffff<<0)
+#define MEM_SDREFCFG_TRC_N(N)	((N)<<MEM_SDREFCFG_TRC)
+#define MEM_SDREFCFG_TRPM_N(N)	((N)<<MEM_SDREFCFG_TRPM)
+#define MEM_SDREFCFG_REF_N(N)	(N)
 #endif
 
+/***********************************************************************/
+
+/*
+ * Au1550 SDRAM Register Offsets
+ */
+
+/***********************************************************************/
+
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+#define MEM_SDMODE0		(0x0800)
+#define MEM_SDMODE1		(0x0808)
+#define MEM_SDMODE2		(0x0810)
+#define MEM_SDADDR0		(0x0820)
+#define MEM_SDADDR1		(0x0828)
+#define MEM_SDADDR2		(0x0830)
+#define MEM_SDCONFIGA	(0x0840)
+#define MEM_SDCONFIGB	(0x0848)
+#define MEM_SDSTAT		(0x0850)
+#define MEM_SDERRADDR	(0x0858)
+#define MEM_SDSTRIDE0	(0x0860)
+#define MEM_SDSTRIDE1	(0x0868)
+#define MEM_SDSTRIDE2	(0x0870)
+#define MEM_SDWRMD0		(0x0880)
+#define MEM_SDWRMD1		(0x0888)
+#define MEM_SDWRMD2		(0x0890)
+#define MEM_SDPRECMD	(0x08C0)
+#define MEM_SDAUTOREF	(0x08C8)
+#define MEM_SDSREF		(0x08D0)
+#define MEM_SDSLEEP		MEM_SDSREF
+
+#endif
+
+/*
+ * Physical base addresses for integrated peripherals
+ */
+
+#ifdef CONFIG_SOC_AU1000
+#define	MEM_PHYS_ADDR		0x14000000
+#define	STATIC_MEM_PHYS_ADDR	0x14001000
+#define	DMA0_PHYS_ADDR		0x14002000
+#define	DMA1_PHYS_ADDR		0x14002100
+#define	DMA2_PHYS_ADDR		0x14002200
+#define	DMA3_PHYS_ADDR		0x14002300
+#define	DMA4_PHYS_ADDR		0x14002400
+#define	DMA5_PHYS_ADDR		0x14002500
+#define	DMA6_PHYS_ADDR		0x14002600
+#define	DMA7_PHYS_ADDR		0x14002700
+#define	IC0_PHYS_ADDR		0x10400000
+#define	IC1_PHYS_ADDR		0x11800000
+#define	AC97_PHYS_ADDR		0x10000000
+#define	USBH_PHYS_ADDR		0x10100000
+#define	USBD_PHYS_ADDR		0x10200000
+#define	IRDA_PHYS_ADDR		0x10300000
+#define	MAC0_PHYS_ADDR		0x10500000
+#define	MAC1_PHYS_ADDR		0x10510000
+#define	MACEN_PHYS_ADDR		0x10520000
+#define	MACDMA0_PHYS_ADDR	0x14004000
+#define	MACDMA1_PHYS_ADDR	0x14004200
+#define	I2S_PHYS_ADDR		0x11000000
+#define	UART0_PHYS_ADDR		0x11100000
+#define	UART1_PHYS_ADDR		0x11200000
+#define	UART2_PHYS_ADDR		0x11300000
+#define	UART3_PHYS_ADDR		0x11400000
+#define	SSI0_PHYS_ADDR		0x11600000
+#define	SSI1_PHYS_ADDR		0x11680000
+#define	SYS_PHYS_ADDR		0x11900000
+#define PCMCIA_IO_PHYS_ADDR   0xF00000000ULL
+#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL
+#define PCMCIA_MEM_PHYS_ADDR  0xF80000000ULL
+#endif
+
+/********************************************************************/
+
+#ifdef CONFIG_SOC_AU1500
+#define	MEM_PHYS_ADDR		0x14000000
+#define	STATIC_MEM_PHYS_ADDR	0x14001000
+#define	DMA0_PHYS_ADDR		0x14002000
+#define	DMA1_PHYS_ADDR		0x14002100
+#define	DMA2_PHYS_ADDR		0x14002200
+#define	DMA3_PHYS_ADDR		0x14002300
+#define	DMA4_PHYS_ADDR		0x14002400
+#define	DMA5_PHYS_ADDR		0x14002500
+#define	DMA6_PHYS_ADDR		0x14002600
+#define	DMA7_PHYS_ADDR		0x14002700
+#define	IC0_PHYS_ADDR		0x10400000
+#define	IC1_PHYS_ADDR		0x11800000
+#define	AC97_PHYS_ADDR		0x10000000
+#define	USBH_PHYS_ADDR		0x10100000
+#define	USBD_PHYS_ADDR		0x10200000
+#define PCI_PHYS_ADDR		0x14005000
+#define	MAC0_PHYS_ADDR		0x11500000
+#define	MAC1_PHYS_ADDR		0x11510000
+#define	MACEN_PHYS_ADDR		0x11520000
+#define	MACDMA0_PHYS_ADDR	0x14004000
+#define	MACDMA1_PHYS_ADDR	0x14004200
+#define	I2S_PHYS_ADDR		0x11000000
+#define	UART0_PHYS_ADDR		0x11100000
+#define	UART3_PHYS_ADDR		0x11400000
+#define GPIO2_PHYS_ADDR		0x11700000
+#define	SYS_PHYS_ADDR		0x11900000
+#define PCI_MEM_PHYS_ADDR     0x400000000ULL
+#define PCI_IO_PHYS_ADDR      0x500000000ULL
+#define PCI_CONFIG0_PHYS_ADDR 0x600000000ULL
+#define PCI_CONFIG1_PHYS_ADDR 0x680000000ULL
+#define PCMCIA_IO_PHYS_ADDR   0xF00000000ULL
+#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL
+#define PCMCIA_MEM_PHYS_ADDR  0xF80000000ULL
+#endif
+
+/********************************************************************/
+
+#ifdef CONFIG_SOC_AU1100
+#define	MEM_PHYS_ADDR		0x14000000
+#define	STATIC_MEM_PHYS_ADDR	0x14001000
+#define	DMA0_PHYS_ADDR		0x14002000
+#define	DMA1_PHYS_ADDR		0x14002100
+#define	DMA2_PHYS_ADDR		0x14002200
+#define	DMA3_PHYS_ADDR		0x14002300
+#define	DMA4_PHYS_ADDR		0x14002400
+#define	DMA5_PHYS_ADDR		0x14002500
+#define	DMA6_PHYS_ADDR		0x14002600
+#define	DMA7_PHYS_ADDR		0x14002700
+#define	IC0_PHYS_ADDR		0x10400000
+#define SD0_PHYS_ADDR		0x10600000
+#define SD1_PHYS_ADDR		0x10680000
+#define	IC1_PHYS_ADDR		0x11800000
+#define	AC97_PHYS_ADDR		0x10000000
+#define	USBH_PHYS_ADDR		0x10100000
+#define	USBD_PHYS_ADDR		0x10200000
+#define	IRDA_PHYS_ADDR		0x10300000
+#define	MAC0_PHYS_ADDR		0x10500000
+#define	MACEN_PHYS_ADDR		0x10520000
+#define	MACDMA0_PHYS_ADDR	0x14004000
+#define	MACDMA1_PHYS_ADDR	0x14004200
+#define	I2S_PHYS_ADDR		0x11000000
+#define	UART0_PHYS_ADDR		0x11100000
+#define	UART1_PHYS_ADDR		0x11200000
+#define	UART3_PHYS_ADDR		0x11400000
+#define	SSI0_PHYS_ADDR		0x11600000
+#define	SSI1_PHYS_ADDR		0x11680000
+#define GPIO2_PHYS_ADDR		0x11700000
+#define	SYS_PHYS_ADDR		0x11900000
+#define LCD_PHYS_ADDR		0x15000000
+#define PCMCIA_IO_PHYS_ADDR   0xF00000000ULL
+#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL
+#define PCMCIA_MEM_PHYS_ADDR  0xF80000000ULL
+#endif
+
+/***********************************************************************/
+
+#ifdef CONFIG_SOC_AU1550
+#define	MEM_PHYS_ADDR		0x14000000
+#define	STATIC_MEM_PHYS_ADDR	0x14001000
+#define	IC0_PHYS_ADDR		0x10400000
+#define	IC1_PHYS_ADDR		0x11800000
+#define	USBH_PHYS_ADDR		0x14020000
+#define	USBD_PHYS_ADDR		0x10200000
+#define PCI_PHYS_ADDR		0x14005000
+#define	MAC0_PHYS_ADDR		0x10500000
+#define	MAC1_PHYS_ADDR		0x10510000
+#define	MACEN_PHYS_ADDR		0x10520000
+#define	MACDMA0_PHYS_ADDR	0x14004000
+#define	MACDMA1_PHYS_ADDR	0x14004200
+#define	UART0_PHYS_ADDR		0x11100000
+#define	UART1_PHYS_ADDR		0x11200000
+#define	UART3_PHYS_ADDR		0x11400000
+#define GPIO2_PHYS_ADDR		0x11700000
+#define	SYS_PHYS_ADDR		0x11900000
+#define	DDMA_PHYS_ADDR		0x14002000
+#define PE_PHYS_ADDR		0x14008000
+#define PSC0_PHYS_ADDR	 	0x11A00000
+#define PSC1_PHYS_ADDR	 	0x11B00000
+#define PSC2_PHYS_ADDR	 	0x10A00000
+#define PSC3_PHYS_ADDR	 	0x10B00000
+#define PCI_MEM_PHYS_ADDR     0x400000000ULL
+#define PCI_IO_PHYS_ADDR      0x500000000ULL
+#define PCI_CONFIG0_PHYS_ADDR 0x600000000ULL
+#define PCI_CONFIG1_PHYS_ADDR 0x680000000ULL
+#define PCMCIA_IO_PHYS_ADDR   0xF00000000ULL
+#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL
+#define PCMCIA_MEM_PHYS_ADDR  0xF80000000ULL
+#endif
+
+/***********************************************************************/
+
+#ifdef CONFIG_SOC_AU1200
+#define	MEM_PHYS_ADDR		0x14000000
+#define	STATIC_MEM_PHYS_ADDR	0x14001000
+#define AES_PHYS_ADDR		0x10300000
+#define CIM_PHYS_ADDR		0x14004000
+#define	IC0_PHYS_ADDR		0x10400000
+#define	IC1_PHYS_ADDR		0x11800000
+#define USBM_PHYS_ADDR		0x14020000
+#define	USBH_PHYS_ADDR		0x14020100
+#define	UART0_PHYS_ADDR		0x11100000
+#define	UART1_PHYS_ADDR		0x11200000
+#define GPIO2_PHYS_ADDR		0x11700000
+#define	SYS_PHYS_ADDR		0x11900000
+#define	DDMA_PHYS_ADDR		0x14002000
+#define PSC0_PHYS_ADDR	 	0x11A00000
+#define PSC1_PHYS_ADDR	 	0x11B00000
+#define SD0_PHYS_ADDR		0x10600000
+#define SD1_PHYS_ADDR		0x10680000
+#define LCD_PHYS_ADDR		0x15000000
+#define SWCNT_PHYS_ADDR		0x1110010C
+#define MAEFE_PHYS_ADDR		0x14012000
+#define MAEBE_PHYS_ADDR		0x14010000
+#define PCMCIA_IO_PHYS_ADDR   0xF00000000ULL
+#define PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL
+#define PCMCIA_MEM_PHYS_ADDR  0xF80000000ULL
+#endif
+
+
 /* Static Bus Controller */
 #define MEM_STCFG0                 0xB4001000
 #define MEM_STTIME0                0xB4001004
@@ -369,7 +611,7 @@
 #define AU1000_MAC0_ENABLE       0xB0520000
 #define AU1000_MAC1_ENABLE       0xB0520004
 #define NUM_ETH_INTERFACES 2
-#endif // CONFIG_SOC_AU1000
+#endif /* CONFIG_SOC_AU1000 */
 
 /* Au1500 */
 #ifdef CONFIG_SOC_AU1500
@@ -429,6 +671,12 @@
 #define AU1500_GPIO_207           62
 #define AU1500_GPIO_208_215       63
 
+/* shortcuts */
+#define INTA AU1000_PCI_INTA
+#define INTB AU1000_PCI_INTB
+#define INTC AU1000_PCI_INTC
+#define INTD AU1000_PCI_INTD
+
 #define UART0_ADDR                0xB1100000
 #define UART3_ADDR                0xB1400000
 
@@ -440,7 +688,7 @@
 #define AU1500_MAC0_ENABLE       0xB1520000
 #define AU1500_MAC1_ENABLE       0xB1520004
 #define NUM_ETH_INTERFACES 2
-#endif // CONFIG_SOC_AU1500
+#endif /* CONFIG_SOC_AU1500 */
 
 /* Au1100 */
 #ifdef CONFIG_SOC_AU1100
@@ -485,6 +733,22 @@
 #define AU1000_GPIO_13            45
 #define AU1000_GPIO_14            46
 #define AU1000_GPIO_15            47
+#define AU1000_GPIO_16            48
+#define AU1000_GPIO_17            49
+#define AU1000_GPIO_18            50
+#define AU1000_GPIO_19            51
+#define AU1000_GPIO_20            52
+#define AU1000_GPIO_21            53
+#define AU1000_GPIO_22            54
+#define AU1000_GPIO_23            55
+#define AU1000_GPIO_24            56
+#define AU1000_GPIO_25            57
+#define AU1000_GPIO_26            58
+#define AU1000_GPIO_27            59
+#define AU1000_GPIO_28            60
+#define AU1000_GPIO_29            61
+#define AU1000_GPIO_30            62
+#define AU1000_GPIO_31            63
 
 #define UART0_ADDR                0xB1100000
 #define UART1_ADDR                0xB1200000
@@ -496,7 +760,7 @@
 #define AU1100_ETH0_BASE	  0xB0500000
 #define AU1100_MAC0_ENABLE       0xB0520000
 #define NUM_ETH_INTERFACES 1
-#endif // CONFIG_SOC_AU1100
+#endif /* CONFIG_SOC_AU1100 */
 
 #ifdef CONFIG_SOC_AU1550
 #define AU1550_UART0_INT          0
@@ -513,14 +777,14 @@
 #define AU1550_PSC1_INT           11
 #define AU1550_PSC2_INT           12
 #define AU1550_PSC3_INT           13
-#define AU1550_TOY_INT			  14
-#define AU1550_TOY_MATCH0_INT     15
-#define AU1550_TOY_MATCH1_INT     16
-#define AU1550_TOY_MATCH2_INT     17
-#define AU1550_RTC_INT            18
-#define AU1550_RTC_MATCH0_INT     19
-#define AU1550_RTC_MATCH1_INT     20
-#define AU1550_RTC_MATCH2_INT     21
+#define AU1000_TOY_INT			  14
+#define AU1000_TOY_MATCH0_INT     15
+#define AU1000_TOY_MATCH1_INT     16
+#define AU1000_TOY_MATCH2_INT     17
+#define AU1000_RTC_INT            18
+#define AU1000_RTC_MATCH0_INT     19
+#define AU1000_RTC_MATCH1_INT     20
+#define AU1000_RTC_MATCH2_INT     21
 #define AU1550_NAND_INT           23
 #define AU1550_USB_DEV_REQ_INT    24
 #define AU1550_USB_DEV_SUS_INT    25
@@ -563,6 +827,12 @@
 #define AU1500_GPIO_207           62
 #define AU1500_GPIO_208_218       63	// Logical or of GPIO208:218
 
+/* shortcuts */
+#define INTA AU1550_PCI_INTA
+#define INTB AU1550_PCI_INTB
+#define INTC AU1550_PCI_INTC
+#define INTD AU1550_PCI_INTD
+
 #define UART0_ADDR                0xB1100000
 #define UART1_ADDR                0xB1200000
 #define UART3_ADDR                0xB1400000
@@ -575,7 +845,7 @@
 #define AU1550_MAC0_ENABLE       0xB0520000
 #define AU1550_MAC1_ENABLE       0xB0520004
 #define NUM_ETH_INTERFACES 2
-#endif // CONFIG_SOC_AU1550
+#endif /* CONFIG_SOC_AU1550 */
 
 #ifdef CONFIG_SOC_AU1200
 #define AU1200_UART0_INT          0
@@ -592,14 +862,14 @@
 #define AU1200_PSC1_INT           11
 #define AU1200_AES_INT            12
 #define AU1200_CAMERA_INT         13
-#define AU1200_TOY_INT			  14
-#define AU1200_TOY_MATCH0_INT     15
-#define AU1200_TOY_MATCH1_INT     16
-#define AU1200_TOY_MATCH2_INT     17
-#define AU1200_RTC_INT            18
-#define AU1200_RTC_MATCH0_INT     19
-#define AU1200_RTC_MATCH1_INT     20
-#define AU1200_RTC_MATCH2_INT     21
+#define AU1000_TOY_INT			  14
+#define AU1000_TOY_MATCH0_INT     15
+#define AU1000_TOY_MATCH1_INT     16
+#define AU1000_TOY_MATCH2_INT     17
+#define AU1000_RTC_INT            18
+#define AU1000_RTC_MATCH0_INT     19
+#define AU1000_RTC_MATCH1_INT     20
+#define AU1000_RTC_MATCH2_INT     21
 #define AU1200_NAND_INT           23
 #define AU1200_GPIO_204           24
 #define AU1200_GPIO_205           25
@@ -607,6 +877,7 @@
 #define AU1200_GPIO_207           27
 #define AU1200_GPIO_208_215       28 // Logical OR of 208:215
 #define AU1200_USB_INT            29
+#define AU1000_USB_HOST_INT		  AU1200_USB_INT
 #define AU1200_LCD_INT            30
 #define AU1200_MAE_BOTH_INT       31
 #define AU1000_GPIO_0             32
@@ -645,20 +916,36 @@
 #define UART0_ADDR                0xB1100000
 #define UART1_ADDR                0xB1200000
 
-#define USB_OHCI_BASE             0x14020000 // phys addr for ioremap
-#define USB_HOST_CONFIG           0xB4027ffc
+#define USB_UOC_BASE              0x14020020
+#define USB_UOC_LEN               0x20
+#define USB_OHCI_BASE             0x14020100
+#define USB_OHCI_LEN              0x100
+#define USB_EHCI_BASE             0x14020200
+#define USB_EHCI_LEN              0x100
+#define USB_UDC_BASE              0x14022000
+#define USB_UDC_LEN               0x2000
+#define USB_MSR_BASE			  0xB4020000
+#define USB_MSR_MCFG              4
+#define USBMSRMCFG_OMEMEN         0
+#define USBMSRMCFG_OBMEN          1
+#define USBMSRMCFG_EMEMEN         2
+#define USBMSRMCFG_EBMEN          3
+#define USBMSRMCFG_DMEMEN         4
+#define USBMSRMCFG_DBMEN          5
+#define USBMSRMCFG_GMEMEN         6
+#define USBMSRMCFG_OHCCLKEN       16
+#define USBMSRMCFG_EHCCLKEN       17
+#define USBMSRMCFG_UDCCLKEN       18
+#define USBMSRMCFG_PHYPLLEN       19
+#define USBMSRMCFG_RDCOMB         30
+#define USBMSRMCFG_PFEN           31
 
-// these are here for prototyping on au1550 (do not exist on au1200)
-#define AU1200_ETH0_BASE      0xB0500000
-#define AU1200_ETH1_BASE      0xB0510000
-#define AU1200_MAC0_ENABLE       0xB0520000
-#define AU1200_MAC1_ENABLE       0xB0520004
-#define NUM_ETH_INTERFACES 2
-#endif // CONFIG_SOC_AU1200
+#endif /* CONFIG_SOC_AU1200 */
 
 #define AU1000_LAST_INTC0_INT     31
+#define AU1000_LAST_INTC1_INT     63
 #define AU1000_MAX_INTR           63
-
+#define INTX    		0xFF /* not valid */
 
 /* Programmable Counters 0 and 1 */
 #define SYS_BASE                   0xB1900000
@@ -730,6 +1017,8 @@
   #define I2S_CONTROL_D         (1<<1)
   #define I2S_CONTROL_CE        (1<<0)
 
+#ifndef CONFIG_SOC_AU1200
+
 /* USB Host Controller */
 #define USB_OHCI_LEN              0x00100000
 
@@ -775,6 +1064,8 @@
   #define USBDEV_ENABLE (1<<1)
   #define USBDEV_CE     (1<<0)
 
+#endif /* !CONFIG_SOC_AU1200 */
+
 /* Ethernet Controllers  */
 
 /* 4 byte offsets from AU1000_ETH_BASE */
@@ -1173,6 +1464,37 @@
   #define SYS_PF_PSC1_S1		(1 << 1)
   #define SYS_PF_MUST_BE_SET		((1 << 5) | (1 << 2))
 
+/* Au1200 Only */
+#ifdef CONFIG_SOC_AU1200
+#define SYS_PINFUNC_DMA		(1<<31)
+#define SYS_PINFUNC_S0A		(1<<30)
+#define SYS_PINFUNC_S1A		(1<<29)
+#define SYS_PINFUNC_LP0		(1<<28)
+#define SYS_PINFUNC_LP1		(1<<27)
+#define SYS_PINFUNC_LD16	(1<<26)
+#define SYS_PINFUNC_LD8		(1<<25)
+#define SYS_PINFUNC_LD1		(1<<24)
+#define SYS_PINFUNC_LD0		(1<<23)
+#define SYS_PINFUNC_P1A		(3<<21)
+#define SYS_PINFUNC_P1B		(1<<20)
+#define SYS_PINFUNC_FS3		(1<<19)
+#define SYS_PINFUNC_P0A		(3<<17)
+#define SYS_PINFUNC_CS		(1<<16)
+#define SYS_PINFUNC_CIM		(1<<15)
+#define SYS_PINFUNC_P1C		(1<<14)
+#define SYS_PINFUNC_U1T		(1<<12)
+#define SYS_PINFUNC_U1R		(1<<11)
+#define SYS_PINFUNC_EX1		(1<<10)
+#define SYS_PINFUNC_EX0		(1<<9)
+#define SYS_PINFUNC_U0R		(1<<8)
+#define SYS_PINFUNC_MC		(1<<7)
+#define SYS_PINFUNC_S0B		(1<<6)
+#define SYS_PINFUNC_S0C		(1<<5)
+#define SYS_PINFUNC_P0B		(1<<4)
+#define SYS_PINFUNC_U0T		(1<<3)
+#define SYS_PINFUNC_S1B		(1<<2)
+#endif
+
 #define SYS_TRIOUTRD              0xB1900100
 #define SYS_TRIOUTCLR             0xB1900100
 #define SYS_OUTPUTRD              0xB1900108
@@ -1239,6 +1561,12 @@
   #define SYS_CS_MI2_MASK           (0x7<<SYS_CS_MI2_BIT)
   #define SYS_CS_DI2                (1<<16)
   #define SYS_CS_CI2                (1<<15)
+#ifdef CONFIG_SOC_AU1100
+  #define SYS_CS_ML_BIT             7
+  #define SYS_CS_ML_MASK            (0x7<<SYS_CS_ML_BIT)
+  #define SYS_CS_DL                 (1<<6)
+  #define SYS_CS_CL                 (1<<5)
+#else
   #define SYS_CS_MUH_BIT            12
   #define SYS_CS_MUH_MASK           (0x7<<SYS_CS_MUH_BIT)
   #define SYS_CS_DUH                (1<<11)
@@ -1247,6 +1575,7 @@
   #define SYS_CS_MUD_MASK           (0x7<<SYS_CS_MUD_BIT)
   #define SYS_CS_DUD                (1<<6)
   #define SYS_CS_CUD                (1<<5)
+#endif
   #define SYS_CS_MIR_BIT            2
   #define SYS_CS_MIR_MASK           (0x7<<SYS_CS_MIR_BIT)
   #define SYS_CS_DIR                (1<<1)
@@ -1300,7 +1629,6 @@
 #define SD1_XMIT_FIFO	0xB0680000
 #define SD1_RECV_FIFO	0xB0680004
 
-
 #if defined (CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
 /* Au1500 PCI Controller */
 #define Au1500_CFG_BASE           0xB4005000 // virtual, kseg0 addr
@@ -1363,36 +1691,77 @@
 		      _ctl_; })
 
 
-#else /* Au1000 and Au1100 */
+#else /* Au1000 and Au1100 and Au1200 */
 
 /* don't allow any legacy ports probing */
-#define IOPORT_RESOURCE_START 0x10000000;
+#define IOPORT_RESOURCE_START 0x10000000
 #define IOPORT_RESOURCE_END   0xffffffff
 #define IOMEM_RESOURCE_START  0x10000000
 #define IOMEM_RESOURCE_END    0xffffffff
 
-#ifdef CONFIG_MIPS_PB1000
-#define PCI_IO_START      0x10000000
-#define PCI_IO_END        0x1000ffff
-#define PCI_MEM_START     0x18000000
-#define PCI_MEM_END       0x18ffffff
-#define PCI_FIRST_DEVFN   0
-#define PCI_LAST_DEVFN    1
-#else
-/* no PCI bus controller */
 #define PCI_IO_START    0
 #define PCI_IO_END      0
 #define PCI_MEM_START   0
 #define PCI_MEM_END     0
 #define PCI_FIRST_DEVFN 0
 #define PCI_LAST_DEVFN  0
-#endif
 
 #endif
 
+#ifndef _LANGUAGE_ASSEMBLY
+typedef volatile struct
+{
+	/* 0x0000 */ u32 toytrim;
+	/* 0x0004 */ u32 toywrite;
+	/* 0x0008 */ u32 toymatch0;
+	/* 0x000C */ u32 toymatch1;
+	/* 0x0010 */ u32 toymatch2;
+	/* 0x0014 */ u32 cntrctrl;
+	/* 0x0018 */ u32 scratch0;
+	/* 0x001C */ u32 scratch1;
+	/* 0x0020 */ u32 freqctrl0;
+	/* 0x0024 */ u32 freqctrl1;
+	/* 0x0028 */ u32 clksrc;
+	/* 0x002C */ u32 pinfunc;
+	/* 0x0030 */ u32 reserved0;
+	/* 0x0034 */ u32 wakemsk;
+	/* 0x0038 */ u32 endian;
+	/* 0x003C */ u32 powerctrl;
+	/* 0x0040 */ u32 toyread;
+	/* 0x0044 */ u32 rtctrim;
+	/* 0x0048 */ u32 rtcwrite;
+	/* 0x004C */ u32 rtcmatch0;
+	/* 0x0050 */ u32 rtcmatch1;
+	/* 0x0054 */ u32 rtcmatch2;
+	/* 0x0058 */ u32 rtcread;
+	/* 0x005C */ u32 wakesrc;
+	/* 0x0060 */ u32 cpupll;
+	/* 0x0064 */ u32 auxpll;
+	/* 0x0068 */ u32 reserved1;
+	/* 0x006C */ u32 reserved2;
+	/* 0x0070 */ u32 reserved3;
+	/* 0x0074 */ u32 reserved4;
+	/* 0x0078 */ u32 slppwr;
+	/* 0x007C */ u32 sleep;
+	/* 0x0080 */ u32 reserved5[32];
+	/* 0x0100 */ u32 trioutrd;
+#define trioutclr trioutrd
+	/* 0x0104 */ u32 reserved6;
+	/* 0x0108 */ u32 outputrd;
+#define outputset outputrd
+	/* 0x010C */ u32 outputclr;
+	/* 0x0110 */ u32 pinstaterd;
+#define pininputen pinstaterd
+
+} AU1X00_SYS;
+
+static AU1X00_SYS* const sys  = (AU1X00_SYS *)SYS_BASE;
+
+#endif
 /* Processor information base on prid.
  * Copied from PowerPC.
  */
+#ifndef _LANGUAGE_ASSEMBLY
 struct cpu_spec {
 	/* CPU is matched via (PRID & prid_mask) == prid_value */
 	unsigned int	prid_mask;
@@ -1406,3 +1775,6 @@
 extern struct cpu_spec		cpu_specs[];
 extern struct cpu_spec		*cur_cpu_spec[];
 #endif
+
+#endif
+
diff --git a/include/asm-mips/mach-au1x00/au1xxx.h b/include/asm-mips/mach-au1x00/au1xxx.h
new file mode 100644
index 0000000..b7b46dd
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/au1xxx.h
@@ -0,0 +1,44 @@
+/*
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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 _AU1XXX_H_
+#define _AU1XXX_H_
+
+#include <linux/config.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550)
+#include <asm/mach-db1x00/db1x00.h>
+
+#elif defined(CONFIG_MIPS_PB1550)
+#include <asm/mach-pb1x00/pb1550.h>
+
+#elif defined(CONFIG_MIPS_PB1200)
+#include <asm/mach-pb1x00/pb1200.h>
+
+#elif defined(CONFIG_MIPS_DB1200)
+#include <asm/mach-db1x00/db1200.h>
+
+#endif
+
+#endif /* _AU1XXX_H_ */
diff --git a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h b/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
index d5eb88c..b327bcd 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
@@ -45,7 +45,7 @@
 #define DDMA_GLOBAL_BASE	0xb4003000
 #define DDMA_CHANNEL_BASE	0xb4002000
 
-typedef struct dbdma_global {
+typedef volatile struct dbdma_global {
 	u32	ddma_config;
 	u32	ddma_intstat;
 	u32	ddma_throttle;
@@ -62,7 +62,7 @@
 
 /* The structure of a DMA Channel.
 */
-typedef struct au1xxx_dma_channel {
+typedef volatile struct au1xxx_dma_channel {
 	u32	ddma_cfg;	/* See below */
 	u32	ddma_desptr;	/* 32-byte aligned pointer to descriptor */
 	u32	ddma_statptr;	/* word aligned pointer to status word */
@@ -98,7 +98,7 @@
 /* "Standard" DDMA Descriptor.
  * Must be 32-byte aligned.
  */
-typedef struct au1xxx_ddma_desc {
+typedef volatile struct au1xxx_ddma_desc {
 	u32	dscr_cmd0;		/* See below */
 	u32	dscr_cmd1;		/* See below */
 	u32	dscr_source0;		/* source phys address */
@@ -107,6 +107,12 @@
 	u32	dscr_dest1;		/* See below */
 	u32	dscr_stat;		/* completion status */
 	u32	dscr_nxtptr;		/* Next descriptor pointer (mostly) */
+	/* First 32bytes are HW specific!!!
+	   Lets have some SW data following.. make sure its 32bytes
+	 */
+	u32	sw_status;
+	u32 	sw_context;
+	u32	sw_reserved[6];
 } au1x_ddma_desc_t;
 
 #define DSCR_CMD0_V		(1 << 31)	/* Descriptor valid */
@@ -125,8 +131,11 @@
 #define DSCR_CMD0_CV		(0x1 << 2)	/* Clear Valid when done */
 #define DSCR_CMD0_ST_MASK	(0x3 << 0)	/* Status instruction */
 
+#define SW_STATUS_INUSE		(1<<0)
+
 /* Command 0 device IDs.
 */
+#ifdef CONFIG_SOC_AU1550
 #define DSCR_CMD0_UART0_TX	0
 #define DSCR_CMD0_UART0_RX	1
 #define DSCR_CMD0_UART3_TX	2
@@ -155,9 +164,45 @@
 #define DSCR_CMD0_MAC0_TX	25
 #define DSCR_CMD0_MAC1_RX	26
 #define DSCR_CMD0_MAC1_TX	27
+#endif /* CONFIG_SOC_AU1550 */
+
+#ifdef CONFIG_SOC_AU1200
+#define DSCR_CMD0_UART0_TX	0
+#define DSCR_CMD0_UART0_RX	1
+#define DSCR_CMD0_UART1_TX	2
+#define DSCR_CMD0_UART1_RX	3
+#define DSCR_CMD0_DMA_REQ0	4
+#define DSCR_CMD0_DMA_REQ1	5
+#define DSCR_CMD0_MAE_BE	6
+#define DSCR_CMD0_MAE_FE	7
+#define DSCR_CMD0_SDMS_TX0	8
+#define DSCR_CMD0_SDMS_RX0	9
+#define DSCR_CMD0_SDMS_TX1	10
+#define DSCR_CMD0_SDMS_RX1	11
+#define DSCR_CMD0_AES_TX	13
+#define DSCR_CMD0_AES_RX	12
+#define DSCR_CMD0_PSC0_TX	14
+#define DSCR_CMD0_PSC0_RX	15
+#define DSCR_CMD0_PSC1_TX	16
+#define DSCR_CMD0_PSC1_RX	17
+#define DSCR_CMD0_CIM_RXA	18
+#define DSCR_CMD0_CIM_RXB	19
+#define DSCR_CMD0_CIM_RXC	20
+#define DSCR_CMD0_MAE_BOTH	21
+#define DSCR_CMD0_LCD		22
+#define DSCR_CMD0_NAND_FLASH	23
+#define DSCR_CMD0_PSC0_SYNC	24
+#define DSCR_CMD0_PSC1_SYNC	25
+#define DSCR_CMD0_CIM_SYNC	26
+#endif /* CONFIG_SOC_AU1200 */
+
 #define DSCR_CMD0_THROTTLE	30
 #define DSCR_CMD0_ALWAYS	31
 #define DSCR_NDEV_IDS		32
+/* THis macro is used to find/create custom device types */
+#define DSCR_DEV2CUSTOM_ID(x,d)	(((((x)&0xFFFF)<<8)|0x32000000)|((d)&0xFF))
+#define DSCR_CUSTOM2DEV_ID(x)	((x)&0xFF)
+
 
 #define DSCR_CMD0_SID(x)	(((x) & 0x1f) << 25)
 #define DSCR_CMD0_DID(x)	(((x) & 0x1f) << 20)
@@ -246,6 +291,43 @@
 */
 #define NUM_DBDMA_CHANS	16
 
+/*
+ * Ddma API definitions
+ * FIXME: may not fit to this header file
+ */
+typedef struct dbdma_device_table {
+	u32		dev_id;
+	u32		dev_flags;
+	u32		dev_tsize;
+	u32		dev_devwidth;
+	u32		dev_physaddr;		/* If FIFO */
+	u32		dev_intlevel;
+	u32		dev_intpolarity;
+} dbdev_tab_t;
+
+
+typedef struct dbdma_chan_config {
+	spinlock_t      lock;
+
+	u32			chan_flags;
+	u32			chan_index;
+	dbdev_tab_t		*chan_src;
+	dbdev_tab_t		*chan_dest;
+	au1x_dma_chan_t		*chan_ptr;
+	au1x_ddma_desc_t	*chan_desc_base;
+	au1x_ddma_desc_t	*get_ptr, *put_ptr, *cur_ptr;
+	void			*chan_callparam;
+	void (*chan_callback)(int, void *, struct pt_regs *);
+} chan_tab_t;
+
+#define DEV_FLAGS_INUSE		(1 << 0)
+#define DEV_FLAGS_ANYUSE	(1 << 1)
+#define DEV_FLAGS_OUT		(1 << 2)
+#define DEV_FLAGS_IN		(1 << 3)
+#define DEV_FLAGS_BURSTABLE (1 << 4)
+#define DEV_FLAGS_SYNC		(1 << 5)
+/* end Ddma API definitions */
+
 /* External functions for drivers to use.
 */
 /* Use this to allocate a dbdma channel.  The device ids are one of the
@@ -258,18 +340,6 @@
 
 #define DBDMA_MEM_CHAN	DSCR_CMD0_ALWAYS
 
-/* ACK!  These should be in a board specific description file.
-*/
-#ifdef CONFIG_MIPS_PB1550
-#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
-#endif
-#ifdef CONFIG_MIPS_DB1550
-#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
-#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
-#endif
-
-
 /* Set the device width of a in/out fifo.
 */
 u32 au1xxx_dbdma_set_devwidth(u32 chanid, int bits);
@@ -280,8 +350,8 @@
 
 /* Put buffers on source/destination descriptors.
 */
-u32 au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes);
-u32 au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes);
+u32 _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags);
+u32 _au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags);
 
 /* Get a buffer from the destination descriptor.
 */
@@ -295,5 +365,29 @@
 void au1xxx_dbdma_chan_free(u32 chanid);
 void au1xxx_dbdma_dump(u32 chanid);
 
+u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr );
+
+u32 au1xxx_ddma_add_device( dbdev_tab_t *dev );
+void * au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp);
+
+/*
+ 	Some compatibilty macros --
+		Needed to make changes to API without breaking existing drivers
+*/
+#define	au1xxx_dbdma_put_source(chanid,buf,nbytes)_au1xxx_dbdma_put_source(chanid, buf, nbytes, DDMA_FLAGS_IE)
+#define	au1xxx_dbdma_put_source_flags(chanid,buf,nbytes,flags) _au1xxx_dbdma_put_source(chanid, buf, nbytes, flags)
+#define	put_source_flags(chanid,buf,nbytes,flags) au1xxx_dbdma_put_source_flags(chanid,buf,nbytes,flags)
+
+
+#define au1xxx_dbdma_put_dest(chanid,buf,nbytes) _au1xxx_dbdma_put_dest(chanid, buf, nbytes, DDMA_FLAGS_IE)
+#define	au1xxx_dbdma_put_dest_flags(chanid,buf,nbytes,flags) _au1xxx_dbdma_put_dest(chanid, buf, nbytes, flags)
+#define	put_dest_flags(chanid,buf,nbytes,flags) au1xxx_dbdma_put_dest_flags(chanid,buf,nbytes,flags)
+
+/*
+ *	Flags for the put_source/put_dest functions.
+ */
+#define DDMA_FLAGS_IE	(1<<0)
+#define DDMA_FLAGS_NOIE (1<<1)
+
 #endif /* _LANGUAGE_ASSEMBLY */
 #endif /* _AU1000_DBDMA_H_ */
diff --git a/include/asm-mips/mach-au1x00/au1xxx_gpio.h b/include/asm-mips/mach-au1x00/au1xxx_gpio.h
new file mode 100644
index 0000000..27911e0
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/au1xxx_gpio.h
@@ -0,0 +1,20 @@
+#ifndef __AU1XXX_GPIO_H
+#define __AU1XXX_GPIO_H
+
+void au1xxx_gpio1_set_inputs(void);
+void au1xxx_gpio_tristate(int signal);
+void au1xxx_gpio_write(int signal, int value);
+int  au1xxx_gpio_read(int signal);
+
+typedef volatile struct
+{
+	u32 dir;
+	u32 reserved;
+	u32 output;
+	u32 pinstate;
+	u32 inten;
+	u32 enable;
+
+} AU1X00_GPIO2;
+
+#endif //__AU1XXX_GPIO_H
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
new file mode 100644
index 0000000..33d275c
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -0,0 +1,301 @@
+/*
+ * include/asm-mips/mach-au1x00/au1xxx_ide.h  version 01.30.00   Aug. 02 2005
+ *
+ * BRIEF MODULE DESCRIPTION
+ * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
+ *
+ * Copyright (c) 2003-2005 AMD, Personal Connectivity Solutions
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.
+ *
+ * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
+ *       Interface and Linux Device Driver" Application Note.
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+        #define DMA_WAIT_TIMEOUT        100
+        #define NUM_DESCRIPTORS         PRD_ENTRIES
+#else /* CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA */
+        #define NUM_DESCRIPTORS         2
+#endif
+
+#ifndef AU1XXX_ATA_RQSIZE
+        #define AU1XXX_ATA_RQSIZE       128
+#endif
+
+/* Disable Burstable-Support for DBDMA */
+#ifndef CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON
+        #define CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON  0
+#endif
+
+#ifdef CONFIG_PM
+/*
+* This will enable the device to be powered up when write() or read()
+* is called. If this is not defined, the driver will return -EBUSY.
+*/
+#define WAKE_ON_ACCESS 1
+
+typedef struct
+{
+        spinlock_t         lock;       /* Used to block on state transitions */
+        au1xxx_power_dev_t *dev;       /* Power Managers device structure */
+        unsigned	   stopped;    /* USed to signaling device is stopped */
+} pm_state;
+#endif
+
+
+typedef struct
+{
+        u32                     tx_dev_id, rx_dev_id, target_dev_id;
+        u32                     tx_chan, rx_chan;
+        void                    *tx_desc_head, *rx_desc_head;
+        ide_hwif_t              *hwif;
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+        ide_drive_t             *drive;
+        u8                      white_list, black_list;
+        struct dbdma_cmd        *dma_table_cpu;
+        dma_addr_t              dma_table_dma;
+        struct scatterlist      *sg_table;
+        int                     sg_nents;
+        int                     sg_dma_direction;
+#endif
+        struct device           *dev;
+	int			irq;
+	u32			regbase;
+#ifdef CONFIG_PM
+        pm_state                pm;
+#endif
+} _auide_hwif;
+
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+struct drive_list_entry {
+        const char * id_model;
+        const char * id_firmware;
+};
+
+/* HD white list */
+static const struct drive_list_entry dma_white_list [] = {
+/*
+ * Hitachi
+ */
+        { "HITACHI_DK14FA-20"    ,       "ALL"           },
+        { "HTS726060M9AT00"      ,       "ALL"           },
+/*
+ * Maxtor
+ */
+        { "Maxtor 6E040L0"      ,       "ALL"           },
+        { "Maxtor 6Y080P0"      ,       "ALL"           },
+        { "Maxtor 6Y160P0"      ,       "ALL"           },
+/*
+ * Seagate
+ */
+        { "ST3120026A"          ,       "ALL"           },
+        { "ST320014A"           ,       "ALL"           },
+        { "ST94011A"            ,       "ALL"           },
+        { "ST340016A"           ,       "ALL"           },
+/*
+ * Western Digital
+ */
+        { "WDC WD400UE-00HCT0"  ,       "ALL"           },
+        { "WDC WD400JB-00JJC0"  ,       "ALL"           },
+        { NULL                  ,       NULL            }
+};
+
+/* HD black list */
+static const struct drive_list_entry dma_black_list [] = {
+/*
+ * Western Digital
+ */
+        { "WDC WD100EB-00CGH0"  ,       "ALL"           },
+        { "WDC WD200BB-00AUA1"  ,       "ALL"           },
+        { "WDC AC24300L"        ,       "ALL"           },
+        { NULL                  ,       NULL            }
+};
+#endif
+
+/* function prototyping */
+u8 auide_inb(unsigned long port);
+u16 auide_inw(unsigned long port);
+u32 auide_inl(unsigned long port);
+void auide_insw(unsigned long port, void *addr, u32 count);
+void auide_insl(unsigned long port, void *addr, u32 count);
+void auide_outb(u8 addr, unsigned long port);
+void auide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port);
+void auide_outw(u16 addr, unsigned long port);
+void auide_outl(u32 addr, unsigned long port);
+void auide_outsw(unsigned long port, void *addr, u32 count);
+void auide_outsl(unsigned long port, void *addr, u32 count);
+static void auide_tune_drive(ide_drive_t *drive, byte pio);
+static int auide_tune_chipset (ide_drive_t *drive, u8 speed);
+static int auide_ddma_init( _auide_hwif *auide );
+static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif);
+int __init auide_probe(void);
+
+#ifdef CONFIG_PM
+        int au1200ide_pm_callback( au1xxx_power_dev_t *dev,
+                                   au1xxx_request_t request, void *data);
+        static int au1xxxide_pm_standby( au1xxx_power_dev_t *dev );
+        static int au1xxxide_pm_sleep( au1xxx_power_dev_t *dev );
+        static int au1xxxide_pm_resume( au1xxx_power_dev_t *dev );
+        static int au1xxxide_pm_getstatus( au1xxx_power_dev_t *dev );
+        static int au1xxxide_pm_access( au1xxx_power_dev_t *dev );
+        static int au1xxxide_pm_idle( au1xxx_power_dev_t *dev );
+        static int au1xxxide_pm_cleanup( au1xxx_power_dev_t *dev );
+#endif
+
+
+/*
+ * Multi-Word DMA + DbDMA functions
+ */
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+
+        static int in_drive_list(struct hd_driveid *id,
+                                 const struct drive_list_entry *drive_table);
+        static int auide_build_sglist(ide_drive_t *drive,  struct request *rq);
+        static int auide_build_dmatable(ide_drive_t *drive);
+        static int auide_dma_end(ide_drive_t *drive);
+        static void auide_dma_start(ide_drive_t *drive );
+        ide_startstop_t auide_dma_intr (ide_drive_t *drive);
+        static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command);
+        static int auide_dma_setup(ide_drive_t *drive);
+        static int auide_dma_check(ide_drive_t *drive);
+        static int auide_dma_test_irq(ide_drive_t *drive);
+        static int auide_dma_host_off(ide_drive_t *drive);
+        static int auide_dma_host_on(ide_drive_t *drive);
+        static int auide_dma_lostirq(ide_drive_t *drive);
+        static int auide_dma_on(ide_drive_t *drive);
+        static void auide_ddma_tx_callback(int irq, void *param,
+                                           struct pt_regs *regs);
+        static void auide_ddma_rx_callback(int irq, void *param,
+                                           struct pt_regs *regs);
+        static int auide_dma_off_quietly(ide_drive_t *drive);
+        static int auide_dma_timeout(ide_drive_t *drive);
+
+#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+
+/*******************************************************************************
+* PIO Mode timing calculation :                                                *
+*                                                                              *
+* Static Bus Spec   ATA Spec                                                   *
+*      Tcsoe      =   t1                                                       *
+*      Toecs      =   t9                                                       *
+*      Twcs       =   t9                                                       *
+*      Tcsh       =   t2i | t2                                                 *
+*      Tcsoff     =   t2i | t2                                                 *
+*      Twp        =   t2                                                       *
+*      Tcsw       =   t1                                                       *
+*      Tpm        =   0                                                        *
+*      Ta         =   t1+t2                                                    *
+*******************************************************************************/
+
+#define TCSOE_MASK            (0x07<<29)
+#define TOECS_MASK            (0x07<<26)
+#define TWCS_MASK             (0x07<<28)
+#define TCSH_MASK             (0x0F<<24)
+#define TCSOFF_MASK           (0x07<<20)
+#define TWP_MASK              (0x3F<<14)
+#define TCSW_MASK             (0x0F<<10)
+#define TPM_MASK              (0x0F<<6)
+#define TA_MASK               (0x3F<<0)
+#define TS_MASK               (1<<8)
+
+/* Timing parameters PIO mode 0 */
+#define SBC_IDE_PIO0_TCSOE    (0x04<<29)
+#define SBC_IDE_PIO0_TOECS    (0x01<<26)
+#define SBC_IDE_PIO0_TWCS     (0x02<<28)
+#define SBC_IDE_PIO0_TCSH     (0x08<<24)
+#define SBC_IDE_PIO0_TCSOFF   (0x07<<20)
+#define SBC_IDE_PIO0_TWP      (0x10<<14)
+#define SBC_IDE_PIO0_TCSW     (0x04<<10)
+#define SBC_IDE_PIO0_TPM      (0x0<<6)
+#define SBC_IDE_PIO0_TA       (0x15<<0)
+/* Timing parameters PIO mode 1 */
+#define SBC_IDE_PIO1_TCSOE    (0x03<<29)
+#define SBC_IDE_PIO1_TOECS    (0x01<<26)
+#define SBC_IDE_PIO1_TWCS     (0x01<<28)
+#define SBC_IDE_PIO1_TCSH     (0x06<<24)
+#define SBC_IDE_PIO1_TCSOFF   (0x06<<20)
+#define SBC_IDE_PIO1_TWP      (0x08<<14)
+#define SBC_IDE_PIO1_TCSW     (0x03<<10)
+#define SBC_IDE_PIO1_TPM      (0x00<<6)
+#define SBC_IDE_PIO1_TA       (0x0B<<0)
+/* Timing parameters PIO mode 2 */
+#define SBC_IDE_PIO2_TCSOE    (0x05<<29)
+#define SBC_IDE_PIO2_TOECS    (0x01<<26)
+#define SBC_IDE_PIO2_TWCS     (0x01<<28)
+#define SBC_IDE_PIO2_TCSH     (0x07<<24)
+#define SBC_IDE_PIO2_TCSOFF   (0x07<<20)
+#define SBC_IDE_PIO2_TWP      (0x1F<<14)
+#define SBC_IDE_PIO2_TCSW     (0x05<<10)
+#define SBC_IDE_PIO2_TPM      (0x00<<6)
+#define SBC_IDE_PIO2_TA       (0x22<<0)
+/* Timing parameters PIO mode 3 */
+#define SBC_IDE_PIO3_TCSOE    (0x05<<29)
+#define SBC_IDE_PIO3_TOECS    (0x01<<26)
+#define SBC_IDE_PIO3_TWCS     (0x01<<28)
+#define SBC_IDE_PIO3_TCSH     (0x0D<<24)
+#define SBC_IDE_PIO3_TCSOFF   (0x0D<<20)
+#define SBC_IDE_PIO3_TWP      (0x15<<14)
+#define SBC_IDE_PIO3_TCSW     (0x05<<10)
+#define SBC_IDE_PIO3_TPM      (0x00<<6)
+#define SBC_IDE_PIO3_TA       (0x1A<<0)
+/* Timing parameters PIO mode 4 */
+#define SBC_IDE_PIO4_TCSOE    (0x04<<29)
+#define SBC_IDE_PIO4_TOECS    (0x01<<26)
+#define SBC_IDE_PIO4_TWCS     (0x01<<28)
+#define SBC_IDE_PIO4_TCSH     (0x04<<24)
+#define SBC_IDE_PIO4_TCSOFF   (0x04<<20)
+#define SBC_IDE_PIO4_TWP      (0x0D<<14)
+#define SBC_IDE_PIO4_TCSW     (0x03<<10)
+#define SBC_IDE_PIO4_TPM      (0x00<<6)
+#define SBC_IDE_PIO4_TA       (0x12<<0)
+/* Timing parameters MDMA mode 0 */
+#define SBC_IDE_MDMA0_TCSOE   (0x03<<29)
+#define SBC_IDE_MDMA0_TOECS   (0x01<<26)
+#define SBC_IDE_MDMA0_TWCS    (0x01<<28)
+#define SBC_IDE_MDMA0_TCSH    (0x07<<24)
+#define SBC_IDE_MDMA0_TCSOFF  (0x07<<20)
+#define SBC_IDE_MDMA0_TWP     (0x0C<<14)
+#define SBC_IDE_MDMA0_TCSW    (0x03<<10)
+#define SBC_IDE_MDMA0_TPM     (0x00<<6)
+#define SBC_IDE_MDMA0_TA      (0x0F<<0)
+/* Timing parameters MDMA mode 1 */
+#define SBC_IDE_MDMA1_TCSOE   (0x05<<29)
+#define SBC_IDE_MDMA1_TOECS   (0x01<<26)
+#define SBC_IDE_MDMA1_TWCS    (0x01<<28)
+#define SBC_IDE_MDMA1_TCSH    (0x05<<24)
+#define SBC_IDE_MDMA1_TCSOFF  (0x05<<20)
+#define SBC_IDE_MDMA1_TWP     (0x0F<<14)
+#define SBC_IDE_MDMA1_TCSW    (0x05<<10)
+#define SBC_IDE_MDMA1_TPM     (0x00<<6)
+#define SBC_IDE_MDMA1_TA      (0x15<<0)
+/* Timing parameters MDMA mode 2 */
+#define SBC_IDE_MDMA2_TCSOE   (0x04<<29)
+#define SBC_IDE_MDMA2_TOECS   (0x01<<26)
+#define SBC_IDE_MDMA2_TWCS    (0x01<<28)
+#define SBC_IDE_MDMA2_TCSH    (0x04<<24)
+#define SBC_IDE_MDMA2_TCSOFF  (0x04<<20)
+#define SBC_IDE_MDMA2_TWP     (0x0D<<14)
+#define SBC_IDE_MDMA2_TCSW    (0x04<<10)
+#define SBC_IDE_MDMA2_TPM     (0x00<<6)
+#define SBC_IDE_MDMA2_TA      (0x12<<0)
+
diff --git a/include/asm-mips/mach-au1x00/au1xxx_psc.h b/include/asm-mips/mach-au1x00/au1xxx_psc.h
index 283519d..8e5fb3c 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_psc.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_psc.h
@@ -33,6 +33,8 @@
 #ifndef _AU1000_PSC_H_
 #define _AU1000_PSC_H_
 
+#include <linux/config.h>
+
 /* The PSC base addresses.  */
 #ifdef CONFIG_SOC_AU1550
 #define PSC0_BASE_ADDR		0xb1a00000
diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/include/asm-mips/mach-au1x00/ioremap.h
new file mode 100644
index 0000000..d3ec627
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/ioremap.h
@@ -0,0 +1,32 @@
+/*
+ *	include/asm-mips/mach-au1x00/ioremap.h
+ *
+ *	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 __ASM_MACH_AU1X00_IOREMAP_H
+#define __ASM_MACH_AU1X00_IOREMAP_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+extern phys_t __fixup_bigphys_addr(phys_t, phys_t);
+#else
+static inline phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+#endif
+
+/*
+ * Allow physical addresses to be fixed up to help 36-bit peripherals.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return __fixup_bigphys_addr(phys_addr, size);
+}
+
+#endif /* __ASM_MACH_AU1X00_IOREMAP_H */
diff --git a/include/asm-mips/mach-db1x00/db1200.h b/include/asm-mips/mach-db1x00/db1200.h
new file mode 100644
index 0000000..5d89437
--- /dev/null
+++ b/include/asm-mips/mach-db1x00/db1200.h
@@ -0,0 +1,224 @@
+/*
+ * AMD Alchemy DB1200 Referrence Board
+ * Board Registers defines.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * ########################################################################
+ *
+ *
+ */
+#ifndef __ASM_DB1200_H
+#define __ASM_DB1200_H
+
+#include <linux/types.h>
+
+// This is defined in au1000.h with bogus value
+#undef AU1X00_EXTERNAL_INT
+
+#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX
+#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX
+
+/* SPI and SMB are muxed on the Pb1200 board.
+   Refer to board documentation.
+ */
+#define SPI_PSC_BASE        PSC0_BASE_ADDR
+#define SMBUS_PSC_BASE      PSC0_BASE_ADDR
+/* AC97 and I2S are muxed on the Pb1200 board.
+   Refer to board documentation.
+ */
+#define AC97_PSC_BASE       PSC1_BASE_ADDR
+#define I2S_PSC_BASE		PSC1_BASE_ADDR
+
+#define BCSR_KSEG1_ADDR 0xB9800000
+
+typedef volatile struct
+{
+	/*00*/	u16 whoami;
+		u16 reserved0;
+	/*04*/	u16 status;
+		u16 reserved1;
+	/*08*/	u16 switches;
+		u16 reserved2;
+	/*0C*/	u16 resets;
+		u16 reserved3;
+
+	/*10*/	u16 pcmcia;
+		u16 reserved4;
+	/*14*/	u16 board;
+		u16 reserved5;
+	/*18*/	u16 disk_leds;
+		u16 reserved6;
+	/*1C*/	u16 system;
+		u16 reserved7;
+
+	/*20*/	u16 intclr;
+		u16 reserved8;
+	/*24*/	u16 intset;
+		u16 reserved9;
+	/*28*/	u16 intclr_mask;
+		u16 reserved10;
+	/*2C*/	u16 intset_mask;
+		u16 reserved11;
+
+	/*30*/	u16 sig_status;
+		u16 reserved12;
+	/*34*/	u16 int_status;
+		u16 reserved13;
+	/*38*/	u16 reserved14;
+		u16 reserved15;
+	/*3C*/	u16 reserved16;
+		u16 reserved17;
+
+} BCSR;
+
+static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+
+/*
+ * Register bit definitions for the BCSRs
+ */
+#define BCSR_WHOAMI_DCID	0x000F
+#define BCSR_WHOAMI_CPLD	0x00F0
+#define BCSR_WHOAMI_BOARD	0x0F00
+
+#define BCSR_STATUS_PCMCIA0VS	0x0003
+#define BCSR_STATUS_PCMCIA1VS	0x000C
+#define BCSR_STATUS_SWAPBOOT	0x0040
+#define BCSR_STATUS_FLASHBUSY	0x0100
+#define BCSR_STATUS_IDECBLID	0x0200
+#define BCSR_STATUS_SD0WP		0x0400
+#define BCSR_STATUS_U0RXD		0x1000
+#define BCSR_STATUS_U1RXD		0x2000
+
+#define BCSR_SWITCHES_OCTAL	0x00FF
+#define BCSR_SWITCHES_DIP_1	0x0080
+#define BCSR_SWITCHES_DIP_2	0x0040
+#define BCSR_SWITCHES_DIP_3	0x0020
+#define BCSR_SWITCHES_DIP_4	0x0010
+#define BCSR_SWITCHES_DIP_5	0x0008
+#define BCSR_SWITCHES_DIP_6	0x0004
+#define BCSR_SWITCHES_DIP_7	0x0002
+#define BCSR_SWITCHES_DIP_8	0x0001
+#define BCSR_SWITCHES_ROTARY	0x0F00
+
+#define BCSR_RESETS_ETH		0x0001
+#define BCSR_RESETS_CAMERA	0x0002
+#define BCSR_RESETS_DC		0x0004
+#define BCSR_RESETS_IDE		0x0008
+#define BCSR_RESETS_TV		0x0010
+/* not resets but in the same register */
+#define BCSR_RESETS_PWMR1mUX 0x0800
+#define BCSR_RESETS_PCS0MUX	0x1000
+#define BCSR_RESETS_PCS1MUX	0x2000
+#define BCSR_RESETS_SPISEL	0x4000
+
+#define BCSR_PCMCIA_PC0VPP	0x0003
+#define BCSR_PCMCIA_PC0VCC	0x000C
+#define BCSR_PCMCIA_PC0DRVEN	0x0010
+#define BCSR_PCMCIA_PC0RST	0x0080
+#define BCSR_PCMCIA_PC1VPP	0x0300
+#define BCSR_PCMCIA_PC1VCC	0x0C00
+#define BCSR_PCMCIA_PC1DRVEN	0x1000
+#define BCSR_PCMCIA_PC1RST	0x8000
+
+#define BCSR_BOARD_LCDVEE	0x0001
+#define BCSR_BOARD_LCDVDD	0x0002
+#define BCSR_BOARD_LCDBL	0x0004
+#define BCSR_BOARD_CAMSNAP	0x0010
+#define BCSR_BOARD_CAMPWR	0x0020
+#define BCSR_BOARD_SD0PWR	0x0040
+
+#define BCSR_LEDS_DECIMALS	0x0003
+#define BCSR_LEDS_LED0		0x0100
+#define BCSR_LEDS_LED1		0x0200
+#define BCSR_LEDS_LED2		0x0400
+#define BCSR_LEDS_LED3		0x0800
+
+#define BCSR_SYSTEM_POWEROFF	0x4000
+#define BCSR_SYSTEM_RESET	0x8000
+
+/* Bit positions for the different interrupt sources */
+#define BCSR_INT_IDE		0x0001
+#define BCSR_INT_ETH		0x0002
+#define BCSR_INT_PC0		0x0004
+#define BCSR_INT_PC0STSCHG	0x0008
+#define BCSR_INT_PC1		0x0010
+#define BCSR_INT_PC1STSCHG	0x0020
+#define BCSR_INT_DC			0x0040
+#define BCSR_INT_FLASHBUSY	0x0080
+#define BCSR_INT_PC0INSERT	0x0100
+#define BCSR_INT_PC0EJECT	0x0200
+#define BCSR_INT_PC1INSERT	0x0400
+#define BCSR_INT_PC1EJECT	0x0800
+#define BCSR_INT_SD0INSERT	0x1000
+#define BCSR_INT_SD0EJECT	0x2000
+
+#define AU1XXX_SMC91111_PHYS_ADDR	(0x19000300)
+#define AU1XXX_SMC91111_IRQ			DB1200_ETH_INT
+
+#define AU1XXX_ATA_PHYS_ADDR		(0x18800000)
+#define AU1XXX_ATA_PHYS_LEN			(0x100)
+#define AU1XXX_ATA_REG_OFFSET	(5)
+#define AU1XXX_ATA_INT			DB1200_IDE_INT
+#define AU1XXX_ATA_DDMA_REQ		DSCR_CMD0_DMA_REQ1;
+#define AU1XXX_ATA_RQSIZE		128
+
+#define NAND_PHYS_ADDR   0x20000000
+
+/*
+ *	External Interrupts for Pb1200 as of 8/6/2004.
+ *   Bit positions in the CPLD registers can be calculated by taking
+ *   the interrupt define and subtracting the DB1200_INT_BEGIN value.
+ *    *example: IDE bis pos is  = 64 - 64
+                ETH bit pos is  = 65 - 64
+ */
+#define DB1200_INT_BEGIN		(AU1000_LAST_INTC1_INT + 1)
+#define DB1200_IDE_INT			(DB1200_INT_BEGIN + 0)
+#define DB1200_ETH_INT			(DB1200_INT_BEGIN + 1)
+#define DB1200_PC0_INT			(DB1200_INT_BEGIN + 2)
+#define DB1200_PC0_STSCHG_INT	(DB1200_INT_BEGIN + 3)
+#define DB1200_PC1_INT			(DB1200_INT_BEGIN + 4)
+#define DB1200_PC1_STSCHG_INT	(DB1200_INT_BEGIN + 5)
+#define DB1200_DC_INT			(DB1200_INT_BEGIN + 6)
+#define DB1200_FLASHBUSY_INT	(DB1200_INT_BEGIN + 7)
+#define DB1200_PC0_INSERT_INT	(DB1200_INT_BEGIN + 8)
+#define DB1200_PC0_EJECT_INT	(DB1200_INT_BEGIN + 9)
+#define DB1200_PC1_INSERT_INT	(DB1200_INT_BEGIN + 10)
+#define DB1200_PC1_EJECT_INT	(DB1200_INT_BEGIN + 11)
+#define DB1200_SD0_INSERT_INT	(DB1200_INT_BEGIN + 12)
+#define DB1200_SD0_EJECT_INT	(DB1200_INT_BEGIN + 13)
+
+#define DB1200_INT_END			(DB1200_INT_BEGIN + 15)
+
+/* For drivers/pcmcia/au1000_db1x00.c */
+
+/* PCMCIA Db1x00 specific defines */
+
+#define PCMCIA_MAX_SOCK 1
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+/* VPP/VCC */
+#define SET_VCC_VPP(VCC, VPP, SLOT)\
+	((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+
+#define BOARD_PC0_INT DB1200_PC0_INT
+#define BOARD_PC1_INT DB1200_PC1_INT
+#define BOARD_CARD_INSERTED(SOCKET) bcsr->sig_status & (1<<(8+(2*SOCKET)))
+
+#endif /* __ASM_DB1200_H */
+
diff --git a/include/asm-mips/mach-dec/mc146818rtc.h b/include/asm-mips/mach-dec/mc146818rtc.h
index a326f45..6d37a56 100644
--- a/include/asm-mips/mach-dec/mc146818rtc.h
+++ b/include/asm-mips/mach-dec/mc146818rtc.h
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1998, 2001 by Ralf Baechle
  * Copyright (C) 1998 by Harald Koerfgen
- * Copyright (C) 2002  Maciej W. Rozycki
+ * Copyright (C) 2002, 2005  Maciej W. Rozycki
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -14,23 +14,18 @@
 #define __ASM_MIPS_DEC_RTC_DEC_H
 
 #include <linux/types.h>
-
 #include <asm/addrspace.h>
+#include <asm/dec/system.h>
 
 extern volatile u8 *dec_rtc_base;
-extern unsigned long dec_kn_slot_size;
 
-#define RTC_PORT(x)	CPHYSADDR(dec_rtc_base)
+#define RTC_PORT(x)	CPHYSADDR((long)dec_rtc_base)
 #define RTC_IO_EXTENT	dec_kn_slot_size
 #define RTC_IOMAPPED	0
 #undef RTC_IRQ
 
 #define RTC_DEC_YEAR	0x3f	/* Where we store the real year on DECs.  */
 
-#include <linux/mc146818rtc.h>
-#include <linux/module.h>
-#include <linux/types.h>
-
 static inline unsigned char CMOS_READ(unsigned long addr)
 {
 	return dec_rtc_base[addr * 4];
diff --git a/include/asm-mips/mach-generic/cpu-feature-overrides.h b/include/asm-mips/mach-generic/cpu-feature-overrides.h
index 0aecfd0..7c185bb 100644
--- a/include/asm-mips/mach-generic/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-generic/cpu-feature-overrides.h
@@ -8,6 +8,6 @@
 #ifndef __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H
 
-/* Intensionally empty file ...  */
+/* Intentionally empty file ...  */
 
 #endif /* __ASM_MACH_GENERIC_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index cb2edd0..9610069 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -18,6 +18,7 @@
 #include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/stddef.h>
+#include <asm/processor.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
@@ -104,15 +105,71 @@
 
 /* MIPS port and memory-mapped I/O string operations.  */
 
-#define __ide_insw	insw
-#define __ide_insl	insl
-#define __ide_outsw	outsw
-#define __ide_outsl	outsl
+static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
+{
+	if (cpu_has_dc_aliases) {
+		unsigned long end = addr + size;
+		for (; addr < end; addr += PAGE_SIZE)
+			flush_dcache_page(virt_to_page(addr));
+	}
+}
 
-#define __ide_mm_insw	readsw
-#define __ide_mm_insl	readsl
-#define __ide_mm_outsw	writesw
-#define __ide_mm_outsl	writesl
+static inline void __ide_insw(unsigned long port, void *addr,
+	unsigned int count)
+{
+	insw(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+}
+
+static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
+{
+	insl(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+}
+
+static inline void __ide_outsw(unsigned long port, const void *addr,
+	unsigned long count)
+{
+	outsw(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+}
+
+static inline void __ide_outsl(unsigned long port, const void *addr,
+	unsigned long count)
+{
+	outsl(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+}
+
+static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
+{
+	readsw(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+}
+
+static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
+{
+	readsl(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+}
+
+static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
+{
+	writesw(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+}
+
+static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
+{
+	writesl(port, addr, count);
+	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+}
+
+/* ide_insw calls insw, not __ide_insw.  Why? */
+#undef insw
+#undef insl
+#define insw(port, addr, count) __ide_insw(port, addr, count)
+#define insl(port, addr, count) __ide_insl(port, addr, count)
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-mips/mach-generic/ioremap.h b/include/asm-mips/mach-generic/ioremap.h
new file mode 100644
index 0000000..9b64ff6
--- /dev/null
+++ b/include/asm-mips/mach-generic/ioremap.h
@@ -0,0 +1,23 @@
+/*
+ *	include/asm-mips/mach-generic/ioremap.h
+ *
+ *	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 __ASM_MACH_GENERIC_IOREMAP_H
+#define __ASM_MACH_GENERIC_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+#endif /* __ASM_MACH_GENERIC_IOREMAP_H */
diff --git a/include/asm-mips/mach-generic/kernel-entry-init.h b/include/asm-mips/mach-generic/kernel-entry-init.h
new file mode 100644
index 0000000..7e66505
--- /dev/null
+++ b/include/asm-mips/mach-generic/kernel-entry-init.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_MACH_GENERIC_KERNEL_ENTRY_H
+#define __ASM_MACH_GENERIC_KERNEL_ENTRY_H
+
+/* Intentionally empty macro, used in head.S. Override in
+ * arch/mips/mach-xxx/kernel-entry-init.h when necessary.
+ */
+.macro	kernel_entry_setup
+.endm
+
+/*
+ * Do SMP slave processor setup necessary before we can savely execute C code.
+ */
+	.macro	smp_slave_setup
+	.endm
+
+
+#endif /* __ASM_MACH_GENERIC_KERNEL_ENTRY_H */
diff --git a/include/asm-mips/mach-generic/kmalloc.h b/include/asm-mips/mach-generic/kmalloc.h
new file mode 100644
index 0000000..373d66d
--- /dev/null
+++ b/include/asm-mips/mach-generic/kmalloc.h
@@ -0,0 +1,13 @@
+#ifndef __ASM_MACH_GENERIC_KMALLOC_H
+#define __ASM_MACH_GENERIC_KMALLOC_H
+
+#include <linux/config.h>
+
+#ifndef CONFIG_DMA_COHERENT
+/*
+ * Total overkill for most systems but need as a safe default.
+ */
+#define ARCH_KMALLOC_MINALIGN	128
+#endif
+
+#endif /* __ASM_MACH_GENERIC_KMALLOC_H */
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index 5a2c1ef..b849d8d 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -55,13 +55,13 @@
 #endif
 
 #ifdef CONFIG_DMA_NONCOHERENT
-#define CAC_BASE		0x9800000000000000
+#define CAC_BASE		0x9800000000000000UL
 #else
-#define CAC_BASE		0xa800000000000000
+#define CAC_BASE		0xa800000000000000UL
 #endif
-#define IO_BASE			0x9000000000000000
-#define UNCAC_BASE		0x9000000000000000
-#define MAP_BASE		0xc000000000000000
+#define IO_BASE			0x9000000000000000UL
+#define UNCAC_BASE		0x9000000000000000UL
+#define MAP_BASE		0xc000000000000000UL
 
 #define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
diff --git a/include/asm-mips/mach-ip22/cpu-feature-overrides.h b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
index 3c8896d..ab97146 100644
--- a/include/asm-mips/mach-ip22/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
@@ -11,6 +11,12 @@
 /*
  * IP22 with a variety of processors so we can't use defaults for everything.
  */
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_4kcache		1
+#define cpu_has_fpu		1
+#define cpu_has_32fpr		1
+#define cpu_has_counter		1
 #define cpu_has_mips16		0
 #define cpu_has_divec		0
 #define cpu_has_cache_cdex_p	1
@@ -23,6 +29,8 @@
 #define cpu_has_dc_aliases	(PAGE_SIZE < 0x4000)
 #define cpu_has_ic_fills_f_dc	0
 
+#define cpu_has_dsp		0
+
 #define cpu_has_nofpuex		0
 #define cpu_has_64bits		1
 
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index e96166f..8385f71 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -44,7 +44,7 @@
 #define CAC_BASE		0xffffffff80000000
 #define IO_BASE			0xffffffffa0000000
 #define UNCAC_BASE		0xffffffffa0000000
-#define MAP_BASE		0xffffffffc0000000
+#define MAP_BASE		0xc000000000000000
 
 #define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
diff --git a/include/asm-mips/mach-ip27/cpu-feature-overrides.h b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
index fe96d73..4c8a900 100644
--- a/include/asm-mips/mach-ip27/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
 #define cpu_has_vtag_icache	0
 #define cpu_has_dc_aliases	0
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 #define cpu_icache_snoops_remote_store	1
 
 #define cpu_has_nofpuex		0
diff --git a/include/asm-mips/mach-ip27/kernel-entry-init.h b/include/asm-mips/mach-ip27/kernel-entry-init.h
new file mode 100644
index 0000000..c1a1031
--- /dev/null
+++ b/include/asm-mips/mach-ip27/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * 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) 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2005 Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_IP27_KERNEL_ENTRY_H
+#define __ASM_MACH_IP27_KERNEL_ENTRY_H
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn0/hubni.h>
+#include <asm/sn/klkernvars.h>
+
+/*
+ * Returns the local nasid into res.
+ */
+	.macro GET_NASID_ASM res
+	dli	\res, LOCAL_HUB_ADDR(NI_STATUS_REV_ID)
+	ld	\res, (\res)
+	and	\res, NSRI_NODEID_MASK
+	dsrl	\res, NSRI_NODEID_SHFT
+	.endm
+
+/*
+ * Intentionally empty macro, used in head.S. Override in
+ * arch/mips/mach-xxx/kernel-entry-init.h when necessary.
+ */
+	.macro	kernel_entry_setup
+	GET_NASID_ASM	t1
+	move		t2, t1			# text and data are here
+	MAPPED_KERNEL_SETUP_TLB
+	.endm
+
+/*
+ * Do SMP slave processor setup necessary before we can savely execute C code.
+ */
+	.macro	smp_slave_setup
+	GET_NASID_ASM	t1
+	dli	t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \
+		    KLDIR_OFF_POINTER + CAC_BASE
+	dsll	t1, NASID_SHFT
+	or	t0, t0, t1
+	ld	t0, 0(t0)			# t0 points to kern_vars struct
+	lh	t1, KV_RO_NASID_OFFSET(t0)
+	lh	t2, KV_RW_NASID_OFFSET(t0)
+	MAPPED_KERNEL_SETUP_TLB
+	ARC64_TWIDDLE_PC
+	.endm
+
+#endif /* __ASM_MACH_IP27_KERNEL_ENTRY_H */
diff --git a/include/asm-mips/mach-ip27/kmalloc.h b/include/asm-mips/mach-ip27/kmalloc.h
new file mode 100644
index 0000000..426bd04
--- /dev/null
+++ b/include/asm-mips/mach-ip27/kmalloc.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_MACH_IP27_KMALLOC_H
+#define __ASM_MACH_IP27_KMALLOC_H
+
+/*
+ * All happy, no need to define ARCH_KMALLOC_MINALIGN
+ */
+
+#endif /* __ASM_MACH_IP27_KMALLOC_H */
diff --git a/include/asm-mips/mach-ip27/mmzone.h b/include/asm-mips/mach-ip27/mmzone.h
index d3f5663..986a3b9 100644
--- a/include/asm-mips/mach-ip27/mmzone.h
+++ b/include/asm-mips/mach-ip27/mmzone.h
@@ -10,7 +10,6 @@
 #define LEVELS_PER_SLICE        128
 
 struct slice_data {
-	unsigned long irq_alloc_mask[2];
 	unsigned long irq_enable_mask[2];
 	int level_to_irq[LEVELS_PER_SLICE];
 };
@@ -20,6 +19,7 @@
 	DECLARE_BITMAP(h_bigwin_used, HUB_NUM_BIG_WINDOW);
 	cpumask_t	h_cpus;
 	unsigned long slice_map;
+	unsigned long irq_alloc_mask[2];
 	struct slice_data slice[2];
 };
 
diff --git a/include/asm-mips/mach-ip27/spaces.h b/include/asm-mips/mach-ip27/spaces.h
index e3b3fe3..45e6178 100644
--- a/include/asm-mips/mach-ip27/spaces.h
+++ b/include/asm-mips/mach-ip27/spaces.h
@@ -20,6 +20,7 @@
 #define IO_BASE			0x9200000000000000
 #define MSPEC_BASE		0x9400000000000000
 #define UNCAC_BASE		0x9600000000000000
+#define MAP_BASE		0xc000000000000000
 
 #define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
diff --git a/include/asm-mips/mach-ip27/topology.h b/include/asm-mips/mach-ip27/topology.h
index a70a812..82141c7 100644
--- a/include/asm-mips/mach-ip27/topology.h
+++ b/include/asm-mips/mach-ip27/topology.h
@@ -9,6 +9,9 @@
 #define parent_node(node)	(node)
 #define node_to_cpumask(node)	(hub_data(node)->h_cpus)
 #define node_to_first_cpu(node)	(first_cpu(node_to_cpumask(node)))
+struct pci_bus;
+extern int pcibus_to_node(struct pci_bus *);
+
 #define pcibus_to_cpumask(bus)	(cpu_online_map)
 
 extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
index 0471397..ab37fc1 100644
--- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
@@ -37,5 +37,6 @@
 #define cpu_has_ejtag		0
 #define cpu_has_vtag_icache	0
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 
 #endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ip32/kmalloc.h b/include/asm-mips/mach-ip32/kmalloc.h
new file mode 100644
index 0000000..9d2d4d9
--- /dev/null
+++ b/include/asm-mips/mach-ip32/kmalloc.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_MACH_IP32_KMALLOC_H
+#define __ASM_MACH_IP32_KMALLOC_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_CPU_R5000) || defined (CONFIG_CPU_RM7000)
+#define ARCH_KMALLOC_MINALIGN	32
+#else
+#define ARCH_KMALLOC_MINALIGN	128
+#endif
+
+#endif /* __ASM_MACH_IP32_KMALLOC_H */
diff --git a/include/asm-mips/mach-ip32/spaces.h b/include/asm-mips/mach-ip32/spaces.h
index c7839f8..44abe5c 100644
--- a/include/asm-mips/mach-ip32/spaces.h
+++ b/include/asm-mips/mach-ip32/spaces.h
@@ -19,10 +19,10 @@
 #define HIGHMEM_START		(1UL << 59UL)
 #endif
 
-#define CAC_BASE		0x9800000000000000
-#define IO_BASE			0x9000000000000000
-#define UNCAC_BASE		0x9000000000000000
-#define MAP_BASE		0xc000000000000000
+#define CAC_BASE		0x9800000000000000UL
+#define IO_BASE			0x9000000000000000UL
+#define UNCAC_BASE		0x9000000000000000UL
+#define MAP_BASE		0xc000000000000000UL
 
 #define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h
index ca57e7d..a0fde40 100644
--- a/include/asm-mips/mach-ja/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ja/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
 #define cpu_has_vtag_icache	0
 #define cpu_has_dc_aliases	0
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 #define cpu_icache_snoops_remote_store	0
 
 #define cpu_has_nofpuex		0
@@ -36,10 +37,4 @@
 #define cpu_icache_line_size()	32
 #define cpu_scache_line_size()	32
 
-/*
- * On the RM9000 we need to ensure that I-cache lines being fetches only
- * contain valid instructions are funny things will happen.
- */
-#define PLAT_TRAMPOLINE_STUFF_LINE	32UL
-
 #endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-mips/cpu-feature-overrides.h b/include/asm-mips/mach-mips/cpu-feature-overrides.h
index 6f51be5..9f92aed 100644
--- a/include/asm-mips/mach-mips/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-mips/cpu-feature-overrides.h
@@ -17,7 +17,7 @@
 #ifdef CONFIG_CPU_MIPS32
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4ktlb		1
+#define cpu_has_4kcache		1
 /* #define cpu_has_fpu		? */
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
@@ -37,12 +37,13 @@
 /* #define cpu_has_64bits	? */
 /* #define cpu_has_64bit_zero_reg ? */
 /* #define cpu_has_subset_pcaches ? */
+#define cpu_icache_snoops_remote_store 1
 #endif
 
 #ifdef CONFIG_CPU_MIPS64
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4ktlb		1
+#define cpu_has_4kcache		1
 /* #define cpu_has_fpu		? */
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
@@ -62,6 +63,7 @@
 /* #define cpu_has_64bits	? */
 /* #define cpu_has_64bit_zero_reg ? */
 /* #define cpu_has_subset_pcaches ? */
+#define cpu_icache_snoops_remote_store 1
 #endif
 
 #endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-mips/irq.h b/include/asm-mips/mach-mips/irq.h
new file mode 100644
index 0000000..f857969
--- /dev/null
+++ b/include/asm-mips/mach-mips/irq.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_MACH_MIPS_IRQ_H
+#define __ASM_MACH_MIPS_IRQ_H
+
+#include <linux/config.h>
+
+#define NR_IRQS	256
+
+#ifdef CONFIG_SMP
+
+#define ARCH_HAS_IRQ_PER_CPU
+
+#endif
+
+#endif /* __ASM_MACH_MIPS_IRQ_H */
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
index 7473512..825c5f6 100644
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
@@ -28,6 +28,7 @@
 #define cpu_has_vtag_icache	0
 #define cpu_has_dc_aliases	0
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 #define cpu_icache_snoops_remote_store	0
 
 #define cpu_has_nofpuex 	0
@@ -39,10 +40,4 @@
 #define cpu_icache_line_size()	32
 #define cpu_scache_line_size()	32
 
-/*
- * On the RM9000 we need to ensure that I-cache lines being fetches only
- * contain valid instructions are funny things will happen.
- */
-#define PLAT_TRAMPOLINE_STUFF_LINE	32UL
-
 #endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-pb1x00/pb1200.h b/include/asm-mips/mach-pb1x00/pb1200.h
new file mode 100644
index 0000000..9a3088b
--- /dev/null
+++ b/include/asm-mips/mach-pb1x00/pb1200.h
@@ -0,0 +1,252 @@
+/*
+ * AMD Alchemy PB1200 Referrence Board
+ * Board Registers defines.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ * ########################################################################
+ *
+ *
+ */
+#ifndef __ASM_PB1200_H
+#define __ASM_PB1200_H
+
+#include <linux/types.h>
+
+// This is defined in au1000.h with bogus value
+#undef AU1X00_EXTERNAL_INT
+
+#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN DSCR_CMD0_PSC1_TX
+#define DBDMA_I2S_RX_CHAN DSCR_CMD0_PSC1_RX
+
+/* SPI and SMB are muxed on the Pb1200 board.
+   Refer to board documentation.
+ */
+#define SPI_PSC_BASE        PSC0_BASE_ADDR
+#define SMBUS_PSC_BASE      PSC0_BASE_ADDR
+/* AC97 and I2S are muxed on the Pb1200 board.
+   Refer to board documentation.
+ */
+#define AC97_PSC_BASE       PSC1_BASE_ADDR
+#define I2S_PSC_BASE		PSC1_BASE_ADDR
+
+#define BCSR_KSEG1_ADDR 0xAD800000
+
+typedef volatile struct
+{
+	/*00*/	u16 whoami;
+		u16 reserved0;
+	/*04*/	u16 status;
+		u16 reserved1;
+	/*08*/	u16 switches;
+		u16 reserved2;
+	/*0C*/	u16 resets;
+		u16 reserved3;
+
+	/*10*/	u16 pcmcia;
+		u16 reserved4;
+	/*14*/	u16 board;
+		u16 reserved5;
+	/*18*/	u16 disk_leds;
+		u16 reserved6;
+	/*1C*/	u16 system;
+		u16 reserved7;
+
+	/*20*/	u16 intclr;
+		u16 reserved8;
+	/*24*/	u16 intset;
+		u16 reserved9;
+	/*28*/	u16 intclr_mask;
+		u16 reserved10;
+	/*2C*/	u16 intset_mask;
+		u16 reserved11;
+
+	/*30*/	u16 sig_status;
+		u16 reserved12;
+	/*34*/	u16 int_status;
+		u16 reserved13;
+	/*38*/	u16 reserved14;
+		u16 reserved15;
+	/*3C*/	u16 reserved16;
+		u16 reserved17;
+
+} BCSR;
+
+static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+
+/*
+ * Register bit definitions for the BCSRs
+ */
+#define BCSR_WHOAMI_DCID	0x000F
+#define BCSR_WHOAMI_CPLD	0x00F0
+#define BCSR_WHOAMI_BOARD	0x0F00
+
+#define BCSR_STATUS_PCMCIA0VS	0x0003
+#define BCSR_STATUS_PCMCIA1VS	0x000C
+#define BCSR_STATUS_SWAPBOOT	0x0040
+#define BCSR_STATUS_FLASHBUSY	0x0100
+#define BCSR_STATUS_IDECBLID	0x0200
+#define BCSR_STATUS_SD0WP		0x0400
+#define BCSR_STATUS_SD1WP		0x0800
+#define BCSR_STATUS_U0RXD		0x1000
+#define BCSR_STATUS_U1RXD		0x2000
+
+#define BCSR_SWITCHES_OCTAL	0x00FF
+#define BCSR_SWITCHES_DIP_1	0x0080
+#define BCSR_SWITCHES_DIP_2	0x0040
+#define BCSR_SWITCHES_DIP_3	0x0020
+#define BCSR_SWITCHES_DIP_4	0x0010
+#define BCSR_SWITCHES_DIP_5	0x0008
+#define BCSR_SWITCHES_DIP_6	0x0004
+#define BCSR_SWITCHES_DIP_7	0x0002
+#define BCSR_SWITCHES_DIP_8	0x0001
+#define BCSR_SWITCHES_ROTARY	0x0F00
+
+#define BCSR_RESETS_ETH		0x0001
+#define BCSR_RESETS_CAMERA	0x0002
+#define BCSR_RESETS_DC		0x0004
+#define BCSR_RESETS_IDE		0x0008
+/* not resets but in the same register */
+#define BCSR_RESETS_WSCFSM  0x0800
+#define BCSR_RESETS_PCS0MUX	0x1000
+#define BCSR_RESETS_PCS1MUX	0x2000
+#define BCSR_RESETS_SPISEL	0x4000
+#define BCSR_RESETS_SD1MUX  0x8000
+
+#define BCSR_PCMCIA_PC0VPP	0x0003
+#define BCSR_PCMCIA_PC0VCC	0x000C
+#define BCSR_PCMCIA_PC0DRVEN	0x0010
+#define BCSR_PCMCIA_PC0RST	0x0080
+#define BCSR_PCMCIA_PC1VPP	0x0300
+#define BCSR_PCMCIA_PC1VCC	0x0C00
+#define BCSR_PCMCIA_PC1DRVEN	0x1000
+#define BCSR_PCMCIA_PC1RST	0x8000
+
+#define BCSR_BOARD_LCDVEE	0x0001
+#define BCSR_BOARD_LCDVDD	0x0002
+#define BCSR_BOARD_LCDBL	0x0004
+#define BCSR_BOARD_CAMSNAP	0x0010
+#define BCSR_BOARD_CAMPWR	0x0020
+#define BCSR_BOARD_SD0PWR	0x0040
+#define BCSR_BOARD_SD1PWR	0x0080
+
+#define BCSR_LEDS_DECIMALS	0x00FF
+#define BCSR_LEDS_LED0		0x0100
+#define BCSR_LEDS_LED1		0x0200
+#define BCSR_LEDS_LED2		0x0400
+#define BCSR_LEDS_LED3		0x0800
+
+#define BCSR_SYSTEM_VDDI	0x001F
+#define BCSR_SYSTEM_POWEROFF	0x4000
+#define BCSR_SYSTEM_RESET	0x8000
+
+/* Bit positions for the different interrupt sources */
+#define BCSR_INT_IDE		0x0001
+#define BCSR_INT_ETH		0x0002
+#define BCSR_INT_PC0		0x0004
+#define BCSR_INT_PC0STSCHG	0x0008
+#define BCSR_INT_PC1		0x0010
+#define BCSR_INT_PC1STSCHG	0x0020
+#define BCSR_INT_DC			0x0040
+#define BCSR_INT_FLASHBUSY	0x0080
+#define BCSR_INT_PC0INSERT	0x0100
+#define BCSR_INT_PC0EJECT	0x0200
+#define BCSR_INT_PC1INSERT	0x0400
+#define BCSR_INT_PC1EJECT	0x0800
+#define BCSR_INT_SD0INSERT	0x1000
+#define BCSR_INT_SD0EJECT	0x2000
+#define BCSR_INT_SD1INSERT	0x4000
+#define BCSR_INT_SD1EJECT	0x8000
+
+/* PCMCIA Db1x00 specific defines */
+#define PCMCIA_MAX_SOCK 1
+#define PCMCIA_NUM_SOCKS (PCMCIA_MAX_SOCK+1)
+
+/* VPP/VCC */
+#define SET_VCC_VPP(VCC, VPP, SLOT)\
+	((((VCC)<<2) | ((VPP)<<0)) << ((SLOT)*8))
+
+#define AU1XXX_SMC91111_PHYS_ADDR	(0x0D000300)
+#define AU1XXX_SMC91111_IRQ			PB1200_ETH_INT
+
+#define AU1XXX_ATA_PHYS_ADDR		(0x0C800000)
+#define AU1XXX_ATA_PHYS_LEN			(0x100)
+#define AU1XXX_ATA_REG_OFFSET	(5)
+#define AU1XXX_ATA_INT			PB1200_IDE_INT
+#define AU1XXX_ATA_DDMA_REQ		DSCR_CMD0_DMA_REQ1;
+#define AU1XXX_ATA_RQSIZE		128
+
+#define NAND_PHYS_ADDR   0x1C000000
+
+/* Timing values as described in databook, * ns value stripped of
+ * lower 2 bits.
+ * These defines are here rather than an SOC1200 generic file because
+ * the parts chosen on another board may be different and may require
+ * different timings.
+ */
+#define NAND_T_H			(18 >> 2)
+#define NAND_T_PUL			(30 >> 2)
+#define NAND_T_SU			(30 >> 2)
+#define NAND_T_WH			(30 >> 2)
+
+/* Bitfield shift amounts */
+#define NAND_T_H_SHIFT		0
+#define NAND_T_PUL_SHIFT	4
+#define NAND_T_SU_SHIFT		8
+#define NAND_T_WH_SHIFT		12
+
+#define NAND_TIMING	((NAND_T_H   & 0xF)	<< NAND_T_H_SHIFT)   | \
+			((NAND_T_PUL & 0xF)	<< NAND_T_PUL_SHIFT) | \
+			((NAND_T_SU  & 0xF)	<< NAND_T_SU_SHIFT)  | \
+			((NAND_T_WH  & 0xF)	<< NAND_T_WH_SHIFT)
+
+
+/*
+ *	External Interrupts for Pb1200 as of 8/6/2004.
+ *   Bit positions in the CPLD registers can be calculated by taking
+ *   the interrupt define and subtracting the PB1200_INT_BEGIN value.
+ *    *example: IDE bis pos is  = 64 - 64
+                ETH bit pos is  = 65 - 64
+ */
+#define PB1200_INT_BEGIN		(AU1000_LAST_INTC1_INT + 1)
+#define PB1200_IDE_INT			(PB1200_INT_BEGIN + 0)
+#define PB1200_ETH_INT			(PB1200_INT_BEGIN + 1)
+#define PB1200_PC0_INT			(PB1200_INT_BEGIN + 2)
+#define PB1200_PC0_STSCHG_INT	(PB1200_INT_BEGIN + 3)
+#define PB1200_PC1_INT			(PB1200_INT_BEGIN + 4)
+#define PB1200_PC1_STSCHG_INT	(PB1200_INT_BEGIN + 5)
+#define PB1200_DC_INT			(PB1200_INT_BEGIN + 6)
+#define PB1200_FLASHBUSY_INT	(PB1200_INT_BEGIN + 7)
+#define PB1200_PC0_INSERT_INT	(PB1200_INT_BEGIN + 8)
+#define PB1200_PC0_EJECT_INT	(PB1200_INT_BEGIN + 9)
+#define PB1200_PC1_INSERT_INT	(PB1200_INT_BEGIN + 10)
+#define PB1200_PC1_EJECT_INT	(PB1200_INT_BEGIN + 11)
+#define PB1200_SD0_INSERT_INT	(PB1200_INT_BEGIN + 12)
+#define PB1200_SD0_EJECT_INT	(PB1200_INT_BEGIN + 13)
+#define PB1200_SD1_INSERT_INT	(PB1200_INT_BEGIN + 14)
+#define PB1200_SD1_EJECT_INT	(PB1200_INT_BEGIN + 15)
+
+#define PB1200_INT_END			(PB1200_INT_BEGIN + 15)
+
+/* For drivers/pcmcia/au1000_db1x00.c */
+#define BOARD_PC0_INT PB1200_PC0_INT
+#define BOARD_PC1_INT PB1200_PC1_INT
+#define BOARD_CARD_INSERTED(SOCKET) bcsr->sig_status & (1<<(8+(2*SOCKET)))
+
+#endif /* __ASM_PB1200_H */
+
diff --git a/include/asm-mips/mach-pnx8550/cm.h b/include/asm-mips/mach-pnx8550/cm.h
new file mode 100644
index 0000000..bb0a56c
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/cm.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *   Clock module specific definitions
+ *
+ * Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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.
+ */
+
+#ifndef __PNX8550_CM_H
+#define __PNX8550_CM_H
+
+#define PNX8550_CM_BASE	0xBBE47000
+
+#define PNX8550_CM_PLL0_CTL    *(volatile unsigned long *)(PNX8550_CM_BASE + 0x000)
+#define PNX8550_CM_PLL1_CTL    *(volatile unsigned long *)(PNX8550_CM_BASE + 0x004)
+#define PNX8550_CM_PLL2_CTL    *(volatile unsigned long *)(PNX8550_CM_BASE + 0x008)
+#define PNX8550_CM_PLL3_CTL    *(volatile unsigned long *)(PNX8550_CM_BASE + 0x00C)
+
+// Table not complete.....
+
+#define PNX8550_CM_PLL_BLOCKED_MASK     0x80000000
+#define PNX8550_CM_PLL_LOCK_MASK        0x40000000
+#define PNX8550_CM_PLL_CURRENT_ADJ_MASK 0x3c000000
+#define PNX8550_CM_PLL_N_MASK           0x01ff0000
+#define PNX8550_CM_PLL_M_MASK           0x00003f00
+#define PNX8550_CM_PLL_P_MASK           0x0000000c
+#define PNX8550_CM_PLL_PD_MASK          0x00000002
+
+
+#endif
diff --git a/include/asm-mips/mach-pnx8550/glb.h b/include/asm-mips/mach-pnx8550/glb.h
new file mode 100644
index 0000000..07aa85e
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/glb.h
@@ -0,0 +1,86 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *   PNX8550 global definitions
+ *
+ * Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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.
+ */
+
+#ifndef __PNX8550_GLB_H
+#define __PNX8550_GLB_H
+
+#define PNX8550_GLB1_BASE	0xBBE63000
+#define PNX8550_GLB2_BASE	0xBBE4d000
+#define PNX8550_RESET_BASE      0xBBE60000
+
+/* PCI Inta Output Enable Registers */
+#define PNX8550_GLB2_ENAB_INTA_O	*(volatile unsigned long *)(PNX8550_GLB2_BASE + 0x050)
+
+/* Bit 1:Enable DAC Powerdown
+     0:DACs are enabled and are working normally
+     1:DACs are powerdown
+*/
+#define PNX8550_GLB_DAC_PD      0x2
+/*   Bit 0:Enable of PCI inta output
+     0 = Disable PCI inta output
+     1 = Enable PCI inta output
+*/
+#define PNX8550_GLB_ENABLE_INTA_O 0x1
+
+/* PCI Direct Mappings */
+#define PNX8550_PCIMEM	        0x12000000
+#define PNX8550_PCIMEM_SIZE	0x08000000
+#define PNX8550_PCIIO	        0x1c000000
+#define PNX8550_PCIIO_SIZE	0x02000000	/* 32M */
+
+#define PNX8550_PORT_BASE	KSEG1
+
+// GPIO def
+#define PNX8550_GPIO_BASE	0x1Be00000
+
+#define PNX8550_GPIO_DIRQ0	 (PNX8550_GPIO_BASE + 0x104500)
+#define PNX8550_GPIO_MC1         (PNX8550_GPIO_BASE + 0x104004)
+#define PNX8550_GPIO_MC_31_BIT   30
+#define PNX8550_GPIO_MC_30_BIT   28
+#define PNX8550_GPIO_MC_29_BIT   26
+#define PNX8550_GPIO_MC_28_BIT   24
+#define PNX8550_GPIO_MC_27_BIT   22
+#define PNX8550_GPIO_MC_26_BIT   20
+#define PNX8550_GPIO_MC_25_BIT   18
+#define PNX8550_GPIO_MC_24_BIT   16
+#define PNX8550_GPIO_MC_23_BIT   14
+#define PNX8550_GPIO_MC_22_BIT   12
+#define PNX8550_GPIO_MC_21_BIT   10
+#define PNX8550_GPIO_MC_20_BIT   8
+#define PNX8550_GPIO_MC_19_BIT   6
+#define PNX8550_GPIO_MC_18_BIT   4
+#define PNX8550_GPIO_MC_17_BIT   2
+#define PNX8550_GPIO_MC_16_BIT   0
+
+#define PNX8550_GPIO_MODE_PRIMOP    0x1
+#define PNX8550_GPIO_MODE_NO_OPENDR 0x2
+#define PNX8550_GPIO_MODE_OPENDR    0x3
+
+// RESET module
+#define PNX8550_RST_CTL             *(volatile unsigned long *)(PNX8550_RESET_BASE + 0x0)
+#define PNX8550_RST_CAUSE           *(volatile unsigned long *)(PNX8550_RESET_BASE + 0x4)
+#define PNX8550_RST_EN_WATCHDOG     *(volatile unsigned long *)(PNX8550_RESET_BASE + 0x8)
+
+#define PNX8550_RST_REL_MIPS_RST_N     0x8
+#define PNX8550_RST_DO_SW_RST          0x4
+#define PNX8550_RST_REL_SYS_RST_OUT    0x2
+#define PNX8550_RST_ASSERT_SYS_RST_OUT 0x1
+#endif
diff --git a/include/asm-mips/mach-pnx8550/int.h b/include/asm-mips/mach-pnx8550/int.h
new file mode 100644
index 0000000..0e0668b
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/int.h
@@ -0,0 +1,140 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *   Interrupt specific definitions
+ *
+ * Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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.
+ */
+
+#ifndef __PNX8550_INT_H
+#define __PNX8550_INT_H
+
+#define PNX8550_GIC_BASE	0xBBE3E000
+
+#define PNX8550_GIC_PRIMASK_0	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x000)
+#define PNX8550_GIC_PRIMASK_1	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x004)
+#define PNX8550_GIC_VECTOR_0	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x100)
+#define PNX8550_GIC_VECTOR_1	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x104)
+#define PNX8550_GIC_PEND_1_31	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x200)
+#define PNX8550_GIC_PEND_32_63	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x204)
+#define PNX8550_GIC_PEND_64_70	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x208)
+#define PNX8550_GIC_FEATURES	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x300)
+#define PNX8550_GIC_REQ(x)	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0x400 + (x)*4)
+#define PNX8550_GIC_MOD_ID	*(volatile unsigned long *)(PNX8550_GIC_BASE + 0xFFC)
+
+// cp0 is two software + six hw exceptions
+#define PNX8550_INT_CP0_TOTINT	8
+#define PNX8550_INT_CP0_MIN	0
+#define PNX8550_INT_CP0_MAX	(PNX8550_INT_CP0_MIN + PNX8550_INT_CP0_TOTINT - 1)
+
+#define MIPS_CPU_GIC_IRQ        2
+#define MIPS_CPU_TIMER_IRQ      7
+
+// GIC are 71 exceptions connected to cp0's first hardware exception
+#define PNX8550_INT_GIC_TOTINT	71
+#define PNX8550_INT_GIC_MIN	(PNX8550_INT_CP0_MAX+1)
+#define PNX8550_INT_GIC_MAX	(PNX8550_INT_GIC_MIN + PNX8550_INT_GIC_TOTINT - 1)
+
+#define PNX8550_INT_UNDEF              (PNX8550_INT_GIC_MIN+0)
+#define PNX8550_INT_IPC_TARGET0_MIPS   (PNX8550_INT_GIC_MIN+1)
+#define PNX8550_INT_IPC_TARGET1_TM32_1 (PNX8550_INT_GIC_MIN+2)
+#define PNX8550_INT_IPC_TARGET1_TM32_2 (PNX8550_INT_GIC_MIN+3)
+#define PNX8550_INT_RESERVED_4         (PNX8550_INT_GIC_MIN+4)
+#define PNX8550_INT_USB                (PNX8550_INT_GIC_MIN+5)
+#define PNX8550_INT_GPIO_EQ1           (PNX8550_INT_GIC_MIN+6)
+#define PNX8550_INT_GPIO_EQ2           (PNX8550_INT_GIC_MIN+7)
+#define PNX8550_INT_GPIO_EQ3           (PNX8550_INT_GIC_MIN+8)
+#define PNX8550_INT_GPIO_EQ4           (PNX8550_INT_GIC_MIN+9)
+
+#define PNX8550_INT_GPIO_EQ5           (PNX8550_INT_GIC_MIN+10)
+#define PNX8550_INT_GPIO_EQ6           (PNX8550_INT_GIC_MIN+11)
+#define PNX8550_INT_RESERVED_12        (PNX8550_INT_GIC_MIN+12)
+#define PNX8550_INT_QVCP1              (PNX8550_INT_GIC_MIN+13)
+#define PNX8550_INT_QVCP2              (PNX8550_INT_GIC_MIN+14)
+#define PNX8550_INT_I2C1               (PNX8550_INT_GIC_MIN+15)
+#define PNX8550_INT_I2C2               (PNX8550_INT_GIC_MIN+16)
+#define PNX8550_INT_ISO_UART1          (PNX8550_INT_GIC_MIN+17)
+#define PNX8550_INT_ISO_UART2          (PNX8550_INT_GIC_MIN+18)
+#define PNX8550_INT_UART1              (PNX8550_INT_GIC_MIN+19)
+
+#define PNX8550_INT_UART2              (PNX8550_INT_GIC_MIN+20)
+#define PNX8550_INT_QNTR               (PNX8550_INT_GIC_MIN+21)
+#define PNX8550_INT_RESERVED22         (PNX8550_INT_GIC_MIN+22)
+#define PNX8550_INT_T_DSC              (PNX8550_INT_GIC_MIN+23)
+#define PNX8550_INT_M_DSC              (PNX8550_INT_GIC_MIN+24)
+#define PNX8550_INT_RESERVED25         (PNX8550_INT_GIC_MIN+25)
+#define PNX8550_INT_2D_DRAW_ENG        (PNX8550_INT_GIC_MIN+26)
+#define PNX8550_INT_MEM_BASED_SCALAR1  (PNX8550_INT_GIC_MIN+27)
+#define PNX8550_INT_VIDEO_MPEG         (PNX8550_INT_GIC_MIN+28)
+#define PNX8550_INT_VIDEO_INPUT_P1     (PNX8550_INT_GIC_MIN+29)
+
+#define PNX8550_INT_VIDEO_INPUT_P2     (PNX8550_INT_GIC_MIN+30)
+#define PNX8550_INT_SPDI1              (PNX8550_INT_GIC_MIN+31)
+#define PNX8550_INT_SPDO               (PNX8550_INT_GIC_MIN+32)
+#define PNX8550_INT_AUDIO_INPUT1       (PNX8550_INT_GIC_MIN+33)
+#define PNX8550_INT_AUDIO_OUTPUT1      (PNX8550_INT_GIC_MIN+34)
+#define PNX8550_INT_AUDIO_INPUT2       (PNX8550_INT_GIC_MIN+35)
+#define PNX8550_INT_AUDIO_OUTPUT2      (PNX8550_INT_GIC_MIN+36)
+#define PNX8550_INT_MEMBASED_SCALAR2   (PNX8550_INT_GIC_MIN+37)
+#define PNX8550_INT_VPK                (PNX8550_INT_GIC_MIN+38)
+#define PNX8550_INT_MPEG1_MIPS         (PNX8550_INT_GIC_MIN+39)
+
+#define PNX8550_INT_MPEG1_TM           (PNX8550_INT_GIC_MIN+40)
+#define PNX8550_INT_MPEG2_MIPS         (PNX8550_INT_GIC_MIN+41)
+#define PNX8550_INT_MPEG2_TM           (PNX8550_INT_GIC_MIN+42)
+#define PNX8550_INT_TS_DMA             (PNX8550_INT_GIC_MIN+43)
+#define PNX8550_INT_EDMA               (PNX8550_INT_GIC_MIN+44)
+#define PNX8550_INT_TM_DEBUG1          (PNX8550_INT_GIC_MIN+45)
+#define PNX8550_INT_TM_DEBUG2          (PNX8550_INT_GIC_MIN+46)
+#define PNX8550_INT_PCI_INTA           (PNX8550_INT_GIC_MIN+47)
+#define PNX8550_INT_CLOCK_MODULE       (PNX8550_INT_GIC_MIN+48)
+#define PNX8550_INT_PCI_XIO_INTA_PCI   (PNX8550_INT_GIC_MIN+49)
+
+#define PNX8550_INT_PCI_XIO_INTB_DMA   (PNX8550_INT_GIC_MIN+50)
+#define PNX8550_INT_PCI_XIO_INTC_GPPM  (PNX8550_INT_GIC_MIN+51)
+#define PNX8550_INT_PCI_XIO_INTD_GPXIO (PNX8550_INT_GIC_MIN+52)
+#define PNX8550_INT_DVD_CSS            (PNX8550_INT_GIC_MIN+53)
+#define PNX8550_INT_VLD                (PNX8550_INT_GIC_MIN+54)
+#define PNX8550_INT_GPIO_TSU_7_0       (PNX8550_INT_GIC_MIN+55)
+#define PNX8550_INT_GPIO_TSU_15_8      (PNX8550_INT_GIC_MIN+56)
+#define PNX8550_INT_GPIO_CTU_IR        (PNX8550_INT_GIC_MIN+57)
+#define PNX8550_INT_GPIO0              (PNX8550_INT_GIC_MIN+58)
+#define PNX8550_INT_GPIO1              (PNX8550_INT_GIC_MIN+59)
+
+#define PNX8550_INT_GPIO2              (PNX8550_INT_GIC_MIN+60)
+#define PNX8550_INT_GPIO3              (PNX8550_INT_GIC_MIN+61)
+#define PNX8550_INT_GPIO4              (PNX8550_INT_GIC_MIN+62)
+#define PNX8550_INT_GPIO5              (PNX8550_INT_GIC_MIN+63)
+#define PNX8550_INT_GPIO6              (PNX8550_INT_GIC_MIN+64)
+#define PNX8550_INT_GPIO7              (PNX8550_INT_GIC_MIN+65)
+#define PNX8550_INT_PMAN_SECURITY      (PNX8550_INT_GIC_MIN+66)
+#define PNX8550_INT_I2C3               (PNX8550_INT_GIC_MIN+67)
+#define PNX8550_INT_RESERVED_68        (PNX8550_INT_GIC_MIN+68)
+#define PNX8550_INT_SPDI2              (PNX8550_INT_GIC_MIN+69)
+
+#define PNX8550_INT_I2C4               (PNX8550_INT_GIC_MIN+70)
+
+// Timer are 3 exceptions connected to cp0's 7th hardware exception
+#define PNX8550_INT_TIMER_TOTINT       3
+#define PNX8550_INT_TIMER_MIN	       (PNX8550_INT_GIC_MAX+1)
+#define PNX8550_INT_TIMER_MAX          (PNX8550_INT_TIMER_MIN + PNX8550_INT_TIMER_TOTINT - 1)
+
+#define PNX8550_INT_TIMER1             (PNX8550_INT_TIMER_MIN+0)
+#define PNX8550_INT_TIMER2             (PNX8550_INT_TIMER_MIN+1)
+#define PNX8550_INT_TIMER3             (PNX8550_INT_TIMER_MIN+2)
+#define PNX8550_INT_WATCHDOG           PNX8550_INT_TIMER3
+
+#endif
diff --git a/include/asm-mips/mach-pnx8550/kernel-entry-init.h b/include/asm-mips/mach-pnx8550/kernel-entry-init.h
new file mode 100644
index 0000000..57102fa
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/kernel-entry-init.h
@@ -0,0 +1,262 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ */
+#ifndef __ASM_MACH_KERNEL_ENTRY_INIT_H
+#define __ASM_MACH_KERNEL_ENTRY_INIT_H
+
+#include <asm/cacheops.h>
+#include <asm/addrspace.h>
+
+#define CO_CONFIGPR_VALID  0x3F1F41FF    /* valid bits to write to ConfigPR */
+#define HAZARD_CP0 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;
+#define CACHE_OPC      0xBC000000  /* MIPS cache instruction opcode */
+#define ICACHE_LINE_SIZE        32      /* Instruction cache line size bytes */
+#define DCACHE_LINE_SIZE        32      /* Data cache line size in bytes */
+
+#define ICACHE_SET_COUNT        256     /* Instruction cache set count */
+#define DCACHE_SET_COUNT        128     /* Data cache set count */
+
+#define ICACHE_SET_SIZE         (ICACHE_SET_COUNT * ICACHE_LINE_SIZE)
+#define DCACHE_SET_SIZE         (DCACHE_SET_COUNT * DCACHE_LINE_SIZE)
+
+	.macro	kernel_entry_setup
+	.set	push
+	.set	noreorder
+	/*
+	 * PNX8550 entry point, when running a non compressed
+	 * kernel. When loading a zImage, the head.S code in
+	 * arch/mips/zboot/pnx8550 will init the caches and,
+	 * decompress the kernel, and branch to kernel_entry.
+		 */
+cache_begin:	li	t0, (1<<28)
+	mtc0	t0, CP0_STATUS /* cp0 usable */
+	HAZARD_CP0
+
+	mtc0 	zero, CP0_CAUSE
+	HAZARD_CP0
+
+
+	/* Set static virtual to phys address translation and TLB disabled */
+	mfc0 	t0, CP0_CONFIG, 7
+	HAZARD_CP0
+
+	and t0,~((1<<19) | (1<<20))     /* TLB/MAP cleared */
+	mtc0	t0, CP0_CONFIG, 7
+	HAZARD_CP0
+
+	/* CPU boots with kseg0 cache algo set to 0x2 -- uncached */
+
+	init_icache
+	nop
+	init_dcache
+	nop
+
+	cachePr4450ICReset
+	nop
+
+	cachePr4450DCReset
+	nop
+
+	/* read ConfigPR into t0 */
+	mfc0	t0, CP0_CONFIG, 7
+	HAZARD_CP0
+
+	/*  enable the TLB */
+	or      t0, (1<<19)
+
+	/* disable the ICACHE: at least 10x slower */
+	/* or      t0, (1<<26) */
+
+	/* disable the DCACHE; CONFIG_CPU_HAS_LLSC should not be set  */
+	/* or      t0, (1<<27) */
+
+	and	t0, CO_CONFIGPR_VALID
+
+	/* enable TLB. */
+	mtc0	t0, CP0_CONFIG, 7
+	HAZARD_CP0
+cache_end:
+	/* Setup CMEM_0 to MMIO address space, 2MB */
+	lui    t0, 0x1BE0
+	addi   t0, t0, 0x3
+	mtc0   $8, $22, 4
+	nop
+
+	/* Setup CMEM_1, 128MB */
+	lui    t0, 0x1000
+	addi   t0, t0, 0xf
+	mtc0   $8, $22, 5
+	nop
+
+
+	/* Setup CMEM_2, 32MB */
+	lui    t0, 0x1C00
+	addi   t0, t0, 0xb
+	mtc0   $8, $22, 6
+	nop
+
+	/* Setup CMEM_3, 0MB */
+	lui    t0, 0x0
+	addi   t0, t0, 0x0
+	mtc0   $8, $22, 7
+	nop
+
+	/* Enable cache */
+	mfc0	t0, CP0_CONFIG
+	HAZARD_CP0
+	and	t0, t0, 0xFFFFFFF8
+	or	t0, t0, 3
+	mtc0	t0, CP0_CONFIG
+	HAZARD_CP0
+	.set	pop
+	.endm
+
+	.macro	init_icache
+	.set	push
+	.set	noreorder
+
+	/* Get Cache Configuration */
+	mfc0	t3, CP0_CONFIG, 1
+	HAZARD_CP0
+
+	/* get cache Line size */
+
+	srl   t1, t3, 19   /* C0_CONFIGPR_IL_SHIFT */
+	andi  t1, t1, 0x7  /* C0_CONFIGPR_IL_MASK */
+	beq   t1, zero, pr4450_instr_cache_invalidated /* if zero instruction cache is absent */
+	nop
+	addiu t0, t1, 1
+	ori   t1, zero, 1
+	sllv  t1, t1, t0
+
+	/* get max cache Index */
+	srl   t2, t3, 22  /* C0_CONFIGPR_IS_SHIFT */
+	andi  t2, t2, 0x7 /* C0_CONFIGPR_IS_MASK */
+	addiu t0, t2, 6
+	ori   t2, zero, 1
+	sllv  t2, t2, t0
+
+	/* get max cache way */
+	srl   t3, t3, 16  /* C0_CONFIGPR_IA_SHIFT */
+	andi  t3, t3, 0x7 /* C0_CONFIGPR_IA_MASK */
+	addiu t3, t3, 1
+
+	/* total no of cache lines */
+	multu t2, t3             /* max index * max way */
+	mflo  t2
+	addiu t2, t2, -1
+
+	move  t0, zero
+pr4450_next_instruction_cache_set:
+	cache  Index_Invalidate_I, 0(t0)
+	addu  t0, t0, t1         /* add bytes in a line */
+	bne   t2, zero, pr4450_next_instruction_cache_set
+	addiu t2, t2, -1   /* reduce no of lines to invalidate by one */
+pr4450_instr_cache_invalidated:
+	.set	pop
+	.endm
+
+	.macro	init_dcache
+	.set	push
+	.set	noreorder
+	move t1, zero
+
+	/* Store Tag Information */
+	mtc0	zero, CP0_TAGLO, 0
+	HAZARD_CP0
+
+	mtc0	zero, CP0_TAGHI, 0
+	HAZARD_CP0
+
+	/* Cache size is 16384 = 512 lines x 32 bytes per line */
+	or       t2, zero, (128*4)-1  /* 512 lines  */
+	/* Invalidate all lines */
+2:
+	cache Index_Store_Tag_D, 0(t1)
+	addiu    t2, t2, -1
+	bne      t2, zero, 2b
+	addiu    t1, t1, 32        /* 32 bytes in a line */
+	.set pop
+	.endm
+
+	.macro	cachePr4450ICReset
+	.set	push
+	.set	noreorder
+
+	/* Save CP0 status reg on entry; */
+	/* disable interrupts during cache reset */
+	mfc0    t0, CP0_STATUS      /* T0 = interrupt status on entry */
+	HAZARD_CP0
+
+	mtc0    zero, CP0_STATUS   /* disable CPU interrupts */
+	HAZARD_CP0
+
+	or      t1, zero, zero              /* T1 = starting cache index (0) */
+	ori     t2, zero, (256 - 1) /* T2 = inst cache set cnt - 1 */
+
+	icache_invd_loop:
+	/* 9 == register t1 */
+	.word   (CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
+		(0 * ICACHE_SET_SIZE))  /* invalidate inst cache WAY0 */
+	.word   (CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \
+		(1 * ICACHE_SET_SIZE))  /* invalidate inst cache WAY1 */
+
+	addiu   t1, t1, ICACHE_LINE_SIZE    /* T1 = next cache line index */
+	bne     t2, zero, icache_invd_loop /* T2 = 0 if all sets invalidated */
+	addiu   t2, t2, -1        /* decrement T2 set cnt (delay slot) */
+
+	/* Initialize the latches in the instruction cache tag */
+	/* that drive the way selection tri-state bus drivers, by doing a */
+	/* dummy load while the instruction cache is still disabled. */
+	/* TODO: Is this needed ? */
+	la      t1, KSEG0            /* T1 = cached memory base address */
+	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */
+
+	mtc0    t0, CP0_STATUS        /* restore interrupt status on entry */
+	HAZARD_CP0
+	.set	pop
+	.endm
+
+	.macro	cachePr4450DCReset
+	.set	push
+	.set	noreorder
+	mfc0    t0, CP0_STATUS           /* T0 = interrupt status on entry */
+	HAZARD_CP0
+	mtc0    zero, CP0_STATUS         /* disable CPU interrupts */
+	HAZARD_CP0
+
+	/* Writeback/invalidate entire data cache sets/ways/lines */
+	or      t1, zero, zero              /* T1 = starting cache index (0) */
+	ori     t2, zero, (DCACHE_SET_COUNT - 1) /* T2 = data cache set cnt - 1 */
+
+	dcache_wbinvd_loop:
+	/* 9 == register t1 */
+	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
+		(0 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY0 */
+	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
+		(1 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY1 */
+	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
+		(2 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY2 */
+	.word   (CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \
+		(3 * DCACHE_SET_SIZE))  /* writeback/invalidate WAY3 */
+
+	addiu   t1, t1, DCACHE_LINE_SIZE  /* T1 = next data cache line index */
+	bne     t2, zero, dcache_wbinvd_loop /* T2 = 0 when wbinvd entire cache */
+	addiu   t2, t2, -1          /* decrement T2 set cnt (delay slot) */
+
+	/* Initialize the latches in the data cache tag that drive the way
+	selection tri-state bus drivers, by doing a dummy load while the
+	data cache is still in the disabled mode.  TODO: Is this needed ? */
+	la      t1, KSEG0            /* T1 = cached memory base address */
+	lw      zero, 0x0000(t1)      /* (dummy read of first memory word) */
+
+	mtc0    t0, CP0_STATUS       /* restore interrupt status on entry */
+	HAZARD_CP0
+	.set	pop
+	.endm
+
+#endif /* __ASM_MACH_KERNEL_ENTRY_INIT_H */
diff --git a/include/asm-mips/mach-pnx8550/nand.h b/include/asm-mips/mach-pnx8550/nand.h
new file mode 100644
index 0000000..aefbc51
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/nand.h
@@ -0,0 +1,121 @@
+#ifndef __PNX8550_NAND_H
+#define __PNX8550_NAND_H
+
+#define PNX8550_NAND_BASE_ADDR   0x10000000
+#define PNX8550_PCIXIO_BASE	 0xBBE40000
+
+#define PNX8550_DMA_EXT_ADDR     *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x800)
+#define PNX8550_DMA_INT_ADDR     *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x804)
+#define PNX8550_DMA_TRANS_SIZE   *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x808)
+#define PNX8550_DMA_CTRL         *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x80c)
+#define PNX8550_XIO_SEL0         *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x814)
+#define PNX8550_GPXIO_ADDR       *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x820)
+#define PNX8550_GPXIO_WR         *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x824)
+#define PNX8550_GPXIO_RD         *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x828)
+#define PNX8550_GPXIO_CTRL       *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x82C)
+#define PNX8550_XIO_FLASH_CTRL   *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0x830)
+#define PNX8550_GPXIO_INT_STATUS *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfb0)
+#define PNX8550_GPXIO_INT_ENABLE *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfb4)
+#define PNX8550_GPXIO_INT_CLEAR  *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfb8)
+#define PNX8550_DMA_INT_STATUS   *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfd0)
+#define PNX8550_DMA_INT_ENABLE   *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfd4)
+#define PNX8550_DMA_INT_CLEAR    *(volatile unsigned long *)(PNX8550_PCIXIO_BASE + 0xfd8)
+
+#define PNX8550_XIO_SEL0_EN_16BIT    0x00800000
+#define PNX8550_XIO_SEL0_USE_ACK     0x00400000
+#define PNX8550_XIO_SEL0_REN_HIGH    0x00100000
+#define PNX8550_XIO_SEL0_REN_LOW     0x00040000
+#define PNX8550_XIO_SEL0_WEN_HIGH    0x00010000
+#define PNX8550_XIO_SEL0_WEN_LOW     0x00004000
+#define PNX8550_XIO_SEL0_WAIT        0x00000200
+#define PNX8550_XIO_SEL0_OFFSET      0x00000020
+#define PNX8550_XIO_SEL0_TYPE_68360  0x00000000
+#define PNX8550_XIO_SEL0_TYPE_NOR    0x00000008
+#define PNX8550_XIO_SEL0_TYPE_NAND   0x00000010
+#define PNX8550_XIO_SEL0_TYPE_IDE    0x00000018
+#define PNX8550_XIO_SEL0_SIZE_8MB    0x00000000
+#define PNX8550_XIO_SEL0_SIZE_16MB   0x00000002
+#define PNX8550_XIO_SEL0_SIZE_32MB   0x00000004
+#define PNX8550_XIO_SEL0_SIZE_64MB   0x00000006
+#define PNX8550_XIO_SEL0_ENAB        0x00000001
+
+#define PNX8550_SEL0_DEFAULT ((PNX8550_XIO_SEL0_EN_16BIT)  | \
+                              (PNX8550_XIO_SEL0_REN_HIGH*0)| \
+	                      (PNX8550_XIO_SEL0_REN_LOW*2) | \
+	                      (PNX8550_XIO_SEL0_WEN_HIGH*0)| \
+                              (PNX8550_XIO_SEL0_WEN_LOW*2) | \
+	                      (PNX8550_XIO_SEL0_WAIT*4)    | \
+			      (PNX8550_XIO_SEL0_OFFSET*0)  | \
+			      (PNX8550_XIO_SEL0_TYPE_NAND) | \
+			      (PNX8550_XIO_SEL0_SIZE_32MB) | \
+			      (PNX8550_XIO_SEL0_ENAB))
+
+#define PNX8550_GPXIO_PENDING        0x00000200
+#define PNX8550_GPXIO_DONE           0x00000100
+#define PNX8550_GPXIO_CLR_DONE       0x00000080
+#define PNX8550_GPXIO_INIT           0x00000040
+#define PNX8550_GPXIO_READ_CMD       0x00000010
+#define PNX8550_GPXIO_BEN            0x0000000F
+
+#define PNX8550_XIO_FLASH_64MB       0x00200000
+#define PNX8550_XIO_FLASH_INC_DATA   0x00100000
+#define PNX8550_XIO_FLASH_CMD_PH     0x000C0000
+#define PNX8550_XIO_FLASH_CMD_PH2    0x00080000
+#define PNX8550_XIO_FLASH_CMD_PH1    0x00040000
+#define PNX8550_XIO_FLASH_CMD_PH0    0x00000000
+#define PNX8550_XIO_FLASH_ADR_PH     0x00030000
+#define PNX8550_XIO_FLASH_ADR_PH3    0x00030000
+#define PNX8550_XIO_FLASH_ADR_PH2    0x00020000
+#define PNX8550_XIO_FLASH_ADR_PH1    0x00010000
+#define PNX8550_XIO_FLASH_ADR_PH0    0x00000000
+#define PNX8550_XIO_FLASH_CMD_B(x)   ((x<<8) & 0x0000FF00)
+#define PNX8550_XIO_FLASH_CMD_A(x)   (x & 0x000000FF)
+
+#define PNX8550_XIO_INT_ACK          0x00004000
+#define PNX8550_XIO_INT_COMPL        0x00002000
+#define PNX8550_XIO_INT_NONSUP       0x00000200
+#define PNX8550_XIO_INT_ABORT        0x00000004
+
+#define PNX8550_DMA_CTRL_SINGLE_DATA 0x00000400
+#define PNX8550_DMA_CTRL_SND2XIO     0x00000200
+#define PNX8550_DMA_CTRL_FIX_ADDR    0x00000100
+#define PNX8550_DMA_CTRL_BURST_8     0x00000000
+#define PNX8550_DMA_CTRL_BURST_16    0x00000020
+#define PNX8550_DMA_CTRL_BURST_32    0x00000040
+#define PNX8550_DMA_CTRL_BURST_64    0x00000060
+#define PNX8550_DMA_CTRL_BURST_128   0x00000080
+#define PNX8550_DMA_CTRL_BURST_256   0x000000A0
+#define PNX8550_DMA_CTRL_BURST_512   0x000000C0
+#define PNX8550_DMA_CTRL_BURST_NORES 0x000000E0
+#define PNX8550_DMA_CTRL_INIT_DMA    0x00000010
+#define PNX8550_DMA_CTRL_CMD_TYPE    0x0000000F
+
+/* see PCI system arch, page 100 for the full list: */
+#define PNX8550_DMA_CTRL_PCI_CMD_READ    0x00000006
+#define PNX8550_DMA_CTRL_PCI_CMD_WRITE   0x00000007
+
+#define PNX8550_DMA_INT_STAT_ACK_DONE	(1<<14)
+#define PNX8550_DMA_INT_STAT_DMA_DONE	(1<<12)
+#define PNX8550_DMA_INT_STAT_DMA_ERR	(1<<9)
+#define PNX8550_DMA_INT_STAT_PERR5	(1<<5)
+#define PNX8550_DMA_INT_STAT_PERR4	(1<<4)
+#define PNX8550_DMA_INT_STAT_M_ABORT	(1<<2)
+#define PNX8550_DMA_INT_STAT_T_ABORT	(1<<1)
+
+#define PNX8550_DMA_INT_EN_ACK_DONE	(1<<14)
+#define PNX8550_DMA_INT_EN_DMA_DONE	(1<<12)
+#define PNX8550_DMA_INT_EN_DMA_ERR	(1<<9)
+#define PNX8550_DMA_INT_EN_PERR5	(1<<5)
+#define PNX8550_DMA_INT_EN_PERR4	(1<<4)
+#define PNX8550_DMA_INT_EN_M_ABORT	(1<<2)
+#define PNX8550_DMA_INT_EN_T_ABORT	(1<<1)
+
+#define PNX8550_DMA_INT_CLR_ACK_DONE	(1<<14)
+#define PNX8550_DMA_INT_CLR_DMA_DONE	(1<<12)
+#define PNX8550_DMA_INT_CLR_DMA_ERR	(1<<9)
+#define PNX8550_DMA_INT_CLR_PERR5	(1<<5)
+#define PNX8550_DMA_INT_CLR_PERR4	(1<<4)
+#define PNX8550_DMA_INT_CLR_M_ABORT	(1<<2)
+#define PNX8550_DMA_INT_CLR_T_ABORT	(1<<1)
+
+#endif
diff --git a/include/asm-mips/mach-pnx8550/pci.h b/include/asm-mips/mach-pnx8550/pci.h
new file mode 100644
index 0000000..b921508
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/pci.h
@@ -0,0 +1,185 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PCI specific definitions
+ *
+ * Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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.
+ */
+
+#ifndef __PNX8550_PCI_H
+#define __PNX8550_PCI_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+#define PCI_CMD_IOR                     0x20
+#define PCI_CMD_IOW                     0x30
+#define PCI_CMD_CONFIG_READ             0xa0
+#define PCI_CMD_CONFIG_WRITE            0xb0
+
+#define PCI_IO_TIMEOUT                  1000
+#define PCI_IO_RETRY			5
+/* Timeout for IO and CFG accesses.
+   This is in 1/1024 th of a jiffie(=10ms)
+   i.e. approx 10us */
+#define PCI_IO_JIFFIES_TIMEOUT          40
+#define PCI_IO_JIFFIES_SHIFT            10
+
+#define PCI_BYTE_ENABLE_MASK		0x0000000f
+#define PCI_CFG_BUS_SHIFT               16
+#define PCI_CFG_FUNC_SHIFT              8
+#define PCI_CFG_REG_SHIFT               2
+
+#define PCI_BASE                  0x1be00000
+#define PCI_SETUP                 0x00040010
+#define PCI_DIS_REQGNT           (1<<30)
+#define PCI_DIS_REQGNTA          (1<<29)
+#define PCI_DIS_REQGNTB          (1<<28)
+#define PCI_D2_SUPPORT           (1<<27)
+#define PCI_D1_SUPPORT           (1<<26)
+#define PCI_EN_TA                (1<<24)
+#define PCI_EN_PCI2MMI           (1<<23)
+#define PCI_EN_XIO               (1<<22)
+#define PCI_BASE18_PREF          (1<<21)
+#define SIZE_16M                 0x3
+#define SIZE_32M                 0x4
+#define SIZE_64M                 0x5
+#define SIZE_128M                0x6
+#define PCI_SETUP_BASE18_SIZE(X) (X<<18)
+#define PCI_SETUP_BASE18_EN      (1<<17)
+#define PCI_SETUP_BASE14_PREF    (1<<16)
+#define PCI_SETUP_BASE14_SIZE(X) (X<<12)
+#define PCI_SETUP_BASE14_EN      (1<<11)
+#define PCI_SETUP_BASE10_PREF    (1<<10)
+#define PCI_SETUP_BASE10_SIZE(X) (X<<7)
+#define PCI_SETUP_CFGMANAGE_EN   (1<<1)
+#define PCI_SETUP_PCIARB_EN      (1<<0)
+
+#define PCI_CTRL                  0x040014
+#define PCI_SWPB_DCS_PCI         (1<<16)
+#define PCI_SWPB_PCI_PCI         (1<<15)
+#define PCI_SWPB_PCI_DCS         (1<<14)
+#define PCI_REG_WR_POST          (1<<13)
+#define PCI_XIO_WR_POST          (1<<12)
+#define PCI_PCI2_WR_POST         (1<<13)
+#define PCI_PCI1_WR_POST         (1<<12)
+#define PCI_SERR_SEEN            (1<<11)
+#define PCI_B10_SPEC_RD          (1<<6)
+#define PCI_B14_SPEC_RD          (1<<5)
+#define PCI_B18_SPEC_RD          (1<<4)
+#define PCI_B10_NOSUBWORD        (1<<3)
+#define PCI_B14_NOSUBWORD        (1<<2)
+#define PCI_B18_NOSUBWORD        (1<<1)
+#define PCI_RETRY_TMREN          (1<<0)
+
+#define PCI_BASE1_LO              0x040018
+#define PCI_BASE1_HI              0x04001C
+#define PCI_BASE2_LO              0x040020
+#define PCI_BASE2_HI              0x040024
+#define PCI_RDLIFETIM             0x040028
+#define PCI_GPPM_ADDR             0x04002C
+#define PCI_GPPM_WDAT             0x040030
+#define PCI_GPPM_RDAT             0x040034
+#define PCI_GPPM_CTRL             0x040038
+#define GPPM_DONE                (1<<10)
+#define INIT_PCI_CYCLE           (1<<9)
+#define GPPM_CMD(X)              (((X)&0xf)<<4)
+#define GPPM_BYTEEN(X)           ((X)&0xf)
+#define PCI_UNLOCKREG             0x04003C
+#define UNLOCK_SSID(X)           (((X)&0xff)<<8)
+#define UNLOCK_SETUP(X)          (((X)&0xff)<<0)
+#define UNLOCK_MAGIC             0xCA
+#define PCI_DEV_VEND_ID           0x040040
+#define DEVICE_ID(X)             (((X)>>16)&0xffff)
+#define VENDOR_ID(X)             (((X)&0xffff))
+#define PCI_CFG_CMDSTAT           0x040044
+#define PCI_CFG_STATUS(X)            (((X)>>16)&0xffff)
+#define PCI_CFG_COMMAND(X)           ((X)&0xffff)
+#define PCI_CLASS_REV             0x040048
+#define PCI_CLASSCODE(X)         (((X)>>8)&0xffffff)
+#define PCI_REVID(X)             ((X)&0xff)
+#define PCI_LAT_TMR     0x04004c
+#define PCI_BASE10      0x040050
+#define PCI_BASE14      0x040054
+#define PCI_BASE18      0x040058
+#define PCI_SUBSYS_ID   0x04006c
+#define PCI_CAP_PTR     0x040074
+#define PCI_CFG_MISC    0x04007c
+#define PCI_PMC         0x040080
+#define PCI_PWR_STATE   0x040084
+#define PCI_IO          0x040088
+#define PCI_SLVTUNING   0x04008C
+#define PCI_DMATUNING   0x040090
+#define PCI_DMAEADDR    0x040800
+#define PCI_DMAIADDR    0x040804
+#define PCI_DMALEN      0x040808
+#define PCI_DMACTRL     0x04080C
+#define PCI_XIOCTRL     0x040810
+#define PCI_SEL0PROF    0x040814
+#define PCI_SEL1PROF    0x040818
+#define PCI_SEL2PROF    0x04081C
+#define PCI_GPXIOADDR   0x040820
+#define PCI_NANDCTRLS   0x400830
+#define PCI_SEL3PROF    0x040834
+#define PCI_SEL4PROF    0x040838
+#define PCI_GPXIO_STAT  0x040FB0
+#define PCI_GPXIO_IMASK 0x040FB4
+#define PCI_GPXIO_ICLR  0x040FB8
+#define PCI_GPXIO_ISET  0x040FBC
+#define PCI_GPPM_STATUS 0x040FC0
+#define GPPM_DONE      (1<<10)
+#define GPPM_ERR       (1<<9)
+#define GPPM_MPAR_ERR  (1<<8)
+#define GPPM_PAR_ERR   (1<<7)
+#define GPPM_R_MABORT  (1<<2)
+#define GPPM_R_TABORT  (1<<1)
+#define PCI_GPPM_IMASK  0x040FC4
+#define PCI_GPPM_ICLR   0x040FC8
+#define PCI_GPPM_ISET   0x040FCC
+#define PCI_DMA_STATUS  0x040FD0
+#define PCI_DMA_IMASK   0x040FD4
+#define PCI_DMA_ICLR    0x040FD8
+#define PCI_DMA_ISET    0x040FDC
+#define PCI_ISTATUS     0x040FE0
+#define PCI_IMASK       0x040FE4
+#define PCI_ICLR        0x040FE8
+#define PCI_ISET        0x040FEC
+#define PCI_MOD_ID      0x040FFC
+
+/*
+ *  PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF           0
+#define PCI_CFG_TYPE0_FUNC_SHF          8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF           0
+#define PCI_CFG_TYPE1_FUNC_SHF          8
+#define PCI_CFG_TYPE1_DEV_SHF           11
+#define PCI_CFG_TYPE1_BUS_SHF           16
+
+/*
+ *  Ethernet device DP83816 definition
+ */
+#define DP83816_IRQ_ETHER               66
+
+#endif
diff --git a/include/asm-mips/mach-pnx8550/uart.h b/include/asm-mips/mach-pnx8550/uart.h
new file mode 100644
index 0000000..e32b9a2
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/uart.h
@@ -0,0 +1,16 @@
+#ifndef __IP3106_UART_H
+#define __IP3106_UART_H
+
+#include <int.h>
+
+/* early macros for kgdb use. fixme: clean this up */
+
+#define UART_BASE		0xbbe4a000	/* PNX8550 */
+
+#define PNX8550_UART_PORT0	(UART_BASE)
+#define PNX8550_UART_PORT1	(UART_BASE + 0x1000)
+
+#define PNX8550_UART_INT(x)		(PNX8550_INT_GIC_MIN+19+x)
+#define IRQ_TO_UART(x)			(x-PNX8550_INT_GIC_MIN-19)
+
+#endif
diff --git a/include/asm-mips/mach-pnx8550/usb.h b/include/asm-mips/mach-pnx8550/usb.h
new file mode 100644
index 0000000..483b7fc
--- /dev/null
+++ b/include/asm-mips/mach-pnx8550/usb.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *  USB specific definitions
+ *
+ * Author: source@mvista.com
+ *
+ *  This program is free software; you can distribute 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 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.
+ */
+
+#ifndef __PNX8550_USB_H
+#define __PNX8550_USB_H
+
+/*
+ * USB Host controller
+ */
+
+#define PNX8550_USB_OHCI_OP_BASE	0x1be48000
+#define PNX8550_USB_OHCI_OP_LEN	        0x1000
+
+#endif
diff --git a/include/asm-mips/mach-rm200/cpu-feature-overrides.h b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
index f487360..79f9b06 100644
--- a/include/asm-mips/mach-rm200/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
@@ -14,7 +14,7 @@
 
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4ktlb		1
+#define cpu_has_4kcache		1
 #define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
@@ -31,6 +31,7 @@
 #define cpu_has_vtag_icache	0
 #define cpu_has_dc_aliases	(PAGE_SIZE < 0x4000)
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 #define cpu_has_nofpuex		0
 #define cpu_has_64bits		1
 
diff --git a/include/asm-mips/mach-sibyte/cpu-feature-overrides.h b/include/asm-mips/mach-sibyte/cpu-feature-overrides.h
index a3a2cc6..193a666 100644
--- a/include/asm-mips/mach-sibyte/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-sibyte/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
 #define cpu_has_vtag_icache	1
 #define cpu_has_dc_aliases	0
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 #define cpu_icache_snoops_remote_store	0
 
 #define cpu_has_nofpuex		0
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-sim/cpu-feature-overrides.h
new file mode 100644
index 0000000..cadbe8e
--- /dev/null
+++ b/include/asm-mips/mach-sim/cpu-feature-overrides.h
@@ -0,0 +1,66 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Chris Dearman
+ */
+#ifndef __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
+
+#include <linux/config.h>
+
+/*
+ * CPU feature overrides for MIPS boards
+ */
+#ifdef CONFIG_CPU_MIPS32
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_4kcache		1
+#define cpu_has_fpu		0
+/* #define cpu_has_32fpr	? */
+#define cpu_has_counter		1
+/* #define cpu_has_watch	? */
+#define cpu_has_divec		1
+#define cpu_has_vce		0
+/* #define cpu_has_cache_cdex_p	? */
+/* #define cpu_has_cache_cdex_s	? */
+/* #define cpu_has_prefetch	? */
+#define cpu_has_mcheck		1
+/* #define cpu_has_ejtag	? */
+#define cpu_has_llsc		1
+/* #define cpu_has_vtag_icache	? */
+/* #define cpu_has_dc_aliases	? */
+/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_nofpuex		0
+/* #define cpu_has_64bits	? */
+/* #define cpu_has_64bit_zero_reg ? */
+/* #define cpu_has_subset_pcaches ? */
+#endif
+
+#ifdef CONFIG_CPU_MIPS64
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_4kcache		1
+/* #define cpu_has_fpu		? */
+/* #define cpu_has_32fpr	? */
+#define cpu_has_counter		1
+/* #define cpu_has_watch	? */
+#define cpu_has_divec		1
+#define cpu_has_vce		0
+/* #define cpu_has_cache_cdex_p	? */
+/* #define cpu_has_cache_cdex_s	? */
+/* #define cpu_has_prefetch	? */
+#define cpu_has_mcheck		1
+/* #define cpu_has_ejtag	? */
+#define cpu_has_llsc		1
+/* #define cpu_has_vtag_icache	? */
+/* #define cpu_has_dc_aliases	? */
+/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_nofpuex		0
+/* #define cpu_has_64bits	? */
+/* #define cpu_has_64bit_zero_reg ? */
+/* #define cpu_has_subset_pcaches ? */
+#endif
+
+#endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
index 58603e3..463d051 100644
--- a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
@@ -25,6 +25,7 @@
 #define cpu_has_vtag_icache	0
 #define cpu_has_dc_aliases	0
 #define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
 #define cpu_icache_snoops_remote_store	0
 
 #define cpu_has_nofpuex		0
@@ -36,10 +37,4 @@
 #define cpu_icache_line_size()	32
 #define cpu_scache_line_size()	32
 
-/*
- * On the RM9000 we need to ensure that I-cache lines being fetches only
- * contain valid instructions are funny things will happen.
- */
-#define PLAT_TRAMPOLINE_STUFF_LINE	32UL
-
 #endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index 65d1d16..25b6ffc 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -66,6 +66,7 @@
 #define MIPS_REVISION_CORID_CORE_EMUL      6
 #define MIPS_REVISION_CORID_CORE_FPGA2     7
 #define MIPS_REVISION_CORID_CORE_FPGAR2    8
+#define MIPS_REVISION_CORID_CORE_FPGA3     9
 
 /**** Artificial corid defines ****/
 /*
@@ -79,4 +80,10 @@
 
 extern unsigned int mips_revision_corid;
 
+#ifdef CONFIG_PCI
+extern void mips_pcibios_init(void);
+#else
+#define mips_pcibios_init() do { } while (0)
+#endif
+
 #endif  /* __ASM_MIPS_BOARDS_GENERIC_H */
diff --git a/include/asm-mips/mips-boards/maltaint.h b/include/asm-mips/mips-boards/maltaint.h
index 3761818..da6cc2f 100644
--- a/include/asm-mips/mips-boards/maltaint.h
+++ b/include/asm-mips/mips-boards/maltaint.h
@@ -25,9 +25,63 @@
 #ifndef _MIPS_MALTAINT_H
 #define _MIPS_MALTAINT_H
 
-/* Number of IRQ supported on hw interrupt 0. */
-#define MALTAINT_END      16
+/*
+ * Interrupts 0..15 are used for Malta ISA compatible interrupts
+ */
+#define MALTA_INT_BASE		0
 
+/*
+ * Interrupts 16..23 are used for Malta CPU interrupts (nonEIC mode)
+ */
+#define MIPSCPU_INT_BASE	16
+
+/* CPU interrupt offsets */
+#define MIPSCPU_INT_SW0		0
+#define MIPSCPU_INT_SW1		1
+#define MIPSCPU_INT_MB0		2
+#define MIPSCPU_INT_I8259A	MIPSCPU_INT_MB0
+#define MIPSCPU_INT_MB1		3
+#define MIPSCPU_INT_SMI		MIPSCPU_INT_MB1
+#define MIPSCPU_INT_MB2		4
+#define MIPSCPU_INT_MB3		5
+#define MIPSCPU_INT_COREHI	MIPSCPU_INT_MB3
+#define MIPSCPU_INT_MB4		6
+#define MIPSCPU_INT_CORELO	MIPSCPU_INT_MB4
+#define MIPSCPU_INT_CPUCTR	7
+
+/*
+ * Interrupts 64..127 are used for Soc-it Classic interrupts
+ */
+#define MSC01C_INT_BASE		64
+
+/* SOC-it Classic interrupt offsets */
+#define MSC01C_INT_TMR		0
+#define MSC01C_INT_PCI		1
+
+/*
+ * Interrupts 64..127 are used for Soc-it EIC interrupts
+ */
+#define MSC01E_INT_BASE		64
+
+/* SOC-it EIC interrupt offsets */
+#define MSC01E_INT_SW0		1
+#define MSC01E_INT_SW1		2
+#define MSC01E_INT_MB0		3
+#define MSC01E_INT_I8259A	MSC01E_INT_MB0
+#define MSC01E_INT_MB1		4
+#define MSC01E_INT_SMI		MSC01E_INT_MB1
+#define MSC01E_INT_MB2		5
+#define MSC01E_INT_MB3		6
+#define MSC01E_INT_COREHI	MSC01E_INT_MB3
+#define MSC01E_INT_MB4		7
+#define MSC01E_INT_CORELO	MSC01E_INT_MB4
+#define MSC01E_INT_TMR		8
+#define MSC01E_INT_PCI		9
+#define MSC01E_INT_PERFCTR	10
+#define MSC01E_INT_CPUCTR	11
+
+#ifndef __ASSEMBLY__
 extern void maltaint_init(void);
+#endif
 
 #endif /* !(_MIPS_MALTAINT_H) */
diff --git a/include/asm-mips/mips-boards/msc01_pci.h b/include/asm-mips/mips-boards/msc01_pci.h
index 6b2a87a..8eaefb8 100644
--- a/include/asm-mips/mips-boards/msc01_pci.h
+++ b/include/asm-mips/mips-boards/msc01_pci.h
@@ -1,8 +1,9 @@
 /*
  * PCI Register definitions for the MIPS System Controller.
  *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2002, 2005  MIPS Technologies, Inc.  All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
  *
  * 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
@@ -29,22 +30,22 @@
 #define MSC01_PCI_CFGADDR_OFS		0x0610
 #define MSC01_PCI_CFGDATA_OFS		0x0618
 #define MSC01_PCI_IACK_OFS		0x0620
-#define MSC01_PCI_HEAD0_OFS		0x2000  /* DevID, VendorID */
-#define MSC01_PCI_HEAD1_OFS		0x2008  /* Status, Command */
-#define MSC01_PCI_HEAD2_OFS		0x2010  /* Class code, RevID */
-#define MSC01_PCI_HEAD3_OFS		0x2018  /* bist, header, latency */
-#define MSC01_PCI_HEAD4_OFS		0x2020  /* BAR 0 */
-#define MSC01_PCI_HEAD5_OFS		0x2028  /* BAR 1 */
-#define MSC01_PCI_HEAD6_OFS		0x2030  /* BAR 2 */
-#define MSC01_PCI_HEAD7_OFS		0x2038  /* BAR 3 */
-#define MSC01_PCI_HEAD8_OFS		0x2040  /* BAR 4 */
-#define MSC01_PCI_HEAD9_OFS		0x2048  /* BAR 5 */
-#define MSC01_PCI_HEAD10_OFS		0x2050  /* CardBus CIS Ptr */
-#define MSC01_PCI_HEAD11_OFS		0x2058  /* SubSystem ID, -VendorID */
-#define MSC01_PCI_HEAD12_OFS		0x2060  /* ROM BAR */
-#define MSC01_PCI_HEAD13_OFS		0x2068  /* Capabilities ptr */
-#define MSC01_PCI_HEAD14_OFS		0x2070  /* reserved */
-#define MSC01_PCI_HEAD15_OFS		0x2078  /* Maxl, ming, intpin, int */
+#define MSC01_PCI_HEAD0_OFS		0x2000	/* DevID, VendorID */
+#define MSC01_PCI_HEAD1_OFS		0x2008	/* Status, Command */
+#define MSC01_PCI_HEAD2_OFS		0x2010	/* Class code, RevID */
+#define MSC01_PCI_HEAD3_OFS		0x2018	/* bist, header, latency */
+#define MSC01_PCI_HEAD4_OFS		0x2020	/* BAR 0 */
+#define MSC01_PCI_HEAD5_OFS		0x2028	/* BAR 1 */
+#define MSC01_PCI_HEAD6_OFS		0x2030	/* BAR 2 */
+#define MSC01_PCI_HEAD7_OFS		0x2038	/* BAR 3 */
+#define MSC01_PCI_HEAD8_OFS		0x2040	/* BAR 4 */
+#define MSC01_PCI_HEAD9_OFS		0x2048	/* BAR 5 */
+#define MSC01_PCI_HEAD10_OFS		0x2050	/* CardBus CIS Ptr */
+#define MSC01_PCI_HEAD11_OFS		0x2058	/* SubSystem ID, -VendorID */
+#define MSC01_PCI_HEAD12_OFS		0x2060	/* ROM BAR */
+#define MSC01_PCI_HEAD13_OFS		0x2068	/* Capabilities ptr */
+#define MSC01_PCI_HEAD14_OFS		0x2070	/* reserved */
+#define MSC01_PCI_HEAD15_OFS		0x2078	/* Maxl, ming, intpin, int */
 #define MSC01_PCI_BAR0_OFS		0x2220
 #define MSC01_PCI_CFG_OFS		0x2380
 #define MSC01_PCI_SWAP_OFS		0x2388
@@ -86,73 +87,73 @@
 #define MSC01_PCI_P2SCMAPL_MAP_SHF	24
 #define MSC01_PCI_P2SCMAPL_MAP_MSK	0xff000000
 
-#define MSC01_PCI_INTCFG_RST_SHF        10
-#define MSC01_PCI_INTCFG_RST_MSK        0x00000400
-#define MSC01_PCI_INTCFG_RST_BIT        0x00000400
-#define MSC01_PCI_INTCFG_MWE_SHF        9
-#define MSC01_PCI_INTCFG_MWE_MSK        0x00000200
-#define MSC01_PCI_INTCFG_MWE_BIT        0x00000200
-#define MSC01_PCI_INTCFG_DTO_SHF        8
-#define MSC01_PCI_INTCFG_DTO_MSK        0x00000100
-#define MSC01_PCI_INTCFG_DTO_BIT        0x00000100
-#define MSC01_PCI_INTCFG_MA_SHF         7
-#define MSC01_PCI_INTCFG_MA_MSK         0x00000080
-#define MSC01_PCI_INTCFG_MA_BIT         0x00000080
-#define MSC01_PCI_INTCFG_TA_SHF         6
-#define MSC01_PCI_INTCFG_TA_MSK         0x00000040
-#define MSC01_PCI_INTCFG_TA_BIT         0x00000040
-#define MSC01_PCI_INTCFG_RTY_SHF        5
-#define MSC01_PCI_INTCFG_RTY_MSK        0x00000020
-#define MSC01_PCI_INTCFG_RTY_BIT        0x00000020
-#define MSC01_PCI_INTCFG_MWP_SHF        4
-#define MSC01_PCI_INTCFG_MWP_MSK        0x00000010
-#define MSC01_PCI_INTCFG_MWP_BIT        0x00000010
-#define MSC01_PCI_INTCFG_MRP_SHF        3
-#define MSC01_PCI_INTCFG_MRP_MSK        0x00000008
-#define MSC01_PCI_INTCFG_MRP_BIT        0x00000008
-#define MSC01_PCI_INTCFG_SWP_SHF        2
-#define MSC01_PCI_INTCFG_SWP_MSK        0x00000004
-#define MSC01_PCI_INTCFG_SWP_BIT        0x00000004
-#define MSC01_PCI_INTCFG_SRP_SHF        1
-#define MSC01_PCI_INTCFG_SRP_MSK        0x00000002
-#define MSC01_PCI_INTCFG_SRP_BIT        0x00000002
-#define MSC01_PCI_INTCFG_SE_SHF         0
-#define MSC01_PCI_INTCFG_SE_MSK         0x00000001
-#define MSC01_PCI_INTCFG_SE_BIT         0x00000001
+#define MSC01_PCI_INTCFG_RST_SHF	10
+#define MSC01_PCI_INTCFG_RST_MSK	0x00000400
+#define MSC01_PCI_INTCFG_RST_BIT	0x00000400
+#define MSC01_PCI_INTCFG_MWE_SHF	9
+#define MSC01_PCI_INTCFG_MWE_MSK	0x00000200
+#define MSC01_PCI_INTCFG_MWE_BIT	0x00000200
+#define MSC01_PCI_INTCFG_DTO_SHF	8
+#define MSC01_PCI_INTCFG_DTO_MSK	0x00000100
+#define MSC01_PCI_INTCFG_DTO_BIT	0x00000100
+#define MSC01_PCI_INTCFG_MA_SHF		7
+#define MSC01_PCI_INTCFG_MA_MSK		0x00000080
+#define MSC01_PCI_INTCFG_MA_BIT		0x00000080
+#define MSC01_PCI_INTCFG_TA_SHF		6
+#define MSC01_PCI_INTCFG_TA_MSK		0x00000040
+#define MSC01_PCI_INTCFG_TA_BIT		0x00000040
+#define MSC01_PCI_INTCFG_RTY_SHF	5
+#define MSC01_PCI_INTCFG_RTY_MSK	0x00000020
+#define MSC01_PCI_INTCFG_RTY_BIT	0x00000020
+#define MSC01_PCI_INTCFG_MWP_SHF	4
+#define MSC01_PCI_INTCFG_MWP_MSK	0x00000010
+#define MSC01_PCI_INTCFG_MWP_BIT	0x00000010
+#define MSC01_PCI_INTCFG_MRP_SHF	3
+#define MSC01_PCI_INTCFG_MRP_MSK	0x00000008
+#define MSC01_PCI_INTCFG_MRP_BIT	0x00000008
+#define MSC01_PCI_INTCFG_SWP_SHF	2
+#define MSC01_PCI_INTCFG_SWP_MSK	0x00000004
+#define MSC01_PCI_INTCFG_SWP_BIT	0x00000004
+#define MSC01_PCI_INTCFG_SRP_SHF	1
+#define MSC01_PCI_INTCFG_SRP_MSK	0x00000002
+#define MSC01_PCI_INTCFG_SRP_BIT	0x00000002
+#define MSC01_PCI_INTCFG_SE_SHF		0
+#define MSC01_PCI_INTCFG_SE_MSK		0x00000001
+#define MSC01_PCI_INTCFG_SE_BIT		0x00000001
 
-#define MSC01_PCI_INTSTAT_RST_SHF       10
-#define MSC01_PCI_INTSTAT_RST_MSK       0x00000400
-#define MSC01_PCI_INTSTAT_RST_BIT       0x00000400
-#define MSC01_PCI_INTSTAT_MWE_SHF       9
-#define MSC01_PCI_INTSTAT_MWE_MSK       0x00000200
-#define MSC01_PCI_INTSTAT_MWE_BIT       0x00000200
-#define MSC01_PCI_INTSTAT_DTO_SHF       8
-#define MSC01_PCI_INTSTAT_DTO_MSK       0x00000100
-#define MSC01_PCI_INTSTAT_DTO_BIT       0x00000100
-#define MSC01_PCI_INTSTAT_MA_SHF        7
-#define MSC01_PCI_INTSTAT_MA_MSK        0x00000080
-#define MSC01_PCI_INTSTAT_MA_BIT        0x00000080
-#define MSC01_PCI_INTSTAT_TA_SHF        6
-#define MSC01_PCI_INTSTAT_TA_MSK        0x00000040
-#define MSC01_PCI_INTSTAT_TA_BIT        0x00000040
-#define MSC01_PCI_INTSTAT_RTY_SHF       5
-#define MSC01_PCI_INTSTAT_RTY_MSK       0x00000020
-#define MSC01_PCI_INTSTAT_RTY_BIT       0x00000020
-#define MSC01_PCI_INTSTAT_MWP_SHF       4
-#define MSC01_PCI_INTSTAT_MWP_MSK       0x00000010
-#define MSC01_PCI_INTSTAT_MWP_BIT       0x00000010
-#define MSC01_PCI_INTSTAT_MRP_SHF       3
-#define MSC01_PCI_INTSTAT_MRP_MSK       0x00000008
-#define MSC01_PCI_INTSTAT_MRP_BIT       0x00000008
-#define MSC01_PCI_INTSTAT_SWP_SHF       2
-#define MSC01_PCI_INTSTAT_SWP_MSK       0x00000004
-#define MSC01_PCI_INTSTAT_SWP_BIT       0x00000004
-#define MSC01_PCI_INTSTAT_SRP_SHF       1
-#define MSC01_PCI_INTSTAT_SRP_MSK       0x00000002
-#define MSC01_PCI_INTSTAT_SRP_BIT       0x00000002
-#define MSC01_PCI_INTSTAT_SE_SHF        0
-#define MSC01_PCI_INTSTAT_SE_MSK        0x00000001
-#define MSC01_PCI_INTSTAT_SE_BIT        0x00000001
+#define MSC01_PCI_INTSTAT_RST_SHF	10
+#define MSC01_PCI_INTSTAT_RST_MSK	0x00000400
+#define MSC01_PCI_INTSTAT_RST_BIT	0x00000400
+#define MSC01_PCI_INTSTAT_MWE_SHF	9
+#define MSC01_PCI_INTSTAT_MWE_MSK	0x00000200
+#define MSC01_PCI_INTSTAT_MWE_BIT	0x00000200
+#define MSC01_PCI_INTSTAT_DTO_SHF	8
+#define MSC01_PCI_INTSTAT_DTO_MSK	0x00000100
+#define MSC01_PCI_INTSTAT_DTO_BIT	0x00000100
+#define MSC01_PCI_INTSTAT_MA_SHF	7
+#define MSC01_PCI_INTSTAT_MA_MSK	0x00000080
+#define MSC01_PCI_INTSTAT_MA_BIT	0x00000080
+#define MSC01_PCI_INTSTAT_TA_SHF	6
+#define MSC01_PCI_INTSTAT_TA_MSK	0x00000040
+#define MSC01_PCI_INTSTAT_TA_BIT	0x00000040
+#define MSC01_PCI_INTSTAT_RTY_SHF	5
+#define MSC01_PCI_INTSTAT_RTY_MSK	0x00000020
+#define MSC01_PCI_INTSTAT_RTY_BIT	0x00000020
+#define MSC01_PCI_INTSTAT_MWP_SHF	4
+#define MSC01_PCI_INTSTAT_MWP_MSK	0x00000010
+#define MSC01_PCI_INTSTAT_MWP_BIT	0x00000010
+#define MSC01_PCI_INTSTAT_MRP_SHF	3
+#define MSC01_PCI_INTSTAT_MRP_MSK	0x00000008
+#define MSC01_PCI_INTSTAT_MRP_BIT	0x00000008
+#define MSC01_PCI_INTSTAT_SWP_SHF	2
+#define MSC01_PCI_INTSTAT_SWP_MSK	0x00000004
+#define MSC01_PCI_INTSTAT_SWP_BIT	0x00000004
+#define MSC01_PCI_INTSTAT_SRP_SHF	1
+#define MSC01_PCI_INTSTAT_SRP_MSK	0x00000002
+#define MSC01_PCI_INTSTAT_SRP_BIT	0x00000002
+#define MSC01_PCI_INTSTAT_SE_SHF	0
+#define MSC01_PCI_INTSTAT_SE_MSK	0x00000001
+#define MSC01_PCI_INTSTAT_SE_BIT	0x00000001
 
 #define MSC01_PCI_CFGADDR_BNUM_SHF	16
 #define MSC01_PCI_CFGADDR_BNUM_MSK	0x00ff0000
@@ -167,29 +168,29 @@
 #define MSC01_PCI_CFGDATA_DATA_MSK	0xffffffff
 
 /* The defines below are ONLY valid for a MEM bar! */
-#define MSC01_PCI_BAR0_SIZE_SHF	        4
-#define MSC01_PCI_BAR0_SIZE_MSK	        0xfffffff0
-#define MSC01_PCI_BAR0_P_SHF	        3
-#define MSC01_PCI_BAR0_P_MSK	        0x00000008
-#define MSC01_PCI_BAR0_P_BIT	        MSC01_PCI_BAR0_P_MSK
-#define MSC01_PCI_BAR0_D_SHF	        1
-#define MSC01_PCI_BAR0_D_MSK	        0x00000006
-#define MSC01_PCI_BAR0_T_SHF	        0
-#define MSC01_PCI_BAR0_T_MSK	        0x00000001
-#define MSC01_PCI_BAR0_T_BIT	        MSC01_PCI_BAR0_T_MSK
+#define MSC01_PCI_BAR0_SIZE_SHF		4
+#define MSC01_PCI_BAR0_SIZE_MSK		0xfffffff0
+#define MSC01_PCI_BAR0_P_SHF		3
+#define MSC01_PCI_BAR0_P_MSK		0x00000008
+#define MSC01_PCI_BAR0_P_BIT		MSC01_PCI_BAR0_P_MSK
+#define MSC01_PCI_BAR0_D_SHF		1
+#define MSC01_PCI_BAR0_D_MSK		0x00000006
+#define MSC01_PCI_BAR0_T_SHF		0
+#define MSC01_PCI_BAR0_T_MSK		0x00000001
+#define MSC01_PCI_BAR0_T_BIT		MSC01_PCI_BAR0_T_MSK
 
 
-#define MSC01_PCI_CFG_RA_SHF	        17
-#define MSC01_PCI_CFG_RA_MSK	        0x00020000
-#define MSC01_PCI_CFG_RA_BIT	        MSC01_PCI_CFG_RA_MSK
-#define MSC01_PCI_CFG_G_SHF	        16
-#define MSC01_PCI_CFG_G_MSK	        0x00010000
-#define MSC01_PCI_CFG_G_BIT	        MSC01_PCI_CFG_G_MSK
-#define MSC01_PCI_CFG_EN_SHF	        15
-#define MSC01_PCI_CFG_EN_MSK	        0x00008000
-#define MSC01_PCI_CFG_EN_BIT	        MSC01_PCI_CFG_EN_MSK
-#define MSC01_PCI_CFG_MAXRTRY_SHF       0
-#define MSC01_PCI_CFG_MAXRTRY_MSK       0x000000ff
+#define MSC01_PCI_CFG_RA_SHF		17
+#define MSC01_PCI_CFG_RA_MSK		0x00020000
+#define MSC01_PCI_CFG_RA_BIT		MSC01_PCI_CFG_RA_MSK
+#define MSC01_PCI_CFG_G_SHF		16
+#define MSC01_PCI_CFG_G_MSK		0x00010000
+#define MSC01_PCI_CFG_G_BIT		MSC01_PCI_CFG_G_MSK
+#define MSC01_PCI_CFG_EN_SHF		15
+#define MSC01_PCI_CFG_EN_MSK		0x00008000
+#define MSC01_PCI_CFG_EN_BIT		MSC01_PCI_CFG_EN_MSK
+#define MSC01_PCI_CFG_MAXRTRY_SHF	0
+#define MSC01_PCI_CFG_MAXRTRY_MSK	0x00000fff
 
 #define MSC01_PCI_SWAP_IO_SHF		18
 #define MSC01_PCI_SWAP_IO_MSK		0x000c0000
@@ -206,7 +207,7 @@
  * FIXME - are these macros specific to Malta and co or to the MSC?  If the
  * latter, they should be moved elsewhere.
  */
-#define MIPS_MSC01_PCI_REG_BASE	0x1bd00000
+#define MIPS_MSC01_PCI_REG_BASE		0x1bd00000
 
 extern unsigned long _pcictrl_msc;
 
@@ -219,19 +220,19 @@
  * Registers absolute addresses
  */
 
-#define MSC01_PCI_ID            (MSC01_PCI_REG_BASE + MSC01_PCI_ID_OFS)
-#define MSC01_PCI_SC2PMBASL     (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMBASL_OFS)
-#define MSC01_PCI_SC2PMMSKL     (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMMSKL_OFS)
-#define MSC01_PCI_SC2PMMAPL     (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMMAPL_OFS)
-#define MSC01_PCI_SC2PIOBASL    (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOBASL_OFS)
-#define MSC01_PCI_SC2PIOMSKL    (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOMSKL_OFS)
-#define MSC01_PCI_SC2PIOMAPL    (MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOMAPL_OFS)
-#define MSC01_PCI_P2SCMSKL      (MSC01_PCI_REG_BASE + MSC01_PCI_P2SCMSKL_OFS)
-#define MSC01_PCI_P2SCMAPL      (MSC01_PCI_REG_BASE + MSC01_PCI_P2SCMAPL_OFS)
-#define MSC01_PCI_INTCFG        (MSC01_PCI_REG_BASE + MSC01_PCI_INTCFG_OFS)
-#define MSC01_PCI_INTSTAT       (MSC01_PCI_REG_BASE + MSC01_PCI_INTSTAT_OFS)
-#define MSC01_PCI_CFGADDR       (MSC01_PCI_REG_BASE + MSC01_PCI_CFGADDR_OFS)
-#define MSC01_PCI_CFGDATA       (MSC01_PCI_REG_BASE + MSC01_PCI_CFGDATA_OFS)
+#define MSC01_PCI_ID		(MSC01_PCI_REG_BASE + MSC01_PCI_ID_OFS)
+#define MSC01_PCI_SC2PMBASL	(MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMBASL_OFS)
+#define MSC01_PCI_SC2PMMSKL	(MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMMSKL_OFS)
+#define MSC01_PCI_SC2PMMAPL	(MSC01_PCI_REG_BASE + MSC01_PCI_SC2PMMAPL_OFS)
+#define MSC01_PCI_SC2PIOBASL	(MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOBASL_OFS)
+#define MSC01_PCI_SC2PIOMSKL	(MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOMSKL_OFS)
+#define MSC01_PCI_SC2PIOMAPL	(MSC01_PCI_REG_BASE + MSC01_PCI_SC2PIOMAPL_OFS)
+#define MSC01_PCI_P2SCMSKL	(MSC01_PCI_REG_BASE + MSC01_PCI_P2SCMSKL_OFS)
+#define MSC01_PCI_P2SCMAPL	(MSC01_PCI_REG_BASE + MSC01_PCI_P2SCMAPL_OFS)
+#define MSC01_PCI_INTCFG	(MSC01_PCI_REG_BASE + MSC01_PCI_INTCFG_OFS)
+#define MSC01_PCI_INTSTAT	(MSC01_PCI_REG_BASE + MSC01_PCI_INTSTAT_OFS)
+#define MSC01_PCI_CFGADDR	(MSC01_PCI_REG_BASE + MSC01_PCI_CFGADDR_OFS)
+#define MSC01_PCI_CFGDATA	(MSC01_PCI_REG_BASE + MSC01_PCI_CFGDATA_OFS)
 #define MSC01_PCI_IACK		(MSC01_PCI_REG_BASE + MSC01_PCI_IACK_OFS)
 #define MSC01_PCI_HEAD0		(MSC01_PCI_REG_BASE + MSC01_PCI_HEAD0_OFS)
 #define MSC01_PCI_HEAD1		(MSC01_PCI_REG_BASE + MSC01_PCI_HEAD1_OFS)
@@ -248,7 +249,7 @@
 #define MSC01_PCI_HEAD12	(MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS)
 #define MSC01_PCI_HEAD13	(MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS)
 #define MSC01_PCI_HEAD14	(MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS)
-#define MSC01_PCI_HEAD15        (MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS)
+#define MSC01_PCI_HEAD15	(MSC01_PCI_REG_BASE + MSC01_PCI_HEAD11_OFS)
 #define MSC01_PCI_BAR0		(MSC01_PCI_REG_BASE + MSC01_PCI_BAR0_OFS)
 #define MSC01_PCI_CFG		(MSC01_PCI_REG_BASE + MSC01_PCI_CFG_OFS)
 #define MSC01_PCI_SWAP		(MSC01_PCI_REG_BASE + MSC01_PCI_SWAP_OFS)
diff --git a/include/asm-mips/mips-boards/sim.h b/include/asm-mips/mips-boards/sim.h
new file mode 100644
index 0000000..acb7c23
--- /dev/null
+++ b/include/asm-mips/mips-boards/sim.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ *
+ */
+
+#ifndef _ASM_MIPS_BOARDS_SIM_H
+#define _ASM_MIPS_BOARDS_SIM_H
+
+#define STATS_ON        1
+#define STATS_OFF       2
+#define STATS_CLEAR     3
+#define STATS_DUMP      4
+#define TRACE_ON		5
+#define TRACE_OFF       6
+
+
+#define simcfg(code)						\
+({					   \
+	__asm__  __volatile__( \
+        "sltiu $0,$0, %0" \
+		::"i"(code)					\
+		); \
+})
+
+
+
+#endif
diff --git a/include/asm-mips/mips-boards/simint.h b/include/asm-mips/mips-boards/simint.h
new file mode 100644
index 0000000..4952e0b
--- /dev/null
+++ b/include/asm-mips/mips-boards/simint.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute 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 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.
+ */
+#ifndef _MIPS_SIMINT_H
+#define _MIPS_SIMINT_H
+
+
+#define SIM_INT_BASE		0
+#define MIPSCPU_INT_MB0		2
+#define MIPSCPU_INT_BASE	16
+#define MIPS_CPU_TIMER_IRQ	7
+
+
+#define MIPSCPU_INT_CPUCTR	7
+
+#define MSC01E_INT_BASE		64
+
+#define MIPSCPU_INT_CPUCTR	7
+#define MSC01E_INT_CPUCTR	11
+
+#endif
diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
new file mode 100644
index 0000000..a669c07
--- /dev/null
+++ b/include/asm-mips/mipsmtregs.h
@@ -0,0 +1,391 @@
+/*
+ * MT regs definitions, follows on from mipsregs.h
+ * Copyright (C) 2004 - 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Elizabeth Clarke et. al.
+ *
+ */
+#ifndef _ASM_MIPSMTREGS_H
+#define _ASM_MIPSMTREGS_H
+
+#include <asm/mipsregs.h>
+#include <asm/war.h>
+
+#ifndef __ASSEMBLY__
+
+/*
+ * C macros
+ */
+
+#define read_c0_mvpcontrol()		__read_32bit_c0_register($0, 1)
+#define write_c0_mvpcontrol(val)	__write_32bit_c0_register($0, 1, val)
+
+#define read_c0_mvpconf0()		__read_32bit_c0_register($0, 2)
+#define read_c0_mvpconf1()		__read_32bit_c0_register($0, 3)
+
+#define read_c0_vpecontrol()		__read_32bit_c0_register($1, 1)
+#define write_c0_vpecontrol(val)	__write_32bit_c0_register($1, 1, val)
+
+#define read_c0_vpeconf0()		__read_32bit_c0_register($1, 2)
+#define write_c0_vpeconf0(val)		__write_32bit_c0_register($1, 2, val)
+
+#define read_c0_tcstatus()		__read_32bit_c0_register($2, 1)
+#define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val)
+
+#define read_c0_tcbind()		__read_32bit_c0_register($2, 2)
+
+#define read_c0_tccontext()		__read_32bit_c0_register($2, 5)
+#define write_c0_tccontext(val)		__write_32bit_c0_register($2, 5, val)
+
+#else /* Assembly */
+/*
+ * Macros for use in assembly language code
+ */
+
+#define CP0_MVPCONTROL		$0,1
+#define CP0_MVPCONF0		$0,2
+#define CP0_MVPCONF1		$0,3
+#define CP0_VPECONTROL		$1,1
+#define CP0_VPECONF0		$1,2
+#define CP0_VPECONF1		$1,3
+#define CP0_YQMASK		$1,4
+#define CP0_VPESCHEDULE	$1,5
+#define CP0_VPESCHEFBK		$1,6
+#define CP0_TCSTATUS		$2,1
+#define CP0_TCBIND		$2,2
+#define CP0_TCRESTART		$2,3
+#define CP0_TCHALT		$2,4
+#define CP0_TCCONTEXT		$2,5
+#define CP0_TCSCHEDULE		$2,6
+#define CP0_TCSCHEFBK		$2,7
+#define CP0_SRSCONF0		$6,1
+#define CP0_SRSCONF1		$6,2
+#define CP0_SRSCONF2		$6,3
+#define CP0_SRSCONF3		$6,4
+#define CP0_SRSCONF4		$6,5
+
+#endif
+
+/* MVPControl fields */
+#define MVPCONTROL_EVP		(_ULCAST_(1))
+
+#define MVPCONTROL_VPC_SHIFT	1
+#define MVPCONTROL_VPC		(_ULCAST_(1) << MVPCONTROL_VPC_SHIFT)
+
+#define MVPCONTROL_STLB_SHIFT	2
+#define MVPCONTROL_STLB		(_ULCAST_(1) << MVPCONTROL_STLB_SHIFT)
+
+
+/* MVPConf0 fields */
+#define MVPCONF0_PTC_SHIFT	0
+#define MVPCONF0_PTC		( _ULCAST_(0xff))
+#define MVPCONF0_PVPE_SHIFT	10
+#define MVPCONF0_PVPE		( _ULCAST_(0xf) << MVPCONF0_PVPE_SHIFT)
+#define MVPCONF0_TCA_SHIFT	15
+#define MVPCONF0_TCA		( _ULCAST_(1) << MVPCONF0_TCA_SHIFT)
+#define MVPCONF0_PTLBE_SHIFT	16
+#define MVPCONF0_PTLBE		(_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT)
+#define MVPCONF0_TLBS_SHIFT	29
+#define MVPCONF0_TLBS		(_ULCAST_(1) << MVPCONF0_TLBS_SHIFT)
+#define MVPCONF0_M_SHIFT	31
+#define MVPCONF0_M		(_ULCAST_(0x1) << MVPCONF0_M_SHIFT)
+
+
+/* config3 fields */
+#define CONFIG3_MT_SHIFT	2
+#define CONFIG3_MT		(_ULCAST_(1) << CONFIG3_MT_SHIFT)
+
+
+/* VPEControl fields (per VPE) */
+#define VPECONTROL_TARGTC	(_ULCAST_(0xff))
+
+#define VPECONTROL_TE_SHIFT	15
+#define VPECONTROL_TE		(_ULCAST_(1) << VPECONTROL_TE_SHIFT)
+#define VPECONTROL_EXCPT_SHIFT	16
+#define VPECONTROL_EXCPT	(_ULCAST_(0x7) << VPECONTROL_EXCPT_SHIFT)
+
+/* Thread Exception Codes for EXCPT field */
+#define THREX_TU		0
+#define THREX_TO		1
+#define THREX_IYQ		2
+#define THREX_GSX		3
+#define THREX_YSCH		4
+#define THREX_GSSCH		5
+
+#define VPECONTROL_GSI_SHIFT	20
+#define VPECONTROL_GSI		(_ULCAST_(1) << VPECONTROL_GSI_SHIFT)
+#define VPECONTROL_YSI_SHIFT	21
+#define VPECONTROL_YSI		(_ULCAST_(1) << VPECONTROL_YSI_SHIFT)
+
+/* VPEConf0 fields (per VPE) */
+#define VPECONF0_VPA_SHIFT	0
+#define VPECONF0_VPA		(_ULCAST_(1) << VPECONF0_VPA_SHIFT)
+#define VPECONF0_MVP_SHIFT	1
+#define VPECONF0_MVP		(_ULCAST_(1) << VPECONF0_MVP_SHIFT)
+#define VPECONF0_XTC_SHIFT	21
+#define VPECONF0_XTC		(_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)
+
+/* TCStatus fields (per TC) */
+#define TCSTATUS_TASID		(_ULCAST_(0xff))
+#define TCSTATUS_IXMT_SHIFT	10
+#define TCSTATUS_IXMT		(_ULCAST_(1) << TCSTATUS_IXMT_SHIFT)
+#define TCSTATUS_TKSU_SHIFT	11
+#define TCSTATUS_TKSU		(_ULCAST_(3) << TCSTATUS_TKSU_SHIFT)
+#define TCSTATUS_A_SHIFT	13
+#define TCSTATUS_A		(_ULCAST_(1) << TCSTATUS_A_SHIFT)
+#define TCSTATUS_DA_SHIFT	15
+#define TCSTATUS_DA		(_ULCAST_(1) << TCSTATUS_DA_SHIFT)
+#define TCSTATUS_DT_SHIFT	20
+#define TCSTATUS_DT		(_ULCAST_(1) << TCSTATUS_DT_SHIFT)
+#define TCSTATUS_TDS_SHIFT	21
+#define TCSTATUS_TDS		(_ULCAST_(1) << TCSTATUS_TDS_SHIFT)
+#define TCSTATUS_TSST_SHIFT	22
+#define TCSTATUS_TSST		(_ULCAST_(1) << TCSTATUS_TSST_SHIFT)
+#define TCSTATUS_RNST_SHIFT	23
+#define TCSTATUS_RNST		(_ULCAST_(3) << TCSTATUS_RNST_SHIFT)
+/* Codes for RNST */
+#define TC_RUNNING		0
+#define TC_WAITING		1
+#define TC_YIELDING		2
+#define TC_GATED		3
+
+#define TCSTATUS_TMX_SHIFT	27
+#define TCSTATUS_TMX		(_ULCAST_(1) << TCSTATUS_TMX_SHIFT)
+/* TCStatus TCU bits can use same definitions/offsets as CU bits in Status */
+
+/* TCBind */
+#define TCBIND_CURVPE_SHIFT	0
+#define TCBIND_CURVPE		(_ULCAST_(0xf))
+
+#define TCBIND_CURTC_SHIFT	21
+
+#define TCBIND_CURTC		(_ULCAST_(0xff) << TCBIND_CURTC_SHIFT)
+
+/* TCHalt */
+#define TCHALT_H		(_ULCAST_(1))
+
+#ifndef __ASSEMBLY__
+
+extern void mips_mt_regdump(void);
+
+static inline unsigned int dvpe(void)
+{
+	int res = 0;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41610001		# dvpe $1		\n"
+	"	move	%0, $1						\n"
+	"	ehb							\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+static inline void __raw_evpe(void)
+{
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41600021		# evpe			\n"
+	"	ehb							\n"
+	"	.set	pop						\n");
+}
+
+/* Enable multiMT if previous suggested it should be.
+   EMT_ENABLE to force */
+
+#define EVPE_ENABLE MVPCONTROL_EVP
+
+static inline void evpe(int previous)
+{
+	if ((previous & MVPCONTROL_EVP))
+		__raw_evpe();
+}
+
+static inline unsigned int dmt(void)
+{
+	int res;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	mips32r2					\n"
+	"	.set	noat						\n"
+	"	.word	0x41610BC1			# dmt $1	\n"
+	"	ehb							\n"
+	"	move	%0, $1						\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+static inline void __raw_emt(void)
+{
+	__asm__ __volatile__(
+	"	.set	noreorder					\n"
+	"	.set	mips32r2					\n"
+	"	emt							\n"
+	"	ehb							\n"
+	"	.set	mips0						\n"
+	"	.set	reorder");
+}
+
+/* enable multiVPE if previous suggested it should be.
+   EVPE_ENABLE to force */
+
+#define EMT_ENABLE VPECONTROL_TE
+
+static inline void emt(int previous)
+{
+	if ((previous & EMT_ENABLE))
+		__raw_emt();
+}
+
+static inline void ehb(void)
+{
+	__asm__ __volatile__(
+	"	.set	mips32r2				\n"
+	"	ehb						\n"
+	"	.set	mips0					\n");
+}
+
+#define mftc0(rt,sel)							\
+({									\
+	 unsigned long  __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	# mftc0	$1, $" #rt ", " #sel "			\n"	\
+	"	.word	0x41000800 | (" #rt " << 16) | " #sel "	\n"	\
+	"	move	%0, $1					\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mftgpr(rt)							\
+({									\
+	unsigned long __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	mftgpr	%0," #rt "				\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mftr(rt,u,sel)							\
+({									\
+	unsigned long __res;						\
+									\
+	__asm__ __volatile__(						\
+	".set noat\n\t"							\
+	"mftr\t%0, " #rt ", " #u ", " #sel "\n\t"			\
+	".set at\n\t"							\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mttgpr(rd,v)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttgpr $1, " #rd "				\n"	\
+	"	.word	0x41810020 | (" #rd " << 11)		\n"	\
+	"	.set	pop					\n"	\
+	: : "r" (v));							\
+} while (0)
+
+#define mttc0(rd,sel,v)							\
+({									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttc0 %0," #rd ", " #sel "			\n"	\
+	"	.word	0x41810000 | (" #rd " << 11) | " #sel "	\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (v));							\
+})
+
+
+#define mttr(rd,u,sel,v)						\
+({									\
+	__asm__ __volatile__(						\
+	"mttr	%0," #rd ", " #u ", " #sel				\
+	: : "r" (v));							\
+})
+
+
+#define settc(tc)							\
+do {									\
+	write_c0_vpecontrol((read_c0_vpecontrol()&~VPECONTROL_TARGTC) | (tc)); \
+	ehb();								\
+} while (0)
+
+
+/* you *must* set the target tc (settc) before trying to use these */
+#define read_vpe_c0_vpecontrol()	mftc0(1, 1)
+#define write_vpe_c0_vpecontrol(val)	mttc0(1, 1, val)
+#define read_vpe_c0_vpeconf0()		mftc0(1, 2)
+#define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val)
+#define read_vpe_c0_status()		mftc0(12, 0)
+#define write_vpe_c0_status(val)	mttc0(12, 0, val)
+#define read_vpe_c0_cause()		mftc0(13, 0)
+#define write_vpe_c0_cause(val)		mttc0(13, 0, val)
+#define read_vpe_c0_config()		mftc0(16, 0)
+#define write_vpe_c0_config(val)	mttc0(16, 0, val)
+#define read_vpe_c0_config1()		mftc0(16, 1)
+#define write_vpe_c0_config1(val)	mttc0(16, 1, val)
+#define read_vpe_c0_config7()		mftc0(16, 7)
+#define write_vpe_c0_config7(val)	mttc0(16, 7, val)
+#define read_vpe_c0_ebase()		mftc0(15,1)
+#define write_vpe_c0_ebase(val)		mttc0(15, 1, val)
+#define write_vpe_c0_compare(val)	mttc0(11, 0, val)
+
+
+/* TC */
+#define read_tc_c0_tcstatus()		mftc0(2, 1)
+#define write_tc_c0_tcstatus(val)	mttc0(2,1,val)
+#define read_tc_c0_tcbind()		mftc0(2, 2)
+#define write_tc_c0_tcbind(val)		mttc0(2,2,val)
+#define read_tc_c0_tcrestart()		mftc0(2, 3)
+#define write_tc_c0_tcrestart(val)	mttc0(2,3,val)
+#define read_tc_c0_tchalt()		mftc0(2, 4)
+#define write_tc_c0_tchalt(val)		mttc0(2,4,val)
+#define read_tc_c0_tccontext()		mftc0(2, 5)
+#define write_tc_c0_tccontext(val)	mttc0(2,5,val)
+
+/* GPR */
+#define read_tc_gpr_sp()		mftgpr(29)
+#define write_tc_gpr_sp(val)		mttgpr(29, val)
+#define read_tc_gpr_gp()		mftgpr(28)
+#define write_tc_gpr_gp(val)		mttgpr(28, val)
+
+__BUILD_SET_C0(mvpcontrol)
+
+#endif /* Not __ASSEMBLY__ */
+
+#endif
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 2197aa4..80370e0 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -8,7 +8,7 @@
  * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- * Copyright (C) 2003  Maciej W. Rozycki
+ * Copyright (C) 2003, 2004  Maciej W. Rozycki
  */
 #ifndef _ASM_MIPSREGS_H
 #define _ASM_MIPSREGS_H
@@ -96,6 +96,16 @@
 #define CP0_S1_INTCONTROL $20
 
 /*
+ * Coprocessor 0 Set 2 register names
+ */
+#define CP0_S2_SRSCTL	  $12	/* MIPSR2 */
+
+/*
+ * Coprocessor 0 Set 3 register names
+ */
+#define CP0_S3_SRSMAP	  $12	/* MIPSR2 */
+
+/*
  *  TX39 Series
  */
 #define CP0_TX39_CACHE	$7
@@ -281,6 +291,11 @@
 #define ST0_DL			(_ULCAST_(1) << 24)
 
 /*
+ * Enable the MIPS DSP ASE
+ */
+#define ST0_MX			0x01000000
+
+/*
  * Bitfields in the TX39 family CP0 Configuration Register 3
  */
 #define TX39_CONF_ICS_SHIFT	19
@@ -433,6 +448,14 @@
 #define R5K_CONF_SE		(_ULCAST_(1) << 12)
 #define R5K_CONF_SS		(_ULCAST_(3) << 20)
 
+/* Bits specific to the RM7000.  */
+#define RM7K_CONF_SE		(_ULCAST_(1) <<  3)
+#define RM7K_CONF_TE		(_ULCAST_(1) << 12)
+#define RM7K_CONF_CLK		(_ULCAST_(1) << 16)
+#define RM7K_CONF_TC		(_ULCAST_(1) << 17)
+#define RM7K_CONF_SI		(_ULCAST_(3) << 20)
+#define RM7K_CONF_SC		(_ULCAST_(1) << 31)
+
 /* Bits specific to the R10000.  */
 #define R10K_CONF_DN		(_ULCAST_(3) <<  3)
 #define R10K_CONF_CT		(_ULCAST_(1) <<  5)
@@ -475,6 +498,53 @@
 #define MIPS_CONF_M		(_ULCAST_(1) << 31)
 
 /*
+ * Bits in the MIPS32/64 PRA coprocessor 0 config registers 1 and above.
+ */
+#define MIPS_CONF1_FP		(_ULCAST_(1) <<  0)
+#define MIPS_CONF1_EP		(_ULCAST_(1) <<  1)
+#define MIPS_CONF1_CA		(_ULCAST_(1) <<  2)
+#define MIPS_CONF1_WR		(_ULCAST_(1) <<  3)
+#define MIPS_CONF1_PC		(_ULCAST_(1) <<  4)
+#define MIPS_CONF1_MD		(_ULCAST_(1) <<  5)
+#define MIPS_CONF1_C2		(_ULCAST_(1) <<  6)
+#define MIPS_CONF1_DA		(_ULCAST_(7) <<  7)
+#define MIPS_CONF1_DL		(_ULCAST_(7) << 10)
+#define MIPS_CONF1_DS		(_ULCAST_(7) << 13)
+#define MIPS_CONF1_IA		(_ULCAST_(7) << 16)
+#define MIPS_CONF1_IL		(_ULCAST_(7) << 19)
+#define MIPS_CONF1_IS		(_ULCAST_(7) << 22)
+#define MIPS_CONF1_TLBS		(_ULCAST_(63)<< 25)
+
+#define MIPS_CONF2_SA		(_ULCAST_(15)<<  0)
+#define MIPS_CONF2_SL		(_ULCAST_(15)<<  4)
+#define MIPS_CONF2_SS		(_ULCAST_(15)<<  8)
+#define MIPS_CONF2_SU		(_ULCAST_(15)<< 12)
+#define MIPS_CONF2_TA		(_ULCAST_(15)<< 16)
+#define MIPS_CONF2_TL		(_ULCAST_(15)<< 20)
+#define MIPS_CONF2_TS		(_ULCAST_(15)<< 24)
+#define MIPS_CONF2_TU		(_ULCAST_(7) << 28)
+
+#define MIPS_CONF3_TL		(_ULCAST_(1) <<  0)
+#define MIPS_CONF3_SM		(_ULCAST_(1) <<  1)
+#define MIPS_CONF3_MT		(_ULCAST_(1) <<  2)
+#define MIPS_CONF3_SP		(_ULCAST_(1) <<  4)
+#define MIPS_CONF3_VINT		(_ULCAST_(1) <<  5)
+#define MIPS_CONF3_VEIC		(_ULCAST_(1) <<  6)
+#define MIPS_CONF3_LPA		(_ULCAST_(1) <<  7)
+#define MIPS_CONF3_DSP		(_ULCAST_(1) << 10)
+
+/*
+ * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
+ */
+#define MIPS_FPIR_S		(_ULCAST_(1) << 16)
+#define MIPS_FPIR_D		(_ULCAST_(1) << 17)
+#define MIPS_FPIR_PS		(_ULCAST_(1) << 18)
+#define MIPS_FPIR_3D		(_ULCAST_(1) << 19)
+#define MIPS_FPIR_W		(_ULCAST_(1) << 20)
+#define MIPS_FPIR_L		(_ULCAST_(1) << 21)
+#define MIPS_FPIR_F64		(_ULCAST_(1) << 22)
+
+/*
  * R10000 performance counter definitions.
  *
  * FIXME: The R10000 performance counter opens a nice way to implement CPU
@@ -621,13 +691,13 @@
 	if (sel == 0)							\
 		__asm__ __volatile__(					\
 			"mtc0\t%z0, " #register "\n\t"			\
-			: : "Jr" ((unsigned int)value));		\
+			: : "Jr" ((unsigned int)(value)));		\
 	else								\
 		__asm__ __volatile__(					\
 			".set\tmips32\n\t"				\
 			"mtc0\t%z0, " #register ", " #sel "\n\t"	\
 			".set\tmips0"					\
-			: : "Jr" ((unsigned int)value));		\
+			: : "Jr" ((unsigned int)(value)));		\
 } while (0)
 
 #define __write_64bit_c0_register(register, sel, value)			\
@@ -676,7 +746,7 @@
 do {									\
 	__asm__ __volatile__(						\
 		"ctc0\t%z0, " #register "\n\t"				\
-		: : "Jr" ((unsigned int)value));			\
+		: : "Jr" ((unsigned int)(value)));			\
 } while (0)
 
 /*
@@ -769,12 +839,24 @@
 #define read_c0_count()		__read_32bit_c0_register($9, 0)
 #define write_c0_count(val)	__write_32bit_c0_register($9, 0, val)
 
+#define read_c0_count2()	__read_32bit_c0_register($9, 6) /* pnx8550 */
+#define write_c0_count2(val)	__write_32bit_c0_register($9, 6, val)
+
+#define read_c0_count3()	__read_32bit_c0_register($9, 7) /* pnx8550 */
+#define write_c0_count3(val)	__write_32bit_c0_register($9, 7, val)
+
 #define read_c0_entryhi()	__read_ulong_c0_register($10, 0)
 #define write_c0_entryhi(val)	__write_ulong_c0_register($10, 0, val)
 
 #define read_c0_compare()	__read_32bit_c0_register($11, 0)
 #define write_c0_compare(val)	__write_32bit_c0_register($11, 0, val)
 
+#define read_c0_compare2()	__read_32bit_c0_register($11, 6) /* pnx8550 */
+#define write_c0_compare2(val)	__write_32bit_c0_register($11, 6, val)
+
+#define read_c0_compare3()	__read_32bit_c0_register($11, 7) /* pnx8550 */
+#define write_c0_compare3(val)	__write_32bit_c0_register($11, 7, val)
+
 #define read_c0_status()	__read_32bit_c0_register($12, 0)
 #define write_c0_status(val)	__write_32bit_c0_register($12, 0, val)
 
@@ -790,10 +872,18 @@
 #define read_c0_config1()	__read_32bit_c0_register($16, 1)
 #define read_c0_config2()	__read_32bit_c0_register($16, 2)
 #define read_c0_config3()	__read_32bit_c0_register($16, 3)
+#define read_c0_config4()	__read_32bit_c0_register($16, 4)
+#define read_c0_config5()	__read_32bit_c0_register($16, 5)
+#define read_c0_config6()	__read_32bit_c0_register($16, 6)
+#define read_c0_config7()	__read_32bit_c0_register($16, 7)
 #define write_c0_config(val)	__write_32bit_c0_register($16, 0, val)
 #define write_c0_config1(val)	__write_32bit_c0_register($16, 1, val)
 #define write_c0_config2(val)	__write_32bit_c0_register($16, 2, val)
 #define write_c0_config3(val)	__write_32bit_c0_register($16, 3, val)
+#define write_c0_config4(val)	__write_32bit_c0_register($16, 4, val)
+#define write_c0_config5(val)	__write_32bit_c0_register($16, 5, val)
+#define write_c0_config6(val)	__write_32bit_c0_register($16, 6, val)
+#define write_c0_config7(val)	__write_32bit_c0_register($16, 7, val)
 
 /*
  * The WatchLo register.  There may be upto 8 of them.
@@ -917,6 +1007,22 @@
 #define read_c0_errorepc()	__read_ulong_c0_register($30, 0)
 #define write_c0_errorepc(val)	__write_ulong_c0_register($30, 0, val)
 
+/* MIPSR2 */
+#define read_c0_hwrena()	__read_32bit_c0_register($7,0)
+#define write_c0_hwrena(val)	__write_32bit_c0_register($7, 0, val)
+
+#define read_c0_intctl()	__read_32bit_c0_register($12, 1)
+#define write_c0_intctl(val)	__write_32bit_c0_register($12, 1, val)
+
+#define read_c0_srsctl()	__read_32bit_c0_register($12, 2)
+#define write_c0_srsctl(val)	__write_32bit_c0_register($12, 2, val)
+
+#define read_c0_srsmap()	__read_32bit_c0_register($12, 3)
+#define write_c0_srsmap(val)	__write_32bit_c0_register($12, 3, val)
+
+#define read_c0_ebase()		__read_32bit_c0_register($15,1)
+#define write_c0_ebase(val)	__write_32bit_c0_register($15, 1, val)
+
 /*
  * Macros to access the floating point coprocessor control registers
  */
@@ -930,6 +1036,284 @@
         : "=r" (__res));                                        \
         __res;})
 
+#define rddsp(mask)							\
+({									\
+	unsigned int __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push				\n"		\
+	"	.set	noat				\n"		\
+	"	# rddsp $1, %x1				\n"		\
+	"	.word	0x7c000cb8 | (%x1 << 16)	\n"		\
+	"	move	%0, $1				\n"		\
+	"	.set	pop				\n"		\
+	: "=r" (__res)							\
+	: "i" (mask));							\
+	__res;								\
+})
+
+#define wrdsp(val, mask)						\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# wrdsp $1, %x1					\n"	\
+	"	.word	0x7c2004f8 | (%x1 << 15)		\n"	\
+	"	.set	pop					\n"	\
+        :								\
+	: "r" (val), "i" (mask));					\
+} while (0)
+
+#if 0	/* Need DSP ASE capable assembler ... */
+#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})
+#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})
+#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;})
+#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;})
+
+#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;})
+#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;})
+#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;})
+#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;})
+
+#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x))
+#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x))
+#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x))
+#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x))
+
+#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x))
+#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x))
+#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x))
+#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x))
+
+#else
+
+#define mfhi0()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mfhi	%0, $ac0		\n"			\
+	"	.word	0x00000810		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mfhi1()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mfhi	%0, $ac1		\n"			\
+	"	.word	0x00200810		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mfhi2()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mfhi	%0, $ac2		\n"			\
+	"	.word	0x00400810		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mfhi3()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mfhi	%0, $ac3		\n"			\
+	"	.word	0x00600810		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mflo0()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mflo	%0, $ac0		\n"			\
+	"	.word	0x00000812		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mflo1()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mflo	%0, $ac1		\n"			\
+	"	.word	0x00200812		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mflo2()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mflo	%0, $ac2		\n"			\
+	"	.word	0x00400812		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mflo3()								\
+({									\
+	unsigned long __treg;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push			\n"			\
+	"	.set	noat			\n"			\
+	"	# mflo	%0, $ac3		\n"			\
+	"	.word	0x00600812		\n"			\
+	"	move	%0, $1			\n"			\
+	"	.set	pop			\n"			\
+	: "=r" (__treg));						\
+	__treg;								\
+})
+
+#define mthi0(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mthi	$1, $ac0				\n"	\
+	"	.word	0x00200011				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mthi1(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mthi	$1, $ac1				\n"	\
+	"	.word	0x00200811				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mthi2(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mthi	$1, $ac2				\n"	\
+	"	.word	0x00201011				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mthi3(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mthi	$1, $ac3				\n"	\
+	"	.word	0x00201811				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mtlo0(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mtlo	$1, $ac0				\n"	\
+	"	.word	0x00200013				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mtlo1(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mtlo	$1, $ac1				\n"	\
+	"	.word	0x00200813				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mtlo2(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mtlo	$1, $ac2				\n"	\
+	"	.word	0x00201013				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#define mtlo3(x)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mtlo	$1, $ac3				\n"	\
+	"	.word	0x00201813				\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (x));							\
+} while (0)
+
+#endif
+
 /*
  * TLB operations.
  *
@@ -1012,6 +1396,8 @@
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
 __BUILD_SET_C0(intcontrol)
+__BUILD_SET_C0(intctl)
+__BUILD_SET_C0(srsmap)
 
 #endif /* !__ASSEMBLY__ */
 
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 45cd72d..19cdf76 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -30,7 +30,7 @@
 
 #ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()						\
-	write_c0_context((unsigned long) smp_processor_id() << 23);	\
+	write_c0_context((unsigned long) smp_processor_id() << 25);	\
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
@@ -40,7 +40,7 @@
 #endif
 #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
 #define TLBMISS_HANDLER_SETUP()						\
-	write_c0_context((unsigned long) smp_processor_id() << 23);	\
+	write_c0_context((unsigned long) smp_processor_id() << 26);	\
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h
index d721143..011caeb 100644
--- a/include/asm-mips/mmzone.h
+++ b/include/asm-mips/mmzone.h
@@ -5,6 +5,7 @@
 #ifndef _ASM_MMZONE_H_
 #define _ASM_MMZONE_H_
 
+#include <linux/config.h>
 #include <asm/page.h>
 #include <mmzone.h>
 
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index 0be58b2..2be3993 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -14,15 +14,23 @@
 
 typedef uint8_t Elf64_Byte;		/* Type for a 8-bit quantity.  */
 
-typedef struct
-{
-  Elf64_Addr r_offset;			/* Address of relocation.  */
-  Elf64_Word r_sym;			/* Symbol index.  */
-  Elf64_Byte r_ssym;			/* Special symbol.  */
-  Elf64_Byte r_type3;			/* Third relocation.  */
-  Elf64_Byte r_type2;			/* Second relocation.  */
-  Elf64_Byte r_type;			/* First relocation.  */
-  Elf64_Sxword r_addend;		/* Addend.  */
+typedef struct {
+	Elf64_Addr r_offset;			/* Address of relocation.  */
+	Elf64_Word r_sym;			/* Symbol index.  */
+	Elf64_Byte r_ssym;			/* Special symbol.  */
+	Elf64_Byte r_type3;			/* Third relocation.  */
+	Elf64_Byte r_type2;			/* Second relocation.  */
+	Elf64_Byte r_type;			/* First relocation.  */
+} Elf64_Mips_Rel;
+
+typedef struct {
+	Elf64_Addr r_offset;			/* Address of relocation.  */
+	Elf64_Word r_sym;			/* Symbol index.  */
+	Elf64_Byte r_ssym;			/* Special symbol.  */
+	Elf64_Byte r_type3;			/* Third relocation.  */
+	Elf64_Byte r_type2;			/* Second relocation.  */
+	Elf64_Byte r_type;			/* First relocation.  */
+	Elf64_Sxword r_addend;			/* Addend.  */
 } Elf64_Mips_Rela;
 
 #ifdef CONFIG_32BIT
@@ -30,6 +38,13 @@
 #define Elf_Shdr	Elf32_Shdr
 #define Elf_Sym		Elf32_Sym
 #define Elf_Ehdr	Elf32_Ehdr
+#define Elf_Addr	Elf32_Addr
+
+#define Elf_Mips_Rel	Elf32_Rel
+#define Elf_Mips_Rela	Elf32_Rela
+
+#define ELF_MIPS_R_SYM(rel) ELF32_R_SYM(rel.r_info)
+#define ELF_MIPS_R_TYPE(rel) ELF32_R_TYPE(rel.r_info)
 
 #endif
 
@@ -38,6 +53,13 @@
 #define Elf_Shdr	Elf64_Shdr
 #define Elf_Sym		Elf64_Sym
 #define Elf_Ehdr	Elf64_Ehdr
+#define Elf_Addr	Elf64_Addr
+
+#define Elf_Mips_Rel	Elf64_Mips_Rel
+#define Elf_Mips_Rela	Elf64_Mips_Rela
+
+#define ELF_MIPS_R_SYM(rel) (rel.r_sym)
+#define ELF_MIPS_R_TYPE(rel) (rel.r_type)
 
 #endif
 
@@ -53,4 +75,54 @@
 }
 #endif
 
+#ifdef CONFIG_CPU_MIPS32_R1
+#define MODULE_PROC_FAMILY "MIPS32_R1"
+#elif defined CONFIG_CPU_MIPS32_R2
+#define MODULE_PROC_FAMILY "MIPS32_R2"
+#elif defined CONFIG_CPU_MIPS64_R1
+#define MODULE_PROC_FAMILY "MIPS64_R1"
+#elif defined CONFIG_CPU_MIPS64_R2
+#define MODULE_PROC_FAMILY "MIPS64_R2"
+#elif defined CONFIG_CPU_R3000
+#define MODULE_PROC_FAMILY "R3000"
+#elif defined CONFIG_CPU_TX39XX
+#define MODULE_PROC_FAMILY "TX39XX"
+#elif defined CONFIG_CPU_VR41XX
+#define MODULE_PROC_FAMILY "VR41XX"
+#elif defined CONFIG_CPU_R4300
+#define MODULE_PROC_FAMILY "R4300"
+#elif defined CONFIG_CPU_R4X00
+#define MODULE_PROC_FAMILY "R4X00"
+#elif defined CONFIG_CPU_TX49XX
+#define MODULE_PROC_FAMILY "TX49XX"
+#elif defined CONFIG_CPU_R5000
+#define MODULE_PROC_FAMILY "R5000"
+#elif defined CONFIG_CPU_R5432
+#define MODULE_PROC_FAMILY "R5432"
+#elif defined CONFIG_CPU_R6000
+#define MODULE_PROC_FAMILY "R6000"
+#elif defined CONFIG_CPU_NEVADA
+#define MODULE_PROC_FAMILY "NEVADA"
+#elif defined CONFIG_CPU_R8000
+#define MODULE_PROC_FAMILY "R8000"
+#elif defined CONFIG_CPU_R10000
+#define MODULE_PROC_FAMILY "R10000"
+#elif defined CONFIG_CPU_RM7000
+#define MODULE_PROC_FAMILY "RM7000"
+#elif defined CONFIG_CPU_RM9000
+#define MODULE_PROC_FAMILY "RM9000"
+#elif defined CONFIG_CPU_SB1
+#define MODULE_PROC_FAMILY "SB1"
+#else
+#error MODULE_PROC_FAMILY undefined for your processor configuration
+#endif
+
+#ifdef CONFIG_32BIT
+#define MODULE_KERNEL_TYPE "32BIT "
+#elif defined CONFIG_64BIT
+#define MODULE_KERNEL_TYPE "64BIT "
+#endif
+
+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
+
 #endif /* _ASM_MODULE_H */
diff --git a/include/asm-mips/paccess.h b/include/asm-mips/paccess.h
index 309bc30..46f2d23 100644
--- a/include/asm-mips/paccess.h
+++ b/include/asm-mips/paccess.h
@@ -52,7 +52,7 @@
 })
 
 #define __get_dbe_asm(insn)						\
-({									\
+{									\
 	__asm__ __volatile__(						\
 	"1:\t" insn "\t%1,%2\n\t"					\
 	"move\t%0,$0\n"							\
@@ -67,7 +67,7 @@
 	".previous"							\
 	:"=r" (__gu_err), "=r" (__gu_val)				\
 	:"o" (__mp(__gu_addr)), "i" (-EFAULT));				\
-})
+}
 
 extern void __get_dbe_unknown(void);
 
@@ -90,7 +90,7 @@
 })
 
 #define __put_dbe_asm(insn)						\
-({									\
+{									\
 	__asm__ __volatile__(						\
 	"1:\t" insn "\t%1,%2\n\t"					\
 	"move\t%0,$0\n"							\
@@ -104,7 +104,7 @@
 	".previous"							\
 	: "=r" (__pu_err)						\
 	: "r" (__pu_val), "o" (__mp(__pu_addr)), "i" (-EFAULT));	\
-})
+}
 
 extern void __put_dbe_unknown(void);
 
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 652b6d6..ee25a77 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -87,22 +87,48 @@
 typedef struct { unsigned long pte; } pte_t;
 #define pte_val(x)	((x).pte)
 #endif
+#define __pte(x)	((pte_t) { (x) } )
+
+/*
+ * For 3-level pagetables we defines these ourselves, for 2-level the
+ * definitions are supplied by <asm-generic/pgtable-nopmd.h>.
+ */
+#ifdef CONFIG_64BIT
 
 typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-
 #define pmd_val(x)	((x).pmd)
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define ptep_buddy(x)	((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
-
-#define __pte(x)	((pte_t) { (x) } )
 #define __pmd(x)	((pmd_t) { (x) } )
+
+#endif
+
+/*
+ * Right now we don't support 4-level pagetables, so all pud-related
+ * definitions come from <asm-generic/pgtable-nopud.h>.
+ */
+
+/*
+ * Finall the top of the hierarchy, the pgd
+ */
+typedef struct { unsigned long pgd; } pgd_t;
+#define pgd_val(x)	((x).pgd)
 #define __pgd(x)	((pgd_t) { (x) } )
+
+/*
+ * Manipulate page protection bits
+ */
+typedef struct { unsigned long pgprot; } pgprot_t;
+#define pgprot_val(x)	((x).pgprot)
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
+/*
+ * On R4000-style MMUs where a TLB entry is mapping a adjacent even / odd
+ * pair of pages we only have a single global bit per pair of pages.  When
+ * writing to the TLB make sure we always have the bit set for both pages
+ * or none.  This macro is used to access the `buddy' of the pte we're just
+ * working on.
+ */
+#define ptep_buddy(x)	((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
+
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index c9a00ca..6c9ad81 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -40,6 +40,11 @@
 	unsigned int need_domain_info;
 
 	int iommu;
+
+	/* Optional access methods for reading/writing the bus number
+	   of the PCI controller */
+	int (*get_busno)(void);
+	void (*set_busno)(int busno);
 };
 
 /*
@@ -142,8 +147,22 @@
 
 extern void pcibios_resource_to_bus(struct pci_dev *dev,
 	struct pci_bus_region *region, struct resource *res);
-extern void pcibios_bus_to_resource(struct pci_dev *dev,
-	struct resource *res, struct pci_bus_region *region);
+
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+				    struct pci_bus_region *region);
+
+static inline struct resource *
+pcibios_select_root(struct pci_dev *pdev, struct resource *res)
+{
+	struct resource *root = NULL;
+
+	if (res->flags & IORESOURCE_IO)
+		root = &ioport_resource;
+	if (res->flags & IORESOURCE_MEM)
+		root = &iomem_resource;
+
+	return root;
+}
 
 #ifdef CONFIG_PCI_DOMAINS
 
@@ -169,17 +188,4 @@
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 #endif /* _ASM_PCI_H */
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index ce57288..fe1df57 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -26,10 +26,22 @@
 }
 
 /*
+ * Initialize a new pmd table with invalid pointers.
+ */
+extern void pmd_init(unsigned long page, unsigned long pagetable);
+
+#ifdef CONFIG_64BIT
+
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	set_pud(pud, __pud((unsigned long)pmd));
+}
+#endif
+
+/*
  * Initialize a new pgd / pmd table with invalid pointers.
  */
 extern void pgd_init(unsigned long page);
-extern void pmd_init(unsigned long page, unsigned long pagetable);
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
@@ -86,21 +98,18 @@
 #define __pte_free_tlb(tlb,pte)		tlb_remove_page((tlb),(pte))
 
 #ifdef CONFIG_32BIT
-#define pgd_populate(mm, pmd, pte)	BUG()
 
 /*
  * 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_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
 #define pmd_free(x)			do { } while (0)
 #define __pmd_free_tlb(tlb,x)		do { } while (0)
+
 #endif
 
 #ifdef CONFIG_64BIT
 
-#define pgd_populate(mm, pgd, pmd)	set_pgd(pgd, __pgd(pmd))
-
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
 	pmd_t *pmd;
diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h
index 7fec93b..0cff64c 100644
--- a/include/asm-mips/pgtable-32.h
+++ b/include/asm-mips/pgtable-32.h
@@ -17,6 +17,8 @@
 #include <asm/cachectl.h>
 #include <asm/fixmap.h>
 
+#include <asm-generic/pgtable-nopmd.h>
+
 /*
  * - add_wired_entry() add a fixed TLB entry, and move wired register
  */
@@ -41,42 +43,38 @@
  * works even with the cache aliasing problem the R4k and above have.
  */
 
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#ifdef CONFIG_64BIT_PHYS_ADDR
-#define PMD_SHIFT	21
-#else
-#define PMD_SHIFT	22
-#endif
-#define PMD_SIZE	(1UL << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
-
 /* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT	PMD_SHIFT
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define PGDIR_SHIFT	21
+#else
+#define PGDIR_SHIFT	22
+#endif
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 /*
  * Entries per page directory level: we use two-level, so
- * we don't really have any PMD directory physically.
+ * we don't really have any PUD/PMD directory physically.
  */
 #ifdef CONFIG_64BIT_PHYS_ADDR
 #define PGD_ORDER	1
-#define PMD_ORDER	0
+#define PUD_ORDER	aieeee_attempt_to_allocate_pud
+#define PMD_ORDER	1
 #define PTE_ORDER	0
 #else
 #define PGD_ORDER	0
-#define PMD_ORDER	0
+#define PUD_ORDER	aieeee_attempt_to_allocate_pud
+#define PMD_ORDER	1
 #define PTE_ORDER	0
 #endif
 
 #define PTRS_PER_PGD	((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
-#define PTRS_PER_PMD	1
 #define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
 
 #define USER_PTRS_PER_PGD	(0x80000000UL/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS	0
 
-#define VMALLOC_START     KSEG2
+#define VMALLOC_START     MAP_BASE
 
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
@@ -91,8 +89,6 @@
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
 #endif
-#define pmd_ERROR(e) \
-	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
@@ -120,17 +116,7 @@
 	pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
 }
 
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-static inline int pgd_none(pgd_t pgd)		{ return 0; }
-static inline int pgd_bad(pgd_t pgd)		{ return 0; }
-static inline int pgd_present(pgd_t pgd)	{ return 1; }
-static inline void pgd_clear(pgd_t *pgdp)	{ }
-
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
 #define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
 static inline pte_t
@@ -151,27 +137,22 @@
 #define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
 #else
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
-#define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pte(pfn, prot)	__pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #endif
-#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) */
 
 #define __pgd_offset(address)	pgd_index(address)
+#define __pud_offset(address)	(((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 #define __pmd_offset(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-#define pgd_index(address)	((address) >> PGDIR_SHIFT)
+#define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
 /* to find an entry in a page-table-directory */
 #define pgd_offset(mm,addr)	((mm)->pgd + pgd_index(addr))
 
-/* Find an entry in the second-level page table.. */
-static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
-{
-	return (pmd_t *) dir;
-}
-
 /* Find an entry in the third-level page table.. */
 #define __pte_offset(address)						\
 	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
@@ -221,7 +202,7 @@
  */
 #define PTE_FILE_MAX_BITS	27
 
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 	/* fixme */
 #define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f))
 #define pgoff_to_pte(off) \
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h
index 1011e06..82166b2 100644
--- a/include/asm-mips/pgtable-64.h
+++ b/include/asm-mips/pgtable-64.h
@@ -16,13 +16,15 @@
 #include <asm/page.h>
 #include <asm/cachectl.h>
 
+#include <asm-generic/pgtable-nopud.h>
+
 /*
  * Each address space has 2 4K pages as its page directory, giving 1024
  * (== PTRS_PER_PGD) 8 byte pointers to pmd tables. Each pmd table is a
- * pair of 4K pages, giving 1024 (== PTRS_PER_PMD) 8 byte pointers to
- * page tables. Each page table is a single 4K page, giving 512 (==
- * PTRS_PER_PTE) 8 byte ptes. Each pgde is initialized to point to
- * invalid_pmd_table, each pmde is initialized to point to
+ * single 4K page, giving 512 (== PTRS_PER_PMD) 8 byte pointers to page
+ * tables. Each page table is also a single 4K page, giving 512 (==
+ * PTRS_PER_PTE) 8 byte ptes. Each pud entry is initialized to point to
+ * invalid_pmd_table, each pmd entry is initialized to point to
  * invalid_pte_table, each pte is initialized to 0. When memory is low,
  * and a pmd table or a page table allocation fails, empty_bad_pmd_table
  * and empty_bad_page_table is returned back to higher layer code, so
@@ -36,17 +38,17 @@
  */
 
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT - 3))
+#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3))
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 
 /* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT	(PMD_SHIFT + (PAGE_SHIFT + 1 - 3))
+#define PGDIR_SHIFT	(PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 /*
- * For 4kB page size we use a 3 level page tree and a 8kB pmd and pgds which
+ * For 4kB page size we use a 3 level page tree and an 8kB pud, which
  * permits us mapping 40 bits of virtual address space.
  *
  * We used to implement 41 bits by having an order 1 pmd level but that seemed
@@ -57,7 +59,7 @@
  * two levels would be easy to implement.
  *
  * For 16kB page size we use a 2 level page tree which permits a total of
- * 36 bits of virtual address space.  We could add a third leve. but it seems
+ * 36 bits of virtual address space.  We could add a third level but it seems
  * like at the moment there's no need for this.
  *
  * For 64kB page size we use a 2 level page table tree for a total of 42 bits
@@ -65,21 +67,25 @@
  */
 #ifdef CONFIG_PAGE_SIZE_4KB
 #define PGD_ORDER		1
+#define PUD_ORDER		aieeee_attempt_to_allocate_pud
 #define PMD_ORDER		0
 #define PTE_ORDER		0
 #endif
 #ifdef CONFIG_PAGE_SIZE_8KB
 #define PGD_ORDER		0
+#define PUD_ORDER		aieeee_attempt_to_allocate_pud
 #define PMD_ORDER		0
 #define PTE_ORDER		0
 #endif
 #ifdef CONFIG_PAGE_SIZE_16KB
 #define PGD_ORDER		0
+#define PUD_ORDER		aieeee_attempt_to_allocate_pud
 #define PMD_ORDER		0
 #define PTE_ORDER		0
 #endif
 #ifdef CONFIG_PAGE_SIZE_64KB
 #define PGD_ORDER		0
+#define PUD_ORDER		aieeee_attempt_to_allocate_pud
 #define PMD_ORDER		0
 #define PTE_ORDER		0
 #endif
@@ -91,7 +97,7 @@
 #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 #define FIRST_USER_ADDRESS	0
 
-#define VMALLOC_START		XKSEG
+#define VMALLOC_START		MAP_BASE
 #define VMALLOC_END	\
 	(VMALLOC_START + PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE)
 
@@ -102,13 +108,13 @@
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)];
-extern pte_t empty_bad_page_table[PAGE_SIZE/sizeof(pte_t)];
-extern pmd_t invalid_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
-extern pmd_t empty_bad_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
+extern pte_t invalid_pte_table[PTRS_PER_PTE];
+extern pte_t empty_bad_page_table[PTRS_PER_PTE];
+extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
+extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD];
 
 /*
- * Empty pmd entries point to the invalid_pte_table.
+ * Empty pgd/pmd entries point to the invalid_pte_table.
  */
 static inline int pmd_none(pmd_t pmd)
 {
@@ -128,26 +134,30 @@
 }
 
 /*
- * Empty pgd entries point to the invalid_pmd_table.
+ * Empty pud entries point to the invalid_pmd_table.
  */
-static inline int pgd_none(pgd_t pgd)
+static inline int pud_none(pud_t pud)
 {
-	return pgd_val(pgd) == (unsigned long) invalid_pmd_table;
+	return pud_val(pud) == (unsigned long) invalid_pmd_table;
 }
 
-#define pgd_bad(pgd)		(pgd_val(pgd) &~ PAGE_MASK)
-
-static inline int pgd_present(pgd_t pgd)
+static inline int pud_bad(pud_t pud)
 {
-	return pgd_val(pgd) != (unsigned long) invalid_pmd_table;
+	return pud_val(pud) & ~PAGE_MASK;
 }
 
-static inline void pgd_clear(pgd_t *pgdp)
+static inline int pud_present(pud_t pud)
 {
-	pgd_val(*pgdp) = ((unsigned long) invalid_pmd_table);
+	return pud_val(pud) != (unsigned long) invalid_pmd_table;
 }
 
-#define pte_page(x)		pfn_to_page((unsigned long)((pte_val(x) >> PAGE_SHIFT)))
+static inline void pud_clear(pud_t *pudp)
+{
+	pud_val(*pudp) = ((unsigned long) invalid_pmd_table);
+}
+
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
+
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
@@ -157,26 +167,27 @@
 #endif
 
 #define __pgd_offset(address)	pgd_index(address)
-#define page_pte(page) page_pte_prot(page, __pgprot(0))
+#define __pud_offset(address)	(((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+#define __pmd_offset(address)	pmd_index(address)
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, 0)
 
-#define pgd_index(address)		((address) >> PGDIR_SHIFT)
+#define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define pmd_index(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
 /* to find an entry in a page-table-directory */
 #define pgd_offset(mm,addr)	((mm)->pgd + pgd_index(addr))
 
-static inline unsigned long pgd_page(pgd_t pgd)
+static inline unsigned long pud_page(pud_t pud)
 {
-	return pgd_val(pgd);
+	return pud_val(pud);
 }
 
 /* Find an entry in the second-level page table.. */
-static inline pmd_t *pmd_offset(pgd_t * dir, unsigned long address)
+static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address)
 {
-	return (pmd_t *) pgd_page(*dir) +
-	       ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+	return (pmd_t *) pud_page(*pud) + pmd_index(address);
 }
 
 /* Find an entry in the third-level page table.. */
diff --git a/include/asm-mips/pgtable-bits.h b/include/asm-mips/pgtable-bits.h
index 3aad751..01e76e9 100644
--- a/include/asm-mips/pgtable-bits.h
+++ b/include/asm-mips/pgtable-bits.h
@@ -33,7 +33,7 @@
  * unpredictable things.  The code (when it is written) to deal with
  * this problem will be in the update_mmu_cache() code for the r4k.
  */
-#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+#if defined(CONFIG_CPU_MIPS32_R1) && defined(CONFIG_64BIT_PHYS_ADDR)
 
 #define _PAGE_PRESENT               (1<<6)  /* implemented in software */
 #define _PAGE_READ                  (1<<7)  /* implemented in software */
@@ -123,7 +123,7 @@
 
 #endif
 #endif
-#endif /* defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR) */
+#endif /* defined(CONFIG_CPU_MIPS32_R1) && defined(CONFIG_64BIT_PHYS_ADDR) */
 
 #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
@@ -140,7 +140,7 @@
 #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
 #endif
 
-#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+#if defined(CONFIG_CPU_MIPS32_R1) && defined(CONFIG_64BIT_PHYS_ADDR)
 #define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 3)
 #else
 #define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 9)
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index eaf5d9b..34facd9 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -8,8 +8,6 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
-#include <asm-generic/4level-fixup.h>
-
 #include <linux/config.h>
 #ifdef CONFIG_32BIT
 #include <asm/pgtable-32.h>
@@ -18,6 +16,7 @@
 #include <asm/pgtable-64.h>
 #endif
 
+#include <asm/io.h>
 #include <asm/pgtable-bits.h>
 
 #define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
@@ -76,7 +75,6 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-#define page_pte(page)		page_pte_prot(page, __pgprot(0))
 #define pmd_phys(pmd)		(pmd_val(pmd) - PAGE_OFFSET)
 #define pmd_page(pmd)		(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pmd_page_kernel(pmd)	pmd_val(pmd)
@@ -84,7 +82,7 @@
 #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
 
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
 	ptep->pte_high = pte.pte_high;
@@ -148,11 +146,18 @@
 #endif
 
 /*
- * (pmds are folded into pgds so this doesn't get actually called,
+ * (pmds are folded into puds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
  */
 #define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while(0)
-#define set_pgd(pgdptr, pgdval) do { *(pgdptr) = (pgdval); } while(0)
+
+#ifdef CONFIG_64BIT
+/*
+ * (puds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while(0)
+#endif
 
 #define PGD_T_LOG2	ffz(~sizeof(pgd_t))
 #define PMD_T_LOG2	ffz(~sizeof(pmd_t))
@@ -165,7 +170,7 @@
  * Undefined behaviour if not..
  */
 static inline int pte_user(pte_t pte)	{ BUG(); return 0; }
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 static inline int pte_read(pte_t pte)	{ return (pte).pte_low & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return (pte).pte_low & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return (pte).pte_low & _PAGE_MODIFIED; }
@@ -324,7 +329,7 @@
  */
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	pte.pte_low &= _PAGE_CHG_MASK;
@@ -357,7 +362,6 @@
 #endif
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
-extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
 extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);
 
 static inline int io_remap_pfn_range(struct vm_area_struct *vma,
@@ -367,7 +371,7 @@
 		pgprot_t prot)
 {
 	phys_t phys_addr_high = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
-	return remap_pfn_range(vma, vaddr, pfn, size, prot);
+	return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
 }
 #else
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index d6466aa..f1980c6 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -96,12 +96,26 @@
 	{{0,},} \
 }
 
+#define NUM_DSP_REGS   6
+
+typedef __u32 dspreg_t;
+
+struct mips_dsp_state {
+	dspreg_t        dspr[NUM_DSP_REGS];
+	unsigned int    dspcontrol;
+	unsigned short	used_dsp;
+};
+
+#define INIT_DSP {{0,},}
+
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
 #define ARCH_MIN_TASKALIGN	8
 
+struct mips_abi;
+
 /*
  * If you change thread_struct remember to change the #defines below too!
  */
@@ -117,6 +131,9 @@
 	/* Saved fpu/fpu emulator stuff. */
 	union mips_fpu_union fpu;
 
+	/* Saved state of the DSP ASE, if available. */
+	struct mips_dsp_state dsp;
+
 	/* Other stuff associated with the thread. */
 	unsigned long cp0_badvaddr;	/* Last user fault */
 	unsigned long cp0_baduaddr;	/* Last kernel fault accessing USEG */
@@ -129,6 +146,7 @@
 	unsigned long mflags;
 	unsigned long irix_trampoline;  /* Wheee... */
 	unsigned long irix_oldctx;
+	struct mips_abi *abi;
 };
 
 #define MF_ABI_MASK	(MF_32BIT_REGS | MF_32BIT_ADDR)
@@ -151,6 +169,10 @@
 	 */ \
 	INIT_FPU, \
 	/* \
+	 * saved dsp/dsp emulator stuff \
+	 */ \
+	INIT_DSP, \
+	/* \
 	 * Other stuff associated with the process \
 	 */ \
 	0, 0, 0, 0, \
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 2b5c624..95c5839 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -22,6 +22,8 @@
 #define MMLO		68
 #define FPC_CSR		69
 #define FPC_EIR		70
+#define DSP_BASE	71		/* 3 more hi / lo register pairs */
+#define DSP_CONTROL	77
 
 /*
  * This struct defines the way the registers are stored on the stack during a
@@ -38,18 +40,18 @@
 
 	/* Saved special registers. */
 	unsigned long cp0_status;
-	unsigned long lo;
 	unsigned long hi;
+	unsigned long lo;
 	unsigned long cp0_badvaddr;
 	unsigned long cp0_cause;
 	unsigned long cp0_epc;
 };
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-/* #define PTRACE_GETREGS		12 */
-/* #define PTRACE_SETREGS		13 */
-/* #define PTRACE_GETFPREGS		14 */
-/* #define PTRACE_SETFPREGS		15 */
+#define PTRACE_GETREGS		12
+#define PTRACE_SETREGS		13
+#define PTRACE_GETFPREGS		14
+#define PTRACE_SETFPREGS		15
 /* #define PTRACE_GETFPXREGS		18 */
 /* #define PTRACE_SETFPXREGS		19 */
 
@@ -58,6 +60,13 @@
 #define PTRACE_GET_THREAD_AREA	25
 #define PTRACE_SET_THREAD_AREA	26
 
+/* Calls to trace a 64bit program from a 32bit program.  */
+#define PTRACE_PEEKTEXT_3264	0xc0
+#define PTRACE_PEEKDATA_3264	0xc1
+#define PTRACE_POKETEXT_3264	0xc2
+#define PTRACE_POKEDATA_3264	0xc3
+#define PTRACE_GET_THREAD_AREA_3264	0xc4
+
 #ifdef __KERNEL__
 
 #include <linux/linkage.h>
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index 5bea49f..a5ea9d8 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -21,7 +21,7 @@
  *
  *  - The MIPS32 and MIPS64 specs permit an implementation to directly derive
  *    the index bits from the virtual address.  This breaks with tradition
- *    set by the R4000.  To keep unpleassant surprises from happening we pick
+ *    set by the R4000.  To keep unpleasant surprises from happening we pick
  *    an address in KSEG0 / CKSEG0.
  *  - We need a properly sign extended address for 64-bit code.  To get away
  *    without ifdefs we let the compiler do it by a type cast.
@@ -30,11 +30,11 @@
 
 #define cache_op(op,addr)						\
 	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
 	"	.set	noreorder				\n"	\
 	"	.set	mips3\n\t				\n"	\
 	"	cache	%0, %1					\n"	\
-	"	.set	mips0					\n"	\
-	"	.set	reorder"					\
+	"	.set	pop					\n"	\
 	:								\
 	: "i" (op), "m" (*(unsigned char *)(addr)))
 
@@ -84,14 +84,14 @@
 static inline void protected_flush_icache_line(unsigned long addr)
 {
 	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n"
-		"1:\tcache %0,(%1)\n"
-		"2:\t.set mips0\n\t"
-		".set reorder\n\t"
-		".section\t__ex_table,\"a\"\n\t"
-		STR(PTR)"\t1b,2b\n\t"
-		".previous"
+		"	.set	push			\n"
+		"	.set	noreorder		\n"
+		"	.set	mips3			\n"
+		"1:	cache	%0, (%1)		\n"
+		"2:	.set	pop			\n"
+		"	.section __ex_table,\"a\"	\n"
+		"	"STR(PTR)" 1b, 2b		\n"
+		"	.previous"
 		:
 		: "i" (Hit_Invalidate_I), "r" (addr));
 }
@@ -100,19 +100,19 @@
  * R10000 / R12000 hazard - these processors don't support the Hit_Writeback_D
  * cacheop so we use Hit_Writeback_Inv_D which is supported by all R4000-style
  * caches.  We're talking about one cacheline unnecessarily getting invalidated
- * here so the penaltiy isn't overly hard.
+ * here so the penalty isn't overly hard.
  */
 static inline void protected_writeback_dcache_line(unsigned long addr)
 {
 	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n"
-		"1:\tcache %0,(%1)\n"
-		"2:\t.set mips0\n\t"
-		".set reorder\n\t"
-		".section\t__ex_table,\"a\"\n\t"
-		STR(PTR)"\t1b,2b\n\t"
-		".previous"
+		"	.set	push			\n"
+		"	.set	noreorder		\n"
+		"	.set	mips3			\n"
+		"1:	cache	%0, (%1)		\n"
+		"2:	.set	pop			\n"
+		"	.section __ex_table,\"a\"	\n"
+		"	"STR(PTR)" 1b, 2b		\n"
+		"	.previous"
 		:
 		: "i" (Hit_Writeback_Inv_D), "r" (addr));
 }
@@ -120,14 +120,14 @@
 static inline void protected_writeback_scache_line(unsigned long addr)
 {
 	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n"
-		"1:\tcache %0,(%1)\n"
-		"2:\t.set mips0\n\t"
-		".set reorder\n\t"
-		".section\t__ex_table,\"a\"\n\t"
-		STR(PTR)"\t1b,2b\n\t"
-		".previous"
+		"	.set	push			\n"
+		"	.set	noreorder		\n"
+		"	.set	mips3			\n"
+		"1:	cache	%0, (%1)		\n"
+		"2:	.set	pop			\n"
+		"	.section __ex_table,\"a\"	\n"
+		"	"STR(PTR)" 1b, 2b		\n"
+		"	.previous"
 		:
 		: "i" (Hit_Writeback_Inv_SD), "r" (addr));
 }
@@ -142,6 +142,7 @@
 
 #define cache16_unroll32(base,op)					\
 	__asm__ __volatile__(						\
+	"	.set push					\n"	\
 	"	.set noreorder					\n"	\
 	"	.set mips3					\n"	\
 	"	cache %1, 0x000(%0); cache %1, 0x010(%0)	\n"	\
@@ -160,8 +161,7 @@
 	"	cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)	\n"	\
 	"	cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)	\n"	\
 	"	cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)	\n"	\
-	"	.set mips0					\n"	\
-	"	.set reorder					\n"	\
+	"	.set pop					\n"	\
 		:							\
 		: "r" (base),						\
 		  "i" (op));
@@ -285,6 +285,7 @@
 
 #define cache32_unroll32(base,op)					\
 	__asm__ __volatile__(						\
+	"	.set push					\n"	\
 	"	.set noreorder					\n"	\
 	"	.set mips3					\n"	\
 	"	cache %1, 0x000(%0); cache %1, 0x020(%0)	\n"	\
@@ -303,8 +304,7 @@
 	"	cache %1, 0x340(%0); cache %1, 0x360(%0)	\n"	\
 	"	cache %1, 0x380(%0); cache %1, 0x3a0(%0)	\n"	\
 	"	cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)	\n"	\
-	"	.set mips0					\n"	\
-	"	.set reorder					\n"	\
+	"	.set pop					\n"	\
 		:							\
 		: "r" (base),						\
 		  "i" (op));
@@ -428,6 +428,7 @@
 
 #define cache64_unroll32(base,op)					\
 	__asm__ __volatile__(						\
+	"	.set push					\n"	\
 	"	.set noreorder					\n"	\
 	"	.set mips3					\n"	\
 	"	cache %1, 0x000(%0); cache %1, 0x040(%0)	\n"	\
@@ -446,8 +447,7 @@
 	"	cache %1, 0x680(%0); cache %1, 0x6c0(%0)	\n"	\
 	"	cache %1, 0x700(%0); cache %1, 0x740(%0)	\n"	\
 	"	cache %1, 0x780(%0); cache %1, 0x7c0(%0)	\n"	\
-	"	.set mips0					\n"	\
-	"	.set reorder					\n"	\
+	"	.set pop					\n"	\
 		:							\
 		: "r" (base),						\
 		  "i" (op));
@@ -532,6 +532,7 @@
 
 #define cache128_unroll32(base,op)					\
 	__asm__ __volatile__(						\
+	"	.set push					\n"	\
 	"	.set noreorder					\n"	\
 	"	.set mips3					\n"	\
 	"	cache %1, 0x000(%0); cache %1, 0x080(%0)	\n"	\
@@ -550,8 +551,7 @@
 	"	cache %1, 0xd00(%0); cache %1, 0xd80(%0)	\n"	\
 	"	cache %1, 0xe00(%0); cache %1, 0xe80(%0)	\n"	\
 	"	cache %1, 0xf00(%0); cache %1, 0xf80(%0)	\n"	\
-	"	.set mips0					\n"	\
-	"	.set reorder					\n"	\
+	"	.set pop					\n"	\
 		:							\
 		: "r" (base),						\
 		  "i" (op));
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
index 3c4b637..a60e0dc 100644
--- a/include/asm-mips/rtc.h
+++ b/include/asm-mips/rtc.h
@@ -14,7 +14,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/spinlock.h>
 #include <linux/rtc.h>
+#include <asm/time.h>
 
 #define RTC_PIE 0x40            /* periodic interrupt enable */
 #define RTC_AIE 0x20            /* alarm interrupt enable */
@@ -27,11 +29,52 @@
 #define RTC_24H 0x02            /* 24 hour mode - else hours bit 7 means pm */
 #define RTC_DST_EN 0x01         /* auto switch DST - works f. USA only */
 
-unsigned int get_rtc_time(struct rtc_time *time);
-int set_rtc_time(struct rtc_time *time);
-unsigned int get_rtc_ss(void);
-int get_rtc_pll(struct rtc_pll_info *pll);
-int set_rtc_pll(struct rtc_pll_info *pll);
+static DEFINE_SPINLOCK(mips_rtc_lock);
 
+static inline unsigned int get_rtc_time(struct rtc_time *time)
+{
+	unsigned long nowtime;
+
+	spin_lock(&mips_rtc_lock);
+	nowtime = rtc_get_time();
+	to_tm(nowtime, time);
+	time->tm_year -= 1900;
+	spin_unlock(&mips_rtc_lock);
+
+	return RTC_24H;
+}
+
+static inline int set_rtc_time(struct rtc_time *time)
+{
+	unsigned long nowtime;
+	int ret;
+
+	spin_lock(&mips_rtc_lock);
+	nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
+			time->tm_mday, time->tm_hour, time->tm_min,
+			time->tm_sec);
+	ret = rtc_set_time(nowtime);
+	spin_unlock(&mips_rtc_lock);
+
+	return ret;
+}
+
+static inline unsigned int get_rtc_ss(void)
+{
+	struct rtc_time h;
+
+	get_rtc_time(&h);
+	return h.tm_sec;
+}
+
+static inline int get_rtc_pll(struct rtc_pll_info *pll)
+{
+	return -EINVAL;
+}
+
+static inline int set_rtc_pll(struct rtc_pll_info *pll)
+{
+	return -EINVAL;
+}
 #endif
 #endif
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h
new file mode 100644
index 0000000..83cdf6a
--- /dev/null
+++ b/include/asm-mips/rtlx.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ */
+
+#ifndef _RTLX_H
+#define _RTLX_H_
+
+#define LX_NODE_BASE 10
+
+#define MIPSCPU_INT_BASE       16
+#define MIPS_CPU_RTLX_IRQ 0
+
+#define RTLX_VERSION 1
+#define RTLX_xID 0x12345600
+#define RTLX_ID (RTLX_xID | RTLX_VERSION)
+#define RTLX_CHANNELS 8
+
+enum rtlx_state {
+	RTLX_STATE_UNUSED = 0,
+	RTLX_STATE_INITIALISED,
+	RTLX_STATE_REMOTE_READY,
+	RTLX_STATE_OPENED
+};
+
+#define RTLX_BUFFER_SIZE 1024
+/* each channel supports read and write.
+   linux (vpe0) reads lx_buffer  and writes rt_buffer
+   SP (vpe1) reads rt_buffer and writes lx_buffer
+*/
+typedef struct rtlx_channel {
+	enum rtlx_state rt_state;
+	enum rtlx_state lx_state;
+
+	int buffer_size;
+
+	/* read and write indexes per buffer */
+	int rt_write, rt_read;
+	char *rt_buffer;
+
+	int lx_write, lx_read;
+	char *lx_buffer;
+
+	void *queues;
+
+} rtlx_channel_t;
+
+typedef struct rtlx_info {
+	unsigned long id;
+	enum rtlx_state state;
+
+	struct rtlx_channel channel[RTLX_CHANNELS];
+
+} rtlx_info_t;
+
+#endif
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
index c2c97de..3d6aa7c 100644
--- a/include/asm-mips/semaphore.h
+++ b/include/asm-mips/semaphore.h
@@ -45,9 +45,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name, 1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name, count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index 4eed8e2..e796d75 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -52,16 +52,6 @@
 #define JAZZ_SERIAL_PORT_DEFNS
 #endif
 
-#ifdef CONFIG_MIPS_COBALT
-#include <asm/cobalt/cobalt.h>
-#define COBALT_BASE_BAUD  (18432000 / 16)
-#define COBALT_SERIAL_PORT_DEFNS		\
-	/* UART CLK   PORT  IRQ  FLAGS    */ 		\
-	{ 0, COBALT_BASE_BAUD, 0xc800000, COBALT_SERIAL_IRQ, STD_COM_FLAGS },   /* ttyS0 */
-#else
-#define COBALT_SERIAL_PORT_DEFNS
-#endif
-
 /*
  * Both Galileo boards have the same UART mappings.
  */
@@ -113,17 +103,6 @@
 #define IVR_SERIAL_PORT_DEFNS
 #endif
 
-#ifdef CONFIG_TOSHIBA_JMR3927
-#include <asm/jmr3927/jmr3927.h>
-#define TXX927_SERIAL_PORT_DEFNS                              \
-    { .baud_base = JMR3927_BASE_BAUD, .port = UART0_ADDR, .irq = UART0_INT,  \
-      .flags = UART0_FLAGS, .type = 1 },                        \
-    { .baud_base = JMR3927_BASE_BAUD, .port = UART1_ADDR, .irq = UART1_INT,  \
-      .flags = UART1_FLAGS, .type = 1 },
-#else
-#define TXX927_SERIAL_PORT_DEFNS
-#endif
-
 #ifdef CONFIG_SERIAL_AU1X00
 #include <asm/mach-au1x00/au1000.h>
 #ifdef CONFIG_SOC_AU1000
@@ -227,9 +206,9 @@
 #define JAGUAR_ATX_SERIAL1_BASE	0xfd000023L
 
 #define _JAGUAR_ATX_SERIAL_INIT(int, base)				\
-	{ baud_base: JAGUAR_ATX_BASE_BAUD, irq: int,			\
-	  flags: (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),		\
-	  iomem_base: (u8 *) base, iomem_reg_shift: 2,			\
+	{ .baud_base = JAGUAR_ATX_BASE_BAUD, irq: int,			\
+	  .flags = (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),		\
+	  .iomem_base = (u8 *) base, iomem_reg_shift: 2,			\
 	  io_type: SERIAL_IO_MEM }
 #define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS				\
 	_JAGUAR_ATX_SERIAL_INIT(JAGUAR_ATX_SERIAL1_IRQ, JAGUAR_ATX_SERIAL1_BASE)
@@ -243,9 +222,9 @@
 #define OCELOT_3_SERIAL_BASE	(signed)0xfd000020
 
 #define _OCELOT_3_SERIAL_INIT(int, base)				\
-	{ baud_base: OCELOT_3_BASE_BAUD, irq: int, 			\
-	  flags: STD_COM_FLAGS,						\
-	  iomem_base: (u8 *) base, iomem_reg_shift: 2,			\
+	{ .baud_base = OCELOT_3_BASE_BAUD, irq: int, 			\
+	  .flags = STD_COM_FLAGS,						\
+	  .iomem_base = (u8 *) base, iomem_reg_shift: 2,			\
 	  io_type: SERIAL_IO_MEM }
 
 #define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS				\
@@ -342,7 +321,6 @@
 #endif /* CONFIG_SGI_IP32 */
 
 #define SERIAL_PORT_DFNS				\
-	COBALT_SERIAL_PORT_DEFNS			\
 	DDB5477_SERIAL_PORT_DEFNS			\
 	EV96100_SERIAL_PORT_DEFNS			\
 	IP32_SERIAL_PORT_DEFNS                          \
@@ -354,7 +332,6 @@
 	MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS		\
-	TXX927_SERIAL_PORT_DEFNS                        \
 	AU1000_SERIAL_PORT_DEFNS
 
 #endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/sgi/hpc3.h b/include/asm-mips/sgi/hpc3.h
index ac3dfc7..fcec52b 100644
--- a/include/asm-mips/sgi/hpc3.h
+++ b/include/asm-mips/sgi/hpc3.h
@@ -128,26 +128,26 @@
 	volatile u32 rx_gfptr;	/* current GIO fifo ptr */
 	volatile u32 rx_dfptr;	/* current device fifo ptr */
 	u32 _unused1;		/* padding */
-	volatile u32 rx_reset;	/* reset register */
-#define HPC3_ERXRST_CRESET 0x1	/* Reset dma channel and external controller */
-#define HPC3_ERXRST_CLRIRQ 0x2	/* Clear channel interrupt */
-#define HPC3_ERXRST_LBACK  0x4	/* Enable diagnostic loopback mode of Seeq8003 */
+	volatile u32 reset;	/* reset register */
+#define HPC3_ERST_CRESET 0x1	/* Reset dma channel and external controller */
+#define HPC3_ERST_CLRIRQ 0x2	/* Clear channel interrupt */
+#define HPC3_ERST_LBACK  0x4	/* Enable diagnostic loopback mode of Seeq8003 */
 
-	volatile u32 rx_dconfig;	/* DMA configuration register */
-#define HPC3_ERXDCFG_D1    0x0000f /* Cycles to spend in D1 state for PIO */
-#define HPC3_ERXDCFG_D2    0x000f0 /* Cycles to spend in D2 state for PIO */
-#define HPC3_ERXDCFG_D3    0x00f00 /* Cycles to spend in D3 state for PIO */
-#define HPC3_ERXDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
-#define HPC3_ERXDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
-#define HPC3_ERXDCFG_FEOP  0x04000 /* Bad packet marker timeout enable */
-#define HPC3_ERXDCFG_FIRQ  0x08000 /* Another bad packet timeout enable */
-#define HPC3_ERXDCFG_PTO   0x30000 /* Programmed timeout value for above two */
+	volatile u32 dconfig;    /* DMA configuration register */
+#define HPC3_EDCFG_D1    0x0000f /* Cycles to spend in D1 state for PIO */
+#define HPC3_EDCFG_D2    0x000f0 /* Cycles to spend in D2 state for PIO */
+#define HPC3_EDCFG_D3    0x00f00 /* Cycles to spend in D3 state for PIO */
+#define HPC3_EDCFG_WCTRL 0x01000 /* Enable writes of desc into ex ctrl port */
+#define HPC3_EDCFG_FRXDC 0x02000 /* Clear eop stat bits upon rxdc, hw seeq fix */
+#define HPC3_EDCFG_FEOP  0x04000 /* Bad packet marker timeout enable */
+#define HPC3_EDCFG_FIRQ  0x08000 /* Another bad packet timeout enable */
+#define HPC3_EDCFG_PTO   0x30000 /* Programmed timeout value for above two */
 
-	volatile u32 rx_pconfig;	/* PIO configuration register */
-#define HPC3_ERXPCFG_P1    0x000f /* Cycles to spend in P1 state for PIO */
-#define HPC3_ERXPCFG_P2    0x00f0 /* Cycles to spend in P2 state for PIO */
-#define HPC3_ERXPCFG_P3    0x0f00 /* Cycles to spend in P3 state for PIO */
-#define HPC3_ERXPCFG_TST   0x1000 /* Diagnistic ram test feature bit */
+	volatile u32 pconfig;   /* PIO configuration register */
+#define HPC3_EPCFG_P1    0x000f /* Cycles to spend in P1 state for PIO */
+#define HPC3_EPCFG_P2    0x00f0 /* Cycles to spend in P2 state for PIO */
+#define HPC3_EPCFG_P3    0x0f00 /* Cycles to spend in P3 state for PIO */
+#define HPC3_EPCFG_TST   0x1000 /* Diagnistic ram test feature bit */
 
 	u32 _unused2[0x1000/4 - 8];	/* padding */
 
diff --git a/include/asm-mips/sibyte/bcm1480_int.h b/include/asm-mips/sibyte/bcm1480_int.h
new file mode 100644
index 0000000..42d4cf0
--- /dev/null
+++ b/include/asm-mips/sibyte/bcm1480_int.h
@@ -0,0 +1,310 @@
+/*  *********************************************************************
+    *  BCM1280/BCM1480 Board Support Package
+    *
+    *  Interrupt Mapper definitions		File: bcm1480_int.h
+    *
+    *  This module contains constants for manipulating the
+    *  BCM1255/BCM1280/BCM1455/BCM1480's interrupt mapper and
+    *  definitions for the interrupt sources.
+    *
+    *  BCM1480 specification level: 1X55_1X80-UM100-D4 (11/24/03)
+    *
+    *********************************************************************
+    *
+    *  Copyright 2000,2001,2002,2003
+    *  Broadcom Corporation. 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
+    ********************************************************************* */
+
+
+#ifndef _BCM1480_INT_H
+#define _BCM1480_INT_H
+
+#include "sb1250_defs.h"
+
+/*  *********************************************************************
+    *  Interrupt Mapper Constants
+    ********************************************************************* */
+
+/*
+ * The interrupt mapper deals with 128-bit logical registers that are
+ * implemented as pairs of 64-bit registers, with the "low" 64 bits in
+ * a register that has an address 0x1000 higher(!) than the
+ * corresponding "high" register.
+ *
+ * For appropriate registers, bit 0 of the "high" register is a
+ * cascade bit that summarizes (as a bit-OR) the 64 bits of the "low"
+ * register.
+ */
+
+/*
+ * This entire file uses _BCM1480_ in all the symbols because it is
+ * entirely BCM1480 specific.
+ */
+
+/*
+ * Interrupt sources (Table 22)
+ */
+
+#define K_BCM1480_INT_SOURCES               128
+
+#define _BCM1480_INT_HIGH(k)   (k)
+#define _BCM1480_INT_LOW(k)    ((k)+64)
+
+#define K_BCM1480_INT_ADDR_TRAP             _BCM1480_INT_HIGH(1)
+#define K_BCM1480_INT_GPIO_0                _BCM1480_INT_HIGH(4)
+#define K_BCM1480_INT_GPIO_1                _BCM1480_INT_HIGH(5)
+#define K_BCM1480_INT_GPIO_2                _BCM1480_INT_HIGH(6)
+#define K_BCM1480_INT_GPIO_3                _BCM1480_INT_HIGH(7)
+#define K_BCM1480_INT_PCI_INTA              _BCM1480_INT_HIGH(8)
+#define K_BCM1480_INT_PCI_INTB              _BCM1480_INT_HIGH(9)
+#define K_BCM1480_INT_PCI_INTC              _BCM1480_INT_HIGH(10)
+#define K_BCM1480_INT_PCI_INTD              _BCM1480_INT_HIGH(11)
+#define K_BCM1480_INT_CYCLE_CP0             _BCM1480_INT_HIGH(12)
+#define K_BCM1480_INT_CYCLE_CP1             _BCM1480_INT_HIGH(13)
+#define K_BCM1480_INT_CYCLE_CP2             _BCM1480_INT_HIGH(14)
+#define K_BCM1480_INT_CYCLE_CP3             _BCM1480_INT_HIGH(15)
+#define K_BCM1480_INT_TIMER_0               _BCM1480_INT_HIGH(20)
+#define K_BCM1480_INT_TIMER_1               _BCM1480_INT_HIGH(21)
+#define K_BCM1480_INT_TIMER_2               _BCM1480_INT_HIGH(22)
+#define K_BCM1480_INT_TIMER_3               _BCM1480_INT_HIGH(23)
+#define K_BCM1480_INT_DM_CH_0               _BCM1480_INT_HIGH(28)
+#define K_BCM1480_INT_DM_CH_1               _BCM1480_INT_HIGH(29)
+#define K_BCM1480_INT_DM_CH_2               _BCM1480_INT_HIGH(30)
+#define K_BCM1480_INT_DM_CH_3               _BCM1480_INT_HIGH(31)
+#define K_BCM1480_INT_MAC_0                 _BCM1480_INT_HIGH(36)
+#define K_BCM1480_INT_MAC_0_CH1             _BCM1480_INT_HIGH(37)
+#define K_BCM1480_INT_MAC_1                 _BCM1480_INT_HIGH(38)
+#define K_BCM1480_INT_MAC_1_CH1             _BCM1480_INT_HIGH(39)
+#define K_BCM1480_INT_MAC_2                 _BCM1480_INT_HIGH(40)
+#define K_BCM1480_INT_MAC_2_CH1             _BCM1480_INT_HIGH(41)
+#define K_BCM1480_INT_MAC_3                 _BCM1480_INT_HIGH(42)
+#define K_BCM1480_INT_MAC_3_CH1             _BCM1480_INT_HIGH(43)
+#define K_BCM1480_INT_PMI_LOW               _BCM1480_INT_HIGH(52)
+#define K_BCM1480_INT_PMI_HIGH              _BCM1480_INT_HIGH(53)
+#define K_BCM1480_INT_PMO_LOW               _BCM1480_INT_HIGH(54)
+#define K_BCM1480_INT_PMO_HIGH              _BCM1480_INT_HIGH(55)
+#define K_BCM1480_INT_MBOX_0_0              _BCM1480_INT_HIGH(56)
+#define K_BCM1480_INT_MBOX_0_1              _BCM1480_INT_HIGH(57)
+#define K_BCM1480_INT_MBOX_0_2              _BCM1480_INT_HIGH(58)
+#define K_BCM1480_INT_MBOX_0_3              _BCM1480_INT_HIGH(59)
+#define K_BCM1480_INT_MBOX_1_0              _BCM1480_INT_HIGH(60)
+#define K_BCM1480_INT_MBOX_1_1              _BCM1480_INT_HIGH(61)
+#define K_BCM1480_INT_MBOX_1_2              _BCM1480_INT_HIGH(62)
+#define K_BCM1480_INT_MBOX_1_3              _BCM1480_INT_HIGH(63)
+
+#define K_BCM1480_INT_BAD_ECC               _BCM1480_INT_LOW(1)
+#define K_BCM1480_INT_COR_ECC               _BCM1480_INT_LOW(2)
+#define K_BCM1480_INT_IO_BUS                _BCM1480_INT_LOW(3)
+#define K_BCM1480_INT_PERF_CNT              _BCM1480_INT_LOW(4)
+#define K_BCM1480_INT_SW_PERF_CNT           _BCM1480_INT_LOW(5)
+#define K_BCM1480_INT_TRACE_FREEZE          _BCM1480_INT_LOW(6)
+#define K_BCM1480_INT_SW_TRACE_FREEZE       _BCM1480_INT_LOW(7)
+#define K_BCM1480_INT_WATCHDOG_TIMER_0      _BCM1480_INT_LOW(8)
+#define K_BCM1480_INT_WATCHDOG_TIMER_1      _BCM1480_INT_LOW(9)
+#define K_BCM1480_INT_WATCHDOG_TIMER_2      _BCM1480_INT_LOW(10)
+#define K_BCM1480_INT_WATCHDOG_TIMER_3      _BCM1480_INT_LOW(11)
+#define K_BCM1480_INT_PCI_ERROR             _BCM1480_INT_LOW(16)
+#define K_BCM1480_INT_PCI_RESET             _BCM1480_INT_LOW(17)
+#define K_BCM1480_INT_NODE_CONTROLLER       _BCM1480_INT_LOW(18)
+#define K_BCM1480_INT_HOST_BRIDGE           _BCM1480_INT_LOW(19)
+#define K_BCM1480_INT_PORT_0_FATAL          _BCM1480_INT_LOW(20)
+#define K_BCM1480_INT_PORT_0_NONFATAL       _BCM1480_INT_LOW(21)
+#define K_BCM1480_INT_PORT_1_FATAL          _BCM1480_INT_LOW(22)
+#define K_BCM1480_INT_PORT_1_NONFATAL       _BCM1480_INT_LOW(23)
+#define K_BCM1480_INT_PORT_2_FATAL          _BCM1480_INT_LOW(24)
+#define K_BCM1480_INT_PORT_2_NONFATAL       _BCM1480_INT_LOW(25)
+#define K_BCM1480_INT_LDT_SMI               _BCM1480_INT_LOW(32)
+#define K_BCM1480_INT_LDT_NMI               _BCM1480_INT_LOW(33)
+#define K_BCM1480_INT_LDT_INIT              _BCM1480_INT_LOW(34)
+#define K_BCM1480_INT_LDT_STARTUP           _BCM1480_INT_LOW(35)
+#define K_BCM1480_INT_LDT_EXT               _BCM1480_INT_LOW(36)
+#define K_BCM1480_INT_SMB_0                 _BCM1480_INT_LOW(40)
+#define K_BCM1480_INT_SMB_1                 _BCM1480_INT_LOW(41)
+#define K_BCM1480_INT_PCMCIA                _BCM1480_INT_LOW(42)
+#define K_BCM1480_INT_UART_0                _BCM1480_INT_LOW(44)
+#define K_BCM1480_INT_UART_1                _BCM1480_INT_LOW(45)
+#define K_BCM1480_INT_UART_2                _BCM1480_INT_LOW(46)
+#define K_BCM1480_INT_UART_3                _BCM1480_INT_LOW(47)
+#define K_BCM1480_INT_GPIO_4                _BCM1480_INT_LOW(52)
+#define K_BCM1480_INT_GPIO_5                _BCM1480_INT_LOW(53)
+#define K_BCM1480_INT_GPIO_6                _BCM1480_INT_LOW(54)
+#define K_BCM1480_INT_GPIO_7                _BCM1480_INT_LOW(55)
+#define K_BCM1480_INT_GPIO_8                _BCM1480_INT_LOW(56)
+#define K_BCM1480_INT_GPIO_9                _BCM1480_INT_LOW(57)
+#define K_BCM1480_INT_GPIO_10               _BCM1480_INT_LOW(58)
+#define K_BCM1480_INT_GPIO_11               _BCM1480_INT_LOW(59)
+#define K_BCM1480_INT_GPIO_12               _BCM1480_INT_LOW(60)
+#define K_BCM1480_INT_GPIO_13               _BCM1480_INT_LOW(61)
+#define K_BCM1480_INT_GPIO_14               _BCM1480_INT_LOW(62)
+#define K_BCM1480_INT_GPIO_15               _BCM1480_INT_LOW(63)
+
+/*
+ * Mask values for each interrupt
+ */
+
+#define _BCM1480_INT_MASK1(n)               _SB_MAKEMASK1(((n) & 0x3F))
+#define _BCM1480_INT_OFFSET(n)              (((n) & 0x40) << 6)
+
+#define M_BCM1480_INT_CASCADE               _BCM1480_INT_MASK1(_BCM1480_INT_HIGH(0))
+
+#define M_BCM1480_INT_ADDR_TRAP             _BCM1480_INT_MASK1(K_BCM1480_INT_ADDR_TRAP)
+#define M_BCM1480_INT_GPIO_0                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_0)
+#define M_BCM1480_INT_GPIO_1                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_1)
+#define M_BCM1480_INT_GPIO_2                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_2)
+#define M_BCM1480_INT_GPIO_3                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_3)
+#define M_BCM1480_INT_PCI_INTA              _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTA)
+#define M_BCM1480_INT_PCI_INTB              _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTB)
+#define M_BCM1480_INT_PCI_INTC              _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTC)
+#define M_BCM1480_INT_PCI_INTD              _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_INTD)
+#define M_BCM1480_INT_CYCLE_CP0             _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP0)
+#define M_BCM1480_INT_CYCLE_CP1             _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP1)
+#define M_BCM1480_INT_CYCLE_CP2             _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP2)
+#define M_BCM1480_INT_CYCLE_CP3             _BCM1480_INT_MASK1(K_BCM1480_INT_CYCLE_CP3)
+#define M_BCM1480_INT_TIMER_0               _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_0)
+#define M_BCM1480_INT_TIMER_1               _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_1)
+#define M_BCM1480_INT_TIMER_2               _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_2)
+#define M_BCM1480_INT_TIMER_3               _BCM1480_INT_MASK1(K_BCM1480_INT_TIMER_3)
+#define M_BCM1480_INT_DM_CH_0               _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_0)
+#define M_BCM1480_INT_DM_CH_1               _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_1)
+#define M_BCM1480_INT_DM_CH_2               _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_2)
+#define M_BCM1480_INT_DM_CH_3               _BCM1480_INT_MASK1(K_BCM1480_INT_DM_CH_3)
+#define M_BCM1480_INT_MAC_0                 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_0)
+#define M_BCM1480_INT_MAC_0_CH1             _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_0_CH1)
+#define M_BCM1480_INT_MAC_1                 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_1)
+#define M_BCM1480_INT_MAC_1_CH1             _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_1_CH1)
+#define M_BCM1480_INT_MAC_2                 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_2)
+#define M_BCM1480_INT_MAC_2_CH1             _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_2_CH1)
+#define M_BCM1480_INT_MAC_3                 _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_3)
+#define M_BCM1480_INT_MAC_3_CH1             _BCM1480_INT_MASK1(K_BCM1480_INT_MAC_3_CH1)
+#define M_BCM1480_INT_PMI_LOW               _BCM1480_INT_MASK1(K_BCM1480_INT_PMI_LOW)
+#define M_BCM1480_INT_PMI_HIGH              _BCM1480_INT_MASK1(K_BCM1480_INT_PMI_HIGH)
+#define M_BCM1480_INT_PMO_LOW               _BCM1480_INT_MASK1(K_BCM1480_INT_PMO_LOW)
+#define M_BCM1480_INT_PMO_HIGH              _BCM1480_INT_MASK1(K_BCM1480_INT_PMO_HIGH)
+#define M_BCM1480_INT_MBOX_0_0              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_0)
+#define M_BCM1480_INT_MBOX_0_1              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_1)
+#define M_BCM1480_INT_MBOX_0_2              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_2)
+#define M_BCM1480_INT_MBOX_0_3              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_0_3)
+#define M_BCM1480_INT_MBOX_1_0              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_0)
+#define M_BCM1480_INT_MBOX_1_1              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_1)
+#define M_BCM1480_INT_MBOX_1_2              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_2)
+#define M_BCM1480_INT_MBOX_1_3              _BCM1480_INT_MASK1(K_BCM1480_INT_MBOX_1_3)
+#define M_BCM1480_INT_BAD_ECC               _BCM1480_INT_MASK1(K_BCM1480_INT_BAD_ECC)
+#define M_BCM1480_INT_COR_ECC               _BCM1480_INT_MASK1(K_BCM1480_INT_COR_ECC)
+#define M_BCM1480_INT_IO_BUS                _BCM1480_INT_MASK1(K_BCM1480_INT_IO_BUS)
+#define M_BCM1480_INT_PERF_CNT              _BCM1480_INT_MASK1(K_BCM1480_INT_PERF_CNT)
+#define M_BCM1480_INT_SW_PERF_CNT           _BCM1480_INT_MASK1(K_BCM1480_INT_SW_PERF_CNT)
+#define M_BCM1480_INT_TRACE_FREEZE          _BCM1480_INT_MASK1(K_BCM1480_INT_TRACE_FREEZE)
+#define M_BCM1480_INT_SW_TRACE_FREEZE       _BCM1480_INT_MASK1(K_BCM1480_INT_SW_TRACE_FREEZE)
+#define M_BCM1480_INT_WATCHDOG_TIMER_0      _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_0)
+#define M_BCM1480_INT_WATCHDOG_TIMER_1      _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_1)
+#define M_BCM1480_INT_WATCHDOG_TIMER_2      _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_2)
+#define M_BCM1480_INT_WATCHDOG_TIMER_3      _BCM1480_INT_MASK1(K_BCM1480_INT_WATCHDOG_TIMER_3)
+#define M_BCM1480_INT_PCI_ERROR             _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_ERROR)
+#define M_BCM1480_INT_PCI_RESET             _BCM1480_INT_MASK1(K_BCM1480_INT_PCI_RESET)
+#define M_BCM1480_INT_NODE_CONTROLLER       _BCM1480_INT_MASK1(K_BCM1480_INT_NODE_CONTROLLER)
+#define M_BCM1480_INT_HOST_BRIDGE           _BCM1480_INT_MASK1(K_BCM1480_INT_HOST_BRIDGE)
+#define M_BCM1480_INT_PORT_0_FATAL          _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_0_FATAL)
+#define M_BCM1480_INT_PORT_0_NONFATAL       _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_0_NONFATAL)
+#define M_BCM1480_INT_PORT_1_FATAL          _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_1_FATAL)
+#define M_BCM1480_INT_PORT_1_NONFATAL       _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_1_NONFATAL)
+#define M_BCM1480_INT_PORT_2_FATAL          _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_2_FATAL)
+#define M_BCM1480_INT_PORT_2_NONFATAL       _BCM1480_INT_MASK1(K_BCM1480_INT_PORT_2_NONFATAL)
+#define M_BCM1480_INT_LDT_SMI               _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_SMI)
+#define M_BCM1480_INT_LDT_NMI               _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_NMI)
+#define M_BCM1480_INT_LDT_INIT              _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_INIT)
+#define M_BCM1480_INT_LDT_STARTUP           _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_STARTUP)
+#define M_BCM1480_INT_LDT_EXT               _BCM1480_INT_MASK1(K_BCM1480_INT_LDT_EXT)
+#define M_BCM1480_INT_SMB_0                 _BCM1480_INT_MASK1(K_BCM1480_INT_SMB_0)
+#define M_BCM1480_INT_SMB_1                 _BCM1480_INT_MASK1(K_BCM1480_INT_SMB_1)
+#define M_BCM1480_INT_PCMCIA                _BCM1480_INT_MASK1(K_BCM1480_INT_PCMCIA)
+#define M_BCM1480_INT_UART_0                _BCM1480_INT_MASK1(K_BCM1480_INT_UART_0)
+#define M_BCM1480_INT_UART_1                _BCM1480_INT_MASK1(K_BCM1480_INT_UART_1)
+#define M_BCM1480_INT_UART_2                _BCM1480_INT_MASK1(K_BCM1480_INT_UART_2)
+#define M_BCM1480_INT_UART_3                _BCM1480_INT_MASK1(K_BCM1480_INT_UART_3)
+#define M_BCM1480_INT_GPIO_4                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_4)
+#define M_BCM1480_INT_GPIO_5                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_5)
+#define M_BCM1480_INT_GPIO_6                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_6)
+#define M_BCM1480_INT_GPIO_7                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_7)
+#define M_BCM1480_INT_GPIO_8                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_8)
+#define M_BCM1480_INT_GPIO_9                _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_9)
+#define M_BCM1480_INT_GPIO_10               _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_10)
+#define M_BCM1480_INT_GPIO_11               _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_11)
+#define M_BCM1480_INT_GPIO_12               _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_12)
+#define M_BCM1480_INT_GPIO_13               _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_13)
+#define M_BCM1480_INT_GPIO_14               _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_14)
+#define M_BCM1480_INT_GPIO_15               _BCM1480_INT_MASK1(K_BCM1480_INT_GPIO_15)
+
+/*
+ * Interrupt mappings (Table 18)
+ */
+
+#define K_BCM1480_INT_MAP_I0    0		/* interrupt pins on processor */
+#define K_BCM1480_INT_MAP_I1    1
+#define K_BCM1480_INT_MAP_I2    2
+#define K_BCM1480_INT_MAP_I3    3
+#define K_BCM1480_INT_MAP_I4    4
+#define K_BCM1480_INT_MAP_I5    5
+#define K_BCM1480_INT_MAP_NMI   6		/* nonmaskable */
+#define K_BCM1480_INT_MAP_DINT  7		/* debug interrupt */
+
+/*
+ * Interrupt LDT Set Register (Table 19)
+ */
+
+#define S_BCM1480_INT_HT_INTMSG             0
+#define M_BCM1480_INT_HT_INTMSG             _SB_MAKEMASK(3,S_BCM1480_INT_HT_INTMSG)
+#define V_BCM1480_INT_HT_INTMSG(x)          _SB_MAKEVALUE(x,S_BCM1480_INT_HT_INTMSG)
+#define G_BCM1480_INT_HT_INTMSG(x)          _SB_GETVALUE(x,S_BCM1480_INT_HT_INTMSG,M_BCM1480_INT_HT_INTMSG)
+
+#define K_BCM1480_INT_HT_INTMSG_FIXED       0
+#define K_BCM1480_INT_HT_INTMSG_ARBITRATED  1
+#define K_BCM1480_INT_HT_INTMSG_SMI         2
+#define K_BCM1480_INT_HT_INTMSG_NMI         3
+#define K_BCM1480_INT_HT_INTMSG_INIT        4
+#define K_BCM1480_INT_HT_INTMSG_STARTUP     5
+#define K_BCM1480_INT_HT_INTMSG_EXTINT      6
+#define K_BCM1480_INT_HT_INTMSG_RESERVED    7
+
+#define M_BCM1480_INT_HT_TRIGGERMODE        _SB_MAKEMASK1(3)
+#define V_BCM1480_INT_HT_EDGETRIGGER        0
+#define V_BCM1480_INT_HT_LEVELTRIGGER       M_BCM1480_INT_HT_TRIGGERMODE
+
+#define M_BCM1480_INT_HT_DESTMODE           _SB_MAKEMASK1(4)
+#define V_BCM1480_INT_HT_PHYSICALDEST       0
+#define V_BCM1480_INT_HT_LOGICALDEST        M_BCM1480_INT_HT_DESTMODE
+
+#define S_BCM1480_INT_HT_INTDEST            5
+#define M_BCM1480_INT_HT_INTDEST            _SB_MAKEMASK(8,S_BCM1480_INT_HT_INTDEST)
+#define V_BCM1480_INT_HT_INTDEST(x)         _SB_MAKEVALUE(x,S_BCM1480_INT_HT_INTDEST)
+#define G_BCM1480_INT_HT_INTDEST(x)         _SB_GETVALUE(x,S_BCM1480_INT_HT_INTDEST,M_BCM1480_INT_HT_INTDEST)
+
+#define S_BCM1480_INT_HT_VECTOR             13
+#define M_BCM1480_INT_HT_VECTOR             _SB_MAKEMASK(8,S_BCM1480_INT_HT_VECTOR)
+#define V_BCM1480_INT_HT_VECTOR(x)          _SB_MAKEVALUE(x,S_BCM1480_INT_HT_VECTOR)
+#define G_BCM1480_INT_HT_VECTOR(x)          _SB_GETVALUE(x,S_BCM1480_INT_HT_VECTOR,M_BCM1480_INT_HT_VECTOR)
+
+/*
+ * Vector prefix (Table 4-7)
+ */
+
+#define M_BCM1480_HTVECT_RAISE_INTLDT_HIGH  0x00
+#define M_BCM1480_HTVECT_RAISE_MBOX_0       0x40
+#define M_BCM1480_HTVECT_RAISE_INTLDT_LO    0x80
+#define M_BCM1480_HTVECT_RAISE_MBOX_1       0xC0
+
+#endif /* _BCM1480_INT_H */
diff --git a/include/asm-mips/sibyte/bcm1480_l2c.h b/include/asm-mips/sibyte/bcm1480_l2c.h
new file mode 100644
index 0000000..886b099
--- /dev/null
+++ b/include/asm-mips/sibyte/bcm1480_l2c.h
@@ -0,0 +1,176 @@
+/*  *********************************************************************
+    *  BCM1280/BCM1480 Board Support Package
+    *
+    *  L2 Cache constants and macros		File: bcm1480_l2c.h
+    *
+    *  This module contains constants useful for manipulating the
+    *  level 2 cache.
+    *
+    *  BCM1400 specification level:  1280-UM100-D2 (11/14/03)
+    *
+    *********************************************************************
+    *
+    *  Copyright 2000,2001,2002,2003
+    *  Broadcom Corporation. 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
+    ********************************************************************* */
+
+
+#ifndef _BCM1480_L2C_H
+#define _BCM1480_L2C_H
+
+#include "sb1250_defs.h"
+
+/*
+ * Format of level 2 cache management address (Table 55)
+ */
+
+#define S_BCM1480_L2C_MGMT_INDEX            5
+#define M_BCM1480_L2C_MGMT_INDEX            _SB_MAKEMASK(12,S_BCM1480_L2C_MGMT_INDEX)
+#define V_BCM1480_L2C_MGMT_INDEX(x)         _SB_MAKEVALUE(x,S_BCM1480_L2C_MGMT_INDEX)
+#define G_BCM1480_L2C_MGMT_INDEX(x)         _SB_GETVALUE(x,S_BCM1480_L2C_MGMT_INDEX,M_BCM1480_L2C_MGMT_INDEX)
+
+#define S_BCM1480_L2C_MGMT_WAY              17
+#define M_BCM1480_L2C_MGMT_WAY              _SB_MAKEMASK(3,S_BCM1480_L2C_MGMT_WAY)
+#define V_BCM1480_L2C_MGMT_WAY(x)           _SB_MAKEVALUE(x,S_BCM1480_L2C_MGMT_WAY)
+#define G_BCM1480_L2C_MGMT_WAY(x)           _SB_GETVALUE(x,S_BCM1480_L2C_MGMT_WAY,M_BCM1480_L2C_MGMT_WAY)
+
+#define M_BCM1480_L2C_MGMT_DIRTY            _SB_MAKEMASK1(20)
+#define M_BCM1480_L2C_MGMT_VALID            _SB_MAKEMASK1(21)
+
+#define S_BCM1480_L2C_MGMT_ECC_DIAG         22
+#define M_BCM1480_L2C_MGMT_ECC_DIAG         _SB_MAKEMASK(2,S_BCM1480_L2C_MGMT_ECC_DIAG)
+#define V_BCM1480_L2C_MGMT_ECC_DIAG(x)      _SB_MAKEVALUE(x,S_BCM1480_L2C_MGMT_ECC_DIAG)
+#define G_BCM1480_L2C_MGMT_ECC_DIAG(x)      _SB_GETVALUE(x,S_BCM1480_L2C_MGMT_ECC_DIAG,M_BCM1480_L2C_MGMT_ECC_DIAG)
+
+#define A_BCM1480_L2C_MGMT_TAG_BASE         0x00D0000000
+
+#define BCM1480_L2C_ENTRIES_PER_WAY         4096
+#define BCM1480_L2C_NUM_WAYS                8
+
+
+/*
+ * Level 2 Cache Tag register (Table 59)
+ */
+
+#define S_BCM1480_L2C_TAG_MBZ               0
+#define M_BCM1480_L2C_TAG_MBZ               _SB_MAKEMASK(5,S_BCM1480_L2C_TAG_MBZ)
+
+#define S_BCM1480_L2C_TAG_INDEX             5
+#define M_BCM1480_L2C_TAG_INDEX             _SB_MAKEMASK(12,S_BCM1480_L2C_TAG_INDEX)
+#define V_BCM1480_L2C_TAG_INDEX(x)          _SB_MAKEVALUE(x,S_BCM1480_L2C_TAG_INDEX)
+#define G_BCM1480_L2C_TAG_INDEX(x)          _SB_GETVALUE(x,S_BCM1480_L2C_TAG_INDEX,M_BCM1480_L2C_TAG_INDEX)
+
+/* Note that index bit 16 is also tag bit 40 */
+#define S_BCM1480_L2C_TAG_TAG               17
+#define M_BCM1480_L2C_TAG_TAG               _SB_MAKEMASK(23,S_BCM1480_L2C_TAG_TAG)
+#define V_BCM1480_L2C_TAG_TAG(x)            _SB_MAKEVALUE(x,S_BCM1480_L2C_TAG_TAG)
+#define G_BCM1480_L2C_TAG_TAG(x)            _SB_GETVALUE(x,S_BCM1480_L2C_TAG_TAG,M_BCM1480_L2C_TAG_TAG)
+
+#define S_BCM1480_L2C_TAG_ECC               40
+#define M_BCM1480_L2C_TAG_ECC               _SB_MAKEMASK(6,S_BCM1480_L2C_TAG_ECC)
+#define V_BCM1480_L2C_TAG_ECC(x)            _SB_MAKEVALUE(x,S_BCM1480_L2C_TAG_ECC)
+#define G_BCM1480_L2C_TAG_ECC(x)            _SB_GETVALUE(x,S_BCM1480_L2C_TAG_ECC,M_BCM1480_L2C_TAG_ECC)
+
+#define S_BCM1480_L2C_TAG_WAY               46
+#define M_BCM1480_L2C_TAG_WAY               _SB_MAKEMASK(3,S_BCM1480_L2C_TAG_WAY)
+#define V_BCM1480_L2C_TAG_WAY(x)            _SB_MAKEVALUE(x,S_BCM1480_L2C_TAG_WAY)
+#define G_BCM1480_L2C_TAG_WAY(x)            _SB_GETVALUE(x,S_BCM1480_L2C_TAG_WAY,M_BCM1480_L2C_TAG_WAY)
+
+#define M_BCM1480_L2C_TAG_DIRTY             _SB_MAKEMASK1(49)
+#define M_BCM1480_L2C_TAG_VALID             _SB_MAKEMASK1(50)
+
+#define S_BCM1480_L2C_DATA_ECC              51
+#define M_BCM1480_L2C_DATA_ECC              _SB_MAKEMASK(10,S_BCM1480_L2C_DATA_ECC)
+#define V_BCM1480_L2C_DATA_ECC(x)           _SB_MAKEVALUE(x,S_BCM1480_L2C_DATA_ECC)
+#define G_BCM1480_L2C_DATA_ECC(x)           _SB_GETVALUE(x,S_BCM1480_L2C_DATA_ECC,M_BCM1480_L2C_DATA_ECC)
+
+
+/*
+ * L2 Misc0 Value Register (Table 60)
+ */
+
+#define S_BCM1480_L2C_MISC0_WAY_REMOTE      0
+#define M_BCM1480_L2C_MISC0_WAY_REMOTE      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC0_WAY_REMOTE)
+#define G_BCM1480_L2C_MISC0_WAY_REMOTE(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC0_WAY_REMOTE,M_BCM1480_L2C_MISC0_WAY_REMOTE)
+
+#define S_BCM1480_L2C_MISC0_WAY_LOCAL       8
+#define M_BCM1480_L2C_MISC0_WAY_LOCAL       _SB_MAKEMASK(8,S_BCM1480_L2C_MISC0_WAY_LOCAL)
+#define G_BCM1480_L2C_MISC0_WAY_LOCAL(x)    _SB_GETVALUE(x,S_BCM1480_L2C_MISC0_WAY_LOCAL,M_BCM1480_L2C_MISC0_WAY_LOCAL)
+
+#define S_BCM1480_L2C_MISC0_WAY_ENABLE      16
+#define M_BCM1480_L2C_MISC0_WAY_ENABLE      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC0_WAY_ENABLE)
+#define G_BCM1480_L2C_MISC0_WAY_ENABLE(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC0_WAY_ENABLE,M_BCM1480_L2C_MISC0_WAY_ENABLE)
+
+#define S_BCM1480_L2C_MISC0_CACHE_DISABLE   24
+#define M_BCM1480_L2C_MISC0_CACHE_DISABLE   _SB_MAKEMASK(2,S_BCM1480_L2C_MISC0_CACHE_DISABLE)
+#define G_BCM1480_L2C_MISC0_CACHE_DISABLE(x) _SB_GETVALUE(x,S_BCM1480_L2C_MISC0_CACHE_DISABLE,M_BCM1480_L2C_MISC0_CACHE_DISABLE)
+
+#define S_BCM1480_L2C_MISC0_CACHE_QUAD      26
+#define M_BCM1480_L2C_MISC0_CACHE_QUAD      _SB_MAKEMASK(2,S_BCM1480_L2C_MISC0_CACHE_QUAD)
+#define G_BCM1480_L2C_MISC0_CACHE_QUAD(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC0_CACHE_QUAD,M_BCM1480_L2C_MISC0_CACHE_QUAD)
+
+#define S_BCM1480_L2C_MISC0_MC_PRIORITY      30
+#define M_BCM1480_L2C_MISC0_MC_PRIORITY      _SB_MAKEMASK1(S_BCM1480_L2C_MISC0_MC_PRIORITY)
+
+#define S_BCM1480_L2C_MISC0_ECC_CLEANUP      31
+#define M_BCM1480_L2C_MISC0_ECC_CLEANUP      _SB_MAKEMASK1(S_BCM1480_L2C_MISC0_ECC_CLEANUP)
+
+
+/*
+ * L2 Misc1 Value Register (Table 60)
+ */
+
+#define S_BCM1480_L2C_MISC1_WAY_AGENT_0      0
+#define M_BCM1480_L2C_MISC1_WAY_AGENT_0      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC1_WAY_AGENT_0)
+#define G_BCM1480_L2C_MISC1_WAY_AGENT_0(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC1_WAY_AGENT_0,M_BCM1480_L2C_MISC1_WAY_AGENT_0)
+
+#define S_BCM1480_L2C_MISC1_WAY_AGENT_1      8
+#define M_BCM1480_L2C_MISC1_WAY_AGENT_1      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC1_WAY_AGENT_1)
+#define G_BCM1480_L2C_MISC1_WAY_AGENT_1(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC1_WAY_AGENT_1,M_BCM1480_L2C_MISC1_WAY_AGENT_1)
+
+#define S_BCM1480_L2C_MISC1_WAY_AGENT_2      16
+#define M_BCM1480_L2C_MISC1_WAY_AGENT_2      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC1_WAY_AGENT_2)
+#define G_BCM1480_L2C_MISC1_WAY_AGENT_2(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC1_WAY_AGENT_2,M_BCM1480_L2C_MISC1_WAY_AGENT_2)
+
+#define S_BCM1480_L2C_MISC1_WAY_AGENT_3      24
+#define M_BCM1480_L2C_MISC1_WAY_AGENT_3      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC1_WAY_AGENT_3)
+#define G_BCM1480_L2C_MISC1_WAY_AGENT_3(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC1_WAY_AGENT_3,M_BCM1480_L2C_MISC1_WAY_AGENT_3)
+
+#define S_BCM1480_L2C_MISC1_WAY_AGENT_4      32
+#define M_BCM1480_L2C_MISC1_WAY_AGENT_4      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC1_WAY_AGENT_4)
+#define G_BCM1480_L2C_MISC1_WAY_AGENT_4(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC1_WAY_AGENT_4,M_BCM1480_L2C_MISC1_WAY_AGENT_4)
+
+
+/*
+ * L2 Misc2 Value Register (Table 60)
+ */
+
+#define S_BCM1480_L2C_MISC2_WAY_AGENT_8      0
+#define M_BCM1480_L2C_MISC2_WAY_AGENT_8      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC2_WAY_AGENT_8)
+#define G_BCM1480_L2C_MISC2_WAY_AGENT_8(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC2_WAY_AGENT_8,M_BCM1480_L2C_MISC2_WAY_AGENT_8)
+
+#define S_BCM1480_L2C_MISC2_WAY_AGENT_9      8
+#define M_BCM1480_L2C_MISC2_WAY_AGENT_9      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC2_WAY_AGENT_9)
+#define G_BCM1480_L2C_MISC2_WAY_AGENT_9(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC2_WAY_AGENT_9,M_BCM1480_L2C_MISC2_WAY_AGENT_9)
+
+#define S_BCM1480_L2C_MISC2_WAY_AGENT_A      16
+#define M_BCM1480_L2C_MISC2_WAY_AGENT_A      _SB_MAKEMASK(8,S_BCM1480_L2C_MISC2_WAY_AGENT_A)
+#define G_BCM1480_L2C_MISC2_WAY_AGENT_A(x)   _SB_GETVALUE(x,S_BCM1480_L2C_MISC2_WAY_AGENT_A,M_BCM1480_L2C_MISC2_WAY_AGENT_A)
+
+
+#endif /* _BCM1480_L2C_H */
diff --git a/include/asm-mips/sibyte/bcm1480_mc.h b/include/asm-mips/sibyte/bcm1480_mc.h
new file mode 100644
index 0000000..6bdc941
--- /dev/null
+++ b/include/asm-mips/sibyte/bcm1480_mc.h
@@ -0,0 +1,962 @@
+/*  *********************************************************************
+    *  BCM1280/BCM1480 Board Support Package
+    *
+    *  Memory Controller constants              File: bcm1480_mc.h
+    *
+    *  This module contains constants and macros useful for
+    *  programming the memory controller.
+    *
+    *  BCM1400 specification level:  1280-UM100-D1 (11/14/03 Review Copy)
+    *
+    *********************************************************************
+    *
+    *  Copyright 2000,2001,2002,2003
+    *  Broadcom Corporation. 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
+    ********************************************************************* */
+
+
+#ifndef _BCM1480_MC_H
+#define _BCM1480_MC_H
+
+#include "sb1250_defs.h"
+
+/*
+ * Memory Channel Configuration Register (Table 81)
+ */
+
+#define S_BCM1480_MC_INTLV0                 0
+#define M_BCM1480_MC_INTLV0                 _SB_MAKEMASK(6,S_BCM1480_MC_INTLV0)
+#define V_BCM1480_MC_INTLV0(x)              _SB_MAKEVALUE(x,S_BCM1480_MC_INTLV0)
+#define G_BCM1480_MC_INTLV0(x)              _SB_GETVALUE(x,S_BCM1480_MC_INTLV0,M_BCM1480_MC_INTLV0)
+#define V_BCM1480_MC_INTLV0_DEFAULT         V_BCM1480_MC_INTLV0(0)
+
+#define S_BCM1480_MC_INTLV1                 8
+#define M_BCM1480_MC_INTLV1                 _SB_MAKEMASK(6,S_BCM1480_MC_INTLV1)
+#define V_BCM1480_MC_INTLV1(x)              _SB_MAKEVALUE(x,S_BCM1480_MC_INTLV1)
+#define G_BCM1480_MC_INTLV1(x)              _SB_GETVALUE(x,S_BCM1480_MC_INTLV1,M_BCM1480_MC_INTLV1)
+#define V_BCM1480_MC_INTLV1_DEFAULT         V_BCM1480_MC_INTLV1(0)
+
+#define S_BCM1480_MC_INTLV2                 16
+#define M_BCM1480_MC_INTLV2                 _SB_MAKEMASK(6,S_BCM1480_MC_INTLV2)
+#define V_BCM1480_MC_INTLV2(x)              _SB_MAKEVALUE(x,S_BCM1480_MC_INTLV2)
+#define G_BCM1480_MC_INTLV2(x)              _SB_GETVALUE(x,S_BCM1480_MC_INTLV2,M_BCM1480_MC_INTLV2)
+#define V_BCM1480_MC_INTLV2_DEFAULT         V_BCM1480_MC_INTLV2(0)
+
+#define S_BCM1480_MC_CS_MODE                32
+#define M_BCM1480_MC_CS_MODE                _SB_MAKEMASK(8,S_BCM1480_MC_CS_MODE)
+#define V_BCM1480_MC_CS_MODE(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_CS_MODE)
+#define G_BCM1480_MC_CS_MODE(x)             _SB_GETVALUE(x,S_BCM1480_MC_CS_MODE,M_BCM1480_MC_CS_MODE)
+#define V_BCM1480_MC_CS_MODE_DEFAULT        V_BCM1480_MC_CS_MODE(0)
+
+#define V_BCM1480_MC_CONFIG_DEFAULT         (V_BCM1480_MC_INTLV0_DEFAULT  | \
+                                     V_BCM1480_MC_INTLV1_DEFAULT  | \
+                                     V_BCM1480_MC_INTLV2_DEFAULT  | \
+				     V_BCM1480_MC_CS_MODE_DEFAULT)
+
+#define K_BCM1480_MC_CS01_MODE		    0x03
+#define K_BCM1480_MC_CS02_MODE		    0x05
+#define K_BCM1480_MC_CS0123_MODE	    0x0F
+#define K_BCM1480_MC_CS0246_MODE	    0x55
+#define K_BCM1480_MC_CS0145_MODE	    0x33
+#define K_BCM1480_MC_CS0167_MODE	    0xC3
+#define K_BCM1480_MC_CSFULL_MODE	    0xFF
+
+/*
+ * Chip Select Start Address Register (Table 82)
+ */
+
+#define S_BCM1480_MC_CS0_START              0
+#define M_BCM1480_MC_CS0_START              _SB_MAKEMASK(12,S_BCM1480_MC_CS0_START)
+#define V_BCM1480_MC_CS0_START(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_CS0_START)
+#define G_BCM1480_MC_CS0_START(x)           _SB_GETVALUE(x,S_BCM1480_MC_CS0_START,M_BCM1480_MC_CS0_START)
+
+#define S_BCM1480_MC_CS1_START              16
+#define M_BCM1480_MC_CS1_START              _SB_MAKEMASK(12,S_BCM1480_MC_CS1_START)
+#define V_BCM1480_MC_CS1_START(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_CS1_START)
+#define G_BCM1480_MC_CS1_START(x)           _SB_GETVALUE(x,S_BCM1480_MC_CS1_START,M_BCM1480_MC_CS1_START)
+
+#define S_BCM1480_MC_CS2_START              32
+#define M_BCM1480_MC_CS2_START              _SB_MAKEMASK(12,S_BCM1480_MC_CS2_START)
+#define V_BCM1480_MC_CS2_START(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_CS2_START)
+#define G_BCM1480_MC_CS2_START(x)           _SB_GETVALUE(x,S_BCM1480_MC_CS2_START,M_BCM1480_MC_CS2_START)
+
+#define S_BCM1480_MC_CS3_START              48
+#define M_BCM1480_MC_CS3_START              _SB_MAKEMASK(12,S_BCM1480_MC_CS3_START)
+#define V_BCM1480_MC_CS3_START(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_CS3_START)
+#define G_BCM1480_MC_CS3_START(x)           _SB_GETVALUE(x,S_BCM1480_MC_CS3_START,M_BCM1480_MC_CS3_START)
+
+/*
+ * Chip Select End Address Register (Table 83)
+ */
+
+#define S_BCM1480_MC_CS0_END                0
+#define M_BCM1480_MC_CS0_END                _SB_MAKEMASK(12,S_BCM1480_MC_CS0_END)
+#define V_BCM1480_MC_CS0_END(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_CS0_END)
+#define G_BCM1480_MC_CS0_END(x)             _SB_GETVALUE(x,S_BCM1480_MC_CS0_END,M_BCM1480_MC_CS0_END)
+
+#define S_BCM1480_MC_CS1_END                16
+#define M_BCM1480_MC_CS1_END                _SB_MAKEMASK(12,S_BCM1480_MC_CS1_END)
+#define V_BCM1480_MC_CS1_END(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_CS1_END)
+#define G_BCM1480_MC_CS1_END(x)             _SB_GETVALUE(x,S_BCM1480_MC_CS1_END,M_BCM1480_MC_CS1_END)
+
+#define S_BCM1480_MC_CS2_END                32
+#define M_BCM1480_MC_CS2_END                _SB_MAKEMASK(12,S_BCM1480_MC_CS2_END)
+#define V_BCM1480_MC_CS2_END(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_CS2_END)
+#define G_BCM1480_MC_CS2_END(x)             _SB_GETVALUE(x,S_BCM1480_MC_CS2_END,M_BCM1480_MC_CS2_END)
+
+#define S_BCM1480_MC_CS3_END                48
+#define M_BCM1480_MC_CS3_END                _SB_MAKEMASK(12,S_BCM1480_MC_CS3_END)
+#define V_BCM1480_MC_CS3_END(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_CS3_END)
+#define G_BCM1480_MC_CS3_END(x)             _SB_GETVALUE(x,S_BCM1480_MC_CS3_END,M_BCM1480_MC_CS3_END)
+
+/*
+ * Row Address Bit Select Register 0 (Table 84)
+ */
+
+#define S_BCM1480_MC_ROW00                  0
+#define M_BCM1480_MC_ROW00                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW00)
+#define V_BCM1480_MC_ROW00(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW00)
+#define G_BCM1480_MC_ROW00(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW00,M_BCM1480_MC_ROW00)
+
+#define S_BCM1480_MC_ROW01                  8
+#define M_BCM1480_MC_ROW01                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW01)
+#define V_BCM1480_MC_ROW01(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW01)
+#define G_BCM1480_MC_ROW01(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW01,M_BCM1480_MC_ROW01)
+
+#define S_BCM1480_MC_ROW02                  16
+#define M_BCM1480_MC_ROW02                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW02)
+#define V_BCM1480_MC_ROW02(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW02)
+#define G_BCM1480_MC_ROW02(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW02,M_BCM1480_MC_ROW02)
+
+#define S_BCM1480_MC_ROW03                  24
+#define M_BCM1480_MC_ROW03                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW03)
+#define V_BCM1480_MC_ROW03(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW03)
+#define G_BCM1480_MC_ROW03(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW03,M_BCM1480_MC_ROW03)
+
+#define S_BCM1480_MC_ROW04                  32
+#define M_BCM1480_MC_ROW04                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW04)
+#define V_BCM1480_MC_ROW04(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW04)
+#define G_BCM1480_MC_ROW04(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW04,M_BCM1480_MC_ROW04)
+
+#define S_BCM1480_MC_ROW05                  40
+#define M_BCM1480_MC_ROW05                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW05)
+#define V_BCM1480_MC_ROW05(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW05)
+#define G_BCM1480_MC_ROW05(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW05,M_BCM1480_MC_ROW05)
+
+#define S_BCM1480_MC_ROW06                  48
+#define M_BCM1480_MC_ROW06                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW06)
+#define V_BCM1480_MC_ROW06(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW06)
+#define G_BCM1480_MC_ROW06(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW06,M_BCM1480_MC_ROW06)
+
+#define S_BCM1480_MC_ROW07                  56
+#define M_BCM1480_MC_ROW07                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW07)
+#define V_BCM1480_MC_ROW07(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW07)
+#define G_BCM1480_MC_ROW07(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW07,M_BCM1480_MC_ROW07)
+
+/*
+ * Row Address Bit Select Register 1 (Table 85)
+ */
+
+#define S_BCM1480_MC_ROW08                  0
+#define M_BCM1480_MC_ROW08                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW08)
+#define V_BCM1480_MC_ROW08(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW08)
+#define G_BCM1480_MC_ROW08(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW08,M_BCM1480_MC_ROW08)
+
+#define S_BCM1480_MC_ROW09                  8
+#define M_BCM1480_MC_ROW09                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW09)
+#define V_BCM1480_MC_ROW09(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW09)
+#define G_BCM1480_MC_ROW09(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW09,M_BCM1480_MC_ROW09)
+
+#define S_BCM1480_MC_ROW10                  16
+#define M_BCM1480_MC_ROW10                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW10)
+#define V_BCM1480_MC_ROW10(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW10)
+#define G_BCM1480_MC_ROW10(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW10,M_BCM1480_MC_ROW10)
+
+#define S_BCM1480_MC_ROW11                  24
+#define M_BCM1480_MC_ROW11                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW11)
+#define V_BCM1480_MC_ROW11(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW11)
+#define G_BCM1480_MC_ROW11(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW11,M_BCM1480_MC_ROW11)
+
+#define S_BCM1480_MC_ROW12                  32
+#define M_BCM1480_MC_ROW12                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW12)
+#define V_BCM1480_MC_ROW12(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW12)
+#define G_BCM1480_MC_ROW12(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW12,M_BCM1480_MC_ROW12)
+
+#define S_BCM1480_MC_ROW13                  40
+#define M_BCM1480_MC_ROW13                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW13)
+#define V_BCM1480_MC_ROW13(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW13)
+#define G_BCM1480_MC_ROW13(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW13,M_BCM1480_MC_ROW13)
+
+#define S_BCM1480_MC_ROW14                  48
+#define M_BCM1480_MC_ROW14                  _SB_MAKEMASK(6,S_BCM1480_MC_ROW14)
+#define V_BCM1480_MC_ROW14(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_ROW14)
+#define G_BCM1480_MC_ROW14(x)               _SB_GETVALUE(x,S_BCM1480_MC_ROW14,M_BCM1480_MC_ROW14)
+
+#define K_BCM1480_MC_ROWX_BIT_SPACING  	    8
+
+/*
+ * Column Address Bit Select Register 0 (Table 86)
+ */
+
+#define S_BCM1480_MC_COL00                  0
+#define M_BCM1480_MC_COL00                  _SB_MAKEMASK(6,S_BCM1480_MC_COL00)
+#define V_BCM1480_MC_COL00(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL00)
+#define G_BCM1480_MC_COL00(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL00,M_BCM1480_MC_COL00)
+
+#define S_BCM1480_MC_COL01                  8
+#define M_BCM1480_MC_COL01                  _SB_MAKEMASK(6,S_BCM1480_MC_COL01)
+#define V_BCM1480_MC_COL01(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL01)
+#define G_BCM1480_MC_COL01(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL01,M_BCM1480_MC_COL01)
+
+#define S_BCM1480_MC_COL02                  16
+#define M_BCM1480_MC_COL02                  _SB_MAKEMASK(6,S_BCM1480_MC_COL02)
+#define V_BCM1480_MC_COL02(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL02)
+#define G_BCM1480_MC_COL02(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL02,M_BCM1480_MC_COL02)
+
+#define S_BCM1480_MC_COL03                  24
+#define M_BCM1480_MC_COL03                  _SB_MAKEMASK(6,S_BCM1480_MC_COL03)
+#define V_BCM1480_MC_COL03(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL03)
+#define G_BCM1480_MC_COL03(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL03,M_BCM1480_MC_COL03)
+
+#define S_BCM1480_MC_COL04                  32
+#define M_BCM1480_MC_COL04                  _SB_MAKEMASK(6,S_BCM1480_MC_COL04)
+#define V_BCM1480_MC_COL04(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL04)
+#define G_BCM1480_MC_COL04(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL04,M_BCM1480_MC_COL04)
+
+#define S_BCM1480_MC_COL05                  40
+#define M_BCM1480_MC_COL05                  _SB_MAKEMASK(6,S_BCM1480_MC_COL05)
+#define V_BCM1480_MC_COL05(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL05)
+#define G_BCM1480_MC_COL05(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL05,M_BCM1480_MC_COL05)
+
+#define S_BCM1480_MC_COL06                  48
+#define M_BCM1480_MC_COL06                  _SB_MAKEMASK(6,S_BCM1480_MC_COL06)
+#define V_BCM1480_MC_COL06(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL06)
+#define G_BCM1480_MC_COL06(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL06,M_BCM1480_MC_COL06)
+
+#define S_BCM1480_MC_COL07                  56
+#define M_BCM1480_MC_COL07                  _SB_MAKEMASK(6,S_BCM1480_MC_COL07)
+#define V_BCM1480_MC_COL07(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL07)
+#define G_BCM1480_MC_COL07(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL07,M_BCM1480_MC_COL07)
+
+/*
+ * Column Address Bit Select Register 1 (Table 87)
+ */
+
+#define S_BCM1480_MC_COL08                  0
+#define M_BCM1480_MC_COL08                  _SB_MAKEMASK(6,S_BCM1480_MC_COL08)
+#define V_BCM1480_MC_COL08(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL08)
+#define G_BCM1480_MC_COL08(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL08,M_BCM1480_MC_COL08)
+
+#define S_BCM1480_MC_COL09                  8
+#define M_BCM1480_MC_COL09                  _SB_MAKEMASK(6,S_BCM1480_MC_COL09)
+#define V_BCM1480_MC_COL09(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL09)
+#define G_BCM1480_MC_COL09(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL09,M_BCM1480_MC_COL09)
+
+#define S_BCM1480_MC_COL10                  16   /* not a valid position, must be prog as 0 */
+
+#define S_BCM1480_MC_COL11                  24
+#define M_BCM1480_MC_COL11                  _SB_MAKEMASK(6,S_BCM1480_MC_COL11)
+#define V_BCM1480_MC_COL11(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL11)
+#define G_BCM1480_MC_COL11(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL11,M_BCM1480_MC_COL11)
+
+#define S_BCM1480_MC_COL12                  32
+#define M_BCM1480_MC_COL12                  _SB_MAKEMASK(6,S_BCM1480_MC_COL12)
+#define V_BCM1480_MC_COL12(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL12)
+#define G_BCM1480_MC_COL12(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL12,M_BCM1480_MC_COL12)
+
+#define S_BCM1480_MC_COL13                  40
+#define M_BCM1480_MC_COL13                  _SB_MAKEMASK(6,S_BCM1480_MC_COL13)
+#define V_BCM1480_MC_COL13(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL13)
+#define G_BCM1480_MC_COL13(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL13,M_BCM1480_MC_COL13)
+
+#define S_BCM1480_MC_COL14                  48
+#define M_BCM1480_MC_COL14                  _SB_MAKEMASK(6,S_BCM1480_MC_COL14)
+#define V_BCM1480_MC_COL14(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_COL14)
+#define G_BCM1480_MC_COL14(x)               _SB_GETVALUE(x,S_BCM1480_MC_COL14,M_BCM1480_MC_COL14)
+
+#define K_BCM1480_MC_COLX_BIT_SPACING  	    8
+
+/*
+ * CS0 and CS1 Bank Address Bit Select Register (Table 88)
+ */
+
+#define S_BCM1480_MC_CS01_BANK0             0
+#define M_BCM1480_MC_CS01_BANK0             _SB_MAKEMASK(6,S_BCM1480_MC_CS01_BANK0)
+#define V_BCM1480_MC_CS01_BANK0(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_CS01_BANK0)
+#define G_BCM1480_MC_CS01_BANK0(x)          _SB_GETVALUE(x,S_BCM1480_MC_CS01_BANK0,M_BCM1480_MC_CS01_BANK0)
+
+#define S_BCM1480_MC_CS01_BANK1             8
+#define M_BCM1480_MC_CS01_BANK1             _SB_MAKEMASK(6,S_BCM1480_MC_CS01_BANK1)
+#define V_BCM1480_MC_CS01_BANK1(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_CS01_BANK1)
+#define G_BCM1480_MC_CS01_BANK1(x)          _SB_GETVALUE(x,S_BCM1480_MC_CS01_BANK1,M_BCM1480_MC_CS01_BANK1)
+
+#define S_BCM1480_MC_CS01_BANK2             16
+#define M_BCM1480_MC_CS01_BANK2             _SB_MAKEMASK(6,S_BCM1480_MC_CS01_BANK2)
+#define V_BCM1480_MC_CS01_BANK2(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_CS01_BANK2)
+#define G_BCM1480_MC_CS01_BANK2(x)          _SB_GETVALUE(x,S_BCM1480_MC_CS01_BANK2,M_BCM1480_MC_CS01_BANK2)
+
+/*
+ * CS2 and CS3 Bank Address Bit Select Register (Table 89)
+ */
+
+#define S_BCM1480_MC_CS23_BANK0             0
+#define M_BCM1480_MC_CS23_BANK0             _SB_MAKEMASK(6,S_BCM1480_MC_CS23_BANK0)
+#define V_BCM1480_MC_CS23_BANK0(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_CS23_BANK0)
+#define G_BCM1480_MC_CS23_BANK0(x)          _SB_GETVALUE(x,S_BCM1480_MC_CS23_BANK0,M_BCM1480_MC_CS23_BANK0)
+
+#define S_BCM1480_MC_CS23_BANK1             8
+#define M_BCM1480_MC_CS23_BANK1             _SB_MAKEMASK(6,S_BCM1480_MC_CS23_BANK1)
+#define V_BCM1480_MC_CS23_BANK1(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_CS23_BANK1)
+#define G_BCM1480_MC_CS23_BANK1(x)          _SB_GETVALUE(x,S_BCM1480_MC_CS23_BANK1,M_BCM1480_MC_CS23_BANK1)
+
+#define S_BCM1480_MC_CS23_BANK2             16
+#define M_BCM1480_MC_CS23_BANK2             _SB_MAKEMASK(6,S_BCM1480_MC_CS23_BANK2)
+#define V_BCM1480_MC_CS23_BANK2(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_CS23_BANK2)
+#define G_BCM1480_MC_CS23_BANK2(x)          _SB_GETVALUE(x,S_BCM1480_MC_CS23_BANK2,M_BCM1480_MC_CS23_BANK2)
+
+#define K_BCM1480_MC_CSXX_BANKX_BIT_SPACING  8
+
+/*
+ * DRAM Command Register (Table 90)
+ */
+
+#define S_BCM1480_MC_COMMAND                0
+#define M_BCM1480_MC_COMMAND                _SB_MAKEMASK(4,S_BCM1480_MC_COMMAND)
+#define V_BCM1480_MC_COMMAND(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_COMMAND)
+#define G_BCM1480_MC_COMMAND(x)             _SB_GETVALUE(x,S_BCM1480_MC_COMMAND,M_BCM1480_MC_COMMAND)
+
+#define K_BCM1480_MC_COMMAND_EMRS           0
+#define K_BCM1480_MC_COMMAND_MRS            1
+#define K_BCM1480_MC_COMMAND_PRE            2
+#define K_BCM1480_MC_COMMAND_AR             3
+#define K_BCM1480_MC_COMMAND_SETRFSH        4
+#define K_BCM1480_MC_COMMAND_CLRRFSH        5
+#define K_BCM1480_MC_COMMAND_SETPWRDN       6
+#define K_BCM1480_MC_COMMAND_CLRPWRDN       7
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define K_BCM1480_MC_COMMAND_EMRS2	    8
+#define K_BCM1480_MC_COMMAND_EMRS3	    9
+#define K_BCM1480_MC_COMMAND_ENABLE_MCLK    10
+#define K_BCM1480_MC_COMMAND_DISABLE_MCLK   11
+#endif
+
+#define V_BCM1480_MC_COMMAND_EMRS           V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_EMRS)
+#define V_BCM1480_MC_COMMAND_MRS            V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_MRS)
+#define V_BCM1480_MC_COMMAND_PRE            V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_PRE)
+#define V_BCM1480_MC_COMMAND_AR             V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_AR)
+#define V_BCM1480_MC_COMMAND_SETRFSH        V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_SETRFSH)
+#define V_BCM1480_MC_COMMAND_CLRRFSH        V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_CLRRFSH)
+#define V_BCM1480_MC_COMMAND_SETPWRDN       V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_SETPWRDN)
+#define V_BCM1480_MC_COMMAND_CLRPWRDN       V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_CLRPWRDN)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define V_BCM1480_MC_COMMAND_EMRS2          V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_EMRS2)
+#define V_BCM1480_MC_COMMAND_EMRS3          V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_EMRS3)
+#define V_BCM1480_MC_COMMAND_ENABLE_MCLK    V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_ENABLE_MCLK)
+#define V_BCM1480_MC_COMMAND_DISABLE_MCLK   V_BCM1480_MC_COMMAND(K_BCM1480_MC_COMMAND_DISABLE_MCLK)
+#endif
+
+#define S_BCM1480_MC_CS0		    4
+#define M_BCM1480_MC_CS0                    _SB_MAKEMASK1(4)
+#define M_BCM1480_MC_CS1                    _SB_MAKEMASK1(5)
+#define M_BCM1480_MC_CS2                    _SB_MAKEMASK1(6)
+#define M_BCM1480_MC_CS3                    _SB_MAKEMASK1(7)
+#define M_BCM1480_MC_CS4                    _SB_MAKEMASK1(8)
+#define M_BCM1480_MC_CS5                    _SB_MAKEMASK1(9)
+#define M_BCM1480_MC_CS6                    _SB_MAKEMASK1(10)
+#define M_BCM1480_MC_CS7                    _SB_MAKEMASK1(11)
+
+#define M_BCM1480_MC_CMD_ACTIVE             _SB_MAKEMASK1(16)
+
+/*
+ * DRAM Mode Register (Table 91)
+ */
+
+#define S_BCM1480_MC_EMODE                  0
+#define M_BCM1480_MC_EMODE                  _SB_MAKEMASK(15,S_BCM1480_MC_EMODE)
+#define V_BCM1480_MC_EMODE(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_EMODE)
+#define G_BCM1480_MC_EMODE(x)               _SB_GETVALUE(x,S_BCM1480_MC_EMODE,M_BCM1480_MC_EMODE)
+#define V_BCM1480_MC_EMODE_DEFAULT          V_BCM1480_MC_EMODE(0)
+
+#define S_BCM1480_MC_MODE                   16
+#define M_BCM1480_MC_MODE                   _SB_MAKEMASK(15,S_BCM1480_MC_MODE)
+#define V_BCM1480_MC_MODE(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_MODE)
+#define G_BCM1480_MC_MODE(x)                _SB_GETVALUE(x,S_BCM1480_MC_MODE,M_BCM1480_MC_MODE)
+#define V_BCM1480_MC_MODE_DEFAULT           V_BCM1480_MC_MODE(0)
+
+#define S_BCM1480_MC_DRAM_TYPE              32
+#define M_BCM1480_MC_DRAM_TYPE              _SB_MAKEMASK(4,S_BCM1480_MC_DRAM_TYPE)
+#define V_BCM1480_MC_DRAM_TYPE(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_DRAM_TYPE)
+#define G_BCM1480_MC_DRAM_TYPE(x)           _SB_GETVALUE(x,S_BCM1480_MC_DRAM_TYPE,M_BCM1480_MC_DRAM_TYPE)
+
+#define K_BCM1480_MC_DRAM_TYPE_JEDEC        0
+#define K_BCM1480_MC_DRAM_TYPE_FCRAM        1
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define K_BCM1480_MC_DRAM_TYPE_DDR2	    2
+#endif
+
+#define V_BCM1480_MC_DRAM_TYPE_JEDEC        V_BCM1480_MC_DRAM_TYPE(K_BCM1480_MC_DRAM_TYPE_JEDEC)
+#define V_BCM1480_MC_DRAM_TYPE_FCRAM        V_BCM1480_MC_DRAM_TYPE(K_BCM1480_MC_DRAM_TYPE_FCRAM)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define V_BCM1480_MC_DRAM_TYPE_DDR2	    V_BCM1480_MC_DRAM_TYPE(K_BCM1480_MC_DRAM_TYPE_DDR2)
+#endif
+
+#define M_BCM1480_MC_GANGED                 _SB_MAKEMASK1(36)
+#define M_BCM1480_MC_BY9_INTF               _SB_MAKEMASK1(37)
+#define M_BCM1480_MC_FORCE_ECC64            _SB_MAKEMASK1(38)
+#define M_BCM1480_MC_ECC_DISABLE            _SB_MAKEMASK1(39)
+
+#define S_BCM1480_MC_PG_POLICY              40
+#define M_BCM1480_MC_PG_POLICY              _SB_MAKEMASK(2,S_BCM1480_MC_PG_POLICY)
+#define V_BCM1480_MC_PG_POLICY(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_PG_POLICY)
+#define G_BCM1480_MC_PG_POLICY(x)           _SB_GETVALUE(x,S_BCM1480_MC_PG_POLICY,M_BCM1480_MC_PG_POLICY)
+
+#define K_BCM1480_MC_PG_POLICY_CLOSED       0
+#define K_BCM1480_MC_PG_POLICY_CAS_TIME_CHK 1
+
+#define V_BCM1480_MC_PG_POLICY_CLOSED       V_BCM1480_MC_PG_POLICY(K_BCM1480_MC_PG_POLICY_CLOSED)
+#define V_BCM1480_MC_PG_POLICY_CAS_TIME_CHK V_BCM1480_MC_PG_POLICY(K_BCM1480_MC_PG_POLICY_CAS_TIME_CHK)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define M_BCM1480_MC_2T_CMD		    _SB_MAKEMASK1(42)
+#define M_BCM1480_MC_ECC_COR_DIS	    _SB_MAKEMASK1(43)
+#endif
+
+#define V_BCM1480_MC_DRAMMODE_DEFAULT	V_BCM1480_MC_EMODE_DEFAULT | V_BCM1480_MC_MODE_DEFAULT | V_BCM1480_MC_DRAM_TYPE_JEDEC | \
+                                V_BCM1480_MC_PG_POLICY(K_BCM1480_MC_PG_POLICY_CAS_TIME_CHK)
+
+/*
+ * Memory Clock Configuration Register (Table 92)
+ */
+
+#define S_BCM1480_MC_CLK_RATIO              0
+#define M_BCM1480_MC_CLK_RATIO              _SB_MAKEMASK(6,S_BCM1480_MC_CLK_RATIO)
+#define V_BCM1480_MC_CLK_RATIO(x)           _SB_MAKEVALUE(x,S_BCM1480_MC_CLK_RATIO)
+#define G_BCM1480_MC_CLK_RATIO(x)           _SB_GETVALUE(x,S_BCM1480_MC_CLK_RATIO,M_BCM1480_MC_CLK_RATIO)
+
+#define V_BCM1480_MC_CLK_RATIO_DEFAULT      V_BCM1480_MC_CLK_RATIO(10)
+
+#define S_BCM1480_MC_REF_RATE               8
+#define M_BCM1480_MC_REF_RATE               _SB_MAKEMASK(8,S_BCM1480_MC_REF_RATE)
+#define V_BCM1480_MC_REF_RATE(x)            _SB_MAKEVALUE(x,S_BCM1480_MC_REF_RATE)
+#define G_BCM1480_MC_REF_RATE(x)            _SB_GETVALUE(x,S_BCM1480_MC_REF_RATE,M_BCM1480_MC_REF_RATE)
+
+#define K_BCM1480_MC_REF_RATE_100MHz        0x31
+#define K_BCM1480_MC_REF_RATE_200MHz        0x62
+#define K_BCM1480_MC_REF_RATE_400MHz        0xC4
+
+#define V_BCM1480_MC_REF_RATE_100MHz        V_BCM1480_MC_REF_RATE(K_BCM1480_MC_REF_RATE_100MHz)
+#define V_BCM1480_MC_REF_RATE_200MHz        V_BCM1480_MC_REF_RATE(K_BCM1480_MC_REF_RATE_200MHz)
+#define V_BCM1480_MC_REF_RATE_400MHz        V_BCM1480_MC_REF_RATE(K_BCM1480_MC_REF_RATE_400MHz)
+#define V_BCM1480_MC_REF_RATE_DEFAULT       V_BCM1480_MC_REF_RATE_400MHz
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define M_BCM1480_MC_AUTO_REF_DIS	    _SB_MAKEMASK1(16)
+#endif
+
+/*
+ * ODT Register (Table 99)
+ */
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define M_BCM1480_MC_RD_ODT0_CS0	    _SB_MAKEMASK1(0)
+#define M_BCM1480_MC_RD_ODT0_CS2	    _SB_MAKEMASK1(1)
+#define M_BCM1480_MC_RD_ODT0_CS4	    _SB_MAKEMASK1(2)
+#define M_BCM1480_MC_RD_ODT0_CS6	    _SB_MAKEMASK1(3)
+#define M_BCM1480_MC_WR_ODT0_CS0	    _SB_MAKEMASK1(4)
+#define M_BCM1480_MC_WR_ODT0_CS2	    _SB_MAKEMASK1(5)
+#define M_BCM1480_MC_WR_ODT0_CS4	    _SB_MAKEMASK1(6)
+#define M_BCM1480_MC_WR_ODT0_CS6	    _SB_MAKEMASK1(7)
+#define M_BCM1480_MC_RD_ODT2_CS0	    _SB_MAKEMASK1(8)
+#define M_BCM1480_MC_RD_ODT2_CS2	    _SB_MAKEMASK1(9)
+#define M_BCM1480_MC_RD_ODT2_CS4	    _SB_MAKEMASK1(10)
+#define M_BCM1480_MC_RD_ODT2_CS6	    _SB_MAKEMASK1(11)
+#define M_BCM1480_MC_WR_ODT2_CS0	    _SB_MAKEMASK1(12)
+#define M_BCM1480_MC_WR_ODT2_CS2	    _SB_MAKEMASK1(13)
+#define M_BCM1480_MC_WR_ODT2_CS4	    _SB_MAKEMASK1(14)
+#define M_BCM1480_MC_WR_ODT2_CS6	    _SB_MAKEMASK1(15)
+#define M_BCM1480_MC_RD_ODT4_CS0	    _SB_MAKEMASK1(16)
+#define M_BCM1480_MC_RD_ODT4_CS2	    _SB_MAKEMASK1(17)
+#define M_BCM1480_MC_RD_ODT4_CS4	    _SB_MAKEMASK1(18)
+#define M_BCM1480_MC_RD_ODT4_CS6	    _SB_MAKEMASK1(19)
+#define M_BCM1480_MC_WR_ODT4_CS0	    _SB_MAKEMASK1(20)
+#define M_BCM1480_MC_WR_ODT4_CS2	    _SB_MAKEMASK1(21)
+#define M_BCM1480_MC_WR_ODT4_CS4	    _SB_MAKEMASK1(22)
+#define M_BCM1480_MC_WR_ODT4_CS6	    _SB_MAKEMASK1(23)
+#define M_BCM1480_MC_RD_ODT6_CS0	    _SB_MAKEMASK1(24)
+#define M_BCM1480_MC_RD_ODT6_CS2	    _SB_MAKEMASK1(25)
+#define M_BCM1480_MC_RD_ODT6_CS4	    _SB_MAKEMASK1(26)
+#define M_BCM1480_MC_RD_ODT6_CS6	    _SB_MAKEMASK1(27)
+#define M_BCM1480_MC_WR_ODT6_CS0	    _SB_MAKEMASK1(28)
+#define M_BCM1480_MC_WR_ODT6_CS2	    _SB_MAKEMASK1(29)
+#define M_BCM1480_MC_WR_ODT6_CS4	    _SB_MAKEMASK1(30)
+#define M_BCM1480_MC_WR_ODT6_CS6	    _SB_MAKEMASK1(31)
+
+#define M_BCM1480_MC_CS_ODD_ODT_EN	    _SB_MAKEMASK1(32)
+#endif
+
+/*
+ * Memory DLL Configuration Register (Table 93)
+ */
+
+#define S_BCM1480_MC_ADDR_COARSE_ADJ         0
+#define M_BCM1480_MC_ADDR_COARSE_ADJ         _SB_MAKEMASK(6,S_BCM1480_MC_ADDR_COARSE_ADJ)
+#define V_BCM1480_MC_ADDR_COARSE_ADJ(x)      _SB_MAKEVALUE(x,S_BCM1480_MC_ADDR_COARSE_ADJ)
+#define G_BCM1480_MC_ADDR_COARSE_ADJ(x)      _SB_GETVALUE(x,S_BCM1480_MC_ADDR_COARSE_ADJ,M_BCM1480_MC_ADDR_COARSE_ADJ)
+#define V_BCM1480_MC_ADDR_COARSE_ADJ_DEFAULT V_BCM1480_MC_ADDR_COARSE_ADJ(0x0)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_ADDR_FREQ_RANGE	    	8
+#define M_BCM1480_MC_ADDR_FREQ_RANGE	    	_SB_MAKEMASK(4,S_BCM1480_MC_ADDR_FREQ_RANGE)
+#define V_BCM1480_MC_ADDR_FREQ_RANGE(x)     	_SB_MAKEVALUE(x,S_BCM1480_MC_ADDR_FREQ_RANGE)
+#define G_BCM1480_MC_ADDR_FREQ_RANGE(x)     	_SB_GETVALUE(x,S_BCM1480_MC_ADDR_FREQ_RANGE,M_BCM1480_MC_ADDR_FREQ_RANGE)
+#define V_BCM1480_MC_ADDR_FREQ_RANGE_DEFAULT 	V_BCM1480_MC_ADDR_FREQ_RANGE(0x4)
+#endif
+
+#define S_BCM1480_MC_ADDR_FINE_ADJ          8
+#define M_BCM1480_MC_ADDR_FINE_ADJ          _SB_MAKEMASK(4,S_BCM1480_MC_ADDR_FINE_ADJ)
+#define V_BCM1480_MC_ADDR_FINE_ADJ(x)       _SB_MAKEVALUE(x,S_BCM1480_MC_ADDR_FINE_ADJ)
+#define G_BCM1480_MC_ADDR_FINE_ADJ(x)       _SB_GETVALUE(x,S_BCM1480_MC_ADDR_FINE_ADJ,M_BCM1480_MC_ADDR_FINE_ADJ)
+#define V_BCM1480_MC_ADDR_FINE_ADJ_DEFAULT  V_BCM1480_MC_ADDR_FINE_ADJ(0x8)
+
+#define S_BCM1480_MC_DQI_COARSE_ADJ         16
+#define M_BCM1480_MC_DQI_COARSE_ADJ         _SB_MAKEMASK(6,S_BCM1480_MC_DQI_COARSE_ADJ)
+#define V_BCM1480_MC_DQI_COARSE_ADJ(x)      _SB_MAKEVALUE(x,S_BCM1480_MC_DQI_COARSE_ADJ)
+#define G_BCM1480_MC_DQI_COARSE_ADJ(x)      _SB_GETVALUE(x,S_BCM1480_MC_DQI_COARSE_ADJ,M_BCM1480_MC_DQI_COARSE_ADJ)
+#define V_BCM1480_MC_DQI_COARSE_ADJ_DEFAULT V_BCM1480_MC_DQI_COARSE_ADJ(0x0)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_DQI_FREQ_RANGE	    	24
+#define M_BCM1480_MC_DQI_FREQ_RANGE	    	_SB_MAKEMASK(4,S_BCM1480_MC_DQI_FREQ_RANGE)
+#define V_BCM1480_MC_DQI_FREQ_RANGE(x)     	_SB_MAKEVALUE(x,S_BCM1480_MC_DQI_FREQ_RANGE)
+#define G_BCM1480_MC_DQI_FREQ_RANGE(x)     	_SB_GETVALUE(x,S_BCM1480_MC_DQI_FREQ_RANGE,M_BCM1480_MC_DQI_FREQ_RANGE)
+#define V_BCM1480_MC_DQI_FREQ_RANGE_DEFAULT 	V_BCM1480_MC_DQI_FREQ_RANGE(0x4)
+#endif
+
+#define S_BCM1480_MC_DQI_FINE_ADJ           24
+#define M_BCM1480_MC_DQI_FINE_ADJ           _SB_MAKEMASK(4,S_BCM1480_MC_DQI_FINE_ADJ)
+#define V_BCM1480_MC_DQI_FINE_ADJ(x)        _SB_MAKEVALUE(x,S_BCM1480_MC_DQI_FINE_ADJ)
+#define G_BCM1480_MC_DQI_FINE_ADJ(x)        _SB_GETVALUE(x,S_BCM1480_MC_DQI_FINE_ADJ,M_BCM1480_MC_DQI_FINE_ADJ)
+#define V_BCM1480_MC_DQI_FINE_ADJ_DEFAULT   V_BCM1480_MC_DQI_FINE_ADJ(0x8)
+
+#define S_BCM1480_MC_DQO_COARSE_ADJ         32
+#define M_BCM1480_MC_DQO_COARSE_ADJ         _SB_MAKEMASK(6,S_BCM1480_MC_DQO_COARSE_ADJ)
+#define V_BCM1480_MC_DQO_COARSE_ADJ(x)      _SB_MAKEVALUE(x,S_BCM1480_MC_DQO_COARSE_ADJ)
+#define G_BCM1480_MC_DQO_COARSE_ADJ(x)      _SB_GETVALUE(x,S_BCM1480_MC_DQO_COARSE_ADJ,M_BCM1480_MC_DQO_COARSE_ADJ)
+#define V_BCM1480_MC_DQO_COARSE_ADJ_DEFAULT V_BCM1480_MC_DQO_COARSE_ADJ(0x0)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_DQO_FREQ_RANGE	    	40
+#define M_BCM1480_MC_DQO_FREQ_RANGE	    	_SB_MAKEMASK(4,S_BCM1480_MC_DQO_FREQ_RANGE)
+#define V_BCM1480_MC_DQO_FREQ_RANGE(x)     	_SB_MAKEVALUE(x,S_BCM1480_MC_DQO_FREQ_RANGE)
+#define G_BCM1480_MC_DQO_FREQ_RANGE(x)     	_SB_GETVALUE(x,S_BCM1480_MC_DQO_FREQ_RANGE,M_BCM1480_MC_DQO_FREQ_RANGE)
+#define V_BCM1480_MC_DQO_FREQ_RANGE_DEFAULT 	V_BCM1480_MC_DQO_FREQ_RANGE(0x4)
+#endif
+
+#define S_BCM1480_MC_DQO_FINE_ADJ           40
+#define M_BCM1480_MC_DQO_FINE_ADJ           _SB_MAKEMASK(4,S_BCM1480_MC_DQO_FINE_ADJ)
+#define V_BCM1480_MC_DQO_FINE_ADJ(x)        _SB_MAKEVALUE(x,S_BCM1480_MC_DQO_FINE_ADJ)
+#define G_BCM1480_MC_DQO_FINE_ADJ(x)        _SB_GETVALUE(x,S_BCM1480_MC_DQO_FINE_ADJ,M_BCM1480_MC_DQO_FINE_ADJ)
+#define V_BCM1480_MC_DQO_FINE_ADJ_DEFAULT   V_BCM1480_MC_DQO_FINE_ADJ(0x8)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_DLL_PDSEL            44
+#define M_BCM1480_MC_DLL_PDSEL            _SB_MAKEMASK(2,S_BCM1480_MC_DLL_PDSEL)
+#define V_BCM1480_MC_DLL_PDSEL(x)         _SB_MAKEVALUE(x,S_BCM1480_MC_DLL_PDSEL)
+#define G_BCM1480_MC_DLL_PDSEL(x)         _SB_GETVALUE(x,S_BCM1480_MC_DLL_PDSEL,M_BCM1480_MC_DLL_PDSEL)
+#define V_BCM1480_MC_DLL_DEFAULT_PDSEL    V_BCM1480_MC_DLL_PDSEL(0x0)
+
+#define	M_BCM1480_MC_DLL_REGBYPASS        _SB_MAKEMASK1(46)
+#define	M_BCM1480_MC_DQO_SHIFT            _SB_MAKEMASK1(47)
+#endif
+
+#define S_BCM1480_MC_DLL_DEFAULT            48
+#define M_BCM1480_MC_DLL_DEFAULT            _SB_MAKEMASK(6,S_BCM1480_MC_DLL_DEFAULT)
+#define V_BCM1480_MC_DLL_DEFAULT(x)         _SB_MAKEVALUE(x,S_BCM1480_MC_DLL_DEFAULT)
+#define G_BCM1480_MC_DLL_DEFAULT(x)         _SB_GETVALUE(x,S_BCM1480_MC_DLL_DEFAULT,M_BCM1480_MC_DLL_DEFAULT)
+#define V_BCM1480_MC_DLL_DEFAULT_DEFAULT    V_BCM1480_MC_DLL_DEFAULT(0x10)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_DLL_REGCTRL	  54
+#define M_BCM1480_MC_DLL_REGCTRL       	  _SB_MAKEMASK(2,S_BCM1480_MC_DLL_REGCTRL)
+#define V_BCM1480_MC_DLL_REGCTRL(x)       _SB_MAKEVALUE(x,S_BCM1480_MC_DLL_REGCTRL)
+#define G_BCM1480_MC_DLL_REGCTRL(x)       _SB_GETVALUE(x,S_BCM1480_MC_DLL_REGCTRL,M_BCM1480_MC_DLL_REGCTRL)
+#define V_BCM1480_MC_DLL_DEFAULT_REGCTRL  V_BCM1480_MC_DLL_REGCTRL(0x0)
+#endif
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_DLL_FREQ_RANGE	    	56
+#define M_BCM1480_MC_DLL_FREQ_RANGE	    	_SB_MAKEMASK(4,S_BCM1480_MC_DLL_FREQ_RANGE)
+#define V_BCM1480_MC_DLL_FREQ_RANGE(x)     	_SB_MAKEVALUE(x,S_BCM1480_MC_DLL_FREQ_RANGE)
+#define G_BCM1480_MC_DLL_FREQ_RANGE(x)     	_SB_GETVALUE(x,S_BCM1480_MC_DLL_FREQ_RANGE,M_BCM1480_MC_DLL_FREQ_RANGE)
+#define V_BCM1480_MC_DLL_FREQ_RANGE_DEFAULT 	V_BCM1480_MC_DLL_FREQ_RANGE(0x4)
+#endif
+
+#define S_BCM1480_MC_DLL_STEP_SIZE          56
+#define M_BCM1480_MC_DLL_STEP_SIZE          _SB_MAKEMASK(4,S_BCM1480_MC_DLL_STEP_SIZE)
+#define V_BCM1480_MC_DLL_STEP_SIZE(x)       _SB_MAKEVALUE(x,S_BCM1480_MC_DLL_STEP_SIZE)
+#define G_BCM1480_MC_DLL_STEP_SIZE(x)       _SB_GETVALUE(x,S_BCM1480_MC_DLL_STEP_SIZE,M_BCM1480_MC_DLL_STEP_SIZE)
+#define V_BCM1480_MC_DLL_STEP_SIZE_DEFAULT  V_BCM1480_MC_DLL_STEP_SIZE(0x8)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_DLL_BGCTRL	  60
+#define M_BCM1480_MC_DLL_BGCTRL       	  _SB_MAKEMASK(2,S_BCM1480_MC_DLL_BGCTRL)
+#define V_BCM1480_MC_DLL_BGCTRL(x)       _SB_MAKEVALUE(x,S_BCM1480_MC_DLL_BGCTRL)
+#define G_BCM1480_MC_DLL_BGCTRL(x)       _SB_GETVALUE(x,S_BCM1480_MC_DLL_BGCTRL,M_BCM1480_MC_DLL_BGCTRL)
+#define V_BCM1480_MC_DLL_DEFAULT_BGCTRL  V_BCM1480_MC_DLL_BGCTRL(0x0)
+#endif
+
+#define	M_BCM1480_MC_DLL_BYPASS		    _SB_MAKEMASK1(63)
+
+/*
+ * Memory Drive Configuration Register (Table 94)
+ */
+
+#define S_BCM1480_MC_RTT_BYP_PULLDOWN       0
+#define M_BCM1480_MC_RTT_BYP_PULLDOWN       _SB_MAKEMASK(3,S_BCM1480_MC_RTT_BYP_PULLDOWN)
+#define V_BCM1480_MC_RTT_BYP_PULLDOWN(x)    _SB_MAKEVALUE(x,S_BCM1480_MC_RTT_BYP_PULLDOWN)
+#define G_BCM1480_MC_RTT_BYP_PULLDOWN(x)    _SB_GETVALUE(x,S_BCM1480_MC_RTT_BYP_PULLDOWN,M_BCM1480_MC_RTT_BYP_PULLDOWN)
+
+#define S_BCM1480_MC_RTT_BYP_PULLUP         6
+#define M_BCM1480_MC_RTT_BYP_PULLUP         _SB_MAKEMASK(3,S_BCM1480_MC_RTT_BYP_PULLUP)
+#define V_BCM1480_MC_RTT_BYP_PULLUP(x)      _SB_MAKEVALUE(x,S_BCM1480_MC_RTT_BYP_PULLUP)
+#define G_BCM1480_MC_RTT_BYP_PULLUP(x)      _SB_GETVALUE(x,S_BCM1480_MC_RTT_BYP_PULLUP,M_BCM1480_MC_RTT_BYP_PULLUP)
+
+#define M_BCM1480_MC_RTT_BYPASS             _SB_MAKEMASK1(8)
+#define M_BCM1480_MC_RTT_COMP_MOV_AVG       _SB_MAKEMASK1(9)
+
+#define S_BCM1480_MC_PVT_BYP_C1_PULLDOWN    10
+#define M_BCM1480_MC_PVT_BYP_C1_PULLDOWN    _SB_MAKEMASK(4,S_BCM1480_MC_PVT_BYP_C1_PULLDOWN)
+#define V_BCM1480_MC_PVT_BYP_C1_PULLDOWN(x) _SB_MAKEVALUE(x,S_BCM1480_MC_PVT_BYP_C1_PULLDOWN)
+#define G_BCM1480_MC_PVT_BYP_C1_PULLDOWN(x) _SB_GETVALUE(x,S_BCM1480_MC_PVT_BYP_C1_PULLDOWN,M_BCM1480_MC_PVT_BYP_C1_PULLDOWN)
+
+#define S_BCM1480_MC_PVT_BYP_C1_PULLUP      15
+#define M_BCM1480_MC_PVT_BYP_C1_PULLUP      _SB_MAKEMASK(4,S_BCM1480_MC_PVT_BYP_C1_PULLUP)
+#define V_BCM1480_MC_PVT_BYP_C1_PULLUP(x)   _SB_MAKEVALUE(x,S_BCM1480_MC_PVT_BYP_C1_PULLUP)
+#define G_BCM1480_MC_PVT_BYP_C1_PULLUP(x)   _SB_GETVALUE(x,S_BCM1480_MC_PVT_BYP_C1_PULLUP,M_BCM1480_MC_PVT_BYP_C1_PULLUP)
+
+#define S_BCM1480_MC_PVT_BYP_C2_PULLDOWN    20
+#define M_BCM1480_MC_PVT_BYP_C2_PULLDOWN    _SB_MAKEMASK(4,S_BCM1480_MC_PVT_BYP_C2_PULLDOWN)
+#define V_BCM1480_MC_PVT_BYP_C2_PULLDOWN(x) _SB_MAKEVALUE(x,S_BCM1480_MC_PVT_BYP_C2_PULLDOWN)
+#define G_BCM1480_MC_PVT_BYP_C2_PULLDOWN(x) _SB_GETVALUE(x,S_BCM1480_MC_PVT_BYP_C2_PULLDOWN,M_BCM1480_MC_PVT_BYP_C2_PULLDOWN)
+
+#define S_BCM1480_MC_PVT_BYP_C2_PULLUP      25
+#define M_BCM1480_MC_PVT_BYP_C2_PULLUP      _SB_MAKEMASK(4,S_BCM1480_MC_PVT_BYP_C2_PULLUP)
+#define V_BCM1480_MC_PVT_BYP_C2_PULLUP(x)   _SB_MAKEVALUE(x,S_BCM1480_MC_PVT_BYP_C2_PULLUP)
+#define G_BCM1480_MC_PVT_BYP_C2_PULLUP(x)   _SB_GETVALUE(x,S_BCM1480_MC_PVT_BYP_C2_PULLUP,M_BCM1480_MC_PVT_BYP_C2_PULLUP)
+
+#define M_BCM1480_MC_PVT_BYPASS             _SB_MAKEMASK1(30)
+#define M_BCM1480_MC_PVT_COMP_MOV_AVG       _SB_MAKEMASK1(31)
+
+#define M_BCM1480_MC_CLK_CLASS              _SB_MAKEMASK1(34)
+#define M_BCM1480_MC_DATA_CLASS             _SB_MAKEMASK1(35)
+#define M_BCM1480_MC_ADDR_CLASS             _SB_MAKEMASK1(36)
+
+#define M_BCM1480_MC_DQ_ODT_75              _SB_MAKEMASK1(37)
+#define M_BCM1480_MC_DQ_ODT_150             _SB_MAKEMASK1(38)
+#define M_BCM1480_MC_DQS_ODT_75             _SB_MAKEMASK1(39)
+#define M_BCM1480_MC_DQS_ODT_150            _SB_MAKEMASK1(40)
+#define M_BCM1480_MC_DQS_DIFF               _SB_MAKEMASK1(41)
+
+/*
+ * ECC Test Data Register (Table 95)
+ */
+
+#define S_BCM1480_MC_DATA_INVERT            0
+#define M_DATA_ECC_INVERT           _SB_MAKEMASK(64,S_BCM1480_MC_ECC_INVERT)
+
+/*
+ * ECC Test ECC Register (Table 96)
+ */
+
+#define S_BCM1480_MC_ECC_INVERT             0
+#define M_BCM1480_MC_ECC_INVERT             _SB_MAKEMASK(8,S_BCM1480_MC_ECC_INVERT)
+
+/*
+ * SDRAM Timing Register  (Table 97)
+ */
+
+#define S_BCM1480_MC_tRCD                   0
+#define M_BCM1480_MC_tRCD                   _SB_MAKEMASK(4,S_BCM1480_MC_tRCD)
+#define V_BCM1480_MC_tRCD(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRCD)
+#define G_BCM1480_MC_tRCD(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRCD,M_BCM1480_MC_tRCD)
+#define K_BCM1480_MC_tRCD_DEFAULT           3
+#define V_BCM1480_MC_tRCD_DEFAULT           V_BCM1480_MC_tRCD(K_BCM1480_MC_tRCD_DEFAULT)
+
+#define S_BCM1480_MC_tCL                    4
+#define M_BCM1480_MC_tCL                    _SB_MAKEMASK(4,S_BCM1480_MC_tCL)
+#define V_BCM1480_MC_tCL(x)                 _SB_MAKEVALUE(x,S_BCM1480_MC_tCL)
+#define G_BCM1480_MC_tCL(x)                 _SB_GETVALUE(x,S_BCM1480_MC_tCL,M_BCM1480_MC_tCL)
+#define K_BCM1480_MC_tCL_DEFAULT            2
+#define V_BCM1480_MC_tCL_DEFAULT            V_BCM1480_MC_tCL(K_BCM1480_MC_tCL_DEFAULT)
+
+#define M_BCM1480_MC_tCrDh                  _SB_MAKEMASK1(8)
+
+#define S_BCM1480_MC_tWR                    9
+#define M_BCM1480_MC_tWR                    _SB_MAKEMASK(3,S_BCM1480_MC_tWR)
+#define V_BCM1480_MC_tWR(x)                 _SB_MAKEVALUE(x,S_BCM1480_MC_tWR)
+#define G_BCM1480_MC_tWR(x)                 _SB_GETVALUE(x,S_BCM1480_MC_tWR,M_BCM1480_MC_tWR)
+#define K_BCM1480_MC_tWR_DEFAULT            2
+#define V_BCM1480_MC_tWR_DEFAULT            V_BCM1480_MC_tWR(K_BCM1480_MC_tWR_DEFAULT)
+
+#define S_BCM1480_MC_tCwD                   12
+#define M_BCM1480_MC_tCwD                   _SB_MAKEMASK(4,S_BCM1480_MC_tCwD)
+#define V_BCM1480_MC_tCwD(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tCwD)
+#define G_BCM1480_MC_tCwD(x)                _SB_GETVALUE(x,S_BCM1480_MC_tCwD,M_BCM1480_MC_tCwD)
+#define K_BCM1480_MC_tCwD_DEFAULT           1
+#define V_BCM1480_MC_tCwD_DEFAULT           V_BCM1480_MC_tCwD(K_BCM1480_MC_tCwD_DEFAULT)
+
+#define S_BCM1480_MC_tRP                    16
+#define M_BCM1480_MC_tRP                    _SB_MAKEMASK(4,S_BCM1480_MC_tRP)
+#define V_BCM1480_MC_tRP(x)                 _SB_MAKEVALUE(x,S_BCM1480_MC_tRP)
+#define G_BCM1480_MC_tRP(x)                 _SB_GETVALUE(x,S_BCM1480_MC_tRP,M_BCM1480_MC_tRP)
+#define K_BCM1480_MC_tRP_DEFAULT            4
+#define V_BCM1480_MC_tRP_DEFAULT            V_BCM1480_MC_tRP(K_BCM1480_MC_tRP_DEFAULT)
+
+#define S_BCM1480_MC_tRRD                   20
+#define M_BCM1480_MC_tRRD                   _SB_MAKEMASK(4,S_BCM1480_MC_tRRD)
+#define V_BCM1480_MC_tRRD(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRRD)
+#define G_BCM1480_MC_tRRD(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRRD,M_BCM1480_MC_tRRD)
+#define K_BCM1480_MC_tRRD_DEFAULT           2
+#define V_BCM1480_MC_tRRD_DEFAULT           V_BCM1480_MC_tRRD(K_BCM1480_MC_tRRD_DEFAULT)
+
+#define S_BCM1480_MC_tRCw                   24
+#define M_BCM1480_MC_tRCw                   _SB_MAKEMASK(5,S_BCM1480_MC_tRCw)
+#define V_BCM1480_MC_tRCw(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRCw)
+#define G_BCM1480_MC_tRCw(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRCw,M_BCM1480_MC_tRCw)
+#define K_BCM1480_MC_tRCw_DEFAULT           10
+#define V_BCM1480_MC_tRCw_DEFAULT           V_BCM1480_MC_tRCw(K_BCM1480_MC_tRCw_DEFAULT)
+
+#define S_BCM1480_MC_tRCr                   32
+#define M_BCM1480_MC_tRCr                   _SB_MAKEMASK(5,S_BCM1480_MC_tRCr)
+#define V_BCM1480_MC_tRCr(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRCr)
+#define G_BCM1480_MC_tRCr(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRCr,M_BCM1480_MC_tRCr)
+#define K_BCM1480_MC_tRCr_DEFAULT           9
+#define V_BCM1480_MC_tRCr_DEFAULT           V_BCM1480_MC_tRCr(K_BCM1480_MC_tRCr_DEFAULT)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define S_BCM1480_MC_tFAW                   40
+#define M_BCM1480_MC_tFAW                   _SB_MAKEMASK(6,S_BCM1480_MC_tFAW)
+#define V_BCM1480_MC_tFAW(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tFAW)
+#define G_BCM1480_MC_tFAW(x)                _SB_GETVALUE(x,S_BCM1480_MC_tFAW,M_BCM1480_MC_tFAW)
+#define K_BCM1480_MC_tFAW_DEFAULT           0
+#define V_BCM1480_MC_tFAW_DEFAULT           V_BCM1480_MC_tFAW(K_BCM1480_MC_tFAW_DEFAULT)
+#endif
+
+#define S_BCM1480_MC_tRFC                   48
+#define M_BCM1480_MC_tRFC                   _SB_MAKEMASK(7,S_BCM1480_MC_tRFC)
+#define V_BCM1480_MC_tRFC(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRFC)
+#define G_BCM1480_MC_tRFC(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRFC,M_BCM1480_MC_tRFC)
+#define K_BCM1480_MC_tRFC_DEFAULT           12
+#define V_BCM1480_MC_tRFC_DEFAULT           V_BCM1480_MC_tRFC(K_BCM1480_MC_tRFC_DEFAULT)
+
+#define S_BCM1480_MC_tFIFO                  56
+#define M_BCM1480_MC_tFIFO                  _SB_MAKEMASK(2,S_BCM1480_MC_tFIFO)
+#define V_BCM1480_MC_tFIFO(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_tFIFO)
+#define G_BCM1480_MC_tFIFO(x)               _SB_GETVALUE(x,S_BCM1480_MC_tFIFO,M_BCM1480_MC_tFIFO)
+#define K_BCM1480_MC_tFIFO_DEFAULT          0
+#define V_BCM1480_MC_tFIFO_DEFAULT          V_BCM1480_MC_tFIFO(K_BCM1480_MC_tFIFO_DEFAULT)
+
+#define S_BCM1480_MC_tW2R                  58
+#define M_BCM1480_MC_tW2R                  _SB_MAKEMASK(2,S_BCM1480_MC_tW2R)
+#define V_BCM1480_MC_tW2R(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_tW2R)
+#define G_BCM1480_MC_tW2R(x)               _SB_GETVALUE(x,S_BCM1480_MC_tW2R,M_BCM1480_MC_tW2R)
+#define K_BCM1480_MC_tW2R_DEFAULT          1
+#define V_BCM1480_MC_tW2R_DEFAULT          V_BCM1480_MC_tW2R(K_BCM1480_MC_tW2R_DEFAULT)
+
+#define S_BCM1480_MC_tR2W                  60
+#define M_BCM1480_MC_tR2W                  _SB_MAKEMASK(2,S_BCM1480_MC_tR2W)
+#define V_BCM1480_MC_tR2W(x)               _SB_MAKEVALUE(x,S_BCM1480_MC_tR2W)
+#define G_BCM1480_MC_tR2W(x)               _SB_GETVALUE(x,S_BCM1480_MC_tR2W,M_BCM1480_MC_tR2W)
+#define K_BCM1480_MC_tR2W_DEFAULT          0
+#define V_BCM1480_MC_tR2W_DEFAULT          V_BCM1480_MC_tR2W(K_BCM1480_MC_tR2W_DEFAULT)
+
+#define M_BCM1480_MC_tR2R		    _SB_MAKEMASK1(62)
+
+#define V_BCM1480_MC_TIMING_DEFAULT         (M_BCM1480_MC_tR2R | \
+                                     V_BCM1480_MC_tFIFO_DEFAULT | \
+                                     V_BCM1480_MC_tR2W_DEFAULT | \
+                                     V_BCM1480_MC_tW2R_DEFAULT | \
+                                     V_BCM1480_MC_tRFC_DEFAULT | \
+                                     V_BCM1480_MC_tRCr_DEFAULT | \
+                                     V_BCM1480_MC_tRCw_DEFAULT | \
+                                     V_BCM1480_MC_tRRD_DEFAULT | \
+                                     V_BCM1480_MC_tRP_DEFAULT | \
+                                     V_BCM1480_MC_tCwD_DEFAULT | \
+                                     V_BCM1480_MC_tWR_DEFAULT | \
+                                     M_BCM1480_MC_tCrDh | \
+                                     V_BCM1480_MC_tCL_DEFAULT | \
+                                     V_BCM1480_MC_tRCD_DEFAULT)
+
+/*
+ * SDRAM Timing Register 2
+ */
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+
+#define S_BCM1480_MC_tAL                   0
+#define M_BCM1480_MC_tAL                   _SB_MAKEMASK(4,S_BCM1480_MC_tAL)
+#define V_BCM1480_MC_tAL(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tAL)
+#define G_BCM1480_MC_tAL(x)                _SB_GETVALUE(x,S_BCM1480_MC_tAL,M_BCM1480_MC_tAL)
+#define K_BCM1480_MC_tAL_DEFAULT           0
+#define V_BCM1480_MC_tAL_DEFAULT           V_BCM1480_MC_tAL(K_BCM1480_MC_tAL_DEFAULT)
+
+#define S_BCM1480_MC_tRTP                   4
+#define M_BCM1480_MC_tRTP                   _SB_MAKEMASK(3,S_BCM1480_MC_tRTP)
+#define V_BCM1480_MC_tRTP(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRTP)
+#define G_BCM1480_MC_tRTP(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRTP,M_BCM1480_MC_tRTP)
+#define K_BCM1480_MC_tRTP_DEFAULT           2
+#define V_BCM1480_MC_tRTP_DEFAULT           V_BCM1480_MC_tRTP(K_BCM1480_MC_tRTP_DEFAULT)
+
+#define S_BCM1480_MC_tW2W                   8
+#define M_BCM1480_MC_tW2W                   _SB_MAKEMASK(2,S_BCM1480_MC_tW2W)
+#define V_BCM1480_MC_tW2W(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tW2W)
+#define G_BCM1480_MC_tW2W(x)                _SB_GETVALUE(x,S_BCM1480_MC_tW2W,M_BCM1480_MC_tW2W)
+#define K_BCM1480_MC_tW2W_DEFAULT           0
+#define V_BCM1480_MC_tW2W_DEFAULT           V_BCM1480_MC_tW2W(K_BCM1480_MC_tW2W_DEFAULT)
+
+#define S_BCM1480_MC_tRAP                   12
+#define M_BCM1480_MC_tRAP                  _SB_MAKEMASK(4,S_BCM1480_MC_tRAP)
+#define V_BCM1480_MC_tRAP(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_tRAP)
+#define G_BCM1480_MC_tRAP(x)                _SB_GETVALUE(x,S_BCM1480_MC_tRAP,M_BCM1480_MC_tRAP)
+#define K_BCM1480_MC_tRAP_DEFAULT           0
+#define V_BCM1480_MC_tRAP_DEFAULT           V_BCM1480_MC_tRAP(K_BCM1480_MC_tRAP_DEFAULT)
+
+#endif
+
+
+
+/*
+ * Global Registers: single instances per BCM1480
+ */
+
+/*
+ * Global Configuration Register (Table 99)
+ */
+
+#define S_BCM1480_MC_BLK_SET_MARK           8
+#define M_BCM1480_MC_BLK_SET_MARK           _SB_MAKEMASK(4,S_BCM1480_MC_BLK_SET_MARK)
+#define V_BCM1480_MC_BLK_SET_MARK(x)        _SB_MAKEVALUE(x,S_BCM1480_MC_BLK_SET_MARK)
+#define G_BCM1480_MC_BLK_SET_MARK(x)        _SB_GETVALUE(x,S_BCM1480_MC_BLK_SET_MARK,M_BCM1480_MC_BLK_SET_MARK)
+
+#define S_BCM1480_MC_BLK_CLR_MARK           12
+#define M_BCM1480_MC_BLK_CLR_MARK           _SB_MAKEMASK(4,S_BCM1480_MC_BLK_CLR_MARK)
+#define V_BCM1480_MC_BLK_CLR_MARK(x)        _SB_MAKEVALUE(x,S_BCM1480_MC_BLK_CLR_MARK)
+#define G_BCM1480_MC_BLK_CLR_MARK(x)        _SB_GETVALUE(x,S_BCM1480_MC_BLK_CLR_MARK,M_BCM1480_MC_BLK_CLR_MARK)
+
+#define M_BCM1480_MC_PKT_PRIORITY           _SB_MAKEMASK1(16)
+
+#define S_BCM1480_MC_MAX_AGE                20
+#define M_BCM1480_MC_MAX_AGE                _SB_MAKEMASK(4,S_BCM1480_MC_MAX_AGE)
+#define V_BCM1480_MC_MAX_AGE(x)             _SB_MAKEVALUE(x,S_BCM1480_MC_MAX_AGE)
+#define G_BCM1480_MC_MAX_AGE(x)             _SB_GETVALUE(x,S_BCM1480_MC_MAX_AGE,M_BCM1480_MC_MAX_AGE)
+
+#define M_BCM1480_MC_BERR_DISABLE           _SB_MAKEMASK1(29)
+#define M_BCM1480_MC_FORCE_SEQ              _SB_MAKEMASK1(30)
+#define M_BCM1480_MC_VGEN                   _SB_MAKEMASK1(32)
+
+#define S_BCM1480_MC_SLEW                   33
+#define M_BCM1480_MC_SLEW                   _SB_MAKEMASK(2,S_BCM1480_MC_SLEW)
+#define V_BCM1480_MC_SLEW(x)                _SB_MAKEVALUE(x,S_BCM1480_MC_SLEW)
+#define G_BCM1480_MC_SLEW(x)                _SB_GETVALUE(x,S_BCM1480_MC_SLEW,M_BCM1480_MC_SLEW)
+
+#define M_BCM1480_MC_SSTL_VOLTAGE           _SB_MAKEMASK1(35)
+
+/*
+ * Global Channel Interleave Register (Table 100)
+ */
+
+#define S_BCM1480_MC_INTLV0                 0
+#define M_BCM1480_MC_INTLV0                 _SB_MAKEMASK(6,S_BCM1480_MC_INTLV0)
+#define V_BCM1480_MC_INTLV0(x)              _SB_MAKEVALUE(x,S_BCM1480_MC_INTLV0)
+#define G_BCM1480_MC_INTLV0(x)              _SB_GETVALUE(x,S_BCM1480_MC_INTLV0,M_BCM1480_MC_INTLV0)
+
+#define S_BCM1480_MC_INTLV1                 8
+#define M_BCM1480_MC_INTLV1                 _SB_MAKEMASK(6,S_BCM1480_MC_INTLV1)
+#define V_BCM1480_MC_INTLV1(x)              _SB_MAKEVALUE(x,S_BCM1480_MC_INTLV1)
+#define G_BCM1480_MC_INTLV1(x)              _SB_GETVALUE(x,S_BCM1480_MC_INTLV1,M_BCM1480_MC_INTLV1)
+
+#define S_BCM1480_MC_INTLV_MODE             16
+#define M_BCM1480_MC_INTLV_MODE             _SB_MAKEMASK(3,S_BCM1480_MC_INTLV_MODE)
+#define V_BCM1480_MC_INTLV_MODE(x)          _SB_MAKEVALUE(x,S_BCM1480_MC_INTLV_MODE)
+#define G_BCM1480_MC_INTLV_MODE(x)          _SB_GETVALUE(x,S_BCM1480_MC_INTLV_MODE,M_BCM1480_MC_INTLV_MODE)
+
+#define K_BCM1480_MC_INTLV_MODE_NONE        0x0
+#define K_BCM1480_MC_INTLV_MODE_01          0x1
+#define K_BCM1480_MC_INTLV_MODE_23          0x2
+#define K_BCM1480_MC_INTLV_MODE_01_23       0x3
+#define K_BCM1480_MC_INTLV_MODE_0123        0x4
+
+#define V_BCM1480_MC_INTLV_MODE_NONE        V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_NONE)
+#define V_BCM1480_MC_INTLV_MODE_01          V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_01)
+#define V_BCM1480_MC_INTLV_MODE_23          V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_23)
+#define V_BCM1480_MC_INTLV_MODE_01_23       V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_01_23)
+#define V_BCM1480_MC_INTLV_MODE_0123        V_BCM1480_MC_INTLV_MODE(K_BCM1480_MC_INTLV_MODE_0123)
+
+/*
+ * ECC Status Register
+ */
+
+#define S_BCM1480_MC_ECC_ERR_ADDR           0
+#define M_BCM1480_MC_ECC_ERR_ADDR           _SB_MAKEMASK(37,S_BCM1480_MC_ECC_ERR_ADDR)
+#define V_BCM1480_MC_ECC_ERR_ADDR(x)        _SB_MAKEVALUE(x,S_BCM1480_MC_ECC_ERR_ADDR)
+#define G_BCM1480_MC_ECC_ERR_ADDR(x)        _SB_GETVALUE(x,S_BCM1480_MC_ECC_ERR_ADDR,M_BCM1480_MC_ECC_ERR_ADDR)
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define M_BCM1480_MC_ECC_ERR_RMW            _SB_MAKEMASK1(60)
+#endif
+
+#define M_BCM1480_MC_ECC_MULT_ERR_DET       _SB_MAKEMASK1(61)
+#define M_BCM1480_MC_ECC_UERR_DET           _SB_MAKEMASK1(62)
+#define M_BCM1480_MC_ECC_CERR_DET           _SB_MAKEMASK1(63)
+
+/*
+ * Global ECC Address Register (Table 102)
+ */
+
+#define S_BCM1480_MC_ECC_CORR_ADDR          0
+#define M_BCM1480_MC_ECC_CORR_ADDR          _SB_MAKEMASK(37,S_BCM1480_MC_ECC_CORR_ADDR)
+#define V_BCM1480_MC_ECC_CORR_ADDR(x)       _SB_MAKEVALUE(x,S_BCM1480_MC_ECC_CORR_ADDR)
+#define G_BCM1480_MC_ECC_CORR_ADDR(x)       _SB_GETVALUE(x,S_BCM1480_MC_ECC_CORR_ADDR,M_BCM1480_MC_ECC_CORR_ADDR)
+
+/*
+ * Global ECC Correction Register (Table 103)
+ */
+
+#define S_BCM1480_MC_ECC_CORRECT            0
+#define M_BCM1480_MC_ECC_CORRECT            _SB_MAKEMASK(64,S_BCM1480_MC_ECC_CORRECT)
+#define V_BCM1480_MC_ECC_CORRECT(x)         _SB_MAKEVALUE(x,S_BCM1480_MC_ECC_CORRECT)
+#define G_BCM1480_MC_ECC_CORRECT(x)         _SB_GETVALUE(x,S_BCM1480_MC_ECC_CORRECT,M_BCM1480_MC_ECC_CORRECT)
+
+/*
+ * Global ECC Performance Counters Control Register (Table 104)
+ */
+
+#define S_BCM1480_MC_CHANNEL_SELECT         0
+#define M_BCM1480_MC_CHANNEL_SELECT         _SB_MAKEMASK(4,S_BCM1480_MC_CHANNEL_SELECT)
+#define V_BCM1480_MC_CHANNEL_SELECT(x)      _SB_MAKEVALUE(x,S_BCM1480_MC_CHANNEL_SELECT)
+#define G_BCM1480_MC_CHANNEL_SELECT(x)      _SB_GETVALUE(x,S_BCM1480_MC_CHANNEL_SELECT,M_BCM1480_MC_CHANNEL_SELECT)
+#define K_BCM1480_MC_CHANNEL_SELECT_0       0x1
+#define K_BCM1480_MC_CHANNEL_SELECT_1       0x2
+#define K_BCM1480_MC_CHANNEL_SELECT_2       0x4
+#define K_BCM1480_MC_CHANNEL_SELECT_3       0x8
+
+#endif /* _BCM1480_MC_H */
diff --git a/include/asm-mips/sibyte/bcm1480_regs.h b/include/asm-mips/sibyte/bcm1480_regs.h
new file mode 100644
index 0000000..c2dd2fe
--- /dev/null
+++ b/include/asm-mips/sibyte/bcm1480_regs.h
@@ -0,0 +1,869 @@
+/*  *********************************************************************
+    *  BCM1255/BCM1280/BCM1455/BCM1480 Board Support Package
+    *
+    *  Register Definitions                     File: bcm1480_regs.h
+    *
+    *  This module contains the addresses of the on-chip peripherals
+    *  on the BCM1280 and BCM1480.
+    *
+    *  BCM1480 specification level:  1X55_1X80-UM100-D4 (11/24/03)
+    *
+    *********************************************************************
+    *
+    *  Copyright 2000,2001,2002,2003
+    *  Broadcom Corporation. 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
+    ********************************************************************* */
+
+#ifndef _BCM1480_REGS_H
+#define _BCM1480_REGS_H
+
+#include "sb1250_defs.h"
+
+/*  *********************************************************************
+    *  Pull in the BCM1250's registers since a great deal of the 1480's
+    *  functions are the same as the BCM1250.
+    ********************************************************************* */
+
+#include "sb1250_regs.h"
+
+
+/*  *********************************************************************
+    *  Some general notes:
+    *
+    *  Register addresses are grouped by function and follow the order
+    *  of the User Manual.
+    *
+    *  For the most part, when there is more than one peripheral
+    *  of the same type on the SOC, the constants below will be
+    *  offsets from the base of each peripheral.  For example,
+    *  the MAC registers are described as offsets from the first
+    *  MAC register, and there will be a MAC_REGISTER() macro
+    *  to calculate the base address of a given MAC.
+    *
+    *  The information in this file is based on the BCM1X55/BCM1X80
+    *  User Manual, Document 1X55_1X80-UM100-R, 22/12/03.
+    *
+    *  This file is basically a "what's new" header file.  Since the
+    *  BCM1250 and the new BCM1480 (and derivatives) share many common
+    *  features, this file contains only what's new or changed from
+    *  the 1250.  (above, you can see that we include the 1250 symbols
+    *  to get the base functionality).
+    *
+    *  In software, be sure to use the correct symbols, particularly
+    *  for blocks that are different between the two chip families.
+    *  All BCM1480-specific symbols have _BCM1480_ in their names,
+    *  and all BCM1250-specific and "base" functions that are common in
+    *  both chips have no special names (this is for compatibility with
+    *  older include files).  Therefore, if you're working with the
+    *  SCD, which is very different on each chip, A_SCD_xxx implies
+    *  the BCM1250 version and A_BCM1480_SCD_xxx implies the BCM1480
+    *  version.
+    ********************************************************************* */
+
+
+/*  *********************************************************************
+    * Memory Controller Registers (Section 6)
+    ********************************************************************* */
+
+#define A_BCM1480_MC_BASE_0                 0x0010050000
+#define A_BCM1480_MC_BASE_1                 0x0010051000
+#define A_BCM1480_MC_BASE_2                 0x0010052000
+#define A_BCM1480_MC_BASE_3                 0x0010053000
+#define BCM1480_MC_REGISTER_SPACING         0x1000
+
+#define A_BCM1480_MC_BASE(ctlid)            (A_BCM1480_MC_BASE_0+(ctlid)*BCM1480_MC_REGISTER_SPACING)
+#define A_BCM1480_MC_REGISTER(ctlid,reg)    (A_BCM1480_MC_BASE(ctlid)+(reg))
+
+#define R_BCM1480_MC_CONFIG                 0x0000000100
+#define R_BCM1480_MC_CS_START               0x0000000120
+#define R_BCM1480_MC_CS_END                 0x0000000140
+#define S_BCM1480_MC_CS_STARTEND            24
+
+#define R_BCM1480_MC_CS01_ROW0              0x0000000180
+#define R_BCM1480_MC_CS01_ROW1              0x00000001A0
+#define R_BCM1480_MC_CS23_ROW0              0x0000000200
+#define R_BCM1480_MC_CS23_ROW1              0x0000000220
+#define R_BCM1480_MC_CS01_COL0              0x0000000280
+#define R_BCM1480_MC_CS01_COL1              0x00000002A0
+#define R_BCM1480_MC_CS23_COL0              0x0000000300
+#define R_BCM1480_MC_CS23_COL1              0x0000000320
+
+#define R_BCM1480_MC_CSX_BASE               0x0000000180
+#define R_BCM1480_MC_CSX_ROW0               0x0000000000   /* relative to CSX_BASE */
+#define R_BCM1480_MC_CSX_ROW1               0x0000000020   /* relative to CSX_BASE */
+#define R_BCM1480_MC_CSX_COL0               0x0000000100   /* relative to CSX_BASE */
+#define R_BCM1480_MC_CSX_COL1               0x0000000120   /* relative to CSX_BASE */
+#define BCM1480_MC_CSX_SPACING              0x0000000080   /* CS23 relative to CS01 */
+
+#define R_BCM1480_MC_CS01_BA                0x0000000380
+#define R_BCM1480_MC_CS23_BA                0x00000003A0
+#define R_BCM1480_MC_DRAMCMD                0x0000000400
+#define R_BCM1480_MC_DRAMMODE               0x0000000420
+#define R_BCM1480_MC_CLOCK_CFG              0x0000000440
+#define R_BCM1480_MC_MCLK_CFG               R_BCM1480_MC_CLOCK_CFG
+#define R_BCM1480_MC_TEST_DATA              0x0000000480
+#define R_BCM1480_MC_TEST_ECC               0x00000004A0
+#define R_BCM1480_MC_TIMING1                0x00000004C0
+#define R_BCM1480_MC_TIMING2                0x00000004E0
+#define R_BCM1480_MC_DLL_CFG                0x0000000500
+#define R_BCM1480_MC_DRIVE_CFG              0x0000000520
+
+#if SIBYTE_HDR_FEATURE(1480, PASS2)
+#define R_BCM1480_MC_ODT		    0x0000000460
+#define R_BCM1480_MC_ECC_STATUS		    0x0000000540
+#endif
+
+/* Global registers (single instance) */
+#define A_BCM1480_MC_GLB_CONFIG             0x0010054100
+#define A_BCM1480_MC_GLB_INTLV              0x0010054120
+#define A_BCM1480_MC_GLB_ECC_STATUS         0x0010054140
+#define A_BCM1480_MC_GLB_ECC_ADDR           0x0010054160
+#define A_BCM1480_MC_GLB_ECC_CORRECT        0x0010054180
+#define A_BCM1480_MC_GLB_PERF_CNT_CONTROL   0x00100541A0
+
+/*  *********************************************************************
+    * L2 Cache Control Registers (Section 5)
+    ********************************************************************* */
+
+#define A_BCM1480_L2_BASE                   0x0010040000
+
+#define A_BCM1480_L2_READ_TAG               0x0010040018
+#define A_BCM1480_L2_ECC_TAG                0x0010040038
+#define A_BCM1480_L2_MISC0_VALUE            0x0010040058
+#define A_BCM1480_L2_MISC1_VALUE            0x0010040078
+#define A_BCM1480_L2_MISC2_VALUE            0x0010040098
+#define A_BCM1480_L2_MISC_CONFIG            0x0010040040	/* x040 */
+#define A_BCM1480_L2_CACHE_DISABLE          0x0010040060	/* x060 */
+#define A_BCM1480_L2_MAKECACHEDISABLE(x)    (A_BCM1480_L2_CACHE_DISABLE | (((x)&0xF) << 12))
+#define A_BCM1480_L2_WAY_ENABLE_3_0         0x0010040080	/* x080 */
+#define A_BCM1480_L2_WAY_ENABLE_7_4         0x00100400A0	/* x0A0 */
+#define A_BCM1480_L2_MAKE_WAY_ENABLE_LO(x)  (A_BCM1480_L2_WAY_ENABLE_3_0 | (((x)&0xF) << 12))
+#define A_BCM1480_L2_MAKE_WAY_ENABLE_HI(x)  (A_BCM1480_L2_WAY_ENABLE_7_4 | (((x)&0xF) << 12))
+#define A_BCM1480_L2_MAKE_WAY_DISABLE_LO(x)  (A_BCM1480_L2_WAY_ENABLE_3_0 | (((~x)&0xF) << 12))
+#define A_BCM1480_L2_MAKE_WAY_DISABLE_HI(x)  (A_BCM1480_L2_WAY_ENABLE_7_4 | (((~x)&0xF) << 12))
+#define A_BCM1480_L2_WAY_LOCAL_3_0          0x0010040100	/* x100 */
+#define A_BCM1480_L2_WAY_LOCAL_7_4          0x0010040120	/* x120 */
+#define A_BCM1480_L2_WAY_REMOTE_3_0         0x0010040140	/* x140 */
+#define A_BCM1480_L2_WAY_REMOTE_7_4         0x0010040160	/* x160 */
+#define A_BCM1480_L2_WAY_AGENT_3_0          0x00100400C0	/* xxC0 */
+#define A_BCM1480_L2_WAY_AGENT_7_4          0x00100400E0	/* xxE0 */
+#define A_BCM1480_L2_WAY_ENABLE(A, banks)   (A | (((~(banks))&0x0F) << 8))
+#define A_BCM1480_L2_BANK_BASE              0x00D0300000
+#define A_BCM1480_L2_BANK_ADDRESS(b)        (A_BCM1480_L2_BANK_BASE | (((b)&0x7)<<17))
+#define A_BCM1480_L2_MGMT_TAG_BASE          0x00D0000000
+
+
+/*  *********************************************************************
+    * PCI-X Interface Registers (Section 7)
+    ********************************************************************* */
+
+#define A_BCM1480_PCI_BASE                  0x0010061400
+
+#define A_BCM1480_PCI_RESET                 0x0010061400
+#define A_BCM1480_PCI_DLL                   0x0010061500
+
+#define A_BCM1480_PCI_TYPE00_HEADER         0x002E000000
+
+/*  *********************************************************************
+    * Ethernet MAC Registers (Section 11) and DMA Registers (Section 10.6)
+    ********************************************************************* */
+
+/* No register changes with Rev.C BCM1250, but one additional MAC */
+
+#define A_BCM1480_MAC_BASE_2        0x0010066000
+
+#ifndef A_MAC_BASE_2
+#define A_MAC_BASE_2                A_BCM1480_MAC_BASE_2
+#endif
+
+#define A_BCM1480_MAC_BASE_3        0x0010067000
+#define A_MAC_BASE_3                A_BCM1480_MAC_BASE_3
+
+#define R_BCM1480_MAC_DMA_OODPKTLOST        0x00000038
+
+#ifndef R_MAC_DMA_OODPKTLOST
+#define R_MAC_DMA_OODPKTLOST        R_BCM1480_MAC_DMA_OODPKTLOST
+#endif
+
+
+/*  *********************************************************************
+    * DUART Registers (Section 14)
+    ********************************************************************* */
+
+/* No significant differences from BCM1250, two DUARTs */
+
+/*  Conventions, per user manual:
+ *     DUART    generic, channels A,B,C,D
+ *     DUART0   implementing channels A,B
+ *     DUART1   inplementing channels C,D
+ */
+
+#define BCM1480_DUART_NUM_PORTS           4
+
+#define A_BCM1480_DUART0                    0x0010060000
+#define A_BCM1480_DUART1                    0x0010060400
+#define A_BCM1480_DUART(chan)               ((((chan)&2) == 0)? A_BCM1480_DUART0 : A_BCM1480_DUART1)
+
+#define BCM1480_DUART_CHANREG_SPACING       0x100
+#define A_BCM1480_DUART_CHANREG(chan,reg)   (A_BCM1480_DUART(chan) \
+                                     + BCM1480_DUART_CHANREG_SPACING*((chan)&1) \
+                                     + (reg))
+#define R_BCM1480_DUART_CHANREG(chan,reg)   (BCM1480_DUART_CHANREG_SPACING*((chan)&1) + (reg))
+
+#define R_BCM1480_DUART_IMRREG(chan)	    (R_DUART_IMR_A + ((chan)&1)*DUART_IMRISR_SPACING)
+#define R_BCM1480_DUART_ISRREG(chan)	    (R_DUART_ISR_A + ((chan)&1)*DUART_IMRISR_SPACING)
+
+#define A_BCM1480_DUART_IMRREG(chan)	    (A_BCM1480_DUART(chan) + R_BCM1480_DUART_IMRREG(chan))
+#define A_BCM1480_DUART_ISRREG(chan)	    (A_BCM1480_DUART(chan) + R_BCM1480_DUART_ISRREG(chan))
+
+/*
+ * These constants are the absolute addresses.
+ */
+
+#define A_BCM1480_DUART_MODE_REG_1_C        0x0010060400
+#define A_BCM1480_DUART_MODE_REG_2_C        0x0010060410
+#define A_BCM1480_DUART_STATUS_C            0x0010060420
+#define A_BCM1480_DUART_CLK_SEL_C           0x0010060430
+#define A_BCM1480_DUART_FULL_CTL_C          0x0010060440
+#define A_BCM1480_DUART_CMD_C               0x0010060450
+#define A_BCM1480_DUART_RX_HOLD_C           0x0010060460
+#define A_BCM1480_DUART_TX_HOLD_C           0x0010060470
+#define A_BCM1480_DUART_OPCR_C              0x0010060480
+#define A_BCM1480_DUART_AUX_CTRL_C          0x0010060490
+
+#define A_BCM1480_DUART_MODE_REG_1_D        0x0010060500
+#define A_BCM1480_DUART_MODE_REG_2_D        0x0010060510
+#define A_BCM1480_DUART_STATUS_D            0x0010060520
+#define A_BCM1480_DUART_CLK_SEL_D           0x0010060530
+#define A_BCM1480_DUART_FULL_CTL_D          0x0010060540
+#define A_BCM1480_DUART_CMD_D               0x0010060550
+#define A_BCM1480_DUART_RX_HOLD_D           0x0010060560
+#define A_BCM1480_DUART_TX_HOLD_D           0x0010060570
+#define A_BCM1480_DUART_OPCR_D              0x0010060580
+#define A_BCM1480_DUART_AUX_CTRL_D          0x0010060590
+
+#define A_BCM1480_DUART_INPORT_CHNG_CD      0x0010060600
+#define A_BCM1480_DUART_AUX_CTRL_CD         0x0010060610
+#define A_BCM1480_DUART_ISR_C               0x0010060620
+#define A_BCM1480_DUART_IMR_C               0x0010060630
+#define A_BCM1480_DUART_ISR_D               0x0010060640
+#define A_BCM1480_DUART_IMR_D               0x0010060650
+#define A_BCM1480_DUART_OUT_PORT_CD         0x0010060660
+#define A_BCM1480_DUART_OPCR_CD             0x0010060670
+#define A_BCM1480_DUART_IN_PORT_CD          0x0010060680
+#define A_BCM1480_DUART_ISR_CD              0x0010060690
+#define A_BCM1480_DUART_IMR_CD              0x00100606A0
+#define A_BCM1480_DUART_SET_OPR_CD          0x00100606B0
+#define A_BCM1480_DUART_CLEAR_OPR_CD        0x00100606C0
+#define A_BCM1480_DUART_INPORT_CHNG_C       0x00100606D0
+#define A_BCM1480_DUART_INPORT_CHNG_D       0x00100606E0
+
+
+/*  *********************************************************************
+    * Generic Bus Registers (Section 15) and PCMCIA Registers (Section 16)
+    ********************************************************************* */
+
+#define A_BCM1480_IO_PCMCIA_CFG_B	0x0010061A58
+#define A_BCM1480_IO_PCMCIA_STATUS_B	0x0010061A68
+
+/*  *********************************************************************
+    * GPIO Registers (Section 17)
+    ********************************************************************* */
+
+/* One additional GPIO register, placed _before_ the BCM1250's GPIO block base */
+
+#define A_BCM1480_GPIO_INT_ADD_TYPE         0x0010061A78
+#define R_BCM1480_GPIO_INT_ADD_TYPE         (-8)
+
+#define A_GPIO_INT_ADD_TYPE	A_BCM1480_GPIO_INT_ADD_TYPE
+#define R_GPIO_INT_ADD_TYPE	R_BCM1480_GPIO_INT_ADD_TYPE
+
+/*  *********************************************************************
+    * SMBus Registers (Section 18)
+    ********************************************************************* */
+
+/* No changes from BCM1250 */
+
+/*  *********************************************************************
+    * Timer Registers (Sections 4.6)
+    ********************************************************************* */
+
+/* BCM1480 has two additional watchdogs */
+
+/* Watchdog timers */
+
+#define A_BCM1480_SCD_WDOG_2                0x0010022050
+#define A_BCM1480_SCD_WDOG_3                0x0010022150
+
+#define BCM1480_SCD_NUM_WDOGS               4
+
+#define A_BCM1480_SCD_WDOG_BASE(w)       (A_BCM1480_SCD_WDOG_0+((w)&2)*0x1000 + ((w)&1)*0x100)
+#define A_BCM1480_SCD_WDOG_REGISTER(w,r) (A_BCM1480_SCD_WDOG_BASE(w) + (r))
+
+#define A_BCM1480_SCD_WDOG_INIT_2       0x0010022050
+#define A_BCM1480_SCD_WDOG_CNT_2        0x0010022058
+#define A_BCM1480_SCD_WDOG_CFG_2        0x0010022060
+
+#define A_BCM1480_SCD_WDOG_INIT_3       0x0010022150
+#define A_BCM1480_SCD_WDOG_CNT_3        0x0010022158
+#define A_BCM1480_SCD_WDOG_CFG_3        0x0010022160
+
+/* BCM1480 has two additional compare registers */
+
+#define A_BCM1480_SCD_ZBBUS_CYCLE_COUNT		A_SCD_ZBBUS_CYCLE_COUNT
+#define A_BCM1480_SCD_ZBBUS_CYCLE_CP_BASE       0x0010020C00
+#define A_BCM1480_SCD_ZBBUS_CYCLE_CP0           A_SCD_ZBBUS_CYCLE_CP0
+#define A_BCM1480_SCD_ZBBUS_CYCLE_CP1           A_SCD_ZBBUS_CYCLE_CP1
+#define A_BCM1480_SCD_ZBBUS_CYCLE_CP2           0x0010020C10
+#define A_BCM1480_SCD_ZBBUS_CYCLE_CP3           0x0010020C18
+
+/*  *********************************************************************
+    * System Control Registers (Section 4.2)
+    ********************************************************************* */
+
+/* Scratch register in different place */
+
+#define A_BCM1480_SCD_SCRATCH	 	0x100200A0
+
+/*  *********************************************************************
+    * System Address Trap Registers (Section 4.9)
+    ********************************************************************* */
+
+/* No changes from BCM1250 */
+
+/*  *********************************************************************
+    * System Interrupt Mapper Registers (Sections 4.3-4.5)
+    ********************************************************************* */
+
+#define A_BCM1480_IMR_CPU0_BASE             0x0010020000
+#define A_BCM1480_IMR_CPU1_BASE             0x0010022000
+#define A_BCM1480_IMR_CPU2_BASE             0x0010024000
+#define A_BCM1480_IMR_CPU3_BASE             0x0010026000
+#define BCM1480_IMR_REGISTER_SPACING        0x2000
+#define BCM1480_IMR_REGISTER_SPACING_SHIFT  13
+
+#define A_BCM1480_IMR_MAPPER(cpu)       (A_BCM1480_IMR_CPU0_BASE+(cpu)*BCM1480_IMR_REGISTER_SPACING)
+#define A_BCM1480_IMR_REGISTER(cpu,reg) (A_BCM1480_IMR_MAPPER(cpu)+(reg))
+
+/* Most IMR registers are 128 bits, implemented as non-contiguous
+   64-bit registers high (_H) and low (_L) */
+#define BCM1480_IMR_HL_SPACING                  0x1000
+
+#define R_BCM1480_IMR_INTERRUPT_DIAG_H          0x0010
+#define R_BCM1480_IMR_LDT_INTERRUPT_H           0x0018
+#define R_BCM1480_IMR_LDT_INTERRUPT_CLR_H       0x0020
+#define R_BCM1480_IMR_INTERRUPT_MASK_H          0x0028
+#define R_BCM1480_IMR_INTERRUPT_TRACE_H         0x0038
+#define R_BCM1480_IMR_INTERRUPT_SOURCE_STATUS_H 0x0040
+#define R_BCM1480_IMR_LDT_INTERRUPT_SET         0x0048
+#define R_BCM1480_IMR_MAILBOX_0_CPU             0x00C0
+#define R_BCM1480_IMR_MAILBOX_0_SET_CPU         0x00C8
+#define R_BCM1480_IMR_MAILBOX_0_CLR_CPU         0x00D0
+#define R_BCM1480_IMR_MAILBOX_1_CPU             0x00E0
+#define R_BCM1480_IMR_MAILBOX_1_SET_CPU         0x00E8
+#define R_BCM1480_IMR_MAILBOX_1_CLR_CPU         0x00F0
+#define R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H   0x0100
+#define BCM1480_IMR_INTERRUPT_STATUS_COUNT      8
+#define R_BCM1480_IMR_INTERRUPT_MAP_BASE_H      0x0200
+#define BCM1480_IMR_INTERRUPT_MAP_COUNT         64
+
+#define R_BCM1480_IMR_INTERRUPT_DIAG_L          0x1010
+#define R_BCM1480_IMR_LDT_INTERRUPT_L           0x1018
+#define R_BCM1480_IMR_LDT_INTERRUPT_CLR_L       0x1020
+#define R_BCM1480_IMR_INTERRUPT_MASK_L          0x1028
+#define R_BCM1480_IMR_INTERRUPT_TRACE_L         0x1038
+#define R_BCM1480_IMR_INTERRUPT_SOURCE_STATUS_L 0x1040
+#define R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L   0x1100
+#define R_BCM1480_IMR_INTERRUPT_MAP_BASE_L      0x1200
+
+#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU0_BASE   0x0010028000
+#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU1_BASE   0x0010028100
+#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU2_BASE   0x0010028200
+#define A_BCM1480_IMR_ALIAS_MAILBOX_CPU3_BASE   0x0010028300
+#define BCM1480_IMR_ALIAS_MAILBOX_SPACING       0100
+
+#define A_BCM1480_IMR_ALIAS_MAILBOX(cpu)     (A_BCM1480_IMR_ALIAS_MAILBOX_CPU0_BASE + \
+                                        (cpu)*BCM1480_IMR_ALIAS_MAILBOX_SPACING)
+#define A_BCM1480_IMR_ALIAS_MAILBOX_REGISTER(cpu,reg) (A_BCM1480_IMR_ALIAS_MAILBOX(cpu)+(reg))
+
+#define R_BCM1480_IMR_ALIAS_MAILBOX_0           0x0000		/* 0x0x0 */
+#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET       0x0008		/* 0x0x8 */
+
+/*  *********************************************************************
+    * System Performance Counter Registers (Section 4.7)
+    ********************************************************************* */
+
+/* BCM1480 has four more performance counter registers, and two control
+   registers. */
+
+#define A_BCM1480_SCD_PERF_CNT_BASE         0x00100204C0
+
+#define A_BCM1480_SCD_PERF_CNT_CFG0         0x00100204C0
+#define A_BCM1480_SCD_PERF_CNT_CFG_0        A_BCM1480_SCD_PERF_CNT_CFG0
+#define A_BCM1480_SCD_PERF_CNT_CFG1         0x00100204C8
+#define A_BCM1480_SCD_PERF_CNT_CFG_1        A_BCM1480_SCD_PERF_CNT_CFG1
+
+#define A_BCM1480_SCD_PERF_CNT_0            A_SCD_PERF_CNT_0
+#define A_BCM1480_SCD_PERF_CNT_1            A_SCD_PERF_CNT_1
+#define A_BCM1480_SCD_PERF_CNT_2            A_SCD_PERF_CNT_2
+#define A_BCM1480_SCD_PERF_CNT_3            A_SCD_PERF_CNT_3
+
+#define A_BCM1480_SCD_PERF_CNT_4            0x00100204F0
+#define A_BCM1480_SCD_PERF_CNT_5            0x00100204F8
+#define A_BCM1480_SCD_PERF_CNT_6            0x0010020500
+#define A_BCM1480_SCD_PERF_CNT_7            0x0010020508
+
+/*  *********************************************************************
+    * System Bus Watcher Registers (Section 4.8)
+    ********************************************************************* */
+
+
+/* Same as 1250 except BUS_ERR_STATUS_DEBUG is in a different place. */
+
+#define A_BCM1480_BUS_ERR_STATUS_DEBUG      0x00100208D8
+
+/*  *********************************************************************
+    * System Debug Controller Registers (Section 19)
+    ********************************************************************* */
+
+/* Same as 1250 */
+
+/*  *********************************************************************
+    * System Trace Unit Registers (Sections 4.10)
+    ********************************************************************* */
+
+/* Same as 1250 */
+
+/*  *********************************************************************
+    * Data Mover DMA Registers (Section 10.7)
+    ********************************************************************* */
+
+/* Same as 1250 */
+
+
+/*  *********************************************************************
+    * HyperTransport Interface Registers (Section 8)
+    ********************************************************************* */
+
+#define BCM1480_HT_NUM_PORTS		   3
+#define BCM1480_HT_PORT_SPACING		   0x800
+#define A_BCM1480_HT_PORT_HEADER(x)	   (A_BCM1480_HT_PORT0_HEADER + ((x)*BCM1480_HT_PORT_SPACING))
+
+#define A_BCM1480_HT_PORT0_HEADER          0x00FE000000
+#define A_BCM1480_HT_PORT1_HEADER          0x00FE000800
+#define A_BCM1480_HT_PORT2_HEADER          0x00FE001000
+#define A_BCM1480_HT_TYPE00_HEADER         0x00FE002000
+
+
+/*  *********************************************************************
+    * Node Controller Registers (Section 9)
+    ********************************************************************* */
+
+#define A_BCM1480_NC_BASE                   0x00DFBD0000
+
+#define A_BCM1480_NC_RLD_FIELD              0x00DFBD0000
+#define A_BCM1480_NC_RLD_TRIGGER            0x00DFBD0020
+#define A_BCM1480_NC_RLD_BAD_ERROR          0x00DFBD0040
+#define A_BCM1480_NC_RLD_COR_ERROR          0x00DFBD0060
+#define A_BCM1480_NC_RLD_ECC_STATUS         0x00DFBD0080
+#define A_BCM1480_NC_RLD_WAY_ENABLE         0x00DFBD00A0
+#define A_BCM1480_NC_RLD_RANDOM_LFSR        0x00DFBD00C0
+
+#define A_BCM1480_NC_INTERRUPT_STATUS       0x00DFBD00E0
+#define A_BCM1480_NC_INTERRUPT_ENABLE       0x00DFBD0100
+#define A_BCM1480_NC_TIMEOUT_COUNTER        0x00DFBD0120
+#define A_BCM1480_NC_TIMEOUT_COUNTER_SEL    0x00DFBD0140
+
+#define A_BCM1480_NC_CREDIT_STATUS_REG0     0x00DFBD0200
+#define A_BCM1480_NC_CREDIT_STATUS_REG1     0x00DFBD0220
+#define A_BCM1480_NC_CREDIT_STATUS_REG2     0x00DFBD0240
+#define A_BCM1480_NC_CREDIT_STATUS_REG3     0x00DFBD0260
+#define A_BCM1480_NC_CREDIT_STATUS_REG4     0x00DFBD0280
+#define A_BCM1480_NC_CREDIT_STATUS_REG5     0x00DFBD02A0
+#define A_BCM1480_NC_CREDIT_STATUS_REG6     0x00DFBD02C0
+#define A_BCM1480_NC_CREDIT_STATUS_REG7     0x00DFBD02E0
+#define A_BCM1480_NC_CREDIT_STATUS_REG8     0x00DFBD0300
+#define A_BCM1480_NC_CREDIT_STATUS_REG9     0x00DFBD0320
+#define A_BCM1480_NC_CREDIT_STATUS_REG10    0x00DFBE0000
+#define A_BCM1480_NC_CREDIT_STATUS_REG11    0x00DFBE0020
+#define A_BCM1480_NC_CREDIT_STATUS_REG12    0x00DFBE0040
+
+#define A_BCM1480_NC_SR_TIMEOUT_COUNTER     0x00DFBE0060
+#define A_BCM1480_NC_SR_TIMEOUT_COUNTER_SEL 0x00DFBE0080
+
+
+/*  *********************************************************************
+    * H&R Block Configuration Registers (Section 12.4)
+    ********************************************************************* */
+
+#define A_BCM1480_HR_BASE_0                 0x00DF820000
+#define A_BCM1480_HR_BASE_1                 0x00DF8A0000
+#define A_BCM1480_HR_BASE_2                 0x00DF920000
+#define BCM1480_HR_REGISTER_SPACING         0x80000
+
+#define A_BCM1480_HR_BASE(idx)              (A_BCM1480_HR_BASE_0 + ((idx)*BCM1480_HR_REGISTER_SPACING))
+#define A_BCM1480_HR_REGISTER(idx,reg)      (A_BCM1480_HR_BASE(idx) + (reg))
+
+#define R_BCM1480_HR_CFG                    0x0000000000
+
+#define R_BCM1480_HR_MAPPING		    0x0000010010
+
+#define BCM1480_HR_RULE_SPACING             0x0000000010
+#define BCM1480_HR_NUM_RULES                16
+#define BCM1480_HR_OP_OFFSET                0x0000000100
+#define BCM1480_HR_TYPE_OFFSET              0x0000000108
+#define R_BCM1480_HR_RULE_OP(idx)           (BCM1480_HR_OP_OFFSET + ((idx)*BCM1480_HR_RULE_SPACING))
+#define R_BCM1480_HR_RULE_TYPE(idx)         (BCM1480_HR_TYPE_OFFSET + ((idx)*BCM1480_HR_RULE_SPACING))
+
+#define BCM1480_HR_LEAF_SPACING             0x0000000010
+#define BCM1480_HR_NUM_LEAVES               10
+#define BCM1480_HR_LEAF_OFFSET              0x0000000300
+#define R_BCM1480_HR_HA_LEAF0(idx)          (BCM1480_HR_LEAF_OFFSET + ((idx)*BCM1480_HR_LEAF_SPACING))
+
+#define R_BCM1480_HR_EX_LEAF0               0x00000003A0
+
+#define BCM1480_HR_PATH_SPACING             0x0000000010
+#define BCM1480_HR_NUM_PATHS                16
+#define BCM1480_HR_PATH_OFFSET              0x0000000600
+#define R_BCM1480_HR_PATH(idx)              (BCM1480_HR_PATH_OFFSET + ((idx)*BCM1480_HR_PATH_SPACING))
+
+#define R_BCM1480_HR_PATH_DEFAULT           0x0000000700
+
+#define BCM1480_HR_ROUTE_SPACING            8
+#define BCM1480_HR_NUM_ROUTES               512
+#define BCM1480_HR_ROUTE_OFFSET             0x0000001000
+#define R_BCM1480_HR_RT_WORD(idx)           (BCM1480_HR_ROUTE_OFFSET + ((idx)*BCM1480_HR_ROUTE_SPACING))
+
+
+/* checked to here - ehs */
+/*  *********************************************************************
+    * Packet Manager DMA Registers (Section 12.5)
+    ********************************************************************* */
+
+#define A_BCM1480_PM_BASE                   0x0010056000
+
+#define A_BCM1480_PMI_LCL_0                 0x0010058000
+#define A_BCM1480_PMO_LCL_0                 0x001005C000
+#define A_BCM1480_PMI_OFFSET_0              (A_BCM1480_PMI_LCL_0 - A_BCM1480_PM_BASE)
+#define A_BCM1480_PMO_OFFSET_0              (A_BCM1480_PMO_LCL_0 - A_BCM1480_PM_BASE)
+
+#define BCM1480_PM_LCL_REGISTER_SPACING     0x100
+#define BCM1480_PM_NUM_CHANNELS             32
+
+#define A_BCM1480_PMI_LCL_BASE(idx)             (A_BCM1480_PMI_LCL_0 + ((idx)*BCM1480_PM_LCL_REGISTER_SPACING))
+#define A_BCM1480_PMI_LCL_REGISTER(idx,reg)     (A_BCM1480_PMI_LCL_BASE(idx) + (reg))
+#define A_BCM1480_PMO_LCL_BASE(idx)             (A_BCM1480_PMO_LCL_0 + ((idx)*BCM1480_PM_LCL_REGISTER_SPACING))
+#define A_BCM1480_PMO_LCL_REGISTER(idx,reg)     (A_BCM1480_PMO_LCL_BASE(idx) + (reg))
+
+#define BCM1480_PM_INT_PACKING              8
+#define BCM1480_PM_INT_FUNCTION_SPACING     0x40
+#define BCM1480_PM_INT_NUM_FUNCTIONS        3
+
+/*
+ * DMA channel registers relative to A_BCM1480_PMI_LCL_BASE(n) and A_BCM1480_PMO_LCL_BASE(n)
+ */
+
+#define R_BCM1480_PM_BASE_SIZE              0x0000000000
+#define R_BCM1480_PM_CNT                    0x0000000008
+#define R_BCM1480_PM_PFCNT                  0x0000000010
+#define R_BCM1480_PM_LAST                   0x0000000018
+#define R_BCM1480_PM_PFINDX                 0x0000000020
+#define R_BCM1480_PM_INT_WMK                0x0000000028
+#define R_BCM1480_PM_CONFIG0                0x0000000030
+#define R_BCM1480_PM_LOCALDEBUG             0x0000000078
+#define R_BCM1480_PM_CACHEABILITY           0x0000000080   /* PMI only */
+#define R_BCM1480_PM_INT_CNFG               0x0000000088
+#define R_BCM1480_PM_DESC_MERGE_TIMER       0x0000000090
+#define R_BCM1480_PM_LOCALDEBUG_PIB         0x00000000F8   /* PMI only */
+#define R_BCM1480_PM_LOCALDEBUG_POB         0x00000000F8   /* PMO only */
+
+/*
+ * Global Registers (Not Channelized)
+ */
+
+#define A_BCM1480_PMI_GLB_0                 0x0010056000
+#define A_BCM1480_PMO_GLB_0                 0x0010057000
+
+/*
+ * PM to TX Mapping Register relative to A_BCM1480_PMI_GLB_0 and A_BCM1480_PMO_GLB_0
+ */
+
+#define R_BCM1480_PM_PMO_MAPPING            0x00000008C8   /* PMO only */
+
+#define A_BCM1480_PM_PMO_MAPPING	(A_BCM1480_PMO_GLB_0 + R_BCM1480_PM_PMO_MAPPING)
+
+/*
+ * Interrupt mapping registers
+ */
+
+
+#define A_BCM1480_PMI_INT_0                 0x0010056800
+#define A_BCM1480_PMI_INT(q)                (A_BCM1480_PMI_INT_0 + ((q>>8)<<8))
+#define A_BCM1480_PMI_INT_OFFSET_0          (A_BCM1480_PMI_INT_0 - A_BCM1480_PM_BASE)
+#define A_BCM1480_PMO_INT_0                 0x0010057800
+#define A_BCM1480_PMO_INT(q)                (A_BCM1480_PMO_INT_0 + ((q>>8)<<8))
+#define A_BCM1480_PMO_INT_OFFSET_0          (A_BCM1480_PMO_INT_0 - A_BCM1480_PM_BASE)
+
+/*
+ * Interrupt registers relative to A_BCM1480_PMI_INT_0 and A_BCM1480_PMO_INT_0
+ */
+
+#define R_BCM1480_PM_INT_ST                 0x0000000000
+#define R_BCM1480_PM_INT_MSK                0x0000000040
+#define R_BCM1480_PM_INT_CLR                0x0000000080
+#define R_BCM1480_PM_MRGD_INT               0x00000000C0
+
+/*
+ * Debug registers (global)
+ */
+
+#define A_BCM1480_PM_GLOBALDEBUGMODE_PMI    0x0010056000
+#define A_BCM1480_PM_GLOBALDEBUG_PID        0x00100567F8
+#define A_BCM1480_PM_GLOBALDEBUG_PIB        0x0010056FF8
+#define A_BCM1480_PM_GLOBALDEBUGMODE_PMO    0x0010057000
+#define A_BCM1480_PM_GLOBALDEBUG_POD        0x00100577F8
+#define A_BCM1480_PM_GLOBALDEBUG_POB        0x0010057FF8
+
+/*  *********************************************************************
+    *  Switch performance counters
+    ********************************************************************* */
+
+#define A_BCM1480_SWPERF_CFG	0xdfb91800
+#define A_BCM1480_SWPERF_CNT0	0xdfb91880
+#define A_BCM1480_SWPERF_CNT1	0xdfb91888
+#define A_BCM1480_SWPERF_CNT2	0xdfb91890
+#define A_BCM1480_SWPERF_CNT3	0xdfb91898
+
+
+/*  *********************************************************************
+    *  Switch Trace Unit
+    ********************************************************************* */
+
+#define A_BCM1480_SWTRC_MATCH_CONTROL_0		0xDFB91000
+#define A_BCM1480_SWTRC_MATCH_DATA_VALUE_0	0xDFB91100
+#define A_BCM1480_SWTRC_MATCH_DATA_MASK_0	0xDFB91108
+#define A_BCM1480_SWTRC_MATCH_TAG_VALUE_0	0xDFB91200
+#define A_BCM1480_SWTRC_MATCH_TAG_MAKS_0	0xDFB91208
+#define A_BCM1480_SWTRC_EVENT_0			0xDFB91300
+#define A_BCM1480_SWTRC_SEQUENCE_0		0xDFB91400
+
+#define A_BCM1480_SWTRC_CFG			0xDFB91500
+#define A_BCM1480_SWTRC_READ			0xDFB91508
+
+#define A_BCM1480_SWDEBUG_SCHEDSTOP		0xDFB92000
+
+#define A_BCM1480_SWTRC_MATCH_CONTROL(x) (A_BCM1480_SWTRC_MATCH_CONTROL_0 + ((x)*8))
+#define A_BCM1480_SWTRC_EVENT(x) (A_BCM1480_SWTRC_EVENT_0 + ((x)*8))
+#define A_BCM1480_SWTRC_SEQUENCE(x) (A_BCM1480_SWTRC_SEQUENCE_0 + ((x)*8))
+
+#define A_BCM1480_SWTRC_MATCH_DATA_VALUE(x) (A_BCM1480_SWTRC_MATCH_DATA_VALUE_0 + ((x)*16))
+#define A_BCM1480_SWTRC_MATCH_DATA_MASK(x) (A_BCM1480_SWTRC_MATCH_DATA_MASK_0 + ((x)*16))
+#define A_BCM1480_SWTRC_MATCH_TAG_VALUE(x) (A_BCM1480_SWTRC_MATCH_TAG_VALUE_0 + ((x)*16))
+#define A_BCM1480_SWTRC_MATCH_TAG_MASK(x) (A_BCM1480_SWTRC_MATCH_TAG_MASK_0 + ((x)*16))
+
+
+
+/*  *********************************************************************
+    *  High-Speed Port Registers (Section 13)
+    ********************************************************************* */
+
+#define A_BCM1480_HSP_BASE_0                0x00DF810000
+#define A_BCM1480_HSP_BASE_1                0x00DF890000
+#define A_BCM1480_HSP_BASE_2                0x00DF910000
+#define BCM1480_HSP_REGISTER_SPACING        0x80000
+
+#define A_BCM1480_HSP_BASE(idx)             (A_BCM1480_HSP_BASE_0 + ((idx)*BCM1480_HSP_REGISTER_SPACING))
+#define A_BCM1480_HSP_REGISTER(idx,reg)     (A_BCM1480_HSP_BASE(idx) + (reg))
+
+#define R_BCM1480_HSP_RX_SPI4_CFG_0           0x0000000000
+#define R_BCM1480_HSP_RX_SPI4_CFG_1           0x0000000008
+#define R_BCM1480_HSP_RX_SPI4_DESKEW_OVERRIDE 0x0000000010
+#define R_BCM1480_HSP_RX_SPI4_DESKEW_DATAPATH 0x0000000018
+#define R_BCM1480_HSP_RX_SPI4_PORT_INT_EN     0x0000000020
+#define R_BCM1480_HSP_RX_SPI4_PORT_INT_STATUS 0x0000000028
+
+#define R_BCM1480_HSP_RX_SPI4_CALENDAR_0      0x0000000200
+#define R_BCM1480_HSP_RX_SPI4_CALENDAR_1      0x0000000208
+
+#define R_BCM1480_HSP_RX_PLL_CNFG             0x0000000800
+#define R_BCM1480_HSP_RX_CALIBRATION          0x0000000808
+#define R_BCM1480_HSP_RX_TEST                 0x0000000810
+#define R_BCM1480_HSP_RX_DIAG_DETAILS         0x0000000818
+#define R_BCM1480_HSP_RX_DIAG_CRC_0           0x0000000820
+#define R_BCM1480_HSP_RX_DIAG_CRC_1           0x0000000828
+#define R_BCM1480_HSP_RX_DIAG_HTCMD           0x0000000830
+#define R_BCM1480_HSP_RX_DIAG_PKTCTL          0x0000000838
+
+#define R_BCM1480_HSP_RX_VIS_FLCTRL_COUNTER   0x0000000870
+
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_0       0x0000020020
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_1       0x0000020028
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_2       0x0000020030
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_3       0x0000020038
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_4       0x0000020040
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_5       0x0000020048
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_6       0x0000020050
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC_7       0x0000020058
+#define R_BCM1480_HSP_RX_PKT_RAMALLOC(idx)    (R_BCM1480_HSP_RX_PKT_RAMALLOC_0 + 8*(idx))
+
+/* XXX Following registers were shuffled.  Renamed/renumbered per errata. */
+#define R_BCM1480_HSP_RX_HT_RAMALLOC_0      0x0000020078
+#define R_BCM1480_HSP_RX_HT_RAMALLOC_1      0x0000020080
+#define R_BCM1480_HSP_RX_HT_RAMALLOC_2      0x0000020088
+#define R_BCM1480_HSP_RX_HT_RAMALLOC_3      0x0000020090
+#define R_BCM1480_HSP_RX_HT_RAMALLOC_4      0x0000020098
+#define R_BCM1480_HSP_RX_HT_RAMALLOC_5      0x00000200A0
+
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_0      0x00000200B0
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_1      0x00000200B8
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_2      0x00000200C0
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_3      0x00000200C8
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_4      0x00000200D0
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_5      0x00000200D8
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_6      0x00000200E0
+#define R_BCM1480_HSP_RX_SPI_WATERMARK_7      0x00000200E8
+#define R_BCM1480_HSP_RX_SPI_WATERMARK(idx)   (R_BCM1480_HSP_RX_SPI_WATERMARK_0 + 8*(idx))
+
+#define R_BCM1480_HSP_RX_VIS_CMDQ_0           0x00000200F0
+#define R_BCM1480_HSP_RX_VIS_CMDQ_1           0x00000200F8
+#define R_BCM1480_HSP_RX_VIS_CMDQ_2           0x0000020100
+#define R_BCM1480_HSP_RX_RAM_READCTL          0x0000020108
+#define R_BCM1480_HSP_RX_RAM_READWINDOW       0x0000020110
+#define R_BCM1480_HSP_RX_RF_READCTL           0x0000020118
+#define R_BCM1480_HSP_RX_RF_READWINDOW        0x0000020120
+
+#define R_BCM1480_HSP_TX_SPI4_CFG_0           0x0000040000
+#define R_BCM1480_HSP_TX_SPI4_CFG_1           0x0000040008
+#define R_BCM1480_HSP_TX_SPI4_TRAINING_FMT    0x0000040010
+
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_0       0x0000040020
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_1       0x0000040028
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_2       0x0000040030
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_3       0x0000040038
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_4       0x0000040040
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_5       0x0000040048
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_6       0x0000040050
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC_7       0x0000040058
+#define R_BCM1480_HSP_TX_PKT_RAMALLOC(idx)    (R_BCM1480_HSP_TX_PKT_RAMALLOC_0 + 8*(idx))
+#define R_BCM1480_HSP_TX_NPC_RAMALLOC         0x0000040078
+#define R_BCM1480_HSP_TX_RSP_RAMALLOC         0x0000040080
+#define R_BCM1480_HSP_TX_PC_RAMALLOC          0x0000040088
+#define R_BCM1480_HSP_TX_HTCC_RAMALLOC_0      0x0000040090
+#define R_BCM1480_HSP_TX_HTCC_RAMALLOC_1      0x0000040098
+#define R_BCM1480_HSP_TX_HTCC_RAMALLOC_2      0x00000400A0
+
+#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_0      0x00000400B0
+#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_1      0x00000400B8
+#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_2      0x00000400C0
+#define R_BCM1480_HSP_TX_PKT_RXPHITCNT_3      0x00000400C8
+#define R_BCM1480_HSP_TX_PKT_RXPHITCNT(idx)   (R_BCM1480_HSP_TX_PKT_RXPHITCNT_0 + 8*(idx))
+#define R_BCM1480_HSP_TX_HTIO_RXPHITCNT       0x00000400D0
+#define R_BCM1480_HSP_TX_HTCC_RXPHITCNT       0x00000400D8
+
+#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_0      0x00000400E0
+#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_1      0x00000400E8
+#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_2      0x00000400F0
+#define R_BCM1480_HSP_TX_PKT_TXPHITCNT_3      0x00000400F8
+#define R_BCM1480_HSP_TX_PKT_TXPHITCNT(idx)   (R_BCM1480_HSP_TX_PKT_TXPHITCNT_0 + 8*(idx))
+#define R_BCM1480_HSP_TX_HTIO_TXPHITCNT       0x0000040100
+#define R_BCM1480_HSP_TX_HTCC_TXPHITCNT       0x0000040108
+
+#define R_BCM1480_HSP_TX_SPI4_CALENDAR_0      0x0000040200
+#define R_BCM1480_HSP_TX_SPI4_CALENDAR_1      0x0000040208
+
+#define R_BCM1480_HSP_TX_PLL_CNFG             0x0000040800
+#define R_BCM1480_HSP_TX_CALIBRATION          0x0000040808
+#define R_BCM1480_HSP_TX_TEST                 0x0000040810
+
+#define R_BCM1480_HSP_TX_VIS_CMDQ_0           0x0000040840
+#define R_BCM1480_HSP_TX_VIS_CMDQ_1           0x0000040848
+#define R_BCM1480_HSP_TX_VIS_CMDQ_2           0x0000040850
+#define R_BCM1480_HSP_TX_RAM_READCTL          0x0000040860
+#define R_BCM1480_HSP_TX_RAM_READWINDOW       0x0000040868
+#define R_BCM1480_HSP_TX_RF_READCTL           0x0000040870
+#define R_BCM1480_HSP_TX_RF_READWINDOW        0x0000040878
+
+#define R_BCM1480_HSP_TX_SPI4_PORT_INT_STATUS 0x0000040880
+#define R_BCM1480_HSP_TX_SPI4_PORT_INT_EN     0x0000040888
+
+#define R_BCM1480_HSP_TX_NEXT_ADDR_BASE 0x000040400
+#define R_BCM1480_HSP_TX_NEXT_ADDR_REGISTER(x)  (R_BCM1480_HSP_TX_NEXT_ADDR_BASE+ 8*(x))
+
+
+
+/*  *********************************************************************
+    *  Physical Address Map (Table 10 and Figure 7)
+    ********************************************************************* */
+
+#define A_BCM1480_PHYS_MEMORY_0                 _SB_MAKE64(0x0000000000)
+#define A_BCM1480_PHYS_MEMORY_SIZE              _SB_MAKE64((256*1024*1024))
+#define A_BCM1480_PHYS_SYSTEM_CTL               _SB_MAKE64(0x0010000000)
+#define A_BCM1480_PHYS_IO_SYSTEM                _SB_MAKE64(0x0010060000)
+#define A_BCM1480_PHYS_GENBUS                   _SB_MAKE64(0x0010090000)
+#define A_BCM1480_PHYS_GENBUS_END               _SB_MAKE64(0x0028000000)
+#define A_BCM1480_PHYS_PCI_MISC_MATCH_BYTES     _SB_MAKE64(0x0028000000)
+#define A_BCM1480_PHYS_PCI_IACK_MATCH_BYTES     _SB_MAKE64(0x0029000000)
+#define A_BCM1480_PHYS_PCI_IO_MATCH_BYTES       _SB_MAKE64(0x002C000000)
+#define A_BCM1480_PHYS_PCI_CFG_MATCH_BYTES      _SB_MAKE64(0x002E000000)
+#define A_BCM1480_PHYS_PCI_OMAP_MATCH_BYTES     _SB_MAKE64(0x002F000000)
+#define A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES      _SB_MAKE64(0x0030000000)
+#define A_BCM1480_PHYS_HT_MEM_MATCH_BYTES       _SB_MAKE64(0x0040000000)
+#define A_BCM1480_PHYS_HT_MEM_MATCH_BITS        _SB_MAKE64(0x0060000000)
+#define A_BCM1480_PHYS_MEMORY_1                 _SB_MAKE64(0x0080000000)
+#define A_BCM1480_PHYS_MEMORY_2                 _SB_MAKE64(0x0090000000)
+#define A_BCM1480_PHYS_PCI_MISC_MATCH_BITS      _SB_MAKE64(0x00A8000000)
+#define A_BCM1480_PHYS_PCI_IACK_MATCH_BITS      _SB_MAKE64(0x00A9000000)
+#define A_BCM1480_PHYS_PCI_IO_MATCH_BITS        _SB_MAKE64(0x00AC000000)
+#define A_BCM1480_PHYS_PCI_CFG_MATCH_BITS       _SB_MAKE64(0x00AE000000)
+#define A_BCM1480_PHYS_PCI_OMAP_MATCH_BITS      _SB_MAKE64(0x00AF000000)
+#define A_BCM1480_PHYS_PCI_MEM_MATCH_BITS       _SB_MAKE64(0x00B0000000)
+#define A_BCM1480_PHYS_MEMORY_3                 _SB_MAKE64(0x00C0000000)
+#define A_BCM1480_PHYS_L2_CACHE_TEST            _SB_MAKE64(0x00D0000000)
+#define A_BCM1480_PHYS_HT_SPECIAL_MATCH_BYTES   _SB_MAKE64(0x00D8000000)
+#define A_BCM1480_PHYS_HT_IO_MATCH_BYTES        _SB_MAKE64(0x00DC000000)
+#define A_BCM1480_PHYS_HT_CFG_MATCH_BYTES       _SB_MAKE64(0x00DE000000)
+#define A_BCM1480_PHYS_HS_SUBSYS                _SB_MAKE64(0x00DF000000)
+#define A_BCM1480_PHYS_HT_SPECIAL_MATCH_BITS    _SB_MAKE64(0x00F8000000)
+#define A_BCM1480_PHYS_HT_IO_MATCH_BITS         _SB_MAKE64(0x00FC000000)
+#define A_BCM1480_PHYS_HT_CFG_MATCH_BITS        _SB_MAKE64(0x00FE000000)
+#define A_BCM1480_PHYS_MEMORY_EXP               _SB_MAKE64(0x0100000000)
+#define A_BCM1480_PHYS_MEMORY_EXP_SIZE          _SB_MAKE64((508*1024*1024*1024))
+#define A_BCM1480_PHYS_PCI_UPPER                _SB_MAKE64(0x1000000000)
+#define A_BCM1480_PHYS_HT_UPPER_MATCH_BYTES     _SB_MAKE64(0x2000000000)
+#define A_BCM1480_PHYS_HT_UPPER_MATCH_BITS      _SB_MAKE64(0x3000000000)
+#define A_BCM1480_PHYS_HT_NODE_ALIAS            _SB_MAKE64(0x4000000000)
+#define A_BCM1480_PHYS_HT_FULLACCESS            _SB_MAKE64(0xF000000000)
+
+
+/*  *********************************************************************
+    *  L2 Cache as RAM (Table 54)
+    ********************************************************************* */
+
+#define A_BCM1480_PHYS_L2CACHE_WAY_SIZE         _SB_MAKE64(0x0000020000)
+#define BCM1480_PHYS_L2CACHE_NUM_WAYS           8
+#define A_BCM1480_PHYS_L2CACHE_TOTAL_SIZE       _SB_MAKE64(0x0000100000)
+#define A_BCM1480_PHYS_L2CACHE_WAY0             _SB_MAKE64(0x00D0300000)
+#define A_BCM1480_PHYS_L2CACHE_WAY1             _SB_MAKE64(0x00D0320000)
+#define A_BCM1480_PHYS_L2CACHE_WAY2             _SB_MAKE64(0x00D0340000)
+#define A_BCM1480_PHYS_L2CACHE_WAY3             _SB_MAKE64(0x00D0360000)
+#define A_BCM1480_PHYS_L2CACHE_WAY4             _SB_MAKE64(0x00D0380000)
+#define A_BCM1480_PHYS_L2CACHE_WAY5             _SB_MAKE64(0x00D03A0000)
+#define A_BCM1480_PHYS_L2CACHE_WAY6             _SB_MAKE64(0x00D03C0000)
+#define A_BCM1480_PHYS_L2CACHE_WAY7             _SB_MAKE64(0x00D03E0000)
+
+#endif /* _BCM1480_REGS_H */
diff --git a/include/asm-mips/sibyte/bcm1480_scd.h b/include/asm-mips/sibyte/bcm1480_scd.h
new file mode 100644
index 0000000..648bed9
--- /dev/null
+++ b/include/asm-mips/sibyte/bcm1480_scd.h
@@ -0,0 +1,436 @@
+/*  *********************************************************************
+    *  BCM1280/BCM1400 Board Support Package
+    *
+    *  SCD Constants and Macros                     File: bcm1480_scd.h
+    *
+    *  This module contains constants and macros useful for
+    *  manipulating the System Control and Debug module.
+    *
+    *  BCM1400 specification level: 1X55_1X80-UM100-R (12/18/03)
+    *
+    *********************************************************************
+    *
+    *  Copyright 2000,2001,2002,2003
+    *  Broadcom Corporation. 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
+    ********************************************************************* */
+
+#ifndef _BCM1480_SCD_H
+#define _BCM1480_SCD_H
+
+#include "sb1250_defs.h"
+
+/*  *********************************************************************
+    *  Pull in the BCM1250's SCD since lots of stuff is the same.
+    ********************************************************************* */
+
+#include "sb1250_scd.h"
+
+/*  *********************************************************************
+    *  Some general notes:
+    *
+    *  This file is basically a "what's new" header file.  Since the
+    *  BCM1250 and the new BCM1480 (and derivatives) share many common
+    *  features, this file contains only what's new or changed from
+    *  the 1250.  (above, you can see that we include the 1250 symbols
+    *  to get the base functionality).
+    *
+    *  In software, be sure to use the correct symbols, particularly
+    *  for blocks that are different between the two chip families.
+    *  All BCM1480-specific symbols have _BCM1480_ in their names,
+    *  and all BCM1250-specific and "base" functions that are common in
+    *  both chips have no special names (this is for compatibility with
+    *  older include files).  Therefore, if you're working with the
+    *  SCD, which is very different on each chip, A_SCD_xxx implies
+    *  the BCM1250 version and A_BCM1480_SCD_xxx implies the BCM1480
+    *  version.
+    ********************************************************************* */
+
+/*  *********************************************************************
+    *  System control/debug registers
+    ********************************************************************* */
+
+/*
+ * System Identification and Revision Register (Table 12)
+ * Register: SCD_SYSTEM_REVISION
+ * This register is field compatible with the 1250.
+ */
+
+/*
+ * New part definitions
+ */
+
+#define K_SYS_PART_BCM1480          0x1406
+#define K_SYS_PART_BCM1280          0x1206
+#define K_SYS_PART_BCM1455          0x1407
+#define K_SYS_PART_BCM1255          0x1257
+
+/*
+ * Manufacturing Information Register (Table 14)
+ * Register: SCD_SYSTEM_MANUF
+ */
+
+/*
+ * System Configuration Register (Table 15)
+ * Register: SCD_SYSTEM_CFG
+ * Entire register is different from 1250, all new constants below
+ */
+
+#define M_BCM1480_SYS_RESERVED0             _SB_MAKEMASK1(0)
+#define M_BCM1480_SYS_HT_MINRSTCNT          _SB_MAKEMASK1(1)
+#define M_BCM1480_SYS_RESERVED2             _SB_MAKEMASK1(2)
+#define M_BCM1480_SYS_RESERVED3             _SB_MAKEMASK1(3)
+#define M_BCM1480_SYS_RESERVED4             _SB_MAKEMASK1(4)
+#define M_BCM1480_SYS_IOB_DIV               _SB_MAKEMASK1(5)
+
+#define S_BCM1480_SYS_PLL_DIV               _SB_MAKE64(6)
+#define M_BCM1480_SYS_PLL_DIV               _SB_MAKEMASK(5,S_BCM1480_SYS_PLL_DIV)
+#define V_BCM1480_SYS_PLL_DIV(x)            _SB_MAKEVALUE(x,S_BCM1480_SYS_PLL_DIV)
+#define G_BCM1480_SYS_PLL_DIV(x)            _SB_GETVALUE(x,S_BCM1480_SYS_PLL_DIV,M_BCM1480_SYS_PLL_DIV)
+
+#define S_BCM1480_SYS_SW_DIV                _SB_MAKE64(11)
+#define M_BCM1480_SYS_SW_DIV                _SB_MAKEMASK(5,S_BCM1480_SYS_SW_DIV)
+#define V_BCM1480_SYS_SW_DIV(x)             _SB_MAKEVALUE(x,S_BCM1480_SYS_SW_DIV)
+#define G_BCM1480_SYS_SW_DIV(x)             _SB_GETVALUE(x,S_BCM1480_SYS_SW_DIV,M_BCM1480_SYS_SW_DIV)
+
+#define M_BCM1480_SYS_PCMCIA_ENABLE         _SB_MAKEMASK1(16)
+#define M_BCM1480_SYS_DUART1_ENABLE         _SB_MAKEMASK1(17)
+
+#define S_BCM1480_SYS_BOOT_MODE             _SB_MAKE64(18)
+#define M_BCM1480_SYS_BOOT_MODE             _SB_MAKEMASK(2,S_BCM1480_SYS_BOOT_MODE)
+#define V_BCM1480_SYS_BOOT_MODE(x)          _SB_MAKEVALUE(x,S_BCM1480_SYS_BOOT_MODE)
+#define G_BCM1480_SYS_BOOT_MODE(x)          _SB_GETVALUE(x,S_BCM1480_SYS_BOOT_MODE,M_BCM1480_SYS_BOOT_MODE)
+#define K_BCM1480_SYS_BOOT_MODE_ROM32       0
+#define K_BCM1480_SYS_BOOT_MODE_ROM8        1
+#define K_BCM1480_SYS_BOOT_MODE_SMBUS_SMALL 2
+#define K_BCM1480_SYS_BOOT_MODE_SMBUS_BIG   3
+#define M_BCM1480_SYS_BOOT_MODE_SMBUS       _SB_MAKEMASK1(19)
+
+#define M_BCM1480_SYS_PCI_HOST              _SB_MAKEMASK1(20)
+#define M_BCM1480_SYS_PCI_ARBITER           _SB_MAKEMASK1(21)
+#define M_BCM1480_SYS_BIG_ENDIAN            _SB_MAKEMASK1(22)
+#define M_BCM1480_SYS_GENCLK_EN             _SB_MAKEMASK1(23)
+#define M_BCM1480_SYS_GEN_PARITY_EN         _SB_MAKEMASK1(24)
+#define M_BCM1480_SYS_RESERVED25            _SB_MAKEMASK1(25)
+
+#define S_BCM1480_SYS_CONFIG                26
+#define M_BCM1480_SYS_CONFIG                _SB_MAKEMASK(6,S_BCM1480_SYS_CONFIG)
+#define V_BCM1480_SYS_CONFIG(x)             _SB_MAKEVALUE(x,S_BCM1480_SYS_CONFIG)
+#define G_BCM1480_SYS_CONFIG(x)             _SB_GETVALUE(x,S_BCM1480_SYS_CONFIG,M_BCM1480_SYS_CONFIG)
+
+#define M_BCM1480_SYS_RESERVED32            _SB_MAKEMASK(32,15)
+
+#define S_BCM1480_SYS_NODEID                47
+#define M_BCM1480_SYS_NODEID                _SB_MAKEMASK(4,S_BCM1480_SYS_NODEID)
+#define V_BCM1480_SYS_NODEID(x)             _SB_MAKEVALUE(x,S_BCM1480_SYS_NODEID)
+#define G_BCM1480_SYS_NODEID(x)             _SB_GETVALUE(x,S_BCM1480_SYS_NODEID,M_BCM1480_SYS_NODEID)
+
+#define M_BCM1480_SYS_CCNUMA_EN             _SB_MAKEMASK1(51)
+#define M_BCM1480_SYS_CPU_RESET_0           _SB_MAKEMASK1(52)
+#define M_BCM1480_SYS_CPU_RESET_1           _SB_MAKEMASK1(53)
+#define M_BCM1480_SYS_CPU_RESET_2           _SB_MAKEMASK1(54)
+#define M_BCM1480_SYS_CPU_RESET_3           _SB_MAKEMASK1(55)
+#define S_BCM1480_SYS_DISABLECPU0           56
+#define M_BCM1480_SYS_DISABLECPU0           _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU0)
+#define S_BCM1480_SYS_DISABLECPU1           57
+#define M_BCM1480_SYS_DISABLECPU1           _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU1)
+#define S_BCM1480_SYS_DISABLECPU2           58
+#define M_BCM1480_SYS_DISABLECPU2           _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU2)
+#define S_BCM1480_SYS_DISABLECPU3           59
+#define M_BCM1480_SYS_DISABLECPU3           _SB_MAKEMASK1(S_BCM1480_SYS_DISABLECPU3)
+
+#define M_BCM1480_SYS_SB_SOFTRES            _SB_MAKEMASK1(60)
+#define M_BCM1480_SYS_EXT_RESET             _SB_MAKEMASK1(61)
+#define M_BCM1480_SYS_SYSTEM_RESET          _SB_MAKEMASK1(62)
+#define M_BCM1480_SYS_SW_FLAG               _SB_MAKEMASK1(63)
+
+/*
+ * Scratch Register (Table 16)
+ * Register: SCD_SYSTEM_SCRATCH
+ * Same as BCM1250
+ */
+
+
+/*
+ * Mailbox Registers (Table 17)
+ * Registers: SCD_MBOX_{0,1}_CPU_x
+ * Same as BCM1250
+ */
+
+
+/*
+ * See bcm1480_int.h for interrupt mapper registers.
+ */
+
+
+/*
+ * Watchdog Timer Initial Count Registers (Table 23)
+ * Registers: SCD_WDOG_INIT_CNT_x
+ *
+ * The watchdogs are almost the same as the 1250, except
+ * the configuration register has more bits to control the
+ * other CPUs.
+ */
+
+
+/*
+ * Watchdog Timer Configuration Registers (Table 25)
+ * Registers: SCD_WDOG_CFG_x
+ */
+
+#define M_BCM1480_SCD_WDOG_ENABLE           _SB_MAKEMASK1(0)
+
+#define S_BCM1480_SCD_WDOG_RESET_TYPE       2
+#define M_BCM1480_SCD_WDOG_RESET_TYPE       _SB_MAKEMASK(5,S_BCM1480_SCD_WDOG_RESET_TYPE)
+#define V_BCM1480_SCD_WDOG_RESET_TYPE(x)    _SB_MAKEVALUE(x,S_BCM1480_SCD_WDOG_RESET_TYPE)
+#define G_BCM1480_SCD_WDOG_RESET_TYPE(x)    _SB_GETVALUE(x,S_BCM1480_SCD_WDOG_RESET_TYPE,M_BCM1480_SCD_WDOG_RESET_TYPE)
+
+#define K_BCM1480_SCD_WDOG_RESET_FULL       0	/* actually, (x & 1) == 0  */
+#define K_BCM1480_SCD_WDOG_RESET_SOFT       1
+#define K_BCM1480_SCD_WDOG_RESET_CPU0       3
+#define K_BCM1480_SCD_WDOG_RESET_CPU1       5
+#define K_BCM1480_SCD_WDOG_RESET_CPU2       9
+#define K_BCM1480_SCD_WDOG_RESET_CPU3       17
+#define K_BCM1480_SCD_WDOG_RESET_ALL_CPUS   31
+
+
+#define M_BCM1480_SCD_WDOG_HAS_RESET        _SB_MAKEMASK1(8)
+
+/*
+ * General Timer Initial Count Registers (Table 26)
+ * Registers: SCD_TIMER_INIT_x
+ *
+ * The timer registers are the same as the BCM1250
+ */
+
+
+/*
+ * ZBbus Count Register (Table 29)
+ * Register: ZBBUS_CYCLE_COUNT
+ *
+ * Same as BCM1250
+ */
+
+/*
+ * ZBbus Compare Registers (Table 30)
+ * Registers: ZBBUS_CYCLE_CPx
+ *
+ * Same as BCM1250
+ */
+
+
+/*
+ * System Performance Counter Configuration Register (Table 31)
+ * Register: PERF_CNT_CFG_0
+ *
+ * Since the clear/enable bits are moved compared to the
+ * 1250 and there are more fields, this register will be BCM1480 specific.
+ */
+
+#define S_BCM1480_SPC_CFG_SRC0              0
+#define M_BCM1480_SPC_CFG_SRC0              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC0)
+#define V_BCM1480_SPC_CFG_SRC0(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC0)
+#define G_BCM1480_SPC_CFG_SRC0(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC0,M_BCM1480_SPC_CFG_SRC0)
+
+#define S_BCM1480_SPC_CFG_SRC1              8
+#define M_BCM1480_SPC_CFG_SRC1              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC1)
+#define V_BCM1480_SPC_CFG_SRC1(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC1)
+#define G_BCM1480_SPC_CFG_SRC1(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC1,M_BCM1480_SPC_CFG_SRC1)
+
+#define S_BCM1480_SPC_CFG_SRC2              16
+#define M_BCM1480_SPC_CFG_SRC2              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC2)
+#define V_BCM1480_SPC_CFG_SRC2(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC2)
+#define G_BCM1480_SPC_CFG_SRC2(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC2,M_BCM1480_SPC_CFG_SRC2)
+
+#define S_BCM1480_SPC_CFG_SRC3              24
+#define M_BCM1480_SPC_CFG_SRC3              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC3)
+#define V_BCM1480_SPC_CFG_SRC3(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC3)
+#define G_BCM1480_SPC_CFG_SRC3(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC3,M_BCM1480_SPC_CFG_SRC3)
+
+#define S_BCM1480_SPC_CFG_SRC4              32
+#define M_BCM1480_SPC_CFG_SRC4              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC4)
+#define V_BCM1480_SPC_CFG_SRC4(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC4)
+#define G_BCM1480_SPC_CFG_SRC4(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC4,M_BCM1480_SPC_CFG_SRC4)
+
+#define S_BCM1480_SPC_CFG_SRC5              40
+#define M_BCM1480_SPC_CFG_SRC5              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC5)
+#define V_BCM1480_SPC_CFG_SRC5(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC5)
+#define G_BCM1480_SPC_CFG_SRC5(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC5,M_BCM1480_SPC_CFG_SRC5)
+
+#define S_BCM1480_SPC_CFG_SRC6              48
+#define M_BCM1480_SPC_CFG_SRC6              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC6)
+#define V_BCM1480_SPC_CFG_SRC6(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC6)
+#define G_BCM1480_SPC_CFG_SRC6(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC6,M_BCM1480_SPC_CFG_SRC6)
+
+#define S_BCM1480_SPC_CFG_SRC7              56
+#define M_BCM1480_SPC_CFG_SRC7              _SB_MAKEMASK(8,S_BCM1480_SPC_CFG_SRC7)
+#define V_BCM1480_SPC_CFG_SRC7(x)           _SB_MAKEVALUE(x,S_BCM1480_SPC_CFG_SRC7)
+#define G_BCM1480_SPC_CFG_SRC7(x)           _SB_GETVALUE(x,S_BCM1480_SPC_CFG_SRC7,M_BCM1480_SPC_CFG_SRC7)
+
+/*
+ * System Performance Counter Control Register (Table 32)
+ * Register: PERF_CNT_CFG_1
+ * BCM1480 specific
+ */
+
+#define M_BCM1480_SPC_CFG_CLEAR             _SB_MAKEMASK1(0)
+#define M_BCM1480_SPC_CFG_ENABLE            _SB_MAKEMASK1(1)
+
+/*
+ * System Performance Counters (Table 33)
+ * Registers: PERF_CNT_x
+ */
+
+#define S_BCM1480_SPC_CNT_COUNT             0
+#define M_BCM1480_SPC_CNT_COUNT             _SB_MAKEMASK(40,S_BCM1480_SPC_CNT_COUNT)
+#define V_BCM1480_SPC_CNT_COUNT(x)          _SB_MAKEVALUE(x,S_BCM1480_SPC_CNT_COUNT)
+#define G_BCM1480_SPC_CNT_COUNT(x)          _SB_GETVALUE(x,S_BCM1480_SPC_CNT_COUNT,M_BCM1480_SPC_CNT_COUNT)
+
+#define M_BCM1480_SPC_CNT_OFLOW             _SB_MAKEMASK1(40)
+
+
+/*
+ * Bus Watcher Error Status Register (Tables 36, 37)
+ * Registers: BUS_ERR_STATUS, BUS_ERR_STATUS_DEBUG
+ * Same as BCM1250.
+ */
+
+/*
+ * Bus Watcher Error Data Registers (Table 38)
+ * Registers: BUS_ERR_DATA_x
+ * Same as BCM1250.
+ */
+
+/*
+ * Bus Watcher L2 ECC Counter Register (Table 39)
+ * Register: BUS_L2_ERRORS
+ * Same as BCM1250.
+ */
+
+
+/*
+ * Bus Watcher Memory and I/O Error Counter Register (Table 40)
+ * Register: BUS_MEM_IO_ERRORS
+ * Same as BCM1250.
+ */
+
+
+/*
+ * Address Trap Registers
+ *
+ * Register layout same as BCM1250, almost.  The bus agents
+ * are different, and the address trap configuration bits are
+ * slightly different.
+ */
+
+#define M_BCM1480_ATRAP_INDEX		  _SB_MAKEMASK(4,0)
+#define M_BCM1480_ATRAP_ADDRESS		  _SB_MAKEMASK(40,0)
+
+#define S_BCM1480_ATRAP_CFG_CNT            0
+#define M_BCM1480_ATRAP_CFG_CNT            _SB_MAKEMASK(3,S_BCM1480_ATRAP_CFG_CNT)
+#define V_BCM1480_ATRAP_CFG_CNT(x)         _SB_MAKEVALUE(x,S_BCM1480_ATRAP_CFG_CNT)
+#define G_BCM1480_ATRAP_CFG_CNT(x)         _SB_GETVALUE(x,S_BCM1480_ATRAP_CFG_CNT,M_BCM1480_ATRAP_CFG_CNT)
+
+#define M_BCM1480_ATRAP_CFG_WRITE	   _SB_MAKEMASK1(3)
+#define M_BCM1480_ATRAP_CFG_ALL	  	   _SB_MAKEMASK1(4)
+#define M_BCM1480_ATRAP_CFG_INV	   	   _SB_MAKEMASK1(5)
+#define M_BCM1480_ATRAP_CFG_USESRC	   _SB_MAKEMASK1(6)
+#define M_BCM1480_ATRAP_CFG_SRCINV	   _SB_MAKEMASK1(7)
+
+#define S_BCM1480_ATRAP_CFG_AGENTID     8
+#define M_BCM1480_ATRAP_CFG_AGENTID     _SB_MAKEMASK(4,S_BCM1480_ATRAP_CFG_AGENTID)
+#define V_BCM1480_ATRAP_CFG_AGENTID(x)  _SB_MAKEVALUE(x,S_BCM1480_ATRAP_CFG_AGENTID)
+#define G_BCM1480_ATRAP_CFG_AGENTID(x)  _SB_GETVALUE(x,S_BCM1480_ATRAP_CFG_AGENTID,M_BCM1480_ATRAP_CFG_AGENTID)
+
+
+#define K_BCM1480_BUS_AGENT_CPU0            0
+#define K_BCM1480_BUS_AGENT_CPU1            1
+#define K_BCM1480_BUS_AGENT_NC              2
+#define K_BCM1480_BUS_AGENT_IOB             3
+#define K_BCM1480_BUS_AGENT_SCD             4
+#define K_BCM1480_BUS_AGENT_L2C             6
+#define K_BCM1480_BUS_AGENT_MC              7
+#define K_BCM1480_BUS_AGENT_CPU2            8
+#define K_BCM1480_BUS_AGENT_CPU3            9
+#define K_BCM1480_BUS_AGENT_PM              10
+
+#define S_BCM1480_ATRAP_CFG_CATTR           12
+#define M_BCM1480_ATRAP_CFG_CATTR           _SB_MAKEMASK(2,S_BCM1480_ATRAP_CFG_CATTR)
+#define V_BCM1480_ATRAP_CFG_CATTR(x)        _SB_MAKEVALUE(x,S_BCM1480_ATRAP_CFG_CATTR)
+#define G_BCM1480_ATRAP_CFG_CATTR(x)        _SB_GETVALUE(x,S_BCM1480_ATRAP_CFG_CATTR,M_BCM1480_ATRAP_CFG_CATTR)
+
+#define K_BCM1480_ATRAP_CFG_CATTR_IGNORE    0
+#define K_BCM1480_ATRAP_CFG_CATTR_UNC       1
+#define K_BCM1480_ATRAP_CFG_CATTR_NONCOH    2
+#define K_BCM1480_ATRAP_CFG_CATTR_COHERENT  3
+
+#define M_BCM1480_ATRAP_CFG_CATTRINV        _SB_MAKEMASK1(14)
+
+
+/*
+ * Trace Event Registers (Table 47)
+ * Same as BCM1250.
+ */
+
+/*
+ * Trace Sequence Control Registers (Table 48)
+ * Registers: TRACE_SEQUENCE_x
+ *
+ * Same as BCM1250 except for two new fields.
+ */
+
+
+#define M_BCM1480_SCD_TRSEQ_TID_MATCH_EN    _SB_MAKEMASK1(25)
+
+#define S_BCM1480_SCD_TRSEQ_SWFUNC          26
+#define M_BCM1480_SCD_TRSEQ_SWFUNC          _SB_MAKEMASK(2,S_BCM1480_SCD_TRSEQ_SWFUNC)
+#define V_BCM1480_SCD_TRSEQ_SWFUNC(x)       _SB_MAKEVALUE(x,S_BCM1480_SCD_TRSEQ_SWFUNC)
+#define G_BCM1480_SCD_TRSEQ_SWFUNC(x)       _SB_GETVALUE(x,S_BCM1480_SCD_TRSEQ_SWFUNC,M_BCM1480_SCD_TRSEQ_SWFUNC)
+
+/*
+ * Trace Control Register (Table 49)
+ * Register: TRACE_CFG
+ *
+ * Bits 0..8 are the same as the BCM1250, rest are different.
+ * Entire register is redefined below.
+ */
+
+#define M_BCM1480_SCD_TRACE_CFG_RESET       _SB_MAKEMASK1(0)
+#define M_BCM1480_SCD_TRACE_CFG_START_READ  _SB_MAKEMASK1(1)
+#define M_BCM1480_SCD_TRACE_CFG_START       _SB_MAKEMASK1(2)
+#define M_BCM1480_SCD_TRACE_CFG_STOP        _SB_MAKEMASK1(3)
+#define M_BCM1480_SCD_TRACE_CFG_FREEZE      _SB_MAKEMASK1(4)
+#define M_BCM1480_SCD_TRACE_CFG_FREEZE_FULL _SB_MAKEMASK1(5)
+#define M_BCM1480_SCD_TRACE_CFG_DEBUG_FULL  _SB_MAKEMASK1(6)
+#define M_BCM1480_SCD_TRACE_CFG_FULL        _SB_MAKEMASK1(7)
+#define M_BCM1480_SCD_TRACE_CFG_FORCE_CNT   _SB_MAKEMASK1(8)
+
+#define S_BCM1480_SCD_TRACE_CFG_MODE        16
+#define M_BCM1480_SCD_TRACE_CFG_MODE        _SB_MAKEMASK(2,S_BCM1480_SCD_TRACE_CFG_MODE)
+#define V_BCM1480_SCD_TRACE_CFG_MODE(x)     _SB_MAKEVALUE(x,S_BCM1480_SCD_TRACE_CFG_MODE)
+#define G_BCM1480_SCD_TRACE_CFG_MODE(x)     _SB_GETVALUE(x,S_BCM1480_SCD_TRACE_CFG_MODE,M_BCM1480_SCD_TRACE_CFG_MODE)
+
+#define K_BCM1480_SCD_TRACE_CFG_MODE_BLOCKERS	0
+#define K_BCM1480_SCD_TRACE_CFG_MODE_BYTEEN_INT	1
+#define K_BCM1480_SCD_TRACE_CFG_MODE_FLOW_ID	2
+
+#define S_BCM1480_SCD_TRACE_CFG_CUR_ADDR    24
+#define M_BCM1480_SCD_TRACE_CFG_CUR_ADDR    _SB_MAKEMASK(8,S_BCM1480_SCD_TRACE_CFG_CUR_ADDR)
+#define V_BCM1480_SCD_TRACE_CFG_CUR_ADDR(x) _SB_MAKEVALUE(x,S_BCM1480_SCD_TRACE_CFG_CUR_ADDR)
+#define G_BCM1480_SCD_TRACE_CFG_CUR_ADDR(x) _SB_GETVALUE(x,S_BCM1480_SCD_TRACE_CFG_CUR_ADDR,M_BCM1480_SCD_TRACE_CFG_CUR_ADDR)
+
+#endif /* _BCM1480_SCD_H */
diff --git a/include/asm-mips/sibyte/bigsur.h b/include/asm-mips/sibyte/bigsur.h
new file mode 100644
index 0000000..ebefe79
--- /dev/null
+++ b/include/asm-mips/sibyte/bigsur.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#ifndef __ASM_SIBYTE_BIGSUR_H
+#define __ASM_SIBYTE_BIGSUR_H
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+#ifdef CONFIG_SIBYTE_BIGSUR
+#define SIBYTE_BOARD_NAME "BCM91x80A/B (BigSur)"
+#define SIBYTE_HAVE_PCMCIA 1
+#define SIBYTE_HAVE_IDE    1
+#endif
+
+/* Generic bus chip selects */
+#define LEDS_CS         3
+#define LEDS_PHYS       0x100a0000
+
+#ifdef SIBYTE_HAVE_IDE
+#define IDE_CS          4
+#define IDE_PHYS        0x100b0000
+#define K_GPIO_GB_IDE   4
+#define K_INT_GB_IDE    (K_INT_GPIO_0 + K_GPIO_GB_IDE)
+#endif
+
+#ifdef SIBYTE_HAVE_PCMCIA
+#define PCMCIA_CS       6
+#define PCMCIA_PHYS     0x11000000
+#define K_GPIO_PC_READY 9
+#define K_INT_PC_READY  (K_INT_GPIO_0 + K_GPIO_PC_READY)
+#endif
+
+#endif /* __ASM_SIBYTE_BIGSUR_H */
+
diff --git a/include/asm-mips/sibyte/board.h b/include/asm-mips/sibyte/board.h
index d7b11b6..900edcb 100644
--- a/include/asm-mips/sibyte/board.h
+++ b/include/asm-mips/sibyte/board.h
@@ -21,8 +21,6 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_SIBYTE_BOARD
-
 #if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM) || \
     defined(CONFIG_SIBYTE_CRHONE) || defined(CONFIG_SIBYTE_CRHINE) || \
     defined(CONFIG_SIBYTE_LITTLESUR)
@@ -37,6 +35,10 @@
 #include <asm/sibyte/carmel.h>
 #endif
 
+#ifdef CONFIG_SIBYTE_BIGSUR
+#include <asm/sibyte/bigsur.h>
+#endif
+
 #ifdef __ASSEMBLY__
 
 #ifdef LEDS_PHYS
@@ -54,16 +56,6 @@
 #define setleds(t0,t1,c0,c1,c2,c3)
 #endif /* LEDS_PHYS */
 
-#else
-
-#ifdef LEDS_PHYS
-extern void setleds(char *str);
-#else
-#define setleds(s) do { } while (0)
-#endif /* LEDS_PHYS */
-
 #endif /* __ASSEMBLY__ */
 
-#endif /* CONFIG_SIBYTE_BOARD */
-
 #endif /* _SIBYTE_BOARD_H */
diff --git a/include/asm-mips/sibyte/sb1250.h b/include/asm-mips/sibyte/sb1250.h
index d62da4e..a474c29 100644
--- a/include/asm-mips/sibyte/sb1250.h
+++ b/include/asm-mips/sibyte/sb1250.h
@@ -27,6 +27,9 @@
 
 #define SB1250_NR_IRQS 64
 
+#define BCM1480_NR_IRQS                 128
+#define BCM1480_NR_IRQS_HALF            64
+
 #define SB1250_DUART_MINOR_BASE		64
 
 #ifndef __ASSEMBLY__
@@ -35,6 +38,7 @@
 
 /* For revision/pass information */
 #include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/bcm1480_scd.h>
 extern unsigned int sb1_pass;
 extern unsigned int soc_pass;
 extern unsigned int soc_type;
@@ -46,6 +50,13 @@
 extern void sb1250_mask_irq(int cpu, int irq);
 extern void sb1250_unmask_irq(int cpu, int irq);
 extern void sb1250_smp_finish(void);
+
+extern void bcm1480_time_init(void);
+extern unsigned long bcm1480_gettimeoffset(void);
+extern void bcm1480_mask_irq(int cpu, int irq);
+extern void bcm1480_unmask_irq(int cpu, int irq);
+extern void bcm1480_smp_finish(void);
+
 extern void prom_printf(char *fmt, ...);
 
 #define AT_spin \
@@ -58,6 +69,6 @@
 
 #endif
 
-#define IOADDR(a) (IO_BASE + (a))
+#define IOADDR(a) ((volatile void __iomem *)(IO_BASE + (a)))
 
 #endif
diff --git a/include/asm-mips/sibyte/sb1250_defs.h b/include/asm-mips/sibyte/sb1250_defs.h
index 40ef97c..335dbaf 100644
--- a/include/asm-mips/sibyte/sb1250_defs.h
+++ b/include/asm-mips/sibyte/sb1250_defs.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -97,13 +95,17 @@
     *  ordering, so be careful when adding support for new minor revs.
     ********************************************************************* */
 
-#define	SIBYTE_HDR_FMASK_1250_ALL		0x00000ff
-#define	SIBYTE_HDR_FMASK_1250_PASS1		0x0000001
-#define	SIBYTE_HDR_FMASK_1250_PASS2		0x0000002
-#define	SIBYTE_HDR_FMASK_1250_PASS3		0x0000004
+#define	SIBYTE_HDR_FMASK_1250_ALL		0x000000ff
+#define	SIBYTE_HDR_FMASK_1250_PASS1		0x00000001
+#define	SIBYTE_HDR_FMASK_1250_PASS2		0x00000002
+#define	SIBYTE_HDR_FMASK_1250_PASS3		0x00000004
 
-#define	SIBYTE_HDR_FMASK_112x_ALL		0x0000f00
-#define	SIBYTE_HDR_FMASK_112x_PASS1		0x0000100
+#define	SIBYTE_HDR_FMASK_112x_ALL		0x00000f00
+#define	SIBYTE_HDR_FMASK_112x_PASS1		0x00000100
+
+#define SIBYTE_HDR_FMASK_1480_ALL		0x0000f000
+#define SIBYTE_HDR_FMASK_1480_PASS1		0x00001000
+#define SIBYTE_HDR_FMASK_1480_PASS2		0x00002000
 
 /* Bit mask for chip/revision.  (use _ALL for all revisions of a chip).  */
 #define	SIBYTE_HDR_FMASK(chip, pass)					\
@@ -111,8 +113,17 @@
 #define	SIBYTE_HDR_FMASK_ALLREVS(chip)					\
     (SIBYTE_HDR_FMASK_ ## chip ## _ALL)
 
+/* Default constant value for all chips, all revisions */
 #define	SIBYTE_HDR_FMASK_ALL						\
+    (SIBYTE_HDR_FMASK_1250_ALL | SIBYTE_HDR_FMASK_112x_ALL		\
+     | SIBYTE_HDR_FMASK_1480_ALL)
+
+/* This one is used for the "original" BCM1250/BCM112x chips.  We use this
+   to weed out constants and macros that do not exist on later chips like
+   the BCM1480  */
+#define SIBYTE_HDR_FMASK_1250_112x_ALL					\
     (SIBYTE_HDR_FMASK_1250_ALL | SIBYTE_HDR_FMASK_112x_ALL)
+#define SIBYTE_HDR_FMASK_1250_112x SIBYTE_HDR_FMASK_1250_112x_ALL
 
 #ifndef SIBYTE_HDR_FEATURES
 #define	SIBYTE_HDR_FEATURES			SIBYTE_HDR_FMASK_ALL
@@ -133,6 +144,12 @@
 #define SIBYTE_HDR_FEATURE_CHIP(chip)					\
     (!! (SIBYTE_HDR_FMASK_ALLREVS(chip) & SIBYTE_HDR_FEATURES))
 
+/* True for all versions of the BCM1250 and BCM1125, but not true for
+   anything else */
+#define SIBYTE_HDR_FEATURE_1250_112x \
+      (SIBYTE_HDR_FEATURE_CHIP(1250) || SIBYTE_HDR_FEATURE_CHIP(112x))
+/*    (!!  (SIBYTE_HDR_FEATURES & SIBYHTE_HDR_FMASK_1250_112x)) */
+
 /* True if header features enabled for that rev or later, inclusive.  */
 #define SIBYTE_HDR_FEATURE(chip, pass)					\
     (!! ((SIBYTE_HDR_FMASK(chip, pass)					\
diff --git a/include/asm-mips/sibyte/sb1250_dma.h b/include/asm-mips/sibyte/sb1250_dma.h
index 3cdb48f..e6145f5 100644
--- a/include/asm-mips/sibyte/sb1250_dma.h
+++ b/include/asm-mips/sibyte/sb1250_dma.h
@@ -7,9 +7,8 @@
     *  programming the SB1250's DMA controllers, both the data mover
     *  and the Ethernet DMA.
     *
-    *  SB1250 specification level:  User's manual 1/02/02
-    *
-    *  Author:  Mitch Lichtenberg
+    *  SB1250 specification level:  User's manual 10/21/02
+    *  BCM1280 specification level: User's manual 11/24/03
     *
     *********************************************************************
     *
@@ -58,17 +57,17 @@
 #define M_DMA_RESERVED1             _SB_MAKEMASK1(2)
 
 #define S_DMA_DESC_TYPE		    _SB_MAKE64(1)
-#define M_DMA_DESC_TYPE		    _SB_MAKE64(2,S_DMA_DESC_TYPE)
+#define M_DMA_DESC_TYPE		    _SB_MAKEMASK(2,S_DMA_DESC_TYPE)
 #define V_DMA_DESC_TYPE(x)          _SB_MAKEVALUE(x,S_DMA_DESC_TYPE)
 #define G_DMA_DESC_TYPE(x)          _SB_GETVALUE(x,S_DMA_DESC_TYPE,M_DMA_DESC_TYPE)
 
 #define K_DMA_DESC_TYPE_RING_AL		0
 #define K_DMA_DESC_TYPE_CHAIN_AL	1
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define K_DMA_DESC_TYPE_RING_UAL_WI	2
 #define K_DMA_DESC_TYPE_RING_UAL_RMW	3
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define M_DMA_EOP_INT_EN            _SB_MAKEMASK1(3)
 #define M_DMA_HWM_INT_EN            _SB_MAKEMASK1(4)
@@ -111,11 +110,11 @@
 #define M_DMA_NO_DSCR_UPDT          _SB_MAKEMASK1(4)
 #define M_DMA_L2CA		    _SB_MAKEMASK1(5)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_DMA_RX_XTRA_STATUS	    _SB_MAKEMASK1(6)
 #define M_DMA_TX_CPU_PAUSE	    _SB_MAKEMASK1(6)
 #define M_DMA_TX_FC_PAUSE_EN	    _SB_MAKEMASK1(7)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define M_DMA_MBZ1                  _SB_MAKEMASK(6,15)
 
@@ -165,14 +164,14 @@
 #define S_DMA_CURDSCR_COUNT         _SB_MAKE64(40)
 #define M_DMA_CURDSCR_COUNT         _SB_MAKEMASK(16,S_DMA_CURDSCR_COUNT)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_DMA_TX_CH_PAUSE_ON	    _SB_MAKEMASK1(56)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 /*
  * Receive Packet Drop Registers
  */
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_DMA_OODLOST_RX           _SB_MAKE64(0)
 #define M_DMA_OODLOST_RX           _SB_MAKEMASK(16,S_DMA_OODLOST_RX)
 #define G_DMA_OODLOST_RX(x)        _SB_GETVALUE(x,S_DMA_OODLOST_RX,M_DMA_OODLOST_RX)
@@ -180,7 +179,7 @@
 #define S_DMA_EOP_COUNT_RX         _SB_MAKE64(16)
 #define M_DMA_EOP_COUNT_RX         _SB_MAKEMASK(8,S_DMA_EOP_COUNT_RX)
 #define G_DMA_EOP_COUNT_RX(x)      _SB_GETVALUE(x,S_DMA_EOP_COUNT_RX,M_DMA_EOP_COUNT_RX)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 /*  *********************************************************************
     *  DMA Descriptors
@@ -201,21 +200,21 @@
 
 #define M_DMA_DSCRA_A_ADDR_OFFSET   (M_DMA_DSCRA_OFFSET | M_DMA_DSCRA_A_ADDR)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_DMA_DSCRA_A_ADDR_UA        _SB_MAKE64(0)
 #define M_DMA_DSCRA_A_ADDR_UA        _SB_MAKEMASK(40,S_DMA_DSCRA_A_ADDR_UA)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define S_DMA_DSCRA_A_SIZE          _SB_MAKE64(40)
 #define M_DMA_DSCRA_A_SIZE          _SB_MAKEMASK(9,S_DMA_DSCRA_A_SIZE)
 #define V_DMA_DSCRA_A_SIZE(x)       _SB_MAKEVALUE(x,S_DMA_DSCRA_A_SIZE)
 #define G_DMA_DSCRA_A_SIZE(x)       _SB_GETVALUE(x,S_DMA_DSCRA_A_SIZE,M_DMA_DSCRA_A_SIZE)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_DMA_DSCRA_DSCR_CNT	    _SB_MAKE64(40)
 #define M_DMA_DSCRA_DSCR_CNT	    _SB_MAKEMASK(8,S_DMA_DSCRA_DSCR_CNT)
 #define G_DMA_DSCRA_DSCR_CNT(x)	    _SB_GETVALUE(x,S_DMA_DSCRA_DSCR_CNT,M_DMA_DSCRA_DSCR_CNT)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define M_DMA_DSCRA_INTERRUPT       _SB_MAKEMASK1(49)
 #define M_DMA_DSCRA_OFFSETB	    _SB_MAKEMASK1(50)
@@ -235,12 +234,12 @@
 #define V_DMA_DSCRB_OPTIONS(x)      _SB_MAKEVALUE(x,S_DMA_DSCRB_OPTIONS)
 #define G_DMA_DSCRB_OPTIONS(x)      _SB_GETVALUE(x,S_DMA_DSCRB_OPTIONS,M_DMA_DSCRB_OPTIONS)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_DMA_DSCRB_A_SIZE        _SB_MAKE64(8)
 #define M_DMA_DSCRB_A_SIZE        _SB_MAKEMASK(14,S_DMA_DSCRB_A_SIZE)
 #define V_DMA_DSCRB_A_SIZE(x)     _SB_MAKEVALUE(x,S_DMA_DSCRB_A_SIZE)
 #define G_DMA_DSCRB_A_SIZE(x)     _SB_GETVALUE(x,S_DMA_DSCRB_A_SIZE,M_DMA_DSCRB_A_SIZE)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define R_DMA_DSCRB_ADDR            _SB_MAKE64(0x10)
 
@@ -255,12 +254,12 @@
 
 #define M_DMA_DSCRB_B_VALID         _SB_MAKEMASK1(49)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_DMA_DSCRB_PKT_SIZE_MSB    _SB_MAKE64(48)
 #define M_DMA_DSCRB_PKT_SIZE_MSB    _SB_MAKEMASK(2,S_DMA_DSCRB_PKT_SIZE_MSB)
 #define V_DMA_DSCRB_PKT_SIZE_MSB(x) _SB_MAKEVALUE(x,S_DMA_DSCRB_PKT_SIZE_MSB)
 #define G_DMA_DSCRB_PKT_SIZE_MSB(x) _SB_GETVALUE(x,S_DMA_DSCRB_PKT_SIZE_MSB,M_DMA_DSCRB_PKT_SIZE_MSB)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define S_DMA_DSCRB_PKT_SIZE        _SB_MAKE64(50)
 #define M_DMA_DSCRB_PKT_SIZE        _SB_MAKEMASK(14,S_DMA_DSCRB_PKT_SIZE)
@@ -282,15 +281,16 @@
 #define M_DMA_ETHRX_BADIP4CS        _SB_MAKEMASK1(51)
 #define M_DMA_ETHRX_DSCRERR	    _SB_MAKEMASK1(52)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
-/* Note: BADTCPCS is actually in DSCR_B options field */
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
+/* Note: This bit is in the DSCR_B options field */
 #define M_DMA_ETHRX_BADTCPCS	_SB_MAKEMASK1(0)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
+/* Note: These bits are in the DSCR_B options field */
 #define M_DMA_ETH_VLAN_FLAG	_SB_MAKEMASK1(1)
 #define M_DMA_ETH_CRC_FLAG	_SB_MAKEMASK1(2)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define S_DMA_ETHRX_RXCH            53
 #define M_DMA_ETHRX_RXCH            _SB_MAKEMASK(2,S_DMA_ETHRX_RXCH)
@@ -438,7 +438,7 @@
                                      M_DM_CUR_DSCR_DSCR_COUNT)
 
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 /*
  * Data Mover Channel Partial Result Registers
  * Register: DM_PARTIAL_0
@@ -459,10 +459,10 @@
                                        M_DM_PARTIAL_TCPCS_PARTIAL)
 
 #define M_DM_PARTIAL_ODD_BYTE         _SB_MAKEMASK1(48)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 /*
  * Data Mover CRC Definition Registers
  * Register: CRC_DEF_0
@@ -479,10 +479,10 @@
 #define V_CRC_DEF_CRC_POLY(r)         _SB_MAKEVALUE(r,S_CRC_DEF_CRC_POLY)
 #define G_CRC_DEF_CRC_POLY(r)         _SB_GETVALUE(r,S_CRC_DEF_CRC_POLY,\
                                        M_CRC_DEF_CRC_POLY)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 /*
  * Data Mover CRC/Checksum Definition Registers
  * Register: CTCP_DEF_0
@@ -511,7 +511,7 @@
 #define K_CTCP_DEF_CRC_WIDTH_1        2
 
 #define M_CTCP_DEF_CRC_BIT_ORDER      _SB_MAKEMASK1(50)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 
 /*
@@ -560,12 +560,12 @@
 #define M_DM_DSCRA_L2C_DEST         _SB_MAKEMASK1(50)
 #define M_DM_DSCRA_L2C_SRC          _SB_MAKEMASK1(51)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_DM_DSCRA_RD_BKOFF	    _SB_MAKEMASK1(52)
 #define M_DM_DSCRA_WR_BKOFF	    _SB_MAKEMASK1(53)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_DM_DSCRA_TCPCS_EN         _SB_MAKEMASK1(54)
 #define M_DM_DSCRA_TCPCS_RES        _SB_MAKEMASK1(55)
 #define M_DM_DSCRA_TCPCS_AP         _SB_MAKEMASK1(56)
@@ -574,7 +574,7 @@
 #define M_DM_DSCRA_CRC_AP           _SB_MAKEMASK1(59)
 #define M_DM_DSCRA_CRC_DFN          _SB_MAKEMASK1(60)
 #define M_DM_DSCRA_CRC_XBIT         _SB_MAKEMASK1(61)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define M_DM_DSCRA_RESERVED2        _SB_MAKEMASK(3,61)
 
diff --git a/include/asm-mips/sibyte/sb1250_genbus.h b/include/asm-mips/sibyte/sb1250_genbus.h
index f1f509f..1b5cbc5 100644
--- a/include/asm-mips/sibyte/sb1250_genbus.h
+++ b/include/asm-mips/sibyte/sb1250_genbus.h
@@ -6,9 +6,8 @@
     *  This module contains constants and macros useful for
     *  manipulating the SB1250's Generic Bus interface
     *
-    *  SB1250 specification level:  User's manual 1/02/02
-    *
-    *  Author:  Mitch Lichtenberg
+    *  SB1250 specification level:  User's manual 10/21/02
+    *  BCM1280 specification level: User's Manual 11/14/03
     *
     *********************************************************************
     *
@@ -51,19 +50,21 @@
 #define M_IO_WIDTH_SEL		_SB_MAKEMASK(2,S_IO_WIDTH_SEL)
 #define K_IO_WIDTH_SEL_1	0
 #define K_IO_WIDTH_SEL_2	1
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \
+    || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define K_IO_WIDTH_SEL_1L       2
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 #define K_IO_WIDTH_SEL_4	3
 #define V_IO_WIDTH_SEL(x)	_SB_MAKEVALUE(x,S_IO_WIDTH_SEL)
 #define G_IO_WIDTH_SEL(x)	_SB_GETVALUE(x,S_IO_WIDTH_SEL,M_IO_WIDTH_SEL)
 
 #define S_IO_PARITY_ENA		4
 #define M_IO_PARITY_ENA		_SB_MAKEMASK1(S_IO_PARITY_ENA)
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \
+    || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_IO_BURST_EN		5
 #define M_IO_BURST_EN		_SB_MAKEMASK1(S_IO_BURST_EN)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 #define S_IO_PARITY_ODD		6
 #define M_IO_PARITY_ODD		_SB_MAKEMASK1(S_IO_PARITY_ODD)
 #define S_IO_NONMUX		7
@@ -96,8 +97,11 @@
 
 #define S_IO_ADDRBASE		16	 /* # bits to shift addr for this reg */
 
+#define M_IO_BLK_CACHE		_SB_MAKEMASK1(15)
+
+
 /*
- * Generic Bus Region 0 Timing Registers (Table 11-7)
+ * Generic Bus Timing 0 Registers (Table 11-7)
  */
 
 #define S_IO_ALE_WIDTH		0
@@ -105,21 +109,23 @@
 #define V_IO_ALE_WIDTH(x)	_SB_MAKEVALUE(x,S_IO_ALE_WIDTH)
 #define G_IO_ALE_WIDTH(x)	_SB_GETVALUE(x,S_IO_ALE_WIDTH,M_IO_ALE_WIDTH)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \
+    || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_IO_EARLY_CS	        _SB_MAKEMASK1(3)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 #define S_IO_ALE_TO_CS		4
 #define M_IO_ALE_TO_CS		_SB_MAKEMASK(2,S_IO_ALE_TO_CS)
 #define V_IO_ALE_TO_CS(x)	_SB_MAKEVALUE(x,S_IO_ALE_TO_CS)
 #define G_IO_ALE_TO_CS(x)	_SB_GETVALUE(x,S_IO_ALE_TO_CS,M_IO_ALE_TO_CS)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \
+    || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_IO_BURST_WIDTH           _SB_MAKE64(6)
 #define M_IO_BURST_WIDTH           _SB_MAKEMASK(2,S_IO_BURST_WIDTH)
 #define V_IO_BURST_WIDTH(x)        _SB_MAKEVALUE(x,S_IO_BURST_WIDTH)
 #define G_IO_BURST_WIDTH(x)        _SB_GETVALUE(x,S_IO_BURST_WIDTH,M_IO_BURST_WIDTH)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 #define S_IO_CS_WIDTH		8
 #define M_IO_CS_WIDTH		_SB_MAKEMASK(5,S_IO_CS_WIDTH)
@@ -141,9 +147,10 @@
 #define V_IO_ALE_TO_WRITE(x)	_SB_MAKEVALUE(x,S_IO_ALE_TO_WRITE)
 #define G_IO_ALE_TO_WRITE(x)	_SB_GETVALUE(x,S_IO_ALE_TO_WRITE,M_IO_ALE_TO_WRITE)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) \
+    || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_IO_RDY_SYNC	        _SB_MAKEMASK1(3)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 #define S_IO_WRITE_WIDTH	4
 #define M_IO_WRITE_WIDTH	_SB_MAKEMASK(4,S_IO_WRITE_WIDTH)
@@ -183,9 +190,127 @@
 #define M_IO_TIMEOUT_INT	_SB_MAKEMASK1(10)
 #define M_IO_ILL_ADDR_INT	_SB_MAKEMASK1(11)
 #define M_IO_MULT_CS_INT	_SB_MAKEMASK1(12)
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_IO_COH_ERR	        _SB_MAKEMASK1(14)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
+
+
+/*
+ * Generic Bus Output Drive Control Register 0 (Table 14-18)
+ */
+
+#define S_IO_SLEW0		0
+#define M_IO_SLEW0		_SB_MAKEMASK(2,S_IO_SLEW0)
+#define V_IO_SLEW0(x)		_SB_MAKEVALUE(x,S_IO_SLEW0)
+#define G_IO_SLEW0(x)		_SB_GETVALUE(x,S_IO_SLEW0,M_IO_SLEW0)
+
+#define S_IO_DRV_A		2
+#define M_IO_DRV_A		_SB_MAKEMASK(2,S_IO_DRV_A)
+#define V_IO_DRV_A(x)		_SB_MAKEVALUE(x,S_IO_DRV_A)
+#define G_IO_DRV_A(x)		_SB_GETVALUE(x,S_IO_DRV_A,M_IO_DRV_A)
+
+#define S_IO_DRV_B		6
+#define M_IO_DRV_B		_SB_MAKEMASK(2,S_IO_DRV_B)
+#define V_IO_DRV_B(x)		_SB_MAKEVALUE(x,S_IO_DRV_B)
+#define G_IO_DRV_B(x)		_SB_GETVALUE(x,S_IO_DRV_B,M_IO_DRV_B)
+
+#define S_IO_DRV_C		10
+#define M_IO_DRV_C		_SB_MAKEMASK(2,S_IO_DRV_C)
+#define V_IO_DRV_C(x)		_SB_MAKEVALUE(x,S_IO_DRV_C)
+#define G_IO_DRV_C(x)		_SB_GETVALUE(x,S_IO_DRV_C,M_IO_DRV_C)
+
+#define S_IO_DRV_D		14
+#define M_IO_DRV_D		_SB_MAKEMASK(2,S_IO_DRV_D)
+#define V_IO_DRV_D(x)		_SB_MAKEVALUE(x,S_IO_DRV_D)
+#define G_IO_DRV_D(x)		_SB_GETVALUE(x,S_IO_DRV_D,M_IO_DRV_D)
+
+/*
+ * Generic Bus Output Drive Control Register 1 (Table 14-19)
+ */
+
+#define S_IO_DRV_E		2
+#define M_IO_DRV_E		_SB_MAKEMASK(2,S_IO_DRV_E)
+#define V_IO_DRV_E(x)		_SB_MAKEVALUE(x,S_IO_DRV_E)
+#define G_IO_DRV_E(x)		_SB_GETVALUE(x,S_IO_DRV_E,M_IO_DRV_E)
+
+#define S_IO_DRV_F		6
+#define M_IO_DRV_F		_SB_MAKEMASK(2,S_IO_DRV_F)
+#define V_IO_DRV_F(x)		_SB_MAKEVALUE(x,S_IO_DRV_F)
+#define G_IO_DRV_F(x)		_SB_GETVALUE(x,S_IO_DRV_F,M_IO_DRV_F)
+
+#define S_IO_SLEW1		8
+#define M_IO_SLEW1		_SB_MAKEMASK(2,S_IO_SLEW1)
+#define V_IO_SLEW1(x)		_SB_MAKEVALUE(x,S_IO_SLEW1)
+#define G_IO_SLEW1(x)		_SB_GETVALUE(x,S_IO_SLEW1,M_IO_SLEW1)
+
+#define S_IO_DRV_G		10
+#define M_IO_DRV_G		_SB_MAKEMASK(2,S_IO_DRV_G)
+#define V_IO_DRV_G(x)		_SB_MAKEVALUE(x,S_IO_DRV_G)
+#define G_IO_DRV_G(x)		_SB_GETVALUE(x,S_IO_DRV_G,M_IO_DRV_G)
+
+#define S_IO_SLEW2		12
+#define M_IO_SLEW2		_SB_MAKEMASK(2,S_IO_SLEW2)
+#define V_IO_SLEW2(x)		_SB_MAKEVALUE(x,S_IO_SLEW2)
+#define G_IO_SLEW2(x)		_SB_GETVALUE(x,S_IO_SLEW2,M_IO_SLEW2)
+
+#define S_IO_DRV_H		14
+#define M_IO_DRV_H		_SB_MAKEMASK(2,S_IO_DRV_H)
+#define V_IO_DRV_H(x)		_SB_MAKEVALUE(x,S_IO_DRV_H)
+#define G_IO_DRV_H(x)		_SB_GETVALUE(x,S_IO_DRV_H,M_IO_DRV_H)
+
+/*
+ * Generic Bus Output Drive Control Register 2 (Table 14-20)
+ */
+
+#define S_IO_DRV_J		2
+#define M_IO_DRV_J		_SB_MAKEMASK(2,S_IO_DRV_J)
+#define V_IO_DRV_J(x)		_SB_MAKEVALUE(x,S_IO_DRV_J)
+#define G_IO_DRV_J(x)		_SB_GETVALUE(x,S_IO_DRV_J,M_IO_DRV_J)
+
+#define S_IO_DRV_K		6
+#define M_IO_DRV_K		_SB_MAKEMASK(2,S_IO_DRV_K)
+#define V_IO_DRV_K(x)		_SB_MAKEVALUE(x,S_IO_DRV_K)
+#define G_IO_DRV_K(x)		_SB_GETVALUE(x,S_IO_DRV_K,M_IO_DRV_K)
+
+#define S_IO_DRV_L		10
+#define M_IO_DRV_L		_SB_MAKEMASK(2,S_IO_DRV_L)
+#define V_IO_DRV_L(x)		_SB_MAKEVALUE(x,S_IO_DRV_L)
+#define G_IO_DRV_L(x)		_SB_GETVALUE(x,S_IO_DRV_L,M_IO_DRV_L)
+
+#define S_IO_DRV_M		14
+#define M_IO_DRV_M		_SB_MAKEMASK(2,S_IO_DRV_M)
+#define V_IO_DRV_M(x)		_SB_MAKEVALUE(x,S_IO_DRV_M)
+#define G_IO_DRV_M(x)		_SB_GETVALUE(x,S_IO_DRV_M,M_IO_DRV_M)
+
+/*
+ * Generic Bus Output Drive Control Register 3 (Table 14-21)
+ */
+
+#define S_IO_SLEW3		0
+#define M_IO_SLEW3		_SB_MAKEMASK(2,S_IO_SLEW3)
+#define V_IO_SLEW3(x)		_SB_MAKEVALUE(x,S_IO_SLEW3)
+#define G_IO_SLEW3(x)		_SB_GETVALUE(x,S_IO_SLEW3,M_IO_SLEW3)
+
+#define S_IO_DRV_N		2
+#define M_IO_DRV_N		_SB_MAKEMASK(2,S_IO_DRV_N)
+#define V_IO_DRV_N(x)		_SB_MAKEVALUE(x,S_IO_DRV_N)
+#define G_IO_DRV_N(x)		_SB_GETVALUE(x,S_IO_DRV_N,M_IO_DRV_N)
+
+#define S_IO_DRV_P		6
+#define M_IO_DRV_P		_SB_MAKEMASK(2,S_IO_DRV_P)
+#define V_IO_DRV_P(x)		_SB_MAKEVALUE(x,S_IO_DRV_P)
+#define G_IO_DRV_P(x)		_SB_GETVALUE(x,S_IO_DRV_P,M_IO_DRV_P)
+
+#define S_IO_DRV_Q		10
+#define M_IO_DRV_Q		_SB_MAKEMASK(2,S_IO_DRV_Q)
+#define V_IO_DRV_Q(x)		_SB_MAKEVALUE(x,S_IO_DRV_Q)
+#define G_IO_DRV_Q(x)		_SB_GETVALUE(x,S_IO_DRV_Q,M_IO_DRV_Q)
+
+#define S_IO_DRV_R		14
+#define M_IO_DRV_R		_SB_MAKEMASK(2,S_IO_DRV_R)
+#define V_IO_DRV_R(x)		_SB_MAKEVALUE(x,S_IO_DRV_R)
+#define G_IO_DRV_R(x)		_SB_GETVALUE(x,S_IO_DRV_R,M_IO_DRV_R)
+
 
 /*
  * PCMCIA configuration register (Table 12-6)
@@ -202,6 +327,22 @@
 #define M_PCMCIA_CFG_RDYMASK	_SB_MAKEMASK1(8)
 #define M_PCMCIA_CFG_PWRCTL	_SB_MAKEMASK1(9)
 
+#if SIBYTE_HDR_FEATURE_CHIP(1480)
+#define S_PCMCIA_MODE		16
+#define M_PCMCIA_MODE		_SB_MAKEMASK(3,S_PCMCIA_MODE)
+#define V_PCMCIA_MODE(x)	_SB_MAKEVALUE(x,S_PCMCIA_MODE)
+#define G_PCMCIA_MODE(x)	_SB_GETVALUE(x,S_PCMCIA_MODE,M_PCMCIA_MODE)
+
+#define K_PCMCIA_MODE_PCMA_NOB	0	/* standard PCMCIA "A", no "B" */
+#define K_PCMCIA_MODE_IDEA_NOB	1	/* IDE "A", no "B" */
+#define K_PCMCIA_MODE_PCMIOA_NOB 2	/* PCMCIA with I/O "A", no "B" */
+#define K_PCMCIA_MODE_PCMA_PCMB 4	/* standard PCMCIA "A", standard PCMCIA "B" */
+#define K_PCMCIA_MODE_IDEA_PCMB 5	/* IDE "A", standard PCMCIA "B" */
+#define K_PCMCIA_MODE_PCMA_IDEB 6	/* standard PCMCIA "A", IDE "B" */
+#define K_PCMCIA_MODE_IDEA_IDEB 7	/* IDE "A", IDE "B" */
+#endif
+
+
 /*
  * PCMCIA status register (Table 12-7)
  */
@@ -272,5 +413,62 @@
 #define V_GPIO_INTR_TYPE14(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_TYPE14)
 #define G_GPIO_INTR_TYPE14(x)	_SB_GETVALUE(x,S_GPIO_INTR_TYPE14,M_GPIO_INTR_TYPE14)
 
+#if SIBYTE_HDR_FEATURE_CHIP(1480)
+
+/*
+ * GPIO Interrupt Additional Type Register
+ */
+
+#define K_GPIO_INTR_BOTHEDGE	0
+#define K_GPIO_INTR_RISEEDGE	1
+#define K_GPIO_INTR_UNPRED1	2
+#define K_GPIO_INTR_UNPRED2	3
+
+#define S_GPIO_INTR_ATYPEX(n)	(((n)/2)*2)
+#define M_GPIO_INTR_ATYPEX(n)	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPEX(n))
+#define V_GPIO_INTR_ATYPEX(n,x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPEX(n))
+#define G_GPIO_INTR_ATYPEX(n,x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPEX(n),M_GPIO_INTR_ATYPEX(n))
+
+#define S_GPIO_INTR_ATYPE0	0
+#define M_GPIO_INTR_ATYPE0	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE0)
+#define V_GPIO_INTR_ATYPE0(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE0)
+#define G_GPIO_INTR_ATYPE0(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE0,M_GPIO_INTR_ATYPE0)
+
+#define S_GPIO_INTR_ATYPE2	2
+#define M_GPIO_INTR_ATYPE2	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE2)
+#define V_GPIO_INTR_ATYPE2(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE2)
+#define G_GPIO_INTR_ATYPE2(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE2,M_GPIO_INTR_ATYPE2)
+
+#define S_GPIO_INTR_ATYPE4	4
+#define M_GPIO_INTR_ATYPE4	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE4)
+#define V_GPIO_INTR_ATYPE4(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE4)
+#define G_GPIO_INTR_ATYPE4(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE4,M_GPIO_INTR_ATYPE4)
+
+#define S_GPIO_INTR_ATYPE6	6
+#define M_GPIO_INTR_ATYPE6	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE6)
+#define V_GPIO_INTR_ATYPE6(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE6)
+#define G_GPIO_INTR_ATYPE6(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE6,M_GPIO_INTR_ATYPE6)
+
+#define S_GPIO_INTR_ATYPE8	8
+#define M_GPIO_INTR_ATYPE8	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE8)
+#define V_GPIO_INTR_ATYPE8(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE8)
+#define G_GPIO_INTR_ATYPE8(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE8,M_GPIO_INTR_ATYPE8)
+
+#define S_GPIO_INTR_ATYPE10	10
+#define M_GPIO_INTR_ATYPE10	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE10)
+#define V_GPIO_INTR_ATYPE10(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE10)
+#define G_GPIO_INTR_ATYPE10(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE10,M_GPIO_INTR_ATYPE10)
+
+#define S_GPIO_INTR_ATYPE12	12
+#define M_GPIO_INTR_ATYPE12	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE12)
+#define V_GPIO_INTR_ATYPE12(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE12)
+#define G_GPIO_INTR_ATYPE12(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE12,M_GPIO_INTR_ATYPE12)
+
+#define S_GPIO_INTR_ATYPE14	14
+#define M_GPIO_INTR_ATYPE14	_SB_MAKEMASK(2,S_GPIO_INTR_ATYPE14)
+#define V_GPIO_INTR_ATYPE14(x)	_SB_MAKEVALUE(x,S_GPIO_INTR_ATYPE14)
+#define G_GPIO_INTR_ATYPE14(x)	_SB_GETVALUE(x,S_GPIO_INTR_ATYPE14,M_GPIO_INTR_ATYPE14)
+#endif
+
 
 #endif
diff --git a/include/asm-mips/sibyte/sb1250_int.h b/include/asm-mips/sibyte/sb1250_int.h
index e173e2e..05c7b39 100644
--- a/include/asm-mips/sibyte/sb1250_int.h
+++ b/include/asm-mips/sibyte/sb1250_int.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -47,6 +45,10 @@
  * First, the interrupt numbers.
  */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
+
+#define K_INT_SOURCES               64
+
 #define K_INT_WATCHDOG_TIMER_0      0
 #define K_INT_WATCHDOG_TIMER_1      1
 #define K_INT_TIMER_0               2
@@ -244,4 +246,6 @@
 #define M_LDTVECT_RAISEMBOX             0x40
 
 
+#endif	/* 1250/112x */
+
 #endif
diff --git a/include/asm-mips/sibyte/sb1250_l2c.h b/include/asm-mips/sibyte/sb1250_l2c.h
index 8afe8e0..842f205 100644
--- a/include/asm-mips/sibyte/sb1250_l2c.h
+++ b/include/asm-mips/sibyte/sb1250_l2c.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -89,8 +87,13 @@
 #define V_L2C_MGMT_WAY(x)           _SB_MAKEVALUE(x,S_L2C_MGMT_WAY)
 #define G_L2C_MGMT_WAY(x)           _SB_GETVALUE(x,S_L2C_MGMT_WAY,M_L2C_MGMT_WAY)
 
-#define S_L2C_MGMT_TAG              21
-#define M_L2C_MGMT_TAG              _SB_MAKEMASK(6,S_L2C_MGMT_TAG)
+#define S_L2C_MGMT_ECC_DIAG         21
+#define M_L2C_MGMT_ECC_DIAG         _SB_MAKEMASK(2,S_L2C_MGMT_ECC_DIAG)
+#define V_L2C_MGMT_ECC_DIAG(x)      _SB_MAKEVALUE(x,S_L2C_MGMT_ECC_DIAG)
+#define G_L2C_MGMT_ECC_DIAG(x)      _SB_GETVALUE(x,S_L2C_MGMT_ECC_DIAG,M_L2C_MGMT_ECC_DIAG)
+
+#define S_L2C_MGMT_TAG              23
+#define M_L2C_MGMT_TAG              _SB_MAKEMASK(4,S_L2C_MGMT_TAG)
 #define V_L2C_MGMT_TAG(x)           _SB_MAKEVALUE(x,S_L2C_MGMT_TAG)
 #define G_L2C_MGMT_TAG(x)           _SB_GETVALUE(x,S_L2C_MGMT_TAG,M_L2C_MGMT_TAG)
 
diff --git a/include/asm-mips/sibyte/sb1250_ldt.h b/include/asm-mips/sibyte/sb1250_ldt.h
index f2617de..7092535 100644
--- a/include/asm-mips/sibyte/sb1250_ldt.h
+++ b/include/asm-mips/sibyte/sb1250_ldt.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
diff --git a/include/asm-mips/sibyte/sb1250_mac.h b/include/asm-mips/sibyte/sb1250_mac.h
index 18e74e4..adfc688 100644
--- a/include/asm-mips/sibyte/sb1250_mac.h
+++ b/include/asm-mips/sibyte/sb1250_mac.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -81,7 +79,10 @@
 #define M_MAC_RESERVED1             _SB_MAKEMASK(8,9)
 
 #define M_MAC_AP_STAT_EN            _SB_MAKEMASK1(17)
-#define M_MAC_RESERVED2		    _SB_MAKEMASK1(18)
+
+#if SIBYTE_HDR_FEATURE_CHIP(1480)
+#define M_MAC_TIMESTAMP		    _SB_MAKEMASK1(18)
+#endif
 #define M_MAC_DRP_ERRPKT_EN         _SB_MAKEMASK1(19)
 #define M_MAC_DRP_FCSERRPKT_EN      _SB_MAKEMASK1(20)
 #define M_MAC_DRP_CODEERRPKT_EN     _SB_MAKEMASK1(21)
@@ -132,9 +133,9 @@
 #define M_MAC_RX_CH_SEL_MSB	    _SB_MAKEMASK1(44)
 #endif /* 1250 PASS2 || 112x PASS1 */
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_MAC_SPLIT_CH_SEL	    _SB_MAKEMASK1(45)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define S_MAC_BYPASS_IFG            _SB_MAKE64(46)
 #define M_MAC_BYPASS_IFG            _SB_MAKEMASK(8,S_MAC_BYPASS_IFG)
@@ -176,10 +177,22 @@
 
 #define M_MAC_PORT_RESET            _SB_MAKEMASK1(8)
 
+#if (SIBYTE_HDR_FEATURE_CHIP(1250) || SIBYTE_HDR_FEATURE_CHIP(112x))
 #define M_MAC_RX_ENABLE             _SB_MAKEMASK1(10)
 #define M_MAC_TX_ENABLE             _SB_MAKEMASK1(11)
 #define M_MAC_BYP_RX_ENABLE         _SB_MAKEMASK1(12)
 #define M_MAC_BYP_TX_ENABLE         _SB_MAKEMASK1(13)
+#endif
+
+/*
+ * MAC reset information register (1280/1255)
+ */
+#if SIBYTE_HDR_FEATURE_CHIP(1480)
+#define M_MAC_RX_CH0_PAUSE_ON	_SB_MAKEMASK1(8)
+#define M_MAC_RX_CH1_PAUSE_ON	_SB_MAKEMASK1(16)
+#define M_MAC_TX_CH0_PAUSE_ON	_SB_MAKEMASK1(24)
+#define M_MAC_TX_CH1_PAUSE_ON	_SB_MAKEMASK1(32)
+#endif
 
 /*
  * MAC DMA Control Register
@@ -267,12 +280,12 @@
 #define V_MAC_IFG_RX(x)             _SB_MAKEVALUE(x,S_MAC_IFG_RX)
 #define G_MAC_IFG_RX(x)             _SB_GETVALUE(x,S_MAC_IFG_RX,M_MAC_IFG_RX)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_MAC_PRE_LEN               _SB_MAKE64(0)
 #define M_MAC_PRE_LEN               _SB_MAKEMASK(6,S_MAC_PRE_LEN)
 #define V_MAC_PRE_LEN(x)            _SB_MAKEVALUE(x,S_MAC_PRE_LEN)
 #define G_MAC_PRE_LEN(x)            _SB_GETVALUE(x,S_MAC_PRE_LEN,M_MAC_PRE_LEN)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 #define S_MAC_IFG_TX                _SB_MAKE64(6)
 #define M_MAC_IFG_TX                _SB_MAKEMASK(6,S_MAC_IFG_TX)
@@ -458,9 +471,9 @@
 #define V_MAC_COUNTER_ADDR(x)       _SB_MAKEVALUE(x,S_MAC_COUNTER_ADDR)
 #define G_MAC_COUNTER_ADDR(x)       _SB_GETVALUE(x,S_MAC_COUNTER_ADDR,M_MAC_COUNTER_ADDR)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define M_MAC_TX_PAUSE_ON	    _SB_MAKEMASK1(52)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 /*
  * MAC Fifo Pointer Registers (Table 9-19)    [Debug register]
@@ -594,7 +607,7 @@
 #define V_MAC_IPHDR_OFFSET(x)	_SB_MAKEVALUE(x,S_MAC_IPHDR_OFFSET)
 #define G_MAC_IPHDR_OFFSET(x)	_SB_GETVALUE(x,S_MAC_IPHDR_OFFSET,M_MAC_IPHDR_OFFSET)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define S_MAC_RX_CRC_OFFSET     _SB_MAKE64(16)
 #define M_MAC_RX_CRC_OFFSET     _SB_MAKEMASK(8,S_MAC_RX_CRC_OFFSET)
 #define V_MAC_RX_CRC_OFFSET(x)	_SB_MAKEVALUE(x,S_MAC_RX_CRC_OFFSET)
@@ -612,7 +625,7 @@
 #define M_MAC_RX_CH_MSN_SEL     _SB_MAKEMASK(8,S_MAC_RX_CH_MSN_SEL)
 #define V_MAC_RX_CH_MSN_SEL(x)	_SB_MAKEVALUE(x,S_MAC_RX_CH_MSN_SEL)
 #define G_MAC_RX_CH_MSN_SEL(x)	_SB_GETVALUE(x,S_MAC_RX_CH_MSN_SEL,M_MAC_RX_CH_MSN_SEL)
-#endif /* 1250 PASS3 || 112x PASS1 */
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
 
 /*
  * MAC Receive Channel Select Registers (Table 9-25)
diff --git a/include/asm-mips/sibyte/sb1250_mc.h b/include/asm-mips/sibyte/sb1250_mc.h
index 1dd41c9..26e42149 100644
--- a/include/asm-mips/sibyte/sb1250_mc.h
+++ b/include/asm-mips/sibyte/sb1250_mc.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -324,6 +322,10 @@
 #define K_MC_tRFC_DEFAULT         12
 #define V_MC_tRFC_DEFAULT         V_MC_tRFC(K_MC_tRFC_DEFAULT)
 
+#if SIBYTE_HDR_FEATURE(1250, PASS3)
+#define M_MC_tRFC_PLUS16          _SB_MAKEMASK1(51)	/* 1250C3 and later.  */
+#endif
+
 #define S_MC_tCwCr                40
 #define M_MC_tCwCr                _SB_MAKEMASK(4,S_MC_tCwCr)
 #define V_MC_tCwCr(x)             _SB_MAKEVALUE(x,S_MC_tCwCr)
diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/include/asm-mips/sibyte/sb1250_regs.h
index 9db80cd..bab3a45 100644
--- a/include/asm-mips/sibyte/sb1250_regs.h
+++ b/include/asm-mips/sibyte/sb1250_regs.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  01/02/2002
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -61,6 +59,8 @@
  * XXX: can't remove MC base 0 if 112x, since it's used by other macros,
  * since there is one reg there (but it could get its addr/offset constant).
  */
+
+#if SIBYTE_HDR_FEATURE_1250_112x		/* This MC only on 1250 & 112x */
 #define A_MC_BASE_0                 0x0010051000
 #define A_MC_BASE_1                 0x0010052000
 #define MC_REGISTER_SPACING         0x1000
@@ -101,10 +101,14 @@
 #define R_MC_TEST_ECC               0x0000000420
 #define R_MC_MCLK_CFG               0x0000000500
 
+#endif	/* 1250 & 112x */
+
 /*  *********************************************************************
     * L2 Cache Control Registers
     ********************************************************************* */
 
+#if SIBYTE_HDR_FEATURE_1250_112x	/* This L2C only on 1250/112x */
+
 #define A_L2_READ_TAG               0x0010040018
 #define A_L2_ECC_TAG                0x0010040038
 #if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1)
@@ -125,13 +129,16 @@
 #define A_L2_READ_ADDRESS           A_L2_READ_TAG
 #define A_L2_EEC_ADDRESS            A_L2_ECC_TAG
 
+#endif
 
 /*  *********************************************************************
     * PCI Interface Registers
     ********************************************************************* */
 
+#if SIBYTE_HDR_FEATURE_1250_112x	/* This PCI/HT only on 1250/112x */
 #define A_PCI_TYPE00_HEADER         0x00DE000000
 #define A_PCI_TYPE01_HEADER         0x00DE000800
+#endif
 
 
 /*  *********************************************************************
@@ -264,15 +271,15 @@
     ********************************************************************* */
 
 
+#if SIBYTE_HDR_FEATURE_1250_112x		/* This MC only on 1250 & 112x */
 #define R_DUART_NUM_PORTS           2
 
 #define A_DUART                     0x0010060000
 
-#define A_DUART_REG(r)
-
 #define DUART_CHANREG_SPACING       0x100
 #define A_DUART_CHANREG(chan,reg)   (A_DUART + DUART_CHANREG_SPACING*(chan) + (reg))
 #define R_DUART_CHANREG(chan,reg)   (DUART_CHANREG_SPACING*(chan) + (reg))
+#endif	/* 1250 & 112x */
 
 #define R_DUART_MODE_REG_1	    0x100
 #define R_DUART_MODE_REG_2	    0x110
@@ -307,11 +314,13 @@
 
 #define DUART_IMRISR_SPACING        0x20
 
+#if SIBYTE_HDR_FEATURE_1250_112x		/* This MC only on 1250 & 112x */
 #define R_DUART_IMRREG(chan)	    (R_DUART_IMR_A + (chan)*DUART_IMRISR_SPACING)
 #define R_DUART_ISRREG(chan)	    (R_DUART_ISR_A + (chan)*DUART_IMRISR_SPACING)
 
 #define A_DUART_IMRREG(chan)	    (A_DUART + R_DUART_IMRREG(chan))
 #define A_DUART_ISRREG(chan)	    (A_DUART + R_DUART_ISRREG(chan))
+#endif	/* 1250 & 112x */
 
 
 
@@ -368,6 +377,8 @@
     ********************************************************************* */
 
 
+#if SIBYTE_HDR_FEATURE_1250_112x	/* sync serial only on 1250/112x */
+
 #define A_SER_BASE_0                0x0010060400
 #define A_SER_BASE_1                0x0010060800
 #define SER_SPACING                 0x400
@@ -457,6 +468,8 @@
 #define R_SER_RMON_RX_ERRORS        0x000001F0
 #define R_SER_RMON_RX_BADADDR       0x000001F8
 
+#endif	/* 1250/112x */
+
 /*  *********************************************************************
     * Generic Bus Registers
     ********************************************************************* */
@@ -634,12 +647,13 @@
 
 #if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
 #define A_SCD_SCRATCH		   0x0010020C10
+#endif /* 1250 PASS2 || 112x PASS1 */
 
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define A_SCD_ZBBUS_CYCLE_COUNT	   0x0010030000
 #define A_SCD_ZBBUS_CYCLE_CP0	   0x0010020C00
 #define A_SCD_ZBBUS_CYCLE_CP1	   0x0010020C08
-#endif /* 1250 PASS2 || 112x PASS1 */
-
+#endif
 
 /*  *********************************************************************
     * System Control Registers
@@ -667,15 +681,16 @@
 #define A_ADDR_TRAP_CFG_1           0x0010020448
 #define A_ADDR_TRAP_CFG_2           0x0010020450
 #define A_ADDR_TRAP_CFG_3           0x0010020458
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 #define A_ADDR_TRAP_REG_DEBUG	    0x0010020460
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 
 /*  *********************************************************************
     * System Interrupt Mapper Registers
     ********************************************************************* */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
 #define A_IMR_CPU0_BASE                 0x0010020000
 #define A_IMR_CPU1_BASE                 0x0010022000
 #define IMR_REGISTER_SPACING            0x2000
@@ -700,6 +715,7 @@
 #define R_IMR_INTERRUPT_STATUS_COUNT    7
 #define R_IMR_INTERRUPT_MAP_BASE        0x0200
 #define R_IMR_INTERRUPT_MAP_COUNT       64
+#endif	/* 1250/112x */
 
 /*  *********************************************************************
     * System Performance Counter Registers
@@ -718,6 +734,7 @@
 #define A_SCD_BUS_ERR_STATUS        0x0010020880
 #if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
 #define A_SCD_BUS_ERR_STATUS_DEBUG  0x00100208D0
+#define A_BUS_ERR_STATUS_DEBUG  0x00100208D0
 #endif /* 1250 PASS2 || 112x PASS1 */
 #define A_BUS_ERR_DATA_0            0x00100208A0
 #define A_BUS_ERR_DATA_1            0x00100208A8
@@ -798,6 +815,7 @@
     *  Physical Address Map
     ********************************************************************* */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
 #define A_PHYS_MEMORY_0                 _SB_MAKE64(0x0000000000)
 #define A_PHYS_MEMORY_SIZE              _SB_MAKE64((256*1024*1024))
 #define A_PHYS_SYSTEM_CTL               _SB_MAKE64(0x0010000000)
@@ -831,6 +849,7 @@
 #define A_PHYS_L2CACHE_WAY1             _SB_MAKE64(0x00D01A0000)
 #define A_PHYS_L2CACHE_WAY2             _SB_MAKE64(0x00D01C0000)
 #define A_PHYS_L2CACHE_WAY3             _SB_MAKE64(0x00D01E0000)
+#endif
 
 
 #endif
diff --git a/include/asm-mips/sibyte/sb1250_scd.h b/include/asm-mips/sibyte/sb1250_scd.h
index dbbd682..a667bc1 100644
--- a/include/asm-mips/sibyte/sb1250_scd.h
+++ b/include/asm-mips/sibyte/sb1250_scd.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -51,26 +49,70 @@
 #define V_SYS_REVISION(x)           _SB_MAKEVALUE(x,S_SYS_REVISION)
 #define G_SYS_REVISION(x)           _SB_GETVALUE(x,S_SYS_REVISION,M_SYS_REVISION)
 
-#if SIBYTE_HDR_FEATURE_CHIP(1250)
-#define K_SYS_REVISION_BCM1250_PASS1	1
-#define K_SYS_REVISION_BCM1250_PASS2	3
-#define K_SYS_REVISION_BCM1250_A10	11
-#define K_SYS_REVISION_BCM1250_PASS2_2	16
-#define K_SYS_REVISION_BCM1250_B2	17
-#define K_SYS_REVISION_BCM1250_PASS3	32
-#define K_SYS_REVISION_BCM1250_C1	33
+#define K_SYS_REVISION_BCM1250_PASS1	0x01
 
+#define K_SYS_REVISION_BCM1250_PASS2	0x03
+#define K_SYS_REVISION_BCM1250_A1	0x03	/* Pass 2.0 WB */
+#define K_SYS_REVISION_BCM1250_A2	0x04	/* Pass 2.0 FC */
+#define K_SYS_REVISION_BCM1250_A3	0x05	/* Pass 2.1 FC */
+#define K_SYS_REVISION_BCM1250_A4	0x06	/* Pass 2.1 WB */
+#define K_SYS_REVISION_BCM1250_A6	0x07	/* OR 0x04 (A2) w/WID != 0 */
+#define K_SYS_REVISION_BCM1250_A8	0x0b	/* A8/A10 */
+#define K_SYS_REVISION_BCM1250_A9	0x08
+#define K_SYS_REVISION_BCM1250_A10	K_SYS_REVISION_BCM1250_A8
+
+#define K_SYS_REVISION_BCM1250_PASS2_2	0x10
+#define K_SYS_REVISION_BCM1250_B0	K_SYS_REVISION_BCM1250_B1
+#define K_SYS_REVISION_BCM1250_B1	0x10
+#define K_SYS_REVISION_BCM1250_B2	0x11
+
+#define K_SYS_REVISION_BCM1250_C0	0x20
+#define K_SYS_REVISION_BCM1250_C1	0x21
+#define K_SYS_REVISION_BCM1250_C2	0x22
+#define K_SYS_REVISION_BCM1250_C3	0x23
+
+#if SIBYTE_HDR_FEATURE_CHIP(1250)
 /* XXX: discourage people from using these constants.  */
 #define K_SYS_REVISION_PASS1	    K_SYS_REVISION_BCM1250_PASS1
 #define K_SYS_REVISION_PASS2	    K_SYS_REVISION_BCM1250_PASS2
 #define K_SYS_REVISION_PASS2_2	    K_SYS_REVISION_BCM1250_PASS2_2
 #define K_SYS_REVISION_PASS3	    K_SYS_REVISION_BCM1250_PASS3
+#define K_SYS_REVISION_BCM1250_PASS3	K_SYS_REVISION_BCM1250_C0
 #endif /* 1250 */
 
-#if SIBYTE_HDR_FEATURE_CHIP(112x)
-#define K_SYS_REVISION_BCM112x_A1	32
-#define K_SYS_REVISION_BCM112x_A2	33
-#endif /* 112x */
+#define K_SYS_REVISION_BCM112x_A1	0x20
+#define K_SYS_REVISION_BCM112x_A2	0x21
+#define K_SYS_REVISION_BCM112x_A3	0x22
+#define K_SYS_REVISION_BCM112x_A4	0x23
+
+#define K_SYS_REVISION_BCM1480_S0	0x01
+#define K_SYS_REVISION_BCM1480_A1	0x02
+#define K_SYS_REVISION_BCM1480_A2	0x03
+#define K_SYS_REVISION_BCM1480_A3	0x04
+#define K_SYS_REVISION_BCM1480_B0	0x11
+
+/*Cache size - 23:20  of revision register*/
+#define S_SYS_L2C_SIZE            _SB_MAKE64(20)
+#define M_SYS_L2C_SIZE            _SB_MAKEMASK(4,S_SYS_L2C_SIZE)
+#define V_SYS_L2C_SIZE(x)         _SB_MAKEVALUE(x,S_SYS_L2C_SIZE)
+#define G_SYS_L2C_SIZE(x)         _SB_GETVALUE(x,S_SYS_L2C_SIZE,M_SYS_L2C_SIZE)
+
+#define K_SYS_L2C_SIZE_1MB	0
+#define K_SYS_L2C_SIZE_512KB	5
+#define K_SYS_L2C_SIZE_256KB	2
+#define K_SYS_L2C_SIZE_128KB	1
+
+#define K_SYS_L2C_SIZE_BCM1250	K_SYS_L2C_SIZE_512KB
+#define K_SYS_L2C_SIZE_BCM1125	K_SYS_L2C_SIZE_256KB
+#define K_SYS_L2C_SIZE_BCM1122	K_SYS_L2C_SIZE_128KB
+
+
+/* Number of CPU cores, bits 27:24  of revision register*/
+#define S_SYS_NUM_CPUS            _SB_MAKE64(24)
+#define M_SYS_NUM_CPUS            _SB_MAKEMASK(4,S_SYS_NUM_CPUS)
+#define V_SYS_NUM_CPUS(x)         _SB_MAKEVALUE(x,S_SYS_NUM_CPUS)
+#define G_SYS_NUM_CPUS(x)         _SB_GETVALUE(x,S_SYS_NUM_CPUS,M_SYS_NUM_CPUS)
+
 
 /* XXX: discourage people from using these constants.  */
 #define S_SYS_PART                  _SB_MAKE64(16)
@@ -83,6 +125,8 @@
 #define K_SYS_PART_BCM1120          0x1121
 #define K_SYS_PART_BCM1125          0x1123
 #define K_SYS_PART_BCM1125H         0x1124
+#define K_SYS_PART_BCM1122          0x1113
+
 
 /* The "peripheral set" (SOC type) is the low 4 bits of the "part" field.  */
 #define S_SYS_SOC_TYPE              _SB_MAKE64(16)
@@ -96,6 +140,8 @@
 #define K_SYS_SOC_TYPE_BCM1125      0x3
 #define K_SYS_SOC_TYPE_BCM1125H     0x4
 #define K_SYS_SOC_TYPE_BCM1250_ALT2 0x5		/* 1250pass2 w/ 1/2 L2.  */
+#define K_SYS_SOC_TYPE_BCM1x80      0x6
+#define K_SYS_SOC_TYPE_BCM1x55      0x7
 
 /*
  * Calculate correct SOC type given a copy of system revision register.
@@ -127,10 +173,12 @@
 #define V_SYS_WID(x)                _SB_MAKEVALUE(x,S_SYS_WID)
 #define G_SYS_WID(x)                _SB_GETVALUE(x,S_SYS_WID,M_SYS_WID)
 
-/* System Manufacturing Register
-* Register: SCD_SYSTEM_MANUF
-*/
+/*
+ * System Manufacturing Register
+ * Register: SCD_SYSTEM_MANUF
+ */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
 /* Wafer ID: bits 31:0 */
 #define S_SYS_WAFERID1_200        _SB_MAKE64(0)
 #define M_SYS_WAFERID1_200        _SB_MAKEMASK(32,S_SYS_WAFERID1_200)
@@ -139,8 +187,8 @@
 
 #define S_SYS_BIN                 _SB_MAKE64(32)
 #define M_SYS_BIN                 _SB_MAKEMASK(4,S_SYS_BIN)
-#define V_SYS_BIN                 _SB_MAKEVALUE(x,S_SYS_BIN)
-#define G_SYS_BIN                 _SB_GETVALUE(x,S_SYS_BIN,M_SYS_BIN)
+#define V_SYS_BIN(x)              _SB_MAKEVALUE(x,S_SYS_BIN)
+#define G_SYS_BIN(x)              _SB_GETVALUE(x,S_SYS_BIN,M_SYS_BIN)
 
 /* Wafer ID: bits 39:36 */
 #define S_SYS_WAFERID2_200        _SB_MAKE64(36)
@@ -163,12 +211,14 @@
 #define M_SYS_YPOS                _SB_MAKEMASK(6,S_SYS_YPOS)
 #define V_SYS_YPOS(x)             _SB_MAKEVALUE(x,S_SYS_YPOS)
 #define G_SYS_YPOS(x)             _SB_GETVALUE(x,S_SYS_YPOS,M_SYS_YPOS)
+#endif
 
 /*
  * System Config Register (Table 4-2)
  * Register: SCD_SYSTEM_CFG
  */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
 #define M_SYS_LDT_PLL_BYP           _SB_MAKEMASK1(3)
 #define M_SYS_PCI_SYNC_TEST_MODE    _SB_MAKEMASK1(4)
 #define M_SYS_IOB0_DIV              _SB_MAKEMASK1(5)
@@ -253,6 +303,8 @@
 #define M_SYS_SW_FLAG		    _SB_MAKEMASK1(63)
 #endif /* 1250 PASS2 || 112x PASS1 */
 
+#endif
+
 
 /*
  * Mailbox Registers (Table 4-3)
@@ -326,6 +378,7 @@
  * System Performance Counters
  */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
 #define S_SPC_CFG_SRC0            0
 #define M_SPC_CFG_SRC0            _SB_MAKEMASK(8,S_SPC_CFG_SRC0)
 #define V_SPC_CFG_SRC0(x)         _SB_MAKEVALUE(x,S_SPC_CFG_SRC0)
@@ -348,6 +401,7 @@
 
 #define M_SPC_CFG_CLEAR		_SB_MAKEMASK1(32)
 #define M_SPC_CFG_ENABLE	_SB_MAKEMASK1(33)
+#endif
 
 
 /*
@@ -412,6 +466,7 @@
  * Address Trap Registers
  */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
 #define M_ATRAP_INDEX		  _SB_MAKEMASK(4,0)
 #define M_ATRAP_ADDRESS		  _SB_MAKEMASK(40,0)
 
@@ -436,7 +491,6 @@
 #define K_BUS_AGENT_IOB0	2
 #define K_BUS_AGENT_IOB1	3
 #define K_BUS_AGENT_SCD	4
-#define K_BUS_AGENT_RESERVED	5
 #define K_BUS_AGENT_L2C	6
 #define K_BUS_AGENT_MC	7
 
@@ -454,10 +508,14 @@
 #define K_ATRAP_CFG_CATTR_NOTNONCOH	6
 #define K_ATRAP_CFG_CATTR_NOTCOHERENT   7
 
+#endif	/* 1250/112x */
+
 /*
  * Trace Buffer Config register
  */
 
+#if SIBYTE_HDR_FEATURE_1250_112x
+
 #define M_SCD_TRACE_CFG_RESET           _SB_MAKEMASK1(0)
 #define M_SCD_TRACE_CFG_START_READ      _SB_MAKEMASK1(1)
 #define M_SCD_TRACE_CFG_START           _SB_MAKEMASK1(2)
@@ -475,6 +533,8 @@
 #define V_SCD_TRACE_CFG_CUR_ADDR(x)     _SB_MAKEVALUE(x,S_SCD_TRACE_CFG_CUR_ADDR)
 #define G_SCD_TRACE_CFG_CUR_ADDR(x)     _SB_GETVALUE(x,S_SCD_TRACE_CFG_CUR_ADDR,M_SCD_TRACE_CFG_CUR_ADDR)
 
+#endif	/* 1250/112x */
+
 /*
  * Trace Event registers
  */
@@ -578,5 +638,7 @@
 #define M_SCD_TRSEQ_DEBUGPIN            _SB_MAKEMASK1(20)
 #define M_SCD_TRSEQ_DEBUGCPU            _SB_MAKEMASK1(21)
 #define M_SCD_TRSEQ_CLEARUSE            _SB_MAKEMASK1(22)
+#define M_SCD_TRSEQ_ALLD_A              _SB_MAKEMASK1(23)
+#define M_SCD_TRSEQ_ALL_A               _SB_MAKEMASK1(24)
 
 #endif
diff --git a/include/asm-mips/sibyte/sb1250_smbus.h b/include/asm-mips/sibyte/sb1250_smbus.h
index 335c53e..279a912 100644
--- a/include/asm-mips/sibyte/sb1250_smbus.h
+++ b/include/asm-mips/sibyte/sb1250_smbus.h
@@ -6,9 +6,8 @@
     *  This module contains constants and macros useful for
     *  manipulating the SB1250's SMbus devices.
     *
-    *  SB1250 specification level:  01/02/2002
-    *
-    *  Author:  Mitch Lichtenberg
+    *  SB1250 specification level:  10/21/02
+    *  BCM1280 specification level:  11/24/03
     *
     *********************************************************************
     *
@@ -47,6 +46,7 @@
 
 #define K_SMB_FREQ_400KHZ	    0x1F
 #define K_SMB_FREQ_100KHZ	    0x7D
+#define K_SMB_FREQ_10KHZ	    1250
 
 #define S_SMB_CMD                   0
 #define M_SMB_CMD                   _SB_MAKEMASK(8,S_SMB_CMD)
@@ -58,7 +58,11 @@
 
 #define M_SMB_ERR_INTR              _SB_MAKEMASK1(0)
 #define M_SMB_FINISH_INTR           _SB_MAKEMASK1(1)
-#define M_SMB_DATA_OUT              _SB_MAKEMASK1(4)
+
+#define S_SMB_DATA_OUT              4
+#define M_SMB_DATA_OUT              _SB_MAKEMASK1(S_SMB_DATA_OUT)
+#define V_SMB_DATA_OUT(x)           _SB_MAKEVALUE(x,S_SMB_DATA_OUT)
+
 #define M_SMB_DATA_DIR              _SB_MAKEMASK1(5)
 #define M_SMB_DATA_DIR_OUTPUT       M_SMB_DATA_DIR
 #define M_SMB_CLK_OUT               _SB_MAKEMASK1(6)
@@ -71,8 +75,23 @@
 #define M_SMB_BUSY                  _SB_MAKEMASK1(0)
 #define M_SMB_ERROR                 _SB_MAKEMASK1(1)
 #define M_SMB_ERROR_TYPE            _SB_MAKEMASK1(2)
-#define M_SMB_REF                   _SB_MAKEMASK1(6)
-#define M_SMB_DATA_IN               _SB_MAKEMASK1(7)
+
+#if SIBYTE_HDR_FEATURE(1250, PASS3) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
+#define S_SMB_SCL_IN                5
+#define M_SMB_SCL_IN                _SB_MAKEMASK1(S_SMB_SCL_IN)
+#define V_SMB_SCL_IN(x)             _SB_MAKEVALUE(x,S_SMB_SCL_IN)
+#define G_SMB_SCL_IN(x)             _SB_GETVALUE(x,S_SMB_SCL_IN,M_SMB_SCL_IN)
+#endif /* 1250 PASS3 || 112x PASS1 || 1480 */
+
+#define S_SMB_REF                   6
+#define M_SMB_REF                   _SB_MAKEMASK1(S_SMB_REF)
+#define V_SMB_REF(x)                _SB_MAKEVALUE(x,S_SMB_REF)
+#define G_SMB_REF(x)                _SB_GETVALUE(x,S_SMB_REF,M_SMB_REF)
+
+#define S_SMB_DATA_IN               7
+#define M_SMB_DATA_IN               _SB_MAKEMASK1(S_SMB_DATA_IN)
+#define V_SMB_DATA_IN(x)            _SB_MAKEVALUE(x,S_SMB_DATA_IN)
+#define G_SMB_DATA_IN(x)            _SB_GETVALUE(x,S_SMB_DATA_IN,M_SMB_DATA_IN)
 
 /*
  * SMBus Start/Command registers (Table 14-9)
@@ -132,16 +151,14 @@
 #define V_SPEC_MB(x)                _SB_MAKEVALUE(x,S_SPEC_PEC)
 
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 
 #define S_SMB_CMDH                  8
-#define M_SMB_CMDH                  _SB_MAKEMASK(8,S_SMBH_CMD)
-#define V_SMB_CMDH(x)               _SB_MAKEVALUE(x,S_SMBH_CMD)
+#define M_SMB_CMDH                  _SB_MAKEMASK(8,S_SMB_CMDH)
+#define V_SMB_CMDH(x)               _SB_MAKEVALUE(x,S_SMB_CMDH)
 
 #define M_SMB_EXTEND		    _SB_MAKEMASK1(14)
 
-#define M_SMB_DIR		    _SB_MAKEMASK1(13)
-
 #define S_SMB_DFMT                  8
 #define M_SMB_DFMT                  _SB_MAKEMASK(3,S_SMB_DFMT)
 #define V_SMB_DFMT(x)               _SB_MAKEVALUE(x,S_SMB_DFMT)
@@ -165,6 +182,23 @@
 #define V_SMB_DFMT_CMD5BYTE	    V_SMB_DFMT(K_SMB_DFMT_CMD5BYTE)
 #define V_SMB_DFMT_RESERVED	    V_SMB_DFMT(K_SMB_DFMT_RESERVED)
 
-#endif /* 1250 PASS2 || 112x PASS1 */
+#define S_SMB_AFMT                  11
+#define M_SMB_AFMT                  _SB_MAKEMASK(2,S_SMB_AFMT)
+#define V_SMB_AFMT(x)               _SB_MAKEVALUE(x,S_SMB_AFMT)
+#define G_SMB_AFMT(x)               _SB_GETVALUE(x,S_SMB_AFMT,M_SMB_AFMT)
+
+#define K_SMB_AFMT_NONE             0
+#define K_SMB_AFMT_ADDR             1
+#define K_SMB_AFMT_ADDR_CMD1BYTE    2
+#define K_SMB_AFMT_ADDR_CMD2BYTE    3
+
+#define V_SMB_AFMT_NONE		    V_SMB_AFMT(K_SMB_AFMT_NONE)
+#define V_SMB_AFMT_ADDR		    V_SMB_AFMT(K_SMB_AFMT_ADDR)
+#define V_SMB_AFMT_ADDR_CMD1BYTE    V_SMB_AFMT(K_SMB_AFMT_ADDR_CMD1BYTE)
+#define V_SMB_AFMT_ADDR_CMD2BYTE    V_SMB_AFMT(K_SMB_AFMT_ADDR_CMD2BYTE)
+
+#define M_SMB_DIR		    _SB_MAKEMASK1(13)
+
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 #endif
diff --git a/include/asm-mips/sibyte/sb1250_syncser.h b/include/asm-mips/sibyte/sb1250_syncser.h
index fa2760d..dd154ac 100644
--- a/include/asm-mips/sibyte/sb1250_syncser.h
+++ b/include/asm-mips/sibyte/sb1250_syncser.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/include/asm-mips/sibyte/sb1250_uart.h
index 923ea4f..e87045e 100644
--- a/include/asm-mips/sibyte/sb1250_uart.h
+++ b/include/asm-mips/sibyte/sb1250_uart.h
@@ -8,8 +8,6 @@
     *
     *  SB1250 specification level:  User's manual 1/02/02
     *
-    *  Author:  Mitch Lichtenberg
-    *
     *********************************************************************
     *
     *  Copyright 2000,2001,2002,2003
@@ -240,7 +238,12 @@
  */
 
 #define M_DUART_ISR_TX_A            _SB_MAKEMASK1(0)
-#define M_DUART_ISR_RX_A            _SB_MAKEMASK1(1)
+
+#define S_DUART_ISR_RX_A            1
+#define M_DUART_ISR_RX_A            _SB_MAKEMASK1(S_DUART_ISR_RX_A)
+#define V_DUART_ISR_RX_A(x)         _SB_MAKEVALUE(x,S_DUART_ISR_RX_A)
+#define G_DUART_ISR_RX_A(x)         _SB_GETVALUE(x,S_DUART_ISR_RX_A,M_DUART_ISR_RX_A)
+
 #define M_DUART_ISR_BRK_A           _SB_MAKEMASK1(2)
 #define M_DUART_ISR_IN_A            _SB_MAKEMASK1(3)
 #define M_DUART_ISR_TX_B            _SB_MAKEMASK1(4)
@@ -331,7 +334,7 @@
 #define M_DUART_OUT_PIN_CLR(chan) \
     (chan == 0 ? M_DUART_OUT_PIN_CLR0 : M_DUART_OUT_PIN_CLR1)
 
-#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1)
+#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
 /*
  * Full Interrupt Control Register
  */
@@ -345,7 +348,7 @@
 #define M_DUART_INT_TIME           _SB_MAKEMASK(4,S_DUART_INT_TIME)
 #define V_DUART_INT_TIME(x)        _SB_MAKEVALUE(x,S_DUART_INT_TIME)
 #define G_DUART_INT_TIME(x)        _SB_GETVALUE(x,S_DUART_INT_TIME,M_DUART_INT_TIME)
-#endif /* 1250 PASS2 || 112x PASS1 */
+#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
 
 
 /* ********************************************************************** */
diff --git a/include/asm-mips/sibyte/swarm.h b/include/asm-mips/sibyte/swarm.h
index 97fa049..06e1d52 100644
--- a/include/asm-mips/sibyte/swarm.h
+++ b/include/asm-mips/sibyte/swarm.h
@@ -34,7 +34,7 @@
 #define SIBYTE_DEFAULT_CONSOLE "ttyS0,115200"
 #endif
 #ifdef CONFIG_SIBYTE_LITTLESUR
-#define SIBYTE_BOARD_NAME "BCM1250C2 (LittleSur)"
+#define SIBYTE_BOARD_NAME "BCM91250C2 (LittleSur)"
 #define SIBYTE_HAVE_PCMCIA 0
 #define SIBYTE_HAVE_IDE    1
 #define SIBYTE_DEFAULT_CONSOLE "cfe0"
diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h
index f7fbeba..8edabb0 100644
--- a/include/asm-mips/sigcontext.h
+++ b/include/asm-mips/sigcontext.h
@@ -27,14 +27,15 @@
 	unsigned int		sc_fpc_csr;
 	unsigned int		sc_fpc_eir;	/* Unused */
 	unsigned int		sc_used_math;
-	unsigned int		sc_ssflags;	/* Unused */
+	unsigned int		sc_dsp;		/* dsp status, was sc_ssflags */
 	unsigned long long	sc_mdhi;
 	unsigned long long	sc_mdlo;
-
-	unsigned int		sc_cause;	/* Unused */
-	unsigned int		sc_badvaddr;	/* Unused */
-
-	unsigned long		sc_sigset[4];	/* kernel's sigset_t */
+	unsigned long		sc_hi1;		/* Was sc_cause */
+	unsigned long		sc_lo1;		/* Was sc_badvaddr */
+	unsigned long		sc_hi2;		/* Was sc_sigset[4] */
+	unsigned long		sc_lo2;
+	unsigned long		sc_hi3;
+	unsigned long		sc_lo3;
 };
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
@@ -48,19 +49,19 @@
  * Warning: this structure illdefined with sc_badvaddr being just an unsigned
  * int so it was changed to unsigned long in 2.6.0-test1.  This may break
  * binary compatibility - no prisoners.
+ * DSP ASE in 2.6.12-rc4.  Turn sc_mdhi and sc_mdlo into an array of four
+ * entries, add sc_dsp and sc_reserved for padding.  No prisoners.
  */
 struct sigcontext {
 	unsigned long	sc_regs[32];
 	unsigned long	sc_fpregs[32];
-	unsigned long	sc_mdhi;
-	unsigned long	sc_mdlo;
+	unsigned long	sc_hi[4];
+	unsigned long	sc_lo[4];
 	unsigned long	sc_pc;
-	unsigned long	sc_badvaddr;
-	unsigned int	sc_status;
 	unsigned int	sc_fpc_csr;
-	unsigned int	sc_fpc_eir;
 	unsigned int	sc_used_math;
-	unsigned int	sc_cause;
+	unsigned int	sc_dsp;
+	unsigned int	sc_reserved;
 };
 
 #ifdef __KERNEL__
@@ -68,23 +69,24 @@
 #include <linux/posix_types.h>
 
 struct sigcontext32 {
-	__u32	sc_regmask;		/* Unused */
-	__u32	sc_status;
-	__u64	sc_pc;
-	__u64	sc_regs[32];
-	__u64	sc_fpregs[32];
-	__u32	sc_ownedfp;		/* Unused */
-	__u32	sc_fpc_csr;
-	__u32	sc_fpc_eir;		/* Unused */
-	__u32	sc_used_math;
-	__u32	sc_ssflags;		/* Unused */
-	__u64	sc_mdhi;
-	__u64	sc_mdlo;
-
-	__u32	sc_cause;		/* Unused */
-	__u32	sc_badvaddr;		/* Unused */
-
-	__u32	sc_sigset[4];		/* kernel's sigset_t */
+	__u32		sc_regmask;	/* Unused */
+	__u32		sc_status;
+	__u64		sc_pc;
+	__u64		sc_regs[32];
+	__u64		sc_fpregs[32];
+	__u32		sc_ownedfp;	/* Unused */
+	__u32		sc_fpc_csr;
+	__u32		sc_fpc_eir;	/* Unused */
+	__u32		sc_used_math;
+	__u32		sc_dsp;		/* dsp status, was sc_ssflags */
+	__u64		sc_mdhi;
+	__u64		sc_mdlo;
+	__u32		sc_hi1;		/* Was sc_cause */
+	__u32		sc_lo1;		/* Was sc_badvaddr */
+	__u32		sc_hi2;		/* Was sc_sigset[4] */
+	__u32		sc_lo2;
+	__u32		sc_hi3;
+	__u32		sc_lo3;
 };
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
index 698beca..2ba313d 100644
--- a/include/asm-mips/siginfo.h
+++ b/include/asm-mips/siginfo.h
@@ -11,6 +11,7 @@
 
 #include <linux/config.h>
 
+#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int))
 #undef __ARCH_SI_TRAPNO	/* exception code needs to fill this ...  */
 
 #define HAVE_ARCH_SIGINFO_T
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
index f2c470f..8ca539e 100644
--- a/include/asm-mips/signal.h
+++ b/include/asm-mips/signal.h
@@ -98,12 +98,39 @@
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
+ */
+#define SA_SAMPLE_RANDOM	SA_RESTART
+
+#ifdef CONFIG_TRAD_SIGNALS
+#define sig_uses_siginfo(ka)	((ka)->sa.sa_flags & SA_SIGINFO)
+#else
+#define sig_uses_siginfo(ka)	(1)
+#endif
+
+#endif /* __KERNEL__ */
+
 #define SIG_BLOCK	1	/* for blocking signals */
 #define SIG_UNBLOCK	2	/* for unblocking signals */
 #define SIG_SETMASK	3	/* for setting the signal mask */
 #define SIG_SETMASK32	256	/* Goodie from SGI for BSD compatibility:
 				   set only the low 32 bit of the sigset.  */
-#include <asm-generic/signal.h>
+
+/* Type of a signal handler.  */
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
+
+/* Fake signal functions */
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 
 struct sigaction {
 	unsigned int	sa_flags;
diff --git a/include/asm-mips/sn/sn0/arch.h b/include/asm-mips/sn/sn0/arch.h
index 0e00dd4..fb78773 100644
--- a/include/asm-mips/sn/sn0/arch.h
+++ b/include/asm-mips/sn/sn0/arch.h
@@ -74,13 +74,8 @@
 #define MAX_MEM_SLOTS   32                      /* max slots per node */
 #endif /* defined(N_MODE) */
 
-#if SABLE_RTL
-#define SLOT_SHIFT      	(28)
-#define SLOT_MIN_MEM_SIZE	(16*1024*1024)
-#else
 #define SLOT_SHIFT      	(27)
 #define SLOT_MIN_MEM_SIZE	(32*1024*1024)
-#endif
 
 #define CPUS_PER_NODE		2	/* CPUs on a single hub */
 #define CPUS_PER_NODE_SHFT	1	/* Bits to shift in the node number */
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
index 753b662..0bb31e5 100644
--- a/include/asm-mips/socket.h
+++ b/include/asm-mips/socket.h
@@ -37,8 +37,6 @@
 #define SO_ERROR	0x1007	/* get error status and clear */
 #define SO_SNDBUF	0x1001	/* Send buffer size. */
 #define SO_RCVBUF	0x1002	/* Receive buffer. */
-#define SO_SNDBUFFORCE	0x100a
-#define SO_RCVBUFFORCE	0x100b
 #define SO_SNDLOWAT	0x1003	/* send low-water mark */
 #define SO_RCVLOWAT	0x1004	/* receive low-water mark */
 #define SO_SNDTIMEO	0x1005	/* send timeout */
@@ -69,6 +67,8 @@
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
 #define SO_PEERSEC		30
+#define SO_SNDBUFFORCE		31
+#define SO_RCVBUFFORCE		33
 
 #ifdef __KERNEL__
 
@@ -92,6 +92,7 @@
 	SOCK_RAW	= 3,
 	SOCK_RDM	= 4,
 	SOCK_SEQPACKET	= 5,
+	SOCK_DCCP	= 6,
 	SOCK_PACKET	= 10,
 };
 
diff --git a/include/asm-mips/spinlock.h b/include/asm-mips/spinlock.h
index 4d0135b..669b8e3 100644
--- a/include/asm-mips/spinlock.h
+++ b/include/asm-mips/spinlock.h
@@ -9,17 +9,16 @@
 #ifndef _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 
-#include <linux/config.h>
 #include <asm/war.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  */
 
-#define __raw_spin_is_locked(x)	((x)->lock != 0)
+#define __raw_spin_is_locked(x)       ((x)->lock != 0)
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 #define __raw_spin_unlock_wait(x) \
-		do { cpu_relax(); } while ((x)->lock)
+	do { cpu_relax(); } while ((x)->lock)
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
@@ -119,6 +118,18 @@
  * read-locks.
  */
 
+/*
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define __raw_read_can_lock(rw)	((rw)->lock >= 0)
+
+/*
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define __raw_write_can_lock(rw)	(!(rw)->lock)
+
 static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
 	unsigned int tmp;
@@ -197,8 +208,7 @@
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
-		"	 nop						\n"
-		"	sync						\n"
+		"	 sync						\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
@@ -211,8 +221,7 @@
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
-		"	 nop						\n"
-		"	sync						\n"
+		"	 sync						\n"
 		"	.set	reorder					\n"
 		: "=m" (rw->lock), "=&r" (tmp)
 		: "m" (rw->lock)
@@ -246,8 +255,7 @@
 		"	 lui	%1, 0x8000				\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
-		"	 nop						\n"
-		"	sync						\n"
+		"	 sync						\n"
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 7b5e646..a8919dc 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -60,7 +60,6 @@
 		mfc0	k0, CP0_CONTEXT
 		lui	k1, %hi(kernelsp)
 		srl	k0, k0, 23
-		sll	k0, k0, 2
 		addu	k1, k0
 		LONG_L	k1, %lo(kernelsp)(k1)
 #endif
@@ -76,9 +75,14 @@
 #endif
 #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
 		MFC0	k1, CP0_CONTEXT
+		lui	k0, %highest(kernelsp)
 		dsrl	k1, 23
-		dsll	k1, k1, 3
-		LONG_L	k1, kernelsp(k1)
+		daddiu	k0, %higher(kernelsp)
+		dsll	k0, k0, 16
+		daddiu	k0, %hi(kernelsp)
+		dsll	k0, k0, 16
+		daddu	k1, k1, k0
+		LONG_L	k1, %lo(kernelsp)(k1)
 #endif
 		.endm
 
@@ -86,25 +90,28 @@
 #ifdef CONFIG_32BIT
 		mfc0	\temp, CP0_CONTEXT
 		srl	\temp, 23
-		sll	\temp, 2
-		LONG_S	\stackp, kernelsp(\temp)
 #endif
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
 		lw	\temp, TI_CPU(gp)
 		dsll	\temp, 3
-		lui	\temp2, %hi(kernelsp)
-		daddu	\temp, \temp2
-		LONG_S	\stackp, %lo(kernelsp)(\temp)
 #endif
 #if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
-		lw	\temp, TI_CPU(gp)
-		dsll	\temp, 3
-		LONG_S	\stackp, kernelsp(\temp)
+		MFC0	\temp, CP0_CONTEXT
+		dsrl	\temp, 23
 #endif
+		LONG_S	\stackp, kernelsp(\temp)
 		.endm
 #else
 		.macro	get_saved_sp	/* Uniprocessor variation */
+#if defined(CONFIG_64BIT) && defined(CONFIG_BUILD_ELF64)
+		lui	k1, %highest(kernelsp)
+		daddiu	k1, %higher(kernelsp)
+		dsll	k1, k1, 16
+		daddiu	k1, %hi(kernelsp)
+		dsll	k1, k1, 16
+#else
 		lui	k1, %hi(kernelsp)
+#endif
 		LONG_L	k1, %lo(kernelsp)(k1)
 		.endm
 
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 6663efd..330c4e4 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -17,6 +17,7 @@
 
 #include <asm/addrspace.h>
 #include <asm/cpu-features.h>
+#include <asm/dsp.h>
 #include <asm/ptrace.h>
 #include <asm/war.h>
 #include <asm/interrupt.h>
@@ -70,7 +71,7 @@
  * does not enforce ordering, since there is no data dependency between
  * the read of "a" and the read of "b".  Therefore, on some CPUs, such
  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like thiswhere there are no data dependencies.
+ * in cases like this where there are no data dependencies.
  */
 
 #define read_barrier_depends()	do { } while(0)
@@ -154,15 +155,15 @@
 
 struct task_struct;
 
-#define switch_to(prev,next,last) \
-do { \
-	(last) = resume(prev, next, next->thread_info); \
+#define switch_to(prev,next,last)					\
+do {									\
+	if (cpu_has_dsp)						\
+		__save_dsp(prev);					\
+	(last) = resume(prev, next, next->thread_info);			\
+	if (cpu_has_dsp)						\
+		__restore_dsp(current);					\
 } while(0)
 
-#define ROT_IN_PIECES							\
-	"	.set	noreorder	\n"				\
-	"	.set	reorder		\n"
-
 static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
 {
 	__u32 retval;
@@ -171,14 +172,17 @@
 		unsigned long dummy;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%0, %3			# xchg_u32	\n"
+		"	.set	mips0					\n"
 		"	move	%2, %z4					\n"
+		"	.set	mips3					\n"
 		"	sc	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
-		ROT_IN_PIECES
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "memory");
@@ -186,13 +190,17 @@
 		unsigned long dummy;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	ll	%0, %3			# xchg_u32	\n"
+		"	.set	mips0					\n"
 		"	move	%2, %z4					\n"
+		"	.set	mips3					\n"
 		"	sc	%2, %1					\n"
 		"	beqz	%2, 1b					\n"
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "memory");
@@ -217,14 +225,15 @@
 		unsigned long dummy;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%0, %3			# xchg_u64	\n"
 		"	move	%2, %z4					\n"
 		"	scd	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
-		ROT_IN_PIECES
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "memory");
@@ -232,6 +241,7 @@
 		unsigned long dummy;
 
 		__asm__ __volatile__(
+		"	.set	mips3					\n"
 		"1:	lld	%0, %3			# xchg_u64	\n"
 		"	move	%2, %z4					\n"
 		"	scd	%2, %1					\n"
@@ -239,6 +249,7 @@
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
+		"	.set	mips0					\n"
 		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
 		: "R" (*m), "Jr" (val)
 		: "memory");
@@ -286,34 +297,41 @@
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
 		__asm__ __volatile__(
+		"	.set	push					\n"
 		"	.set	noat					\n"
+		"	.set	mips3					\n"
 		"1:	ll	%0, %2			# __cmpxchg_u32	\n"
 		"	bne	%0, %z3, 2f				\n"
+		"	.set	mips0					\n"
 		"	move	$1, %z4					\n"
+		"	.set	mips3					\n"
 		"	sc	$1, %1					\n"
 		"	beqzl	$1, 1b					\n"
-		ROT_IN_PIECES
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
 		"2:							\n"
-		"	.set	at					\n"
+		"	.set	pop					\n"
 		: "=&r" (retval), "=m" (*m)
 		: "R" (*m), "Jr" (old), "Jr" (new)
 		: "memory");
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
+		"	.set	push					\n"
 		"	.set	noat					\n"
+		"	.set	mips3					\n"
 		"1:	ll	%0, %2			# __cmpxchg_u32	\n"
 		"	bne	%0, %z3, 2f				\n"
+		"	.set	mips0					\n"
 		"	move	$1, %z4					\n"
+		"	.set	mips3					\n"
 		"	sc	$1, %1					\n"
 		"	beqz	$1, 1b					\n"
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
 		"2:							\n"
-		"	.set	at					\n"
+		"	.set	pop					\n"
 		: "=&r" (retval), "=m" (*m)
 		: "R" (*m), "Jr" (old), "Jr" (new)
 		: "memory");
@@ -338,24 +356,27 @@
 
 	if (cpu_has_llsc) {
 		__asm__ __volatile__(
+		"	.set	push					\n"
 		"	.set	noat					\n"
+		"	.set	mips3					\n"
 		"1:	lld	%0, %2			# __cmpxchg_u64	\n"
 		"	bne	%0, %z3, 2f				\n"
 		"	move	$1, %z4					\n"
 		"	scd	$1, %1					\n"
 		"	beqzl	$1, 1b					\n"
-		ROT_IN_PIECES
 #ifdef CONFIG_SMP
 		"	sync						\n"
 #endif
 		"2:							\n"
-		"	.set	at					\n"
+		"	.set	pop					\n"
 		: "=&r" (retval), "=m" (*m)
 		: "R" (*m), "Jr" (old), "Jr" (new)
 		: "memory");
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
+		"	.set	push					\n"
 		"	.set	noat					\n"
+		"	.set	mips3					\n"
 		"1:	lld	%0, %2			# __cmpxchg_u64	\n"
 		"	bne	%0, %z3, 2f				\n"
 		"	move	$1, %z4					\n"
@@ -365,7 +386,7 @@
 		"	sync						\n"
 #endif
 		"2:							\n"
-		"	.set	at					\n"
+		"	.set	pop					\n"
 		: "=&r" (retval), "=m" (*m)
 		: "R" (*m), "Jr" (old), "Jr" (new)
 		: "memory");
@@ -406,18 +427,20 @@
 
 #define cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
 
+extern void set_handler (unsigned long offset, void *addr, unsigned long len);
+extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
+extern void *set_vi_handler (int n, void *addr);
+extern void *set_vi_srs_handler (int n, void *addr, int regset);
 extern void *set_except_vector(int n, void *addr);
 extern void per_cpu_trap_init(void);
 
-extern NORET_TYPE void __die(const char *, struct pt_regs *, const char *file,
-	const char *func, unsigned long line);
-extern void __die_if_kernel(const char *, struct pt_regs *, const char *file,
-	const char *func, unsigned long line);
+extern NORET_TYPE void die(const char *, struct pt_regs *);
 
-#define die(msg, regs)							\
-	__die(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
-#define die_if_kernel(msg, regs)					\
-	__die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
+static inline void die_if_kernel(const char *str, struct pt_regs *regs)
+{
+	if (unlikely(!user_mode(regs)))
+		die(str, regs);
+}
 
 extern int stop_a_enabled;
 
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index a70cb08..e6c2447 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -26,6 +26,7 @@
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
+	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
@@ -114,6 +115,7 @@
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */
+#define TIF_SECCOMP		5	/* secure computing */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
@@ -124,13 +126,14 @@
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
-#define _TIF_WORK_MASK		0x0000ffef	/* work to do on
-                                                   interrupt/exception return */
-#define _TIF_ALLWORK_MASK	0x8000ffff	/* work to do on any return to
-                                                   u-space */
+/* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK		(0x0000ffef & ~_TIF_SECCOMP)
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK	(0x8000ffff & ~_TIF_SECCOMP)
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-mips/traps.h b/include/asm-mips/traps.h
index 1790122..d02e019 100644
--- a/include/asm-mips/traps.h
+++ b/include/asm-mips/traps.h
@@ -21,4 +21,7 @@
 extern void (*board_be_init)(void);
 extern int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 
+extern void (*board_nmi_handler_setup)(void);
+extern void (*board_ejtag_handler_setup)(void);
+
 #endif /* _ASM_TRAPS_H */
diff --git a/include/asm-mips/tx4938/rbtx4938.h b/include/asm-mips/tx4938/rbtx4938.h
new file mode 100644
index 0000000..0fbedaf
--- /dev/null
+++ b/include/asm-mips/tx4938/rbtx4938.h
@@ -0,0 +1,207 @@
+/*
+ * linux/include/asm-mips/tx4938/rbtx4938.h
+ * Definitions for TX4937/TX4938
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#ifndef __ASM_TX_BOARDS_RBTX4938_H
+#define __ASM_TX_BOARDS_RBTX4938_H
+
+#include <asm/addrspace.h>
+#include <asm/tx4938/tx4938.h>
+
+/* CS */
+#define RBTX4938_CE0	0x1c000000	/* 64M */
+#define RBTX4938_CE2	0x17f00000	/* 1M */
+
+/* Address map */
+#define RBTX4938_FPGA_REG_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00000000)
+#define RBTX4938_FPGA_REV_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00000002)
+#define RBTX4938_CONFIG1_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00000004)
+#define RBTX4938_CONFIG2_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00000006)
+#define RBTX4938_CONFIG3_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00000008)
+#define RBTX4938_LED_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00001000)
+#define RBTX4938_DIPSW_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00001002)
+#define RBTX4938_BDIPSW_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00001004)
+#define RBTX4938_IMASK_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00002000)
+#define RBTX4938_IMASK2_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00002002)
+#define RBTX4938_INTPOL_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00002004)
+#define RBTX4938_ISTAT_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00002006)
+#define RBTX4938_ISTAT2_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00002008)
+#define RBTX4938_IMSTAT_ADDR	(KSEG1 + RBTX4938_CE2 + 0x0000200a)
+#define RBTX4938_IMSTAT2_ADDR	(KSEG1 + RBTX4938_CE2 + 0x0000200c)
+#define RBTX4938_SOFTINT_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00003000)
+#define RBTX4938_PIOSEL_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00005000)
+#define RBTX4938_SPICS_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00005002)
+#define RBTX4938_SFPWR_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00005008)
+#define RBTX4938_SFVOL_ADDR	(KSEG1 + RBTX4938_CE2 + 0x0000500a)
+#define RBTX4938_SOFTRESET_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00007000)
+#define RBTX4938_SOFTRESETLOCK_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00007002)
+#define RBTX4938_PCIRESET_ADDR	(KSEG1 + RBTX4938_CE2 + 0x00007004)
+#define RBTX4938_ETHER_BASE	(KSEG1 + RBTX4938_CE2 + 0x00020000)
+
+/* Ethernet port address (Jumperless Mode (W12:Open)) */
+#define RBTX4938_ETHER_ADDR	(RBTX4938_ETHER_BASE + 0x280)
+
+/* bits for ISTAT/IMASK/IMSTAT */
+#define RBTX4938_INTB_PCID	0
+#define RBTX4938_INTB_PCIC	1
+#define RBTX4938_INTB_PCIB	2
+#define RBTX4938_INTB_PCIA	3
+#define RBTX4938_INTB_RTC	4
+#define RBTX4938_INTB_ATA	5
+#define RBTX4938_INTB_MODEM	6
+#define RBTX4938_INTB_SWINT	7
+#define RBTX4938_INTF_PCID	(1 << RBTX4938_INTB_PCID)
+#define RBTX4938_INTF_PCIC	(1 << RBTX4938_INTB_PCIC)
+#define RBTX4938_INTF_PCIB	(1 << RBTX4938_INTB_PCIB)
+#define RBTX4938_INTF_PCIA	(1 << RBTX4938_INTB_PCIA)
+#define RBTX4938_INTF_RTC	(1 << RBTX4938_INTB_RTC)
+#define RBTX4938_INTF_ATA	(1 << RBTX4938_INTB_ATA)
+#define RBTX4938_INTF_MODEM	(1 << RBTX4938_INTB_MODEM)
+#define RBTX4938_INTF_SWINT	(1 << RBTX4938_INTB_SWINT)
+
+#define rbtx4938_fpga_rev_ptr	\
+	((volatile unsigned char *)RBTX4938_FPGA_REV_ADDR)
+#define rbtx4938_led_ptr	\
+	((volatile unsigned char *)RBTX4938_LED_ADDR)
+#define rbtx4938_dipsw_ptr	\
+	((volatile unsigned char *)RBTX4938_DIPSW_ADDR)
+#define rbtx4938_bdipsw_ptr	\
+	((volatile unsigned char *)RBTX4938_BDIPSW_ADDR)
+#define rbtx4938_imask_ptr	\
+	((volatile unsigned char *)RBTX4938_IMASK_ADDR)
+#define rbtx4938_imask2_ptr	\
+	((volatile unsigned char *)RBTX4938_IMASK2_ADDR)
+#define rbtx4938_intpol_ptr	\
+	((volatile unsigned char *)RBTX4938_INTPOL_ADDR)
+#define rbtx4938_istat_ptr	\
+	((volatile unsigned char *)RBTX4938_ISTAT_ADDR)
+#define rbtx4938_istat2_ptr	\
+	((volatile unsigned char *)RBTX4938_ISTAT2_ADDR)
+#define rbtx4938_imstat_ptr	\
+	((volatile unsigned char *)RBTX4938_IMSTAT_ADDR)
+#define rbtx4938_imstat2_ptr	\
+	((volatile unsigned char *)RBTX4938_IMSTAT2_ADDR)
+#define rbtx4938_softint_ptr	\
+	((volatile unsigned char *)RBTX4938_SOFTINT_ADDR)
+#define rbtx4938_piosel_ptr	\
+	((volatile unsigned char *)RBTX4938_PIOSEL_ADDR)
+#define rbtx4938_spics_ptr	\
+	((volatile unsigned char *)RBTX4938_SPICS_ADDR)
+#define rbtx4938_sfpwr_ptr	\
+	((volatile unsigned char *)RBTX4938_SFPWR_ADDR)
+#define rbtx4938_sfvol_ptr	\
+	((volatile unsigned char *)RBTX4938_SFVOL_ADDR)
+#define rbtx4938_softreset_ptr	\
+	((volatile unsigned char *)RBTX4938_SOFTRESET_ADDR)
+#define rbtx4938_softresetlock_ptr	\
+	((volatile unsigned char *)RBTX4938_SOFTRESETLOCK_ADDR)
+#define rbtx4938_pcireset_ptr	\
+	((volatile unsigned char *)RBTX4938_PCIRESET_ADDR)
+
+/* SPI */
+#define RBTX4938_SEEPROM1_CHIPID	0
+#define RBTX4938_SEEPROM2_CHIPID	1
+#define RBTX4938_SEEPROM3_CHIPID	2
+#define RBTX4938_SRTC_CHIPID	3
+
+/*
+ * IRQ mappings
+ */
+
+#define RBTX4938_SOFT_INT0	0	/* not used */
+#define RBTX4938_SOFT_INT1	1	/* not used */
+#define RBTX4938_IRC_INT	2
+#define RBTX4938_TIMER_INT	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 RBTX4938 machine.  Add new 'spaces' as new
+ * IRQ hardware is supported.
+ */
+#define RBTX4938_NR_IRQ_LOCAL	8
+#define RBTX4938_NR_IRQ_IRC	32	/* On-Chip IRC */
+#define RBTX4938_NR_IRQ_IOC	8
+
+#define MI8259_IRQ_ISA_RAW_BEG   0	/* optional backplane i8259 */
+#define MI8259_IRQ_ISA_RAW_END  15
+#define TX4938_IRQ_CP0_RAW_BEG   0	/* tx4938 cpu built-in cp0 */
+#define TX4938_IRQ_CP0_RAW_END   7
+#define TX4938_IRQ_PIC_RAW_BEG   0	/* tx4938 cpu build-in pic */
+#define TX4938_IRQ_PIC_RAW_END  31
+
+#define MI8259_IRQ_ISA_BEG                          MI8259_IRQ_ISA_RAW_BEG	/*  0 */
+#define MI8259_IRQ_ISA_END                          MI8259_IRQ_ISA_RAW_END	/* 15 */
+
+#define TX4938_IRQ_CP0_BEG  ((MI8259_IRQ_ISA_END+1)+TX4938_IRQ_CP0_RAW_BEG)	/* 16 */
+#define TX4938_IRQ_CP0_END  ((MI8259_IRQ_ISA_END+1)+TX4938_IRQ_CP0_RAW_END)	/* 23 */
+
+#define TX4938_IRQ_PIC_BEG  ((TX4938_IRQ_CP0_END+1)+TX4938_IRQ_PIC_RAW_BEG)	/* 24 */
+#define TX4938_IRQ_PIC_END  ((TX4938_IRQ_CP0_END+1)+TX4938_IRQ_PIC_RAW_END)	/* 55 */
+#define TX4938_IRQ_NEST_EXT_ON_PIC  (TX4938_IRQ_PIC_BEG+2)
+#define TX4938_IRQ_NEST_PIC_ON_CP0  (TX4938_IRQ_CP0_BEG+2)
+#define TX4938_IRQ_USER0            (TX4938_IRQ_CP0_BEG+0)
+#define TX4938_IRQ_USER1            (TX4938_IRQ_CP0_BEG+1)
+#define TX4938_IRQ_CPU_TIMER        (TX4938_IRQ_CP0_BEG+7)
+
+#define TOSHIBA_RBTX4938_IRQ_IOC_RAW_BEG   0
+#define TOSHIBA_RBTX4938_IRQ_IOC_RAW_END   7
+
+#define TOSHIBA_RBTX4938_IRQ_IOC_BEG  ((TX4938_IRQ_PIC_END+1)+TOSHIBA_RBTX4938_IRQ_IOC_RAW_BEG) /* 56 */
+#define TOSHIBA_RBTX4938_IRQ_IOC_END  ((TX4938_IRQ_PIC_END+1)+TOSHIBA_RBTX4938_IRQ_IOC_RAW_END) /* 63 */
+#define RBTX4938_IRQ_LOCAL	TX4938_IRQ_CP0_BEG
+#define RBTX4938_IRQ_IRC	(RBTX4938_IRQ_LOCAL + RBTX4938_NR_IRQ_LOCAL)
+#define RBTX4938_IRQ_IOC	(RBTX4938_IRQ_IRC + RBTX4938_NR_IRQ_IRC)
+#define RBTX4938_IRQ_END	(RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC)
+
+#define RBTX4938_IRQ_LOCAL_SOFT0	(RBTX4938_IRQ_LOCAL + RBTX4938_SOFT_INT0)
+#define RBTX4938_IRQ_LOCAL_SOFT1	(RBTX4938_IRQ_LOCAL + RBTX4938_SOFT_INT1)
+#define RBTX4938_IRQ_LOCAL_IRC	(RBTX4938_IRQ_LOCAL + RBTX4938_IRC_INT)
+#define RBTX4938_IRQ_LOCAL_TIMER	(RBTX4938_IRQ_LOCAL + RBTX4938_TIMER_INT)
+#define RBTX4938_IRQ_IRC_ECCERR	(RBTX4938_IRQ_IRC + TX4938_IR_ECCERR)
+#define RBTX4938_IRQ_IRC_WTOERR	(RBTX4938_IRQ_IRC + TX4938_IR_WTOERR)
+#define RBTX4938_IRQ_IRC_INT(n)	(RBTX4938_IRQ_IRC + TX4938_IR_INT(n))
+#define RBTX4938_IRQ_IRC_SIO(n)	(RBTX4938_IRQ_IRC + TX4938_IR_SIO(n))
+#define RBTX4938_IRQ_IRC_DMA(ch,n)	(RBTX4938_IRQ_IRC + TX4938_IR_DMA(ch,n))
+#define RBTX4938_IRQ_IRC_PIO	(RBTX4938_IRQ_IRC + TX4938_IR_PIO)
+#define RBTX4938_IRQ_IRC_PDMAC	(RBTX4938_IRQ_IRC + TX4938_IR_PDMAC)
+#define RBTX4938_IRQ_IRC_PCIC	(RBTX4938_IRQ_IRC + TX4938_IR_PCIC)
+#define RBTX4938_IRQ_IRC_TMR(n)	(RBTX4938_IRQ_IRC + TX4938_IR_TMR(n))
+#define RBTX4938_IRQ_IRC_NDFMC	(RBTX4938_IRQ_IRC + TX4938_IR_NDFMC)
+#define RBTX4938_IRQ_IRC_PCIERR	(RBTX4938_IRQ_IRC + TX4938_IR_PCIERR)
+#define RBTX4938_IRQ_IRC_PCIPME	(RBTX4938_IRQ_IRC + TX4938_IR_PCIPME)
+#define RBTX4938_IRQ_IRC_ACLC	(RBTX4938_IRQ_IRC + TX4938_IR_ACLC)
+#define RBTX4938_IRQ_IRC_ACLCPME	(RBTX4938_IRQ_IRC + TX4938_IR_ACLCPME)
+#define RBTX4938_IRQ_IRC_PCIC1	(RBTX4938_IRQ_IRC + TX4938_IR_PCIC1)
+#define RBTX4938_IRQ_IRC_SPI	(RBTX4938_IRQ_IRC + TX4938_IR_SPI)
+#define RBTX4938_IRQ_IOC_PCID	(RBTX4938_IRQ_IOC + RBTX4938_INTB_PCID)
+#define RBTX4938_IRQ_IOC_PCIC	(RBTX4938_IRQ_IOC + RBTX4938_INTB_PCIC)
+#define RBTX4938_IRQ_IOC_PCIB	(RBTX4938_IRQ_IOC + RBTX4938_INTB_PCIB)
+#define RBTX4938_IRQ_IOC_PCIA	(RBTX4938_IRQ_IOC + RBTX4938_INTB_PCIA)
+#define RBTX4938_IRQ_IOC_RTC	(RBTX4938_IRQ_IOC + RBTX4938_INTB_RTC)
+#define RBTX4938_IRQ_IOC_ATA	(RBTX4938_IRQ_IOC + RBTX4938_INTB_ATA)
+#define RBTX4938_IRQ_IOC_MODEM	(RBTX4938_IRQ_IOC + RBTX4938_INTB_MODEM)
+#define RBTX4938_IRQ_IOC_SWINT	(RBTX4938_IRQ_IOC + RBTX4938_INTB_SWINT)
+
+
+/* IOC (PCI, etc) */
+#define RBTX4938_IRQ_IOCINT	(TX4938_IRQ_NEST_EXT_ON_PIC)
+/* Onboard 10M Ether */
+#define RBTX4938_IRQ_ETHER	(TX4938_IRQ_NEST_EXT_ON_PIC + 1)
+
+#define RBTX4938_RTL_8019_BASE (RBTX4938_ETHER_ADDR - mips_io_port_base)
+#define RBTX4938_RTL_8019_IRQ  (RBTX4938_IRQ_ETHER)
+
+/* IRCR : Int. Control */
+#define TX4938_IRCR_LOW  0x00000000
+#define TX4938_IRCR_HIGH 0x00000001
+#define TX4938_IRCR_DOWN 0x00000002
+#define TX4938_IRCR_UP   0x00000003
+
+#endif /* __ASM_TX_BOARDS_RBTX4938_H */
diff --git a/include/asm-mips/tx4938/spi.h b/include/asm-mips/tx4938/spi.h
new file mode 100644
index 0000000..0dbbab8
--- /dev/null
+++ b/include/asm-mips/tx4938/spi.h
@@ -0,0 +1,74 @@
+/*
+ * linux/include/asm-mips/tx4938/spi.h
+ * Definitions for TX4937/TX4938 SPI
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#ifndef __ASM_TX_BOARDS_TX4938_SPI_H
+#define __ASM_TX_BOARDS_TX4938_SPI_H
+
+/* SPI */
+struct spi_dev_desc {
+	unsigned int baud;
+	unsigned short tcss, tcsh, tcsr; /* CS setup/hold/recovery time */
+	unsigned int byteorder:1;	/* 0:LSB-First, 1:MSB-First */
+	unsigned int polarity:1;	/* 0:High-Active */
+	unsigned int phase:1;		/* 0:Sample-Then-Shift */
+};
+
+extern void txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)) __init;
+extern void txx9_spi_irqinit(int irc_irq) __init;
+extern int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
+		       unsigned char **inbufs, unsigned int *incounts,
+		       unsigned char **outbufs, unsigned int *outcounts,
+		       int cansleep);
+extern int spi_eeprom_write_enable(int chipid, int enable);
+extern int spi_eeprom_read_status(int chipid);
+extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
+extern int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len);
+extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) __init;
+
+#define TXX9_IMCLK     (txx9_gbus_clock / 2)
+
+/*
+* SPI
+*/
+
+/* SPMCR : SPI Master Control */
+#define TXx9_SPMCR_OPMODE	0xc0
+#define TXx9_SPMCR_CONFIG	0x40
+#define TXx9_SPMCR_ACTIVE	0x80
+#define TXx9_SPMCR_SPSTP	0x02
+#define TXx9_SPMCR_BCLR	0x01
+
+/* SPCR0 : SPI Status */
+#define TXx9_SPCR0_TXIFL_MASK	0xc000
+#define TXx9_SPCR0_RXIFL_MASK	0x3000
+#define TXx9_SPCR0_SIDIE	0x0800
+#define TXx9_SPCR0_SOEIE	0x0400
+#define TXx9_SPCR0_RBSIE	0x0200
+#define TXx9_SPCR0_TBSIE	0x0100
+#define TXx9_SPCR0_IFSPSE	0x0010
+#define TXx9_SPCR0_SBOS	0x0004
+#define TXx9_SPCR0_SPHA	0x0002
+#define TXx9_SPCR0_SPOL	0x0001
+
+/* SPSR : SPI Status */
+#define TXx9_SPSR_TBSI	0x8000
+#define TXx9_SPSR_RBSI	0x4000
+#define TXx9_SPSR_TBS_MASK	0x3800
+#define TXx9_SPSR_RBS_MASK	0x0700
+#define TXx9_SPSR_SPOE	0x0080
+#define TXx9_SPSR_IFSD	0x0008
+#define TXx9_SPSR_SIDLE	0x0004
+#define TXx9_SPSR_STRDY	0x0002
+#define TXx9_SPSR_SRRDY	0x0001
+
+#endif /* __ASM_TX_BOARDS_TX4938_SPI_H */
diff --git a/include/asm-mips/tx4938/tx4938.h b/include/asm-mips/tx4938/tx4938.h
new file mode 100644
index 0000000..e25b1a0
--- /dev/null
+++ b/include/asm-mips/tx4938/tx4938.h
@@ -0,0 +1,706 @@
+/*
+ * linux/include/asm-mips/tx4938/tx4938.h
+ * Definitions for TX4937/TX4938
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#ifndef __ASM_TX_BOARDS_TX4938_H
+#define __ASM_TX_BOARDS_TX4938_H
+
+#include <asm/tx4938/tx4938_mips.h>
+
+#define tx4938_read_nfmc(addr) (*(volatile unsigned int *)(addr))
+#define tx4938_write_nfmc(b,addr) (*(volatile unsigned int *)(addr)) = (b)
+
+#define TX4938_NR_IRQ_LOCAL     TX4938_IRQ_PIC_BEG
+
+#define TX4938_IRQ_IRC_PCIC     (TX4938_NR_IRQ_LOCAL + TX4938_IR_PCIC)
+#define TX4938_IRQ_IRC_PCIERR   (TX4938_NR_IRQ_LOCAL + TX4938_IR_PCIERR)
+
+#define TX4938_PCIIO_0 0x10000000
+#define TX4938_PCIIO_1 0x01010000
+#define TX4938_PCIMEM_0 0x08000000
+#define TX4938_PCIMEM_1 0x11000000
+
+#define TX4938_PCIIO_SIZE_0 0x01000000
+#define TX4938_PCIIO_SIZE_1 0x00010000
+#define TX4938_PCIMEM_SIZE_0 0x08000000
+#define TX4938_PCIMEM_SIZE_1 0x00010000
+
+#define TX4938_REG_BASE	0xff1f0000 /* == TX4937_REG_BASE */
+#define TX4938_REG_SIZE	0x00010000 /* == TX4937_REG_SIZE */
+
+/* NDFMC, SRAMC, PCIC1, SPIC: TX4938 only */
+#define TX4938_NDFMC_REG	(TX4938_REG_BASE + 0x5000)
+#define TX4938_SRAMC_REG	(TX4938_REG_BASE + 0x6000)
+#define TX4938_PCIC1_REG	(TX4938_REG_BASE + 0x7000)
+#define TX4938_SDRAMC_REG	(TX4938_REG_BASE + 0x8000)
+#define TX4938_EBUSC_REG	(TX4938_REG_BASE + 0x9000)
+#define TX4938_DMA_REG(ch)	(TX4938_REG_BASE + 0xb000 + (ch) * 0x800)
+#define TX4938_PCIC_REG		(TX4938_REG_BASE + 0xd000)
+#define TX4938_CCFG_REG		(TX4938_REG_BASE + 0xe000)
+#define TX4938_NR_TMR	3
+#define TX4938_TMR_REG(ch)	((TX4938_REG_BASE + 0xf000) + (ch) * 0x100)
+#define TX4938_NR_SIO	2
+#define TX4938_SIO_REG(ch)	((TX4938_REG_BASE + 0xf300) + (ch) * 0x100)
+#define TX4938_PIO_REG		(TX4938_REG_BASE + 0xf500)
+#define TX4938_IRC_REG		(TX4938_REG_BASE + 0xf600)
+#define TX4938_ACLC_REG		(TX4938_REG_BASE + 0xf700)
+#define TX4938_SPI_REG		(TX4938_REG_BASE + 0xf800)
+
+#ifndef _LANGUAGE_ASSEMBLY
+#include <asm/byteorder.h>
+
+#define TX4938_MKA(x) ((u32)( ((u32)(TX4938_REG_BASE)) | ((u32)(x)) ))
+
+#define TX4938_RD08( reg      )   (*(vu08*)(reg))
+#define TX4938_WR08( reg, val )  ((*(vu08*)(reg))=(val))
+
+#define TX4938_RD16( reg      )   (*(vu16*)(reg))
+#define TX4938_WR16( reg, val )  ((*(vu16*)(reg))=(val))
+
+#define TX4938_RD32( reg      )   (*(vu32*)(reg))
+#define TX4938_WR32( reg, val )  ((*(vu32*)(reg))=(val))
+
+#define TX4938_RD64( reg      )   (*(vu64*)(reg))
+#define TX4938_WR64( reg, val )  ((*(vu64*)(reg))=(val))
+
+#define TX4938_RD( reg      ) TX4938_RD32( reg )
+#define TX4938_WR( reg, val ) TX4938_WR32( reg, val )
+
+#endif /* !__ASSEMBLY__ */
+
+#ifdef __ASSEMBLY__
+#define _CONST64(c)	c
+#else
+#define _CONST64(c)	c##ull
+
+#include <asm/byteorder.h>
+
+#ifdef __BIG_ENDIAN
+#define endian_def_l2(e1,e2)	\
+	volatile unsigned long e1,e2
+#define endian_def_s2(e1,e2)	\
+	volatile unsigned short e1,e2
+#define endian_def_sb2(e1,e2,e3)	\
+	volatile unsigned short e1;volatile unsigned char e2,e3
+#define endian_def_b2s(e1,e2,e3)	\
+	volatile unsigned char e1,e2;volatile unsigned short e3
+#define endian_def_b4(e1,e2,e3,e4)	\
+	volatile unsigned char e1,e2,e3,e4
+#else
+#define endian_def_l2(e1,e2)	\
+	volatile unsigned long e2,e1
+#define endian_def_s2(e1,e2)	\
+	volatile unsigned short e2,e1
+#define endian_def_sb2(e1,e2,e3)	\
+	volatile unsigned char e3,e2;volatile unsigned short e1
+#define endian_def_b2s(e1,e2,e3)	\
+	volatile unsigned short e3;volatile unsigned char e2,e1
+#define endian_def_b4(e1,e2,e3,e4)	\
+	volatile unsigned char e4,e3,e2,e1
+#endif
+
+
+struct tx4938_sdramc_reg {
+	volatile unsigned long long cr[4];
+	volatile unsigned long long unused0[4];
+	volatile unsigned long long tr;
+	volatile unsigned long long unused1[2];
+	volatile unsigned long long cmd;
+	volatile unsigned long long sfcmd;
+};
+
+struct tx4938_ebusc_reg {
+	volatile unsigned long long cr[8];
+};
+
+struct tx4938_dma_reg {
+	struct tx4938_dma_ch_reg {
+		volatile unsigned long long cha;
+		volatile unsigned long long sar;
+		volatile unsigned long long dar;
+		endian_def_l2(unused0, cntr);
+		endian_def_l2(unused1, sair);
+		endian_def_l2(unused2, dair);
+		endian_def_l2(unused3, ccr);
+		endian_def_l2(unused4, csr);
+	} ch[4];
+	volatile unsigned long long dbr[8];
+	volatile unsigned long long tdhr;
+	volatile unsigned long long midr;
+	endian_def_l2(unused0, mcr);
+};
+
+struct tx4938_pcic_reg {
+	volatile unsigned long pciid;
+	volatile unsigned long pcistatus;
+	volatile unsigned long pciccrev;
+	volatile unsigned long pcicfg1;
+	volatile unsigned long p2gm0plbase;		/* +10 */
+	volatile unsigned long p2gm0pubase;
+	volatile unsigned long p2gm1plbase;
+	volatile unsigned long p2gm1pubase;
+	volatile unsigned long p2gm2pbase;		/* +20 */
+	volatile unsigned long p2giopbase;
+	volatile unsigned long unused0;
+	volatile unsigned long pcisid;
+	volatile unsigned long unused1;		/* +30 */
+	volatile unsigned long pcicapptr;
+	volatile unsigned long unused2;
+	volatile unsigned long pcicfg2;
+	volatile unsigned long g2ptocnt;		/* +40 */
+	volatile unsigned long unused3[15];
+	volatile unsigned long g2pstatus;		/* +80 */
+	volatile unsigned long g2pmask;
+	volatile unsigned long pcisstatus;
+	volatile unsigned long pcimask;
+	volatile unsigned long p2gcfg;		/* +90 */
+	volatile unsigned long p2gstatus;
+	volatile unsigned long p2gmask;
+	volatile unsigned long p2gccmd;
+	volatile unsigned long unused4[24];		/* +a0 */
+	volatile unsigned long pbareqport;		/* +100 */
+	volatile unsigned long pbacfg;
+	volatile unsigned long pbastatus;
+	volatile unsigned long pbamask;
+	volatile unsigned long pbabm;		/* +110 */
+	volatile unsigned long pbacreq;
+	volatile unsigned long pbacgnt;
+	volatile unsigned long pbacstate;
+	volatile unsigned long long g2pmgbase[3];		/* +120 */
+	volatile unsigned long long g2piogbase;
+	volatile unsigned long g2pmmask[3];		/* +140 */
+	volatile unsigned long g2piomask;
+	volatile unsigned long long g2pmpbase[3];		/* +150 */
+	volatile unsigned long long g2piopbase;
+	volatile unsigned long pciccfg;		/* +170 */
+	volatile unsigned long pcicstatus;
+	volatile unsigned long pcicmask;
+	volatile unsigned long unused5;
+	volatile unsigned long long p2gmgbase[3];		/* +180 */
+	volatile unsigned long long p2giogbase;
+	volatile unsigned long g2pcfgadrs;		/* +1a0 */
+	volatile unsigned long g2pcfgdata;
+	volatile unsigned long unused6[8];
+	volatile unsigned long g2pintack;
+	volatile unsigned long g2pspc;
+	volatile unsigned long unused7[12];		/* +1d0 */
+	volatile unsigned long long pdmca;		/* +200 */
+	volatile unsigned long long pdmga;
+	volatile unsigned long long pdmpa;
+	volatile unsigned long long pdmctr;
+	volatile unsigned long long pdmcfg;		/* +220 */
+	volatile unsigned long long pdmsts;
+};
+
+struct tx4938_aclc_reg {
+	volatile unsigned long acctlen;
+	volatile unsigned long acctldis;
+	volatile unsigned long acregacc;
+	volatile unsigned long unused0;
+	volatile unsigned long acintsts;
+	volatile unsigned long acintmsts;
+	volatile unsigned long acinten;
+	volatile unsigned long acintdis;
+	volatile unsigned long acsemaph;
+	volatile unsigned long unused1[7];
+	volatile unsigned long acgpidat;
+	volatile unsigned long acgpodat;
+	volatile unsigned long acslten;
+	volatile unsigned long acsltdis;
+	volatile unsigned long acfifosts;
+	volatile unsigned long unused2[11];
+	volatile unsigned long acdmasts;
+	volatile unsigned long acdmasel;
+	volatile unsigned long unused3[6];
+	volatile unsigned long acaudodat;
+	volatile unsigned long acsurrdat;
+	volatile unsigned long accentdat;
+	volatile unsigned long aclfedat;
+	volatile unsigned long acaudiat;
+	volatile unsigned long unused4;
+	volatile unsigned long acmodoat;
+	volatile unsigned long acmodidat;
+	volatile unsigned long unused5[15];
+	volatile unsigned long acrevid;
+};
+
+
+struct tx4938_tmr_reg {
+	volatile unsigned long tcr;
+	volatile unsigned long tisr;
+	volatile unsigned long cpra;
+	volatile unsigned long cprb;
+	volatile unsigned long itmr;
+	volatile unsigned long unused0[3];
+	volatile unsigned long ccdr;
+	volatile unsigned long unused1[3];
+	volatile unsigned long pgmr;
+	volatile unsigned long unused2[3];
+	volatile unsigned long wtmr;
+	volatile unsigned long unused3[43];
+	volatile unsigned long trr;
+};
+
+struct tx4938_sio_reg {
+	volatile unsigned long lcr;
+	volatile unsigned long dicr;
+	volatile unsigned long disr;
+	volatile unsigned long cisr;
+	volatile unsigned long fcr;
+	volatile unsigned long flcr;
+	volatile unsigned long bgr;
+	volatile unsigned long tfifo;
+	volatile unsigned long rfifo;
+};
+
+struct tx4938_pio_reg {
+	volatile unsigned long dout;
+	volatile unsigned long din;
+	volatile unsigned long dir;
+	volatile unsigned long od;
+	volatile unsigned long flag[2];
+	volatile unsigned long pol;
+	volatile unsigned long intc;
+	volatile unsigned long maskcpu;
+	volatile unsigned long maskext;
+};
+struct tx4938_irc_reg {
+	volatile unsigned long cer;
+	volatile unsigned long cr[2];
+	volatile unsigned long unused0;
+	volatile unsigned long ilr[8];
+	volatile unsigned long unused1[4];
+	volatile unsigned long imr;
+	volatile unsigned long unused2[7];
+	volatile unsigned long scr;
+	volatile unsigned long unused3[7];
+	volatile unsigned long ssr;
+	volatile unsigned long unused4[7];
+	volatile unsigned long csr;
+};
+
+struct tx4938_ndfmc_reg {
+	endian_def_l2(unused0, dtr);
+	endian_def_l2(unused1, mcr);
+	endian_def_l2(unused2, sr);
+	endian_def_l2(unused3, isr);
+	endian_def_l2(unused4, imr);
+	endian_def_l2(unused5, spr);
+	endian_def_l2(unused6, rstr);
+};
+
+struct tx4938_spi_reg {
+	volatile unsigned long mcr;
+	volatile unsigned long cr0;
+	volatile unsigned long cr1;
+	volatile unsigned long fs;
+	volatile unsigned long unused1;
+	volatile unsigned long sr;
+	volatile unsigned long dr;
+	volatile unsigned long unused2;
+};
+
+struct tx4938_sramc_reg {
+	volatile unsigned long long cr;
+};
+
+struct tx4938_ccfg_reg {
+	volatile unsigned long long ccfg;
+	volatile unsigned long long crir;
+	volatile unsigned long long pcfg;
+	volatile unsigned long long tear;
+	volatile unsigned long long clkctr;
+	volatile unsigned long long unused0;
+	volatile unsigned long long garbc;
+	volatile unsigned long long unused1;
+	volatile unsigned long long unused2;
+	volatile unsigned long long ramp;
+	volatile unsigned long long unused3;
+	volatile unsigned long long jmpadr;
+};
+
+#undef endian_def_l2
+#undef endian_def_s2
+#undef endian_def_sb2
+#undef endian_def_b2s
+#undef endian_def_b4
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * NDFMC
+ */
+
+/* NDFMCR : NDFMC Mode Control */
+#define TX4938_NDFMCR_WE	0x80
+#define TX4938_NDFMCR_ECC_ALL	0x60
+#define TX4938_NDFMCR_ECC_RESET	0x60
+#define TX4938_NDFMCR_ECC_READ	0x40
+#define TX4938_NDFMCR_ECC_ON	0x20
+#define TX4938_NDFMCR_ECC_OFF	0x00
+#define TX4938_NDFMCR_CE	0x10
+#define TX4938_NDFMCR_BSPRT	0x04
+#define TX4938_NDFMCR_ALE	0x02
+#define TX4938_NDFMCR_CLE	0x01
+
+/* NDFMCR : NDFMC Status */
+#define TX4938_NDFSR_BUSY	0x80
+
+/* NDFMCR : NDFMC Reset */
+#define TX4938_NDFRSTR_RST	0x01
+
+/*
+ * IRC
+ */
+
+#define TX4938_IR_ECCERR	0
+#define TX4938_IR_WTOERR	1
+#define TX4938_NUM_IR_INT	6
+#define TX4938_IR_INT(n)	(2 + (n))
+#define TX4938_NUM_IR_SIO	2
+#define TX4938_IR_SIO(n)	(8 + (n))
+#define TX4938_NUM_IR_DMA	4
+#define TX4938_IR_DMA(ch,n)	((ch ? 27 : 10) + (n)) /* 10-13,27-30 */
+#define TX4938_IR_PIO	14
+#define TX4938_IR_PDMAC	15
+#define TX4938_IR_PCIC	16
+#define TX4938_NUM_IR_TMR	3
+#define TX4938_IR_TMR(n)	(17 + (n))
+#define TX4938_IR_NDFMC	21
+#define TX4938_IR_PCIERR	22
+#define TX4938_IR_PCIPME	23
+#define TX4938_IR_ACLC	24
+#define TX4938_IR_ACLCPME	25
+#define TX4938_IR_PCIC1	26
+#define TX4938_IR_SPI	31
+#define TX4938_NUM_IR	32
+/* multiplex */
+#define TX4938_IR_ETH0	TX4938_IR_INT(4)
+#define TX4938_IR_ETH1	TX4938_IR_INT(3)
+
+/*
+ * CCFG
+ */
+/* CCFG : Chip Configuration */
+#define TX4938_CCFG_WDRST	_CONST64(0x0000020000000000)
+#define TX4938_CCFG_WDREXEN	_CONST64(0x0000010000000000)
+#define TX4938_CCFG_BCFG_MASK	_CONST64(0x000000ff00000000)
+#define TX4938_CCFG_TINTDIS	0x01000000
+#define TX4938_CCFG_PCI66	0x00800000
+#define TX4938_CCFG_PCIMODE	0x00400000
+#define TX4938_CCFG_PCI1_66	0x00200000
+#define TX4938_CCFG_DIVMODE_MASK	0x001e0000
+#define TX4938_CCFG_DIVMODE_2	(0x4 << 17)
+#define TX4938_CCFG_DIVMODE_2_5	(0xf << 17)
+#define TX4938_CCFG_DIVMODE_3	(0x5 << 17)
+#define TX4938_CCFG_DIVMODE_4	(0x6 << 17)
+#define TX4938_CCFG_DIVMODE_4_5	(0xd << 17)
+#define TX4938_CCFG_DIVMODE_8	(0x0 << 17)
+#define TX4938_CCFG_DIVMODE_10	(0xb << 17)
+#define TX4938_CCFG_DIVMODE_12	(0x1 << 17)
+#define TX4938_CCFG_DIVMODE_16	(0x2 << 17)
+#define TX4938_CCFG_DIVMODE_18	(0x9 << 17)
+#define TX4938_CCFG_BEOW	0x00010000
+#define TX4938_CCFG_WR	0x00008000
+#define TX4938_CCFG_TOE	0x00004000
+#define TX4938_CCFG_PCIXARB	0x00002000
+#define TX4938_CCFG_PCIDIVMODE_MASK	0x00001c00
+#define TX4938_CCFG_PCIDIVMODE_4	(0x1 << 10)
+#define TX4938_CCFG_PCIDIVMODE_4_5	(0x3 << 10)
+#define TX4938_CCFG_PCIDIVMODE_5	(0x5 << 10)
+#define TX4938_CCFG_PCIDIVMODE_5_5	(0x7 << 10)
+#define TX4938_CCFG_PCIDIVMODE_8	(0x0 << 10)
+#define TX4938_CCFG_PCIDIVMODE_9	(0x2 << 10)
+#define TX4938_CCFG_PCIDIVMODE_10	(0x4 << 10)
+#define TX4938_CCFG_PCIDIVMODE_11	(0x6 << 10)
+#define TX4938_CCFG_PCI1DMD	0x00000100
+#define TX4938_CCFG_SYSSP_MASK	0x000000c0
+#define TX4938_CCFG_ENDIAN	0x00000004
+#define TX4938_CCFG_HALT	0x00000002
+#define TX4938_CCFG_ACEHOLD	0x00000001
+
+/* PCFG : Pin Configuration */
+#define TX4938_PCFG_ETH0_SEL	_CONST64(0x8000000000000000)
+#define TX4938_PCFG_ETH1_SEL	_CONST64(0x4000000000000000)
+#define TX4938_PCFG_ATA_SEL	_CONST64(0x2000000000000000)
+#define TX4938_PCFG_ISA_SEL	_CONST64(0x1000000000000000)
+#define TX4938_PCFG_SPI_SEL	_CONST64(0x0800000000000000)
+#define TX4938_PCFG_NDF_SEL	_CONST64(0x0400000000000000)
+#define TX4938_PCFG_SDCLKDLY_MASK	0x30000000
+#define TX4938_PCFG_SDCLKDLY(d)	((d)<<28)
+#define TX4938_PCFG_SYSCLKEN	0x08000000
+#define TX4938_PCFG_SDCLKEN_ALL	0x07800000
+#define TX4938_PCFG_SDCLKEN(ch)	(0x00800000<<(ch))
+#define TX4938_PCFG_PCICLKEN_ALL	0x003f0000
+#define TX4938_PCFG_PCICLKEN(ch)	(0x00010000<<(ch))
+#define TX4938_PCFG_SEL2	0x00000200
+#define TX4938_PCFG_SEL1	0x00000100
+#define TX4938_PCFG_DMASEL_ALL	0x0000000f
+#define TX4938_PCFG_DMASEL0_DRQ0	0x00000000
+#define TX4938_PCFG_DMASEL0_SIO1	0x00000001
+#define TX4938_PCFG_DMASEL1_DRQ1	0x00000000
+#define TX4938_PCFG_DMASEL1_SIO1	0x00000002
+#define TX4938_PCFG_DMASEL2_DRQ2	0x00000000
+#define TX4938_PCFG_DMASEL2_SIO0	0x00000004
+#define TX4938_PCFG_DMASEL3_DRQ3	0x00000000
+#define TX4938_PCFG_DMASEL3_SIO0	0x00000008
+
+/* CLKCTR : Clock Control */
+#define TX4938_CLKCTR_NDFCKD	_CONST64(0x0001000000000000)
+#define TX4938_CLKCTR_NDFRST	_CONST64(0x0000000100000000)
+#define TX4938_CLKCTR_ETH1CKD	0x80000000
+#define TX4938_CLKCTR_ETH0CKD	0x40000000
+#define TX4938_CLKCTR_SPICKD	0x20000000
+#define TX4938_CLKCTR_SRAMCKD	0x10000000
+#define TX4938_CLKCTR_PCIC1CKD	0x08000000
+#define TX4938_CLKCTR_DMA1CKD	0x04000000
+#define TX4938_CLKCTR_ACLCKD	0x02000000
+#define TX4938_CLKCTR_PIOCKD	0x01000000
+#define TX4938_CLKCTR_DMACKD	0x00800000
+#define TX4938_CLKCTR_PCICKD	0x00400000
+#define TX4938_CLKCTR_TM0CKD	0x00100000
+#define TX4938_CLKCTR_TM1CKD	0x00080000
+#define TX4938_CLKCTR_TM2CKD	0x00040000
+#define TX4938_CLKCTR_SIO0CKD	0x00020000
+#define TX4938_CLKCTR_SIO1CKD	0x00010000
+#define TX4938_CLKCTR_ETH1RST	0x00008000
+#define TX4938_CLKCTR_ETH0RST	0x00004000
+#define TX4938_CLKCTR_SPIRST	0x00002000
+#define TX4938_CLKCTR_SRAMRST	0x00001000
+#define TX4938_CLKCTR_PCIC1RST	0x00000800
+#define TX4938_CLKCTR_DMA1RST	0x00000400
+#define TX4938_CLKCTR_ACLRST	0x00000200
+#define TX4938_CLKCTR_PIORST	0x00000100
+#define TX4938_CLKCTR_DMARST	0x00000080
+#define TX4938_CLKCTR_PCIRST	0x00000040
+#define TX4938_CLKCTR_TM0RST	0x00000010
+#define TX4938_CLKCTR_TM1RST	0x00000008
+#define TX4938_CLKCTR_TM2RST	0x00000004
+#define TX4938_CLKCTR_SIO0RST	0x00000002
+#define TX4938_CLKCTR_SIO1RST	0x00000001
+
+/* bits for G2PSTATUS/G2PMASK */
+#define TX4938_PCIC_G2PSTATUS_ALL	0x00000003
+#define TX4938_PCIC_G2PSTATUS_TTOE	0x00000002
+#define TX4938_PCIC_G2PSTATUS_RTOE	0x00000001
+
+/* bits for PCIMASK (see also PCI_STATUS_XXX in linux/pci.h */
+#define TX4938_PCIC_PCISTATUS_ALL	0x0000f900
+
+/* bits for PBACFG */
+#define TX4938_PCIC_PBACFG_FIXPA	0x00000008
+#define TX4938_PCIC_PBACFG_RPBA	0x00000004
+#define TX4938_PCIC_PBACFG_PBAEN	0x00000002
+#define TX4938_PCIC_PBACFG_BMCEN	0x00000001
+
+/* bits for G2PMnGBASE */
+#define TX4938_PCIC_G2PMnGBASE_BSDIS	_CONST64(0x0000002000000000)
+#define TX4938_PCIC_G2PMnGBASE_ECHG	_CONST64(0x0000001000000000)
+
+/* bits for G2PIOGBASE */
+#define TX4938_PCIC_G2PIOGBASE_BSDIS	_CONST64(0x0000002000000000)
+#define TX4938_PCIC_G2PIOGBASE_ECHG	_CONST64(0x0000001000000000)
+
+/* bits for PCICSTATUS/PCICMASK */
+#define TX4938_PCIC_PCICSTATUS_ALL	0x000007b8
+#define TX4938_PCIC_PCICSTATUS_PME	0x00000400
+#define TX4938_PCIC_PCICSTATUS_TLB	0x00000200
+#define TX4938_PCIC_PCICSTATUS_NIB	0x00000100
+#define TX4938_PCIC_PCICSTATUS_ZIB	0x00000080
+#define TX4938_PCIC_PCICSTATUS_PERR	0x00000020
+#define TX4938_PCIC_PCICSTATUS_SERR	0x00000010
+#define TX4938_PCIC_PCICSTATUS_GBE	0x00000008
+#define TX4938_PCIC_PCICSTATUS_IWB	0x00000002
+#define TX4938_PCIC_PCICSTATUS_E2PDONE	0x00000001
+
+/* bits for PCICCFG */
+#define TX4938_PCIC_PCICCFG_GBWC_MASK	0x0fff0000
+#define TX4938_PCIC_PCICCFG_HRST	0x00000800
+#define TX4938_PCIC_PCICCFG_SRST	0x00000400
+#define TX4938_PCIC_PCICCFG_IRBER	0x00000200
+#define TX4938_PCIC_PCICCFG_G2PMEN(ch)	(0x00000100>>(ch))
+#define TX4938_PCIC_PCICCFG_G2PM0EN	0x00000100
+#define TX4938_PCIC_PCICCFG_G2PM1EN	0x00000080
+#define TX4938_PCIC_PCICCFG_G2PM2EN	0x00000040
+#define TX4938_PCIC_PCICCFG_G2PIOEN	0x00000020
+#define TX4938_PCIC_PCICCFG_TCAR	0x00000010
+#define TX4938_PCIC_PCICCFG_ICAEN	0x00000008
+
+/* bits for P2GMnGBASE */
+#define TX4938_PCIC_P2GMnGBASE_TMEMEN	_CONST64(0x0000004000000000)
+#define TX4938_PCIC_P2GMnGBASE_TBSDIS	_CONST64(0x0000002000000000)
+#define TX4938_PCIC_P2GMnGBASE_TECHG	_CONST64(0x0000001000000000)
+
+/* bits for P2GIOGBASE */
+#define TX4938_PCIC_P2GIOGBASE_TIOEN	_CONST64(0x0000004000000000)
+#define TX4938_PCIC_P2GIOGBASE_TBSDIS	_CONST64(0x0000002000000000)
+#define TX4938_PCIC_P2GIOGBASE_TECHG	_CONST64(0x0000001000000000)
+
+#define TX4938_PCIC_IDSEL_AD_TO_SLOT(ad)	((ad) - 11)
+#define TX4938_PCIC_MAX_DEVNU	TX4938_PCIC_IDSEL_AD_TO_SLOT(32)
+
+/* bits for PDMCFG */
+#define TX4938_PCIC_PDMCFG_RSTFIFO	0x00200000
+#define TX4938_PCIC_PDMCFG_EXFER	0x00100000
+#define TX4938_PCIC_PDMCFG_REQDLY_MASK	0x00003800
+#define TX4938_PCIC_PDMCFG_REQDLY_NONE	(0 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_16	(1 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_32	(2 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_64	(3 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_128	(4 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_256	(5 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_512	(6 << 11)
+#define TX4938_PCIC_PDMCFG_REQDLY_1024	(7 << 11)
+#define TX4938_PCIC_PDMCFG_ERRIE	0x00000400
+#define TX4938_PCIC_PDMCFG_NCCMPIE	0x00000200
+#define TX4938_PCIC_PDMCFG_NTCMPIE	0x00000100
+#define TX4938_PCIC_PDMCFG_CHNEN	0x00000080
+#define TX4938_PCIC_PDMCFG_XFRACT	0x00000040
+#define TX4938_PCIC_PDMCFG_BSWAP	0x00000020
+#define TX4938_PCIC_PDMCFG_XFRSIZE_MASK	0x0000000c
+#define TX4938_PCIC_PDMCFG_XFRSIZE_1DW	0x00000000
+#define TX4938_PCIC_PDMCFG_XFRSIZE_1QW	0x00000004
+#define TX4938_PCIC_PDMCFG_XFRSIZE_4QW	0x00000008
+#define TX4938_PCIC_PDMCFG_XFRDIRC	0x00000002
+#define TX4938_PCIC_PDMCFG_CHRST	0x00000001
+
+/* bits for PDMSTS */
+#define TX4938_PCIC_PDMSTS_REQCNT_MASK	0x3f000000
+#define TX4938_PCIC_PDMSTS_FIFOCNT_MASK	0x00f00000
+#define TX4938_PCIC_PDMSTS_FIFOWP_MASK	0x000c0000
+#define TX4938_PCIC_PDMSTS_FIFORP_MASK	0x00030000
+#define TX4938_PCIC_PDMSTS_ERRINT	0x00000800
+#define TX4938_PCIC_PDMSTS_DONEINT	0x00000400
+#define TX4938_PCIC_PDMSTS_CHNEN	0x00000200
+#define TX4938_PCIC_PDMSTS_XFRACT	0x00000100
+#define TX4938_PCIC_PDMSTS_ACCMP	0x00000080
+#define TX4938_PCIC_PDMSTS_NCCMP	0x00000040
+#define TX4938_PCIC_PDMSTS_NTCMP	0x00000020
+#define TX4938_PCIC_PDMSTS_CFGERR	0x00000008
+#define TX4938_PCIC_PDMSTS_PCIERR	0x00000004
+#define TX4938_PCIC_PDMSTS_CHNERR	0x00000002
+#define TX4938_PCIC_PDMSTS_DATAERR	0x00000001
+#define TX4938_PCIC_PDMSTS_ALL_CMP	0x000000e0
+#define TX4938_PCIC_PDMSTS_ALL_ERR	0x0000000f
+
+/*
+ * DMA
+ */
+/* bits for MCR */
+#define TX4938_DMA_MCR_EIS(ch)	(0x10000000<<(ch))
+#define TX4938_DMA_MCR_DIS(ch)	(0x01000000<<(ch))
+#define TX4938_DMA_MCR_RSFIF	0x00000080
+#define TX4938_DMA_MCR_FIFUM(ch)	(0x00000008<<(ch))
+#define TX4938_DMA_MCR_RPRT	0x00000002
+#define TX4938_DMA_MCR_MSTEN	0x00000001
+
+/* bits for CCRn */
+#define TX4938_DMA_CCR_IMMCHN	0x20000000
+#define TX4938_DMA_CCR_USEXFSZ	0x10000000
+#define TX4938_DMA_CCR_LE	0x08000000
+#define TX4938_DMA_CCR_DBINH	0x04000000
+#define TX4938_DMA_CCR_SBINH	0x02000000
+#define TX4938_DMA_CCR_CHRST	0x01000000
+#define TX4938_DMA_CCR_RVBYTE	0x00800000
+#define TX4938_DMA_CCR_ACKPOL	0x00400000
+#define TX4938_DMA_CCR_REQPL	0x00200000
+#define TX4938_DMA_CCR_EGREQ	0x00100000
+#define TX4938_DMA_CCR_CHDN	0x00080000
+#define TX4938_DMA_CCR_DNCTL	0x00060000
+#define TX4938_DMA_CCR_EXTRQ	0x00010000
+#define TX4938_DMA_CCR_INTRQD	0x0000e000
+#define TX4938_DMA_CCR_INTENE	0x00001000
+#define TX4938_DMA_CCR_INTENC	0x00000800
+#define TX4938_DMA_CCR_INTENT	0x00000400
+#define TX4938_DMA_CCR_CHNEN	0x00000200
+#define TX4938_DMA_CCR_XFACT	0x00000100
+#define TX4938_DMA_CCR_SMPCHN	0x00000020
+#define TX4938_DMA_CCR_XFSZ(order)	(((order) << 2) & 0x0000001c)
+#define TX4938_DMA_CCR_XFSZ_1W	TX4938_DMA_CCR_XFSZ(2)
+#define TX4938_DMA_CCR_XFSZ_2W	TX4938_DMA_CCR_XFSZ(3)
+#define TX4938_DMA_CCR_XFSZ_4W	TX4938_DMA_CCR_XFSZ(4)
+#define TX4938_DMA_CCR_XFSZ_8W	TX4938_DMA_CCR_XFSZ(5)
+#define TX4938_DMA_CCR_XFSZ_16W	TX4938_DMA_CCR_XFSZ(6)
+#define TX4938_DMA_CCR_XFSZ_32W	TX4938_DMA_CCR_XFSZ(7)
+#define TX4938_DMA_CCR_MEMIO	0x00000002
+#define TX4938_DMA_CCR_SNGAD	0x00000001
+
+/* bits for CSRn */
+#define TX4938_DMA_CSR_CHNEN	0x00000400
+#define TX4938_DMA_CSR_STLXFER	0x00000200
+#define TX4938_DMA_CSR_CHNACT	0x00000100
+#define TX4938_DMA_CSR_ABCHC	0x00000080
+#define TX4938_DMA_CSR_NCHNC	0x00000040
+#define TX4938_DMA_CSR_NTRNFC	0x00000020
+#define TX4938_DMA_CSR_EXTDN	0x00000010
+#define TX4938_DMA_CSR_CFERR	0x00000008
+#define TX4938_DMA_CSR_CHERR	0x00000004
+#define TX4938_DMA_CSR_DESERR	0x00000002
+#define TX4938_DMA_CSR_SORERR	0x00000001
+
+/* TX4938 Interrupt Controller (32-bit registers) */
+#define TX4938_IRC_BASE                 0xf510
+#define TX4938_IRC_IRFLAG0              0xf510
+#define TX4938_IRC_IRFLAG1              0xf514
+#define TX4938_IRC_IRPOL                0xf518
+#define TX4938_IRC_IRRCNT               0xf51c
+#define TX4938_IRC_IRMASKINT            0xf520
+#define TX4938_IRC_IRMASKEXT            0xf524
+#define TX4938_IRC_IRDEN                0xf600
+#define TX4938_IRC_IRDM0                0xf604
+#define TX4938_IRC_IRDM1                0xf608
+#define TX4938_IRC_IRLVL0               0xf610
+#define TX4938_IRC_IRLVL1               0xf614
+#define TX4938_IRC_IRLVL2               0xf618
+#define TX4938_IRC_IRLVL3               0xf61c
+#define TX4938_IRC_IRLVL4               0xf620
+#define TX4938_IRC_IRLVL5               0xf624
+#define TX4938_IRC_IRLVL6               0xf628
+#define TX4938_IRC_IRLVL7               0xf62c
+#define TX4938_IRC_IRMSK                0xf640
+#define TX4938_IRC_IREDC                0xf660
+#define TX4938_IRC_IRPND                0xf680
+#define TX4938_IRC_IRCS                 0xf6a0
+#define TX4938_IRC_LIMIT                0xf6ff
+
+
+#ifndef __ASSEMBLY__
+
+#define tx4938_sdramcptr	((struct tx4938_sdramc_reg *)TX4938_SDRAMC_REG)
+#define tx4938_ebuscptr         ((struct tx4938_ebusc_reg *)TX4938_EBUSC_REG)
+#define tx4938_dmaptr(ch)	((struct tx4938_dma_reg *)TX4938_DMA_REG(ch))
+#define tx4938_ndfmcptr		((struct tx4938_ndfmc_reg *)TX4938_NDFMC_REG)
+#define tx4938_ircptr		((struct tx4938_irc_reg *)TX4938_IRC_REG)
+#define tx4938_pcicptr		((struct tx4938_pcic_reg *)TX4938_PCIC_REG)
+#define tx4938_pcic1ptr		((struct tx4938_pcic_reg *)TX4938_PCIC1_REG)
+#define tx4938_ccfgptr		((struct tx4938_ccfg_reg *)TX4938_CCFG_REG)
+#define tx4938_tmrptr(ch)	((struct tx4938_tmr_reg *)TX4938_TMR_REG(ch))
+#define tx4938_sioptr(ch)	((struct tx4938_sio_reg *)TX4938_SIO_REG(ch))
+#define tx4938_pioptr		((struct tx4938_pio_reg *)TX4938_PIO_REG)
+#define tx4938_aclcptr		((struct tx4938_aclc_reg *)TX4938_ACLC_REG)
+#define tx4938_spiptr		((struct tx4938_spi_reg *)TX4938_SPI_REG)
+#define tx4938_sramcptr		((struct tx4938_sramc_reg *)TX4938_SRAMC_REG)
+
+
+#define TX4938_REV_MAJ_MIN()	((unsigned long)tx4938_ccfgptr->crir & 0x00ff)
+#define TX4938_REV_PCODE()	((unsigned long)tx4938_ccfgptr->crir >> 16)
+
+#define TX4938_SDRAMC_BA(ch)	((tx4938_sdramcptr->cr[ch] >> 49) << 21)
+#define TX4938_SDRAMC_SIZE(ch)	(((tx4938_sdramcptr->cr[ch] >> 33) + 1) << 21)
+
+#define TX4938_EBUSC_BA(ch)	((tx4938_ebuscptr->cr[ch] >> 48) << 20)
+#define TX4938_EBUSC_SIZE(ch)	\
+	(0x00100000 << ((unsigned long)(tx4938_ebuscptr->cr[ch] >> 8) & 0xf))
+
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/include/asm-mips/tx4938/tx4938_mips.h b/include/asm-mips/tx4938/tx4938_mips.h
new file mode 100644
index 0000000..cf89b20
--- /dev/null
+++ b/include/asm-mips/tx4938/tx4938_mips.h
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-mips/tx4938/tx4938_bitmask.h
+ * Generic bitmask definitions
+ *
+ * 2003-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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+#ifndef TX4938_TX4938_MIPS_H
+#define TX4938_TX4938_MIPS_H
+#ifndef __ASSEMBLY__
+
+#define reg_rd08(r)    ((u8 )(*((vu8 *)(r))))
+#define reg_rd16(r)    ((u16)(*((vu16*)(r))))
+#define reg_rd32(r)    ((u32)(*((vu32*)(r))))
+#define reg_rd64(r)    ((u64)(*((vu64*)(r))))
+
+#define reg_wr08(r,v)  ((*((vu8 *)(r)))=((u8 )(v)))
+#define reg_wr16(r,v)  ((*((vu16*)(r)))=((u16)(v)))
+#define reg_wr32(r,v)  ((*((vu32*)(r)))=((u32)(v)))
+#define reg_wr64(r,v)  ((*((vu64*)(r)))=((u64)(v)))
+
+typedef volatile __signed char vs8;
+typedef volatile unsigned char vu8;
+
+typedef volatile __signed short vs16;
+typedef volatile unsigned short vu16;
+
+typedef volatile __signed int vs32;
+typedef volatile unsigned int vu32;
+
+typedef s8 s08;
+typedef vs8 vs08;
+
+typedef u8 u08;
+typedef vu8 vu08;
+
+#if (_MIPS_SZLONG == 64)
+
+typedef volatile __signed__ long vs64;
+typedef volatile unsigned long vu64;
+
+#else
+
+typedef volatile __signed__ long long vs64;
+typedef volatile unsigned long long vu64;
+
+#endif
+#endif
+#endif
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 5c2c983..41bb96b 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -196,63 +196,55 @@
 	__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
 
 struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+#define __m(x) (*(struct __large_struct __user *)(x))
 
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
  */
 #ifdef __mips64
-#define __GET_USER_DW(__gu_err) __get_user_asm("ld", __gu_err)
+#define __GET_USER_DW(ptr) __get_user_asm("ld", ptr)
 #else
-#define __GET_USER_DW(__gu_err) __get_user_asm_ll32(__gu_err)
+#define __GET_USER_DW(ptr) __get_user_asm_ll32(ptr)
 #endif
 
 #define __get_user_nocheck(x,ptr,size)					\
 ({									\
-	__typeof(*(ptr)) __gu_val = 0;					\
-	long __gu_addr;							\
+	__typeof(*(ptr)) __gu_val =  (__typeof(*(ptr))) 0;		\
 	long __gu_err = 0;						\
 									\
-	might_sleep();							\
-	__gu_addr = (long) (ptr);					\
 	switch (size) {							\
-	case 1: __get_user_asm("lb", __gu_err); break;			\
-	case 2: __get_user_asm("lh", __gu_err); break;			\
-	case 4: __get_user_asm("lw", __gu_err); break;			\
-	case 8: __GET_USER_DW(__gu_err); break;				\
+	case 1: __get_user_asm("lb", ptr); break;			\
+	case 2: __get_user_asm("lh", ptr); break;			\
+	case 4: __get_user_asm("lw", ptr); break;			\
+	case 8: __GET_USER_DW(ptr); break;				\
 	default: __get_user_unknown(); break;				\
 	}								\
-	x = (__typeof__(*(ptr))) __gu_val;				\
+	(x) = (__typeof__(*(ptr))) __gu_val;				\
 	__gu_err;							\
 })
 
 #define __get_user_check(x,ptr,size)					\
 ({									\
+	const __typeof__(*(ptr)) __user * __gu_addr = (ptr);		\
 	__typeof__(*(ptr)) __gu_val = 0;				\
-	long __gu_addr;							\
-	long __gu_err;							\
+	long __gu_err = -EFAULT;					\
 									\
-	might_sleep();							\
-	__gu_addr = (long) (ptr);					\
-	__gu_err = access_ok(VERIFY_READ, (void *) __gu_addr, size)	\
-				? 0 : -EFAULT;				\
-									\
-	if (likely(!__gu_err)) {					\
+	if (likely(access_ok(VERIFY_READ,  __gu_addr, size))) {		\
 		switch (size) {						\
-		case 1: __get_user_asm("lb", __gu_err); break;		\
-		case 2: __get_user_asm("lh", __gu_err); break;		\
-		case 4: __get_user_asm("lw", __gu_err); break;		\
-		case 8: __GET_USER_DW(__gu_err); break;			\
+		case 1: __get_user_asm("lb", __gu_addr); break;		\
+		case 2: __get_user_asm("lh", __gu_addr); break;		\
+		case 4: __get_user_asm("lw", __gu_addr); break;		\
+		case 8: __GET_USER_DW(__gu_addr); break;		\
 		default: __get_user_unknown(); break;			\
 		}							\
 	}								\
-	x = (__typeof__(*(ptr))) __gu_val;				\
+	(x) = (__typeof__(*(ptr))) __gu_val;				\
 	__gu_err;							\
 })
 
-#define __get_user_asm(insn,__gu_err)					\
-({									\
+#define __get_user_asm(insn, addr)					\
+{									\
 	__asm__ __volatile__(						\
 	"1:	" insn "	%1, %3				\n"	\
 	"2:							\n"	\
@@ -264,20 +256,20 @@
 	"	"__UA_ADDR "\t1b, 3b				\n"	\
 	"	.previous					\n"	\
 	: "=r" (__gu_err), "=r" (__gu_val)				\
-	: "0" (__gu_err), "o" (__m(__gu_addr)), "i" (-EFAULT));		\
-})
+	: "0" (0), "o" (__m(addr)), "i" (-EFAULT));			\
+}
 
 /*
  * Get a long long 64 using 32 bit registers.
  */
-#define __get_user_asm_ll32(__gu_err)					\
-({									\
+#define __get_user_asm_ll32(addr)					\
+{									\
 	__asm__ __volatile__(						\
-	"1:	lw	%1, %3					\n"	\
-	"2:	lw	%D1, %4					\n"	\
+	"1:	lw	%1, (%3)				\n"	\
+	"2:	lw	%D1, 4(%3)				\n"	\
 	"	move	%0, $0					\n"	\
 	"3:	.section	.fixup,\"ax\"			\n"	\
-	"4:	li	%0, %5					\n"	\
+	"4:	li	%0, %4					\n"	\
 	"	move	%1, $0					\n"	\
 	"	move	%D1, $0					\n"	\
 	"	j	3b					\n"	\
@@ -287,9 +279,8 @@
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous					\n"	\
 	: "=r" (__gu_err), "=&r" (__gu_val)				\
-	: "0" (__gu_err), "o" (__m(__gu_addr)),				\
-	  "o" (__m(__gu_addr + 4)), "i" (-EFAULT));			\
-})
+	: "0" (0), "r" (addr), "i" (-EFAULT));				\
+}
 
 extern void __get_user_unknown(void);
 
@@ -298,25 +289,22 @@
  * for 32 bit mode and old iron.
  */
 #ifdef __mips64
-#define __PUT_USER_DW(__pu_val) __put_user_asm("sd", __pu_val)
+#define __PUT_USER_DW(ptr) __put_user_asm("sd", ptr)
 #else
-#define __PUT_USER_DW(__pu_val) __put_user_asm_ll32(__pu_val)
+#define __PUT_USER_DW(ptr) __put_user_asm_ll32(ptr)
 #endif
 
 #define __put_user_nocheck(x,ptr,size)					\
 ({									\
 	__typeof__(*(ptr)) __pu_val;					\
-	long __pu_addr;							\
 	long __pu_err = 0;						\
 									\
-	might_sleep();							\
 	__pu_val = (x);							\
-	__pu_addr = (long) (ptr);					\
 	switch (size) {							\
-	case 1: __put_user_asm("sb", __pu_val); break;			\
-	case 2: __put_user_asm("sh", __pu_val); break;			\
-	case 4: __put_user_asm("sw", __pu_val); break;			\
-	case 8: __PUT_USER_DW(__pu_val); break;				\
+	case 1: __put_user_asm("sb", ptr); break;			\
+	case 2: __put_user_asm("sh", ptr); break;			\
+	case 4: __put_user_asm("sw", ptr); break;			\
+	case 8: __PUT_USER_DW(ptr); break;				\
 	default: __put_user_unknown(); break;				\
 	}								\
 	__pu_err;							\
@@ -324,30 +312,24 @@
 
 #define __put_user_check(x,ptr,size)					\
 ({									\
-	__typeof__(*(ptr)) __pu_val;					\
-	long __pu_addr;							\
-	long __pu_err;							\
+	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
+	__typeof__(*(ptr)) __pu_val = (x);				\
+	long __pu_err = -EFAULT;					\
 									\
-	might_sleep();							\
-	__pu_val = (x);							\
-	__pu_addr = (long) (ptr);					\
-	__pu_err = access_ok(VERIFY_WRITE, (void *) __pu_addr, size)	\
-				? 0 : -EFAULT;				\
-									\
-	if (likely(!__pu_err)) {					\
+	if (likely(access_ok(VERIFY_WRITE,  __pu_addr, size))) {	\
 		switch (size) {						\
-		case 1: __put_user_asm("sb", __pu_val); break;		\
-		case 2: __put_user_asm("sh", __pu_val); break;		\
-		case 4: __put_user_asm("sw", __pu_val); break;		\
-		case 8: __PUT_USER_DW(__pu_val); break;			\
+		case 1: __put_user_asm("sb", __pu_addr); break;		\
+		case 2: __put_user_asm("sh", __pu_addr); break;		\
+		case 4: __put_user_asm("sw", __pu_addr); break;		\
+		case 8: __PUT_USER_DW(__pu_addr); break;		\
 		default: __put_user_unknown(); break;			\
 		}							\
 	}								\
 	__pu_err;							\
 })
 
-#define __put_user_asm(insn, __pu_val)					\
-({									\
+#define __put_user_asm(insn, ptr)					\
+{									\
 	__asm__ __volatile__(						\
 	"1:	" insn "	%z2, %3		# __put_user_asm\n"	\
 	"2:							\n"	\
@@ -359,18 +341,18 @@
 	"	" __UA_ADDR "	1b, 3b				\n"	\
 	"	.previous					\n"	\
 	: "=r" (__pu_err)						\
-	: "0" (__pu_err), "Jr" (__pu_val), "o" (__m(__pu_addr)),	\
+	: "0" (0), "Jr" (__pu_val), "o" (__m(ptr)),			\
 	  "i" (-EFAULT));						\
-})
+}
 
-#define __put_user_asm_ll32(__pu_val)					\
-({									\
+#define __put_user_asm_ll32(ptr)					\
+{									\
 	__asm__ __volatile__(						\
-	"1:	sw	%2, %3		# __put_user_asm_ll32	\n"	\
-	"2:	sw	%D2, %4					\n"	\
+	"1:	sw	%2, (%3)	# __put_user_asm_ll32	\n"	\
+	"2:	sw	%D2, 4(%3)				\n"	\
 	"3:							\n"	\
 	"	.section	.fixup,\"ax\"			\n"	\
-	"4:	li	%0, %5					\n"	\
+	"4:	li	%0, %4					\n"	\
 	"	j	3b					\n"	\
 	"	.previous					\n"	\
 	"	.section	__ex_table,\"a\"		\n"	\
@@ -378,9 +360,9 @@
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous"						\
 	: "=r" (__pu_err)						\
-	: "0" (__pu_err), "r" (__pu_val), "o" (__m(__pu_addr)),		\
-	  "o" (__m(__pu_addr + 4)), "i" (-EFAULT));			\
-})
+	: "0" (0), "r" (__pu_val), "r" (ptr),				\
+	  "i" (-EFAULT));						\
+}
 
 extern void __put_user_unknown(void);
 
@@ -403,7 +385,7 @@
 
 #define __invoke_copy_to_user(to,from,n)				\
 ({									\
-	register void *__cu_to_r __asm__ ("$4");			\
+	register void __user *__cu_to_r __asm__ ("$4");			\
 	register const void *__cu_from_r __asm__ ("$5");		\
 	register long __cu_len_r __asm__ ("$6");			\
 									\
@@ -435,7 +417,7 @@
  */
 #define __copy_to_user(to,from,n)					\
 ({									\
-	void *__cu_to;							\
+	void __user *__cu_to;						\
 	const void *__cu_from;						\
 	long __cu_len;							\
 									\
@@ -465,7 +447,7 @@
  */
 #define copy_to_user(to,from,n)						\
 ({									\
-	void *__cu_to;							\
+	void __user *__cu_to;						\
 	const void *__cu_from;						\
 	long __cu_len;							\
 									\
@@ -482,7 +464,7 @@
 #define __invoke_copy_from_user(to,from,n)				\
 ({									\
 	register void *__cu_to_r __asm__ ("$4");			\
-	register const void *__cu_from_r __asm__ ("$5");		\
+	register const void __user *__cu_from_r __asm__ ("$5");		\
 	register long __cu_len_r __asm__ ("$6");			\
 									\
 	__cu_to_r = (to);						\
@@ -521,7 +503,7 @@
 #define __copy_from_user(to,from,n)					\
 ({									\
 	void *__cu_to;							\
-	const void *__cu_from;						\
+	const void __user *__cu_from;					\
 	long __cu_len;							\
 									\
 	might_sleep();							\
@@ -552,7 +534,7 @@
 #define copy_from_user(to,from,n)					\
 ({									\
 	void *__cu_to;							\
-	const void *__cu_from;						\
+	const void __user *__cu_from;					\
 	long __cu_len;							\
 									\
 	might_sleep();							\
@@ -569,8 +551,8 @@
 
 #define copy_in_user(to,from,n)						\
 ({									\
-	void *__cu_to;							\
-	const void *__cu_from;						\
+	void __user *__cu_to;						\
+	const void __user *__cu_from;					\
 	long __cu_len;							\
 									\
 	might_sleep();							\
@@ -596,7 +578,7 @@
  * On success, this will be zero.
  */
 static inline __kernel_size_t
-__clear_user(void *addr, __kernel_size_t size)
+__clear_user(void __user *addr, __kernel_size_t size)
 {
 	__kernel_size_t res;
 
@@ -616,7 +598,7 @@
 
 #define clear_user(addr,n)						\
 ({									\
-	void * __cl_addr = (addr);					\
+	void __user * __cl_addr = (addr);				\
 	unsigned long __cl_size = (n);					\
 	if (__cl_size && access_ok(VERIFY_WRITE,			\
 		((unsigned long)(__cl_addr)), __cl_size))		\
@@ -645,7 +627,7 @@
  * and returns @count.
  */
 static inline long
-__strncpy_from_user(char *__to, const char *__from, long __len)
+__strncpy_from_user(char *__to, const char __user *__from, long __len)
 {
 	long res;
 
@@ -682,7 +664,7 @@
  * and returns @count.
  */
 static inline long
-strncpy_from_user(char *__to, const char *__from, long __len)
+strncpy_from_user(char *__to, const char __user *__from, long __len)
 {
 	long res;
 
@@ -701,7 +683,7 @@
 }
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-static inline long __strlen_user(const char *s)
+static inline long __strlen_user(const char __user *s)
 {
 	long res;
 
@@ -731,7 +713,7 @@
  * If there is a limit on the length of a valid string, you may wish to
  * consider using strnlen_user() instead.
  */
-static inline long strlen_user(const char *s)
+static inline long strlen_user(const char __user *s)
 {
 	long res;
 
@@ -748,7 +730,7 @@
 }
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-static inline long __strnlen_user(const char *s, long n)
+static inline long __strnlen_user(const char __user *s, long n)
 {
 	long res;
 
@@ -779,7 +761,7 @@
  * If there is a limit on the length of a valid string, you may wish to
  * consider using strnlen_user() instead.
  */
-static inline long strnlen_user(const char *s, long n)
+static inline long strnlen_user(const char __user *s, long n)
 {
 	long res;
 
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index ad4d480..89ea8b6 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -303,16 +303,21 @@
 #define __NR_add_key			(__NR_Linux + 280)
 #define __NR_request_key		(__NR_Linux + 281)
 #define __NR_keyctl			(__NR_Linux + 282)
+#define __NR_set_thread_area		(__NR_Linux + 283)
+#define __NR_inotify_init		(__NR_Linux + 284)
+#define __NR_inotify_add_watch		(__NR_Linux + 285)
+#define __NR_inotify_rm_watch		(__NR_Linux + 286)
+
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		282
+#define __NR_Linux_syscalls		286
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		282
+#define __NR_O32_Linux_syscalls		283
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -562,16 +567,20 @@
 #define __NR_add_key			(__NR_Linux + 239)
 #define __NR_request_key		(__NR_Linux + 240)
 #define __NR_keyctl			(__NR_Linux + 241)
+#define __NR_set_thread_area		(__NR_Linux + 242)
+#define __NR_inotify_init		(__NR_Linux + 243)
+#define __NR_inotify_add_watch		(__NR_Linux + 244)
+#define __NR_inotify_rm_watch		(__NR_Linux + 245)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		241
+#define __NR_Linux_syscalls		245
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		241
+#define __NR_64_Linux_syscalls		242
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -825,16 +834,20 @@
 #define __NR_add_key			(__NR_Linux + 243)
 #define __NR_request_key		(__NR_Linux + 244)
 #define __NR_keyctl			(__NR_Linux + 245)
+#define __NR_set_thread_area		(__NR_Linux + 246)
+#define __NR_inotify_init		(__NR_Linux + 247)
+#define __NR_inotify_add_watch		(__NR_Linux + 248)
+#define __NR_inotify_rm_watch		(__NR_Linux + 249)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		245
+#define __NR_Linux_syscalls		249
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		245
+#define __NR_N32_Linux_syscalls		246
 
 #ifndef __ASSEMBLY__
 
@@ -1164,7 +1177,6 @@
 			unsigned long fd, unsigned long pgoff);
 asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs);
 asmlinkage int sys_pipe(nabi_no_regargs struct pt_regs regs);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-mips/vga.h b/include/asm-mips/vga.h
index 6b35cf0..ca5cec9 100644
--- a/include/asm-mips/vga.h
+++ b/include/asm-mips/vga.h
@@ -6,6 +6,8 @@
 #ifndef _ASM_VGA_H
 #define _ASM_VGA_H
 
+#include <asm/byteorder.h>
+
 /*
  *	On the PC, we can just recalculate addresses and then
  *	access the videoram directly without any black magic.
@@ -16,4 +18,27 @@
 #define vga_readb(x)	(*(x))
 #define vga_writeb(x,y)	(*(y) = (x))
 
+#define VT_BUF_HAVE_RW
+/*
+ *  These are only needed for supporting VGA or MDA text mode, which use little
+ *  endian byte ordering.
+ *  In other cases, we can optimize by using native byte ordering and
+ *  <linux/vt_buffer.h> has already done the right job for us.
+ */
+
+static inline void scr_writew(u16 val, volatile u16 *addr)
+{
+	*addr = cpu_to_le16(val);
+}
+
+static inline u16 scr_readw(volatile const u16 *addr)
+{
+	return le16_to_cpu(*addr);
+}
+
+#define scr_memcpyw(d, s, c) memcpy(d, s, c)
+#define scr_memmovew(d, s, c) memmove(d, s, c)
+#define VT_BUF_HAVE_MEMCPYW
+#define VT_BUF_HAVE_MEMMOVEW
+
 #endif /* _ASM_VGA_H */
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index 04ee53b..ad374bd 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -177,6 +177,17 @@
 #endif
 
 /*
+ * The RM9000 has a bug (though PMC-Sierra opposes it being called that)
+ * where invalid instructions in the same I-cache line worth of instructions
+ * being fetched may case spurious exceptions.
+ */
+#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
+    defined(CONFIG_PMC_YOSEMITE)
+#define ICACHE_REFILLS_WORKAROUND_WAR	1
+#endif
+
+
+/*
  * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
  * may cause ll / sc and lld / scd sequences to execute non-atomically.
  */
@@ -187,6 +198,9 @@
 /*
  * Workarounds default to off
  */
+#ifndef ICACHE_REFILLS_WORKAROUND_WAR
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#endif
 #ifndef R4600_V1_INDEX_ICACHEOP_WAR
 #define R4600_V1_INDEX_ICACHEOP_WAR	0
 #endif
diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h
index 30b0234..3ce3440 100644
--- a/include/asm-parisc/assembly.h
+++ b/include/asm-parisc/assembly.h
@@ -21,7 +21,9 @@
 #ifndef _PARISC_ASSEMBLY_H
 #define _PARISC_ASSEMBLY_H
 
-#ifdef __LP64__
+#define CALLEE_FLOAT_FRAME_SIZE	80
+
+#ifdef CONFIG_64BIT
 #define LDREG	ldd
 #define STREG	std
 #define LDREGX  ldd,s
@@ -30,8 +32,8 @@
 #define SHRREG  shrd
 #define RP_OFFSET	16
 #define FRAME_SIZE	128
-#define CALLEE_SAVE_FRAME_SIZE	144
-#else
+#define CALLEE_REG_FRAME_SIZE	144
+#else	/* CONFIG_64BIT */
 #define LDREG	ldw
 #define STREG	stw
 #define LDREGX  ldwx,s
@@ -40,9 +42,11 @@
 #define SHRREG  shr
 #define RP_OFFSET	20
 #define FRAME_SIZE	64
-#define CALLEE_SAVE_FRAME_SIZE	128
+#define CALLEE_REG_FRAME_SIZE	128
 #endif
 
+#define CALLEE_SAVE_FRAME_SIZE (CALLEE_REG_FRAME_SIZE + CALLEE_FLOAT_FRAME_SIZE)
+
 #ifdef CONFIG_PA20
 #define BL		b,l
 # ifdef CONFIG_64BIT
@@ -300,9 +304,35 @@
 	fldd,mb	-8(\regs),       %fr0
 	.endm
 
+	.macro	callee_save_float
+	fstd,ma	 %fr12,	8(%r30)
+	fstd,ma	 %fr13,	8(%r30)
+	fstd,ma	 %fr14,	8(%r30)
+	fstd,ma	 %fr15,	8(%r30)
+	fstd,ma	 %fr16,	8(%r30)
+	fstd,ma	 %fr17,	8(%r30)
+	fstd,ma	 %fr18,	8(%r30)
+	fstd,ma	 %fr19,	8(%r30)
+	fstd,ma	 %fr20,	8(%r30)
+	fstd,ma	 %fr21,	8(%r30)
+	.endm
+
+	.macro	callee_rest_float
+	fldd,mb	-8(%r30),   %fr21
+	fldd,mb	-8(%r30),   %fr20
+	fldd,mb	-8(%r30),   %fr19
+	fldd,mb	-8(%r30),   %fr18
+	fldd,mb	-8(%r30),   %fr17
+	fldd,mb	-8(%r30),   %fr16
+	fldd,mb	-8(%r30),   %fr15
+	fldd,mb	-8(%r30),   %fr14
+	fldd,mb	-8(%r30),   %fr13
+	fldd,mb	-8(%r30),   %fr12
+	.endm
+
 #ifdef __LP64__
 	.macro	callee_save
-	std,ma	  %r3,	CALLEE_SAVE_FRAME_SIZE(%r30)
+	std,ma	  %r3,	 CALLEE_REG_FRAME_SIZE(%r30)
 	mfctl	  %cr27, %r3
 	std	  %r4,	-136(%r30)
 	std	  %r5,	-128(%r30)
@@ -340,13 +370,13 @@
 	ldd	-128(%r30),    %r5
 	ldd	-136(%r30),    %r4
 	mtctl	%r3, %cr27
-	ldd,mb	-CALLEE_SAVE_FRAME_SIZE(%r30),    %r3
+	ldd,mb	-CALLEE_REG_FRAME_SIZE(%r30),    %r3
 	.endm
 
 #else /* ! __LP64__ */
 
 	.macro	callee_save
-	stw,ma	 %r3,	CALLEE_SAVE_FRAME_SIZE(%r30)
+	stw,ma	 %r3,	CALLEE_REG_FRAME_SIZE(%r30)
 	mfctl	 %cr27, %r3
 	stw	 %r4,	-124(%r30)
 	stw	 %r5,	-120(%r30)
@@ -384,7 +414,7 @@
 	ldw	-120(%r30),   %r5
 	ldw	-124(%r30),   %r4
 	mtctl	%r3, %cr27
-	ldw,mb	-CALLEE_SAVE_FRAME_SIZE(%r30),   %r3
+	ldw,mb	-CALLEE_REG_FRAME_SIZE(%r30),   %r3
 	.endm
 #endif /* ! __LP64__ */
 
@@ -450,5 +480,30 @@
 	REST_CR	(%cr22, PT_PSW	(\regs))
 	.endm
 
+
+	/* First step to create a "relied upon translation"
+	 * See PA 2.0 Arch. page F-4 and F-5.
+	 *
+	 * The ssm was originally necessary due to a "PCxT bug".
+	 * But someone decided it needed to be added to the architecture
+	 * and this "feature" went into rev3 of PA-RISC 1.1 Arch Manual.
+	 * It's been carried forward into PA 2.0 Arch as well. :^(
+	 *
+	 * "ssm 0,%r0" is a NOP with side effects (prefetch barrier).
+	 * rsm/ssm prevents the ifetch unit from speculatively fetching
+	 * instructions past this line in the code stream.
+	 * PA 2.0 processor will single step all insn in the same QUAD (4 insn).
+	 */
+	.macro	pcxt_ssm_bug
+	rsm	PSW_SM_I,%r0
+	nop	/* 1 */
+	nop	/* 2 */
+	nop	/* 3 */
+	nop	/* 4 */
+	nop	/* 5 */
+	nop	/* 6 */
+	nop	/* 7 */
+	.endm
+
 #endif /* __ASSEMBLY__ */
 #endif
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index af7db69..55b98c6 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -2,7 +2,7 @@
 #define _PARISC_BITOPS_H
 
 #include <linux/compiler.h>
-#include <asm/spinlock.h>
+#include <asm/types.h>		/* for BITS_PER_LONG/SHIFT_PER_LONG */
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 
@@ -12,193 +12,157 @@
  * to include/asm-i386/bitops.h or kerneldoc
  */
 
-#ifdef __LP64__
-#   define SHIFT_PER_LONG 6
-#ifndef BITS_PER_LONG
-#   define BITS_PER_LONG 64
-#endif
-#else
-#   define SHIFT_PER_LONG 5
-#ifndef BITS_PER_LONG
-#   define BITS_PER_LONG 32
-#endif
-#endif
-
-#define CHOP_SHIFTCOUNT(x) ((x) & (BITS_PER_LONG - 1))
+#define CHOP_SHIFTCOUNT(x) (((unsigned long) (x)) & (BITS_PER_LONG - 1))
 
 
 #define smp_mb__before_clear_bit()      smp_mb()
 #define smp_mb__after_clear_bit()       smp_mb()
 
-static __inline__ void set_bit(int nr, volatile unsigned long * address)
+/* See http://marc.theaimsgroup.com/?t=108826637900003 for discussion
+ * on use of volatile and __*_bit() (set/clear/change):
+ *	*_bit() want use of volatile.
+ *	__*_bit() are "relaxed" and don't use spinlock or volatile.
+ */
+
+static __inline__ void set_bit(int nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
 	unsigned long flags;
 
 	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
 	_atomic_spin_lock_irqsave(addr, flags);
 	*addr |= mask;
 	_atomic_spin_unlock_irqrestore(addr, flags);
 }
 
-static __inline__ void __set_bit(int nr, volatile unsigned long * address)
+static __inline__ void __set_bit(unsigned long nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
+	unsigned long *m = (unsigned long *) addr + (nr >> SHIFT_PER_LONG);
 
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
-	*addr |= mask;
+	*m |= 1UL << CHOP_SHIFTCOUNT(nr);
 }
 
-static __inline__ void clear_bit(int nr, volatile unsigned long * address)
+static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
+	unsigned long mask = ~(1UL << CHOP_SHIFTCOUNT(nr));
 	unsigned long flags;
 
 	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
 	_atomic_spin_lock_irqsave(addr, flags);
-	*addr &= ~mask;
+	*addr &= mask;
 	_atomic_spin_unlock_irqrestore(addr, flags);
 }
 
-static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long * address)
+static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
+	unsigned long *m = (unsigned long *) addr + (nr >> SHIFT_PER_LONG);
 
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
-	*addr &= ~mask;
+	*m &= ~(1UL << CHOP_SHIFTCOUNT(nr));
 }
 
-static __inline__ void change_bit(int nr, volatile unsigned long * address)
+static __inline__ void change_bit(int nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
 	unsigned long flags;
 
 	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
 	_atomic_spin_lock_irqsave(addr, flags);
 	*addr ^= mask;
 	_atomic_spin_unlock_irqrestore(addr, flags);
 }
 
-static __inline__ void __change_bit(int nr, volatile unsigned long * address)
+static __inline__ void __change_bit(unsigned long nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
+	unsigned long *m = (unsigned long *) addr + (nr >> SHIFT_PER_LONG);
 
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
-	*addr ^= mask;
+	*m ^= 1UL << CHOP_SHIFTCOUNT(nr);
 }
 
-static __inline__ int test_and_set_bit(int nr, volatile unsigned long * address)
+static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
-	int oldbit;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	unsigned long oldbit;
 	unsigned long flags;
 
 	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
 	_atomic_spin_lock_irqsave(addr, flags);
-	oldbit = (*addr & mask) ? 1 : 0;
-	*addr |= mask;
+	oldbit = *addr;
+	*addr = oldbit | mask;
 	_atomic_spin_unlock_irqrestore(addr, flags);
 
-	return oldbit;
+	return (oldbit & mask) ? 1 : 0;
 }
 
 static __inline__ int __test_and_set_bit(int nr, volatile unsigned long * address)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
-	int oldbit;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	unsigned long oldbit;
+	unsigned long *addr = (unsigned long *)address + (nr >> SHIFT_PER_LONG);
 
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
-	oldbit = (*addr & mask) ? 1 : 0;
-	*addr |= mask;
+	oldbit = *addr;
+	*addr = oldbit | mask;
 
-	return oldbit;
+	return (oldbit & mask) ? 1 : 0;
 }
 
-static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * address)
+static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
-	int oldbit;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	unsigned long oldbit;
 	unsigned long flags;
 
 	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
 	_atomic_spin_lock_irqsave(addr, flags);
-	oldbit = (*addr & mask) ? 1 : 0;
-	*addr &= ~mask;
+	oldbit = *addr;
+	*addr = oldbit & ~mask;
 	_atomic_spin_unlock_irqrestore(addr, flags);
 
-	return oldbit;
+	return (oldbit & mask) ? 1 : 0;
 }
 
 static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long * address)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
-	int oldbit;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	unsigned long *addr = (unsigned long *)address + (nr >> SHIFT_PER_LONG);
+	unsigned long oldbit;
 
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
-	oldbit = (*addr & mask) ? 1 : 0;
-	*addr &= ~mask;
+	oldbit = *addr;
+	*addr = oldbit & ~mask;
 
-	return oldbit;
+	return (oldbit & mask) ? 1 : 0;
 }
 
-static __inline__ int test_and_change_bit(int nr, volatile unsigned long * address)
+static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
-	int oldbit;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	unsigned long oldbit;
 	unsigned long flags;
 
 	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
 	_atomic_spin_lock_irqsave(addr, flags);
-	oldbit = (*addr & mask) ? 1 : 0;
-	*addr ^= mask;
+	oldbit = *addr;
+	*addr = oldbit ^ mask;
 	_atomic_spin_unlock_irqrestore(addr, flags);
 
-	return oldbit;
+	return (oldbit & mask) ? 1 : 0;
 }
 
 static __inline__ int __test_and_change_bit(int nr, volatile unsigned long * address)
 {
-	unsigned long mask;
-	unsigned long *addr = (unsigned long *) address;
-	int oldbit;
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	unsigned long *addr = (unsigned long *)address + (nr >> SHIFT_PER_LONG);
+	unsigned long oldbit;
 
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
-	oldbit = (*addr & mask) ? 1 : 0;
-	*addr ^= mask;
+	oldbit = *addr;
+	*addr = oldbit ^ mask;
 
-	return oldbit;
+	return (oldbit & mask) ? 1 : 0;
 }
 
 static __inline__ int test_bit(int nr, const volatile unsigned long *address)
 {
-	unsigned long mask;
-	const unsigned long *addr = (const unsigned long *)address;
-	
-	addr += (nr >> SHIFT_PER_LONG);
-	mask = 1L << CHOP_SHIFTCOUNT(nr);
+	unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
+	const unsigned long *addr = (const unsigned long *)address + (nr >> SHIFT_PER_LONG);
 	
 	return !!(*addr & mask);
 }
@@ -229,7 +193,7 @@
 	unsigned long ret;
 
 	__asm__(
-#if BITS_PER_LONG > 32
+#ifdef __LP64__
 		" ldi       63,%1\n"
 		" extrd,u,*<>  %0,63,32,%%r0\n"
 		" extrd,u,*TR  %0,31,32,%0\n"	/* move top 32-bits down */
@@ -304,14 +268,7 @@
  * hweightN: returns the hamming weight (i.e. the number
  * of bits set) of a N-bit word
  */
-#define hweight64(x)						\
-({								\
-	unsigned long __x = (x);				\
-	unsigned int __w;					\
-	__w = generic_hweight32((unsigned int) __x);		\
-	__w += generic_hweight32((unsigned int) (__x>>32));	\
-	__w;							\
-})
+#define hweight64(x) generic_hweight64(x)
 #define hweight32(x) generic_hweight32(x)
 #define hweight16(x) generic_hweight16(x)
 #define hweight8(x) generic_hweight8(x)
@@ -324,7 +281,13 @@
  */
 static inline int sched_find_first_bit(const unsigned long *b)
 {
-#ifndef __LP64__
+#ifdef __LP64__
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 64;
+	return __ffs(b[2]) + 128;
+#else
 	if (unlikely(b[0]))
 		return __ffs(b[0]);
 	if (unlikely(b[1]))
@@ -334,14 +297,6 @@
 	if (b[3])
 		return __ffs(b[3]) + 96;
 	return __ffs(b[4]) + 128;
-#else
-	if (unlikely(b[0]))
-		return __ffs(b[0]);
-	if (unlikely(((unsigned int)b[1])))
-		return __ffs(b[1]) + 64;
-	if (b[1] >> 32)
-		return __ffs(b[1] >> 32) + 96;
-	return __ffs(b[2]) + 128;
 #endif
 }
 
@@ -391,7 +346,7 @@
 
 static __inline__ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
 {
-	const unsigned long *p = addr + (offset >> 6);
+	const unsigned long *p = addr + (offset >> SHIFT_PER_LONG);
 	unsigned long result = offset & ~(BITS_PER_LONG-1);
 	unsigned long tmp;
 
@@ -445,71 +400,90 @@
  * test_and_{set,clear}_bit guarantee atomicity without
  * disabling interrupts.
  */
-#ifdef __LP64__
-#define ext2_set_bit(nr, addr)		__test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
-#define ext2_set_bit_atomic(l,nr,addr)  test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr)	__test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
-#define ext2_clear_bit_atomic(l,nr,addr) test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
-#else
-#define ext2_set_bit(nr, addr)		__test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
-#define ext2_set_bit_atomic(l,nr,addr)  test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr)	__test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
-#define ext2_clear_bit_atomic(l,nr,addr) test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
-#endif
+
+/* '3' is bits per byte */
+#define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
+
+#define ext2_test_bit(nr, addr) \
+			test_bit((nr)	^ LE_BYTE_ADDR, (unsigned long *)addr)
+#define ext2_set_bit(nr, addr)	\
+		__test_and_set_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
+#define ext2_clear_bit(nr, addr) \
+		__test_and_clear_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
+
+#define ext2_set_bit_atomic(l,nr,addr) \
+		test_and_set_bit((nr)   ^ LE_BYTE_ADDR, (unsigned long *)addr)
+#define ext2_clear_bit_atomic(l,nr,addr) \
+		test_and_clear_bit( (nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
 
 #endif	/* __KERNEL__ */
 
-static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
-{
-	__const__ unsigned char	*ADDR = (__const__ unsigned char *) addr;
-
-	return (ADDR[nr >> 3] >> (nr & 7)) & 1;
-}
-
-/*
- * This implementation of ext2_find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
- */
 
 #define ext2_find_first_zero_bit(addr, size) \
-        ext2_find_next_zero_bit((addr), (size), 0)
+	ext2_find_next_zero_bit((addr), (size), 0)
 
-extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
-	unsigned long size, unsigned long offset)
+/* include/linux/byteorder does not support "unsigned long" type */
+static inline unsigned long ext2_swabp(unsigned long * x)
 {
-	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
-	unsigned int result = offset & ~31UL;
-	unsigned int tmp;
+#ifdef __LP64__
+	return (unsigned long) __swab64p((u64 *) x);
+#else
+	return (unsigned long) __swab32p((u32 *) x);
+#endif
+}
+
+/* include/linux/byteorder doesn't support "unsigned long" type */
+static inline unsigned long ext2_swab(unsigned long y)
+{
+#ifdef __LP64__
+	return (unsigned long) __swab64((u64) y);
+#else
+	return (unsigned long) __swab32((u32) y);
+#endif
+}
+
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = (unsigned long *) addr + (offset >> SHIFT_PER_LONG);
+	unsigned long result = offset & ~(BITS_PER_LONG - 1);
+	unsigned long tmp;
 
 	if (offset >= size)
 		return size;
 	size -= result;
-	offset &= 31UL;
+	offset &= (BITS_PER_LONG - 1UL);
 	if (offset) {
-		tmp = cpu_to_le32p(p++);
-		tmp |= ~0UL >> (32-offset);
-		if (size < 32)
+		tmp = ext2_swabp(p++);
+		tmp |= (~0UL >> (BITS_PER_LONG - offset));
+		if (size < BITS_PER_LONG)
 			goto found_first;
-		if (tmp != ~0U)
+		if (~tmp)
 			goto found_middle;
-		size -= 32;
-		result += 32;
+		size -= BITS_PER_LONG;
+		result += BITS_PER_LONG;
 	}
-	while (size >= 32) {
-		if ((tmp = cpu_to_le32p(p++)) != ~0U)
-			goto found_middle;
-		result += 32;
-		size -= 32;
+
+	while (size & ~(BITS_PER_LONG - 1)) {
+		if (~(tmp = *(p++)))
+			goto found_middle_swap;
+		result += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 	}
 	if (!size)
 		return result;
-	tmp = cpu_to_le32p(p);
+	tmp = ext2_swabp(p);
 found_first:
-	tmp |= ~0U << size;
+	tmp |= ~0UL << size;
+	if (tmp == ~0UL)	/* Are any bits zero? */
+		return result + size; /* Nope. Skip ffz */
 found_middle:
 	return result + ffz(tmp);
+
+found_middle_swap:
+	return result + ffz(ext2_swab(tmp));
 }
 
+
 /* Bitmap functions for the minix filesystem.  */
 #define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
 #define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index aa592d8..1bc3c83 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -100,30 +100,34 @@
 
 /* Simple function to work out if we have an existing address translation
  * for a user space vma. */
-static inline pte_t *__translation_exists(struct mm_struct *mm,
-					  unsigned long addr)
+static inline int translation_exists(struct vm_area_struct *vma,
+				unsigned long addr, unsigned long pfn)
 {
-	pgd_t *pgd = pgd_offset(mm, addr);
+	pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
 	pmd_t *pmd;
-	pte_t *pte;
+	pte_t pte;
 
 	if(pgd_none(*pgd))
-		return NULL;
+		return 0;
 
 	pmd = pmd_offset(pgd, addr);
 	if(pmd_none(*pmd) || pmd_bad(*pmd))
-		return NULL;
+		return 0;
 
-	pte = pte_offset_map(pmd, addr);
+	/* We cannot take the pte lock here: flush_cache_page is usually
+	 * called with pte lock already held.  Whereas flush_dcache_page
+	 * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
+	 * the vma itself is secure, but the pte might come or go racily.
+	 */
+	pte = *pte_offset_map(pmd, addr);
+	/* But pte_unmap() does nothing on this architecture */
 
-	/* The PA flush mappings show up as pte_none, but they're
-	 * valid none the less */
-	if(pte_none(*pte) && ((pte_val(*pte) & _PAGE_FLUSH) == 0))
-		return NULL;
-	return pte;
+	/* Filter out coincidental file entries and swap entries */
+	if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
+		return 0;
+
+	return pte_pfn(pte) == pfn;
 }
-#define	translation_exists(vma, addr)	__translation_exists((vma)->vm_mm, addr)
-
 
 /* Private function to flush a page from the cache of a non-current
  * process.  cr25 contains the Page Directory of the current user
@@ -175,9 +179,8 @@
 {
 	BUG_ON(!vma->vm_mm->context);
 
-	if(likely(translation_exists(vma, vmaddr)))
+	if (likely(translation_exists(vma, vmaddr, pfn)))
 		__flush_cache_page(vma, vmaddr);
 
 }
 #endif
-
diff --git a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h
index 4db84f9..74d4ac6 100644
--- a/include/asm-parisc/dma-mapping.h
+++ b/include/asm-parisc/dma-mapping.h
@@ -9,8 +9,8 @@
 /* See Documentation/DMA-mapping.txt */
 struct hppa_dma_ops {
 	int  (*dma_supported)(struct device *dev, u64 mask);
-	void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, int flag);
-	void *(*alloc_noncoherent)(struct device *dev, size_t size, dma_addr_t *iova, int flag);
+	void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
+	void *(*alloc_noncoherent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
 	void (*free_consistent)(struct device *dev, size_t size, void *vaddr, dma_addr_t iova);
 	dma_addr_t (*map_single)(struct device *dev, void *addr, size_t size, enum dma_data_direction direction);
 	void (*unmap_single)(struct device *dev, dma_addr_t iova, size_t size, enum dma_data_direction direction);
@@ -49,14 +49,14 @@
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   int flag)
+		   gfp_t flag)
 {
 	return hppa_dma_ops->alloc_consistent(dev, size, dma_handle, flag);
 }
 
 static inline void *
 dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		      int flag)
+		      gfp_t flag)
 {
 	return hppa_dma_ops->alloc_noncoherent(dev, size, dma_handle, flag);
 }
diff --git a/include/asm-parisc/errno.h b/include/asm-parisc/errno.h
index 08464c4..e2f3ddc 100644
--- a/include/asm-parisc/errno.h
+++ b/include/asm-parisc/errno.h
@@ -114,6 +114,7 @@
 
 #define ENOTSUP		252	/* Function not implemented (POSIX.4 / HPUX) */
 #define ECANCELLED	253	/* aio request was canceled before complete (POSIX.4 / HPUX) */
+#define ECANCELED	ECANCELLED	/* SuSv3 and Solaris wants one 'L' */
 
 /* for robust mutexes */
 #define EOWNERDEAD	254	/* Owner died */
diff --git a/include/asm-parisc/grfioctl.h b/include/asm-parisc/grfioctl.h
index d3cfc01..6a91031 100644
--- a/include/asm-parisc/grfioctl.h
+++ b/include/asm-parisc/grfioctl.h
@@ -69,6 +69,8 @@
 #define CRT_ID_TVRX		S9000_ID_98765	/* TVRX (gto/falcon) */
 #define CRT_ID_ARTIST		S9000_ID_ARTIST	/* Artist */
 #define CRT_ID_SUMMIT		0x2FC1066B      /* Summit FX2, FX4, FX6 ... */
+#define CRT_ID_LEGO		0x35ACDA30	/* Lego FX5, FX10 ... */
+#define CRT_ID_PINNACLE		0x35ACDA16	/* Pinnacle FXe */ 
 
 /* structure for ioctl(GCDESCRIBE) */
 
diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
index 3243cf2..b27bf7a 100644
--- a/include/asm-parisc/ide.h
+++ b/include/asm-parisc/ide.h
@@ -22,7 +22,6 @@
 
 #define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
 #define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
-#define ide_check_region(from,extent)		check_region((from), (extent))
 #define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
 #define ide_release_region(from,extent)		release_region((from), (extent))
 /* Generic I/O and MEMIO string operations.  */
diff --git a/include/asm-parisc/led.h b/include/asm-parisc/led.h
index 1ac8ab6..efadfd5 100644
--- a/include/asm-parisc/led.h
+++ b/include/asm-parisc/led.h
@@ -23,9 +23,6 @@
 
 #define LED_CMD_REG_NONE 0		/* NULL == no addr for the cmd register */
 
-/* led tasklet struct */
-extern struct tasklet_struct led_tasklet;
-
 /* register_led_driver() */
 int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg);
 
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h
index 595d3dc..ae039f4 100644
--- a/include/asm-parisc/mmzone.h
+++ b/include/asm-parisc/mmzone.h
@@ -27,12 +27,6 @@
 })
 #define node_localnr(pfn, nid)		((pfn) - node_start_pfn(nid))
 
-#define local_mapnr(kvaddr)						\
-({									\
-	unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT;		\
-	(__pfn - node_start_pfn(pfn_to_nid(__pfn)));			\
-})
-
 #define pfn_to_page(pfn)						\
 ({									\
 	unsigned long __pfn = (pfn);					\
diff --git a/include/asm-parisc/parisc-device.h b/include/asm-parisc/parisc-device.h
index ef69ab4..1d247e3 100644
--- a/include/asm-parisc/parisc-device.h
+++ b/include/asm-parisc/parisc-device.h
@@ -1,7 +1,7 @@
 #include <linux/device.h>
 
 struct parisc_device {
-	unsigned long   hpa;		/* Hard Physical Address */
+	struct resource hpa;		/* Hard Physical Address */
 	struct parisc_device_id id;
 	struct parisc_driver *driver;	/* Driver for this device */
 	char		name[80];	/* The hardware description */
@@ -39,6 +39,11 @@
 #define to_parisc_driver(d)	container_of(d, struct parisc_driver, drv)
 #define parisc_parent(d)	to_parisc_device(d->dev.parent)
 
+static inline char *parisc_pathname(struct parisc_device *d)
+{
+	return d->dev.bus_id;
+}
+
 static inline void
 parisc_set_drvdata(struct parisc_device *d, void *p)
 {
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index d0b761f..fa39d07 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -69,7 +69,7 @@
 #define PCI_PORT_HBA(a)		((a) >> HBA_PORT_SPACE_BITS)
 #define PCI_PORT_ADDR(a)	((a) & (HBA_PORT_SPACE_SIZE - 1))
 
-#if CONFIG_64BIT
+#ifdef CONFIG_64BIT
 #define PCI_F_EXTEND		0xffffffff00000000UL
 #define PCI_IS_LMMIO(hba,a)	pci_is_lmmio(hba,a)
 
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index 820c6e7..c28fb6f 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -501,6 +501,8 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
+#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_NO_CACHE)
+
 #define MK_IOSPACE_PFN(space, pfn)	(pfn)
 #define GET_IOSPACE(pfn)		0
 #define GET_PFN(pfn)			(pfn)
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index a9dfadd..aae40e8 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -122,8 +122,27 @@
 }; 
 
 /* Thread struct flags. */
+#define PARISC_UAC_NOPRINT	(1UL << 0)	/* see prctl and unaligned.c */
+#define PARISC_UAC_SIGBUS	(1UL << 1)
 #define PARISC_KERNEL_DEATH	(1UL << 31)	/* see die_if_kernel()... */
 
+#define PARISC_UAC_SHIFT	0
+#define PARISC_UAC_MASK		(PARISC_UAC_NOPRINT|PARISC_UAC_SIGBUS)
+
+#define SET_UNALIGN_CTL(task,value)                                       \
+        ({                                                                \
+        (task)->thread.flags = (((task)->thread.flags & ~PARISC_UAC_MASK) \
+                                | (((value) << PARISC_UAC_SHIFT) &        \
+                                   PARISC_UAC_MASK));                     \
+        0;                                                                \
+        })
+
+#define GET_UNALIGN_CTL(task,addr)                                        \
+        ({                                                                \
+        put_user(((task)->thread.flags & PARISC_UAC_MASK)                 \
+                 >> PARISC_UAC_SHIFT, (int __user *) (addr));             \
+        })
+
 #define INIT_THREAD { \
 	regs:	{	gr: { 0, }, \
 			fr: { 0, }, \
diff --git a/include/asm-parisc/psw.h b/include/asm-parisc/psw.h
index 5132302..4334d6c 100644
--- a/include/asm-parisc/psw.h
+++ b/include/asm-parisc/psw.h
@@ -1,4 +1,7 @@
 #ifndef _PARISC_PSW_H
+
+#include <linux/config.h>
+
 #define	PSW_I	0x00000001
 #define	PSW_D	0x00000002
 #define	PSW_P	0x00000004
@@ -9,6 +12,16 @@
 #define	PSW_G	0x00000040	/* PA1.x only */
 #define PSW_O	0x00000080	/* PA2.0 only */
 
+/* ssm/rsm instructions number PSW_W and PSW_E differently */
+#define PSW_SM_I	PSW_I	/* Enable External Interrupts */
+#define PSW_SM_D	PSW_D
+#define PSW_SM_P	PSW_P
+#define PSW_SM_Q	PSW_Q	/* Enable Interrupt State Collection */
+#define PSW_SM_R	PSW_R	/* Enable Recover Counter Trap */
+#define PSW_SM_W	0x200	/* PA2.0 only : Enable Wide Mode */
+
+#define PSW_SM_QUIET	PSW_SM_R+PSW_SM_Q+PSW_SM_P+PSW_SM_D+PSW_SM_I
+
 #define PSW_CB	0x0000ff00
 
 #define	PSW_M	0x00010000
@@ -30,33 +43,21 @@
 #define	PSW_Z	0x40000000	/* PA1.x only */
 #define	PSW_Y	0x80000000	/* PA1.x only */
 
-#ifdef __LP64__
-#define PSW_HI_CB 0x000000ff    /* PA2.0 only */
+#ifdef CONFIG_64BIT
+#  define PSW_HI_CB 0x000000ff    /* PA2.0 only */
 #endif
 
-/* PSW bits to be used with ssm/rsm */
-#define PSW_SM_I        0x1
-#define PSW_SM_D        0x2
-#define PSW_SM_P        0x4
-#define PSW_SM_Q        0x8
-#define PSW_SM_R        0x10
-#define PSW_SM_F        0x20
-#define PSW_SM_G        0x40
-#define PSW_SM_O        0x80
-#define PSW_SM_E        0x100
-#define PSW_SM_W        0x200
-
-#ifdef __LP64__
-#  define USER_PSW      (PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I)
-#  define KERNEL_PSW    (PSW_W | PSW_C | PSW_Q | PSW_P | PSW_D)
-#  define REAL_MODE_PSW (PSW_W | PSW_Q)
-#  define USER_PSW_MASK (PSW_W | PSW_T | PSW_N | PSW_X | PSW_B | PSW_V | PSW_CB)
-#  define USER_PSW_HI_MASK (PSW_HI_CB)
-#else
-#  define USER_PSW      (PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I)
-#  define KERNEL_PSW    (PSW_C | PSW_Q | PSW_P | PSW_D)
-#  define REAL_MODE_PSW (PSW_Q)
-#  define USER_PSW_MASK (PSW_T | PSW_N | PSW_X | PSW_B | PSW_V | PSW_CB)
+#ifdef CONFIG_64BIT
+#  define USER_PSW_HI_MASK	PSW_HI_CB
+#  define WIDE_PSW		PSW_W
+#else 
+#  define WIDE_PSW		0
 #endif
 
+/* Used when setting up for rfi */
+#define KERNEL_PSW    (WIDE_PSW | PSW_C | PSW_Q | PSW_P | PSW_D)
+#define REAL_MODE_PSW (WIDE_PSW | PSW_Q)
+#define USER_PSW_MASK (WIDE_PSW | PSW_T | PSW_N | PSW_X | PSW_B | PSW_V | PSW_CB)
+#define USER_PSW      (PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I)
+
 #endif
diff --git a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h
index 3f428aa..93f990e 100644
--- a/include/asm-parisc/ptrace.h
+++ b/include/asm-parisc/ptrace.h
@@ -49,7 +49,7 @@
 #define user_mode(regs)			(((regs)->iaoq[0] & 3) ? 1 : 0)
 #define user_space(regs)		(((regs)->iasq[1] != 0) ? 1 : 0)
 #define instruction_pointer(regs)	((regs)->iaoq[0] & ~3)
-#define profile_pc(regs) instruction_pointer(regs)
+unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #endif
 
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
index f78bb2e..c9ee41c 100644
--- a/include/asm-parisc/semaphore.h
+++ b/include/asm-parisc/semaphore.h
@@ -49,9 +49,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
index 43eaa6e..7c3f406 100644
--- a/include/asm-parisc/spinlock.h
+++ b/include/asm-parisc/spinlock.h
@@ -5,11 +5,6 @@
 #include <asm/processor.h>
 #include <asm/spinlock_types.h>
 
-/* Note that PA-RISC has to use `1' to mean unlocked and `0' to mean locked
- * since it only has load-and-zero. Moreover, at least on some PA processors,
- * the semaphore address has to be 16-byte aligned.
- */
-
 static inline int __raw_spin_is_locked(raw_spinlock_t *x)
 {
 	volatile unsigned int *a = __ldcw_align(x);
diff --git a/include/asm-parisc/spinlock_types.h b/include/asm-parisc/spinlock_types.h
index 785bba8..d6b479b 100644
--- a/include/asm-parisc/spinlock_types.h
+++ b/include/asm-parisc/spinlock_types.h
@@ -6,11 +6,15 @@
 #endif
 
 typedef struct {
+#ifdef CONFIG_PA20
+	volatile unsigned int slock;
+# define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+#else
 	volatile unsigned int lock[4];
+# define __RAW_SPIN_LOCK_UNLOCKED	{ { 1, 1, 1, 1 } }
+#endif
 } raw_spinlock_t;
 
-#define __RAW_SPIN_LOCK_UNLOCKED	{ { 1, 1, 1, 1 } }
-
 typedef struct {
 	raw_spinlock_t lock;
 	volatile int counter;
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index 26ff844..f3928d3 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -138,13 +138,7 @@
 #define set_wmb(var, value)		do { var = value; wmb(); } while (0)
 
 
-/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
-#define __ldcw(a) ({ \
-	unsigned __ret; \
-	__asm__ __volatile__("ldcw 0(%1),%0" : "=r" (__ret) : "r" (a)); \
-	__ret; \
-})
-
+#ifndef CONFIG_PA20
 /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
    and GCC only guarantees 8-byte alignment for stack locals, we can't
    be assured of 16-byte alignment for atomic lock data even if we
@@ -152,37 +146,41 @@
    we use a struct containing an array of four ints for the atomic lock
    type and dynamically select the 16-byte aligned int from the array
    for the semaphore.  */
+
 #define __PA_LDCW_ALIGNMENT 16
 #define __ldcw_align(a) ({ \
   unsigned long __ret = (unsigned long) &(a)->lock[0];        		\
   __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); \
   (volatile unsigned int *) __ret;                                      \
 })
+#define LDCW	"ldcw"
+
+#else /*CONFIG_PA20*/
+/* From: "Jim Hull" <jim.hull of hp.com>
+   I've attached a summary of the change, but basically, for PA 2.0, as
+   long as the ",CO" (coherent operation) completer is specified, then the
+   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
+   they only require "natural" alignment (4-byte for ldcw, 8-byte for
+   ldcd). */
+
+#define __PA_LDCW_ALIGNMENT 4
+#define __ldcw_align(a) ((volatile unsigned int *)a)
+#define LDCW	"ldcw,co"
+
+#endif /*!CONFIG_PA20*/
+
+/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
+#define __ldcw(a) ({ \
+	unsigned __ret; \
+	__asm__ __volatile__(LDCW " 0(%1),%0" : "=r" (__ret) : "r" (a)); \
+	__ret; \
+})
 
 #ifdef CONFIG_SMP
 # define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
 #endif
 
 #define KERNEL_START (0x10100000 - 0x1000)
-
-/* This is for the serialisation of PxTLB broadcasts.  At least on the
- * N class systems, only one PxTLB inter processor broadcast can be
- * active at any one time on the Merced bus.  This tlb purge
- * synchronisation is fairly lightweight and harmless so we activate
- * it on all SMP systems not just the N class. */
-#ifdef CONFIG_SMP
-extern spinlock_t pa_tlb_lock;
-
-#define purge_tlb_start(x) spin_lock(&pa_tlb_lock)
-#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
-
-#else
-
-#define purge_tlb_start(x) do { } while(0)
-#define purge_tlb_end(x) do { } while (0)
-
-#endif
-
 #define arch_align_stack(x) (x)
 
 #endif
diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h
index eb27b78..e97aa8d 100644
--- a/include/asm-parisc/tlbflush.h
+++ b/include/asm-parisc/tlbflush.h
@@ -7,6 +7,26 @@
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 
+
+/* This is for the serialisation of PxTLB broadcasts.  At least on the
+ * N class systems, only one PxTLB inter processor broadcast can be
+ * active at any one time on the Merced bus.  This tlb purge
+ * synchronisation is fairly lightweight and harmless so we activate
+ * it on all SMP systems not just the N class. */
+#ifdef CONFIG_SMP
+extern spinlock_t pa_tlb_lock;
+
+#define purge_tlb_start(x) spin_lock(&pa_tlb_lock)
+#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
+
+#else
+
+#define purge_tlb_start(x) do { } while(0)
+#define purge_tlb_end(x) do { } while (0)
+
+#endif
+
+
 extern void flush_tlb_all(void);
 
 /*
@@ -64,29 +84,27 @@
 {
 	unsigned long npages;
 
-	
 	npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-	if (npages >= 512)  /* XXX arbitrary, should be tuned */
+	if (npages >= 512)  /* 2MB of space: arbitrary, should be tuned */
 		flush_tlb_all();
 	else {
-
+		preempt_disable();
 		mtsp(vma->vm_mm->context,1);
+		purge_tlb_start();
 		if (split_tlb) {
-			purge_tlb_start();
 			while (npages--) {
 				pdtlb(start);
 				pitlb(start);
 				start += PAGE_SIZE;
 			}
-			purge_tlb_end();
 		} else {
-			purge_tlb_start();
 			while (npages--) {
 				pdtlb(start);
 				start += PAGE_SIZE;
 			}
-			purge_tlb_end();
+		preempt_enable();
 		}
+		purge_tlb_end();
 	}
 }
 
diff --git a/include/asm-parisc/types.h b/include/asm-parisc/types.h
index d21b9d0..34fdce3 100644
--- a/include/asm-parisc/types.h
+++ b/include/asm-parisc/types.h
@@ -33,8 +33,10 @@
 
 #ifdef __LP64__
 #define BITS_PER_LONG 64
+#define SHIFT_PER_LONG 6
 #else
 #define BITS_PER_LONG 32
+#define SHIFT_PER_LONG 5
 #endif
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 6a9f0ca..80b7b98 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -687,8 +687,8 @@
 #define __NR_shmget             (__NR_Linux + 194)
 #define __NR_shmctl             (__NR_Linux + 195)
 
-#define __NR_getpmsg            (__NR_Linux + 196)      /* some people actually want streams */
-#define __NR_putpmsg            (__NR_Linux + 197)      /* some people actually want streams */
+#define __NR_getpmsg		(__NR_Linux + 196) /* Somebody *wants* streams? */
+#define __NR_putpmsg		(__NR_Linux + 197)
 
 #define __NR_lstat64            (__NR_Linux + 198)
 #define __NR_truncate64         (__NR_Linux + 199)
@@ -755,8 +755,14 @@
 #define __NR_mbind		(__NR_Linux + 260)
 #define __NR_get_mempolicy	(__NR_Linux + 261)
 #define __NR_set_mempolicy	(__NR_Linux + 262)
+#define __NR_vserver		(__NR_Linux + 263)
+#define __NR_add_key		(__NR_Linux + 264)
+#define __NR_request_key	(__NR_Linux + 265)
+#define __NR_keyctl		(__NR_Linux + 266)
+#define __NR_ioprio_set		(__NR_Linux + 267)
+#define __NR_ioprio_get		(__NR_Linux + 268)
 
-#define __NR_Linux_syscalls     263
+#define __NR_Linux_syscalls     269
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
@@ -807,10 +813,10 @@
 #define K_INLINE_SYSCALL(name, nr, args...)	({			\
 	long __sys_res;							\
 	{								\
-		register unsigned long __res asm("r28");		\
+		register unsigned long __res __asm__("r28");		\
 		K_LOAD_ARGS_##nr(args)					\
 		/* FIXME: HACK stw/ldw r19 around syscall */		\
-		asm volatile(						\
+		__asm__ volatile(					\
 			K_STW_ASM_PIC					\
 			"	ble  0x100(%%sr2, %%r0)\n"		\
 			"	ldi %1, %%r20\n"			\
@@ -1005,7 +1011,6 @@
 		struct pt_regs *regs);
 int sys_vfork(struct pt_regs *regs);
 int sys_pipe(int *fildes);
-long sys_ptrace(long request, pid_t pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h
index 0a5b83a..79bae49 100644
--- a/include/asm-powerpc/rwsem.h
+++ b/include/asm-powerpc/rwsem.h
@@ -159,5 +159,10 @@
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_RWSEM_H */
diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
index fd42fe9..57369d2 100644
--- a/include/asm-powerpc/semaphore.h
+++ b/include/asm-powerpc/semaphore.h
@@ -31,9 +31,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name, 1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name, count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index c2d039e..0991dfc 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -486,7 +486,6 @@
 		unsigned long p4, unsigned long p5, unsigned long p6,
 		struct pt_regs *regs);
 int sys_pipe(int __user *fildes);
-int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 long sys_rt_sigaction(int sig, const struct sigaction __user *act,
 		      struct sigaction __user *oact, size_t sigsetsize);
diff --git a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h
index 061bfca..6e96351 100644
--- a/include/asm-ppc/dma-mapping.h
+++ b/include/asm-ppc/dma-mapping.h
@@ -19,7 +19,7 @@
  * allocate the space "normally" and use the cache management functions
  * to ensure it is consistent.
  */
-extern void *__dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp);
+extern void *__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp);
 extern void __dma_free_coherent(size_t size, void *vaddr);
 extern void __dma_sync(void *vaddr, size_t size, int direction);
 extern void __dma_sync_page(struct page *page, unsigned long offset,
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
index ed473f4..80a708e 100644
--- a/include/asm-ppc64/mmzone.h
+++ b/include/asm-ppc64/mmzone.h
@@ -67,9 +67,6 @@
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)	(NODE_DATA(nid)->node_end_pfn)
 
-#define local_mapnr(kvaddr) \
-	( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) 
-
 #ifdef CONFIG_DISCONTIGMEM
 
 /*
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 8cf5991..8c3f574 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -478,10 +478,12 @@
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
 
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
 	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
 #define pud_ERROR(e) \
-	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pud_val(e))
+	printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
diff --git a/include/asm-s390/rwsem.h b/include/asm-s390/rwsem.h
index 8c0cebb..0422a08 100644
--- a/include/asm-s390/rwsem.h
+++ b/include/asm-s390/rwsem.h
@@ -351,5 +351,10 @@
 	return new;
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _S390_RWSEM_H */
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
index 873def6..702cf43 100644
--- a/include/asm-s390/semaphore.h
+++ b/include/asm-s390/semaphore.h
@@ -29,9 +29,6 @@
 #define __SEMAPHORE_INITIALIZER(name,count) \
 	{ ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
index 0d51c48..348a881 100644
--- a/include/asm-s390/setup.h
+++ b/include/asm-s390/setup.h
@@ -8,11 +8,14 @@
 #ifndef _ASM_S390_SETUP_H
 #define _ASM_S390_SETUP_H
 
+#include <asm/types.h>
+
 #define PARMAREA		0x10400
 #define COMMAND_LINE_SIZE 	896
 #define RAMDISK_ORIGIN		0x800000
 #define RAMDISK_SIZE		0x800000
 #define MEMORY_CHUNKS		16	/* max 0x7fff */
+#define IPL_PARMBLOCK_ORIGIN	0x2000
 
 #ifndef __ASSEMBLY__
 
@@ -64,6 +67,53 @@
 #define SET_CONSOLE_3215	do { console_mode = 2; } while (0)
 #define SET_CONSOLE_3270	do { console_mode = 3; } while (0)
 
+struct ipl_list_header {
+	u32 length;
+	u8  reserved[3];
+	u8  version;
+} __attribute__((packed));
+
+struct ipl_block_fcp {
+	u32 length;
+	u8  pbt;
+	u8  reserved1[322-1];
+	u16 devno;
+	u8  reserved2[4];
+	u64 wwpn;
+	u64 lun;
+	u32 bootprog;
+	u8  reserved3[12];
+	u64 br_lba;
+	u32 scp_data_len;
+	u8  reserved4[260];
+	u8  scp_data[];
+} __attribute__((packed));
+
+struct ipl_parameter_block {
+	union {
+		u32 length;
+		struct ipl_list_header header;
+	} hdr;
+	struct ipl_block_fcp fcp;
+} __attribute__((packed));
+
+#define IPL_MAX_SUPPORTED_VERSION (0)
+
+#define IPL_TYPE_FCP (0)
+
+/*
+ * IPL validity flags and parameters as detected in head.S
+ */
+extern u32 ipl_parameter_flags;
+extern u16 ipl_devno;
+
+#define IPL_DEVNO_VALID		(ipl_parameter_flags & 1)
+#define IPL_PARMBLOCK_VALID	(ipl_parameter_flags & 2)
+
+#define IPL_PARMBLOCK_START	((struct ipl_parameter_block *) \
+				 IPL_PARMBLOCK_ORIGIN)
+#define IPL_PARMBLOCK_SIZE	(IPL_PARMBLOCK_START->hdr.length)
+
 #else 
 
 #ifndef __s390x__
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 221e965..f97d926 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -590,7 +590,6 @@
 asmlinkage long sys_fork(struct pt_regs regs);
 asmlinkage long sys_vfork(struct pt_regs regs);
 asmlinkage long sys_pipe(unsigned long __user *fildes);
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 80d164c..d3fa5c2 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -9,7 +9,7 @@
 extern struct bus_type pci_bus_type;
 
 /* arch/sh/mm/consistent.c */
-extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle);
 extern void consistent_free(void *vaddr, size_t size);
 extern void consistent_sync(void *vaddr, size_t size, int direction);
 
@@ -26,7 +26,7 @@
 }
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int flag)
+			 dma_addr_t *dma_handle, gfp_t flag)
 {
 	if (sh_mv.mv_consistent_alloc) {
 		void *ret;
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
index 5771f4b..3f18aa1 100644
--- a/include/asm-sh/machvec.h
+++ b/include/asm-sh/machvec.h
@@ -64,7 +64,7 @@
 
 	void (*mv_heartbeat)(void);
 
-	void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, int);
+	void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, gfp_t);
 	int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t);
 };
 
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 0f4bcaa..aef8ae4 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -224,8 +224,6 @@
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; }
 
-#define page_pte(page) page_pte_prot(page, __pgprot(0))
-
 #define pmd_page_kernel(pmd) \
 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
 
diff --git a/include/asm-sh/rwsem.h b/include/asm-sh/rwsem.h
index 1be4337..0262d3d 100644
--- a/include/asm-sh/rwsem.h
+++ b/include/asm-sh/rwsem.h
@@ -166,5 +166,10 @@
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_SH_RWSEM_H */
diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
index b923a77..489f784 100644
--- a/include/asm-sh/semaphore.h
+++ b/include/asm-sh/semaphore.h
@@ -33,9 +33,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index ea89e8f..f2c8e14 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -503,7 +503,6 @@
 asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
 			unsigned long r6, unsigned long r7,
 			struct pt_regs regs);
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
 asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char *buf,
 				size_t count, long dummy, loff_t pos);
 asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char *buf,
diff --git a/include/asm-sh64/dma-mapping.h b/include/asm-sh64/dma-mapping.h
index b8d26fe..cc9a2e8 100644
--- a/include/asm-sh64/dma-mapping.h
+++ b/include/asm-sh64/dma-mapping.h
@@ -25,7 +25,7 @@
 }
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int flag)
+			 dma_addr_t *dma_handle, gfp_t flag)
 {
 	return consistent_alloc(NULL, size, dma_handle);
 }
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 51db430..51b0581 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -457,9 +457,6 @@
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; }
 
-#define page_pte_prot(page, prot) mk_pte(page, prot)
-#define page_pte(page) page_pte_prot(page, __pgprot(0))
-
 typedef pte_t *pte_addr_t;
 #define pgtable_cache_init()	do { } while (0)
 
diff --git a/include/asm-sh64/semaphore.h b/include/asm-sh64/semaphore.h
index fce22bb..4695264 100644
--- a/include/asm-sh64/semaphore.h
+++ b/include/asm-sh64/semaphore.h
@@ -40,9 +40,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-sparc/dma-mapping.h b/include/asm-sparc/dma-mapping.h
index 2dc5bb8..d7c3b0f 100644
--- a/include/asm-sparc/dma-mapping.h
+++ b/include/asm-sparc/dma-mapping.h
@@ -8,7 +8,7 @@
 #else
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int flag)
+			 dma_addr_t *dma_handle, gfp_t flag)
 {
 	BUG();
 	return NULL;
diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
index caf9261..7a941b8 100644
--- a/include/asm-sparc/floppy.h
+++ b/include/asm-sparc/floppy.h
@@ -17,10 +17,8 @@
 
 /* We don't need no stinkin' I/O port allocation crap. */
 #undef release_region
-#undef check_region
 #undef request_region
 #define release_region(X, Y)	do { } while(0)
-#define check_region(X, Y)	(0)
 #define request_region(X, Y, Z)	(1)
 
 /* References:
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index a14e986..b33c354 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -255,8 +255,6 @@
 #define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
 #define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
 
-#define page_pte_prot(page, prot)	mk_pte(page, prot)
-#define page_pte(page)			mk_pte(page, __pgprot(0))
 #define pfn_pte(pfn, prot)		mk_pte(pfn_to_page(pfn), prot)
 
 BTFIXUPDEF_CALL(unsigned long,	 pte_pfn, pte_t)
diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
index 60ac5fd..f74ba31 100644
--- a/include/asm-sparc/semaphore.h
+++ b/include/asm-sparc/semaphore.h
@@ -22,9 +22,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index 1c5da41..c7d5804 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -10,7 +10,7 @@
 struct device;
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int flag)
+			 dma_addr_t *dma_handle, gfp_t flag)
 {
 	BUG();
 	return NULL;
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 8c6dfc6c..9a02879 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -231,9 +231,6 @@
 #define pte_pfn(x)		((pte_val(x) & _PAGE_PADDR)>>PAGE_SHIFT)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
 
-#define page_pte_prot(page, prot)	mk_pte(page, prot)
-#define page_pte(page)			page_pte_prot(page, __pgprot(0))
-
 static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
 {
 	pte_t __pte;
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h
index 4568ee4..cef5e82 100644
--- a/include/asm-sparc64/rwsem.h
+++ b/include/asm-sparc64/rwsem.h
@@ -56,6 +56,11 @@
 	atomic_add(delta, (atomic_t *)(&sem->count));
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _SPARC64_RWSEM_H */
diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
index 7419dd8..093dcc6 100644
--- a/include/asm-sparc64/semaphore.h
+++ b/include/asm-sparc64/semaphore.h
@@ -22,9 +22,6 @@
 	{ ATOMIC_INIT(count), \
 	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name, 1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name, count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index 9baf57d..66138d9 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -25,9 +25,8 @@
 	struct mm_struct *mm;
 	unsigned int pages_nr;
 	unsigned int need_flush;
-	unsigned int tlb_frozen;
+	unsigned int fullmm;
 	unsigned int tlb_nr;
-	unsigned long freed;
 	unsigned long vaddrs[TLB_BATCH_NR];
 	struct page *pages[FREE_PTE_NR];
 };
@@ -44,14 +43,13 @@
 
 static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	struct mmu_gather *mp = &__get_cpu_var(mmu_gathers);
+	struct mmu_gather *mp = &get_cpu_var(mmu_gathers);
 
 	BUG_ON(mp->tlb_nr);
 
 	mp->mm = mm;
 	mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U;
-	mp->tlb_frozen = full_mm_flush;
-	mp->freed = 0;
+	mp->fullmm = full_mm_flush;
 
 	return mp;
 }
@@ -78,30 +76,19 @@
 
 static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end)
 {
-	unsigned long freed = mp->freed;
-	struct mm_struct *mm = mp->mm;
-	unsigned long rss = get_mm_counter(mm, rss);
-
-	if (rss < freed)
-		freed = rss;
-	add_mm_counter(mm, rss, -freed);
-
 	tlb_flush_mmu(mp);
 
-	if (mp->tlb_frozen) {
-		if (CTX_VALID(mm->context))
-			do_flush_tlb_mm(mm);
-		mp->tlb_frozen = 0;
+	if (mp->fullmm) {
+		if (CTX_VALID(mp->mm->context))
+			do_flush_tlb_mm(mp->mm);
+		mp->fullmm = 0;
 	} else
 		flush_tlb_pending();
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
-}
 
-static inline unsigned int tlb_is_full_mm(struct mmu_gather *mp)
-{
-	return mp->tlb_frozen;
+	put_cpu_var(mmu_gathers);
 }
 
 static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
diff --git a/include/asm-um/cache.h b/include/asm-um/cache.h
index 4b134fe..a10602a 100644
--- a/include/asm-um/cache.h
+++ b/include/asm-um/cache.h
@@ -1,10 +1,21 @@
 #ifndef __UM_CACHE_H
 #define __UM_CACHE_H
 
-/* These are x86 numbers */
-#define L1_CACHE_SHIFT 5
-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+#include <linux/config.h>
 
-#define L1_CACHE_SHIFT_MAX 7	/* largest L1 which this arch supports */
+#if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
+# define L1_CACHE_SHIFT		(CONFIG_X86_L1_CACHE_SHIFT)
+#elif defined(CONFIG_UML_X86) /* 64-bit */
+# define L1_CACHE_SHIFT		6 /* Should be 7 on Intel */
+#else
+/* XXX: this was taken from x86, now it's completely random. Luckily only
+ * affects SMP padding. */
+# define L1_CACHE_SHIFT		5
+#endif
+
+/* XXX: this is valid for x86 and x86_64. */
+#define L1_CACHE_SHIFT_MAX	7	/* largest L1 which this arch supports */
+
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
 
 #endif
diff --git a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h
index 13e6291..babd298 100644
--- a/include/asm-um/dma-mapping.h
+++ b/include/asm-um/dma-mapping.h
@@ -19,7 +19,7 @@
 
 static inline void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   int flag)
+		   gfp_t flag)
 {
 	BUG();
 	return((void *) 0);
diff --git a/include/asm-um/linkage.h b/include/asm-um/linkage.h
index 7dfce37..e3d62dc 100644
--- a/include/asm-um/linkage.h
+++ b/include/asm-um/linkage.h
@@ -3,4 +3,12 @@
 
 #include "asm/arch/linkage.h"
 
+#include <linux/config.h>
+
+/* <linux/linkage.h> will pick sane defaults */
+#ifdef CONFIG_GPROF
+#undef FASTCALL
+#undef fastcall
+#endif
+
 #endif
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 2c192ab..0229814 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -115,7 +115,7 @@
 #define pfn_valid(pfn) ((pfn) < max_mapnr)
 #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
 
-extern struct page *arch_validate(struct page *page, int mask, int order);
+extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
 #define HAVE_ARCH_VALIDATE
 
 extern void arch_free_page(struct page *page, int order);
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 616d02b..ac64eb9 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -138,7 +138,7 @@
 
 #define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
 
-#define pmd_none(x)	(!(pmd_val(x) & ~_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)
diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
index c514062..df6cdec 100644
--- a/include/asm-v850/semaphore.h
+++ b/include/asm-v850/semaphore.h
@@ -18,9 +18,6 @@
 	{ ATOMIC_INIT (count), 0,					      \
 	  __WAIT_QUEUE_HEAD_INITIALIZER ((name).wait) }
 
-#define __MUTEX_INITIALIZER(name)					      \
-	__SEMAPHORE_INITIALIZER (name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count)	\
 	struct semaphore name = __SEMAPHORE_INITIALIZER (name,count)
 
diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
index 3b55209..5a86f8e 100644
--- a/include/asm-v850/unistd.h
+++ b/include/asm-v850/unistd.h
@@ -452,7 +452,6 @@
 struct pt_regs;
 int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs);
 int sys_pipe (int *fildes);
-int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
 asmlinkage long sys_rt_sigaction(int sig,
 				const struct sigaction __user *act,
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index e784fdc..54a380e 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -17,7 +17,7 @@
 	(swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address))
 
 void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-			 unsigned gfp);
+			 gfp_t gfp);
 void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 			 dma_addr_t dma_handle);
 
diff --git a/include/asm-x86_64/mtrr.h b/include/asm-x86_64/mtrr.h
index c5959d6..66ac1c0 100644
--- a/include/asm-x86_64/mtrr.h
+++ b/include/asm-x86_64/mtrr.h
@@ -25,6 +25,7 @@
 
 #include <linux/config.h>
 #include <linux/ioctl.h>
+#include <linux/compat.h>
 
 #define	MTRR_IOCTL_BASE	'M'
 
@@ -105,4 +106,36 @@
 
 #endif
 
+#ifdef CONFIG_COMPAT
+
+struct mtrr_sentry32
+{
+    compat_ulong_t base;    /*  Base address     */
+    compat_uint_t size;    /*  Size of region   */
+    compat_uint_t type;     /*  Type of region   */
+};
+
+struct mtrr_gentry32
+{
+    compat_ulong_t regnum;   /*  Register number  */
+    compat_uint_t base;    /*  Base address     */
+    compat_uint_t size;    /*  Size of region   */
+    compat_uint_t type;     /*  Type of region   */
+};
+
+#define MTRR_IOCTL_BASE 'M'
+
+#define MTRRIOC32_ADD_ENTRY        _IOW(MTRR_IOCTL_BASE,  0, struct mtrr_sentry32)
+#define MTRRIOC32_SET_ENTRY        _IOW(MTRR_IOCTL_BASE,  1, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_ENTRY        _IOW(MTRR_IOCTL_BASE,  2, struct mtrr_sentry32)
+#define MTRRIOC32_GET_ENTRY        _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_ENTRY       _IOW(MTRR_IOCTL_BASE,  4, struct mtrr_sentry32)
+#define MTRRIOC32_ADD_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  5, struct mtrr_sentry32)
+#define MTRRIOC32_SET_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  6, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_PAGE_ENTRY   _IOW(MTRR_IOCTL_BASE,  7, struct mtrr_sentry32)
+#define MTRRIOC32_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
+
+#endif /* CONFIG_COMPAT */
+
 #endif  /*  _LINUX_MTRR_H  */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index dd8711e..7a07196 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -318,8 +318,6 @@
  * and a page entry and page directory to the page they refer to.
  */
 
-#define page_pte(page) page_pte_prot(page, __pgprot(0))
-
 /*
  * Level 4 access.
  */
diff --git a/include/asm-x86_64/rwsem.h b/include/asm-x86_64/rwsem.h
index c002175..46077e9 100644
--- a/include/asm-x86_64/rwsem.h
+++ b/include/asm-x86_64/rwsem.h
@@ -274,5 +274,10 @@
 	return tmp+delta;
 }
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _X8664_RWSEM_H */
diff --git a/include/asm-x86_64/semaphore.h b/include/asm-x86_64/semaphore.h
index f325e39..a389aa6 100644
--- a/include/asm-x86_64/semaphore.h
+++ b/include/asm-x86_64/semaphore.h
@@ -56,9 +56,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
index 3629306..7cbfd10 100644
--- a/include/asm-x86_64/swiotlb.h
+++ b/include/asm-x86_64/swiotlb.h
@@ -27,7 +27,7 @@
 			 int nents, int direction);
 extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
 extern void *swiotlb_alloc_coherent (struct device *hwdev, size_t size,
-				     dma_addr_t *dma_handle, int flags);
+				     dma_addr_t *dma_handle, gfp_t flags);
 extern void swiotlb_free_coherent (struct device *hwdev, size_t size,
 				   void *vaddr, dma_addr_t dma_handle);
 
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 11ba931..3c494b6 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -780,8 +780,6 @@
 #include <linux/types.h>
 #include <asm/ptrace.h>
 
-asmlinkage long sys_ptrace(long request, long pid,
-				unsigned long addr, long data);
 asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
 struct sigaction;
diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h
index e86a206..c425f10 100644
--- a/include/asm-xtensa/dma-mapping.h
+++ b/include/asm-xtensa/dma-mapping.h
@@ -28,7 +28,7 @@
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, int flag);
+			   dma_addr_t *dma_handle, gfp_t flag);
 
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle);
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
index 09e89ab..2a10e19 100644
--- a/include/asm-xtensa/semaphore.h
+++ b/include/asm-xtensa/semaphore.h
@@ -29,9 +29,6 @@
 	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
-#define __MUTEX_INITIALIZER(name) 					\
-	__SEMAPHORE_INITIALIZER(name, 1)
-
 #define __DECLARE_SEMAPHORE_GENERIC(name,count) 			\
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
new file mode 100644
index 0000000..26f6ec3
--- /dev/null
+++ b/include/keys/user-type.h
@@ -0,0 +1,47 @@
+/* user-type.h: User-defined key type
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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 _KEYS_USER_TYPE_H
+#define _KEYS_USER_TYPE_H
+
+#include <linux/key.h>
+#include <linux/rcupdate.h>
+
+/*****************************************************************************/
+/*
+ * the payload for a key of type "user"
+ * - once filled in and attached to a key:
+ *   - the payload struct is invariant may not be changed, only replaced
+ *   - the payload must be read with RCU procedures or with the key semaphore
+ *     held
+ *   - the payload may only be replaced with the key semaphore write-locked
+ * - the key's data length is the size of the actual data, not including the
+ *   payload wrapper
+ */
+struct user_key_payload {
+	struct rcu_head	rcu;		/* RCU destructor */
+	unsigned short	datalen;	/* length of this data */
+	char		data[0];	/* actual data */
+};
+
+extern struct key_type key_type_user;
+
+extern int user_instantiate(struct key *key, const void *data, size_t datalen);
+extern int user_duplicate(struct key *key, const struct key *source);
+extern int user_update(struct key *key, const void *data, size_t datalen);
+extern int user_match(const struct key *key, const void *criterion);
+extern void user_destroy(struct key *key);
+extern void user_describe(const struct key *user, struct seq_file *m);
+extern long user_read(const struct key *key,
+		      char __user *buffer, size_t buflen);
+
+
+#endif /* _KEYS_USER_TYPE_H */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index a5b74ef..d2873b7 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -42,13 +42,18 @@
 	ATA_SECT_SIZE		= 512,
 
 	ATA_ID_WORDS		= 256,
-	ATA_ID_PROD_OFS		= 27,
-	ATA_ID_FW_REV_OFS	= 23,
 	ATA_ID_SERNO_OFS	= 10,
-	ATA_ID_MAJOR_VER	= 80,
-	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_FW_REV_OFS	= 23,
+	ATA_ID_PROD_OFS		= 27,
+	ATA_ID_OLD_PIO_MODES	= 51,
+	ATA_ID_FIELD_VALID	= 53,
 	ATA_ID_MWDMA_MODES	= 63,
+	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_EIDE_DMA_MIN	= 65,
+	ATA_ID_EIDE_PIO		= 67,
+	ATA_ID_EIDE_PIO_IORDY	= 68,
 	ATA_ID_UDMA_MODES	= 88,
+	ATA_ID_MAJOR_VER	= 80,
 	ATA_ID_PIO4		= (1 << 1),
 
 	ATA_PCI_CTL_OFS		= 2,
@@ -128,10 +133,15 @@
 	ATA_CMD_PIO_READ_EXT	= 0x24,
 	ATA_CMD_PIO_WRITE	= 0x30,
 	ATA_CMD_PIO_WRITE_EXT	= 0x34,
+	ATA_CMD_READ_MULTI	= 0xC4,
+	ATA_CMD_READ_MULTI_EXT	= 0x29,
+	ATA_CMD_WRITE_MULTI	= 0xC5,
+	ATA_CMD_WRITE_MULTI_EXT	= 0x39,
 	ATA_CMD_SET_FEATURES	= 0xEF,
 	ATA_CMD_PACKET		= 0xA0,
 	ATA_CMD_VERIFY		= 0x40,
 	ATA_CMD_VERIFY_EXT	= 0x42,
+	ATA_CMD_INIT_DEV_PARAMS	= 0x91,
 
 	/* SETFEATURES stuff */
 	SETFEATURES_XFER	= 0x03,
@@ -146,14 +156,14 @@
 	XFER_MW_DMA_2		= 0x22,
 	XFER_MW_DMA_1		= 0x21,
 	XFER_MW_DMA_0		= 0x20,
+	XFER_SW_DMA_2		= 0x12,
+	XFER_SW_DMA_1		= 0x11,
+	XFER_SW_DMA_0		= 0x10,
 	XFER_PIO_4		= 0x0C,
 	XFER_PIO_3		= 0x0B,
 	XFER_PIO_2		= 0x0A,
 	XFER_PIO_1		= 0x09,
 	XFER_PIO_0		= 0x08,
-	XFER_SW_DMA_2		= 0x12,
-	XFER_SW_DMA_1		= 0x11,
-	XFER_SW_DMA_0		= 0x10,
 	XFER_PIO_SLOW		= 0x00,
 
 	/* ATAPI stuff */
@@ -181,6 +191,7 @@
 	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
 	ATA_TFLAG_DEVICE	= (1 << 2), /* enable r/w to device reg */
 	ATA_TFLAG_WRITE		= (1 << 3), /* data dir: host->dev==1 (write) */
+	ATA_TFLAG_LBA		= (1 << 4), /* enable LBA */
 };
 
 enum ata_tf_protocols {
@@ -250,7 +261,19 @@
 	  ((u64) (id)[(n) + 1] << 16) |	\
 	  ((u64) (id)[(n) + 0]) )
 
-static inline int atapi_cdb_len(u16 *dev_id)
+static inline int ata_id_current_chs_valid(const u16 *id)
+{
+	/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command 
+	   has not been issued to the device then the values of 
+	   id[54] to id[56] are vendor specific. */
+	return (id[53] & 0x01) && /* Current translation valid */
+		id[54] &&  /* cylinders in current translation */
+		id[55] &&  /* heads in current translation */
+		id[55] <= 16 &&
+		id[56];    /* sectors in current translation */
+}
+
+static inline int atapi_cdb_len(const u16 *dev_id)
 {
 	u16 tmp = dev_id[0] & 0x3;
 	switch (tmp) {
@@ -260,7 +283,7 @@
 	}
 }
 
-static inline int is_atapi_taskfile(struct ata_taskfile *tf)
+static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
 {
 	return (tf->protocol == ATA_PROT_ATAPI) ||
 	       (tf->protocol == ATA_PROT_ATAPI_NODATA) ||
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b2a2509..da3c019 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -260,11 +260,11 @@
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
 				/* Public API */
-extern void		    audit_log(struct audit_context *ctx, int gfp_mask,
+extern void		    audit_log(struct audit_context *ctx, gfp_t gfp_mask,
 				      int type, const char *fmt, ...)
 				      __attribute__((format(printf,4,5)));
 
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask, int type);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
 extern void		    audit_log_format(struct audit_buffer *ab,
 					     const char *fmt, ...)
 			    __attribute__((format(printf,2,3)));
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 3344b4e8..685fd37 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -301,7 +301,7 @@
 				    struct sg_iovec *, int, int);
 extern void bio_unmap_user(struct bio *);
 extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
-				unsigned int);
+				gfp_t);
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 86dd550..7d8ff97 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -40,6 +40,8 @@
  * bitmap_weight(src, nbits)			Hamming Weight: number set bits
  * bitmap_shift_right(dst, src, n, nbits)	*dst = *src >> n
  * bitmap_shift_left(dst, src, n, nbits)	*dst = *src << n
+ * bitmap_remap(dst, src, old, new, nbits)	*dst = map(old, new)(src)
+ * bitmap_bitremap(oldbit, old, new, nbits)	newbit = map(old, new)(oldbit)
  * bitmap_scnprintf(buf, len, src, nbits)	Print bitmap src to buf
  * bitmap_parse(ubuf, ulen, dst, nbits)		Parse bitmap dst from user buf
  * bitmap_scnlistprintf(buf, len, src, nbits)	Print bitmap src as list to buf
@@ -104,6 +106,10 @@
 			const unsigned long *src, int nbits);
 extern int bitmap_parselist(const char *buf, unsigned long *maskp,
 			int nmaskbits);
+extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
+		const unsigned long *old, const unsigned long *new, int bits);
+extern int bitmap_bitremap(int oldbit,
+		const unsigned long *old, const unsigned long *new, int bits);
 extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
 extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
 extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index efdc9b5..025a7f0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -96,8 +96,8 @@
 
 void put_io_context(struct io_context *ioc);
 void exit_io_context(void);
-struct io_context *current_io_context(int gfp_flags);
-struct io_context *get_io_context(int gfp_flags);
+struct io_context *current_io_context(gfp_t gfp_flags);
+struct io_context *get_io_context(gfp_t gfp_flags);
 void copy_io_context(struct io_context **pdst, struct io_context **psrc);
 void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
 
@@ -107,9 +107,9 @@
 struct request_list {
 	int count[2];
 	int starved[2];
+	int elvpriv;
 	mempool_t *rq_pool;
 	wait_queue_head_t wait[2];
-	wait_queue_head_t drain;
 };
 
 #define BLK_MAX_CDB	16
@@ -203,6 +203,7 @@
 enum rq_flag_bits {
 	__REQ_RW,		/* not set, read. set, write */
 	__REQ_FAILFAST,		/* no low level driver retries */
+	__REQ_SORTED,		/* elevator knows about this request */
 	__REQ_SOFTBARRIER,	/* may not be passed by ioscheduler */
 	__REQ_HARDBARRIER,	/* may not be passed by drive either */
 	__REQ_CMD,		/* is a regular fs rw request */
@@ -210,6 +211,7 @@
 	__REQ_STARTED,		/* drive already may have started this one */
 	__REQ_DONTPREP,		/* don't call prep for this one */
 	__REQ_QUEUED,		/* uses queueing */
+	__REQ_ELVPRIV,		/* elevator private data attached */
 	/*
 	 * for ATA/ATAPI devices
 	 */
@@ -235,6 +237,7 @@
 
 #define REQ_RW		(1 << __REQ_RW)
 #define REQ_FAILFAST	(1 << __REQ_FAILFAST)
+#define REQ_SORTED	(1 << __REQ_SORTED)
 #define REQ_SOFTBARRIER	(1 << __REQ_SOFTBARRIER)
 #define REQ_HARDBARRIER	(1 << __REQ_HARDBARRIER)
 #define REQ_CMD		(1 << __REQ_CMD)
@@ -242,6 +245,7 @@
 #define REQ_STARTED	(1 << __REQ_STARTED)
 #define REQ_DONTPREP	(1 << __REQ_DONTPREP)
 #define REQ_QUEUED	(1 << __REQ_QUEUED)
+#define REQ_ELVPRIV	(1 << __REQ_ELVPRIV)
 #define REQ_PC		(1 << __REQ_PC)
 #define REQ_BLOCK_PC	(1 << __REQ_BLOCK_PC)
 #define REQ_SENSE	(1 << __REQ_SENSE)
@@ -333,6 +337,12 @@
 	end_flush_fn		*end_flush_fn;
 
 	/*
+	 * Dispatch queue sorting
+	 */
+	sector_t		end_sector;
+	struct request		*boundary_rq;
+
+	/*
 	 * Auto-unplugging state
 	 */
 	struct timer_list	unplug_timer;
@@ -354,7 +364,7 @@
 	 * queue needs bounce pages for pages above this limit
 	 */
 	unsigned long		bounce_pfn;
-	unsigned int		bounce_gfp;
+	gfp_t			bounce_gfp;
 
 	/*
 	 * various queue flags, see QUEUE_* below
@@ -405,8 +415,6 @@
 	unsigned int		sg_reserved_size;
 	int			node;
 
-	struct list_head	drain_list;
-
 	/*
 	 * reserved for flush operations
 	 */
@@ -434,7 +442,7 @@
 #define QUEUE_FLAG_DEAD		5	/* queue being torn down */
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
-#define QUEUE_FLAG_DRAIN	8	/* draining queue for sched switch */
+#define QUEUE_FLAG_ELVSWITCH	8	/* don't use elevator, just do FIFO */
 #define QUEUE_FLAG_FLUSH	9	/* doing barrier flush sequence */
 
 #define blk_queue_plugged(q)	test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
@@ -454,6 +462,7 @@
 #define blk_pm_request(rq)	\
 	((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME))
 
+#define blk_sorted_rq(rq)	((rq)->flags & REQ_SORTED)
 #define blk_barrier_rq(rq)	((rq)->flags & REQ_HARDBARRIER)
 #define blk_barrier_preflush(rq)	((rq)->flags & REQ_BAR_PREFLUSH)
 #define blk_barrier_postflush(rq)	((rq)->flags & REQ_BAR_POSTFLUSH)
@@ -550,7 +559,7 @@
 extern void blk_put_request(struct request *);
 extern void blk_end_sync_rq(struct request *rq);
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
-extern struct request *blk_get_request(request_queue_t *, int, int);
+extern struct request *blk_get_request(request_queue_t *, int, gfp_t);
 extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
 extern void blk_requeue_request(request_queue_t *, struct request *);
 extern void blk_plug_device(request_queue_t *);
@@ -565,7 +574,7 @@
 extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);
 extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int);
 extern int blk_rq_unmap_user(struct bio *, unsigned int);
-extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, unsigned int);
+extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t);
 extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int);
 extern int blk_execute_rq(request_queue_t *, struct gendisk *,
 			  struct request *, int);
@@ -611,12 +620,21 @@
 
 static inline void blkdev_dequeue_request(struct request *req)
 {
-	BUG_ON(list_empty(&req->queuelist));
+	elv_dequeue_request(req->q, req);
+}
 
-	list_del_init(&req->queuelist);
+/*
+ * This should be in elevator.h, but that requires pulling in rq and q
+ */
+static inline void elv_dispatch_add_tail(struct request_queue *q,
+					 struct request *rq)
+{
+	if (q->last_merge == rq)
+		q->last_merge = NULL;
 
-	if (req->rl)
-		elv_remove_request(req->q, req);
+	q->end_sector = rq_end_sector(rq);
+	q->boundary_rq = rq;
+	list_add_tail(&rq->queuelist, &q->queue_head);
 }
 
 /*
@@ -650,12 +668,10 @@
 extern void generic_unplug_device(request_queue_t *);
 extern void __generic_unplug_device(request_queue_t *);
 extern long nr_blockdev_pages(void);
-extern void blk_wait_queue_drained(request_queue_t *, int);
-extern void blk_finish_queue_drain(request_queue_t *);
 
 int blk_get_queue(request_queue_t *);
-request_queue_t *blk_alloc_queue(int gfp_mask);
-request_queue_t *blk_alloc_queue_node(int,int);
+request_queue_t *blk_alloc_queue(gfp_t);
+request_queue_t *blk_alloc_queue_node(gfp_t, int);
 #define blk_put_queue(q) blk_cleanup_queue((q))
 
 /*
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 6a1d154..1db061b 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -126,8 +126,8 @@
 /* If we *know* page->private refers to buffer_heads */
 #define page_buffers(page)					\
 	({							\
-		BUG_ON(!PagePrivate(page));		\
-		((struct buffer_head *)(page)->private);	\
+		BUG_ON(!PagePrivate(page));			\
+		((struct buffer_head *)page_private(page));	\
 	})
 #define page_has_buffers(page)	PagePrivate(page)
 
@@ -188,8 +188,9 @@
  * Generic address_space_operations implementations for buffer_head-backed
  * address_spaces.
  */
-int try_to_release_page(struct page * page, int gfp_mask);
+int try_to_release_page(struct page * page, gfp_t gfp_mask);
 int block_invalidatepage(struct page *page, unsigned long offset);
+int do_invalidatepage(struct page *page, unsigned long offset);
 int block_write_full_page(struct page *page, get_block_t *get_block,
 				struct writeback_control *wbc);
 int block_read_full_page(struct page*, get_block_t*);
@@ -219,7 +220,7 @@
 {
 	page_cache_get(page);
 	SetPagePrivate(page);
-	page->private = (unsigned long)head;
+	set_page_private(page, (unsigned long)head);
 }
 
 static inline void get_bh(struct buffer_head *bh)
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 86980c6..1f7b2c0 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -32,6 +32,7 @@
 };
 
 extern int register_cpu(struct cpu *, int, struct node *);
+extern struct sys_device *get_cpu_sysdev(int cpu);
 #ifdef CONFIG_HOTPLUG_CPU
 extern void unregister_cpu(struct cpu *, struct node *);
 #endif
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index ff7f80f..d068176 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -23,6 +23,7 @@
 #include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/cpumask.h>
+#include <asm/div64.h>
 
 #define CPUFREQ_NAME_LEN 16
 
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 9bdba81..13e9f4a 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -12,6 +12,8 @@
  * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
  * For details of cpulist_scnprintf() and cpulist_parse(), see
  * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
+ * For details of cpu_remap(), see bitmap_bitremap in lib/bitmap.c
+ * For details of cpus_remap(), see bitmap_remap in lib/bitmap.c.
  *
  * The available cpumask operations are:
  *
@@ -50,6 +52,8 @@
  * int cpumask_parse(ubuf, ulen, mask)	Parse ascii string as cpumask
  * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
  * int cpulist_parse(buf, map)		Parse ascii string as cpulist
+ * int cpu_remap(oldbit, old, new)	newbit = map(old, new)(oldbit)
+ * int cpus_remap(dst, src, old, new)	*dst = map(old, new)(src)
  *
  * for_each_cpu_mask(cpu, mask)		for-loop cpu over mask
  *
@@ -294,6 +298,22 @@
 	return bitmap_parselist(buf, dstp->bits, nbits);
 }
 
+#define cpu_remap(oldbit, old, new) \
+		__cpu_remap((oldbit), &(old), &(new), NR_CPUS)
+static inline int __cpu_remap(int oldbit,
+		const cpumask_t *oldp, const cpumask_t *newp, int nbits)
+{
+	return bitmap_bitremap(oldbit, oldp->bits, newp->bits, nbits);
+}
+
+#define cpus_remap(dst, src, old, new) \
+		__cpus_remap(&(dst), &(src), &(old), &(new), NR_CPUS)
+static inline void __cpus_remap(cpumask_t *dstp, const cpumask_t *srcp,
+		const cpumask_t *oldp, const cpumask_t *newp, int nbits)
+{
+	bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
+}
+
 #if NR_CPUS > 1
 #define for_each_cpu_mask(cpu, mask)		\
 	for ((cpu) = first_cpu(mask);		\
diff --git a/include/linux/cyclomx.h b/include/linux/cyclomx.h
index 04fa7df..300d704 100644
--- a/include/linux/cyclomx.h
+++ b/include/linux/cyclomx.h
@@ -37,8 +37,6 @@
 #include <linux/cycx_x25.h>
 #endif
 
-#define	is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
-
 /* Adapter Data Space.
  * This structure is needed because we handle multiple cards, otherwise
  * static data would do it.
diff --git a/include/linux/cycx_drv.h b/include/linux/cycx_drv.h
index 6621df8..12fe6b0 100644
--- a/include/linux/cycx_drv.h
+++ b/include/linux/cycx_drv.h
@@ -60,6 +60,5 @@
 extern int cycx_poke(struct cycx_hw *hw, u32 addr, void *buf, u32 len);
 extern int cycx_exec(void __iomem *addr);
 
-extern void cycx_inten(struct cycx_hw *hw);
 extern void cycx_intr(struct cycx_hw *hw);
 #endif	/* _CYCX_DRV_H */
diff --git a/include/linux/device.h b/include/linux/device.h
index 95d607a..a9e72ac 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -28,19 +28,6 @@
 #define BUS_ID_SIZE		KOBJ_NAME_LEN
 
 
-enum {
-	SUSPEND_NOTIFY,
-	SUSPEND_SAVE_STATE,
-	SUSPEND_DISABLE,
-	SUSPEND_POWER_DOWN,
-};
-
-enum {
-	RESUME_POWER_ON,
-	RESUME_RESTORE_STATE,
-	RESUME_ENABLE,
-};
-
 struct device;
 struct device_driver;
 struct class;
@@ -115,8 +102,8 @@
 	int	(*probe)	(struct device * dev);
 	int	(*remove)	(struct device * dev);
 	void	(*shutdown)	(struct device * dev);
-	int	(*suspend)	(struct device * dev, pm_message_t state, u32 level);
-	int	(*resume)	(struct device * dev, u32 level);
+	int	(*suspend)	(struct device * dev, pm_message_t state);
+	int	(*resume)	(struct device * dev);
 };
 
 
@@ -190,7 +177,43 @@
 extern int class_create_file(struct class *, const struct class_attribute *);
 extern void class_remove_file(struct class *, const struct class_attribute *);
 
+struct class_device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct class_device *, char * buf);
+	ssize_t (*store)(struct class_device *, const char * buf, size_t count);
+};
 
+#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store)		\
+struct class_device_attribute class_device_attr_##_name = 	\
+	__ATTR(_name,_mode,_show,_store)
+
+extern int class_device_create_file(struct class_device *,
+				    const struct class_device_attribute *);
+
+/**
+ * struct class_device - class devices
+ * @class: pointer to the parent class for this class device.  This is required.
+ * @devt: for internal use by the driver core only.
+ * @node: for internal use by the driver core only.
+ * @kobj: for internal use by the driver core only.
+ * @devt_attr: for internal use by the driver core only.
+ * @dev: if set, a symlink to the struct device is created in the sysfs
+ * directory for this struct class device.
+ * @class_data: pointer to whatever you want to store here for this struct
+ * class_device.  Use class_get_devdata() and class_set_devdata() to get and
+ * set this pointer.
+ * @parent: pointer to a struct class_device that is the parent of this struct
+ * class_device.  If NULL, this class_device will show up at the root of the
+ * struct class in sysfs (which is probably what you want to have happen.)
+ * @release: pointer to a release function for this struct class_device.  If
+ * set, this will be called instead of the class specific release function.
+ * Only use this if you want to override the default release function, like
+ * when you are nesting class_device structures.
+ * @hotplug: pointer to a hotplug function for this struct class_device.  If
+ * set, this will be called instead of the class specific hotplug function.
+ * Only use this if you want to override the default hotplug function, like
+ * when you are nesting class_device structures.
+ */
 struct class_device {
 	struct list_head	node;
 
@@ -198,9 +221,14 @@
 	struct class		* class;	/* required */
 	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
 	struct class_device_attribute *devt_attr;
+	struct class_device_attribute uevent_attr;
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */
+	struct class_device	*parent;	/* parent of this child device, if there is one */
 
+	void	(*release)(struct class_device *dev);
+	int	(*hotplug)(struct class_device *dev, char **envp,
+			   int num_envp, char *buffer, int buffer_size);
 	char	class_id[BUS_ID_SIZE];	/* unique to this class */
 };
 
@@ -228,18 +256,6 @@
 extern struct class_device * class_device_get(struct class_device *);
 extern void class_device_put(struct class_device *);
 
-struct class_device_attribute {
-	struct attribute	attr;
-	ssize_t (*show)(struct class_device *, char * buf);
-	ssize_t (*store)(struct class_device *, const char * buf, size_t count);
-};
-
-#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store)		\
-struct class_device_attribute class_device_attr_##_name = 	\
-	__ATTR(_name,_mode,_show,_store)
-
-extern int class_device_create_file(struct class_device *, 
-				    const struct class_device_attribute *);
 extern void class_device_remove_file(struct class_device *, 
 				     const struct class_device_attribute *);
 extern int class_device_create_bin_file(struct class_device *,
@@ -251,8 +267,8 @@
 	struct list_head	node;
 	struct class		*class;
 
-	int (*add)	(struct class_device *);
-	void (*remove)	(struct class_device *);
+	int (*add)	(struct class_device *, struct class_interface *);
+	void (*remove)	(struct class_device *, struct class_interface *);
 };
 
 extern int class_interface_register(struct class_interface *);
@@ -260,12 +276,29 @@
 
 extern struct class *class_create(struct module *owner, char *name);
 extern void class_destroy(struct class *cls);
-extern struct class_device *class_device_create(struct class *cls, dev_t devt,
-						struct device *device, char *fmt, ...)
-					__attribute__((format(printf,4,5)));
+extern struct class_device *class_device_create(struct class *cls,
+						struct class_device *parent,
+						dev_t devt,
+						struct device *device,
+						char *fmt, ...)
+					__attribute__((format(printf,5,6)));
 extern void class_device_destroy(struct class *cls, dev_t devt);
 
 
+/* interface for exporting device attributes */
+struct device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
+};
+
+#define DEVICE_ATTR(_name,_mode,_show,_store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)
+
+extern int device_create_file(struct device *device, struct device_attribute * entry);
+extern void device_remove_file(struct device * dev, struct device_attribute * attr);
 struct device {
 	struct klist		klist_children;
 	struct klist_node	knode_parent;		/* node in sibling list */
@@ -275,6 +308,7 @@
 
 	struct kobject kobj;
 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
+	struct device_attribute uevent_attr;
 
 	struct semaphore	sem;	/* semaphore to synchronize calls to
 					 * its driver.
@@ -343,23 +377,6 @@
 extern void driver_attach(struct device_driver * drv);
 
 
-/* driverfs interface for exporting device attributes */
-
-struct device_attribute {
-	struct attribute	attr;
-	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count);
-};
-
-#define DEVICE_ATTR(_name,_mode,_show,_store) \
-struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)
-
-
-extern int device_create_file(struct device *device, struct device_attribute * entry);
-extern void device_remove_file(struct device * dev, struct device_attribute * attr);
-
 /*
  * Platform "fixup" functions - allow the platform to have their say
  * about devices and actions that the general device layer doesn't
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index a415f1d..05f4132 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -60,7 +60,7 @@
 	void *device_data;	/* Type specific data */
 };
 
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_32)
 
 extern int dmi_check_system(struct dmi_system_id *list);
 extern char * dmi_get_system_info(int field);
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index ea6bbc2..a74c27e 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -8,18 +8,17 @@
 
 typedef void (elevator_merged_fn) (request_queue_t *, struct request *);
 
-typedef struct request *(elevator_next_req_fn) (request_queue_t *);
+typedef int (elevator_dispatch_fn) (request_queue_t *, int);
 
-typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, int);
+typedef void (elevator_add_req_fn) (request_queue_t *, struct request *);
 typedef int (elevator_queue_empty_fn) (request_queue_t *);
-typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
-typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *);
 typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
 typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
 typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *);
 
-typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int);
+typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, gfp_t);
 typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
+typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
 
 typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
@@ -31,10 +30,9 @@
 	elevator_merged_fn *elevator_merged_fn;
 	elevator_merge_req_fn *elevator_merge_req_fn;
 
-	elevator_next_req_fn *elevator_next_req_fn;
+	elevator_dispatch_fn *elevator_dispatch_fn;
 	elevator_add_req_fn *elevator_add_req_fn;
-	elevator_remove_req_fn *elevator_remove_req_fn;
-	elevator_requeue_req_fn *elevator_requeue_req_fn;
+	elevator_activate_req_fn *elevator_activate_req_fn;
 	elevator_deactivate_req_fn *elevator_deactivate_req_fn;
 
 	elevator_queue_empty_fn *elevator_queue_empty_fn;
@@ -81,15 +79,15 @@
 /*
  * block elevator interface
  */
+extern void elv_dispatch_sort(request_queue_t *, struct request *);
 extern void elv_add_request(request_queue_t *, struct request *, int, int);
 extern void __elv_add_request(request_queue_t *, struct request *, int, int);
 extern int elv_merge(request_queue_t *, struct request **, struct bio *);
 extern void elv_merge_requests(request_queue_t *, struct request *,
 			       struct request *);
 extern void elv_merged_request(request_queue_t *, struct request *);
-extern void elv_remove_request(request_queue_t *, struct request *);
+extern void elv_dequeue_request(request_queue_t *, struct request *);
 extern void elv_requeue_request(request_queue_t *, struct request *);
-extern void elv_deactivate_request(request_queue_t *, struct request *);
 extern int elv_queue_empty(request_queue_t *);
 extern struct request *elv_next_request(struct request_queue *q);
 extern struct request *elv_former_request(request_queue_t *, struct request *);
@@ -98,7 +96,7 @@
 extern void elv_unregister_queue(request_queue_t *q);
 extern int elv_may_queue(request_queue_t *, int, struct bio *);
 extern void elv_completed_request(request_queue_t *, struct request *);
-extern int elv_set_request(request_queue_t *, struct request *, struct bio *, int);
+extern int elv_set_request(request_queue_t *, struct request *, struct bio *, gfp_t);
 extern void elv_put_request(request_queue_t *, struct request *);
 
 /*
@@ -142,4 +140,6 @@
 	ELV_MQUEUE_MUST,
 };
 
+#define rq_end_sector(rq)	((rq)->sector + (rq)->nr_sectors)
+
 #endif
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 4522c71..cc84934 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -104,6 +104,22 @@
 	addr [0] &= 0xfe;	/* clear multicast bit */
 	addr [0] |= 0x02;	/* set local assignment bit (IEEE802) */
 }
+
+/**
+ * compare_ether_addr - Compare two Ethernet addresses
+ * @addr1: Pointer to a six-byte array containing the Ethernet address
+ * @addr2 Pointer other six-byte array containing the Ethernet address
+ *
+ * Compare two ethernet addresses, returns 0 if equal
+ */
+static inline unsigned compare_ether_addr(const u8 *_a, const u8 *_b)
+{
+	const u16 *a = (const u16 *) _a;
+	const u16 *b = (const u16 *) _b;
+
+	BUILD_BUG_ON(ETH_ALEN != 6);
+	return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
+}
 #endif	/* __KERNEL__ */
 
 #endif	/* _LINUX_ETHERDEVICE_H */
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index ed1440e..d2c390e 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -269,6 +269,8 @@
 int ethtool_op_set_tso(struct net_device *dev, u32 data);
 int ethtool_op_get_perm_addr(struct net_device *dev, 
 			     struct ethtool_perm_addr *addr, u8 *data);
+u32 ethtool_op_get_ufo(struct net_device *dev);
+int ethtool_op_set_ufo(struct net_device *dev, u32 data);
 
 /**
  * &ethtool_ops - Alter and report network device settings
@@ -298,6 +300,8 @@
  * set_sg: Turn scatter-gather on or off
  * get_tso: Report whether TCP segmentation offload is enabled
  * set_tso: Turn TCP segmentation offload on or off
+ * get_ufo: Report whether UDP fragmentation offload is enabled
+ * set_ufo: Turn UDP fragmentation offload on or off
  * self_test: Run specified self-tests
  * get_strings: Return a set of strings that describe the requested objects 
  * phys_id: Identify the device
@@ -364,6 +368,8 @@
 	int	(*get_perm_addr)(struct net_device *, struct ethtool_perm_addr *, u8 *);
 	int	(*begin)(struct net_device *);
 	void	(*complete)(struct net_device *);
+	u32     (*get_ufo)(struct net_device *);
+	int     (*set_ufo)(struct net_device *, u32);
 };
 
 /* CMDs currently supported */
@@ -400,6 +406,8 @@
 #define ETHTOOL_GTSO		0x0000001e /* Get TSO enable (ethtool_value) */
 #define ETHTOOL_STSO		0x0000001f /* Set TSO enable (ethtool_value) */
 #define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
+#define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
+#define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e0b77c5..6d62267 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -320,7 +320,7 @@
 	/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
 	sector_t (*bmap)(struct address_space *, sector_t);
 	int (*invalidatepage) (struct page *, unsigned long);
-	int (*releasepage) (struct page *, int);
+	int (*releasepage) (struct page *, gfp_t);
 	ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs);
 	struct page* (*get_xip_page)(struct address_space *, sector_t,
@@ -574,7 +574,14 @@
 #define RA_FLAG_INCACHE 0x02	/* file is already in cache */
 
 struct file {
-	struct list_head	f_list;
+	/*
+	 * fu_list becomes invalid after file_free is called and queued via
+	 * fu_rcuhead for RCU freeing
+	 */
+	union {
+		struct list_head	fu_list;
+		struct rcu_head 	fu_rcuhead;
+	} f_u;
 	struct dentry		*f_dentry;
 	struct vfsmount         *f_vfsmnt;
 	struct file_operations	*f_op;
@@ -598,7 +605,6 @@
 	spinlock_t		f_ep_lock;
 #endif /* #ifdef CONFIG_EPOLL */
 	struct address_space	*f_mapping;
-	struct rcu_head 	f_rcuhead;
 };
 extern spinlock_t files_lock;
 #define file_list_lock() spin_lock(&files_lock);
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
new file mode 100644
index 0000000..bef23bb
--- /dev/null
+++ b/include/linux/fs_enet_pd.h
@@ -0,0 +1,136 @@
+/*
+ * Platform information definitions for the
+ * universal Freescale Ethernet driver.
+ *
+ * Copyright (c) 2003 Intracom S.A. 
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc. 
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ */
+
+#ifndef FS_ENET_PD_H
+#define FS_ENET_PD_H
+
+#include <linux/version.h>
+#include <asm/types.h>
+
+#define FS_ENET_NAME	"fs_enet"
+
+enum fs_id {
+	fsid_fec1,
+	fsid_fec2,
+	fsid_fcc1,
+	fsid_fcc2,
+	fsid_fcc3,
+	fsid_scc1,
+	fsid_scc2,
+	fsid_scc3,
+	fsid_scc4,
+};
+
+#define FS_MAX_INDEX	9
+
+static inline int fs_get_fec_index(enum fs_id id)
+{
+	if (id >= fsid_fec1 && id <= fsid_fec2)
+		return id - fsid_fec1;
+	return -1;
+}
+
+static inline int fs_get_fcc_index(enum fs_id id)
+{
+	if (id >= fsid_fcc1 && id <= fsid_fcc3)
+		return id - fsid_fcc1;
+	return -1;
+}
+
+static inline int fs_get_scc_index(enum fs_id id)
+{
+	if (id >= fsid_scc1 && id <= fsid_scc4)
+		return id - fsid_scc1;
+	return -1;
+}
+
+enum fs_mii_method {
+	fsmii_fixed,
+	fsmii_fec,
+	fsmii_bitbang,
+};
+
+enum fs_ioport {
+	fsiop_porta,
+	fsiop_portb,
+	fsiop_portc,
+	fsiop_portd,
+	fsiop_porte,
+};
+
+struct fs_mii_bus_info {
+	int method;		/* mii method                  */
+	int id;			/* the id of the mii_bus       */
+	int disable_aneg;	/* if the controller needs to negothiate speed & duplex */
+	int lpa; 		/* the default board-specific vallues will be applied otherwise */
+
+	union {
+		struct {
+			int duplex;
+			int speed;
+		} fixed;
+
+		struct {
+			/* nothing */
+		} fec;
+		
+		struct {
+			/* nothing */
+		} scc;
+
+		struct {
+			int mdio_port;	/* port & bit for MDIO */
+			int mdio_bit;
+			int mdc_port;	/* port & bit for MDC  */
+			int mdc_bit;
+			int delay;	/* delay in us         */
+		} bitbang;
+	} i;
+};
+
+struct fs_platform_info {
+	
+	void(*init_ioports)(void);
+	/* device specific information */
+	int fs_no;		/* controller index            */
+
+	u32 cp_page;		/* CPM page */
+	u32 cp_block;		/* CPM sblock */
+	
+	u32 clk_trx;		/* some stuff for pins & mux configuration*/
+	u32 clk_route;
+	u32 clk_mask;
+	
+	u32 mem_offset;
+	u32 dpram_offset;
+	u32 fcc_regs_c;
+	
+	u32 device_flags;
+
+	int phy_addr;		/* the phy address (-1 no phy) */
+	int phy_irq;		/* the phy irq (if it exists)  */
+
+	const struct fs_mii_bus_info *bus_info;
+
+	int rx_ring, tx_ring;	/* number of buffers on rx     */
+	__u8 macaddr[6];	/* mac address                 */
+	int rx_copybreak;	/* limit we copy small frames  */
+	int use_napi;		/* use NAPI                    */
+	int napi_weight;	/* NAPI weight                 */
+
+	int use_rmii;		/* use RMII mode 	       */
+};
+
+#endif
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index acbeb96..f98854c 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -61,7 +61,6 @@
 #define FATTR_SIZE	(1 << 3)
 #define FATTR_ATIME	(1 << 4)
 #define FATTR_MTIME	(1 << 5)
-#define FATTR_CTIME	(1 << 6)
 
 /**
  * Flags returned by the OPEN request
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index cd623ec..2401dea 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <linux/list.h>
 #include <linux/device.h>
+#include <linux/timer.h>
 
 struct gameport {
 
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 01796c4..eabdb5c 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -119,7 +119,7 @@
 	int policy;
 
 	atomic_t sync_io;		/* RAID */
-	unsigned long stamp, stamp_idle;
+	unsigned long stamp;
 	int in_flight;
 #ifdef	CONFIG_SMP
 	struct disk_stats *dkstats;
@@ -132,6 +132,7 @@
 struct disk_attribute {
 	struct attribute attr;
 	ssize_t (*show)(struct gendisk *, char *);
+	ssize_t (*store)(struct gendisk *, const char *, size_t);
 };
 
 /* 
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 3010e17..c377943 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -12,8 +12,8 @@
  * GFP bitmasks..
  */
 /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */
-#define __GFP_DMA	0x01u
-#define __GFP_HIGHMEM	0x02u
+#define __GFP_DMA	((__force gfp_t)0x01u)
+#define __GFP_HIGHMEM	((__force gfp_t)0x02u)
 
 /*
  * Action modifiers - doesn't change the zoning
@@ -26,24 +26,24 @@
  *
  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
  */
-#define __GFP_WAIT	0x10u	/* Can wait and reschedule? */
-#define __GFP_HIGH	0x20u	/* Should access emergency pools? */
-#define __GFP_IO	0x40u	/* Can start physical IO? */
-#define __GFP_FS	0x80u	/* Can call down to low-level FS? */
-#define __GFP_COLD	0x100u	/* Cache-cold page required */
-#define __GFP_NOWARN	0x200u	/* Suppress page allocation failure warning */
-#define __GFP_REPEAT	0x400u	/* Retry the allocation.  Might fail */
-#define __GFP_NOFAIL	0x800u	/* Retry for ever.  Cannot fail */
-#define __GFP_NORETRY	0x1000u	/* Do not retry.  Might fail */
-#define __GFP_NO_GROW	0x2000u	/* Slab internal usage */
-#define __GFP_COMP	0x4000u	/* Add compound page metadata */
-#define __GFP_ZERO	0x8000u	/* Return zeroed page on success */
-#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
-#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */
-#define __GFP_HARDWALL   0x40000u /* Enforce hardwall cpuset memory allocs */
+#define __GFP_WAIT	((__force gfp_t)0x10u)	/* Can wait and reschedule? */
+#define __GFP_HIGH	((__force gfp_t)0x20u)	/* Should access emergency pools? */
+#define __GFP_IO	((__force gfp_t)0x40u)	/* Can start physical IO? */
+#define __GFP_FS	((__force gfp_t)0x80u)	/* Can call down to low-level FS? */
+#define __GFP_COLD	((__force gfp_t)0x100u)	/* Cache-cold page required */
+#define __GFP_NOWARN	((__force gfp_t)0x200u)	/* Suppress page allocation failure warning */
+#define __GFP_REPEAT	((__force gfp_t)0x400u)	/* Retry the allocation.  Might fail */
+#define __GFP_NOFAIL	((__force gfp_t)0x800u)	/* Retry for ever.  Cannot fail */
+#define __GFP_NORETRY	((__force gfp_t)0x1000u)/* Do not retry.  Might fail */
+#define __GFP_NO_GROW	((__force gfp_t)0x2000u)/* Slab internal usage */
+#define __GFP_COMP	((__force gfp_t)0x4000u)/* Add compound page metadata */
+#define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
+#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
+#define __GFP_NORECLAIM  ((__force gfp_t)0x20000u) /* No realy zone reclaim during allocation */
+#define __GFP_HARDWALL   ((__force gfp_t)0x40000u) /* Enforce hardwall cpuset memory allocs */
 
 #define __GFP_BITS_SHIFT 20	/* Room for 20 __GFP_FOO bits */
-#define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
+#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /* if you forget to add the bitmask here kernel will crash, period */
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
@@ -64,6 +64,7 @@
 
 #define GFP_DMA		__GFP_DMA
 
+#define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK))
 
 /*
  * There is only one page-allocator function, and two main namespaces to
@@ -94,7 +95,7 @@
 		return NULL;
 
 	return __alloc_pages(gfp_mask, order,
-		NODE_DATA(nid)->node_zonelists + (gfp_mask & GFP_ZONEMASK));
+		NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask));
 }
 
 #ifdef CONFIG_NUMA
diff --git a/include/linux/hil.h b/include/linux/hil.h
new file mode 100644
index 0000000..13352d7
--- /dev/null
+++ b/include/linux/hil.h
@@ -0,0 +1,483 @@
+#ifndef _HIL_H_
+#define _HIL_H_
+
+/*
+ * Hewlett Packard Human Interface Loop (HP-HIL) Protocol -- header.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ * A note of thanks to HP for providing and shipping reference materials
+ * free of charge to help in the development of HIL support for Linux.
+ *
+ */
+
+#include <asm/types.h>
+
+/* Physical constants relevant to raw loop/device timing. 
+ */ 
+
+#define HIL_CLOCK		8MHZ
+#define HIL_EK1_CLOCK		30HZ
+#define HIL_EK2_CLOCK		60HZ
+
+#define HIL_TIMEOUT_DEV         5	/* ms */
+#define HIL_TIMEOUT_DEVS	10	/* ms */
+#define HIL_TIMEOUT_NORESP	10	/* ms */
+#define HIL_TIMEOUT_DEVS_DATA	16	/* ms */
+#define HIL_TIMEOUT_SELFTEST	200	/* ms */
+
+
+/* Actual wire line coding.  These will only be useful if someone is 
+ * implementing a software MLC to run HIL devices on a non-parisc machine.
+ */
+
+#define HIL_WIRE_PACKET_LEN	15
+enum hil_wire_bitpos {
+	HIL_WIRE_START		= 0,
+	HIL_WIRE_ADDR2,
+	HIL_WIRE_ADDR1,
+	HIL_WIRE_ADDR0,
+	HIL_WIRE_COMMAND,
+	HIL_WIRE_DATA7,
+	HIL_WIRE_DATA6,
+	HIL_WIRE_DATA5,
+	HIL_WIRE_DATA4,
+	HIL_WIRE_DATA3,
+	HIL_WIRE_DATA2,
+	HIL_WIRE_DATA1,
+	HIL_WIRE_DATA0,
+	HIL_WIRE_PARITY,
+	HIL_WIRE_STOP
+};
+
+/* HP documentation uses these bit positions to refer to commands;
+ * we will call these "packets".
+ */
+enum hil_pkt_bitpos {
+	HIL_PKT_CMD		= 0x00000800,
+	HIL_PKT_ADDR2		= 0x00000400,
+	HIL_PKT_ADDR1		= 0x00000200,
+	HIL_PKT_ADDR0		= 0x00000100,
+	HIL_PKT_ADDR_MASK	= 0x00000700,
+	HIL_PKT_ADDR_SHIFT	= 8,
+	HIL_PKT_DATA7		= 0x00000080,
+	HIL_PKT_DATA6		= 0x00000040,
+	HIL_PKT_DATA5		= 0x00000020,
+	HIL_PKT_DATA4		= 0x00000010,
+	HIL_PKT_DATA3		= 0x00000008,
+	HIL_PKT_DATA2		= 0x00000004,
+	HIL_PKT_DATA1		= 0x00000002,
+	HIL_PKT_DATA0		= 0x00000001,
+	HIL_PKT_DATA_MASK	= 0x000000FF,
+	HIL_PKT_DATA_SHIFT	= 0
+};
+
+/* The HIL MLC also has several error/status/control bits.  We extend the 
+ * "packet" to include these when direct access to the MLC is available,
+ * or emulate them in cases where they are not available. 
+ *
+ * This way the device driver knows that the underlying MLC driver
+ * has had to deal with loop errors.
+ */
+enum hil_error_bitpos {
+	HIL_ERR_OB	= 0x00000800, /* MLC is busy sending an auto-poll, 
+					 or we have filled up the output 
+					 buffer and must wait. */
+	HIL_ERR_INT	= 0x00010000, /* A normal interrupt has occurred. */
+	HIL_ERR_NMI	= 0x00020000, /* An NMI has occurred. */
+	HIL_ERR_LERR	= 0x00040000, /* A poll didn't come back. */
+	HIL_ERR_PERR	= 0x01000000, /* There was a Parity Error. */
+	HIL_ERR_FERR	= 0x02000000, /* There was a Framing Error. */
+	HIL_ERR_FOF	= 0x04000000  /* Input FIFO Overflowed. */
+};
+
+enum hil_control_bitpos {
+	HIL_CTRL_TEST	= 0x00010000,
+	HIL_CTRL_IPF	= 0x00040000,
+	HIL_CTRL_APE	= 0x02000000
+};
+
+/* Bits 30,31 are unused, we use them to control write behavior. */
+#define HIL_DO_ALTER_CTRL  0x40000000 /* Write MSW of packet to control 
+                                          before writing LSW to loop */
+#define HIL_CTRL_ONLY      0xc0000000 /* *Only* alter the control registers */
+
+/* This gives us a 32-bit "packet" 
+ */
+typedef u32 hil_packet;
+
+
+/* HIL Loop commands 
+ */
+enum hil_command {
+	HIL_CMD_IFC	= 0x00,	/* Interface Clear */
+	HIL_CMD_EPT	= 0x01,	/* Enter Pass-Thru Mode */
+	HIL_CMD_ELB	= 0x02,	/* Enter Loop-Back Mode */
+	HIL_CMD_IDD	= 0x03,	/* Identify and Describe */
+	HIL_CMD_DSR	= 0x04,	/* Device Soft Reset */
+	HIL_CMD_PST	= 0x05,	/* Perform Self Test */
+	HIL_CMD_RRG	= 0x06,	/* Read Register */
+	HIL_CMD_WRG	= 0x07,	/* Write Register */
+	HIL_CMD_ACF	= 0x08,	/* Auto Configure */
+	HIL_CMDID_ACF	= 0x07,	/* Auto Configure bits with incremented ID */
+	HIL_CMD_POL	= 0x10,	/* Poll */
+	HIL_CMDCT_POL	= 0x0f,	/* Poll command bits with item count  */
+	HIL_CMD_RPL	= 0x20,	/* RePoll */
+	HIL_CMDCT_RPL	= 0x0f,	/* RePoll command bits with item count */
+	HIL_CMD_RNM	= 0x30,	/* Report Name */
+	HIL_CMD_RST	= 0x31,	/* Report Status */
+	HIL_CMD_EXD	= 0x32,	/* Extended Describe */
+	HIL_CMD_RSC	= 0x33,	/* Report Security Code */
+
+	/* 0x34 to 0x3c reserved for future use  */
+
+	HIL_CMD_DKA	= 0x3d,	/* Disable Keyswitch Autorepeat */
+	HIL_CMD_EK1	= 0x3e,	/* Enable Keyswitch Autorepeat 1 */
+	HIL_CMD_EK2	= 0x3f,	/* Enable Keyswitch Autorepeat 2 */
+	HIL_CMD_PR1	= 0x40,	/* Prompt1 */  
+	HIL_CMD_PR2	= 0x41,	/* Prompt2 */
+	HIL_CMD_PR3	= 0x42,	/* Prompt3 */
+	HIL_CMD_PR4	= 0x43,	/* Prompt4 */
+	HIL_CMD_PR5	= 0x44,	/* Prompt5 */
+	HIL_CMD_PR6	= 0x45,	/* Prompt6 */
+	HIL_CMD_PR7	= 0x46,	/* Prompt7 */
+	HIL_CMD_PRM	= 0x47,	/* Prompt (General Purpose) */
+	HIL_CMD_AK1	= 0x48,	/* Acknowlege1 */  
+	HIL_CMD_AK2	= 0x49,	/* Acknowlege2 */
+	HIL_CMD_AK3	= 0x4a,	/* Acknowlege3 */
+	HIL_CMD_AK4	= 0x4b,	/* Acknowlege4 */
+	HIL_CMD_AK5	= 0x4c,	/* Acknowlege5 */
+	HIL_CMD_AK6	= 0x4d,	/* Acknowlege6 */
+	HIL_CMD_AK7	= 0x4e,	/* Acknowlege7 */
+	HIL_CMD_ACK	= 0x4f,	/* Acknowlege (General Purpose) */
+
+	/* 0x50 to 0x78 reserved for future use  */
+	/* 0x80 to 0xEF device-specific commands */
+	/* 0xf0 to 0xf9 reserved for future use  */
+
+	HIL_CMD_RIO	= 0xfa,	/* Register I/O Error */
+	HIL_CMD_SHR	= 0xfb,	/* System Hard Reset */
+	HIL_CMD_TER	= 0xfc,	/* Transmission Error */
+	HIL_CMD_CAE	= 0xfd,	/* Configuration Address Error */
+	HIL_CMD_DHR	= 0xfe,	/* Device Hard Reset */
+
+	/* 0xff is prohibited from use. */
+};
+
+
+/* 
+ * Response "records" to HIL commands
+ */
+
+/* Device ID byte 
+ */
+#define HIL_IDD_DID_TYPE_MASK		0xe0	/* Primary type bits */
+#define HIL_IDD_DID_TYPE_KB_INTEGRAL	0xa0	/* Integral keyboard */
+#define HIL_IDD_DID_TYPE_KB_ITF		0xc0	/* ITD keyboard */
+#define HIL_IDD_DID_TYPE_KB_RSVD	0xe0	/* Reserved keyboard type */
+#define HIL_IDD_DID_TYPE_KB_LANG_MASK	0x1f	/* Keyboard locale bits */
+#define HIL_IDD_DID_KBLANG_USE_ESD	0x00	/* Use ESD Locale instead */
+#define HIL_IDD_DID_TYPE_ABS		0x80    /* Absolute Positioners */
+#define HIL_IDD_DID_ABS_RSVD1_MASK	0xf8	/* Reserved */
+#define HIL_IDD_DID_ABS_RSVD1		0x98
+#define HIL_IDD_DID_ABS_TABLET_MASK	0xf8	/* Tablets and digitizers */
+#define HIL_IDD_DID_ABS_TABLET		0x90
+#define HIL_IDD_DID_ABS_TSCREEN_MASK	0xfc	/* Touch screens */
+#define HIL_IDD_DID_ABS_TSCREEN		0x8c
+#define HIL_IDD_DID_ABS_RSVD2_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_ABS_RSVD2		0x88
+#define HIL_IDD_DID_ABS_RSVD3_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_ABS_RSVD3		0x80
+#define HIL_IDD_DID_TYPE_REL		0x60    /* Relative Positioners */
+#define HIL_IDD_DID_REL_RSVD1_MASK	0xf0	/* Reserved */
+#define HIL_IDD_DID_REL_RSVD1		0x70
+#define HIL_IDD_DID_REL_RSVD2_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_REL_RSVD2		0x6c
+#define HIL_IDD_DID_REL_MOUSE_MASK	0xfc	/* Mouse */
+#define HIL_IDD_DID_REL_MOUSE		0x68
+#define HIL_IDD_DID_REL_QUAD_MASK	0xf8	/* Other Quadrature Devices */
+#define HIL_IDD_DID_REL_QUAD		0x60
+#define HIL_IDD_DID_TYPE_CHAR		0x40    /* Character Entry */
+#define HIL_IDD_DID_CHAR_BARCODE_MASK	0xfc	/* Barcode Reader */
+#define HIL_IDD_DID_CHAR_BARCODE	0x5c
+#define HIL_IDD_DID_CHAR_RSVD1_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_CHAR_RSVD1		0x58
+#define HIL_IDD_DID_CHAR_RSVD2_MASK	0xf8	/* Reserved */
+#define HIL_IDD_DID_CHAR_RSVD2		0x50
+#define HIL_IDD_DID_CHAR_RSVD3_MASK	0xf0	/* Reserved */
+#define HIL_IDD_DID_CHAR_RSVD3		0x40
+#define HIL_IDD_DID_TYPE_OTHER		0x20    /* Miscellaneous */
+#define HIL_IDD_DID_OTHER_RSVD1_MASK	0xf0	/* Reserved */
+#define HIL_IDD_DID_OTHER_RSVD1		0x30
+#define HIL_IDD_DID_OTHER_BARCODE_MASK	0xfc	/* Tone Generator */
+#define HIL_IDD_DID_OTHER_BARCODE	0x2c
+#define HIL_IDD_DID_OTHER_RSVD2_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_OTHER_RSVD2		0x28
+#define HIL_IDD_DID_OTHER_RSVD3_MASK	0xf8	/* Reserved */
+#define HIL_IDD_DID_OTHER_RSVD3		0x20
+#define HIL_IDD_DID_TYPE_KEYPAD		0x00	/* Vectra Keyboard */
+
+/* IDD record header 
+ */
+#define HIL_IDD_HEADER_AXSET_MASK	0x03    /* Number of axis in a set */
+#define HIL_IDD_HEADER_RSC		0x04	/* Supports RSC command */
+#define HIL_IDD_HEADER_EXD		0x08	/* Supports EXD command */
+#define HIL_IDD_HEADER_IOD		0x10	/* IOD byte to follow */
+#define HIL_IDD_HEADER_16BIT		0x20	/* 16 (vs. 8) bit resolution */
+#define HIL_IDD_HEADER_ABS		0x40	/* Reports Absolute Position */
+#define HIL_IDD_HEADER_2X_AXIS		0x80	/* Two sets of 1-3 axis */
+
+/* I/O Descriptor
+ */
+#define HIL_IDD_IOD_NBUTTON_MASK	0x07	/* Number of buttons */
+#define HIL_IDD_IOD_PROXIMITY		0x08	/* Proximity in/out events */
+#define HIL_IDD_IOD_PROMPT_MASK		0x70	/* Number of prompts/acks */
+#define HIL_IDD_IOD_PROMPT_SHIFT	4
+#define HIL_IDD_IOD_PROMPT		0x80	/* Generic prompt/ack */
+
+#define HIL_IDD_NUM_AXES_PER_SET(header_packet) \
+((header_packet) & HIL_IDD_HEADER_AXSET_MASK)
+
+#define HIL_IDD_NUM_AXSETS(header_packet) \
+(2 - !((header_packet) & HIL_IDD_HEADER_2X_AXIS))
+
+#define HIL_IDD_LEN(header_packet) \
+((4 - !(header_packet & HIL_IDD_HEADER_IOD) -			\
+  2 * !(HIL_IDD_NUM_AXES_PER_SET(header_packet))) +		\
+  2 * HIL_IDD_NUM_AXES_PER_SET(header_packet) *			\
+ !!((header_packet) & HIL_IDD_HEADER_ABS))
+
+/* The following HIL_IDD_* macros assume you have an array of 
+ * packets and/or unpacked 8-bit data in the order that they 
+ * were received.
+ */
+
+#define HIL_IDD_AXIS_COUNTS_PER_M(header_ptr) \
+(!(HIL_IDD_NUM_AXSETS(*(header_ptr))) ? -1 :			\
+(((*(header_ptr + 1) & HIL_PKT_DATA_MASK) +			\
+  ((*(header_ptr + 2) & HIL_PKT_DATA_MASK)) << 8)		\
+* ((*(header_ptr) & HIL_IDD_HEADER_16BIT) ? 100 : 1)))
+
+#define HIL_IDD_AXIS_MAX(header_ptr, __axnum) \
+((!(*(header_ptr) & HIL_IDD_HEADER_ABS) ||			\
+  (HIL_IDD_NUM_AXES_PER_SET(*(header_ptr)) <= __axnum)) ? 0 :	\
+ ((HIL_PKT_DATA_MASK & *((header_ptr) + 3 + 2 * __axnum)) +	\
+  ((HIL_PKT_DATA_MASK & *((header_ptr) + 4 + 2 * __axnum)) << 8)))
+
+#define HIL_IDD_IOD(header_ptr) \
+(*(header_ptr + HIL_IDD_LEN((*header_ptr)) - 1))
+
+#define HIL_IDD_HAS_GEN_PROMPT(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) &&				\
+ (HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_PROMPT))
+
+#define HIL_IDD_HAS_GEN_PROXIMITY(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) &&				\
+ (HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_PROXIMITY))
+
+#define HIL_IDD_NUM_BUTTONS(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) ?				\
+ (HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_NBUTTON_MASK) : 0)
+
+#define HIL_IDD_NUM_PROMPTS(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) ?				\
+ ((HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_NPROMPT_MASK)		\
+  >> HIL_IDD_IOD_PROMPT_SHIFT) : 0)
+
+/* The response to HIL EXD commands -- the "extended describe record" */
+#define	HIL_EXD_HEADER_WRG		0x03	/* Supports type2 WRG */
+#define HIL_EXD_HEADER_WRG_TYPE1	0x01	/* Supports type1 WRG */
+#define	HIL_EXD_HEADER_WRG_TYPE2	0x02	/* Supports type2 WRG */
+#define	HIL_EXD_HEADER_RRG		0x04	/* Supports RRG command */
+#define	HIL_EXD_HEADER_RNM		0x10	/* Supports RNM command */
+#define HIL_EXD_HEADER_RST		0x20	/* Supports RST command */
+#define HIL_EXD_HEADER_LOCALE		0x40	/* Contains locale code */
+
+#define HIL_EXD_NUM_RRG(header_ptr) \
+((*header_ptr & HIL_EXD_HEADER_RRG) ? \
+ (*(header_ptr + 1) & HIL_PKT_DATA_MASK) : 0)
+
+#define HIL_EXD_NUM_WWG(header_ptr) \
+((*header_ptr & HIL_EXD_HEADER_WRG) ?				\
+ (*(header_ptr + 2 - !(*header_ptr & HIL_EXD_HEADER_RRG)) &	\
+    HIL_PKT_DATA_MASK) : 0)
+
+#define HIL_EXD_LEN(header_ptr) \
+(!!(*header_ptr & HIL_EXD_HEADER_RRG) +				\
+ !!(*header_ptr & HIL_EXD_HEADER_WRG) +				\
+ !!(*header_ptr & HIL_EXD_HEADER_LOCALE) +			\
+ 2 * !!(*header_ptr & HIL_EXD_HEADER_WRG_TYPE2) + 1)
+
+#define HIL_EXD_LOCALE(header_ptr) \
+(!(*header_ptr & HIL_EXD_HEADER_LOCALE) ? -1 :			\
+ (*(header_ptr + HIL_EXD_LEN(header_ptr) - 1) & HIL_PKT_DATA_MASK))
+
+#define HIL_EXD_WRG_TYPE2_LEN(header_ptr) \
+(!(*header_ptr & HIL_EXD_HEADER_WRG_TYPE2) ? -1	:			\
+ (*(header_ptr + HIL_EXD_LEN(header_ptr) - 2 -                  	\
+    !!(*header_ptr & HIL_EXD_HEADER_LOCALE)) & HIL_PKT_DATA_MASK) +	\
+ ((*(header_ptr + HIL_EXD_LEN(header_ptr) - 1 -				\
+     !!(*header_ptr & HIL_EXD_HEADER_LOCALE)) & HIL_PKT_DATA_MASK) << 8))
+
+/* Device locale codes. */ 
+
+/* Last defined locale code.  Everything above this is "Reserved",
+   and note that this same table applies to the Device ID Byte where 
+   keyboards may have a nationality code which is only 5 bits. */
+#define HIL_LOCALE_MAX 0x1f
+
+/* Map to hopefully useful strings.  I was trying to make these look
+   like locale.aliases strings do; maybe that isn't the right table to
+   emulate.  In either case, I didn't have much to work on. */
+#define HIL_LOCALE_MAP \
+"",			/* 0x00 Reserved */		\
+"",			/* 0x01 Reserved */		\
+"",			/* 0x02 Reserved */		\
+"swiss.french",		/* 0x03 Swiss/French */		\
+"portuguese",		/* 0x04 Portuguese */		\
+"arabic",		/* 0x05 Arabic */		\
+"hebrew",		/* 0x06 Hebrew */		\
+"english.canadian",	/* 0x07 Canadian English */	\
+"turkish",		/* 0x08 Turkish */		\
+"greek",		/* 0x09 Greek */		\
+"thai",			/* 0x0a Thai (Thailand) */	\
+"italian",		/* 0x0b Italian */		\
+"korean",		/* 0x0c Hangul (Korea) */	\
+"dutch",		/* 0x0d Dutch */		\
+"swedish",		/* 0x0e Swedish */		\
+"german",		/* 0x0f German */		\
+"chinese",		/* 0x10 Chinese-PRC */		\
+"chinese",		/* 0x11 Chinese-ROC */		\
+"swiss.french",		/* 0x12 Swiss/French II */	\
+"spanish",		/* 0x13 Spanish */		\
+"swiss.german",		/* 0x14 Swiss/German II */	\
+"flemish",		/* 0x15 Belgian (Flemish) */	\
+"finnish",		/* 0x16 Finnish	*/		\
+"english.uk",		/* 0x17 United Kingdom */	\
+"french.canadian",	/* 0x18 French/Canadian */	\
+"swiss.german",		/* 0x19 Swiss/German */		\
+"norwegian",		/* 0x1a Norwegian */		\
+"french",		/* 0x1b French */		\
+"danish",		/* 0x1c Danish */		\
+"japanese",		/* 0x1d Katakana */		\
+"spanish",		/* 0x1e Latin American/Spanish*/\
+"english.us"		/* 0x1f United States */	\
+
+
+/* HIL keycodes */
+#define HIL_KEYCODES_SET1_TBLSIZE 128
+#define HIL_KEYCODES_SET1 	\
+   KEY_5,		KEY_RESERVED,	KEY_RIGHTALT,	KEY_LEFTALT,	\
+   KEY_RIGHTSHIFT,	KEY_LEFTSHIFT,	KEY_LEFTCTRL,	KEY_SYSRQ,	\
+   KEY_KP4,		KEY_KP8,	KEY_KP5,	KEY_KP9,	\
+   KEY_KP6,		KEY_KP7,	KEY_KPCOMMA,	KEY_KPENTER,	\
+   KEY_KP1,		KEY_KPSLASH,	KEY_KP2,	KEY_KPPLUS,	\
+   KEY_KP3,		KEY_KPASTERISK,	KEY_KP0,	KEY_KPMINUS,	\
+   KEY_B,		KEY_V,		KEY_C,		KEY_X,		\
+   KEY_Z,		KEY_RESERVED,	KEY_RESERVED,   KEY_ESC,	\
+   KEY_6,		KEY_F10,	KEY_3,		KEY_F11,	\
+   KEY_KPDOT,		KEY_F9,		KEY_TAB /*KP*/,	KEY_F12,	\
+   KEY_H,		KEY_G,		KEY_F,		KEY_D,		\
+   KEY_S,		KEY_A,		KEY_RESERVED,	KEY_CAPSLOCK,	\
+   KEY_U,		KEY_Y,		KEY_T,		KEY_R,		\
+   KEY_E,		KEY_W,		KEY_Q,		KEY_TAB,	\
+   KEY_7,		KEY_6,		KEY_5,		KEY_4,		\
+   KEY_3,		KEY_2,		KEY_1,		KEY_GRAVE,	\
+   KEY_F13,		KEY_F14,	KEY_F15,	KEY_F16,	\
+   KEY_F17,		KEY_F18,	KEY_F19,	KEY_F20,	\
+   KEY_MENU,		KEY_F4,		KEY_F3,		KEY_F2,		\
+   KEY_F1,		KEY_VOLUMEUP,	KEY_STOP,	KEY_SENDFILE,	\
+   KEY_SYSRQ,		KEY_F5,		KEY_F6,		KEY_F7,		\
+   KEY_F8,		KEY_VOLUMEDOWN,	KEY_DEL_EOL,	KEY_DEL_EOS,	\
+   KEY_8,		KEY_9,		KEY_0,		KEY_MINUS,	\
+   KEY_EQUAL,		KEY_BACKSPACE,	KEY_INS_LINE,	KEY_DEL_LINE,	\
+   KEY_I,		KEY_O,		KEY_P,		KEY_LEFTBRACE,	\
+   KEY_RIGHTBRACE,	KEY_BACKSLASH,	KEY_INSERT,	KEY_DELETE,	\
+   KEY_J,		KEY_K,		KEY_L,		KEY_SEMICOLON,	\
+   KEY_APOSTROPHE,	KEY_ENTER,	KEY_HOME,	KEY_PAGEUP,	\
+   KEY_M,		KEY_COMMA,	KEY_DOT,	KEY_SLASH,	\
+   KEY_BACKSLASH,	KEY_SELECT,	KEY_102ND,	KEY_PAGEDOWN,	\
+   KEY_N,		KEY_SPACE,	KEY_NEXT,	KEY_RESERVED,	\
+   KEY_LEFT,		KEY_DOWN,	KEY_UP,		KEY_RIGHT
+
+
+#define HIL_KEYCODES_SET3_TBLSIZE 128
+#define HIL_KEYCODES_SET3 	\
+  KEY_RESERVED,	KEY_ESC,	KEY_1,		KEY_2,			\
+  KEY_3,	KEY_4,		KEY_5,		KEY_6,			\
+  KEY_7,	KEY_8,		KEY_9,		KEY_0,			\
+  KEY_MINUS,	KEY_EQUAL,	KEY_BACKSPACE,	KEY_TAB,		\
+  KEY_Q,	KEY_W,		KEY_E,		KEY_R,			\
+  KEY_T,	KEY_Y,		KEY_U,		KEY_I,			\
+  KEY_O,	KEY_P,		KEY_LEFTBRACE,	KEY_RIGHTBRACE,		\
+  KEY_ENTER,	KEY_LEFTCTRL,	KEY_A,		KEY_S,			\
+  KEY_D,	KEY_F,		KEY_G,		KEY_H,			\
+  KEY_J,	KEY_K,		KEY_L,		KEY_SEMICOLON,		\
+  KEY_APOSTROPHE,KEY_GRAVE,	KEY_LEFTSHIFT,	KEY_BACKSLASH,		\
+  KEY_Z,	KEY_X,		KEY_C,		KEY_V,			\
+  KEY_B,	KEY_N,		KEY_M,		KEY_COMMA,		\
+  KEY_DOT,	KEY_SLASH,	KEY_RIGHTSHIFT,	KEY_KPASTERISK,		\
+  KEY_LEFTALT,	KEY_SPACE,	KEY_CAPSLOCK,	KEY_F1,			\
+  KEY_F2,	KEY_F3,		KEY_F4,		KEY_F5,			\
+  KEY_F6,	KEY_F7,		KEY_F8,		KEY_F9,			\
+  KEY_F10,	KEY_NUMLOCK,	KEY_SCROLLLOCK,	KEY_KP7,		\
+  KEY_KP8,	KEY_KP9,	KEY_KPMINUS,	KEY_KP4,		\
+  KEY_KP5,	KEY_KP6,	KEY_KPPLUS,	KEY_KP1,		\
+  KEY_KP2,	KEY_KP3,	KEY_KP0,	KEY_KPDOT,		\
+  KEY_SYSRQ,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_UP,	KEY_LEFT,	KEY_DOWN,	KEY_RIGHT,		\
+  KEY_HOME,	KEY_PAGEUP,	KEY_END,	KEY_PAGEDOWN,		\
+  KEY_INSERT,	KEY_DELETE,	KEY_102ND,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_F1,	KEY_F2,		KEY_F3,		KEY_F4,			\
+  KEY_F5,	KEY_F6,		KEY_F7,		KEY_F8,			\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED
+
+
+/* Response to POL command, the "poll record header" */
+
+#define HIL_POL_NUM_AXES_MASK	0x03	/* Number of axis reported */
+#define HIL_POL_CTS		0x04	/* Device ready to receive data */
+#define HIL_POL_STATUS_PENDING	0x08	/* Device has status to report */
+#define HIL_POL_CHARTYPE_MASK	0x70	/* Type of character data to follow */
+#define HIL_POL_CHARTYPE_NONE	0x00	/* No character data to follow */
+#define HIL_POL_CHARTYPE_RSVD1	0x10	/* Reserved Set 1 */
+#define HIL_POL_CHARTYPE_ASCII	0x20	/* U.S. ASCII */
+#define HIL_POL_CHARTYPE_BINARY	0x30	/* Binary data */
+#define HIL_POL_CHARTYPE_SET1	0x40	/* Keycode Set 1 */
+#define HIL_POL_CHARTYPE_RSVD2	0x50	/* Reserved Set 2 */
+#define HIL_POL_CHARTYPE_SET2	0x60	/* Keycode Set 2 */
+#define HIL_POL_CHARTYPE_SET3	0x70	/* Keycode Set 3 */
+#define HIL_POL_AXIS_ALT	0x80	/* Data is from axis set 2 */
+
+
+#endif /* _HIL_H_ */
diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
new file mode 100644
index 0000000..8df29ca
--- /dev/null
+++ b/include/linux/hil_mlc.h
@@ -0,0 +1,168 @@
+/*
+ * HP Human Interface Loop Master Link Controller driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <asm/semaphore.h>
+#include <linux/serio.h>
+#include <linux/list.h>
+
+typedef struct hil_mlc hil_mlc;
+
+/* The HIL has a complicated state engine.
+ * We define the structure of nodes in the state engine here.
+ */
+enum hilse_act {
+  	/* HILSE_OUT prepares to receive input if the next node
+	 * is an IN or EXPECT, and then sends the given packet.
+	 */
+	HILSE_OUT = 0,
+
+  	/* HILSE_CTS checks if the loop is busy. */
+	HILSE_CTS,
+
+	/* HILSE_OUT_LAST sends the given command packet to 
+	 * the last configured/running device on the loop.
+	 */
+	HILSE_OUT_LAST,
+
+	/* HILSE_OUT_DISC sends the given command packet to
+	 * the next device past the last configured/running one.
+	 */
+	HILSE_OUT_DISC,
+
+	/* HILSE_FUNC runs a callback function with given arguments.
+	 * a positive return value causes the "ugly" branch to be taken.
+	 */
+	HILSE_FUNC,
+
+  	/* HILSE_IN simply expects any non-errored packet to arrive 
+	 * within arg usecs.
+	 */
+	HILSE_IN		= 0x100,
+
+  	/* HILSE_EXPECT expects a particular packet to arrive 
+	 * within arg usecs, any other packet is considered an error.
+	 */
+	HILSE_EXPECT,
+
+  	/* HILSE_EXPECT_LAST as above but dev field should be last 
+	 * discovered/operational device.
+	 */
+	HILSE_EXPECT_LAST,
+
+  	/* HILSE_EXPECT_LAST as above but dev field should be first 
+	 * undiscovered/inoperational device.
+	 */
+	HILSE_EXPECT_DISC
+};
+
+typedef int	(hilse_func) (hil_mlc *mlc, int arg);
+struct hilse_node {
+	enum hilse_act		act;	/* How to process this node         */
+	union {
+		hilse_func	*func;	/* Function to call if HILSE_FUNC   */
+		hil_packet	packet;	/* Packet to send or to compare     */
+	} object;
+	int			arg;	/* Timeout in usec or parm for func */
+	int			good;	/* Node to jump to on success       */
+	int			bad;	/* Node to jump to on error         */
+	int			ugly;	/* Node to jump to on timeout       */
+};
+
+/* Methods for back-end drivers, e.g. hp_sdc_mlc */
+typedef int	(hil_mlc_cts) (hil_mlc *mlc);
+typedef void	(hil_mlc_out) (hil_mlc *mlc);
+typedef int	(hil_mlc_in)  (hil_mlc *mlc, suseconds_t timeout);
+
+struct hil_mlc_devinfo {
+	uint8_t	idd[16];	/* Device ID Byte and Describe Record */
+	uint8_t	rsc[16];	/* Security Code Header and Record */
+	uint8_t	exd[16];	/* Extended Describe Record */
+	uint8_t	rnm[16];	/* Device name as returned by RNM command */
+};
+
+struct hil_mlc_serio_map {
+	hil_mlc *mlc;
+	int di_revmap;
+	int didx;
+};
+
+/* How many (possibly old/detached) devices the we try to keep track of */
+#define HIL_MLC_DEVMEM 16
+
+struct hil_mlc {
+	struct list_head	list;	/* hil_mlc is organized as linked list */
+
+	rwlock_t		lock;
+
+	void *priv; /* Data specific to a particular type of MLC */
+
+	int 			seidx;	/* Current node in state engine */
+	int			istarted, ostarted;
+
+	hil_mlc_cts		*cts;
+	struct semaphore	csem;   /* Raised when loop idle */
+
+	hil_mlc_out		*out;
+	struct semaphore	osem;   /* Raised when outpacket dispatched */
+	hil_packet		opacket;
+
+	hil_mlc_in		*in;
+	struct semaphore	isem;   /* Raised when a packet arrives */
+	hil_packet		ipacket[16];
+	hil_packet		imatch;
+	int			icount;
+	struct timeval		instart;
+	suseconds_t		intimeout;
+
+	int			ddi;	/* Last operational device id */
+	int			lcv;	/* LCV to throttle loops */
+	struct timeval		lcv_tv; /* Time loop was started */
+
+	int			di_map[7]; /* Maps below items to live devs */
+	struct hil_mlc_devinfo	di[HIL_MLC_DEVMEM];
+	struct serio		*serio[HIL_MLC_DEVMEM];
+	struct hil_mlc_serio_map serio_map[HIL_MLC_DEVMEM];
+	hil_packet		serio_opacket[HIL_MLC_DEVMEM];
+	int			serio_oidx[HIL_MLC_DEVMEM];
+	struct hil_mlc_devinfo	di_scratch; /* Temporary area */
+
+	int			opercnt;
+
+	struct tasklet_struct	*tasklet;
+};
+
+int hil_mlc_register(hil_mlc *mlc);
+int hil_mlc_unregister(hil_mlc *mlc);
diff --git a/include/linux/hp_sdc.h b/include/linux/hp_sdc.h
new file mode 100644
index 0000000..debd715
--- /dev/null
+++ b/include/linux/hp_sdc.h
@@ -0,0 +1,300 @@
+/*
+ * HP i8042 System Device Controller -- header
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * 
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ * 	for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ *
+ */
+
+#ifndef _LINUX_HP_SDC_H
+#define _LINUX_HP_SDC_H
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#if defined(__hppa__)
+#include <asm/hardware.h>
+#endif
+
+
+/* No 4X status reads take longer than this (in usec).
+ */
+#define HP_SDC_MAX_REG_DELAY 20000
+
+typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
+			       uint8_t status, uint8_t data);
+
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback);
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback);
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback);
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback);
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback);
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback);
+
+typedef struct {
+	int actidx;	/* Start of act.  Acts are atomic WRT I/O to SDC */
+	int idx;	/* Index within the act */
+	int endidx;	/* transaction is over and done if idx == endidx */
+	uint8_t *seq;	/* commands/data for the transaction */
+	union {
+	  hp_sdc_irqhook   *irqhook;	/* Callback, isr or tasklet context */
+	  struct semaphore *semaphore;	/* Semaphore to sleep on. */
+	} act;
+} hp_sdc_transaction;
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this);
+
+/* The HP_SDC_ACT* values are peculiar to this driver.
+ * Nuance: never HP_SDC_ACT_DATAIN | HP_SDC_ACT_DEALLOC, use another
+ * act to perform the dealloc.
+ */
+#define HP_SDC_ACT_PRECMD	0x01		/* Send a command first */
+#define HP_SDC_ACT_DATAREG	0x02		/* Set data registers */
+#define HP_SDC_ACT_DATAOUT	0x04		/* Send data bytes */
+#define HP_SDC_ACT_POSTCMD      0x08            /* Send command after */
+#define HP_SDC_ACT_DATAIN	0x10		/* Collect data after */
+#define HP_SDC_ACT_DURING	0x1f
+#define HP_SDC_ACT_SEMAPHORE    0x20            /* Raise semaphore after */
+#define HP_SDC_ACT_CALLBACK	0x40		/* Pass data to IRQ handler */
+#define HP_SDC_ACT_DEALLOC	0x80		/* Destroy transaction after */
+#define HP_SDC_ACT_AFTER	0xe0
+#define HP_SDC_ACT_DEAD		0x60		/* Act timed out. */
+
+/* Rest of the flags are straightforward representation of the SDC interface */
+#define HP_SDC_STATUS_IBF	0x02	/* Input buffer full */
+
+#define HP_SDC_STATUS_IRQMASK	0xf0	/* Bits containing "level 1" irq */
+#define HP_SDC_STATUS_PERIODIC  0x10    /* Periodic 10ms timer */
+#define HP_SDC_STATUS_USERTIMER 0x20    /* "Special purpose" timer */
+#define HP_SDC_STATUS_TIMER     0x30    /* Both PERIODIC and USERTIMER */
+#define HP_SDC_STATUS_REG	0x40	/* Data from an i8042 register */
+#define HP_SDC_STATUS_HILCMD    0x50	/* Command from HIL MLC */
+#define HP_SDC_STATUS_HILDATA   0x60	/* Data from HIL MLC */
+#define HP_SDC_STATUS_PUP	0x70	/* Sucessful power-up self test */
+#define HP_SDC_STATUS_KCOOKED	0x80	/* Key from cooked kbd */
+#define HP_SDC_STATUS_KRPG	0xc0	/* Key from Repeat Gen */
+#define HP_SDC_STATUS_KMOD_SUP	0x10	/* Shift key is up */
+#define HP_SDC_STATUS_KMOD_CUP	0x20	/* Control key is up */
+
+#define HP_SDC_NMISTATUS_FHS	0x40	/* NMI is a fast handshake irq */
+
+/* Internal i8042 registers (there are more, but they are not too useful). */
+
+#define HP_SDC_USE		0x02	/* Resource usage (including OB bit) */
+#define HP_SDC_IM		0x04	/* Interrupt mask */
+#define HP_SDC_CFG		0x11	/* Configuration register */
+#define HP_SDC_KBLANGUAGE	0x12	/* Keyboard language */
+
+#define HP_SDC_D0		0x70	/* General purpose data buffer 0 */
+#define HP_SDC_D1		0x71	/* General purpose data buffer 1 */
+#define HP_SDC_D2		0x72	/* General purpose data buffer 2 */
+#define HP_SDC_D3		0x73	/* General purpose data buffer 3 */
+#define HP_SDC_VT1		0x74	/* Timer for voice 1 */
+#define HP_SDC_VT2		0x75	/* Timer for voice 2 */
+#define HP_SDC_VT3		0x76	/* Timer for voice 3 */
+#define HP_SDC_VT4		0x77	/* Timer for voice 4 */
+#define HP_SDC_KBN		0x78	/* Which HIL devs are Nimitz */
+#define HP_SDC_KBC		0x79	/* Which HIL devs are cooked kbds */
+#define HP_SDC_LPS		0x7a	/* i8042's view of HIL status */
+#define HP_SDC_LPC		0x7b	/* i8042's view of HIL "control" */
+#define HP_SDC_RSV  		0x7c	/* Reserved "for testing" */
+#define HP_SDC_LPR		0x7d    /* i8042 count of HIL reconfigs */
+#define HP_SDC_XTD		0x7e    /* "Extended Configuration" register */
+#define HP_SDC_STR		0x7f    /* i8042 self-test result */
+
+/* Bitfields for above registers */
+#define HP_SDC_USE_LOOP		0x04	/* Command is currently on the loop. */
+
+#define HP_SDC_IM_MASK          0x1f    /* these bits not part of cmd/status */
+#define HP_SDC_IM_FH		0x10	/* Mask the fast handshake irq */
+#define HP_SDC_IM_PT		0x08	/* Mask the periodic timer irq */
+#define HP_SDC_IM_TIMERS	0x04	/* Mask the MT/DT/CT irq */
+#define HP_SDC_IM_RESET		0x02	/* Mask the reset key irq */
+#define HP_SDC_IM_HIL		0x01	/* Mask the HIL MLC irq */
+
+#define HP_SDC_CFG_ROLLOVER	0x08	/* WTF is "N-key rollover"? */
+#define HP_SDC_CFG_KBD		0x10	/* There is a keyboard */
+#define HP_SDC_CFG_NEW		0x20	/* Supports/uses HIL MLC */
+#define HP_SDC_CFG_KBD_OLD	0x03	/* keyboard code for non-HIL */
+#define HP_SDC_CFG_KBD_NEW	0x07	/* keyboard code from HIL autoconfig */
+#define HP_SDC_CFG_REV		0x40	/* Code revision bit */
+#define HP_SDC_CFG_IDPROM	0x80	/* IDPROM present in kbd (not HIL) */
+
+#define HP_SDC_LPS_NDEV		0x07	/* # devices autoconfigured on HIL */
+#define HP_SDC_LPS_ACSUCC	0x08	/* loop autoconfigured successfully */
+#define HP_SDC_LPS_ACFAIL	0x80	/* last loop autoconfigure failed */
+
+#define HP_SDC_LPC_APE_IPF	0x01	/* HIL MLC APE/IPF (autopoll) set */
+#define HP_SDC_LPC_ARCONERR	0x02	/* i8042 autoreconfigs loop on err */
+#define HP_SDC_LPC_ARCQUIET	0x03	/* i8042 doesn't report autoreconfigs*/
+#define HP_SDC_LPC_COOK		0x10	/* i8042 cooks devices in _KBN */
+#define HP_SDC_LPC_RC		0x80	/* causes autoreconfig */
+
+#define HP_SDC_XTD_REV		0x07	/* contains revision code */
+#define HP_SDC_XTD_REV_STRINGS(val, str) \
+switch (val) {						\
+	case 0x1: str = "1820-3712"; break;		\
+	case 0x2: str = "1820-4379"; break;		\
+	case 0x3: str = "1820-4784"; break;		\
+	default: str = "unknown";			\
+};
+#define HP_SDC_XTD_BEEPER	0x08	/* TI SN76494 beeper available */
+#define HP_SDC_XTD_BBRTC	0x20	/* OKI MSM-58321 BBRTC present */
+
+#define HP_SDC_CMD_LOAD_RT	0x31	/* Load real time (from 8042) */
+#define HP_SDC_CMD_LOAD_FHS	0x36	/* Load the fast handshake timer */
+#define HP_SDC_CMD_LOAD_MT	0x38	/* Load the match timer */
+#define HP_SDC_CMD_LOAD_DT	0x3B	/* Load the delay timer */
+#define HP_SDC_CMD_LOAD_CT	0x3E	/* Load the cycle timer */
+
+#define HP_SDC_CMD_SET_IM	0x40    /* 010xxxxx == set irq mask */
+
+/* The documents provided do not explicitly state that all registers betweem 
+ * 0x01 and 0x1f inclusive can be read by sending their register index as a 
+ * command, but this is implied and appears to be the case.
+ */
+#define HP_SDC_CMD_READ_RAM	0x00	/* Load from i8042 RAM (autoinc) */
+#define HP_SDC_CMD_READ_USE	0x02	/* Undocumented! Load from usage reg */
+#define HP_SDC_CMD_READ_IM	0x04	/* Load current interrupt mask */
+#define HP_SDC_CMD_READ_KCC	0x11	/* Load primary kbd config code */
+#define HP_SDC_CMD_READ_KLC	0x12	/* Load primary kbd language code */
+#define HP_SDC_CMD_READ_T1	0x13	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T2	0x14	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T3	0x15	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T4	0x16	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T5	0x17	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_D0	0xf0	/* Load from i8042 RAM location 0x70 */
+#define HP_SDC_CMD_READ_D1	0xf1	/* Load from i8042 RAM location 0x71 */
+#define HP_SDC_CMD_READ_D2	0xf2	/* Load from i8042 RAM location 0x72 */
+#define HP_SDC_CMD_READ_D3	0xf3	/* Load from i8042 RAM location 0x73 */
+#define HP_SDC_CMD_READ_VT1	0xf4	/* Load from i8042 RAM location 0x74 */
+#define HP_SDC_CMD_READ_VT2	0xf5	/* Load from i8042 RAM location 0x75 */
+#define HP_SDC_CMD_READ_VT3	0xf6	/* Load from i8042 RAM location 0x76 */
+#define HP_SDC_CMD_READ_VT4	0xf7	/* Load from i8042 RAM location 0x77 */
+#define HP_SDC_CMD_READ_KBN	0xf8	/* Load from i8042 RAM location 0x78 */
+#define HP_SDC_CMD_READ_KBC	0xf9	/* Load from i8042 RAM location 0x79 */
+#define HP_SDC_CMD_READ_LPS	0xfa	/* Load from i8042 RAM location 0x7a */
+#define HP_SDC_CMD_READ_LPC	0xfb	/* Load from i8042 RAM location 0x7b */
+#define HP_SDC_CMD_READ_RSV	0xfc	/* Load from i8042 RAM location 0x7c */
+#define HP_SDC_CMD_READ_LPR	0xfd	/* Load from i8042 RAM location 0x7d */
+#define HP_SDC_CMD_READ_XTD	0xfe	/* Load from i8042 RAM location 0x7e */
+#define HP_SDC_CMD_READ_STR	0xff	/* Load from i8042 RAM location 0x7f */
+
+#define HP_SDC_CMD_SET_ARD	0xA0	/* Set emulated autorepeat delay */
+#define HP_SDC_CMD_SET_ARR	0xA2	/* Set emulated autorepeat rate */
+#define HP_SDC_CMD_SET_BELL	0xA3	/* Set voice 3 params for "beep" cmd */
+#define HP_SDC_CMD_SET_RPGR	0xA6	/* Set "RPG" irq rate (doesn't work) */
+#define HP_SDC_CMD_SET_RTMS	0xAD	/* Set the RTC time (milliseconds) */
+#define HP_SDC_CMD_SET_RTD	0xAF	/* Set the RTC time (days) */
+#define HP_SDC_CMD_SET_FHS	0xB2	/* Set fast handshake timer */
+#define HP_SDC_CMD_SET_MT	0xB4	/* Set match timer */
+#define HP_SDC_CMD_SET_DT	0xB7	/* Set delay timer */
+#define HP_SDC_CMD_SET_CT	0xBA	/* Set cycle timer */
+#define HP_SDC_CMD_SET_RAMP	0xC1	/* Reset READ_RAM autoinc counter */
+#define HP_SDC_CMD_SET_D0	0xe0	/* Load to i8042 RAM location 0x70 */
+#define HP_SDC_CMD_SET_D1	0xe1	/* Load to i8042 RAM location 0x71 */
+#define HP_SDC_CMD_SET_D2	0xe2	/* Load to i8042 RAM location 0x72 */
+#define HP_SDC_CMD_SET_D3	0xe3	/* Load to i8042 RAM location 0x73 */
+#define HP_SDC_CMD_SET_VT1	0xe4	/* Load to i8042 RAM location 0x74 */
+#define HP_SDC_CMD_SET_VT2	0xe5	/* Load to i8042 RAM location 0x75 */
+#define HP_SDC_CMD_SET_VT3	0xe6	/* Load to i8042 RAM location 0x76 */
+#define HP_SDC_CMD_SET_VT4	0xe7	/* Load to i8042 RAM location 0x77 */
+#define HP_SDC_CMD_SET_KBN	0xe8	/* Load to i8042 RAM location 0x78 */
+#define HP_SDC_CMD_SET_KBC	0xe9	/* Load to i8042 RAM location 0x79 */
+#define HP_SDC_CMD_SET_LPS	0xea	/* Load to i8042 RAM location 0x7a */
+#define HP_SDC_CMD_SET_LPC	0xeb	/* Load to i8042 RAM location 0x7b */
+#define HP_SDC_CMD_SET_RSV	0xec	/* Load to i8042 RAM location 0x7c */
+#define HP_SDC_CMD_SET_LPR	0xed	/* Load to i8042 RAM location 0x7d */
+#define HP_SDC_CMD_SET_XTD	0xee	/* Load to i8042 RAM location 0x7e */
+#define HP_SDC_CMD_SET_STR	0xef	/* Load to i8042 RAM location 0x7f */
+
+#define HP_SDC_CMD_DO_RTCW	0xc2	/* i8042 RAM 0x70 --> RTC */
+#define HP_SDC_CMD_DO_RTCR	0xc3	/* RTC[0x70 0:3] --> irq/status/data */
+#define HP_SDC_CMD_DO_BEEP	0xc4	/* i8042 RAM 0x70-74  --> beeper,VT3 */
+#define HP_SDC_CMD_DO_HIL	0xc5	/* i8042 RAM 0x70-73 --> 
+					   HIL MLC R0,R1 i8042 HIL watchdog */
+
+/* Values used to (de)mangle input/output to/from the HIL MLC */
+#define HP_SDC_DATA		0x40	/* Data from an 8042 register */
+#define HP_SDC_HIL_CMD		0x50	/* Data from HIL MLC R1/8042 */
+#define HP_SDC_HIL_R1MASK	0x0f	/* Contents of HIL MLC R1 0:3 */
+#define HP_SDC_HIL_AUTO		0x10	/* Set if POL results from i8042 */   
+#define HP_SDC_HIL_ISERR	0x80	/* Has meaning as in next 4 values */
+#define HP_SDC_HIL_RC_DONE	0x80	/* i8042 auto-configured loop */
+#define HP_SDC_HIL_ERR		0x81	/* HIL MLC R2 had a bit set */
+#define HP_SDC_HIL_TO		0x82	/* i8042 HIL watchdog expired */
+#define HP_SDC_HIL_RC		0x84	/* i8042 is auto-configuring loop */
+#define HP_SDC_HIL_DAT		0x60	/* Data from HIL MLC R0 */
+
+
+typedef struct {
+	rwlock_t	ibf_lock;
+	rwlock_t	lock;		/* user/tasklet lock */
+	rwlock_t	rtq_lock;	/* isr/tasklet lock */
+	rwlock_t	hook_lock;	/* isr/user lock for handler add/del */
+
+	unsigned int	irq, nmi;	/* Our IRQ lines */
+	unsigned long	base_io, status_io, data_io; /* Our IO ports */
+
+	uint8_t		im;		/* Interrupt mask */
+	int		set_im; 	/* Interrupt mask needs to be set. */
+
+	int		ibf;		/* Last known status of IBF flag */
+	uint8_t		wi;		/* current i8042 write index */
+	uint8_t		r7[4];          /* current i8042[0x70 - 0x74] values */
+	uint8_t		r11, r7e;	/* Values from version/revision regs */
+
+	hp_sdc_irqhook	*timer, *reg, *hil, *pup, *cooked;
+
+#define HP_SDC_QUEUE_LEN 16
+	hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
+
+	int		rcurr, rqty;	/* Current read transact in process */
+	struct timeval	rtv;		/* Time when current read started */
+	int		wcurr;		/* Current write transact in process */
+
+	int		dev_err;	/* carries status from registration */
+#if defined(__hppa__)
+	struct parisc_device	*dev;
+#elif defined(__mc68000__)
+	void		*dev;
+#else
+#error No support for device registration on this arch yet.
+#endif
+
+	struct timer_list kicker;	/* Keeps below task alive */
+	struct tasklet_struct	task;
+
+} hp_i8042_sdc;
+
+#endif /* _LINUX_HP_SDC_H */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index d664330..0cea162 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -16,7 +16,6 @@
 int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
 int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
 int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
-void zap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
 void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
 int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
 int hugetlb_report_meminfo(char *);
@@ -87,7 +86,6 @@
 #define follow_huge_addr(mm, addr, write)	ERR_PTR(-EINVAL)
 #define copy_hugetlb_page_range(src, dst, vma)	({ BUG(); 0; })
 #define hugetlb_prefault(mapping, vma)		({ BUG(); 0; })
-#define zap_hugepage_range(vma, start, len)	BUG()
 #define unmap_hugepage_range(vma, start, end)	BUG()
 #define is_hugepage_mem_enough(size)		0
 #define hugetlb_report_meminfo(buf)		0
diff --git a/include/linux/i2c-algo-bit.h b/include/linux/i2c-algo-bit.h
index 1109044..c0e7fab 100644
--- a/include/linux/i2c-algo-bit.h
+++ b/include/linux/i2c-algo-bit.h
@@ -21,8 +21,6 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-algo-bit.h,v 1.10 2003/01/21 08:08:16 kmalkki Exp $ */
-
 #ifndef _LINUX_I2C_ALGO_BIT_H
 #define _LINUX_I2C_ALGO_BIT_H
 
@@ -46,8 +44,6 @@
 	int timeout;		/* in jiffies */
 };
 
-#define I2C_BIT_ADAP_MAX	16
-
 int i2c_bit_add_bus(struct i2c_adapter *);
 int i2c_bit_del_bus(struct i2c_adapter *);
 
diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
index 941b786..226693e 100644
--- a/include/linux/i2c-algo-pca.h
+++ b/include/linux/i2c-algo-pca.h
@@ -9,8 +9,6 @@
 	int  (*wait_for_interrupt)	(struct i2c_algo_pca_data *adap);
 };
 
-#define I2C_PCA_ADAP_MAX	16
-
 int i2c_pca_add_bus(struct i2c_adapter *);
 int i2c_pca_del_bus(struct i2c_adapter *);
 
diff --git a/include/linux/i2c-algo-pcf.h b/include/linux/i2c-algo-pcf.h
index 2a50856..18b0adf 100644
--- a/include/linux/i2c-algo-pcf.h
+++ b/include/linux/i2c-algo-pcf.h
@@ -22,8 +22,6 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-algo-pcf.h,v 1.8 2003/01/21 08:08:16 kmalkki Exp $ */
-
 #ifndef _LINUX_I2C_ALGO_PCF_H
 #define _LINUX_I2C_ALGO_PCF_H
 
@@ -41,8 +39,6 @@
 	int timeout;
 };
 
-#define I2C_PCF_ADAP_MAX	16
-
 int i2c_pcf_add_bus(struct i2c_adapter *);
 int i2c_pcf_del_bus(struct i2c_adapter *);
 
diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h
index 5416956..81c229a 100644
--- a/include/linux/i2c-dev.h
+++ b/include/linux/i2c-dev.h
@@ -19,8 +19,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* $Id: i2c-dev.h,v 1.13 2003/01/21 08:08:16 kmalkki Exp $ */
-
 #ifndef _LINUX_I2C_DEV_H
 #define _LINUX_I2C_DEV_H
 
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 44f3087..1ce4b54 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -164,10 +164,7 @@
 
 /* --- Bit algorithm adapters 						*/
 #define I2C_HW_B_LP		0x010000 /* Parallel port Philips style */
-#define I2C_HW_B_LPC		0x010001 /* Parallel port control reg. */
 #define I2C_HW_B_SER		0x010002 /* Serial line interface */
-#define I2C_HW_B_ELV		0x010003 /* ELV Card */
-#define I2C_HW_B_VELLE		0x010004 /* Vellemann K8000 */
 #define I2C_HW_B_BT848		0x010005 /* BT848 video boards */
 #define I2C_HW_B_WNV		0x010006 /* Winnov Videums */
 #define I2C_HW_B_VIA		0x010007 /* Via vt82c586b */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 3d49a30..5e19a7b 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -23,15 +23,15 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c.h,v 1.68 2003/01/21 08:08:16 kmalkki Exp $ */
-
 #ifndef _LINUX_I2C_H
 #define _LINUX_I2C_H
 
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/i2c-id.h>
+#include <linux/mod_devicetable.h>
 #include <linux/device.h>	/* for struct device */
+#include <linux/sched.h>	/* for completion */
 #include <asm/semaphore.h>
 
 /* --- For i2c-isa ---------------------------------------------------- */
@@ -94,10 +94,10 @@
 extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
 extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                      u8 command, u16 value);
-/* Returns the number of bytes transferred */
 extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
 				      u8 command, u8 length,
 				      u8 *values);
+/* Returns the number of read bytes */
 extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
 					 u8 command, u8 *values);
 
@@ -391,10 +391,6 @@
 #define I2C_FUNC_10BIT_ADDR		0x00000002
 #define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
 #define I2C_FUNC_SMBUS_HWPEC_CALC	0x00000008 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC  0x00000800 /* SMBus 2.0 */ 
-#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ 
-#define I2C_FUNC_SMBUS_PROC_CALL_PEC	0x00002000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */
 #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0x00008000 /* SMBus 2.0 */
 #define I2C_FUNC_SMBUS_QUICK		0x00010000 
 #define I2C_FUNC_SMBUS_READ_BYTE	0x00020000 
@@ -410,8 +406,6 @@
 #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK	0x08000000 /* w/ 1-byte reg. addr. */
 #define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2	 0x10000000 /* I2C-like block xfer  */
 #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC  0x40000000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */
 
 #define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
                              I2C_FUNC_SMBUS_WRITE_BYTE)
@@ -425,17 +419,6 @@
                                   I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
 #define I2C_FUNC_SMBUS_I2C_BLOCK_2 (I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
                                     I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2)
-#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC (I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
-                                       I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC)
-#define I2C_FUNC_SMBUS_WORD_DATA_PEC  (I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
-                                       I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC)
-
-#define I2C_FUNC_SMBUS_READ_BYTE_PEC		I2C_FUNC_SMBUS_READ_BYTE_DATA
-#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC		I2C_FUNC_SMBUS_WRITE_BYTE_DATA
-#define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC	I2C_FUNC_SMBUS_READ_WORD_DATA
-#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC	I2C_FUNC_SMBUS_WRITE_WORD_DATA
-#define I2C_FUNC_SMBUS_BYTE_PEC			I2C_FUNC_SMBUS_BYTE_DATA
-#define I2C_FUNC_SMBUS_BYTE_DATA_PEC		I2C_FUNC_SMBUS_WORD_DATA
 
 #define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
                              I2C_FUNC_SMBUS_BYTE | \
@@ -443,20 +426,17 @@
                              I2C_FUNC_SMBUS_WORD_DATA | \
                              I2C_FUNC_SMBUS_PROC_CALL | \
                              I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
-                             I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
                              I2C_FUNC_SMBUS_I2C_BLOCK)
 
 /* 
  * Data for SMBus Messages 
  */
 #define I2C_SMBUS_BLOCK_MAX	32	/* As specified in SMBus standard */	
-#define I2C_SMBUS_I2C_BLOCK_MAX	32	/* Not specified but we use same structure */
 union i2c_smbus_data {
 	__u8 byte;
 	__u16 word;
-	__u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */
-                          /* one more for read length in block process call */
-	                                            /* and one more for PEC */
+	__u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+	                       /* and one more for user-space compatibility */
 };
 
 /* smbus_access read or write markers */
@@ -473,10 +453,6 @@
 #define I2C_SMBUS_BLOCK_DATA	    5
 #define I2C_SMBUS_I2C_BLOCK_DATA    6
 #define I2C_SMBUS_BLOCK_PROC_CALL   7		/* SMBus 2.0 */
-#define I2C_SMBUS_BLOCK_DATA_PEC    8		/* SMBus 2.0 */
-#define I2C_SMBUS_PROC_CALL_PEC     9		/* SMBus 2.0 */
-#define I2C_SMBUS_BLOCK_PROC_CALL_PEC  10	/* SMBus 2.0 */
-#define I2C_SMBUS_WORD_DATA_PEC	   11		/* SMBus 2.0 */
 
 
 /* ----- commands for the ioctl like i2c_command call:
@@ -506,11 +482,6 @@
 
 #define I2C_SMBUS	0x0720	/* SMBus-level access */
 
-/* ... algo-bit.c recognizes */
-#define I2C_UDELAY	0x0705	/* set delay in microsecs between each	*/
-				/* written byte (except address)	*/
-#define I2C_MDELAY	0x0706	/* millisec delay between written bytes */
-
 /* ----- I2C-DEV: char device interface stuff ------------------------- */
 
 #define I2C_MAJOR	89		/* Device major number		*/
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index bdc286e..d79c8a4 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -25,10 +25,14 @@
 /* How many different OSM's are we allowing */
 #define I2O_MAX_DRIVERS		8
 
-#include <asm/io.h>
-#include <asm/semaphore.h>	/* Needed for MUTEX init macros */
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>	/* work_struct */
+
+#include <asm/io.h>
+#include <asm/semaphore.h>	/* Needed for MUTEX init macros */
 
 /* message queue empty */
 #define I2O_QUEUE_EMPTY		0xffffffff
@@ -66,8 +70,6 @@
 	struct device device;
 
 	struct semaphore lock;	/* device lock */
-
-	struct class_device classdev;	/* i2o device class */
 };
 
 /*
@@ -194,7 +196,7 @@
 	struct resource mem_resource;	/* Mem resource allocated to the IOP */
 
 	struct device device;
-	struct class_device classdev;	/* I2O controller class */
+	struct class_device *classdev;	/* I2O controller class device */
 	struct i2o_device *exec;	/* Executive */
 #if BITS_PER_LONG == 64
 	spinlock_t context_list_lock;	/* lock for context_list */
@@ -492,7 +494,7 @@
  *	Returns 0 on success or -ENOMEM on failure.
  */
 static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
-				size_t len, unsigned int gfp_mask)
+				size_t len, gfp_t gfp_mask)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	int dma_64 = 0;
@@ -551,7 +553,7 @@
  *	Returns the 0 on success or negative error code on failure.
  */
 static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
-				  size_t len, unsigned int gfp_mask)
+				  size_t len, gfp_t gfp_mask)
 {
 	i2o_dma_free(dev, addr);
 
diff --git a/include/linux/ibmtr.h b/include/linux/ibmtr.h
index 2ef0b21..1c7a0dd 100644
--- a/include/linux/ibmtr.h
+++ b/include/linux/ibmtr.h
@@ -7,8 +7,8 @@
 /* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */
 
 #define TR_RETRY_INTERVAL	(30*HZ)	/* 500 on PC = 5 s */
-#define TR_RST_TIME		(HZ/20) /* 5 on PC = 50 ms */
-#define TR_BUSY_INTERVAL	(HZ/5)	/* 5 on PC = 200 ms */
+#define TR_RST_TIME		(msecs_to_jiffies(50))	/* 5 on PC = 50 ms */
+#define TR_BUSY_INTERVAL	(msecs_to_jiffies(200))	/* 5 on PC = 200 ms */
 #define TR_SPIN_INTERVAL	(3*HZ)	/* 3 seconds before init timeout */
 
 #define TR_ISA 1
diff --git a/include/linux/ide.h b/include/linux/ide.h
index a6dbb51..3461abc 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -218,7 +218,7 @@
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_forced
+		ide_au1xxx, ide_forced
 } hwif_chipset_t;
 
 /*
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 3d5de45..7fb3ff9 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -71,7 +71,7 @@
  */
 
 void *idr_find(struct idr *idp, int id);
-int idr_pre_get(struct idr *idp, unsigned gfp_mask);
+int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
 int idr_get_new(struct idr *idp, void *ptr, int *id);
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
 void idr_remove(struct idr *idp, int id);
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 0856548..a8b1a20 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -84,6 +84,7 @@
 #define ARPHRD_IEEE802_TR 800		/* Magic type ident for TR	*/
 #define ARPHRD_IEEE80211 801		/* IEEE 802.11			*/
 #define ARPHRD_IEEE80211_PRISM 802	/* IEEE 802.11 + Prism2 header  */
+#define ARPHRD_IEEE80211_RADIOTAP 803	/* IEEE 802.11 + radiotap header */
 
 #define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */
 #define ARPHRD_NONE	  0xFFFE	/* zero header length */
diff --git a/include/linux/input.h b/include/linux/input.h
index e8c296f..f623c74 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -12,6 +12,7 @@
 #ifdef __KERNEL__
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/device.h>
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
@@ -644,6 +645,7 @@
 #define BUS_ADB			0x17
 #define BUS_I2C			0x18
 #define BUS_HOST		0x19
+#define BUS_GSC			0x1A
 
 /*
  * Values describing the status of an effect
@@ -889,11 +891,15 @@
 	struct semaphore sem;	/* serializes open and close operations */
 	unsigned int users;
 
-	struct device *dev;
+	struct class_device cdev;
+	struct device *dev;	/* will be removed soon */
+
+	int dynalloc;	/* temporarily */
 
 	struct list_head	h_list;
 	struct list_head	node;
 };
+#define to_input_dev(d) container_of(d, struct input_dev, cdev)
 
 /*
  * Structure for hotplug & device<->driver matching.
@@ -984,6 +990,23 @@
 	INIT_LIST_HEAD(&dev->node);
 }
 
+struct input_dev *input_allocate_device(void);
+
+static inline void input_free_device(struct input_dev *dev)
+{
+	kfree(dev);
+}
+
+static inline struct input_dev *input_get_device(struct input_dev *dev)
+{
+	return to_input_dev(class_device_get(&dev->cdev));
+}
+
+static inline void input_put_device(struct input_dev *dev)
+{
+	class_device_put(&dev->cdev);
+}
+
 void input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
@@ -1052,7 +1075,7 @@
 	dev->absbit[LONG(axis)] |= BIT(axis);
 }
 
-extern struct class *input_class;
+extern struct class input_class;
 
 #endif
 #endif
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index ff853b3..be197eb 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -69,7 +69,7 @@
 #define jbd_debug(f, a...)	/**/
 #endif
 
-extern void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry);
+extern void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
 #define jbd_kmalloc(size, flags) \
 	__jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
 #define jbd_rep_kmalloc(size, flags) \
@@ -890,7 +890,7 @@
 extern void	 journal_sync_buffer (struct buffer_head *);
 extern int	 journal_invalidatepage(journal_t *,
 				struct page *, unsigned long);
-extern int	 journal_try_to_free_buffers(journal_t *, struct page *, int);
+extern int	 journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
 extern int	 journal_stop(handle_t *);
 extern int	 journal_flush (journal_t *);
 extern void	 journal_lock_updates (journal_t *);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4367ce4..f1925cc 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -307,7 +307,7 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
-/* Force a compilation error if condition is false */
+/* Force a compilation error if condition is true */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
 
 #ifdef CONFIG_SYSCTL
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h
index 7a2e332..e8b8a7a 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -24,7 +24,8 @@
 #define	KEY_WRITE	0x04	/* require permission to update / modify */
 #define	KEY_SEARCH	0x08	/* require permission to search (keyring) or find (key) */
 #define	KEY_LINK	0x10	/* require permission to link */
-#define	KEY_ALL		0x1f	/* all the above permissions */
+#define	KEY_SETATTR	0x20	/* require permission to change attributes */
+#define	KEY_ALL		0x3f	/* all the above permissions */
 
 /*
  * the keyring payload contains a list of the keys to which the keyring is
diff --git a/include/linux/key.h b/include/linux/key.h
index f1efa01..53513a3 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -40,28 +40,32 @@
 #define KEY_POS_WRITE	0x04000000	/* possessor can update key payload / add link to keyring */
 #define KEY_POS_SEARCH	0x08000000	/* possessor can find a key in search / search a keyring */
 #define KEY_POS_LINK	0x10000000	/* possessor can create a link to a key/keyring */
-#define KEY_POS_ALL	0x1f000000
+#define KEY_POS_SETATTR	0x20000000	/* possessor can set key attributes */
+#define KEY_POS_ALL	0x3f000000
 
 #define KEY_USR_VIEW	0x00010000	/* user permissions... */
 #define KEY_USR_READ	0x00020000
 #define KEY_USR_WRITE	0x00040000
 #define KEY_USR_SEARCH	0x00080000
 #define KEY_USR_LINK	0x00100000
-#define KEY_USR_ALL	0x001f0000
+#define KEY_USR_SETATTR	0x00200000
+#define KEY_USR_ALL	0x003f0000
 
 #define KEY_GRP_VIEW	0x00000100	/* group permissions... */
 #define KEY_GRP_READ	0x00000200
 #define KEY_GRP_WRITE	0x00000400
 #define KEY_GRP_SEARCH	0x00000800
 #define KEY_GRP_LINK	0x00001000
-#define KEY_GRP_ALL	0x00001f00
+#define KEY_GRP_SETATTR	0x00002000
+#define KEY_GRP_ALL	0x00003f00
 
 #define KEY_OTH_VIEW	0x00000001	/* third party permissions... */
 #define KEY_OTH_READ	0x00000002
 #define KEY_OTH_WRITE	0x00000004
 #define KEY_OTH_SEARCH	0x00000008
 #define KEY_OTH_LINK	0x00000010
-#define KEY_OTH_ALL	0x0000001f
+#define KEY_OTH_SETATTR	0x00000020
+#define KEY_OTH_ALL	0x0000003f
 
 struct seq_file;
 struct user_struct;
@@ -119,6 +123,7 @@
 	struct key_type		*type;		/* type of key */
 	struct rw_semaphore	sem;		/* change vs change sem */
 	struct key_user		*user;		/* owner of this key */
+	void			*security;	/* security data for this key */
 	time_t			expiry;		/* time at which key expires (or 0) */
 	uid_t			uid;
 	gid_t			gid;
diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h
index b6cc10b..cbe7d80 100644
--- a/include/linux/kobj_map.h
+++ b/include/linux/kobj_map.h
@@ -1,5 +1,7 @@
 #ifdef __KERNEL__
 
+#include <asm/semaphore.h>
+
 typedef struct kobject *kobj_probe_t(dev_t, int *, void *);
 struct kobj_map;
 
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 3b22304..7f7403a 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -65,7 +65,7 @@
 extern struct kobject * kobject_get(struct kobject *);
 extern void kobject_put(struct kobject *);
 
-extern char * kobject_get_path(struct kobject *, int);
+extern char * kobject_get_path(struct kobject *, gfp_t);
 
 struct kobj_type {
 	void (*release)(struct kobject *);
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index 3fa7864..ebdd41f 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -70,6 +70,18 @@
 int kthread_stop(struct task_struct *k);
 
 /**
+ * kthread_stop_sem: stop a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ * @s: semaphore that @k waits on while idle.
+ *
+ * Does essentially the same thing as kthread_stop() above, but wakes
+ * @k by calling up(@s).
+ *
+ * Returns the result of threadfn(), or -EINTR if wake_up_process()
+ * was never called. */
+int kthread_stop_sem(struct task_struct *k, struct semaphore *s);
+
+/**
  * kthread_should_stop: should this kthread return now?
  *
  * When someone calls kthread_stop on your kthread, it will be woken
diff --git a/include/linux/libata.h b/include/linux/libata.h
index ceee1fc..0ba3af7 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -91,12 +91,13 @@
 	ATA_SHT_EMULATED	= 1,
 	ATA_SHT_CMD_PER_LUN	= 1,
 	ATA_SHT_THIS_ID		= -1,
-	ATA_SHT_USE_CLUSTERING	= 0,
+	ATA_SHT_USE_CLUSTERING	= 1,
 
 	/* struct ata_device stuff */
 	ATA_DFLAG_LBA48		= (1 << 0), /* device supports LBA48 */
 	ATA_DFLAG_PIO		= (1 << 1), /* device currently in PIO mode */
 	ATA_DFLAG_LOCK_SECTORS	= (1 << 2), /* don't adjust max_sectors */
+	ATA_DFLAG_LBA		= (1 << 3), /* device supports LBA */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -154,17 +155,28 @@
 	ATA_SHIFT_UDMA		= 0,
 	ATA_SHIFT_MWDMA		= 8,
 	ATA_SHIFT_PIO		= 11,
+	
+	/* Masks for port functions */
+	ATA_PORT_PRIMARY	= (1 << 0),
+	ATA_PORT_SECONDARY	= (1 << 1),
 };
 
-enum pio_task_states {
-	PIO_ST_UNKNOWN,
-	PIO_ST_IDLE,
-	PIO_ST_POLL,
-	PIO_ST_TMOUT,
-	PIO_ST,
-	PIO_ST_LAST,
-	PIO_ST_LAST_POLL,
-	PIO_ST_ERR,
+enum hsm_task_states {
+	HSM_ST_UNKNOWN,
+	HSM_ST_IDLE,
+	HSM_ST_POLL,
+	HSM_ST_TMOUT,
+	HSM_ST,
+	HSM_ST_LAST,
+	HSM_ST_LAST_POLL,
+	HSM_ST_ERR,
+};
+
+enum ata_completion_errors {
+	AC_ERR_OTHER		= (1 << 0),
+	AC_ERR_DEV		= (1 << 1),
+	AC_ERR_ATA_BUS		= (1 << 2),
+	AC_ERR_HOST_BUS		= (1 << 3),
 };
 
 /* forward declarations */
@@ -174,7 +186,7 @@
 struct ata_queued_cmd;
 
 /* typedefs */
-typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat);
+typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int err_mask);
 
 struct ata_ioports {
 	unsigned long		cmd_addr;
@@ -197,7 +209,7 @@
 struct ata_probe_ent {
 	struct list_head	node;
 	struct device 		*dev;
-	struct ata_port_operations	*port_ops;
+	const struct ata_port_operations *port_ops;
 	Scsi_Host_Template	*sht;
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
@@ -220,7 +232,7 @@
 	void __iomem		*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
-	struct ata_port_operations *ops;
+	const struct ata_port_operations *ops;
 	struct ata_port *	ports[0];
 };
 
@@ -278,15 +290,18 @@
 	u8			xfer_mode;
 	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
 
-	/* cache info about current transfer mode */
-	u8			xfer_protocol;	/* taskfile xfer protocol */
-	u8			read_cmd;	/* opcode to use on read */
-	u8			write_cmd;	/* opcode to use on write */
+	unsigned int		multi_count;	/* sectors count for
+						   READ/WRITE MULTIPLE */
+
+	/* for CHS addressing */
+	u16			cylinders;	/* Number of cylinders */
+	u16			heads;		/* Number of heads */
+	u16			sectors;	/* Number of sectors per track */
 };
 
 struct ata_port {
 	struct Scsi_Host	*host;	/* our co-allocated scsi host */
-	struct ata_port_operations	*ops;
+	const struct ata_port_operations *ops;
 	unsigned long		flags;	/* ATA_FLAG_xxx */
 	unsigned int		id;	/* unique id req'd by scsi midlyr */
 	unsigned int		port_no; /* unique port #; from zero */
@@ -319,7 +334,7 @@
 	struct work_struct	packet_task;
 
 	struct work_struct	pio_task;
-	unsigned int		pio_task_state;
+	unsigned int		hsm_task_state;
 	unsigned long		pio_task_timeout;
 
 	void			*private_data;
@@ -333,13 +348,12 @@
 	void (*set_piomode) (struct ata_port *, struct ata_device *);
 	void (*set_dmamode) (struct ata_port *, struct ata_device *);
 
-	void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
+	void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
 	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
 
-	void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
+	void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf);
 	u8   (*check_status)(struct ata_port *ap);
 	u8   (*check_altstatus)(struct ata_port *ap);
-	u8   (*check_err)(struct ata_port *ap);
 	void (*dev_select)(struct ata_port *ap, unsigned int device);
 
 	void (*phy_reset) (struct ata_port *ap);
@@ -377,9 +391,22 @@
 	unsigned long		pio_mask;
 	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
-	struct ata_port_operations	*port_ops;
+	const struct ata_port_operations *port_ops;
 };
 
+struct ata_timing {
+	unsigned short mode;		/* ATA mode */
+	unsigned short setup;		/* t1 */
+	unsigned short act8b;		/* t2 for 8-bit I/O */
+	unsigned short rec8b;		/* t2i for 8-bit I/O */
+	unsigned short cyc8b;		/* t0 for 8-bit I/O */
+	unsigned short active;		/* t2 or tD */
+	unsigned short recover;		/* t2i or tK */
+	unsigned short cycle;		/* t0 */
+	unsigned short udma;		/* t2CYCTYP/2 */
+};
+
+#define FIT(v,vmin,vmax)	max_t(short,min_t(short,v,vmax),vmin)
 
 extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
@@ -392,7 +419,7 @@
 			     unsigned int n_ports);
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
-extern int ata_device_add(struct ata_probe_ent *ent);
+extern int ata_device_add(const struct ata_probe_ent *ent);
 extern void ata_host_set_remove(struct ata_host_set *host_set);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
@@ -400,19 +427,20 @@
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
 extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+extern int ata_ratelimit(void);
+
 /*
  * Default driver ops implementations
  */
-extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
 extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
-extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
+extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp);
+extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
 extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
 extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
 extern u8 ata_check_status(struct ata_port *ap);
 extern u8 ata_altstatus(struct ata_port *ap);
-extern u8 ata_chk_err(struct ata_port *ap);
-extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern void ata_host_stop (struct ata_host_set *host_set);
@@ -423,8 +451,8 @@
 		unsigned int buflen);
 extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 		 unsigned int n_elem);
-extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
-extern void ata_dev_id_string(u16 *id, unsigned char *s,
+extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
+extern void ata_dev_id_string(const u16 *id, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
 extern void ata_dev_config(struct ata_port *ap, unsigned int i);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
@@ -432,7 +460,7 @@
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
-extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
+extern void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask);
 extern void ata_eng_timeout(struct ata_port *ap);
 extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
@@ -441,6 +469,32 @@
 			      sector_t capacity, int geom[]);
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
 
+/*
+ * Timing helpers
+ */
+extern int ata_timing_compute(struct ata_device *, unsigned short,
+			      struct ata_timing *, int, int);
+extern void ata_timing_merge(const struct ata_timing *,
+			     const struct ata_timing *, struct ata_timing *,
+			     unsigned int);
+
+enum {
+	ATA_TIMING_SETUP	= (1 << 0),
+	ATA_TIMING_ACT8B	= (1 << 1),
+	ATA_TIMING_REC8B	= (1 << 2),
+	ATA_TIMING_CYC8B	= (1 << 3),
+	ATA_TIMING_8BIT		= ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
+				  ATA_TIMING_CYC8B,
+	ATA_TIMING_ACTIVE	= (1 << 4),
+	ATA_TIMING_RECOVER	= (1 << 5),
+	ATA_TIMING_CYCLE	= (1 << 6),
+	ATA_TIMING_UDMA		= (1 << 7),
+	ATA_TIMING_ALL		= ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
+				  ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
+				  ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
+				  ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
+};
+
 
 #ifdef CONFIG_PCI
 struct pci_bits {
@@ -452,8 +506,8 @@
 
 extern void ata_pci_host_stop (struct ata_host_set *host_set);
 extern struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
-extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
+extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
 
 #endif /* CONFIG_PCI */
 
@@ -463,7 +517,7 @@
 	return (tag < ATA_MAX_QUEUE) ? 1 : 0;
 }
 
-static inline unsigned int ata_dev_present(struct ata_device *dev)
+static inline unsigned int ata_dev_present(const struct ata_device *dev)
 {
 	return ((dev->class == ATA_DEV_ATA) ||
 		(dev->class == ATA_DEV_ATAPI));
@@ -662,11 +716,28 @@
 	return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
 }
 
-static inline int ata_try_flush_cache(struct ata_device *dev)
+static inline int ata_try_flush_cache(const struct ata_device *dev)
 {
 	return ata_id_wcache_enabled(dev->id) ||
 	       ata_id_has_flush(dev->id) ||
 	       ata_id_has_flush_ext(dev->id);
 }
 
+static inline unsigned int ac_err_mask(u8 status)
+{
+	if (status & ATA_BUSY)
+		return AC_ERR_ATA_BUS;
+	if (status & (ATA_ERR | ATA_DF))
+		return AC_ERR_DEV;
+	return 0;
+}
+
+static inline unsigned int __ac_err_mask(u8 status)
+{
+	unsigned int mask = ac_err_mask(status);
+	if (mask == 0)
+		return AC_ERR_OTHER;
+	return mask;
+}
+
 #endif /* __LINUX_LIBATA_H__ */
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 53fa515..40f63c9 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -52,7 +52,7 @@
 	unsigned	lo_blocksize;
 	void		*key_data; 
 
-	int		old_gfp_mask;
+	gfp_t		old_gfp_mask;
 
 	spinlock_t		lo_lock;
 	struct bio 		*lo_bio;
diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h
index 9263d2d..99e044b 100644
--- a/include/linux/mbcache.h
+++ b/include/linux/mbcache.h
@@ -22,7 +22,7 @@
 };
 
 struct mb_cache_op {
-	int (*free)(struct mb_cache_entry *, int);
+	int (*free)(struct mb_cache_entry *, gfp_t);
 };
 
 /* Functions on caches */
diff --git a/include/linux/memory.h b/include/linux/memory.h
new file mode 100644
index 0000000..0def328
--- /dev/null
+++ b/include/linux/memory.h
@@ -0,0 +1,94 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+	unsigned long phys_index;
+	unsigned long state;
+	/*
+	 * This serializes all state change requests.  It isn't
+	 * held during creation because the control files are
+	 * created long after the critical areas during
+	 * initialization.
+	 */
+	struct semaphore state_sem;
+	int phys_device;		/* to which fru does this belong? */
+	void *hw;			/* optional pointer to fw/hw data */
+	int (*phys_callback)(struct memory_block *);
+	struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define	MEM_ONLINE		(1<<0) /* exposed to userspace */
+#define	MEM_GOING_OFFLINE	(1<<1) /* exposed to userspace */
+#define	MEM_OFFLINE		(1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid.  The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working.  Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define	MEM_MAPPING_INVALID	(1<<3)
+
+#ifndef CONFIG_MEMORY_HOTPLUG
+static inline int memory_dev_init(void)
+{
+	return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_memory(struct memory_block *, struct mem_section *section, struct node *);
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int register_memory_notifier(struct notifier_block *nb);
+extern void unregister_memory_notifier(struct notifier_block *nb);
+
+#define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
+
+extern int invalidate_phys_mapping(unsigned long, unsigned long);
+struct notifier_block;
+
+extern int register_memory_notifier(struct notifier_block *nb);
+extern void unregister_memory_notifier(struct notifier_block *nb);
+
+extern struct sysdev_class memory_sysdev_class;
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
+#define hotplug_memory_notifier(fn, pri) {			\
+	static struct notifier_block fn##_mem_nb =		\
+		{ .notifier_call = fn, .priority = pri };	\
+	register_memory_notifier(&fn##_mem_nb);			\
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
new file mode 100644
index 0000000..01f03bc
--- /dev/null
+++ b/include/linux/memory_hotplug.h
@@ -0,0 +1,104 @@
+#ifndef __LINUX_MEMORY_HOTPLUG_H
+#define __LINUX_MEMORY_HOTPLUG_H
+
+#include <linux/mmzone.h>
+#include <linux/spinlock.h>
+#include <linux/mmzone.h>
+#include <linux/notifier.h>
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * pgdat resizing functions
+ */
+static inline
+void pgdat_resize_lock(struct pglist_data *pgdat, unsigned long *flags)
+{
+	spin_lock_irqsave(&pgdat->node_size_lock, *flags);
+}
+static inline
+void pgdat_resize_unlock(struct pglist_data *pgdat, unsigned long *flags)
+{
+	spin_unlock_irqrestore(&pgdat->node_size_lock, *flags);
+}
+static inline
+void pgdat_resize_init(struct pglist_data *pgdat)
+{
+	spin_lock_init(&pgdat->node_size_lock);
+}
+/*
+ * Zone resizing functions
+ */
+static inline unsigned zone_span_seqbegin(struct zone *zone)
+{
+	return read_seqbegin(&zone->span_seqlock);
+}
+static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
+{
+	return read_seqretry(&zone->span_seqlock, iv);
+}
+static inline void zone_span_writelock(struct zone *zone)
+{
+	write_seqlock(&zone->span_seqlock);
+}
+static inline void zone_span_writeunlock(struct zone *zone)
+{
+	write_sequnlock(&zone->span_seqlock);
+}
+static inline void zone_seqlock_init(struct zone *zone)
+{
+	seqlock_init(&zone->span_seqlock);
+}
+extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
+extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
+extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
+/* need some defines for these for archs that don't support it */
+extern void online_page(struct page *page);
+/* VM interface that may be used by firmware interface */
+extern int add_memory(u64 start, u64 size);
+extern int remove_memory(u64 start, u64 size);
+extern int online_pages(unsigned long, unsigned long);
+
+/* reasonably generic interface to expand the physical pages in a zone  */
+extern int __add_pages(struct zone *zone, unsigned long start_pfn,
+	unsigned long nr_pages);
+#else /* ! CONFIG_MEMORY_HOTPLUG */
+/*
+ * Stub functions for when hotplug is off
+ */
+static inline void pgdat_resize_lock(struct pglist_data *p, unsigned long *f) {}
+static inline void pgdat_resize_unlock(struct pglist_data *p, unsigned long *f) {}
+static inline void pgdat_resize_init(struct pglist_data *pgdat) {}
+
+static inline unsigned zone_span_seqbegin(struct zone *zone)
+{
+	return 0;
+}
+static inline int zone_span_seqretry(struct zone *zone, unsigned iv)
+{
+	return 0;
+}
+static inline void zone_span_writelock(struct zone *zone) {}
+static inline void zone_span_writeunlock(struct zone *zone) {}
+static inline void zone_seqlock_init(struct zone *zone) {}
+
+static inline int mhp_notimplemented(const char *func)
+{
+	printk(KERN_WARNING "%s() called, with CONFIG_MEMORY_HOTPLUG disabled\n", func);
+	dump_stack();
+	return -ENOSYS;
+}
+
+static inline int __add_pages(struct zone *zone, unsigned long start_pfn,
+	unsigned long nr_pages)
+{
+	return mhp_notimplemented(__FUNCTION__);
+}
+#endif /* ! CONFIG_MEMORY_HOTPLUG */
+static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
+	unsigned long nr_pages)
+{
+	printk(KERN_WARNING "%s() called, not yet supported\n", __FUNCTION__);
+	dump_stack();
+	return -ENOSYS;
+}
+#endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 58385ee..8b67cf8 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -27,10 +27,10 @@
 
 #include <linux/config.h>
 #include <linux/mmzone.h>
-#include <linux/bitmap.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
+#include <linux/nodemask.h>
 
 struct vm_area_struct;
 
@@ -47,8 +47,7 @@
  * Locking policy for interlave:
  * In process context there is no locking because only the process accesses
  * its own state. All vma manipulation is somewhat protected by a down_read on
- * mmap_sem. For allocating in the interleave policy the page_table_lock
- * must be also aquired to protect il_next.
+ * mmap_sem.
  *
  * Freeing policy:
  * When policy is MPOL_BIND v.zonelist is kmalloc'ed and must be kfree'd.
@@ -63,7 +62,7 @@
 	union {
 		struct zonelist  *zonelist;	/* bind */
 		short 		 preferred_node; /* preferred */
-		DECLARE_BITMAP(nodes, MAX_NUMNODES); /* interleave */
+		nodemask_t	 nodes;		/* interleave */
 		/* undefined for default */
 	} v;
 };
@@ -155,6 +154,7 @@
 
 extern void numa_default_policy(void);
 extern void numa_policy_init(void);
+extern void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new);
 extern struct mempolicy default_policy;
 
 #else
@@ -227,6 +227,11 @@
 {
 }
 
+static inline void numa_policy_rebind(const nodemask_t *old,
+					const nodemask_t *new)
+{
+}
+
 #endif /* CONFIG_NUMA */
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 9b8d047..68f5a0f 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -158,6 +158,7 @@
 extern int mii_nway_restart (struct mii_if_info *mii);
 extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
 extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_check_gmii_support(struct mii_if_info *mii);
 extern void mii_check_link (struct mii_if_info *mii);
 extern unsigned int mii_check_media (struct mii_if_info *mii,
 				     unsigned int ok_to_print,
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 097b3a3..5c1fb0a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -157,7 +157,7 @@
 
 #define VM_DONTCOPY	0x00020000      /* Do not copy this vma on fork */
 #define VM_DONTEXPAND	0x00040000	/* Cannot expand with mremap() */
-#define VM_RESERVED	0x00080000	/* Don't unmap it from swap_out */
+#define VM_RESERVED	0x00080000	/* Pages managed in a special way */
 #define VM_ACCOUNT	0x00100000	/* Is a VM accounted object */
 #define VM_HUGETLB	0x00400000	/* Huge TLB Page VM */
 #define VM_NONLINEAR	0x00800000	/* Is non-linear (remap_file_pages) */
@@ -226,13 +226,18 @@
 					 * to show when page is mapped
 					 * & limit reverse map searches.
 					 */
-	unsigned long private;		/* Mapping-private opaque data:
+	union {
+		unsigned long private;	/* Mapping-private opaque data:
 					 * usually used for buffer_heads
 					 * if PagePrivate set; used for
 					 * swp_entry_t if PageSwapCache
 					 * When page is free, this indicates
 					 * order in the buddy system.
 					 */
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+		spinlock_t ptl;
+#endif
+	} u;
 	struct address_space *mapping;	/* If low bit clear, points to
 					 * inode address_space, or NULL.
 					 * If page mapped as anonymous
@@ -260,6 +265,9 @@
 #endif /* WANT_PAGE_VIRTUAL */
 };
 
+#define page_private(page)		((page)->u.private)
+#define set_page_private(page, v)	((page)->u.private = (v))
+
 /*
  * FIXME: take this include out, include page-flags.h in
  * files which need it (119 of them)
@@ -311,17 +319,17 @@
 
 #ifdef CONFIG_HUGETLB_PAGE
 
-static inline int page_count(struct page *p)
+static inline int page_count(struct page *page)
 {
-	if (PageCompound(p))
-		p = (struct page *)p->private;
-	return atomic_read(&(p)->_count) + 1;
+	if (PageCompound(page))
+		page = (struct page *)page_private(page);
+	return atomic_read(&page->_count) + 1;
 }
 
 static inline void get_page(struct page *page)
 {
 	if (unlikely(PageCompound(page)))
-		page = (struct page *)page->private;
+		page = (struct page *)page_private(page);
 	atomic_inc(&page->_count);
 }
 
@@ -338,7 +346,7 @@
 
 static inline void put_page(struct page *page)
 {
-	if (!PageReserved(page) && put_page_testzero(page))
+	if (put_page_testzero(page))
 		__page_cache_release(page);
 }
 
@@ -587,7 +595,7 @@
 static inline pgoff_t page_index(struct page *page)
 {
 	if (unlikely(PageSwapCache(page)))
-		return page->private;
+		return page_private(page);
 	return page->index;
 }
 
@@ -682,7 +690,7 @@
 
 unsigned long zap_page_range(struct vm_area_struct *vma, unsigned long address,
 		unsigned long size, struct zap_details *);
-unsigned long unmap_vmas(struct mmu_gather **tlb, struct mm_struct *mm,
+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 *);
@@ -704,10 +712,6 @@
 }
 
 extern int vmtruncate(struct inode * inode, loff_t offset);
-extern pud_t *FASTCALL(__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address));
-extern pmd_t *FASTCALL(__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address));
-extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsigned long address));
-extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address));
 extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
 extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot);
 extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
@@ -723,6 +727,7 @@
 
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
 		int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
+void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long);
 
 int __set_page_dirty_buffers(struct page *page);
 int __set_page_dirty_nobuffers(struct page *page);
@@ -747,7 +752,7 @@
  * The callback will be passed nr_to_scan == 0 when the VM is querying the
  * cache size, so a fastpath for that case is appropriate.
  */
-typedef int (*shrinker_t)(int nr_to_scan, unsigned int gfp_mask);
+typedef int (*shrinker_t)(int nr_to_scan, gfp_t gfp_mask);
 
 /*
  * Add an aging callback.  The int is the number of 'seeks' it takes
@@ -759,38 +764,83 @@
 extern struct shrinker *set_shrinker(int, shrinker_t);
 extern void remove_shrinker(struct shrinker *shrinker);
 
-/*
- * On a two-level or three-level page table, this ends up being trivial. Thus
- * the inlining and the symmetry break with pte_alloc_map() that does all
- * of this out-of-line.
- */
+int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address);
+int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address);
+int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address);
+int __pte_alloc_kernel(pmd_t *pmd, unsigned long address);
+
 /*
  * The following ifdef needed to get the 4level-fixup.h header to work.
  * Remove it when 4level-fixup.h has been removed.
  */
-#ifdef CONFIG_MMU
-#ifndef __ARCH_HAS_4LEVEL_HACK 
+#if defined(CONFIG_MMU) && !defined(__ARCH_HAS_4LEVEL_HACK)
 static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
 {
-	if (pgd_none(*pgd))
-		return __pud_alloc(mm, pgd, address);
-	return pud_offset(pgd, address);
+	return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address))?
+		NULL: pud_offset(pgd, address);
 }
 
 static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
 {
-	if (pud_none(*pud))
-		return __pmd_alloc(mm, pud, address);
-	return pmd_offset(pud, address);
+	return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address))?
+		NULL: pmd_offset(pud, address);
 }
-#endif
-#endif /* CONFIG_MMU */
+#endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
+
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+/*
+ * We tuck a spinlock to guard each pagetable page into its struct page,
+ * at page->private, with BUILD_BUG_ON to make sure that this will not
+ * overflow into the next struct page (as it might with DEBUG_SPINLOCK).
+ * When freeing, reset page->mapping so free_pages_check won't complain.
+ */
+#define __pte_lockptr(page)	&((page)->u.ptl)
+#define pte_lock_init(_page)	do {					\
+	spin_lock_init(__pte_lockptr(_page));				\
+} while (0)
+#define pte_lock_deinit(page)	((page)->mapping = NULL)
+#define pte_lockptr(mm, pmd)	({(void)(mm); __pte_lockptr(pmd_page(*(pmd)));})
+#else
+/*
+ * We use mm->page_table_lock to guard all pagetable pages of the mm.
+ */
+#define pte_lock_init(page)	do {} while (0)
+#define pte_lock_deinit(page)	do {} while (0)
+#define pte_lockptr(mm, pmd)	({(void)(pmd); &(mm)->page_table_lock;})
+#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
+
+#define pte_offset_map_lock(mm, pmd, address, ptlp)	\
+({							\
+	spinlock_t *__ptl = pte_lockptr(mm, pmd);	\
+	pte_t *__pte = pte_offset_map(pmd, address);	\
+	*(ptlp) = __ptl;				\
+	spin_lock(__ptl);				\
+	__pte;						\
+})
+
+#define pte_unmap_unlock(pte, ptl)	do {		\
+	spin_unlock(ptl);				\
+	pte_unmap(pte);					\
+} while (0)
+
+#define pte_alloc_map(mm, pmd, address)			\
+	((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \
+		NULL: pte_offset_map(pmd, address))
+
+#define pte_alloc_map_lock(mm, pmd, address, ptlp)	\
+	((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \
+		NULL: pte_offset_map_lock(mm, pmd, address, ptlp))
+
+#define pte_alloc_kernel(pmd, address)			\
+	((unlikely(!pmd_present(*(pmd))) && __pte_alloc_kernel(pmd, address))? \
+		NULL: pte_offset_kernel(pmd, address))
 
 extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, pg_data_t *pgdat,
 	unsigned long * zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size);
 extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
+extern void setup_per_zone_pages_min(void);
 extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
@@ -834,6 +884,7 @@
 extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
 extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
 	struct rb_node **, struct rb_node *);
+extern void unlink_file_vma(struct vm_area_struct *);
 extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
 	unsigned long addr, unsigned long len, pgoff_t pgoff);
 extern void exit_mmap(struct mm_struct *);
@@ -894,7 +945,8 @@
 unsigned long max_sane_readahead(unsigned long nr);
 
 /* Do stack extension */
-extern int expand_stack(struct vm_area_struct * vma, unsigned long address);
+extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
+extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
 
 /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
 extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);
@@ -917,40 +969,28 @@
 	return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 }
 
-extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);
+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);
 
-extern struct page * vmalloc_to_page(void *addr);
-extern unsigned long vmalloc_to_pfn(void *addr);
-extern struct page * follow_page(struct mm_struct *mm, unsigned long address,
-		int write);
-extern int check_user_page_readable(struct mm_struct *mm, unsigned long address);
-int remap_pfn_range(struct vm_area_struct *, unsigned long,
-		unsigned long, unsigned long, pgprot_t);
+struct page *follow_page(struct mm_struct *, unsigned long address,
+			unsigned int foll_flags);
+#define FOLL_WRITE	0x01	/* check pte is writable */
+#define FOLL_TOUCH	0x02	/* mark page accessed */
+#define FOLL_GET	0x04	/* do get_page on page */
+#define FOLL_ANON	0x08	/* give ZERO_PAGE if no pgtable */
 
 #ifdef CONFIG_PROC_FS
-void __vm_stat_account(struct mm_struct *, unsigned long, struct file *, long);
+void vm_stat_account(struct mm_struct *, unsigned long, struct file *, long);
 #else
-static inline void __vm_stat_account(struct mm_struct *mm,
+static inline void vm_stat_account(struct mm_struct *mm,
 			unsigned long flags, struct file *file, long pages)
 {
 }
 #endif /* CONFIG_PROC_FS */
 
-static inline void vm_stat_account(struct vm_area_struct *vma)
-{
-	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
-							vma_pages(vma));
-}
-
-static inline void vm_stat_unaccount(struct vm_area_struct *vma)
-{
-	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
-							-vma_pages(vma));
-}
-
-/* update per process rss and vm hiwater data */
-extern void update_mem_hiwater(struct task_struct *tsk);
-
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable)
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 1ab78e8..aef6042 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -50,7 +50,7 @@
 #define MMC_ERR_INVALID	5
 
 	struct mmc_data		*data;		/* data segment associated with cmd */
-	struct mmc_request	*mrq;		/* assoicated request */
+	struct mmc_request	*mrq;		/* associated request */
 };
 
 struct mmc_data {
@@ -68,7 +68,7 @@
 	unsigned int		bytes_xfered;
 
 	struct mmc_command	*stop;		/* stop command */
-	struct mmc_request	*mrq;		/* assoicated request */
+	struct mmc_request	*mrq;		/* associated request */
 
 	unsigned int		sg_len;		/* size of scatter list */
 	struct scatterlist	*sg;		/* I/O scatter list */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 5ed471b..f5fa308 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -12,6 +12,7 @@
 #include <linux/threads.h>
 #include <linux/numa.h>
 #include <linux/init.h>
+#include <linux/seqlock.h>
 #include <asm/atomic.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -137,6 +138,10 @@
 	 * free areas of different sizes
 	 */
 	spinlock_t		lock;
+#ifdef CONFIG_MEMORY_HOTPLUG
+	/* see spanned/present_pages for more description */
+	seqlock_t		span_seqlock;
+#endif
 	struct free_area	free_area[MAX_ORDER];
 
 
@@ -220,6 +225,16 @@
 	/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
 	unsigned long		zone_start_pfn;
 
+	/*
+	 * zone_start_pfn, spanned_pages and present_pages are all
+	 * protected by span_seqlock.  It is a seqlock because it has
+	 * to be read outside of zone->lock, and it is done in the main
+	 * allocator path.  But, it is written quite infrequently.
+	 *
+	 * The lock is declared along with zone->lock because it is
+	 * frequently read in proximity to zone->lock.  It's good to
+	 * give them a chance of being in the same cacheline.
+	 */
 	unsigned long		spanned_pages;	/* total size, including holes */
 	unsigned long		present_pages;	/* amount of memory (excluding holes) */
 
@@ -273,6 +288,16 @@
 	struct page *node_mem_map;
 #endif
 	struct bootmem_data *bdata;
+#ifdef CONFIG_MEMORY_HOTPLUG
+	/*
+	 * Must be held any time you expect node_start_pfn, node_present_pages
+	 * or node_spanned_pages stay constant.  Holding this will also
+	 * guarantee that any pfn_valid() stays that way.
+	 *
+	 * Nests above zone->lock and zone->size_seqlock.
+	 */
+	spinlock_t node_size_lock;
+#endif
 	unsigned long node_start_pfn;
 	unsigned long node_present_pages; /* total number of physical pages */
 	unsigned long node_spanned_pages; /* total size of physical page
@@ -293,6 +318,8 @@
 #endif
 #define nid_page_nr(nid, pagenr) 	pgdat_page_nr(NODE_DATA(nid),(pagenr))
 
+#include <linux/memory_hotplug.h>
+
 extern struct pglist_data *pgdat_list;
 
 void __get_zone_counts(unsigned long *active, unsigned long *inactive,
@@ -302,7 +329,7 @@
 void build_all_zonelists(void);
 void wakeup_kswapd(struct zone *zone, int order);
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
-		int alloc_type, int can_try_harder, int gfp_high);
+		int alloc_type, int can_try_harder, gfp_t gfp_high);
 
 #ifdef CONFIG_HAVE_MEMORY_PRESENT
 void memory_present(int nid, unsigned long start, unsigned long end);
@@ -509,6 +536,7 @@
 		return NULL;
 	return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
 }
+extern int __section_nr(struct mem_section* ms);
 
 /*
  * We use the lower bits of the mem_map pointer to store
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 2f0299a..7b08c11 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -244,4 +244,9 @@
 #define PCMCIA_DEV_ID_MATCH_FAKE_CIS	0x0200
 #define PCMCIA_DEV_ID_MATCH_ANONYMOUS	0x0400
 
+/* I2C */
+struct i2c_device_id {
+	__u16 id;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index f05372b..84d75f3 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -554,7 +554,9 @@
 #ifdef MODULE
 /* DEPRECATED: Do not use. */
 #define MODULE_PARM(var,type)						    \
-struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \
+extern struct obsolete_modparm __parm_##var \
+__attribute__((section("__obsparm"))); \
+struct obsolete_modparm __parm_##var = \
 { __stringify(var), type, &MODULE_PARM_ }; \
 __MODULE_PARM_TYPE(var, type);
 #else
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 9a3d272..941da5c 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -282,6 +282,17 @@
 		MSDOS_I(inode)->i_attrs;
 }
 
+static inline unsigned char fat_checksum(const __u8 *name)
+{
+	unsigned char s = name[0];
+	s = (s<<7) + (s>>1) + name[1];	s = (s<<7) + (s>>1) + name[2];
+	s = (s<<7) + (s>>1) + name[3];	s = (s<<7) + (s>>1) + name[4];
+	s = (s<<7) + (s>>1) + name[5];	s = (s<<7) + (s>>1) + name[6];
+	s = (s<<7) + (s>>1) + name[7];	s = (s<<7) + (s>>1) + name[8];
+	s = (s<<7) + (s>>1) + name[9];	s = (s<<7) + (s>>1) + name[10];
+	return s;
+}
+
 static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
 {
 	return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 142963f..fc28841 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -8,7 +8,10 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/string.h>
+
 #include <linux/mtd/compatmac.h>
+
 #include <asm/unaligned.h>
 #include <asm/system.h>
 #include <asm/io.h>
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 7db67b0..1c975d0 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -8,6 +8,7 @@
 struct open_intent {
 	int	flags;
 	int	create_mode;
+	struct file *file;
 };
 
 enum { MAX_NESTED_LINKS = 5 };
@@ -65,6 +66,13 @@
 extern void path_release(struct nameidata *);
 extern void path_release_on_umount(struct nameidata *);
 
+extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags);
+extern int path_lookup_open(const char *, unsigned lookup_flags, struct nameidata *, int open_flags);
+extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+		int (*open)(struct inode *, struct file *));
+extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+extern void release_open_intent(struct nameidata *);
+
 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 368e4c8..c6efce4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -308,6 +308,7 @@
 #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
 #define NETIF_F_TSO		2048	/* Can offload TCP/IP segmentation */
 #define NETIF_F_LLTX		4096	/* LockLess TX */
+#define NETIF_F_UFO             8192    /* Can offload UDP Large Send*/
 
 	struct net_device	*next_sched;
 
@@ -873,11 +874,9 @@
 
 static inline void netif_poll_disable(struct net_device *dev)
 {
-	while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
+	while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state))
 		/* No hurry. */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-	}
+		schedule_timeout_interruptible(1);
 }
 
 static inline void netif_poll_enable(struct net_device *dev)
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 9a6047f..325fe7a 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -41,6 +41,10 @@
 #define NFS_MAX_FILE_IO_BUFFER_SIZE	32768
 #define NFS_DEF_FILE_IO_BUFFER_SIZE	4096
 
+/* Default timeout values */
+#define NFS_MAX_UDP_TIMEOUT	(60*HZ)
+#define NFS_MAX_TCP_TIMEOUT	(600*HZ)
+
 /*
  * superblock magic number for NFS
  */
@@ -137,6 +141,7 @@
 	unsigned long		attrtimeo_timestamp;
 	__u64			change_attr;		/* v4 only */
 
+	unsigned long		last_updated;
 	/* "Generation counter" for the attribute cache. This is
 	 * bumped whenever we update the metadata on the
 	 * server.
@@ -236,13 +241,17 @@
 	return atomic_read(&NFS_I(inode)->data_updates) != 0;
 }
 
+static inline void nfs_mark_for_revalidate(struct inode *inode)
+{
+	spin_lock(&inode->i_lock);
+	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+	spin_unlock(&inode->i_lock);
+}
+
 static inline void NFS_CACHEINV(struct inode *inode)
 {
-	if (!nfs_caches_unstable(inode)) {
-		spin_lock(&inode->i_lock);
-		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
-		spin_unlock(&inode->i_lock);
-	}
+	if (!nfs_caches_unstable(inode))
+		nfs_mark_for_revalidate(inode);
 }
 
 static inline int nfs_server_capable(struct inode *inode, int cap)
@@ -276,7 +285,7 @@
 static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long chattr)
 {
 	return !nfs_caches_unstable(inode)
-		&& chattr == NFS_I(inode)->cache_change_attribute;
+		&& time_after_eq(chattr, NFS_I(inode)->cache_change_attribute);
 }
 
 /*
@@ -286,6 +295,7 @@
 extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
 				struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
+extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int, struct nameidata *);
 extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);
@@ -312,6 +322,12 @@
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
 
+static inline void nfs_fattr_init(struct nfs_fattr *fattr)
+{
+	fattr->valid = 0;
+	fattr->time_start = jiffies;
+}
+
 /*
  * linux/fs/nfs/file.c
  */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a2bf691..4071866 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -41,7 +41,7 @@
 	__u32			bitmap[2];	/* NFSv4 returned attribute bitmap */
 	__u64			change_attr;	/* NFSv4 change attribute */
 	__u64			pre_change_attr;/* pre-op NFSv4 change attribute */
-	unsigned long		timestamp;
+	unsigned long		time_start;
 };
 
 #define NFS_ATTR_WCC		0x0001		/* pre-op WCC data    */
@@ -96,12 +96,13 @@
 	u64			after;
 };
 
+struct nfs_seqid;
 /*
  * Arguments to the open call.
  */
 struct nfs_openargs {
 	const struct nfs_fh *	fh;
-	__u32                   seqid;
+	struct nfs_seqid *	seqid;
 	int			open_flags;
 	__u64                   clientid;
 	__u32                   id;
@@ -123,6 +124,7 @@
 	struct nfs4_change_info	cinfo;
 	__u32                   rflags;
 	struct nfs_fattr *      f_attr;
+	struct nfs_fattr *      dir_attr;
 	const struct nfs_server *server;
 	int			delegation_type;
 	nfs4_stateid		delegation;
@@ -136,7 +138,7 @@
 struct nfs_open_confirmargs {
 	const struct nfs_fh *	fh;
 	nfs4_stateid            stateid;
-	__u32                   seqid;
+	struct nfs_seqid *	seqid;
 };
 
 struct nfs_open_confirmres {
@@ -148,13 +150,16 @@
  */
 struct nfs_closeargs {
 	struct nfs_fh *         fh;
-	nfs4_stateid            stateid;
-	__u32                   seqid;
+	nfs4_stateid *		stateid;
+	struct nfs_seqid *	seqid;
 	int			open_flags;
+	const u32 *		bitmask;
 };
 
 struct nfs_closeres {
 	nfs4_stateid            stateid;
+	struct nfs_fattr *	fattr;
+	const struct nfs_server *server;
 };
 /*
  *  * Arguments to the lock,lockt, and locku call.
@@ -164,30 +169,19 @@
 	u32                     id;
 };
 
-struct nfs_open_to_lock {
-	__u32                   open_seqid;
-	nfs4_stateid            open_stateid;
-	__u32                   lock_seqid;
-	struct nfs_lowner       lock_owner;
-};
-
-struct nfs_exist_lock {
-	nfs4_stateid            stateid;
-	__u32                   seqid;
-};
-
 struct nfs_lock_opargs {
+	struct nfs_seqid *	lock_seqid;
+	nfs4_stateid *		lock_stateid;
+	struct nfs_seqid *	open_seqid;
+	nfs4_stateid *		open_stateid;
+	struct nfs_lowner       lock_owner;
 	__u32                   reclaim;
 	__u32                   new_lock_owner;
-	union {
-		struct nfs_open_to_lock *open_lock;
-		struct nfs_exist_lock   *exist_lock;
-	} u;
 };
 
 struct nfs_locku_opargs {
-	__u32                   seqid;
-	nfs4_stateid            stateid;
+	struct nfs_seqid *	seqid;
+	nfs4_stateid *		stateid;
 };
 
 struct nfs_lockargs {
@@ -262,6 +256,7 @@
 	enum nfs3_stable_how	stable;
 	unsigned int		pgbase;
 	struct page **		pages;
+	const u32 *		bitmask;
 };
 
 struct nfs_writeverf {
@@ -273,6 +268,7 @@
 	struct nfs_fattr *	fattr;
 	struct nfs_writeverf *	verf;
 	__u32			count;
+	const struct nfs_server *server;
 };
 
 /*
@@ -550,6 +546,7 @@
 	struct nfs_fh *			fh;
 	struct nfs_fattr *		fattr;
 	struct nfs4_change_info		dir_cinfo;
+	struct nfs_fattr *		dir_fattr;
 };
 
 struct nfs4_fsinfo_arg {
@@ -571,8 +568,17 @@
 	const struct nfs_fh *		fh;
 	const struct nfs_fh *		dir_fh;
 	const struct qstr *		name;
+	const u32 *			bitmask;
 };
 
+struct nfs4_link_res {
+	const struct nfs_server *	server;
+	struct nfs_fattr *		fattr;
+	struct nfs4_change_info		cinfo;
+	struct nfs_fattr *		dir_attr;
+};
+
+
 struct nfs4_lookup_arg {
 	const struct nfs_fh *		dir_fh;
 	const struct qstr *		name;
@@ -619,6 +625,13 @@
 struct nfs4_remove_arg {
 	const struct nfs_fh *		fh;
 	const struct qstr *		name;
+	const u32 *			bitmask;
+};
+
+struct nfs4_remove_res {
+	const struct nfs_server *	server;
+	struct nfs4_change_info		cinfo;
+	struct nfs_fattr *		dir_attr;
 };
 
 struct nfs4_rename_arg {
@@ -626,11 +639,15 @@
 	const struct nfs_fh *		new_dir;
 	const struct qstr *		old_name;
 	const struct qstr *		new_name;
+	const u32 *			bitmask;
 };
 
 struct nfs4_rename_res {
+	const struct nfs_server *	server;
 	struct nfs4_change_info		old_cinfo;
+	struct nfs_fattr *		old_fattr;
 	struct nfs4_change_info		new_cinfo;
+	struct nfs_fattr *		new_fattr;
 };
 
 struct nfs4_setclientid {
@@ -722,7 +739,7 @@
 	int	(*write)   (struct nfs_write_data *);
 	int	(*commit)  (struct nfs_write_data *);
 	int	(*create)  (struct inode *, struct dentry *,
-			    struct iattr *, int);
+			    struct iattr *, int, struct nameidata *);
 	int	(*remove)  (struct inode *, struct qstr *);
 	int	(*unlink_setup)  (struct rpc_message *,
 			    struct dentry *, struct qstr *);
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index e96fe90..4726ef7 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -12,6 +12,8 @@
  * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
  * For details of nodelist_scnprintf() and nodelist_parse(), see
  * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
+ * For details of node_remap(), see bitmap_bitremap in lib/bitmap.c.
+ * For details of nodes_remap(), see bitmap_remap in lib/bitmap.c.
  *
  * The available nodemask operations are:
  *
@@ -52,6 +54,8 @@
  * int nodemask_parse(ubuf, ulen, mask)	Parse ascii string as nodemask
  * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
  * int nodelist_parse(buf, map)		Parse ascii string as nodelist
+ * int node_remap(oldbit, old, new)	newbit = map(old, new)(oldbit)
+ * int nodes_remap(dst, src, old, new)	*dst = map(old, new)(dst)
  *
  * for_each_node_mask(node, mask)	for-loop node over mask
  *
@@ -307,6 +311,22 @@
 	return bitmap_parselist(buf, dstp->bits, nbits);
 }
 
+#define node_remap(oldbit, old, new) \
+		__node_remap((oldbit), &(old), &(new), MAX_NUMNODES)
+static inline int __node_remap(int oldbit,
+		const nodemask_t *oldp, const nodemask_t *newp, int nbits)
+{
+	return bitmap_bitremap(oldbit, oldp->bits, newp->bits, nbits);
+}
+
+#define nodes_remap(dst, src, old, new) \
+		__nodes_remap(&(dst), &(src), &(old), &(new), MAX_NUMNODES)
+static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp,
+		const nodemask_t *oldp, const nodemask_t *newp, int nbits)
+{
+	bitmap_remap(dstp->bits, srcp->bits, oldp->bits, newp->bits, nbits);
+}
+
 #if MAX_NUMNODES > 1
 #define for_each_node_mask(node, mask)			\
 	for ((node) = first_node(mask);			\
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index acbf31c..ba6c310 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -21,16 +21,17 @@
 
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
-	return mapping->flags & __GFP_BITS_MASK;
+	return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
 }
 
 /*
  * This is non-atomic.  Only to be used before the mapping is activated.
  * Probably needs a barrier...
  */
-static inline void mapping_set_gfp_mask(struct address_space *m, int mask)
+static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
 {
-	m->flags = (m->flags & ~__GFP_BITS_MASK) | mask;
+	m->flags = (m->flags & ~(__force unsigned long)__GFP_BITS_MASK) |
+				(__force unsigned long)mask;
 }
 
 /*
@@ -69,7 +70,7 @@
 extern struct page * find_trylock_page(struct address_space *mapping,
 				unsigned long index);
 extern struct page * find_or_create_page(struct address_space *mapping,
-				unsigned long index, unsigned int gfp_mask);
+				unsigned long index, gfp_t gfp_mask);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
 			unsigned int nr_pages, struct page **pages);
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
@@ -92,9 +93,9 @@
 		struct list_head *pages, filler_t *filler, void *data);
 
 int add_to_page_cache(struct page *page, struct address_space *mapping,
-				unsigned long index, int gfp_mask);
+				unsigned long index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
-				unsigned long index, int gfp_mask);
+				unsigned long index, gfp_t gfp_mask);
 extern void remove_from_page_cache(struct page *page);
 extern void __remove_from_page_cache(struct page *page);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7349058..3596ac9 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -132,6 +132,7 @@
 	unsigned int	is_enabled:1;	/* pci_enable_device has been called */
 	unsigned int	is_busmaster:1; /* device is busmaster */
 	unsigned int	no_msi:1;	/* device may not use msi */
+	unsigned int	block_ucfg_access:1;	/* userspace config space access is blocked */
 
 	u32		saved_config_space[16]; /* config space saved at suspend time */
 	struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
@@ -490,6 +491,9 @@
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 #endif
 
+extern void pci_block_user_cfg_access(struct pci_dev *dev);
+extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
+
 /*
  * PCI domain support.  Sometimes called PCI segment (eg by ACPI),
  * a PCI domain is defined to be a set of PCI busses which share
@@ -560,6 +564,9 @@
 
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 
+static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
+static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }
+
 #endif /* CONFIG_PCI */
 
 /* Include architecture-dependent settings and functions */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 71834f0..5619200 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -96,6 +96,9 @@
 #define PCI_CLASS_SERIAL_ACCESS		0x0c01
 #define PCI_CLASS_SERIAL_SSA		0x0c02
 #define PCI_CLASS_SERIAL_USB		0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI	0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI	0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI	0x0c0320
 #define PCI_CLASS_SERIAL_FIBER		0x0c04
 #define PCI_CLASS_SERIAL_SMBUS		0x0c05
 
@@ -132,9 +135,6 @@
 
 #define PCI_VENDOR_ID_COMPAQ		0x0e11
 #define PCI_DEVICE_ID_COMPAQ_TOKENRING	0x0508
-#define PCI_DEVICE_ID_COMPAQ_1280	0x3033
-#define PCI_DEVICE_ID_COMPAQ_TRIFLEX	0x4000
-#define PCI_DEVICE_ID_COMPAQ_6010	0x6010
 #define PCI_DEVICE_ID_COMPAQ_TACHYON	0xa0fc
 #define PCI_DEVICE_ID_COMPAQ_SMART2P	0xae10
 #define PCI_DEVICE_ID_COMPAQ_NETEL100	0xae32
@@ -274,7 +274,6 @@
 #define PCI_DEVICE_ID_ATI_RAGE128_PP	0x5050
 #define PCI_DEVICE_ID_ATI_RAGE128_PQ	0x5051
 #define PCI_DEVICE_ID_ATI_RAGE128_PR	0x5052
-#define PCI_DEVICE_ID_ATI_RAGE128_TR	0x5452
 #define PCI_DEVICE_ID_ATI_RAGE128_PS	0x5053
 #define PCI_DEVICE_ID_ATI_RAGE128_PT	0x5054
 #define PCI_DEVICE_ID_ATI_RAGE128_PU	0x5055
@@ -282,8 +281,6 @@
 #define PCI_DEVICE_ID_ATI_RAGE128_PW	0x5057
 #define PCI_DEVICE_ID_ATI_RAGE128_PX	0x5058
 /* Rage128 M4 */
-#define PCI_DEVICE_ID_ATI_RADEON_LE	0x4d45
-#define PCI_DEVICE_ID_ATI_RADEON_LF	0x4d46
 /* Radeon R100 */
 #define PCI_DEVICE_ID_ATI_RADEON_QD	0x5144
 #define PCI_DEVICE_ID_ATI_RADEON_QE	0x5145
@@ -304,32 +301,22 @@
 #define PCI_DEVICE_ID_ATI_RADEON_QW	0x5157
 #define PCI_DEVICE_ID_ATI_RADEON_QX	0x5158
 /* Radeon NV-100 */
-#define PCI_DEVICE_ID_ATI_RADEON_N1	0x5159
-#define PCI_DEVICE_ID_ATI_RADEON_N2	0x515a
 /* Radeon RV250 (9000) */
 #define PCI_DEVICE_ID_ATI_RADEON_Id	0x4964
 #define PCI_DEVICE_ID_ATI_RADEON_Ie	0x4965
 #define PCI_DEVICE_ID_ATI_RADEON_If	0x4966
 #define PCI_DEVICE_ID_ATI_RADEON_Ig	0x4967
 /* Radeon RV280 (9200) */
-#define PCI_DEVICE_ID_ATI_RADEON_Y_	0x5960
 #define PCI_DEVICE_ID_ATI_RADEON_Ya	0x5961
 #define PCI_DEVICE_ID_ATI_RADEON_Yd	0x5964
 /* Radeon R300 (9500) */
-#define PCI_DEVICE_ID_ATI_RADEON_AD	0x4144
 /* Radeon R300 (9700) */
 #define PCI_DEVICE_ID_ATI_RADEON_ND	0x4e44
 #define PCI_DEVICE_ID_ATI_RADEON_NE	0x4e45
 #define PCI_DEVICE_ID_ATI_RADEON_NF	0x4e46
 #define PCI_DEVICE_ID_ATI_RADEON_NG	0x4e47
-#define PCI_DEVICE_ID_ATI_RADEON_AE	0x4145
-#define PCI_DEVICE_ID_ATI_RADEON_AF	0x4146
 /* Radeon R350 (9800) */
-#define PCI_DEVICE_ID_ATI_RADEON_NH	0x4e48
-#define PCI_DEVICE_ID_ATI_RADEON_NI	0x4e49
 /* Radeon RV350 (9600) */
-#define PCI_DEVICE_ID_ATI_RADEON_AP	0x4150
-#define PCI_DEVICE_ID_ATI_RADEON_AR	0x4152
 /* Radeon M6 */
 #define PCI_DEVICE_ID_ATI_RADEON_LY	0x4c59
 #define PCI_DEVICE_ID_ATI_RADEON_LZ	0x4c5a
@@ -342,10 +329,6 @@
 #define PCI_DEVICE_ID_ATI_RADEON_Lf	0x4c66
 #define PCI_DEVICE_ID_ATI_RADEON_Lg	0x4c67
 /* Radeon */
-#define PCI_DEVICE_ID_ATI_RADEON_RA	0x5144
-#define PCI_DEVICE_ID_ATI_RADEON_RB	0x5145
-#define PCI_DEVICE_ID_ATI_RADEON_RC	0x5146
-#define PCI_DEVICE_ID_ATI_RADEON_RD	0x5147
 /* RadeonIGP */
 #define PCI_DEVICE_ID_ATI_RS100		0xcab0
 #define PCI_DEVICE_ID_ATI_RS200		0xcab2
@@ -446,45 +429,28 @@
 #define PCI_DEVICE_ID_CIRRUS_5465	0x00d6
 #define PCI_DEVICE_ID_CIRRUS_6729	0x1100
 #define PCI_DEVICE_ID_CIRRUS_6832	0x1110
-#define PCI_DEVICE_ID_CIRRUS_7542	0x1200
 #define PCI_DEVICE_ID_CIRRUS_7543	0x1202
-#define PCI_DEVICE_ID_CIRRUS_7541	0x1204
 #define PCI_DEVICE_ID_CIRRUS_4610	0x6001
 #define PCI_DEVICE_ID_CIRRUS_4612	0x6003
 #define PCI_DEVICE_ID_CIRRUS_4615	0x6004
-#define PCI_DEVICE_ID_CIRRUS_4281	0x6005
 
 #define PCI_VENDOR_ID_IBM		0x1014
-#define PCI_DEVICE_ID_IBM_FIRE_CORAL	0x000a
 #define PCI_DEVICE_ID_IBM_TR		0x0018
-#define PCI_DEVICE_ID_IBM_82G2675	0x001d
-#define PCI_DEVICE_ID_IBM_MCA		0x0020
-#define PCI_DEVICE_ID_IBM_82351		0x0022
-#define PCI_DEVICE_ID_IBM_PYTHON	0x002d
-#define PCI_DEVICE_ID_IBM_SERVERAID	0x002e
 #define PCI_DEVICE_ID_IBM_TR_WAKE	0x003e
-#define PCI_DEVICE_ID_IBM_MPIC		0x0046
-#define PCI_DEVICE_ID_IBM_3780IDSP	0x007d
-#define PCI_DEVICE_ID_IBM_CHUKAR	0x0096
 #define PCI_DEVICE_ID_IBM_CPC710_PCI64	0x00fc
-#define PCI_DEVICE_ID_IBM_CPC710_PCI32	0x0105
-#define	PCI_DEVICE_ID_IBM_405GP		0x0156
 #define PCI_DEVICE_ID_IBM_SNIPE		0x0180
-#define PCI_DEVICE_ID_IBM_SERVERAIDI960	0x01bd
 #define PCI_DEVICE_ID_IBM_CITRINE		0x028C
 #define PCI_DEVICE_ID_IBM_GEMSTONE		0xB166
-#define PCI_DEVICE_ID_IBM_MPIC_2	0xffff
 #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1	0x0031
 #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2	0x0219
 #define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX		0x021A
 #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM	0x0251
 #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL	0x252
 
-#define PCI_VENDOR_ID_COMPEX2		0x101a // pci.ids says "AT&T GIS (NCR)"
+#define PCI_VENDOR_ID_COMPEX2		0x101a /* pci.ids says "AT&T GIS (NCR)" */
 #define PCI_DEVICE_ID_COMPEX2_100VG	0x0005
 
 #define PCI_VENDOR_ID_WD		0x101c
-#define PCI_DEVICE_ID_WD_7197		0x3296
 #define PCI_DEVICE_ID_WD_90C		0xc24a
 
 #define PCI_VENDOR_ID_AMI		0x101e
@@ -501,33 +467,18 @@
 #define PCI_DEVICE_ID_AMD_FE_GATE_7006	0x7006
 #define PCI_DEVICE_ID_AMD_FE_GATE_7007	0x7007
 #define PCI_DEVICE_ID_AMD_FE_GATE_700C	0x700C
-#define PCI_DEVICE_ID_AMD_FE_GATE_700D	0x700D
 #define PCI_DEVICE_ID_AMD_FE_GATE_700E	0x700E
-#define PCI_DEVICE_ID_AMD_FE_GATE_700F	0x700F
-#define PCI_DEVICE_ID_AMD_COBRA_7400	0x7400
 #define PCI_DEVICE_ID_AMD_COBRA_7401	0x7401
-#define PCI_DEVICE_ID_AMD_COBRA_7403	0x7403
-#define PCI_DEVICE_ID_AMD_COBRA_7404	0x7404
-#define PCI_DEVICE_ID_AMD_VIPER_7408	0x7408
 #define PCI_DEVICE_ID_AMD_VIPER_7409	0x7409
 #define PCI_DEVICE_ID_AMD_VIPER_740B	0x740B
-#define PCI_DEVICE_ID_AMD_VIPER_740C	0x740C
 #define PCI_DEVICE_ID_AMD_VIPER_7410	0x7410
 #define PCI_DEVICE_ID_AMD_VIPER_7411	0x7411
 #define PCI_DEVICE_ID_AMD_VIPER_7413	0x7413
-#define PCI_DEVICE_ID_AMD_VIPER_7414	0x7414
-#define PCI_DEVICE_ID_AMD_OPUS_7440	0x7440
-#	define PCI_DEVICE_ID_AMD_VIPER_7440	PCI_DEVICE_ID_AMD_OPUS_7440
+#define PCI_DEVICE_ID_AMD_VIPER_7440	0x7440
 #define PCI_DEVICE_ID_AMD_OPUS_7441	0x7441
-#	define PCI_DEVICE_ID_AMD_VIPER_7441	PCI_DEVICE_ID_AMD_OPUS_7441
 #define PCI_DEVICE_ID_AMD_OPUS_7443	0x7443
-#	define PCI_DEVICE_ID_AMD_VIPER_7443	PCI_DEVICE_ID_AMD_OPUS_7443
+#define PCI_DEVICE_ID_AMD_VIPER_7443	0x7443
 #define PCI_DEVICE_ID_AMD_OPUS_7445	0x7445
-#define PCI_DEVICE_ID_AMD_OPUS_7448	0x7448
-# define	PCI_DEVICE_ID_AMD_VIPER_7448	PCI_DEVICE_ID_AMD_OPUS_7448
-#define PCI_DEVICE_ID_AMD_OPUS_7449	0x7449
-#	define PCI_DEVICE_ID_AMD_VIPER_7449	PCI_DEVICE_ID_AMD_OPUS_7449
-#define PCI_DEVICE_ID_AMD_8111_LAN	0x7462
 #define PCI_DEVICE_ID_AMD_8111_LPC	0x7468
 #define PCI_DEVICE_ID_AMD_8111_IDE	0x7469
 #define PCI_DEVICE_ID_AMD_8111_SMBUS2	0x746a
@@ -585,7 +536,6 @@
 #define PCI_DEVICE_ID_CT_65550		0x00e0
 #define PCI_DEVICE_ID_CT_65554		0x00e4
 #define PCI_DEVICE_ID_CT_65555		0x00e5
-#define PCI_DEVICE_ID_CT_69000		0x00c0
 
 #define PCI_VENDOR_ID_MIRO		0x1031
 #define PCI_DEVICE_ID_MIRO_36050	0x5601
@@ -639,7 +589,6 @@
 #define PCI_DEVICE_ID_SI_550		0x0550
 #define PCI_DEVICE_ID_SI_540_VGA	0x5300
 #define PCI_DEVICE_ID_SI_550_VGA	0x5315
-#define PCI_DEVICE_ID_SI_601		0x0601
 #define PCI_DEVICE_ID_SI_620		0x0620
 #define PCI_DEVICE_ID_SI_630		0x0630
 #define PCI_DEVICE_ID_SI_633		0x0633
@@ -650,30 +599,22 @@
 #define PCI_DEVICE_ID_SI_648		0x0648
 #define PCI_DEVICE_ID_SI_650		0x0650
 #define PCI_DEVICE_ID_SI_651		0x0651
-#define PCI_DEVICE_ID_SI_652		0x0652
 #define PCI_DEVICE_ID_SI_655		0x0655
 #define PCI_DEVICE_ID_SI_661		0x0661
 #define PCI_DEVICE_ID_SI_730		0x0730
 #define PCI_DEVICE_ID_SI_733		0x0733
 #define PCI_DEVICE_ID_SI_630_VGA	0x6300
-#define PCI_DEVICE_ID_SI_730_VGA	0x7300
 #define PCI_DEVICE_ID_SI_735		0x0735
 #define PCI_DEVICE_ID_SI_740		0x0740
 #define PCI_DEVICE_ID_SI_741		0x0741
 #define PCI_DEVICE_ID_SI_745		0x0745
 #define PCI_DEVICE_ID_SI_746		0x0746
-#define PCI_DEVICE_ID_SI_748		0x0748
-#define PCI_DEVICE_ID_SI_750		0x0750
-#define PCI_DEVICE_ID_SI_751		0x0751
-#define PCI_DEVICE_ID_SI_752		0x0752
 #define PCI_DEVICE_ID_SI_755		0x0755
 #define PCI_DEVICE_ID_SI_760		0x0760
 #define PCI_DEVICE_ID_SI_900		0x0900
 #define PCI_DEVICE_ID_SI_961		0x0961
 #define PCI_DEVICE_ID_SI_962		0x0962
 #define PCI_DEVICE_ID_SI_963		0x0963
-#define PCI_DEVICE_ID_SI_5107		0x5107
-#define PCI_DEVICE_ID_SI_5300		0x5300
 #define PCI_DEVICE_ID_SI_5511		0x5511
 #define PCI_DEVICE_ID_SI_5513		0x5513
 #define PCI_DEVICE_ID_SI_5518		0x5518
@@ -685,10 +626,6 @@
 #define PCI_DEVICE_ID_SI_5597		0x5597
 #define PCI_DEVICE_ID_SI_5598		0x5598
 #define PCI_DEVICE_ID_SI_5600		0x5600
-#define PCI_DEVICE_ID_SI_6300		0x6300
-#define PCI_DEVICE_ID_SI_6306		0x6306
-#define PCI_DEVICE_ID_SI_6326		0x6326
-#define PCI_DEVICE_ID_SI_7001		0x7001
 #define PCI_DEVICE_ID_SI_7012		0x7012
 #define PCI_DEVICE_ID_SI_7013		0x7013
 #define PCI_DEVICE_ID_SI_7016		0x7016
@@ -709,14 +646,11 @@
 #define PCI_DEVICE_ID_HP_DIVA_TOSCA1	0x1049
 #define PCI_DEVICE_ID_HP_DIVA_TOSCA2	0x104A
 #define PCI_DEVICE_ID_HP_DIVA_MAESTRO	0x104B
-#define PCI_DEVICE_ID_HP_PCI_LBA	0x1054
-#define PCI_DEVICE_ID_HP_REO_SBA	0x10f0
 #define PCI_DEVICE_ID_HP_REO_IOC	0x10f1
 #define PCI_DEVICE_ID_HP_VISUALIZE_FXE	0x108b
 #define PCI_DEVICE_ID_HP_DIVA_HALFDOME	0x1223
 #define PCI_DEVICE_ID_HP_DIVA_KEYSTONE	0x1226
 #define PCI_DEVICE_ID_HP_DIVA_POWERBAR	0x1227
-#define PCI_DEVICE_ID_HP_ZX1_SBA	0x1229
 #define PCI_DEVICE_ID_HP_ZX1_IOC	0x122a
 #define PCI_DEVICE_ID_HP_PCIX_LBA	0x122e
 #define PCI_DEVICE_ID_HP_SX1000_IOC	0x127c
@@ -724,9 +658,7 @@
 #define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
 #define PCI_DEVICE_ID_HP_DIVA_RMP3	0x1301
 #define PCI_DEVICE_ID_HP_DIVA_HURRICANE	0x132a
-#define PCI_DEVICE_ID_HP_CISS		0x3210
 #define PCI_DEVICE_ID_HP_CISSA		0x3220
-#define PCI_DEVICE_ID_HP_CISSB		0x3222
 #define PCI_DEVICE_ID_HP_CISSC		0x3230
 #define PCI_DEVICE_ID_HP_CISSD		0x3238
 #define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
@@ -734,8 +666,6 @@
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
 #define PCI_DEVICE_ID_PCTECH_RZ1001	0x1001
-#define PCI_DEVICE_ID_PCTECH_SAMURAI_0	0x3000
-#define PCI_DEVICE_ID_PCTECH_SAMURAI_1	0x3010
 #define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
 
 #define PCI_VENDOR_ID_ASUSTEK		0x1043
@@ -745,24 +675,15 @@
 #define PCI_DEVICE_ID_DPT		0xa400
 
 #define PCI_VENDOR_ID_OPTI		0x1045
-#define PCI_DEVICE_ID_OPTI_92C178	0xc178
-#define PCI_DEVICE_ID_OPTI_82C557	0xc557
 #define PCI_DEVICE_ID_OPTI_82C558	0xc558
 #define PCI_DEVICE_ID_OPTI_82C621	0xc621
 #define PCI_DEVICE_ID_OPTI_82C700	0xc700
-#define PCI_DEVICE_ID_OPTI_82C701	0xc701
-#define PCI_DEVICE_ID_OPTI_82C814	0xc814
-#define PCI_DEVICE_ID_OPTI_82C822	0xc822
-#define PCI_DEVICE_ID_OPTI_82C861	0xc861
 #define PCI_DEVICE_ID_OPTI_82C825	0xd568
 
 #define PCI_VENDOR_ID_ELSA		0x1048
 #define PCI_DEVICE_ID_ELSA_MICROLINK	0x1000
 #define PCI_DEVICE_ID_ELSA_QS3000	0x3000
 
-#define PCI_VENDOR_ID_SGS		0x104a
-#define PCI_DEVICE_ID_SGS_2000		0x0008
-#define PCI_DEVICE_ID_SGS_1764		0x0009
 
 #define PCI_VENDOR_ID_BUSLOGIC		      0x104B
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
@@ -770,7 +691,6 @@
 #define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT     0x8130
 
 #define PCI_VENDOR_ID_TI		0x104c
-#define PCI_DEVICE_ID_TI_TVP4010	0x3d04
 #define PCI_DEVICE_ID_TI_TVP4020	0x3d07
 #define PCI_DEVICE_ID_TI_4450		0x8011
 #define PCI_DEVICE_ID_TI_XX21_XX11	0x8031
@@ -804,14 +724,10 @@
 #define PCI_DEVICE_ID_TI_X420		0xac8e
 
 #define PCI_VENDOR_ID_SONY		0x104d
-#define PCI_DEVICE_ID_SONY_CXD3222	0x8039
 
-#define PCI_VENDOR_ID_OAK		0x104e
-#define PCI_DEVICE_ID_OAK_OTI107	0x0107
 
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2		0x1050
-#define PCI_DEVICE_ID_WINBOND2_89C940	0x0940
 #define PCI_DEVICE_ID_WINBOND2_89C940F	0x5a5a
 #define PCI_DEVICE_ID_WINBOND2_6692	0x6692
 
@@ -820,19 +736,15 @@
   
 #define PCI_VENDOR_ID_EFAR		0x1055
 #define PCI_DEVICE_ID_EFAR_SLC90E66_1	0x9130
-#define PCI_DEVICE_ID_EFAR_SLC90E66_0	0x9460
-#define PCI_DEVICE_ID_EFAR_SLC90E66_2	0x9462
 #define PCI_DEVICE_ID_EFAR_SLC90E66_3	0x9463
 
 #define PCI_VENDOR_ID_MOTOROLA		0x1057
-#define PCI_VENDOR_ID_MOTOROLA_OOPS	0x1507
 #define PCI_DEVICE_ID_MOTOROLA_MPC105	0x0001
 #define PCI_DEVICE_ID_MOTOROLA_MPC106	0x0002
 #define PCI_DEVICE_ID_MOTOROLA_MPC107	0x0004
 #define PCI_DEVICE_ID_MOTOROLA_RAVEN	0x4801
 #define PCI_DEVICE_ID_MOTOROLA_FALCON	0x4802
 #define PCI_DEVICE_ID_MOTOROLA_HAWK	0x4803
-#define PCI_DEVICE_ID_MOTOROLA_CPX8216	0x4806
 #define PCI_DEVICE_ID_MOTOROLA_HARRIER	0x480b
 #define PCI_DEVICE_ID_MOTOROLA_MPC5200	0x5803
 
@@ -843,33 +755,19 @@
 #define PCI_DEVICE_ID_PROMISE_20262	0x4d38
 #define PCI_DEVICE_ID_PROMISE_20263	0x0D38
 #define PCI_DEVICE_ID_PROMISE_20268	0x4d68
-#define PCI_DEVICE_ID_PROMISE_20268R	0x6268
 #define PCI_DEVICE_ID_PROMISE_20269	0x4d69
 #define PCI_DEVICE_ID_PROMISE_20270	0x6268
 #define PCI_DEVICE_ID_PROMISE_20271	0x6269
 #define PCI_DEVICE_ID_PROMISE_20275	0x1275
 #define PCI_DEVICE_ID_PROMISE_20276	0x5275
 #define PCI_DEVICE_ID_PROMISE_20277	0x7275
-#define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
-#define PCI_VENDOR_ID_N9		0x105d
-#define PCI_DEVICE_ID_N9_I128		0x2309
-#define PCI_DEVICE_ID_N9_I128_2		0x2339
-#define PCI_DEVICE_ID_N9_I128_T2R	0x493d
 
 #define PCI_VENDOR_ID_UMC		0x1060
 #define PCI_DEVICE_ID_UMC_UM8673F	0x0101
-#define PCI_DEVICE_ID_UMC_UM8891A	0x0891
 #define PCI_DEVICE_ID_UMC_UM8886BF	0x673a
 #define PCI_DEVICE_ID_UMC_UM8886A	0x886a
-#define PCI_DEVICE_ID_UMC_UM8881F	0x8881
-#define PCI_DEVICE_ID_UMC_UM8886F	0x8886
-#define PCI_DEVICE_ID_UMC_UM9017F	0x9017
-#define PCI_DEVICE_ID_UMC_UM8886N	0xe886
-#define PCI_DEVICE_ID_UMC_UM8891N	0xe891
 
-#define PCI_VENDOR_ID_X			0x1061
-#define PCI_DEVICE_ID_X_AGX016		0x0001
 
 #define PCI_VENDOR_ID_MYLEX		0x1069
 #define PCI_DEVICE_ID_MYLEX_DAC960_P	0x0001
@@ -880,37 +778,26 @@
 #define PCI_DEVICE_ID_MYLEX_DAC960_BA	0xBA56
 #define PCI_DEVICE_ID_MYLEX_DAC960_GEM	0xB166
 
-#define PCI_VENDOR_ID_PICOP		0x1066
-#define PCI_DEVICE_ID_PICOP_PT86C52X	0x0001
-#define PCI_DEVICE_ID_PICOP_PT80C524	0x8002
 
 #define PCI_VENDOR_ID_APPLE		0x106b
 #define PCI_DEVICE_ID_APPLE_BANDIT	0x0001
-#define PCI_DEVICE_ID_APPLE_GC		0x0002
 #define PCI_DEVICE_ID_APPLE_HYDRA	0x000e
 #define PCI_DEVICE_ID_APPLE_UNI_N_FW	0x0018
-#define PCI_DEVICE_ID_APPLE_KL_USB	0x0019
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP	0x0020
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC	0x0021
-#define PCI_DEVICE_ID_APPLE_KEYLARGO	0x0022
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMACP	0x0024
-#define PCI_DEVICE_ID_APPLE_KEYLARGO_P	0x0025
-#define PCI_DEVICE_ID_APPLE_KL_USB_P	0x0026
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P	0x0027
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP15	0x002d
 #define PCI_DEVICE_ID_APPLE_UNI_N_PCI15	0x002e
-#define PCI_DEVICE_ID_APPLE_UNI_N_FW2	0x0030
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2	0x0032
 #define PCI_DEVICE_ID_APPLE_UNI_N_ATA	0x0033
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP2	0x0034
 #define PCI_DEVICE_ID_APPLE_IPID_ATA100	0x003b
-#define PCI_DEVICE_ID_APPLE_KEYLARGO_I	0x003e
 #define PCI_DEVICE_ID_APPLE_K2_ATA100	0x0043
 #define PCI_DEVICE_ID_APPLE_U3_AGP	0x004b
 #define PCI_DEVICE_ID_APPLE_K2_GMAC	0x004c
 #define PCI_DEVICE_ID_APPLE_SH_ATA      0x0050
 #define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
-#define PCI_DEVICE_ID_APPLE_SH_FW       0x0052
 #define PCI_DEVICE_ID_APPLE_U3L_AGP	0x0058
 #define PCI_DEVICE_ID_APPLE_U3H_AGP	0x0059
 #define PCI_DEVICE_ID_APPLE_TIGON3	0x1645
@@ -923,12 +810,9 @@
 #define PCI_DEVICE_ID_YAMAHA_744	0x0010
 #define PCI_DEVICE_ID_YAMAHA_754	0x0012
 
-#define PCI_VENDOR_ID_NEXGEN		0x1074
-#define PCI_DEVICE_ID_NEXGEN_82C501	0x4e78
 
 #define PCI_VENDOR_ID_QLOGIC		0x1077
 #define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
-#define PCI_DEVICE_ID_QLOGIC_ISP1022	0x1022
 #define PCI_DEVICE_ID_QLOGIC_ISP2100	0x2100
 #define PCI_DEVICE_ID_QLOGIC_ISP2200	0x2200
 #define PCI_DEVICE_ID_QLOGIC_ISP2300	0x2300
@@ -946,32 +830,20 @@
 #define PCI_DEVICE_ID_CYRIX_PCI_MASTER	0x0001
 #define PCI_DEVICE_ID_CYRIX_5520	0x0002
 #define PCI_DEVICE_ID_CYRIX_5530_LEGACY	0x0100
-#define PCI_DEVICE_ID_CYRIX_5530_SMI	0x0101
 #define PCI_DEVICE_ID_CYRIX_5530_IDE	0x0102
 #define PCI_DEVICE_ID_CYRIX_5530_AUDIO	0x0103
 #define PCI_DEVICE_ID_CYRIX_5530_VIDEO	0x0104
 
-#define PCI_VENDOR_ID_LEADTEK		0x107d
-#define PCI_DEVICE_ID_LEADTEK_805	0x0000
 
-#define PCI_VENDOR_ID_INTERPHASE	0x107e
-#define PCI_DEVICE_ID_INTERPHASE_5526	0x0004
-#define PCI_DEVICE_ID_INTERPHASE_55x6	0x0005
-#define PCI_DEVICE_ID_INTERPHASE_5575	0x0008
 
 #define PCI_VENDOR_ID_CONTAQ		0x1080
-#define PCI_DEVICE_ID_CONTAQ_82C599	0x0600
 #define PCI_DEVICE_ID_CONTAQ_82C693	0xc693
 
-#define PCI_VENDOR_ID_FOREX		0x1083
 
 #define PCI_VENDOR_ID_OLICOM		0x108d
-#define PCI_DEVICE_ID_OLICOM_OC3136	0x0001
-#define PCI_DEVICE_ID_OLICOM_OC2315	0x0011
 #define PCI_DEVICE_ID_OLICOM_OC2325	0x0012
 #define PCI_DEVICE_ID_OLICOM_OC2183	0x0013
 #define PCI_DEVICE_ID_OLICOM_OC2326	0x0014
-#define PCI_DEVICE_ID_OLICOM_OC6151	0x0021
 
 #define PCI_VENDOR_ID_SUN		0x108e
 #define PCI_DEVICE_ID_SUN_EBUS		0x1000
@@ -990,49 +862,31 @@
 #define PCI_DEVICE_ID_SUN_CASSINI	0xabba
 
 #define PCI_VENDOR_ID_CMD		0x1095
-#define PCI_DEVICE_ID_CMD_640		0x0640
 #define PCI_DEVICE_ID_CMD_643		0x0643
 #define PCI_DEVICE_ID_CMD_646		0x0646
-#define PCI_DEVICE_ID_CMD_647		0x0647
 #define PCI_DEVICE_ID_CMD_648		0x0648
 #define PCI_DEVICE_ID_CMD_649		0x0649
-#define PCI_DEVICE_ID_CMD_670		0x0670
-#define PCI_DEVICE_ID_CMD_680		0x0680
 
 #define PCI_DEVICE_ID_SII_680		0x0680
 #define PCI_DEVICE_ID_SII_3112		0x3112
 #define PCI_DEVICE_ID_SII_1210SA	0x0240
 
-#define PCI_VENDOR_ID_VISION		0x1098
-#define PCI_DEVICE_ID_VISION_QD8500	0x0001
-#define PCI_DEVICE_ID_VISION_QD8580	0x0002
 
 #define PCI_VENDOR_ID_BROOKTREE		0x109e
-#define PCI_DEVICE_ID_BROOKTREE_848	0x0350
-#define PCI_DEVICE_ID_BROOKTREE_849A	0x0351
-#define PCI_DEVICE_ID_BROOKTREE_878_1	0x036e
 #define PCI_DEVICE_ID_BROOKTREE_878	0x0878
 #define PCI_DEVICE_ID_BROOKTREE_879	0x0879
-#define PCI_DEVICE_ID_BROOKTREE_8474	0x8474
 
-#define PCI_VENDOR_ID_SIERRA		0x10a8
-#define PCI_DEVICE_ID_SIERRA_STB	0x0000
 
 #define PCI_VENDOR_ID_SGI		0x10a9
 #define PCI_DEVICE_ID_SGI_IOC3		0x0003
 #define PCI_DEVICE_ID_SGI_IOC4		0x100a
 #define PCI_VENDOR_ID_SGI_LITHIUM	0x1002
 
-#define PCI_VENDOR_ID_ACC		0x10aa
-#define PCI_DEVICE_ID_ACC_2056		0x0000
 
 #define PCI_VENDOR_ID_WINBOND		0x10ad
-#define PCI_DEVICE_ID_WINBOND_83769	0x0001
 #define PCI_DEVICE_ID_WINBOND_82C105	0x0105
 #define PCI_DEVICE_ID_WINBOND_83C553	0x0565
 
-#define PCI_VENDOR_ID_DATABOOK		0x10b3
-#define PCI_DEVICE_ID_DATABOOK_87144	0xb106
 
 #define PCI_VENDOR_ID_PLX		0x10b5
 #define PCI_DEVICE_ID_PLX_R685		0x1030
@@ -1043,33 +897,19 @@
 #define PCI_DEVICE_ID_PLX_DJINN_ITOO	0x1151
 #define PCI_DEVICE_ID_PLX_R753		0x1152
 #define PCI_DEVICE_ID_PLX_OLITEC	0x1187
-#define PCI_DEVICE_ID_PLX_9030		0x9030
 #define PCI_DEVICE_ID_PLX_9050		0x9050
-#define PCI_DEVICE_ID_PLX_9060		0x9060
-#define PCI_DEVICE_ID_PLX_9060ES	0x906E
-#define PCI_DEVICE_ID_PLX_9060SD	0x906D
 #define PCI_DEVICE_ID_PLX_9080		0x9080
 #define PCI_DEVICE_ID_PLX_GTEK_SERIAL2	0xa001
 
 #define PCI_VENDOR_ID_MADGE		0x10b6
 #define PCI_DEVICE_ID_MADGE_MK2		0x0002
-#define PCI_DEVICE_ID_MADGE_C155S	0x1001
 
 #define PCI_VENDOR_ID_3COM		0x10b7
 #define PCI_DEVICE_ID_3COM_3C985	0x0001
 #define PCI_DEVICE_ID_3COM_3C940	0x1700
 #define PCI_DEVICE_ID_3COM_3C339	0x3390
 #define PCI_DEVICE_ID_3COM_3C359	0x3590
-#define PCI_DEVICE_ID_3COM_3C590	0x5900
-#define PCI_DEVICE_ID_3COM_3C595TX	0x5950
-#define PCI_DEVICE_ID_3COM_3C595T4	0x5951
-#define PCI_DEVICE_ID_3COM_3C595MII	0x5952
 #define PCI_DEVICE_ID_3COM_3C940B	0x80eb
-#define PCI_DEVICE_ID_3COM_3C900TPO	0x9000
-#define PCI_DEVICE_ID_3COM_3C900COMBO	0x9001
-#define PCI_DEVICE_ID_3COM_3C905TX	0x9050
-#define PCI_DEVICE_ID_3COM_3C905T4	0x9051
-#define PCI_DEVICE_ID_3COM_3C905B_TX	0x9055
 #define PCI_DEVICE_ID_3COM_3CR990	0x9900
 #define PCI_DEVICE_ID_3COM_3CR990_TX_95	0x9902
 #define PCI_DEVICE_ID_3COM_3CR990_TX_97	0x9903
@@ -1079,24 +919,11 @@
 #define PCI_DEVICE_ID_3COM_3CR990SVR97	0x9909
 #define PCI_DEVICE_ID_3COM_3CR990SVR	0x990a
 
-#define PCI_VENDOR_ID_SMC		0x10b8
-#define PCI_DEVICE_ID_SMC_EPIC100	0x0005
 
 #define PCI_VENDOR_ID_AL		0x10b9
-#define PCI_DEVICE_ID_AL_M1445		0x1445
-#define PCI_DEVICE_ID_AL_M1449		0x1449
-#define PCI_DEVICE_ID_AL_M1451		0x1451
-#define PCI_DEVICE_ID_AL_M1461		0x1461
-#define PCI_DEVICE_ID_AL_M1489		0x1489
-#define PCI_DEVICE_ID_AL_M1511		0x1511
-#define PCI_DEVICE_ID_AL_M1513		0x1513
-#define PCI_DEVICE_ID_AL_M1521		0x1521
-#define PCI_DEVICE_ID_AL_M1523		0x1523
-#define PCI_DEVICE_ID_AL_M1531		0x1531
 #define PCI_DEVICE_ID_AL_M1533		0x1533
 #define PCI_DEVICE_ID_AL_M1535 		0x1535
 #define PCI_DEVICE_ID_AL_M1541		0x1541
-#define PCI_DEVICE_ID_AL_M1543		0x1543
 #define PCI_DEVICE_ID_AL_M1563		0x1563
 #define PCI_DEVICE_ID_AL_M1621		0x1621
 #define PCI_DEVICE_ID_AL_M1631		0x1631
@@ -1109,49 +936,23 @@
 #define PCI_DEVICE_ID_AL_M1681		0x1681
 #define PCI_DEVICE_ID_AL_M1683		0x1683
 #define PCI_DEVICE_ID_AL_M1689		0x1689
-#define PCI_DEVICE_ID_AL_M3307		0x3307
-#define PCI_DEVICE_ID_AL_M4803		0x5215
 #define PCI_DEVICE_ID_AL_M5219		0x5219
 #define PCI_DEVICE_ID_AL_M5228		0x5228
 #define PCI_DEVICE_ID_AL_M5229		0x5229
-#define PCI_DEVICE_ID_AL_M5237		0x5237
-#define PCI_DEVICE_ID_AL_M5243		0x5243
 #define PCI_DEVICE_ID_AL_M5451		0x5451
 #define PCI_DEVICE_ID_AL_M7101		0x7101
 
-#define PCI_VENDOR_ID_MITSUBISHI	0x10ba
 
-#define PCI_VENDOR_ID_SURECOM		0x10bd
-#define PCI_DEVICE_ID_SURECOM_NE34	0x0e34
 
 #define PCI_VENDOR_ID_NEOMAGIC		0x10c8
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV       0x0005
-#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS   0x0083
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 #define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
 
-#define PCI_VENDOR_ID_ASP		0x10cd
-#define PCI_DEVICE_ID_ASP_ABP940	0x1200
-#define PCI_DEVICE_ID_ASP_ABP940U	0x1300
-#define PCI_DEVICE_ID_ASP_ABP940UW	0x2300
-
-#define PCI_VENDOR_ID_MACRONIX		0x10d9
-#define PCI_DEVICE_ID_MACRONIX_MX98713	0x0512
-#define PCI_DEVICE_ID_MACRONIX_MX987x5	0x0531
 
 #define PCI_VENDOR_ID_TCONRAD		0x10da
 #define PCI_DEVICE_ID_TCONRAD_TOKENRING	0x0508
 
-#define PCI_VENDOR_ID_CERN		0x10dc
-#define PCI_DEVICE_ID_CERN_SPSB_PMC	0x0001
-#define PCI_DEVICE_ID_CERN_SPSB_PCI	0x0002
-#define PCI_DEVICE_ID_CERN_HIPPI_DST	0x0021
-#define PCI_DEVICE_ID_CERN_HIPPI_SRC	0x0022
 
 #define PCI_VENDOR_ID_NVIDIA			0x10de
 #define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
@@ -1197,7 +998,6 @@
 #define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
 #define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3		0x00d1
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO		0x00da
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS	0x00d4
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE	0x00d5
 #define PCI_DEVICE_ID_NVIDIA_NVENET_3		0x00d6
@@ -1284,7 +1084,6 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2	0x037F
 #define PCI_DEVICE_ID_NVIDIA_NVENET_12		0x0268
 #define PCI_DEVICE_ID_NVIDIA_NVENET_13		0x0269
-#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO	0x026B
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800	0x0280
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
@@ -1335,24 +1134,13 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
 
 #define PCI_VENDOR_ID_IMS		0x10e0
-#define PCI_DEVICE_ID_IMS_8849		0x8849
 #define PCI_DEVICE_ID_IMS_TT128		0x9128
 #define PCI_DEVICE_ID_IMS_TT3D		0x9135
 
-#define PCI_VENDOR_ID_TEKRAM2		0x10e1
-#define PCI_DEVICE_ID_TEKRAM2_690c	0x690c
 
-#define PCI_VENDOR_ID_TUNDRA		0x10e3
-#define PCI_DEVICE_ID_TUNDRA_CA91C042	0x0000
 
-#define PCI_VENDOR_ID_AMCC		0x10e8
-#define PCI_DEVICE_ID_AMCC_MYRINET	0x8043
-#define PCI_DEVICE_ID_AMCC_PARASTATION	0x8062
-#define PCI_DEVICE_ID_AMCC_S5933	0x807d
-#define PCI_DEVICE_ID_AMCC_S5933_HEPC3	0x809c
 
 #define PCI_VENDOR_ID_INTERG		0x10ea
-#define PCI_DEVICE_ID_INTERG_1680	0x1680
 #define PCI_DEVICE_ID_INTERG_1682	0x1682
 #define PCI_DEVICE_ID_INTERG_2000	0x2000
 #define PCI_DEVICE_ID_INTERG_2010	0x2010
@@ -1360,32 +1148,23 @@
 #define PCI_DEVICE_ID_INTERG_5050	0x5050
 
 #define PCI_VENDOR_ID_REALTEK		0x10ec
-#define PCI_DEVICE_ID_REALTEK_8029	0x8029
-#define PCI_DEVICE_ID_REALTEK_8129	0x8129
 #define PCI_DEVICE_ID_REALTEK_8139	0x8139
-#define PCI_DEVICE_ID_REALTEK_8169	0x8169
 
 #define PCI_VENDOR_ID_XILINX		0x10ee
 #define PCI_DEVICE_ID_RME_DIGI96	0x3fc0
 #define PCI_DEVICE_ID_RME_DIGI96_8	0x3fc1
 #define PCI_DEVICE_ID_RME_DIGI96_8_PRO	0x3fc2
 #define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL	0x3fc4
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
 #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-#define PCI_DEVICE_ID_TURBOPAM		0x4020
 
-#define PCI_VENDOR_ID_TRUEVISION	0x10fa
-#define PCI_DEVICE_ID_TRUEVISION_T1000	0x000c
 
 #define PCI_VENDOR_ID_INIT		0x1101
-#define PCI_DEVICE_ID_INIT_320P		0x9100
-#define PCI_DEVICE_ID_INIT_360P		0x9500
 
-#define PCI_VENDOR_ID_CREATIVE		0x1102 // duplicate: ECTIVA
+#define PCI_VENDOR_ID_CREATIVE		0x1102 /* duplicate: ECTIVA */
 #define PCI_DEVICE_ID_CREATIVE_EMU10K1	0x0002
 
-#define PCI_VENDOR_ID_ECTIVA		0x1102 // duplicate: CREATIVE
+#define PCI_VENDOR_ID_ECTIVA		0x1102 /* duplicate: CREATIVE */
 #define PCI_DEVICE_ID_ECTIVA_EV1938	0x8938
 
 #define PCI_VENDOR_ID_TTI		0x1103
@@ -1395,7 +1174,7 @@
 #define PCI_DEVICE_ID_TTI_HPT302	0x0006
 #define PCI_DEVICE_ID_TTI_HPT371	0x0007
 #define PCI_DEVICE_ID_TTI_HPT374	0x0008
-#define PCI_DEVICE_ID_TTI_HPT372N	0x0009	// apparently a 372N variant?
+#define PCI_DEVICE_ID_TTI_HPT372N	0x0009	/* apparently a 372N variant? */
 
 #define PCI_VENDOR_ID_VIA		0x1106
 #define PCI_DEVICE_ID_VIA_8763_0	0x0198
@@ -1408,36 +1187,25 @@
 #define PCI_DEVICE_ID_VIA_8363_0	0x0305
 #define PCI_DEVICE_ID_VIA_8371_0	0x0391
 #define PCI_DEVICE_ID_VIA_8501_0	0x0501
-#define PCI_DEVICE_ID_VIA_82C505	0x0505
 #define PCI_DEVICE_ID_VIA_82C561	0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1	0x0571
 #define PCI_DEVICE_ID_VIA_82C576	0x0576
-#define PCI_DEVICE_ID_VIA_82C585	0x0585
 #define PCI_DEVICE_ID_VIA_82C586_0	0x0586
-#define PCI_DEVICE_ID_VIA_82C595	0x0595
 #define PCI_DEVICE_ID_VIA_82C596	0x0596
 #define PCI_DEVICE_ID_VIA_82C597_0	0x0597
 #define PCI_DEVICE_ID_VIA_82C598_0	0x0598
 #define PCI_DEVICE_ID_VIA_8601_0	0x0601
 #define PCI_DEVICE_ID_VIA_8605_0	0x0605
-#define PCI_DEVICE_ID_VIA_82C680	0x0680
 #define PCI_DEVICE_ID_VIA_82C686	0x0686
 #define PCI_DEVICE_ID_VIA_82C691_0	0x0691
-#define PCI_DEVICE_ID_VIA_82C693	0x0693
-#define PCI_DEVICE_ID_VIA_82C693_1	0x0698
-#define PCI_DEVICE_ID_VIA_82C926	0x0926
 #define PCI_DEVICE_ID_VIA_82C576_1	0x1571
-#define PCI_DEVICE_ID_VIA_82C595_97	0x1595
 #define PCI_DEVICE_ID_VIA_82C586_2	0x3038
 #define PCI_DEVICE_ID_VIA_82C586_3	0x3040
-#define PCI_DEVICE_ID_VIA_6305		0x3044
 #define PCI_DEVICE_ID_VIA_82C596_3	0x3050
 #define PCI_DEVICE_ID_VIA_82C596B_3	0x3051
 #define PCI_DEVICE_ID_VIA_82C686_4	0x3057
 #define PCI_DEVICE_ID_VIA_82C686_5	0x3058
 #define PCI_DEVICE_ID_VIA_8233_5	0x3059
-#define PCI_DEVICE_ID_VIA_8233_7	0x3065
-#define PCI_DEVICE_ID_VIA_82C686_6	0x3068
 #define PCI_DEVICE_ID_VIA_8233_0	0x3074
 #define PCI_DEVICE_ID_VIA_8633_0	0x3091
 #define PCI_DEVICE_ID_VIA_8367_0	0x3099
@@ -1455,38 +1223,23 @@
 #define PCI_DEVICE_ID_VIA_XN266		0x3156
 #define PCI_DEVICE_ID_VIA_8754C_0	0x3168
 #define PCI_DEVICE_ID_VIA_8235		0x3177
-#define PCI_DEVICE_ID_VIA_P4N333	0x3178
 #define PCI_DEVICE_ID_VIA_8385_0	0x3188
 #define PCI_DEVICE_ID_VIA_8377_0	0x3189
 #define PCI_DEVICE_ID_VIA_8378_0	0x3205
 #define PCI_DEVICE_ID_VIA_8783_0	0x3208
-#define PCI_DEVICE_ID_VIA_P4M400	0x3209
 #define PCI_DEVICE_ID_VIA_8237		0x3227
 #define PCI_DEVICE_ID_VIA_3296_0	0x0296
-#define PCI_DEVICE_ID_VIA_86C100A	0x6100
 #define PCI_DEVICE_ID_VIA_8231		0x8231
 #define PCI_DEVICE_ID_VIA_8231_4	0x8235
 #define PCI_DEVICE_ID_VIA_8365_1	0x8305
 #define PCI_DEVICE_ID_VIA_8371_1	0x8391
-#define PCI_DEVICE_ID_VIA_8501_1	0x8501
-#define PCI_DEVICE_ID_VIA_82C597_1	0x8597
 #define PCI_DEVICE_ID_VIA_82C598_1	0x8598
-#define PCI_DEVICE_ID_VIA_8601_1	0x8601
-#define PCI_DEVICE_ID_VIA_8505_1	0x8605
-#define PCI_DEVICE_ID_VIA_8633_1	0xB091
-#define PCI_DEVICE_ID_VIA_8367_1	0xB099
-#define PCI_DEVICE_ID_VIA_P4X266_1	0xB101
-#define PCI_DEVICE_ID_VIA_8615_1	0xB103
-#define PCI_DEVICE_ID_VIA_8361_1	0xB112
-#define PCI_DEVICE_ID_VIA_8235_1	0xB168
 #define PCI_DEVICE_ID_VIA_838X_1	0xB188
 #define PCI_DEVICE_ID_VIA_83_87XX_1	0xB198
 
 #define PCI_VENDOR_ID_SIEMENS           0x110A
 #define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
 
-#define PCI_VENDOR_ID_SMC2		0x1113
-#define PCI_DEVICE_ID_SMC2_1211TX	0x1211
 
 #define PCI_VENDOR_ID_VORTEX		0x1119
 #define PCI_DEVICE_ID_VORTEX_GDT60x0	0x0000
@@ -1509,18 +1262,6 @@
 #define PCI_DEVICE_ID_VORTEX_GDT6557RP	0x0103
 #define PCI_DEVICE_ID_VORTEX_GDT6x11RP	0x0104
 #define PCI_DEVICE_ID_VORTEX_GDT6x21RP	0x0105
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1	0x0110
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1	0x0111
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP1	0x0112
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP1	0x0113
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1	0x0114
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1	0x0115
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2	0x0120
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2	0x0121
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP2	0x0122
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP2	0x0123
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2	0x0124
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2	0x0125
 
 #define PCI_VENDOR_ID_EF		0x111a
 #define PCI_DEVICE_ID_EF_ATM_FPGA	0x0000
@@ -1532,21 +1273,15 @@
 #define PCI_DEVICE_ID_IDT_IDT77201	0x0001
 
 #define PCI_VENDOR_ID_FORE		0x1127
-#define PCI_DEVICE_ID_FORE_PCA200PC	0x0210
 #define PCI_DEVICE_ID_FORE_PCA200E	0x0300
 
-#define PCI_VENDOR_ID_IMAGINGTECH	0x112f
-#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI	0x0000
 
 #define PCI_VENDOR_ID_PHILIPS		0x1131
-#define PCI_DEVICE_ID_PHILIPS_SAA7145	0x7145
 #define PCI_DEVICE_ID_PHILIPS_SAA7146	0x7146
 #define PCI_DEVICE_ID_PHILIPS_SAA9730	0x9730
 
 #define PCI_VENDOR_ID_EICON		0x1133
-#define PCI_DEVICE_ID_EICON_DIVA20PRO	0xe001
 #define PCI_DEVICE_ID_EICON_DIVA20	0xe002
-#define PCI_DEVICE_ID_EICON_DIVA20PRO_U	0xe003
 #define PCI_DEVICE_ID_EICON_DIVA20_U	0xe004
 #define PCI_DEVICE_ID_EICON_DIVA201	0xe005
 #define PCI_DEVICE_ID_EICON_DIVA202	0xe00b
@@ -1558,35 +1293,17 @@
 #define PCI_VENDOR_ID_ZIATECH		0x1138
 #define PCI_DEVICE_ID_ZIATECH_5550_HC	0x5550
  
-#define PCI_VENDOR_ID_CYCLONE		0x113c
-#define PCI_DEVICE_ID_CYCLONE_SDK	0x0001
 
-#define PCI_VENDOR_ID_ALLIANCE		0x1142
-#define PCI_DEVICE_ID_ALLIANCE_PROMOTIO	0x3210
-#define PCI_DEVICE_ID_ALLIANCE_PROVIDEO	0x6422
-#define PCI_DEVICE_ID_ALLIANCE_AT24	0x6424
-#define PCI_DEVICE_ID_ALLIANCE_AT3D	0x643d
 
 #define PCI_VENDOR_ID_SYSKONNECT	0x1148
-#define PCI_DEVICE_ID_SYSKONNECT_FP	0x4000
 #define PCI_DEVICE_ID_SYSKONNECT_TR	0x4200
 #define PCI_DEVICE_ID_SYSKONNECT_GE	0x4300
 #define PCI_DEVICE_ID_SYSKONNECT_YU	0x4320
 #define PCI_DEVICE_ID_SYSKONNECT_9DXX	0x4400
 #define PCI_DEVICE_ID_SYSKONNECT_9MXX	0x4500
 
-#define PCI_VENDOR_ID_VMIC		0x114a
-#define PCI_DEVICE_ID_VMIC_VME		0x7587
 
 #define PCI_VENDOR_ID_DIGI		0x114f
-#define PCI_DEVICE_ID_DIGI_EPC		0x0002
-#define PCI_DEVICE_ID_DIGI_RIGHTSWITCH	0x0003
-#define PCI_DEVICE_ID_DIGI_XEM		0x0004
-#define PCI_DEVICE_ID_DIGI_XR		0x0005
-#define PCI_DEVICE_ID_DIGI_CX		0x0006
-#define PCI_DEVICE_ID_DIGI_XRJ		0x0009
-#define PCI_DEVICE_ID_DIGI_EPCJ		0x000a
-#define PCI_DEVICE_ID_DIGI_XR_920	0x0027
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E	0x0070
 #define PCI_DEVICE_ID_DIGI_DF_M_E	0x0071
 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A	0x0072
@@ -1596,23 +1313,15 @@
 #define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
 #define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
 
-#define PCI_VENDOR_ID_MUTECH		0x1159
-#define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
 
 #define PCI_VENDOR_ID_XIRCOM		0x115d
-#define PCI_DEVICE_ID_XIRCOM_X3201_ETH	0x0003
 #define PCI_DEVICE_ID_XIRCOM_RBM56G	0x0101
 #define PCI_DEVICE_ID_XIRCOM_X3201_MDM	0x0103
 
-#define PCI_VENDOR_ID_RENDITION		0x1163
-#define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
-#define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
 
 #define PCI_VENDOR_ID_SERVERWORKS	  0x1166
 #define PCI_DEVICE_ID_SERVERWORKS_HE	  0x0008
 #define PCI_DEVICE_ID_SERVERWORKS_LE	  0x0009
-#define PCI_DEVICE_ID_SERVERWORKS_CIOB30  0x0010
-#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011
 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4	  0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5	  0x0201
@@ -1622,13 +1331,7 @@
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
 #define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
-#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
-#define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
-#define PCI_DEVICE_ID_SERVERWORKS_GCLE    0x0225
-#define PCI_DEVICE_ID_SERVERWORKS_GCLE2   0x0227
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
 
 #define PCI_VENDOR_ID_SBE		0x1176
 #define PCI_DEVICE_ID_SBE_WANXL100	0x0301
@@ -1639,17 +1342,12 @@
 #define PCI_DEVICE_ID_TOSHIBA_PICCOLO	0x0102
 #define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1	0x0103
 #define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2	0x0105
-#define PCI_DEVICE_ID_TOSHIBA_601	0x0601
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC95	0x060a
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC95_A 0x0603
-#define PCI_DEVICE_ID_TOSHIBA_TOPIC95_B 0x060a
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC97	0x060f
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC100	0x0617
 
 #define PCI_VENDOR_ID_TOSHIBA_2		0x102f
-#define PCI_DEVICE_ID_TOSHIBA_TX3927	0x000a
 #define PCI_DEVICE_ID_TOSHIBA_TC35815CF	0x0030
-#define PCI_DEVICE_ID_TOSHIBA_TX4927	0x0180
 #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC	0x0108
 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
 
@@ -1664,7 +1362,6 @@
 #define PCI_DEVICE_ID_DLINK_DGE510T	0x4c00
 
 #define PCI_VENDOR_ID_ARTOP		0x1191
-#define PCI_DEVICE_ID_ARTOP_ATP8400	0x0004
 #define PCI_DEVICE_ID_ARTOP_ATP850UF	0x0005
 #define PCI_DEVICE_ID_ARTOP_ATP860	0x0006
 #define PCI_DEVICE_ID_ARTOP_ATP860R	0x0007
@@ -1677,16 +1374,11 @@
 #define PCI_DEVICE_ID_ARTOP_AEC7612D	0x8040
 #define PCI_DEVICE_ID_ARTOP_AEC7612SUW	0x8050
 #define PCI_DEVICE_ID_ARTOP_8060	0x8060
-#define PCI_DEVICE_ID_ARTOP_AEC67160	0x8080
-#define PCI_DEVICE_ID_ARTOP_AEC67160_2	0x8081
-#define PCI_DEVICE_ID_ARTOP_AEC67162	0x808a
 
 #define PCI_VENDOR_ID_ZEITNET		0x1193
 #define PCI_DEVICE_ID_ZEITNET_1221	0x0001
 #define PCI_DEVICE_ID_ZEITNET_1225	0x0002
 
-#define PCI_VENDOR_ID_OMEGA		0x119b
-#define PCI_DEVICE_ID_OMEGA_82C092G	0x1221
 
 #define PCI_VENDOR_ID_FUJITSU_ME	0x119e
 #define PCI_DEVICE_ID_FUJITSU_FS155	0x0001
@@ -1696,61 +1388,41 @@
 #define PCI_SUBDEVICE_ID_KEYSPAN_SX2	0x5334
 
 #define PCI_VENDOR_ID_MARVELL		0x11ab
-#define PCI_DEVICE_ID_MARVELL_GT64011	0x4146
-#define PCI_DEVICE_ID_MARVELL_GT64111	0x4146
 #define PCI_DEVICE_ID_MARVELL_GT64260	0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360	0x6460
 #define PCI_DEVICE_ID_MARVELL_MV64460	0x6480
 #define PCI_DEVICE_ID_MARVELL_GT96100	0x9652
 #define PCI_DEVICE_ID_MARVELL_GT96100A	0x9653
 
-#define PCI_VENDOR_ID_LITEON		0x11ad
-#define PCI_DEVICE_ID_LITEON_LNE100TX	0x0002
 
 #define PCI_VENDOR_ID_V3		0x11b0
 #define PCI_DEVICE_ID_V3_V960		0x0001
-#define PCI_DEVICE_ID_V3_V350		0x0001
-#define PCI_DEVICE_ID_V3_V961		0x0002
 #define PCI_DEVICE_ID_V3_V351		0x0002
 
-#define PCI_VENDOR_ID_NP		0x11bc
-#define PCI_DEVICE_ID_NP_PCI_FDDI	0x0001
 
 #define PCI_VENDOR_ID_ATT		0x11c1
-#define PCI_DEVICE_ID_ATT_L56XMF	0x0440
 #define PCI_DEVICE_ID_ATT_VENUS_MODEM	0x480
 
-#define PCI_VENDOR_ID_NEC2		0x11c3 /* NEC (2nd) */
 
 #define PCI_VENDOR_ID_SPECIALIX		0x11cb
 #define PCI_DEVICE_ID_SPECIALIX_IO8	0x2000
-#define PCI_DEVICE_ID_SPECIALIX_XIO	0x4000
 #define PCI_DEVICE_ID_SPECIALIX_RIO	0x8000
 #define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
 
-#define PCI_VENDOR_ID_AURAVISION	0x11d1
-#define PCI_DEVICE_ID_AURAVISION_VXP524	0x01f7
 
 #define PCI_VENDOR_ID_ANALOG_DEVICES	0x11d4
 #define PCI_DEVICE_ID_AD1889JS		0x1889
 
-#define PCI_VENDOR_ID_IKON		0x11d5
-#define PCI_DEVICE_ID_IKON_10115	0x0115
-#define PCI_DEVICE_ID_IKON_10117	0x0117
 
-#define PCI_VENDOR_ID_SEGA		0x11db
 #define PCI_DEVICE_ID_SEGA_BBA		0x1234
 
 #define PCI_VENDOR_ID_ZORAN		0x11de
 #define PCI_DEVICE_ID_ZORAN_36057	0x6057
 #define PCI_DEVICE_ID_ZORAN_36120	0x6120
 
-#define PCI_VENDOR_ID_KINETIC		0x11f4
-#define PCI_DEVICE_ID_KINETIC_2915	0x2915
 
 #define PCI_VENDOR_ID_COMPEX		0x11f6
 #define PCI_DEVICE_ID_COMPEX_ENET100VG4	0x0112
-#define PCI_DEVICE_ID_COMPEX_RL2000	0x1401
 
 #define PCI_VENDOR_ID_RP		0x11fe
 #define PCI_DEVICE_ID_RP32INTF		0x0001
@@ -1764,7 +1436,6 @@
 #define PCI_DEVICE_ID_RP16SNI		0x0009	
 #define PCI_DEVICE_ID_RPP4		0x000A
 #define PCI_DEVICE_ID_RPP8		0x000B
-#define PCI_DEVICE_ID_RP8M		0x000C
 #define PCI_DEVICE_ID_RP4M		0x000D
 #define PCI_DEVICE_ID_RP2_232		0x000E
 #define PCI_DEVICE_ID_RP2_422		0x000F
@@ -1792,10 +1463,6 @@
 #define PCI_DEVICE_ID_PC300_TE_M_2	0x0320
 #define PCI_DEVICE_ID_PC300_TE_M_1	0x0321
 
-/* Allied Telesyn */
-#define PCI_VENDOR_ID_AT    		0x1259
-#define PCI_SUBDEVICE_ID_AT_2701FX	0x2703
-
 #define PCI_VENDOR_ID_ESSENTIAL		0x120f
 #define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER	0x0001
 
@@ -1812,10 +1479,7 @@
 #define PCI_DEVICE_ID_3DFX_VOODOO3	0x0005
 #define PCI_DEVICE_ID_3DFX_VOODOO5	0x0009
 
-#define PCI_VENDOR_ID_SIGMADES		0x1236
-#define PCI_DEVICE_ID_SIGMADES_6425	0x6401
 
-#define PCI_VENDOR_ID_CCUBE		0x123f
 
 #define PCI_VENDOR_ID_AVM		0x1244
 #define PCI_DEVICE_ID_AVM_B1		0x0700
@@ -1825,19 +1489,8 @@
 #define PCI_DEVICE_ID_AVM_C2		0x1100
 #define PCI_DEVICE_ID_AVM_T1		0x1200
 
-#define PCI_VENDOR_ID_DIPIX		0x1246
 
 #define PCI_VENDOR_ID_STALLION		0x124d
-#define PCI_DEVICE_ID_STALLION_ECHPCI832 0x0000
-#define PCI_DEVICE_ID_STALLION_ECHPCI864 0x0002
-#define PCI_DEVICE_ID_STALLION_EIOPCI	0x0003
-
-#define PCI_VENDOR_ID_OPTIBASE		0x1255
-#define PCI_DEVICE_ID_OPTIBASE_FORGE	0x1110
-#define PCI_DEVICE_ID_OPTIBASE_FUSION	0x1210
-#define PCI_DEVICE_ID_OPTIBASE_VPLEX	0x2110
-#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC	0x2120
-#define PCI_DEVICE_ID_OPTIBASE_VQUEST	0x2130
 
 /* Allied Telesyn */
 #define PCI_VENDOR_ID_AT    		0x1259
@@ -1846,7 +1499,6 @@
 
 #define PCI_VENDOR_ID_ESS		0x125d
 #define PCI_DEVICE_ID_ESS_ESS1968	0x1968
-#define PCI_DEVICE_ID_ESS_AUDIOPCI	0x1969
 #define PCI_DEVICE_ID_ESS_ESS1978	0x1978
 #define PCI_DEVICE_ID_ESS_ALLEGRO_1	0x1988
 #define PCI_DEVICE_ID_ESS_ALLEGRO	0x1989
@@ -1859,11 +1511,7 @@
 
 #define PCI_VENDOR_ID_SATSAGEM		0x1267
 #define PCI_DEVICE_ID_SATSAGEM_NICCY	0x1016
-#define PCI_DEVICE_ID_SATSAGEM_PCR2101	0x5352
-#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
 
-#define PCI_VENDOR_ID_HUGHES		0x1273
-#define PCI_DEVICE_ID_HUGHES_DIRECPC	0x0002
 
 #define PCI_VENDOR_ID_ENSONIQ		0x1274
 #define PCI_DEVICE_ID_ENSONIQ_CT5880	0x5880
@@ -1884,13 +1532,10 @@
 #define PCI_DEVICE_ID_ITE_IT8330G_0	0xe886
 
 /* formerly Platform Tech */
-#define PCI_VENDOR_ID_ESS_OLD		0x1285
 #define PCI_DEVICE_ID_ESS_ESS0100	0x0100
 
 #define PCI_VENDOR_ID_ALTEON		0x12ae
-#define PCI_DEVICE_ID_ALTEON_ACENIC	0x0001
 
-#define PCI_VENDOR_ID_USR		0x12B9
 
 #define PCI_SUBVENDOR_ID_CONNECT_TECH			0x12c4
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232		0x0001
@@ -1905,8 +1550,6 @@
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1	0x000A
 #define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1	0x000B
 
-#define PCI_VENDOR_ID_PICTUREL		0x12c5
-#define PCI_DEVICE_ID_PICTUREL_PCIVST	0x0081
 
 #define PCI_VENDOR_ID_NVIDIA_SGS	0x12d2
 #define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
@@ -1928,8 +1571,6 @@
 #define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
 #define PCI_DEVICE_ID_LML_33R10		0x8a02
 
-#define PCI_VENDOR_ID_CBOARDS		0x1307
-#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
 
 #define PCI_VENDOR_ID_SIIG		0x131f
 #define PCI_SUBVENDOR_ID_SIIG		0x131f
@@ -1973,7 +1614,6 @@
 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL	0x2050
 
 #define PCI_VENDOR_ID_RADISYS		0x1331
-#define PCI_DEVICE_ID_RADISYS_ENP2611	0x0030
 
 #define PCI_VENDOR_ID_DOMEX		0x134a
 #define PCI_DEVICE_ID_DOMEX_DMX3191D	0x0001
@@ -1981,8 +1621,6 @@
 #define PCI_VENDOR_ID_QUATECH		0x135C
 #define PCI_DEVICE_ID_QUATECH_QSC100	0x0010
 #define PCI_DEVICE_ID_QUATECH_DSC100	0x0020
-#define PCI_DEVICE_ID_QUATECH_DSC200	0x0030
-#define PCI_DEVICE_ID_QUATECH_QSC200	0x0040
 #define PCI_DEVICE_ID_QUATECH_ESC100D	0x0050
 #define PCI_DEVICE_ID_QUATECH_ESC100M	0x0060
 
@@ -2001,7 +1639,6 @@
 #define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO		0x0106
 #define PCI_SUBDEVICE_ID_HYPERCOPE_METRO	0x0107
 #define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2	0x0108
-#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS	0x0109
 
 #define PCI_VENDOR_ID_KAWASAKI		0x136b
 #define PCI_DEVICE_ID_MCHIP_KL5A72002	0xff01
@@ -2015,12 +1652,9 @@
 #define PCI_DEVICE_ID_LMC_SSI		0x0005
 #define PCI_DEVICE_ID_LMC_T1		0x0006
 
-#define PCI_VENDOR_ID_MARIAN		0x1382
-#define PCI_DEVICE_ID_MARIAN_PRODIF_PLUS 0x2048
 
 #define PCI_VENDOR_ID_NETGEAR		0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
-#define PCI_DEVICE_ID_NETGEAR_GA622	0x622a
 
 #define PCI_VENDOR_ID_APPLICOM		0x1389
 #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
@@ -2043,9 +1677,6 @@
 #define PCI_DEVICE_ID_MOXA_CP134U	0x1340
 #define PCI_DEVICE_ID_MOXA_C168		0x1680
 #define PCI_DEVICE_ID_MOXA_CP168U	0x1681
-#define PCI_DEVICE_ID_MOXA_CP204J	0x2040
-#define PCI_DEVICE_ID_MOXA_C218		0x2180
-#define PCI_DEVICE_ID_MOXA_C320		0x3200
 
 #define PCI_VENDOR_ID_CCD		0x1397
 #define PCI_DEVICE_ID_CCD_2BD0		0x2bd0
@@ -2066,9 +1697,7 @@
 
 #define PCI_VENDOR_ID_MICROGATE		0x13c0
 #define PCI_DEVICE_ID_MICROGATE_USC	0x0010
-#define PCI_DEVICE_ID_MICROGATE_SCC	0x0020
 #define PCI_DEVICE_ID_MICROGATE_SCA	0x0030
-#define PCI_DEVICE_ID_MICROGATE_USC2	0x0210
 
 #define PCI_VENDOR_ID_3WARE		0x13C1
 #define PCI_DEVICE_ID_3WARE_1000	0x1000
@@ -2119,10 +1748,6 @@
 
 #define PCI_VENDOR_ID_SAMSUNG		0x144d
 
-#define PCI_VENDOR_ID_AIRONET		0x14b9
-#define PCI_DEVICE_ID_AIRONET_4800_1	0x0001
-#define PCI_DEVICE_ID_AIRONET_4800	0x4500 // values switched?  see
-#define PCI_DEVICE_ID_AIRONET_4500	0x4800 // drivers/net/aironet4500_card.c
 
 #define PCI_VENDOR_ID_TITAN		0x14D2
 #define PCI_DEVICE_ID_TITAN_010L	0x8001
@@ -2141,8 +1766,6 @@
 #define PCI_DEVICE_ID_PANACOM_QUADMODEM	0x0400
 #define PCI_DEVICE_ID_PANACOM_DUALMODEM	0x0402
 
-#define PCI_VENDOR_ID_SIPACKETS		0x14d9
-#define PCI_DEVICE_ID_SP_HT		0x0010
 
 #define PCI_VENDOR_ID_AFAVLAB		0x14db
 #define PCI_DEVICE_ID_AFAVLAB_P028	0x2180
@@ -2165,11 +1788,13 @@
 #define PCI_DEVICE_ID_TIGON3_5721	0x1659
 #define PCI_DEVICE_ID_TIGON3_5705M	0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2	0x165e
+#define PCI_DEVICE_ID_TIGON3_5714	0x1668
 #define PCI_DEVICE_ID_TIGON3_5780	0x166a
 #define PCI_DEVICE_ID_TIGON3_5780S	0x166b
 #define PCI_DEVICE_ID_TIGON3_5705F	0x166e
 #define PCI_DEVICE_ID_TIGON3_5750	0x1676
 #define PCI_DEVICE_ID_TIGON3_5751	0x1677
+#define PCI_DEVICE_ID_TIGON3_5715	0x1678
 #define PCI_DEVICE_ID_TIGON3_5750M	0x167c
 #define PCI_DEVICE_ID_TIGON3_5751M	0x167d
 #define PCI_DEVICE_ID_TIGON3_5751F	0x167e
@@ -2207,8 +1832,6 @@
 
 #define PCI_VENDOR_ID_CHELSIO		0x1425
 
-#define PCI_VENDOR_ID_MIPS		0x153f
-#define PCI_DEVICE_ID_SOC_IT		0x0001
 
 #define PCI_VENDOR_ID_SYBA		0x1592
 #define PCI_DEVICE_ID_SYBA_2P_EPP	0x0782
@@ -2228,15 +1851,7 @@
 #define PCI_DEVICE_ID_MELLANOX_SINAI	0x6274
 
 #define PCI_VENDOR_ID_PDC		0x15e9
-#define PCI_DEVICE_ID_PDC_1841		0x1841
 
-#define PCI_VENDOR_ID_MACROLINK		0x15ed
-#define PCI_DEVICE_ID_MACROLINK_MCCS8	0x1000
-#define PCI_DEVICE_ID_MACROLINK_MCCS	0x1001
-#define PCI_DEVICE_ID_MACROLINK_MCCS8H	0x1002
-#define PCI_DEVICE_ID_MACROLINK_MCCSH	0x1003
-#define PCI_DEVICE_ID_MACROLINK_MCCR8	0x2000
-#define PCI_DEVICE_ID_MACROLINK_MCCR	0x2001
 
 #define PCI_VENDOR_ID_FARSITE           0x1619
 #define PCI_DEVICE_ID_FARSITE_T2P       0x0400
@@ -2254,7 +1869,6 @@
 #define PCI_DEVICE_ID_REVOLUTION	0x0044
 
 #define PCI_VENDOR_ID_LINKSYS		0x1737
-#define PCI_DEVICE_ID_LINKSYS_EG1032	0x1032
 #define PCI_DEVICE_ID_LINKSYS_EG1064	0x1064
 
 #define PCI_VENDOR_ID_ALTIMA		0x173b
@@ -2269,7 +1883,6 @@
 #define PCI_DEVICE_ID_HERC_WIN		0x5732
 #define PCI_DEVICE_ID_HERC_UNI		0x5832
 
-#define PCI_VENDOR_ID_INFINICON		0x1820
 
 #define PCI_VENDOR_ID_SITECOM		0x182d
 #define PCI_DEVICE_ID_SITECOM_DC105V2	0x3069
@@ -2279,8 +1892,6 @@
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
-#define PCI_VENDOR_ID_SYMPHONY		0x1c1c
-#define PCI_DEVICE_ID_SYMPHONY_101	0x0001
 
 #define PCI_VENDOR_ID_TEKRAM		0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
@@ -2289,70 +1900,33 @@
 #define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
 
 #define PCI_VENDOR_ID_3DLABS		0x3d3d
-#define PCI_DEVICE_ID_3DLABS_300SX	0x0001
-#define PCI_DEVICE_ID_3DLABS_500TX	0x0002
-#define PCI_DEVICE_ID_3DLABS_DELTA	0x0003
-#define PCI_DEVICE_ID_3DLABS_PERMEDIA	0x0004
-#define PCI_DEVICE_ID_3DLABS_MX		0x0006
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2	0x0007
-#define PCI_DEVICE_ID_3DLABS_GAMMA	0x0008
 #define PCI_DEVICE_ID_3DLABS_PERMEDIA2V	0x0009
 
-#define PCI_VENDOR_ID_AVANCE		0x4005
-#define PCI_DEVICE_ID_AVANCE_ALG2064	0x2064
-#define PCI_DEVICE_ID_AVANCE_2302	0x2302
 
 #define PCI_VENDOR_ID_AKS		0x416c
 #define PCI_DEVICE_ID_AKS_ALADDINCARD	0x0100
-#define PCI_DEVICE_ID_AKS_CPC		0x0200
 
-#define PCI_VENDOR_ID_REDCREEK		0x4916
-#define PCI_DEVICE_ID_RC45		0x1960
 
-#define PCI_VENDOR_ID_NETVIN		0x4a14
-#define PCI_DEVICE_ID_NETVIN_NV5000SC	0x5000
 
 #define PCI_VENDOR_ID_S3		0x5333
-#define PCI_DEVICE_ID_S3_PLATO_PXS	0x0551
-#define PCI_DEVICE_ID_S3_ViRGE		0x5631
 #define PCI_DEVICE_ID_S3_TRIO		0x8811
-#define PCI_DEVICE_ID_S3_AURORA64VP	0x8812
-#define PCI_DEVICE_ID_S3_TRIO64UVP	0x8814
-#define PCI_DEVICE_ID_S3_ViRGE_VX	0x883d
 #define PCI_DEVICE_ID_S3_868		0x8880
-#define PCI_DEVICE_ID_S3_928		0x88b0
-#define PCI_DEVICE_ID_S3_864_1		0x88c0
-#define PCI_DEVICE_ID_S3_864_2		0x88c1
-#define PCI_DEVICE_ID_S3_964_1		0x88d0
-#define PCI_DEVICE_ID_S3_964_2		0x88d1
 #define PCI_DEVICE_ID_S3_968		0x88f0
-#define PCI_DEVICE_ID_S3_TRIO64V2	0x8901
-#define PCI_DEVICE_ID_S3_PLATO_PXG	0x8902
-#define PCI_DEVICE_ID_S3_ViRGE_DXGX	0x8a01
-#define PCI_DEVICE_ID_S3_ViRGE_GX2	0x8a10
 #define PCI_DEVICE_ID_S3_SAVAGE4	0x8a25
-#define PCI_DEVICE_ID_S3_ViRGE_MX	0x8c01
-#define PCI_DEVICE_ID_S3_ViRGE_MXP	0x8c02
-#define PCI_DEVICE_ID_S3_ViRGE_MXPMV	0x8c03
 #define PCI_DEVICE_ID_S3_PROSAVAGE8	0x8d04
 #define PCI_DEVICE_ID_S3_SONICVIBES	0xca00
 
 #define PCI_VENDOR_ID_DUNORD		0x5544
 #define PCI_DEVICE_ID_DUNORD_I3000	0x0001
 
+
 #define PCI_VENDOR_ID_DCI		0x6666
 #define PCI_DEVICE_ID_DCI_PCCOM4	0x0001
 #define PCI_DEVICE_ID_DCI_PCCOM8	0x0002
 
-#define PCI_VENDOR_ID_DUNORD		0x5544
-#define PCI_DEVICE_ID_DUNORD_I3000	0x0001
-
-#define PCI_VENDOR_ID_GENROCO		0x5555
-#define PCI_DEVICE_ID_GENROCO_HFP832	0x0003
-
 #define PCI_VENDOR_ID_INTEL		0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC	0x0008
-#define PCI_DEVICE_ID_INTEL_21145	0x0039
 #define PCI_DEVICE_ID_INTEL_PXHD_0	0x0320
 #define PCI_DEVICE_ID_INTEL_PXHD_1	0x0321
 #define PCI_DEVICE_ID_INTEL_PXH_0	0x0329
@@ -2361,30 +1935,17 @@
 #define PCI_DEVICE_ID_INTEL_82375	0x0482
 #define PCI_DEVICE_ID_INTEL_82424	0x0483
 #define PCI_DEVICE_ID_INTEL_82378	0x0484
-#define PCI_DEVICE_ID_INTEL_82430	0x0486
-#define PCI_DEVICE_ID_INTEL_82434	0x04a3
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM	0x0962
-#define PCI_DEVICE_ID_INTEL_82562ET	0x1031
-#define PCI_DEVICE_ID_INTEL_82801CAM	0x1038
 #define PCI_DEVICE_ID_INTEL_82815_MC	0x1130
-#define PCI_DEVICE_ID_INTEL_82815_AB	0x1131
 #define PCI_DEVICE_ID_INTEL_82815_CGC	0x1132
-#define PCI_DEVICE_ID_INTEL_82559ER	0x1209
 #define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
-#define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
-#define PCI_DEVICE_ID_INTEL_7116	0x1223
 #define PCI_DEVICE_ID_INTEL_7505_0	0x2550  
-#define PCI_DEVICE_ID_INTEL_7505_1	0x2552  
 #define PCI_DEVICE_ID_INTEL_7205_0	0x255d
-#define PCI_DEVICE_ID_INTEL_82596	0x1226
-#define PCI_DEVICE_ID_INTEL_82865	0x1227
-#define PCI_DEVICE_ID_INTEL_82557	0x1229
 #define PCI_DEVICE_ID_INTEL_82437	0x122d
 #define PCI_DEVICE_ID_INTEL_82371FB_0	0x122e
 #define PCI_DEVICE_ID_INTEL_82371FB_1	0x1230
 #define PCI_DEVICE_ID_INTEL_82371MX	0x1234
-#define PCI_DEVICE_ID_INTEL_82437MX	0x1235
 #define PCI_DEVICE_ID_INTEL_82441	0x1237
 #define PCI_DEVICE_ID_INTEL_82380FB	0x124b
 #define PCI_DEVICE_ID_INTEL_82439	0x1250
@@ -2393,83 +1954,53 @@
 #define PCI_DEVICE_ID_INTEL_82845_HB	0x1a30
 #define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
-#define PCI_DEVICE_ID_INTEL_82801AA_2	0x2412
 #define PCI_DEVICE_ID_INTEL_82801AA_3	0x2413
 #define PCI_DEVICE_ID_INTEL_82801AA_5	0x2415
 #define PCI_DEVICE_ID_INTEL_82801AA_6	0x2416
 #define PCI_DEVICE_ID_INTEL_82801AA_8	0x2418
 #define PCI_DEVICE_ID_INTEL_82801AB_0	0x2420
 #define PCI_DEVICE_ID_INTEL_82801AB_1	0x2421
-#define PCI_DEVICE_ID_INTEL_82801AB_2	0x2422
 #define PCI_DEVICE_ID_INTEL_82801AB_3	0x2423
 #define PCI_DEVICE_ID_INTEL_82801AB_5	0x2425
 #define PCI_DEVICE_ID_INTEL_82801AB_6	0x2426
 #define PCI_DEVICE_ID_INTEL_82801AB_8	0x2428
 #define PCI_DEVICE_ID_INTEL_82801BA_0	0x2440
-#define PCI_DEVICE_ID_INTEL_82801BA_1	0x2442
 #define PCI_DEVICE_ID_INTEL_82801BA_2	0x2443
-#define PCI_DEVICE_ID_INTEL_82801BA_3	0x2444
 #define PCI_DEVICE_ID_INTEL_82801BA_4	0x2445
-#define PCI_DEVICE_ID_INTEL_82801BA_5	0x2446
 #define PCI_DEVICE_ID_INTEL_82801BA_6	0x2448
-#define PCI_DEVICE_ID_INTEL_82801BA_7	0x2449
 #define PCI_DEVICE_ID_INTEL_82801BA_8	0x244a
 #define PCI_DEVICE_ID_INTEL_82801BA_9	0x244b
 #define PCI_DEVICE_ID_INTEL_82801BA_10	0x244c
 #define PCI_DEVICE_ID_INTEL_82801BA_11	0x244e
 #define PCI_DEVICE_ID_INTEL_82801E_0	0x2450
-#define PCI_DEVICE_ID_INTEL_82801E_2	0x2452
-#define PCI_DEVICE_ID_INTEL_82801E_3	0x2453
-#define PCI_DEVICE_ID_INTEL_82801E_9	0x2459
 #define PCI_DEVICE_ID_INTEL_82801E_11	0x245b
-#define PCI_DEVICE_ID_INTEL_82801E_13	0x245d
-#define PCI_DEVICE_ID_INTEL_82801E_14	0x245e
 #define PCI_DEVICE_ID_INTEL_82801CA_0	0x2480
-#define PCI_DEVICE_ID_INTEL_82801CA_2	0x2482
 #define PCI_DEVICE_ID_INTEL_82801CA_3	0x2483
-#define PCI_DEVICE_ID_INTEL_82801CA_4	0x2484
 #define PCI_DEVICE_ID_INTEL_82801CA_5	0x2485
 #define PCI_DEVICE_ID_INTEL_82801CA_6	0x2486
-#define PCI_DEVICE_ID_INTEL_82801CA_7	0x2487
 #define PCI_DEVICE_ID_INTEL_82801CA_10	0x248a
 #define PCI_DEVICE_ID_INTEL_82801CA_11	0x248b
 #define PCI_DEVICE_ID_INTEL_82801CA_12	0x248c
 #define PCI_DEVICE_ID_INTEL_82801DB_0	0x24c0
 #define PCI_DEVICE_ID_INTEL_82801DB_1	0x24c1
-#define PCI_DEVICE_ID_INTEL_82801DB_2	0x24c2
 #define PCI_DEVICE_ID_INTEL_82801DB_3	0x24c3
-#define PCI_DEVICE_ID_INTEL_82801DB_4	0x24c4
 #define PCI_DEVICE_ID_INTEL_82801DB_5	0x24c5
 #define PCI_DEVICE_ID_INTEL_82801DB_6	0x24c6
-#define PCI_DEVICE_ID_INTEL_82801DB_7	0x24c7
 #define PCI_DEVICE_ID_INTEL_82801DB_9	0x24c9
 #define PCI_DEVICE_ID_INTEL_82801DB_10	0x24ca
 #define PCI_DEVICE_ID_INTEL_82801DB_11	0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
-#define PCI_DEVICE_ID_INTEL_82801DB_13	0x24cd
 #define PCI_DEVICE_ID_INTEL_82801EB_0	0x24d0
 #define PCI_DEVICE_ID_INTEL_82801EB_1	0x24d1
-#define PCI_DEVICE_ID_INTEL_82801EB_2	0x24d2
 #define PCI_DEVICE_ID_INTEL_82801EB_3	0x24d3
-#define PCI_DEVICE_ID_INTEL_82801EB_4	0x24d4
 #define PCI_DEVICE_ID_INTEL_82801EB_5	0x24d5
 #define PCI_DEVICE_ID_INTEL_82801EB_6	0x24d6
-#define PCI_DEVICE_ID_INTEL_82801EB_7	0x24d7
 #define PCI_DEVICE_ID_INTEL_82801EB_11	0x24db
-#define PCI_DEVICE_ID_INTEL_82801EB_13	0x24dd
 #define PCI_DEVICE_ID_INTEL_ESB_1	0x25a1
 #define PCI_DEVICE_ID_INTEL_ESB_2	0x25a2
-#define PCI_DEVICE_ID_INTEL_ESB_3	0x25a3
-#define PCI_DEVICE_ID_INTEL_ESB_31	0x25b0
 #define PCI_DEVICE_ID_INTEL_ESB_4	0x25a4
 #define PCI_DEVICE_ID_INTEL_ESB_5	0x25a6
-#define PCI_DEVICE_ID_INTEL_ESB_6	0x25a7
-#define PCI_DEVICE_ID_INTEL_ESB_7	0x25a9
-#define PCI_DEVICE_ID_INTEL_ESB_8	0x25aa
 #define PCI_DEVICE_ID_INTEL_ESB_9	0x25ab
-#define PCI_DEVICE_ID_INTEL_ESB_11	0x25ac
-#define PCI_DEVICE_ID_INTEL_ESB_12	0x25ad
-#define PCI_DEVICE_ID_INTEL_ESB_13	0x25ae
 #define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
 #define PCI_DEVICE_ID_INTEL_82850_HB	0x2530
@@ -2479,7 +2010,6 @@
 #define PCI_DEVICE_ID_INTEL_82865_HB	0x2570
 #define PCI_DEVICE_ID_INTEL_82865_IG	0x2572
 #define PCI_DEVICE_ID_INTEL_82875_HB	0x2578
-#define PCI_DEVICE_ID_INTEL_82875_IG	0x257b
 #define PCI_DEVICE_ID_INTEL_82915G_HB	0x2580
 #define PCI_DEVICE_ID_INTEL_82915G_IG	0x2582
 #define PCI_DEVICE_ID_INTEL_82915GM_HB	0x2590
@@ -2489,80 +2019,23 @@
 #define PCI_DEVICE_ID_INTEL_ICH6_0	0x2640
 #define PCI_DEVICE_ID_INTEL_ICH6_1	0x2641
 #define PCI_DEVICE_ID_INTEL_ICH6_2	0x2642
-#define PCI_DEVICE_ID_INTEL_ICH6_3	0x2651
-#define PCI_DEVICE_ID_INTEL_ICH6_4	0x2652
-#define PCI_DEVICE_ID_INTEL_ICH6_5	0x2653
-#define PCI_DEVICE_ID_INTEL_ICH6_6	0x2658
-#define PCI_DEVICE_ID_INTEL_ICH6_7	0x2659
-#define PCI_DEVICE_ID_INTEL_ICH6_8	0x265a
-#define PCI_DEVICE_ID_INTEL_ICH6_9	0x265b
-#define PCI_DEVICE_ID_INTEL_ICH6_10	0x265c
-#define PCI_DEVICE_ID_INTEL_ICH6_11	0x2660
-#define PCI_DEVICE_ID_INTEL_ICH6_12	0x2662
-#define PCI_DEVICE_ID_INTEL_ICH6_13	0x2664
-#define PCI_DEVICE_ID_INTEL_ICH6_14	0x2666
-#define PCI_DEVICE_ID_INTEL_ICH6_15	0x2668
 #define PCI_DEVICE_ID_INTEL_ICH6_16	0x266a
 #define PCI_DEVICE_ID_INTEL_ICH6_17	0x266d
 #define PCI_DEVICE_ID_INTEL_ICH6_18	0x266e
 #define PCI_DEVICE_ID_INTEL_ICH6_19	0x266f
 #define PCI_DEVICE_ID_INTEL_ESB2_0	0x2670
-#define PCI_DEVICE_ID_INTEL_ESB2_1	0x2680
-#define PCI_DEVICE_ID_INTEL_ESB2_2	0x2681
-#define PCI_DEVICE_ID_INTEL_ESB2_3	0x2682
-#define PCI_DEVICE_ID_INTEL_ESB2_4	0x2683
-#define PCI_DEVICE_ID_INTEL_ESB2_5	0x2688
-#define PCI_DEVICE_ID_INTEL_ESB2_6	0x2689
-#define PCI_DEVICE_ID_INTEL_ESB2_7	0x268a
-#define PCI_DEVICE_ID_INTEL_ESB2_8	0x268b
-#define PCI_DEVICE_ID_INTEL_ESB2_9	0x268c
-#define PCI_DEVICE_ID_INTEL_ESB2_10	0x2690
-#define PCI_DEVICE_ID_INTEL_ESB2_11	0x2692
-#define PCI_DEVICE_ID_INTEL_ESB2_12	0x2694
-#define PCI_DEVICE_ID_INTEL_ESB2_13	0x2696
 #define PCI_DEVICE_ID_INTEL_ESB2_14	0x2698
-#define PCI_DEVICE_ID_INTEL_ESB2_15	0x2699
-#define PCI_DEVICE_ID_INTEL_ESB2_16	0x269a
 #define PCI_DEVICE_ID_INTEL_ESB2_17	0x269b
 #define PCI_DEVICE_ID_INTEL_ESB2_18	0x269e
 #define PCI_DEVICE_ID_INTEL_ICH7_0	0x27b8
 #define PCI_DEVICE_ID_INTEL_ICH7_1	0x27b9
-#define PCI_DEVICE_ID_INTEL_ICH7_2	0x27c0
-#define PCI_DEVICE_ID_INTEL_ICH7_3	0x27c1
 #define PCI_DEVICE_ID_INTEL_ICH7_30	0x27b0
 #define PCI_DEVICE_ID_INTEL_ICH7_31	0x27bd
-#define PCI_DEVICE_ID_INTEL_ICH7_5	0x27c4
-#define PCI_DEVICE_ID_INTEL_ICH7_6	0x27c5
-#define PCI_DEVICE_ID_INTEL_ICH7_7	0x27c8
-#define PCI_DEVICE_ID_INTEL_ICH7_8	0x27c9
-#define PCI_DEVICE_ID_INTEL_ICH7_9	0x27ca
-#define PCI_DEVICE_ID_INTEL_ICH7_10	0x27cb
-#define PCI_DEVICE_ID_INTEL_ICH7_11	0x27cc
-#define PCI_DEVICE_ID_INTEL_ICH7_12	0x27d0
-#define PCI_DEVICE_ID_INTEL_ICH7_13	0x27d2
-#define PCI_DEVICE_ID_INTEL_ICH7_14	0x27d4
-#define PCI_DEVICE_ID_INTEL_ICH7_15	0x27d6
-#define PCI_DEVICE_ID_INTEL_ICH7_16	0x27d8
 #define PCI_DEVICE_ID_INTEL_ICH7_17	0x27da
-#define PCI_DEVICE_ID_INTEL_ICH7_18	0x27dc
 #define PCI_DEVICE_ID_INTEL_ICH7_19	0x27dd
 #define PCI_DEVICE_ID_INTEL_ICH7_20	0x27de
 #define PCI_DEVICE_ID_INTEL_ICH7_21	0x27df
-#define PCI_DEVICE_ID_INTEL_ICH7_22	0x27e0
-#define PCI_DEVICE_ID_INTEL_ICH7_23	0x27e2
 #define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
-#define PCI_DEVICE_ID_INTEL_ESB2_19	0x3500
-#define PCI_DEVICE_ID_INTEL_ESB2_20	0x3501
-#define PCI_DEVICE_ID_INTEL_ESB2_21	0x3504
-#define PCI_DEVICE_ID_INTEL_ESB2_22	0x3505
-#define PCI_DEVICE_ID_INTEL_ESB2_23	0x350c
-#define PCI_DEVICE_ID_INTEL_ESB2_24	0x350d
-#define PCI_DEVICE_ID_INTEL_ESB2_25	0x3510
-#define PCI_DEVICE_ID_INTEL_ESB2_26	0x3511
-#define PCI_DEVICE_ID_INTEL_ESB2_27	0x3514
-#define PCI_DEVICE_ID_INTEL_ESB2_28	0x3515
-#define PCI_DEVICE_ID_INTEL_ESB2_29	0x3518
-#define PCI_DEVICE_ID_INTEL_ESB2_30	0x3519
 #define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
 #define PCI_DEVICE_ID_INTEL_82855GM_HB	0x3580
@@ -2576,7 +2049,6 @@
 #define PCI_DEVICE_ID_INTEL_MCH_PC	0x3599
 #define PCI_DEVICE_ID_INTEL_MCH_PC1	0x359a
 #define PCI_DEVICE_ID_INTEL_E7525_MCH	0x359e
-#define PCI_DEVICE_ID_INTEL_80310	0x530d
 #define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
 #define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
 #define PCI_DEVICE_ID_INTEL_82371SB_2	0x7020
@@ -2601,22 +2073,15 @@
 #define PCI_DEVICE_ID_INTEL_440MX_6	0x7196
 #define PCI_DEVICE_ID_INTEL_82443MX_0	0x7198
 #define PCI_DEVICE_ID_INTEL_82443MX_1	0x7199
-#define PCI_DEVICE_ID_INTEL_82443MX_2	0x719a
 #define PCI_DEVICE_ID_INTEL_82443MX_3	0x719b
 #define PCI_DEVICE_ID_INTEL_82443GX_0	0x71a0
-#define PCI_DEVICE_ID_INTEL_82443GX_1	0x71a1
 #define PCI_DEVICE_ID_INTEL_82443GX_2	0x71a2
-#define PCI_DEVICE_ID_INTEL_82372FB_0	0x7600
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
-#define PCI_DEVICE_ID_INTEL_82372FB_2	0x7602
-#define PCI_DEVICE_ID_INTEL_82372FB_3	0x7603
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
-#define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
 #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
 #define PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
-#define PCI_DEVICE_ID_INTEL_IXP2400	0x9001
 #define PCI_DEVICE_ID_INTEL_IXP2800	0x9004
 #define PCI_DEVICE_ID_INTEL_S21152BB	0xb152
 
@@ -2629,7 +2094,6 @@
 #define PCI_SUBDEVICE_ID_COMPUTONE_PG6	0x0003
 
 #define PCI_VENDOR_ID_KTI		0x8e2e
-#define PCI_DEVICE_ID_KTI_ET32P2	0x3000
 
 #define PCI_VENDOR_ID_ADAPTEC		0x9004
 #define PCI_DEVICE_ID_ADAPTEC_7810	0x1078
@@ -2637,7 +2101,6 @@
 #define PCI_DEVICE_ID_ADAPTEC_38602	0x3860
 #define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
 #define PCI_DEVICE_ID_ADAPTEC_7855	0x5578
-#define PCI_DEVICE_ID_ADAPTEC_5800	0x5800
 #define PCI_DEVICE_ID_ADAPTEC_3860	0x6038
 #define PCI_DEVICE_ID_ADAPTEC_1480A	0x6075
 #define PCI_DEVICE_ID_ADAPTEC_7860	0x6078
@@ -2657,7 +2120,6 @@
 #define PCI_DEVICE_ID_ADAPTEC_7886	0x8678
 #define PCI_DEVICE_ID_ADAPTEC_7887	0x8778
 #define PCI_DEVICE_ID_ADAPTEC_7888	0x8878
-#define PCI_DEVICE_ID_ADAPTEC_1030	0x8b78
 
 #define PCI_VENDOR_ID_ADAPTEC2		0x9005
 #define PCI_DEVICE_ID_ADAPTEC2_2940U2	0x0010
@@ -2677,8 +2139,6 @@
 #define PCI_DEVICE_ID_ADAPTEC2_7899P	0x00cf
 #define PCI_DEVICE_ID_ADAPTEC2_SCAMP	0x0503
 
-#define PCI_VENDOR_ID_ATRONICS		0x907f
-#define PCI_DEVICE_ID_ATRONICS_2015	0x2015
 
 #define PCI_VENDOR_ID_HOLTEK		0x9412
 #define PCI_DEVICE_ID_HOLTEK_6565	0x6565
@@ -2711,7 +2171,3 @@
 #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
 
-#define PCI_VENDOR_ID_ARK		0xedd8
-#define PCI_DEVICE_ID_ARK_STING		0xa091
-#define PCI_DEVICE_ID_ARK_STINGARK	0xa099
-#define PCI_DEVICE_ID_ARK_2000MT	0xa0a1
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 5cfb076..1514098 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -170,6 +170,7 @@
 
 struct pm_ops {
 	suspend_disk_method_t pm_disk_mode;
+	int (*valid)(suspend_state_t state);
 	int (*prepare)(suspend_state_t state);
 	int (*enter)(suspend_state_t state);
 	int (*finish)(suspend_state_t state);
@@ -219,10 +220,11 @@
 
 struct dev_pm_info {
 	pm_message_t		power_state;
+	unsigned		can_wakeup:1;
 #ifdef	CONFIG_PM
+	unsigned		should_wakeup:1;
 	pm_message_t		prev_state;
 	void			* saved_state;
-	atomic_t		pm_users;
 	struct device		* pm_parent;
 	struct list_head	entry;
 #endif
@@ -236,13 +238,48 @@
 
 #ifdef CONFIG_PM
 extern int device_suspend(pm_message_t state);
-#else
+
+#define device_set_wakeup_enable(dev,val) \
+	((dev)->power.should_wakeup = !!(val))
+#define device_may_wakeup(dev) \
+	(device_can_wakeup(dev) && (dev)->power.should_wakeup)
+
+extern int dpm_runtime_suspend(struct device *, pm_message_t);
+extern void dpm_runtime_resume(struct device *);
+
+#else /* !CONFIG_PM */
+
 static inline int device_suspend(pm_message_t state)
 {
 	return 0;
 }
+
+#define device_set_wakeup_enable(dev,val)	do{}while(0)
+#define device_may_wakeup(dev)			(0)
+
+static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
+{
+	return 0;
+}
+
+static inline void dpm_runtime_resume(struct device * dev)
+{
+
+}
+
 #endif
 
+/* changes to device_may_wakeup take effect on the next pm state change.
+ * by default, devices should wakeup if they can.
+ */
+#define device_can_wakeup(dev) \
+	((dev)->power.can_wakeup)
+#define device_init_wakeup(dev,val) \
+	do { \
+		device_can_wakeup(dev) = !!(val); \
+		device_set_wakeup_enable(dev,val); \
+	} while(0)
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_PM_H */
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 045d476..9f0f928 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -24,7 +24,7 @@
 
 struct radix_tree_root {
 	unsigned int		height;
-	unsigned int		gfp_mask;
+	gfp_t			gfp_mask;
 	struct radix_tree_node	*rnode;
 };
 
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 70191a5..cce2559 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -275,6 +275,7 @@
 extern void rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
+extern long rcu_batches_completed(void);
 
 /* Exported interfaces */
 extern void FASTCALL(call_rcu(struct rcu_head *head, 
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index af00b10..001ab82 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1972,7 +1972,7 @@
 
 /* fix_nodes.c */
 #ifdef CONFIG_REISERFS_CHECK
-void *reiserfs_kmalloc(size_t size, int flags, struct super_block *s);
+void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s);
 void reiserfs_kfree(const void *vp, size_t size, struct super_block *s);
 #else
 static inline void *reiserfs_kmalloc(size_t size, int flags,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index e80fb7ee..35b30e6 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -95,8 +95,8 @@
 /*
  * Called from mm/filemap_xip.c to unmap empty zero page
  */
-pte_t *page_check_address(struct page *, struct mm_struct *, unsigned long);
-
+pte_t *page_check_address(struct page *, struct mm_struct *,
+				unsigned long, spinlock_t **);
 
 /*
  * Used by swapoff to help locate where page is expected in vma.
diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h
index b52a2af..f30f805 100644
--- a/include/linux/rwsem-spinlock.h
+++ b/include/linux/rwsem-spinlock.h
@@ -61,5 +61,10 @@
 extern void FASTCALL(__up_write(struct rw_semaphore *sem));
 extern void FASTCALL(__downgrade_write(struct rw_semaphore *sem));
 
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->activity != 0);
+}
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_RWSEM_SPINLOCK_H */
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 7f717e9..66ff545 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -1,14 +1,23 @@
 #ifndef _LINUX_SCATTERLIST_H
 #define _LINUX_SCATTERLIST_H
 
-static inline void sg_init_one(struct scatterlist *sg,
-			       u8 *buf, unsigned int buflen)
-{
-	memset(sg, 0, sizeof(*sg));
+#include <asm/scatterlist.h>
+#include <linux/mm.h>
+#include <linux/string.h>
 
+static inline void sg_set_buf(struct scatterlist *sg, void *buf,
+			      unsigned int buflen)
+{
 	sg->page = virt_to_page(buf);
 	sg->offset = offset_in_page(buf);
 	sg->length = buflen;
 }
 
+static inline void sg_init_one(struct scatterlist *sg, void *buf,
+			       unsigned int buflen)
+{
+	memset(sg, 0, sizeof(*sg));
+	sg_set_buf(sg, buf, buflen);
+}
+
 #endif /* _LINUX_SCATTERLIST_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 27519df..03b68a7 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -249,6 +249,36 @@
 extern void arch_unmap_area(struct mm_struct *, unsigned long);
 extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
 
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+/*
+ * The mm counters are not protected by its page_table_lock,
+ * so must be incremented atomically.
+ */
+#ifdef ATOMIC64_INIT
+#define set_mm_counter(mm, member, value) atomic64_set(&(mm)->_##member, value)
+#define get_mm_counter(mm, member) ((unsigned long)atomic64_read(&(mm)->_##member))
+#define add_mm_counter(mm, member, value) atomic64_add(value, &(mm)->_##member)
+#define inc_mm_counter(mm, member) atomic64_inc(&(mm)->_##member)
+#define dec_mm_counter(mm, member) atomic64_dec(&(mm)->_##member)
+typedef atomic64_t mm_counter_t;
+#else /* !ATOMIC64_INIT */
+/*
+ * The counters wrap back to 0 at 2^32 * PAGE_SIZE,
+ * that is, at 16TB if using 4kB page size.
+ */
+#define set_mm_counter(mm, member, value) atomic_set(&(mm)->_##member, value)
+#define get_mm_counter(mm, member) ((unsigned long)atomic_read(&(mm)->_##member))
+#define add_mm_counter(mm, member, value) atomic_add(value, &(mm)->_##member)
+#define inc_mm_counter(mm, member) atomic_inc(&(mm)->_##member)
+#define dec_mm_counter(mm, member) atomic_dec(&(mm)->_##member)
+typedef atomic_t mm_counter_t;
+#endif /* !ATOMIC64_INIT */
+
+#else  /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
+/*
+ * The mm counters are protected by its page_table_lock,
+ * so can be incremented directly.
+ */
 #define set_mm_counter(mm, member, value) (mm)->_##member = (value)
 #define get_mm_counter(mm, member) ((mm)->_##member)
 #define add_mm_counter(mm, member, value) (mm)->_##member += (value)
@@ -256,6 +286,20 @@
 #define dec_mm_counter(mm, member) (mm)->_##member--
 typedef unsigned long mm_counter_t;
 
+#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
+
+#define get_mm_rss(mm)					\
+	(get_mm_counter(mm, file_rss) + get_mm_counter(mm, anon_rss))
+#define update_hiwater_rss(mm)	do {			\
+	unsigned long _rss = get_mm_rss(mm);		\
+	if ((mm)->hiwater_rss < _rss)			\
+		(mm)->hiwater_rss = _rss;		\
+} while (0)
+#define update_hiwater_vm(mm)	do {			\
+	if ((mm)->hiwater_vm < (mm)->total_vm)		\
+		(mm)->hiwater_vm = (mm)->total_vm;	\
+} while (0)
+
 struct mm_struct {
 	struct vm_area_struct * mmap;		/* list of VMAs */
 	struct rb_root mm_rb;
@@ -279,15 +323,20 @@
 						 * by mmlist_lock
 						 */
 
+	/* Special counters, in some configurations protected by the
+	 * page_table_lock, in other configurations by being atomic.
+	 */
+	mm_counter_t _file_rss;
+	mm_counter_t _anon_rss;
+
+	unsigned long hiwater_rss;	/* High-watermark of RSS usage */
+	unsigned long hiwater_vm;	/* High-water virtual memory usage */
+
+	unsigned long total_vm, locked_vm, shared_vm, exec_vm;
+	unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
-	unsigned long total_vm, locked_vm, shared_vm;
-	unsigned long exec_vm, stack_vm, reserved_vm, def_flags, nr_ptes;
-
-	/* Special counters protected by the page_table_lock */
-	mm_counter_t _rss;
-	mm_counter_t _anon_rss;
 
 	unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
 
@@ -308,11 +357,7 @@
 	/* aio bits */
 	rwlock_t		ioctx_list_lock;
 	struct kioctx		*ioctx_list;
-
 	struct kioctx		default_kioctx;
-
-	unsigned long hiwater_rss;	/* High-water RSS usage */
-	unsigned long hiwater_vm;	/* High-water virtual memory usage */
 };
 
 struct sighand_struct {
@@ -895,7 +940,7 @@
 #else
 static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
 {
-	if (!cpus_intersects(new_mask, cpu_online_map))
+	if (!cpu_isset(0, new_mask))
 		return -EINVAL;
 	return 0;
 }
@@ -1039,6 +1084,11 @@
 #define SEND_SIG_PRIV	((struct siginfo *) 1)
 #define SEND_SIG_FORCED	((struct siginfo *) 2)
 
+static inline int is_si_special(const struct siginfo *info)
+{
+	return info <= SEND_SIG_FORCED;
+}
+
 /* True if we are on the alternate signal stack.  */
 
 static inline int on_sig_stack(unsigned long sp)
@@ -1166,7 +1216,7 @@
 /*
  * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring
  * subscriptions and synchronises with wait4().  Also used in procfs.  Also
- * pins the final release of task.io_context.
+ * pins the final release of task.io_context.  Also protects ->cpuset.
  *
  * Nests both inside and outside of read_lock(&tasklist_lock).
  * It must not be nested with write_lock_irq(&tasklist_lock),
diff --git a/include/linux/sdladrv.h b/include/linux/sdladrv.h
index 78f6340..c85e103 100644
--- a/include/linux/sdladrv.h
+++ b/include/linux/sdladrv.h
@@ -52,12 +52,8 @@
 
 extern int sdla_setup	(sdlahw_t* hw, void* sfm, unsigned len);
 extern int sdla_down	(sdlahw_t* hw);
-extern int sdla_inten	(sdlahw_t* hw);
-extern int sdla_intde	(sdlahw_t* hw);
-extern int sdla_intack	(sdlahw_t* hw);
 extern void S514_intack  (sdlahw_t* hw, u32 int_status);
 extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
-extern int sdla_intr	(sdlahw_t* hw);
 extern int sdla_mapmem	(sdlahw_t* hw, unsigned long addr);
 extern int sdla_peek	(sdlahw_t* hw, unsigned long addr, void* buf,
 			 unsigned len);
diff --git a/include/linux/security.h b/include/linux/security.h
index 627382e..f7e0ae0 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -30,6 +30,7 @@
 #include <linux/shm.h>
 #include <linux/msg.h>
 #include <linux/sched.h>
+#include <linux/key.h>
 
 struct ctl_table;
 
@@ -385,6 +386,9 @@
  *	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.
  * @inode_setsecurity:
  *	Set the security label associated with @name for @inode from the
@@ -785,6 +789,27 @@
  * @sk_free_security:
  *	Deallocate security structure.
  *
+ * Security hooks affecting all Key Management operations
+ *
+ * @key_alloc:
+ *	Permit allocation of a key and assign security data. Note that key does
+ *	not have a serial number assigned at this point.
+ *	@key points to the key.
+ *	Return 0 if permission is granted, -ve error otherwise.
+ * @key_free:
+ *	Notification of destruction; free security data.
+ *	@key points to the key.
+ *	No return value.
+ * @key_permission:
+ *	See whether a specific operational right is granted to a process on a
+ *      key.
+ *	@key_ref refers to the key (key pointer + possession attribute bit).
+ *	@context points to the process to provide the context against which to
+ *       evaluate the security data on the key.
+ *	@perm describes the combination of permissions required of this key.
+ *	Return 1 if permission granted, 0 if permission denied and -ve it the
+ *      normal permissions model should be effected.
+ *
  * Security hooks affecting all System V IPC operations.
  *
  * @ipc_permission:
@@ -1091,7 +1116,7 @@
 	int (*inode_getxattr) (struct dentry *dentry, char *name);
 	int (*inode_listxattr) (struct dentry *dentry);
 	int (*inode_removexattr) (struct dentry *dentry, char *name);
-  	int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size);
+  	int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size, int err);
   	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);
 
@@ -1210,9 +1235,20 @@
 	int (*socket_shutdown) (struct socket * sock, int how);
 	int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
 	int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
-	int (*sk_alloc_security) (struct sock *sk, int family, int priority);
+	int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
 	void (*sk_free_security) (struct sock *sk);
 #endif	/* CONFIG_SECURITY_NETWORK */
+
+	/* key management security hooks */
+#ifdef CONFIG_KEYS
+	int (*key_alloc)(struct key *key);
+	void (*key_free)(struct key *key);
+	int (*key_permission)(key_ref_t key_ref,
+			      struct task_struct *context,
+			      key_perm_t perm);
+
+#endif	/* CONFIG_KEYS */
+
 };
 
 /* global variables */
@@ -1580,11 +1616,11 @@
 	return security_ops->inode_removexattr (dentry, name);
 }
 
-static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
+static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
 {
 	if (unlikely (IS_PRIVATE (inode)))
 		return 0;
-	return security_ops->inode_getsecurity(inode, name, buffer, size);
+	return security_ops->inode_getsecurity(inode, name, buffer, size, err);
 }
 
 static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
@@ -2222,7 +2258,7 @@
 	return cap_inode_removexattr(dentry, name);
 }
 
-static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
+static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
 {
 	return -EOPNOTSUPP;
 }
@@ -2761,5 +2797,45 @@
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_KEYS
+#ifdef CONFIG_SECURITY
+static inline int security_key_alloc(struct key *key)
+{
+	return security_ops->key_alloc(key);
+}
+
+static inline void security_key_free(struct key *key)
+{
+	security_ops->key_free(key);
+}
+
+static inline int security_key_permission(key_ref_t key_ref,
+					  struct task_struct *context,
+					  key_perm_t perm)
+{
+	return security_ops->key_permission(key_ref, context, perm);
+}
+
+#else
+
+static inline int security_key_alloc(struct key *key)
+{
+	return 0;
+}
+
+static inline void security_key_free(struct key *key)
+{
+}
+
+static inline int security_key_permission(key_ref_t key_ref,
+					  struct task_struct *context,
+					  key_perm_t perm)
+{
+	return 0;
+}
+
+#endif
+#endif /* CONFIG_KEYS */
+
 #endif /* ! __LINUX_SECURITY_H */
 
diff --git a/include/linux/serial.h b/include/linux/serial.h
index 12cd9cf..33fc8cb 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -11,6 +11,7 @@
 #define _LINUX_SERIAL_H
 
 #ifdef __KERNEL__
+#include <linux/types.h>
 #include <asm/page.h>
 
 /*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 27db8da..2b0401b 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -39,7 +39,8 @@
 #define PORT_RSA	13
 #define PORT_NS16550A	14
 #define PORT_XSCALE	15
-#define PORT_MAX_8250	15	/* max port ID */
+#define PORT_IP3106	16
+#define PORT_MAX_8250	16	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
diff --git a/include/linux/serial_ip3106.h b/include/linux/serial_ip3106.h
new file mode 100644
index 0000000..f500ac6
--- /dev/null
+++ b/include/linux/serial_ip3106.h
@@ -0,0 +1,81 @@
+/*
+ * Embedded Alley Solutions, source@embeddedalley.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_SERIAL_IP3106_H
+#define _LINUX_SERIAL_IP3106_H
+
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#define IP3106_NR_PORTS		2
+
+struct ip3106_port {
+	struct uart_port	port;
+	struct timer_list	timer;
+	unsigned int		old_status;
+};
+
+/* register offsets */
+#define IP3106_LCR		0
+#define IP3106_MCR		0x004
+#define IP3106_BAUD		0x008
+#define IP3106_CFG		0x00c
+#define IP3106_FIFO		0x028
+#define IP3106_ISTAT		0xfe0
+#define IP3106_IEN		0xfe4
+#define IP3106_ICLR		0xfe8
+#define IP3106_ISET		0xfec
+#define IP3106_PD		0xff4
+#define IP3106_MID		0xffc
+
+#define IP3106_UART_LCR_TXBREAK		(1<<30)
+#define IP3106_UART_LCR_PAREVN		0x10000000
+#define IP3106_UART_LCR_PAREN		0x08000000
+#define IP3106_UART_LCR_2STOPB		0x04000000
+#define IP3106_UART_LCR_8BIT		0x01000000
+#define IP3106_UART_LCR_TX_RST		0x00040000
+#define IP3106_UART_LCR_RX_RST		0x00020000
+#define IP3106_UART_LCR_RX_NEXT		0x00010000
+
+#define IP3106_UART_MCR_SCR		0xFF000000
+#define IP3106_UART_MCR_DCD		0x00800000
+#define IP3106_UART_MCR_CTS		0x00100000
+#define IP3106_UART_MCR_LOOP		0x00000010
+#define IP3106_UART_MCR_RTS		0x00000002
+#define IP3106_UART_MCR_DTR		0x00000001
+
+#define IP3106_UART_INT_TX		0x00000080
+#define IP3106_UART_INT_EMPTY		0x00000040
+#define IP3106_UART_INT_RCVTO		0x00000020
+#define IP3106_UART_INT_RX		0x00000010
+#define IP3106_UART_INT_RXOVRN		0x00000008
+#define IP3106_UART_INT_FRERR		0x00000004
+#define IP3106_UART_INT_BREAK		0x00000002
+#define IP3106_UART_INT_PARITY		0x00000001
+#define IP3106_UART_INT_ALLRX		0x0000003F
+#define IP3106_UART_INT_ALLTX		0x000000C0
+
+#define IP3106_UART_FIFO_TXFIFO		0x001F0000
+#define IP3106_UART_FIFO_TXFIFO_STA	(0x1f<<16)
+#define IP3106_UART_FIFO_RXBRK		0x00008000
+#define IP3106_UART_FIFO_RXFE		0x00004000
+#define IP3106_UART_FIFO_RXPAR		0x00002000
+#define IP3106_UART_FIFO_RXFIFO		0x00001F00
+#define IP3106_UART_FIFO_RBRTHR		0x000000FF
+
+#endif
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 7be18b5..5dd5f02 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -25,7 +25,6 @@
 
 struct sigqueue {
 	struct list_head list;
-	spinlock_t *lock;
 	int flags;
 	siginfo_t info;
 	struct user_struct *user;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8f5d9e7..4286d83 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -137,6 +137,8 @@
 	unsigned int	nr_frags;
 	unsigned short	tso_size;
 	unsigned short	tso_segs;
+	unsigned short  ufo_size;
+	unsigned int    ip6_frag_id;
 	struct sk_buff	*frag_list;
 	skb_frag_t	frags[MAX_SKB_FRAGS];
 };
@@ -171,7 +173,6 @@
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
  *	@prev: Previous buffer in list
- *	@list: List we are on
  *	@sk: Socket we are owned by
  *	@tstamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
@@ -190,6 +191,7 @@
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
  *	@pkt_type: Packet class
+ *	@fclone: skbuff clone status
  *	@ip_summed: Driver fed us an IP checksum
  *	@priority: Packet queueing priority
  *	@users: User count - see {datagram,tcp}.c
@@ -202,6 +204,7 @@
  *	@destructor: Destruct function
  *	@nfmark: Can be used for communication between hooks
  *	@nfct: Associated connection, if any
+ *	@ipvs_property: skbuff is owned by ipvs
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@tc_index: Traffic control index
@@ -340,6 +343,11 @@
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
 
+extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+			int getfrag(void *from, char *to, int offset,
+			int len,int odd, struct sk_buff *skb),
+			void *from, int length);
+
 struct skb_seq_state
 {
 	__u32		lower_offset;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 5fc04a1..09b9aa6 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -121,7 +121,7 @@
 extern void *kmem_cache_alloc_node(kmem_cache_t *, gfp_t flags, int node);
 extern void *kmalloc_node(size_t size, gfp_t flags, int node);
 #else
-static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
+static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int node)
 {
 	return kmem_cache_alloc(cachep, flags);
 }
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index cdc99a2..0e9682c 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -171,23 +171,42 @@
 #define write_lock_irq(lock)		_write_lock_irq(lock)
 #define write_lock_bh(lock)		_write_lock_bh(lock)
 
-#define spin_unlock(lock)		_spin_unlock(lock)
-#define write_unlock(lock)		_write_unlock(lock)
-#define read_unlock(lock)		_read_unlock(lock)
+/*
+ * We inline the unlock functions in the nondebug case:
+ */
+#if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP)
+# define spin_unlock(lock)		_spin_unlock(lock)
+# define read_unlock(lock)		_read_unlock(lock)
+# define write_unlock(lock)		_write_unlock(lock)
+#else
+# define spin_unlock(lock)		__raw_spin_unlock(&(lock)->raw_lock)
+# define read_unlock(lock)		__raw_read_unlock(&(lock)->raw_lock)
+# define write_unlock(lock)		__raw_write_unlock(&(lock)->raw_lock)
+#endif
+
+#if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP)
+# define spin_unlock_irq(lock)		_spin_unlock_irq(lock)
+# define read_unlock_irq(lock)		_read_unlock_irq(lock)
+# define write_unlock_irq(lock)		_write_unlock_irq(lock)
+#else
+# define spin_unlock_irq(lock) \
+    do { __raw_spin_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0)
+# define read_unlock_irq(lock) \
+    do { __raw_read_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0)
+# define write_unlock_irq(lock) \
+    do { __raw_write_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0)
+#endif
 
 #define spin_unlock_irqrestore(lock, flags) \
 					_spin_unlock_irqrestore(lock, flags)
-#define spin_unlock_irq(lock)		_spin_unlock_irq(lock)
 #define spin_unlock_bh(lock)		_spin_unlock_bh(lock)
 
 #define read_unlock_irqrestore(lock, flags) \
 					_read_unlock_irqrestore(lock, flags)
-#define read_unlock_irq(lock)		_read_unlock_irq(lock)
 #define read_unlock_bh(lock)		_read_unlock_bh(lock)
 
 #define write_unlock_irqrestore(lock, flags) \
 					_write_unlock_irqrestore(lock, flags)
-#define write_unlock_irq(lock)		_write_unlock_irq(lock)
 #define write_unlock_bh(lock)		_write_unlock_bh(lock)
 
 #define spin_trylock_bh(lock)		__cond_lock(_spin_trylock_bh(lock))
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 04ebc24..b68c11a 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -66,7 +66,12 @@
 
 struct rpc_auth {
 	unsigned int		au_cslack;	/* call cred size estimate */
-	unsigned int		au_rslack;	/* reply verf size guess */
+				/* guess at number of u32's auth adds before
+				 * reply data; normally the verifier size: */
+	unsigned int		au_rslack;
+				/* for gss, used to calculate au_rslack: */
+	unsigned int		au_verfsize;
+
 	unsigned int		au_flags;	/* various flags */
 	struct rpc_authops *	au_ops;		/* operations */
 	rpc_authflavor_t	au_flavor;	/* pseudoflavor (note may
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index eadb31e..1a42d90 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -32,6 +32,7 @@
 #define RPCDBG_AUTH		0x0010
 #define RPCDBG_PMAP		0x0020
 #define RPCDBG_SCHED		0x0040
+#define RPCDBG_TRANS		0x0080
 #define RPCDBG_SVCSOCK		0x0100
 #define RPCDBG_SVCDSP		0x0200
 #define RPCDBG_MISC		0x0400
@@ -94,6 +95,8 @@
 	CTL_NLMDEBUG,
 	CTL_SLOTTABLE_UDP,
 	CTL_SLOTTABLE_TCP,
+	CTL_MIN_RESVPORT,
+	CTL_MAX_RESVPORT,
 };
 
 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 689262f..9b8bcf1 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -40,14 +40,21 @@
 		struct gss_ctx		**ctx_id);
 u32 gss_get_mic(
 		struct gss_ctx		*ctx_id,
-		u32			qop,
 		struct xdr_buf		*message,
 		struct xdr_netobj	*mic_token);
 u32 gss_verify_mic(
 		struct gss_ctx		*ctx_id,
 		struct xdr_buf		*message,
-		struct xdr_netobj	*mic_token,
-		u32			*qstate);
+		struct xdr_netobj	*mic_token);
+u32 gss_wrap(
+		struct gss_ctx		*ctx_id,
+		int			offset,
+		struct xdr_buf		*outbuf,
+		struct page		**inpages);
+u32 gss_unwrap(
+		struct gss_ctx		*ctx_id,
+		int			offset,
+		struct xdr_buf		*inbuf);
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
 
@@ -56,7 +63,6 @@
 
 struct pf_desc {
 	u32	pseudoflavor;
-	u32	qop;
 	u32	service;
 	char	*name;
 	char	*auth_domain_name;
@@ -85,14 +91,21 @@
 			struct gss_ctx		*ctx_id);
 	u32 (*gss_get_mic)(
 			struct gss_ctx		*ctx_id,
-			u32			qop, 
 			struct xdr_buf		*message,
 			struct xdr_netobj	*mic_token);
 	u32 (*gss_verify_mic)(
 			struct gss_ctx		*ctx_id,
 			struct xdr_buf		*message,
-			struct xdr_netobj	*mic_token,
-			u32			*qstate);
+			struct xdr_netobj	*mic_token);
+	u32 (*gss_wrap)(
+			struct gss_ctx		*ctx_id,
+			int			offset,
+			struct xdr_buf		*outbuf,
+			struct page		**inpages);
+	u32 (*gss_unwrap)(
+			struct gss_ctx		*ctx_id,
+			int			offset,
+			struct xdr_buf		*buf);
 	void (*gss_delete_sec_context)(
 			void			*internal_ctx_id);
 };
diff --git a/include/linux/sunrpc/gss_err.h b/include/linux/sunrpc/gss_err.h
index 92608a2..a680786 100644
--- a/include/linux/sunrpc/gss_err.h
+++ b/include/linux/sunrpc/gss_err.h
@@ -66,16 +66,6 @@
 
 
 /*
- * Define the default Quality of Protection for per-message services.  Note
- * that an implementation that offers multiple levels of QOP may either reserve
- * a value (for example zero, as assumed here) to mean "default protection", or
- * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
- * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
- * implementation as a request for the default protection level.
- */
-#define GSS_C_QOP_DEFAULT 0
-
-/*
  * Expiration time of 2^32-1 seconds means infinite lifetime for a
  * credential or security context
  */
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index ffe31d2..2c3601d 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -116,18 +116,22 @@
 
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-		   struct xdr_netobj *cksum);
+		   int body_offset, struct xdr_netobj *cksum);
+
+u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+		struct xdr_netobj *);
+
+u32 gss_verify_mic_kerberos(struct gss_ctx *, struct xdr_buf *,
+		struct xdr_netobj *);
 
 u32
-krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
-	struct xdr_buf *input_message_buffer,
-	struct xdr_netobj *output_message_buffer, int toktype);
+gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
+		struct xdr_buf *outbuf, struct page **pages);
 
 u32
-krb5_read_token(struct krb5_ctx *context_handle,
-	  struct xdr_netobj *input_token_buffer,
-	  struct xdr_buf *message_buffer,
-	  int *qop_state, int toktype);
+gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset,
+		struct xdr_buf *buf);
+
 
 u32
 krb5_encrypt(struct crypto_tfm * key,
@@ -137,6 +141,13 @@
 krb5_decrypt(struct crypto_tfm * key,
 	     void *iv, void *in, void *out, int length); 
 
+int
+gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *outbuf, int offset,
+		struct page **pages);
+
+int
+gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *inbuf, int offset);
+
 s32
 krb5_make_seq_num(struct crypto_tfm * key,
 		int direction,
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
index b5c9968..0beb2cf 100644
--- a/include/linux/sunrpc/gss_spkm3.h
+++ b/include/linux/sunrpc/gss_spkm3.h
@@ -41,9 +41,9 @@
 #define SPKM_WRAP_TOK	5
 #define SPKM_DEL_TOK	6
 
-u32 spkm3_make_token(struct spkm3_ctx *ctx, int qop_req, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
+u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
 
-u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int *qop_state, int toktype);
+u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
 
 #define CKSUMTYPE_RSA_MD5            0x0007
 
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index 15f1153..f43f237 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -76,5 +76,30 @@
 
 #define RPC_MAXNETNAMELEN	256
 
+/*
+ * From RFC 1831:
+ *
+ * "A record is composed of one or more record fragments.  A record
+ *  fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
+ *  fragment data.  The bytes encode an unsigned binary number; as with
+ *  XDR integers, the byte order is from highest to lowest.  The number
+ *  encodes two values -- a boolean which indicates whether the fragment
+ *  is the last fragment of the record (bit value 1 implies the fragment
+ *  is the last fragment) and a 31-bit unsigned binary value which is the
+ *  length in bytes of the fragment's data.  The boolean value is the
+ *  highest-order bit of the header; the length is the 31 low-order bits.
+ *  (Note that this record specification is NOT in XDR standard form!)"
+ *
+ * The Linux RPC client always sends its requests in a single record
+ * fragment, limiting the maximum payload size for stream transports to
+ * 2GB.
+ */
+
+typedef u32	rpc_fraghdr;
+
+#define	RPC_LAST_STREAM_FRAGMENT	(1U << 31)
+#define	RPC_FRAGMENT_SIZE_MASK		(~RPC_LAST_STREAM_FRAGMENT)
+#define	RPC_MAX_FRAGMENT_SIZE		((1U << 31) - 1)
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_MSGPROT_H_ */
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 23448d0..5da9687 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -161,14 +161,10 @@
 
 typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
 
+extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
 extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
 		skb_reader_t *, skb_read_actor_t);
 
-struct socket;
-struct sockaddr;
-extern int xdr_sendpages(struct socket *, struct sockaddr *, int,
-		struct xdr_buf *, unsigned int, int);
-
 extern int xdr_encode_word(struct xdr_buf *, int, u32);
 extern int xdr_decode_word(struct xdr_buf *, int, u32 *);
 
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index e618c16..3b8b6e8 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -1,5 +1,5 @@
 /*
- *  linux/include/linux/sunrpc/clnt_xprt.h
+ *  linux/include/linux/sunrpc/xprt.h
  *
  *  Declarations for the RPC transport interface.
  *
@@ -15,20 +15,6 @@
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/xdr.h>
 
-/*
- * The transport code maintains an estimate on the maximum number of out-
- * standing RPC requests, using a smoothed version of the congestion
- * avoidance implemented in 44BSD. This is basically the Van Jacobson
- * congestion algorithm: If a retransmit occurs, the congestion window is
- * halved; otherwise, it is incremented by 1/cwnd when
- *
- *	-	a reply is received and
- *	-	a full number of requests are outstanding and
- *	-	the congestion window hasn't been updated recently.
- *
- * Upper procedures may check whether a request would block waiting for
- * a free RPC slot by using the RPC_CONGESTED() macro.
- */
 extern unsigned int xprt_udp_slot_table_entries;
 extern unsigned int xprt_tcp_slot_table_entries;
 
@@ -36,36 +22,25 @@
 #define RPC_DEF_SLOT_TABLE	(16U)
 #define RPC_MAX_SLOT_TABLE	(128U)
 
-#define RPC_CWNDSHIFT		(8U)
-#define RPC_CWNDSCALE		(1U << RPC_CWNDSHIFT)
-#define RPC_INITCWND		RPC_CWNDSCALE
-#define RPC_MAXCWND(xprt)	((xprt)->max_reqs << RPC_CWNDSHIFT)
-#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
-
-/* Default timeout values */
-#define RPC_MAX_UDP_TIMEOUT	(60*HZ)
-#define RPC_MAX_TCP_TIMEOUT	(600*HZ)
-
 /*
- * Wait duration for an RPC TCP connection to be established.  Solaris
- * NFS over TCP uses 60 seconds, for example, which is in line with how
- * long a server takes to reboot.
- */
-#define RPC_CONNECT_TIMEOUT	(60*HZ)
-
-/*
- * Delay an arbitrary number of seconds before attempting to reconnect
- * after an error.
- */
-#define RPC_REESTABLISH_TIMEOUT	(15*HZ)
-
-/* RPC call and reply header size as number of 32bit words (verifier
+ * RPC call and reply header size as number of 32bit words (verifier
  * size computed separately)
  */
 #define RPC_CALLHDRSIZE		6
 #define RPC_REPHDRSIZE		4
 
 /*
+ * Parameters for choosing a free port
+ */
+extern unsigned int xprt_min_resvport;
+extern unsigned int xprt_max_resvport;
+
+#define RPC_MIN_RESVPORT	(1U)
+#define RPC_MAX_RESVPORT	(65535U)
+#define RPC_DEF_MIN_RESVPORT	(650U)
+#define RPC_DEF_MAX_RESVPORT	(1023U)
+
+/*
  * This describes a timeout strategy
  */
 struct rpc_timeout {
@@ -76,6 +51,9 @@
 	unsigned char		to_exponential;
 };
 
+struct rpc_task;
+struct rpc_xprt;
+
 /*
  * This describes a complete RPC request
  */
@@ -95,7 +73,10 @@
 	int			rq_cong;	/* has incremented xprt->cong */
 	int			rq_received;	/* receive completed */
 	u32			rq_seqno;	/* gss seq no. used on req. */
-
+	int			rq_enc_pages_num;
+	struct page		**rq_enc_pages;	/* scratch pages for use by
+						   gss privacy code */
+	void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
 	struct list_head	rq_list;
 
 	struct xdr_buf		rq_private_buf;		/* The receive buffer
@@ -121,12 +102,21 @@
 #define rq_svec			rq_snd_buf.head
 #define rq_slen			rq_snd_buf.len
 
-#define XPRT_LAST_FRAG		(1 << 0)
-#define XPRT_COPY_RECM		(1 << 1)
-#define XPRT_COPY_XID		(1 << 2)
-#define XPRT_COPY_DATA		(1 << 3)
+struct rpc_xprt_ops {
+	void		(*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
+	int		(*reserve_xprt)(struct rpc_task *task);
+	void		(*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
+	void		(*connect)(struct rpc_task *task);
+	int		(*send_request)(struct rpc_task *task);
+	void		(*set_retrans_timeout)(struct rpc_task *task);
+	void		(*timer)(struct rpc_task *task);
+	void		(*release_request)(struct rpc_task *task);
+	void		(*close)(struct rpc_xprt *xprt);
+	void		(*destroy)(struct rpc_xprt *xprt);
+};
 
 struct rpc_xprt {
+	struct rpc_xprt_ops *	ops;		/* transport methods */
 	struct socket *		sock;		/* BSD socket layer */
 	struct sock *		inet;		/* INET layer */
 
@@ -137,11 +127,13 @@
 	unsigned long		cong;		/* current congestion */
 	unsigned long		cwnd;		/* congestion window */
 
-	unsigned int		rcvsize,	/* socket receive buffer size */
-				sndsize;	/* socket send buffer size */
+	size_t			rcvsize,	/* transport rcv buffer size */
+				sndsize;	/* transport send buffer size */
 
 	size_t			max_payload;	/* largest RPC payload size,
 						   in bytes */
+	unsigned int		tsh_size;	/* size of transport specific
+						   header */
 
 	struct rpc_wait_queue	sending;	/* requests waiting to send */
 	struct rpc_wait_queue	resend;		/* requests waiting to resend */
@@ -150,11 +142,9 @@
 	struct list_head	free;		/* free slots */
 	struct rpc_rqst *	slot;		/* slot table storage */
 	unsigned int		max_reqs;	/* total slots */
-	unsigned long		sockstate;	/* Socket state */
+	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
-				nocong	   : 1,	/* no congestion control */
-				resvport   : 1, /* use a reserved port */
-				stream     : 1;	/* TCP */
+				resvport   : 1; /* use a reserved port */
 
 	/*
 	 * XID
@@ -171,22 +161,27 @@
 	unsigned long		tcp_copied,	/* copied to request */
 				tcp_flags;
 	/*
-	 * Connection of sockets
+	 * Connection of transports
 	 */
-	struct work_struct	sock_connect;
+	unsigned long		connect_timeout,
+				bind_timeout,
+				reestablish_timeout;
+	struct work_struct	connect_worker;
 	unsigned short		port;
+
 	/*
-	 * Disconnection of idle sockets
+	 * Disconnection of idle transports
 	 */
 	struct work_struct	task_cleanup;
 	struct timer_list	timer;
-	unsigned long		last_used;
+	unsigned long		last_used,
+				idle_timeout;
 
 	/*
 	 * Send stuff
 	 */
-	spinlock_t		sock_lock;	/* lock socket info */
-	spinlock_t		xprt_lock;	/* lock xprt info */
+	spinlock_t		transport_lock;	/* lock transport info */
+	spinlock_t		reserve_lock;	/* lock slot table */
 	struct rpc_task *	snd_task;	/* Task blocked in send */
 
 	struct list_head	recv;
@@ -195,37 +190,111 @@
 	void			(*old_data_ready)(struct sock *, int);
 	void			(*old_state_change)(struct sock *);
 	void			(*old_write_space)(struct sock *);
-
-	wait_queue_head_t	cong_wait;
 };
 
+#define XPRT_LAST_FRAG		(1 << 0)
+#define XPRT_COPY_RECM		(1 << 1)
+#define XPRT_COPY_XID		(1 << 2)
+#define XPRT_COPY_DATA		(1 << 3)
+
 #ifdef __KERNEL__
 
-struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
-					struct rpc_timeout *toparms);
-int			xprt_destroy(struct rpc_xprt *);
-void			xprt_set_timeout(struct rpc_timeout *, unsigned int,
-					unsigned long);
+/*
+ * Transport operations used by ULPs
+ */
+struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr, struct rpc_timeout *to);
+void			xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr);
 
-void			xprt_reserve(struct rpc_task *);
-int			xprt_prepare_transmit(struct rpc_task *);
-void			xprt_transmit(struct rpc_task *);
-void			xprt_receive(struct rpc_task *);
+/*
+ * Generic internal transport functions
+ */
+void			xprt_connect(struct rpc_task *task);
+void			xprt_reserve(struct rpc_task *task);
+int			xprt_reserve_xprt(struct rpc_task *task);
+int			xprt_reserve_xprt_cong(struct rpc_task *task);
+int			xprt_prepare_transmit(struct rpc_task *task);
+void			xprt_transmit(struct rpc_task *task);
+void			xprt_abort_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
-void			xprt_release(struct rpc_task *);
-void			xprt_connect(struct rpc_task *);
-void			xprt_sock_setbufsize(struct rpc_xprt *);
+void			xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
+void			xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
+void			xprt_release(struct rpc_task *task);
+int			xprt_destroy(struct rpc_xprt *xprt);
 
-#define XPRT_LOCKED	0
-#define XPRT_CONNECT	1
-#define XPRT_CONNECTING	2
+static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p)
+{
+	return p + xprt->tsh_size;
+}
 
-#define xprt_connected(xp)		(test_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_set_connected(xp)		(set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_test_and_set_connected(xp)	(test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_test_and_clear_connected(xp) \
-					(test_and_clear_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_clear_connected(xp)	(clear_bit(XPRT_CONNECT, &(xp)->sockstate))
+/*
+ * Transport switch helper functions
+ */
+void			xprt_set_retrans_timeout_def(struct rpc_task *task);
+void			xprt_set_retrans_timeout_rtt(struct rpc_task *task);
+void			xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
+void			xprt_wait_for_buffer_space(struct rpc_task *task);
+void			xprt_write_space(struct rpc_xprt *xprt);
+void			xprt_update_rtt(struct rpc_task *task);
+void			xprt_adjust_cwnd(struct rpc_task *task, int result);
+struct rpc_rqst *	xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid);
+void			xprt_complete_rqst(struct rpc_task *task, int copied);
+void			xprt_release_rqst_cong(struct rpc_task *task);
+void			xprt_disconnect(struct rpc_xprt *xprt);
+
+/*
+ * Socket transport setup operations
+ */
+int			xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+int			xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
+
+/*
+ * Reserved bit positions in xprt->state
+ */
+#define XPRT_LOCKED		(0)
+#define XPRT_CONNECTED		(1)
+#define XPRT_CONNECTING		(2)
+
+static inline void xprt_set_connected(struct rpc_xprt *xprt)
+{
+	set_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline void xprt_clear_connected(struct rpc_xprt *xprt)
+{
+	clear_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_connected(struct rpc_xprt *xprt)
+{
+	return test_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_test_and_set_connected(struct rpc_xprt *xprt)
+{
+	return test_and_set_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline int xprt_test_and_clear_connected(struct rpc_xprt *xprt)
+{
+	return test_and_clear_bit(XPRT_CONNECTED, &xprt->state);
+}
+
+static inline void xprt_clear_connecting(struct rpc_xprt *xprt)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_CONNECTING, &xprt->state);
+	smp_mb__after_clear_bit();
+}
+
+static inline int xprt_connecting(struct rpc_xprt *xprt)
+{
+	return test_bit(XPRT_CONNECTING, &xprt->state);
+}
+
+static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt)
+{
+	return test_and_set_bit(XPRT_CONNECTING, &xprt->state);
+}
 
 #endif /* __KERNEL__*/
 
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index ad15a54..a61c04f 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -71,7 +71,12 @@
 struct saved_context;
 void __save_processor_state(struct saved_context *ctxt);
 void __restore_processor_state(struct saved_context *ctxt);
-extern unsigned long get_usable_page(unsigned gfp_mask);
-extern void free_eaten_memory(void);
+unsigned long get_safe_page(gfp_t gfp_mask);
+
+/*
+ * XXX: We try to keep some more pages free so that I/O operations succeed
+ * without paging. Might this be more?
+ */
+#define PAGES_FOR_IO	512
 
 #endif /* _LINUX_SWSUSP_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a7bf1a3..20c9756 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -171,8 +171,8 @@
 extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_pages(struct zone **, unsigned int);
-extern int zone_reclaim(struct zone *, unsigned int, unsigned int);
+extern int try_to_free_pages(struct zone **, gfp_t);
+extern int zone_reclaim(struct zone *, gfp_t, unsigned int);
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index a6f03e4..c7007b1 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -491,6 +491,7 @@
 asmlinkage long sys_syslog(int type, char __user *buf, int len);
 asmlinkage long sys_uselib(const char __user *library);
 asmlinkage long sys_ni_syscall(void);
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data);
 
 asmlinkage long sys_add_key(const char __user *_type,
 			    const char __user *_description,
diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h
index 515046d..7dac8f0 100644
--- a/include/linux/textsearch.h
+++ b/include/linux/textsearch.h
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 struct ts_config;
 
@@ -40,7 +41,7 @@
 struct ts_ops
 {
 	const char		*name;
-	struct ts_config *	(*init)(const void *, unsigned int, int);
+	struct ts_config *	(*init)(const void *, unsigned int, gfp_t);
 	unsigned int		(*find)(struct ts_config *,
 					struct ts_state *);
 	void			(*destroy)(struct ts_config *);
@@ -148,7 +149,7 @@
 extern int textsearch_register(struct ts_ops *);
 extern int textsearch_unregister(struct ts_ops *);
 extern struct ts_config *textsearch_prepare(const char *, const void *,
-					    unsigned int, int, int);
+					    unsigned int, gfp_t, int);
 extern void textsearch_destroy(struct ts_config *conf);
 extern unsigned int textsearch_find_continuous(struct ts_config *,
 					       struct ts_state *,
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 3340f3b..72f3a77 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -12,16 +12,12 @@
 	struct list_head entry;
 	unsigned long expires;
 
-	unsigned long magic;
-
 	void (*function)(unsigned long);
 	unsigned long data;
 
 	struct timer_base_s *base;
 };
 
-#define TIMER_MAGIC	0x4b87ad6e
-
 extern struct timer_base_s __init_timer_base;
 
 #define TIMER_INITIALIZER(_function, _expires, _data) {		\
@@ -29,7 +25,6 @@
 		.expires = (_expires),				\
 		.data = (_data),				\
 		.base = &__init_timer_base,			\
-		.magic = TIMER_MAGIC,				\
 	}
 
 #define DEFINE_TIMER(_name, _function, _expires, _data)		\
@@ -38,6 +33,15 @@
 
 void fastcall init_timer(struct timer_list * timer);
 
+static inline void setup_timer(struct timer_list * timer,
+				void (*function)(unsigned long),
+				unsigned long data)
+{
+	timer->function = function;
+	timer->data = data;
+	init_timer(timer);
+}
+
 /***
  * timer_pending - is a timer pending?
  * @timer: the timer in question
@@ -74,8 +78,9 @@
  * Timers with an ->expired field in the past will be executed in the next
  * timer tick.
  */
-static inline void add_timer(struct timer_list * timer)
+static inline void add_timer(struct timer_list *timer)
 {
+	BUG_ON(timer_pending(timer));
 	__mod_timer(timer, timer->expires);
 }
 
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 7e050a2..04a4a8c 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -282,6 +282,13 @@
 	return !(time_status & STA_UNSYNC);
 }
 
+/* Required to safely shift negative values */
+#define shift_right(x, s) ({	\
+	__typeof__(x) __x = (x);	\
+	__typeof__(s) __s = (s);	\
+	__x < 0 ? -(-__x >> __s) : __x >> __s;	\
+})
+
 
 #ifdef CONFIG_TIME_INTERPOLATION
 
diff --git a/include/linux/types.h b/include/linux/types.h
index 0aee34f..21b9ce8 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -151,7 +151,12 @@
  */
 
 #ifdef __CHECKER__
-#define __bitwise __attribute__((bitwise))
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
 #else
 #define __bitwise
 #endif
@@ -166,7 +171,7 @@
 #endif
 
 #ifdef __KERNEL__
-typedef unsigned __nocast gfp_t;
+typedef unsigned __bitwise__ gfp_t;
 #endif
 
 struct ustat {
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 4dbe580..748d043 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -57,6 +57,7 @@
 	struct usb_endpoint_descriptor	desc;
 	struct list_head		urb_list;
 	void				*hcpriv;
+	struct kobject			*kobj;	/* For sysfs info */
 
 	unsigned char *extra;   /* Extra descriptors */
 	int extralen;
@@ -136,7 +137,8 @@
 					 * active alternate setting */
 	unsigned num_altsetting;	/* number of alternate settings */
 
-	int minor;			/* minor number this interface is bound to */
+	int minor;			/* minor number this interface is
+					 * bound to */
 	enum usb_interface_condition condition;		/* state of binding */
 	struct device dev;		/* interface specific device info */
 	struct class_device *class_dev;
@@ -229,7 +231,7 @@
 struct usb_host_config {
 	struct usb_config_descriptor	desc;
 
-	char *string;
+	char *string;		/* iConfiguration string, if present */
 	/* the interfaces associated with this configuration,
 	 * stored in no particular order */
 	struct usb_interface *interface[USB_MAXINTERFACES];
@@ -248,7 +250,7 @@
 	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
 		type,(void**)ptr)
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 struct usb_operations;
 
@@ -268,7 +270,8 @@
 	unsigned is_b_host:1;		/* true during some HNP roleswitches */
 	unsigned b_hnp_enable:1;	/* OTG: did A-Host enable HNP? */
 
-	int devnum_next;		/* Next open device number in round-robin allocation */
+	int devnum_next;		/* Next open device number in
+					 * round-robin allocation */
 
 	struct usb_devmap devmap;	/* device address allocation map */
 	struct usb_operations *op;	/* Operations (specific to the HC) */
@@ -289,15 +292,16 @@
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
 
 	struct class_device *class_dev;	/* class device for this bus */
-	struct kref kref;		/* handles reference counting this bus */
-	void (*release)(struct usb_bus *bus);	/* function to destroy this bus's memory */
+	struct kref kref;		/* reference counting for this bus */
+	void (*release)(struct usb_bus *bus);
+
 #if defined(CONFIG_USB_MON)
 	struct mon_bus *mon_bus;	/* non-null when associated */
 	int monitored;			/* non-zero when monitored */
 #endif
 };
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /* This is arbitrary.
  * From USB 2.0 spec Table 11-13, offset 7, a hub can
@@ -326,7 +330,8 @@
 
 	struct semaphore serialize;
 
-	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
+	unsigned int toggle[2];		/* one bit for each endpoint
+					 * ([0] = IN, [1] = OUT) */
 
 	struct usb_device *parent;	/* our hub, unless we're the root */
 	struct usb_bus *bus;		/* Bus we're part of */
@@ -343,12 +348,14 @@
 
 	char **rawdescriptors;		/* Raw descriptors for each config */
 
-	int have_langid;		/* whether string_langid is valid yet */
+	int have_langid;		/* whether string_langid is valid */
 	int string_langid;		/* language ID for strings */
 
-	char *product;
-	char *manufacturer;
-	char *serial;			/* static strings from the device */
+	/* static strings from the device */
+	char *product;			/* iProduct string, if present */
+	char *manufacturer;		/* iManufacturer string, if present */
+	char *serial;			/* iSerialNumber string, if present */
+
 	struct list_head filelist;
 	struct class_device *class_dev;
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */
@@ -440,22 +447,31 @@
  * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
  * high speed, and a different one if they are full or low speed.
  */
-static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size)
+static inline int usb_make_path (struct usb_device *dev, char *buf,
+		size_t size)
 {
 	int actual;
-	actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath);
+	actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name,
+			dev->devpath);
 	return (actual >= (int)size) ? -1 : actual;
 }
 
 /*-------------------------------------------------------------------------*/
 
-#define USB_DEVICE_ID_MATCH_DEVICE		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
-#define USB_DEVICE_ID_MATCH_DEV_RANGE		(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
-#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION	(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
+#define USB_DEVICE_ID_MATCH_DEVICE \
+		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
+#define USB_DEVICE_ID_MATCH_DEV_RANGE \
+		(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
+#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
+		(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
 #define USB_DEVICE_ID_MATCH_DEV_INFO \
-	(USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+		(USB_DEVICE_ID_MATCH_DEV_CLASS | \
+		USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
+		USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
 #define USB_DEVICE_ID_MATCH_INT_INFO \
-	(USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+		(USB_DEVICE_ID_MATCH_INT_CLASS | \
+		USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
+		USB_DEVICE_ID_MATCH_INT_PROTOCOL)
 
 /**
  * USB_DEVICE - macro used to describe a specific usb device
@@ -466,9 +482,11 @@
  * specific device.
  */
 #define USB_DEVICE(vend,prod) \
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), .idProduct = (prod)
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
+			.idProduct = (prod)
 /**
- * USB_DEVICE_VER - macro used to describe a specific usb device with a version range
+ * USB_DEVICE_VER - macro used to describe a specific usb device with a
+ *		version range
  * @vend: the 16 bit USB Vendor ID
  * @prod: the 16 bit USB Product ID
  * @lo: the bcdDevice_lo value
@@ -478,7 +496,9 @@
  * specific device, with a version range.
  */
 #define USB_DEVICE_VER(vend,prod,lo,hi) \
-	.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
+	.idVendor = (vend), .idProduct = (prod), \
+	.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
 
 /**
  * USB_DEVICE_INFO - macro used to describe a class of usb devices
@@ -490,7 +510,8 @@
  * specific class of devices.
  */
 #define USB_DEVICE_INFO(cl,sc,pr) \
-	.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), .bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
+	.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
+	.bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
 
 /**
  * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces 
@@ -502,9 +523,10 @@
  * specific class of interfaces.
  */
 #define USB_INTERFACE_INFO(cl,sc,pr) \
-	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+	.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
+	.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /**
  * struct usb_driver - identifies USB driver to usbcore
@@ -557,7 +579,8 @@
 
 	void (*disconnect) (struct usb_interface *intf);
 
-	int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
+	int (*ioctl) (struct usb_interface *intf, unsigned int code,
+			void *buf);
 
 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
 	int (*resume) (struct usb_interface *intf);
@@ -572,10 +595,8 @@
 
 /**
  * struct usb_class_driver - identifies a USB driver that wants to use the USB major number
- * @name: devfs name for this driver.  Will also be used by the driver
- *	class code to create a usb class device.
+ * @name: the usb class device name for this driver.  Will show up in sysfs.
  * @fops: pointer to the struct file_operations of this driver.
- * @mode: the mode for the devfs file to be created for this driver.
  * @minor_base: the start of the minor range for this driver.
  *
  * This structure is used for the usb_register_dev() and
@@ -585,8 +606,7 @@
 struct usb_class_driver {
 	char *name;
 	struct file_operations *fops;
-	mode_t mode;
-	int minor_base;	
+	int minor_base;
 };
 
 /*
@@ -603,7 +623,7 @@
 
 extern int usb_disabled(void);
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /*
  * URB support, for asynchronous request completions
@@ -613,12 +633,14 @@
  * urb->transfer_flags:
  */
 #define URB_SHORT_NOT_OK	0x0001	/* report short reads as errors */
-#define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame ignored */
+#define URB_ISO_ASAP		0x0002	/* iso-only, urb->start_frame
+					 * ignored */
 #define URB_NO_TRANSFER_DMA_MAP	0x0004	/* urb->transfer_dma valid on submit */
 #define URB_NO_SETUP_DMA_MAP	0x0008	/* urb->setup_dma valid on submit */
 #define URB_NO_FSBR		0x0020	/* UHCI-specific */
-#define URB_ZERO_PACKET		0x0040	/* Finish bulk OUTs with short packet */
-#define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt needed */
+#define URB_ZERO_PACKET		0x0040	/* Finish bulk OUT with short packet */
+#define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt
+					 * needed */
 
 struct usb_iso_packet_descriptor {
 	unsigned int offset;
@@ -806,7 +828,8 @@
 	u8 reject;			/* submissions will fail */
 
 	/* public, documented fields in the urb that can be used by drivers */
-	struct list_head urb_list;	/* list head for use by the urb owner */
+	struct list_head urb_list;	/* list head for use by the urb's
+					 * current owner */
 	struct usb_device *dev; 	/* (in) pointer to associated device */
 	unsigned int pipe;		/* (in) pipe information */
 	int status;			/* (return) non-ISO status */
@@ -819,14 +842,16 @@
 	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
 	int start_frame;		/* (modify) start frame (ISO) */
 	int number_of_packets;		/* (in) number of ISO packets */
-	int interval;			/* (modify) transfer interval (INT/ISO) */
+	int interval;			/* (modify) transfer interval
+					 * (INT/ISO) */
 	int error_count;		/* (return) number of ISO errors */
 	void *context;			/* (in) context for completion */
 	usb_complete_t complete;	/* (in) completion routine */
-	struct usb_iso_packet_descriptor iso_frame_desc[0];	/* (in) ISO ONLY */
+	struct usb_iso_packet_descriptor iso_frame_desc[0];
+					/* (in) ISO ONLY */
 };
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /**
  * usb_fill_control_urb - initializes a control urb
@@ -933,17 +958,17 @@
 }
 
 extern void usb_init_urb(struct urb *urb);
-extern struct urb *usb_alloc_urb(int iso_packets, unsigned mem_flags);
+extern struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);
 extern void usb_free_urb(struct urb *urb);
 #define usb_put_urb usb_free_urb
 extern struct urb *usb_get_urb(struct urb *urb);
-extern int usb_submit_urb(struct urb *urb, unsigned mem_flags);
+extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
 #define HAVE_USB_BUFFERS
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
-	unsigned mem_flags, dma_addr_t *dma);
+	gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
 	void *addr, dma_addr_t dma);
 
@@ -974,11 +999,6 @@
 	void *data, int len, int *actual_length,
 	int timeout);
 
-/* selective suspend/resume */
-extern int usb_suspend_device(struct usb_device *dev, pm_message_t message);
-extern int usb_resume_device(struct usb_device *dev);
-
-
 /* wrappers around usb_control_msg() for the most common standard requests */
 extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
 	unsigned char descindex, void *buf, int size);
@@ -1050,13 +1070,13 @@
 	struct scatterlist	*sg,
 	int			nents,
 	size_t			length,
-	unsigned		mem_flags
+	gfp_t			mem_flags
 );
 void usb_sg_cancel (struct usb_sg_request *io);
 void usb_sg_wait (struct usb_sg_request *io);
 
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
 
 /*
  * For various legacy reasons, Linux has a small cookie that's paired with
@@ -1097,23 +1117,34 @@
 /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
 #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
 #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
-#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
+#define usb_settoggle(dev, ep, out, bit) \
+		((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
+		 ((bit) << (ep)))
 
 
-static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
+static inline unsigned int __create_pipe(struct usb_device *dev,
+		unsigned int endpoint)
 {
 	return (dev->devnum << 8) | (endpoint << 15);
 }
 
 /* Create various pipes... */
-#define usb_sndctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndctrlpipe(dev,endpoint)	\
+	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvctrlpipe(dev,endpoint)	\
+	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndisocpipe(dev,endpoint)	\
+	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvisocpipe(dev,endpoint)	\
+	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndbulkpipe(dev,endpoint)	\
+	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvbulkpipe(dev,endpoint)	\
+	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndintpipe(dev,endpoint)	\
+	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvintpipe(dev,endpoint)	\
+	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
 
 /*-------------------------------------------------------------------------*/
 
@@ -1137,17 +1168,29 @@
 	return le16_to_cpu(ep->desc.wMaxPacketSize);
 }
 
-/* -------------------------------------------------------------------------- */
+/* ----------------------------------------------------------------------- */
+
+/* Events from the usb core */
+#define USB_DEVICE_ADD		0x0001
+#define USB_DEVICE_REMOVE	0x0002
+#define USB_BUS_ADD		0x0003
+#define USB_BUS_REMOVE		0x0004
+extern void usb_register_notify(struct notifier_block *nb);
+extern void usb_unregister_notify(struct notifier_block *nb);
 
 #ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
+#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+	__FILE__ , ## arg)
 #else
 #define dbg(format, arg...) do {} while (0)
 #endif
 
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+	__FILE__ , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , \
+	__FILE__ , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , \
+	__FILE__ , ## arg)
 
 
 #endif  /* __KERNEL__ */
diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
index 71e6086..ff81117 100644
--- a/include/linux/usb_gadget.h
+++ b/include/linux/usb_gadget.h
@@ -107,18 +107,18 @@
 	int (*disable) (struct usb_ep *ep);
 
 	struct usb_request *(*alloc_request) (struct usb_ep *ep,
-		unsigned gfp_flags);
+		gfp_t gfp_flags);
 	void (*free_request) (struct usb_ep *ep, struct usb_request *req);
 
 	void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
-		dma_addr_t *dma, unsigned gfp_flags);
+		dma_addr_t *dma, gfp_t gfp_flags);
 	void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
 		unsigned bytes);
 	// NOTE:  on 2.6, drivers may also use dma_map() and
 	// dma_sync_single_*() to directly manage dma overhead. 
 
 	int (*queue) (struct usb_ep *ep, struct usb_request *req,
-		unsigned gfp_flags);
+		gfp_t gfp_flags);
 	int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
 
 	int (*set_halt) (struct usb_ep *ep, int value);
@@ -214,7 +214,7 @@
  * Returns the request, or null if one could not be allocated.
  */
 static inline struct usb_request *
-usb_ep_alloc_request (struct usb_ep *ep, unsigned gfp_flags)
+usb_ep_alloc_request (struct usb_ep *ep, gfp_t gfp_flags)
 {
 	return ep->ops->alloc_request (ep, gfp_flags);
 }
@@ -254,7 +254,7 @@
  */
 static inline void *
 usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
-	unsigned gfp_flags)
+	gfp_t gfp_flags)
 {
 	return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
 }
@@ -330,7 +330,7 @@
  * reported when the usb peripheral is disconnected.
  */
 static inline int
-usb_ep_queue (struct usb_ep *ep, struct usb_request *req, unsigned gfp_flags)
+usb_ep_queue (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)
 {
 	return ep->ops->queue (ep, req, gfp_flags);
 }
diff --git a/include/linux/usb_otg.h b/include/linux/usb_otg.h
index c668314..f827f6e 100644
--- a/include/linux/usb_otg.h
+++ b/include/linux/usb_otg.h
@@ -63,6 +63,10 @@
 	int	(*set_power)(struct otg_transceiver *otg,
 				unsigned mA);
 
+	/* for non-OTG B devices: set transceiver into suspend mode */
+	int	(*set_suspend)(struct otg_transceiver *otg,
+				int suspend);
+
 	/* for B devices only:  start session with A-Host */
 	int	(*start_srp)(struct otg_transceiver *otg);
 
@@ -108,6 +112,15 @@
 }
 
 static inline int
+otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+	if (otg->set_suspend != NULL)
+		return otg->set_suspend(otg, suspend);
+	else
+		return 0;
+}
+
+static inline int
 otg_start_srp(struct otg_transceiver *otg)
 {
 	return otg->start_srp(otg);
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 9facf73..8859f0b 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -140,6 +140,12 @@
 	compat_caddr_t usercontext; /* unused */
 	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
 };
+
+struct usbdevfs_ioctl32 {
+	s32 ifno;
+	s32 ioctl_code;
+	compat_caddr_t data;
+};
 #endif
 
 #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
@@ -160,6 +166,7 @@
 #define USBDEVFS_RELEASEINTERFACE  _IOR('U', 16, unsigned int)
 #define USBDEVFS_CONNECTINFO       _IOW('U', 17, struct usbdevfs_connectinfo)
 #define USBDEVFS_IOCTL             _IOWR('U', 18, struct usbdevfs_ioctl)
+#define USBDEVFS_IOCTL32           _IOWR('U', 18, struct usbdevfs_ioctl32)
 #define USBDEVFS_HUB_PORTINFO      _IOR('U', 19, struct usbdevfs_hub_portinfo)
 #define USBDEVFS_RESET             _IO('U', 20)
 #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 3701a06..1d5577b 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -32,10 +32,14 @@
  *	Highlevel APIs for driver use
  */
 extern void *vmalloc(unsigned long size);
+extern void *vmalloc_node(unsigned long size, int node);
 extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(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 *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask,
+				pgprot_t prot);
+extern void *__vmalloc_node(unsigned long size, gfp_t gfp_mask,
+				pgprot_t prot, int node);
 extern void vfree(void *addr);
 
 extern void *vmap(struct page **pages, unsigned int count,
@@ -48,6 +52,8 @@
 extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags);
 extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 					unsigned long start, unsigned long end);
+extern struct vm_struct *get_vm_area_node(unsigned long size,
+					unsigned long flags, int node);
 extern struct vm_struct *remove_vm_area(void *addr);
 extern struct vm_struct *__remove_vm_area(void *addr);
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
diff --git a/include/linux/wanpipe.h b/include/linux/wanpipe.h
index 167d956..dae9860 100644
--- a/include/linux/wanpipe.h
+++ b/include/linux/wanpipe.h
@@ -265,15 +265,6 @@
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 
-
-#define	is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
-#define	is_alpha(ch) ((((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'z')||\
-	 	  ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'Z'))?1:0)
-#define	is_hex_digit(ch) ((((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')||\
-	 	  ((ch)>=(unsigned)'a'&&(ch)<=(unsigned)'f')||\
-	 	  ((ch)>=(unsigned)'A'&&(ch)<=(unsigned)'F'))?1:0)
-
-
 /****** Data Structures *****************************************************/
 
 /* Adapter Data Space.
diff --git a/include/linux/x1205.h b/include/linux/x1205.h
new file mode 100644
index 0000000..64fd3af
--- /dev/null
+++ b/include/linux/x1205.h
@@ -0,0 +1,31 @@
+/*
+ *  x1205.h - defines for drivers/i2c/chips/x1205.c
+ *  Copyright 2004 Karen Spearel
+ *  Copyright 2005 Alessandro Zummo
+ *
+ *  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 __LINUX_X1205_H__
+#define __LINUX_X1205_H__
+
+/* commands */
+
+#define X1205_CMD_GETDATETIME	0
+#define X1205_CMD_SETTIME	1
+#define X1205_CMD_SETDATETIME	2
+#define X1205_CMD_GETALARM	3
+#define X1205_CMD_SETALARM	4
+#define X1205_CMD_GETDTRIM	5
+#define X1205_CMD_SETDTRIM	6
+#define X1205_CMD_GETATRIM	7
+#define X1205_CMD_SETATRIM	8
+
+extern int x1205_do_command(unsigned int cmd, void *arg);
+extern int x1205_direct_attach(int adapter_id,
+	struct i2c_client_address_data *address_data);
+
+#endif /* __LINUX_X1205_H__ */
diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h
index cb7c0aa..8138983 100644
--- a/include/media/ovcamchip.h
+++ b/include/media/ovcamchip.h
@@ -17,20 +17,6 @@
 #include <linux/videodev.h>
 #include <linux/i2c.h>
 
-/* Remove these once they are officially defined */
-#ifndef I2C_DRIVERID_OVCAMCHIP
-	#define I2C_DRIVERID_OVCAMCHIP	0xf00f
-#endif
-#ifndef I2C_HW_SMBUS_OV511
-	#define I2C_HW_SMBUS_OV511	0xfe
-#endif
-#ifndef I2C_HW_SMBUS_OV518
-	#define I2C_HW_SMBUS_OV518	0xff
-#endif
-#ifndef I2C_HW_SMBUS_OVFX2
-	#define I2C_HW_SMBUS_OVFX2	0xfd
-#endif
-
 /* --------------------------------- */
 /*           ENUMERATIONS            */
 /* --------------------------------- */
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 30bb4a8..2250a18 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -237,8 +237,7 @@
 static __inline__ void ax25_cb_put(ax25_cb *ax25)
 {
 	if (atomic_dec_and_test(&ax25->refcount)) {
-		if (ax25->digipeat)
-			kfree(ax25->digipeat);
+		kfree(ax25->digipeat);
 		kfree(ax25);
 	}
 }
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 2104586..e42d728 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -171,4 +171,10 @@
 
 int bt_err(__u16 code);
 
+extern int hci_sock_init(void);
+extern int hci_sock_cleanup(void);
+
+extern int bt_sysfs_init(void);
+extern void bt_sysfs_cleanup(void);
+
 #endif /* __BLUETOOTH_H */
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index fbe557f..e656be7 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -275,9 +275,6 @@
 	atomic_inc(&s->refcnt);
 }
 
-/* ---- RFCOMM chechsum ---- */
-extern u8 rfcomm_crc_table[];
-
 /* ---- RFCOMM sockets ---- */
 struct sockaddr_rc {
 	sa_family_t	rc_family;
diff --git a/include/net/dst.h b/include/net/dst.h
index 4a056a6..6c196a5 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -94,7 +94,6 @@
 	struct dst_entry *	(*negative_advice)(struct dst_entry *);
 	void			(*link_failure)(struct sk_buff *);
 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
-	int			(*get_mss)(struct dst_entry *dst, u32 mtu);
 	int			entry_size;
 
 	atomic_t		entries;
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index dc36b1b..5e38dca 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -11,19 +11,26 @@
  *
  * Adaption to a generic IEEE 802.11 stack by James Ketrenos
  * <jketreno@linux.intel.com>
- * Copyright (c) 2004, Intel Corporation
+ * Copyright (c) 2004-2005, Intel Corporation
  *
  * 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. See README and COPYING for
  * more details.
+ *
+ * API Version History
+ * 1.0.x -- Initial version
+ * 1.1.x -- Added radiotap, QoS, TIM, ieee80211_geo APIs,
+ *          various structure changes, and crypto API init method
  */
 #ifndef IEEE80211_H
 #define IEEE80211_H
-#include <linux/if_ether.h> /* ETH_ALEN */
-#include <linux/kernel.h>   /* ARRAY_SIZE */
+#include <linux/if_ether.h>	/* ETH_ALEN */
+#include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
 
+#define IEEE80211_VERSION "git-1.1.6"
+
 #define IEEE80211_DATA_LEN		2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
    6.2.1.1.2.
@@ -33,34 +40,13 @@
    represents the 2304 bytes of real data, plus a possible 8 bytes of
    WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
 
-
-#define IEEE80211_HLEN			30
-#define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct ieee80211_hdr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-} __attribute__ ((packed));
-
 #define IEEE80211_1ADDR_LEN 10
 #define IEEE80211_2ADDR_LEN 16
 #define IEEE80211_3ADDR_LEN 24
 #define IEEE80211_4ADDR_LEN 30
 #define IEEE80211_FCS_LEN    4
+#define IEEE80211_HLEN			(IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN		(IEEE80211_DATA_LEN + IEEE80211_HLEN)
 
 #define MIN_FRAG_THRESHOLD     256U
 #define	MAX_FRAG_THRESHOLD     2346U
@@ -113,11 +99,11 @@
 #define IEEE80211_STYPE_CFACK		0x0050
 #define IEEE80211_STYPE_CFPOLL		0x0060
 #define IEEE80211_STYPE_CFACKPOLL	0x0070
+#define IEEE80211_STYPE_QOS_DATA        0x0080
 
 #define IEEE80211_SCTL_FRAG		0x000F
 #define IEEE80211_SCTL_SEQ		0xFFF0
 
-
 /* debug macros */
 
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -128,8 +114,7 @@
          in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
 #else
 #define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
-#endif	/* CONFIG_IEEE80211_DEBUG */
-
+#endif				/* CONFIG_IEEE80211_DEBUG */
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
@@ -140,7 +125,6 @@
  * messages. It should never be used for passing essid to user space. */
 const char *escape_essid(const char *essid, u8 essid_len);
 
-
 /*
  * To use the debug system:
  *
@@ -177,6 +161,7 @@
 
 #define IEEE80211_DL_TX            (1<<8)
 #define IEEE80211_DL_RX            (1<<9)
+#define IEEE80211_DL_QOS           (1<<31)
 
 #define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
 #define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
@@ -190,9 +175,10 @@
 #define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
 #define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
 #define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+#define IEEE80211_DEBUG_QOS(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
-#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <linux/if_arp.h>	/* ARPHRD_ETHER */
 
 #ifndef WIRELESS_SPY
 #define WIRELESS_SPY		/* enable iwspy support */
@@ -200,10 +186,10 @@
 #include <net/iw_handler.h>	/* new driver API */
 
 #ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
+#define ETH_P_PAE 0x888E	/* Port Access Entity (IEEE 802.1X) */
+#endif				/* ETH_P_PAE */
 
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+#define ETH_P_PREAUTH 0x88C7	/* IEEE 802.11i pre-authentication */
 
 #ifndef ETH_P_80211_RAW
 #define ETH_P_80211_RAW (ETH_P_ECONET + 1)
@@ -215,10 +201,10 @@
 
 struct ieee80211_snap_hdr {
 
-        u8    dsap;   /* always 0xAA */
-        u8    ssap;   /* always 0xAA */
-        u8    ctrl;   /* always 0x03 */
-        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
+	u8 dsap;		/* always 0xAA */
+	u8 ssap;		/* always 0xAA */
+	u8 ctrl;		/* always 0x03 */
+	u8 oui[P80211_OUI_LEN];	/* organizational universal id */
 
 } __attribute__ ((packed));
 
@@ -246,8 +232,9 @@
 #define WLAN_CAPABILITY_PBCC (1<<6)
 #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
 #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_QOS (1<<9)
 #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
-#define WLAN_CAPABILITY_OSSS_OFDM (1<<13)
+#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
 
 /* Status codes */
 enum ieee80211_statuscode {
@@ -312,14 +299,12 @@
 	WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
 };
 
-
 #define IEEE80211_STATMASK_SIGNAL (1<<0)
 #define IEEE80211_STATMASK_RSSI (1<<1)
 #define IEEE80211_STATMASK_NOISE (1<<2)
 #define IEEE80211_STATMASK_RATE (1<<3)
 #define IEEE80211_STATMASK_WEMASK 0x7
 
-
 #define IEEE80211_CCK_MODULATION    (1<<0)
 #define IEEE80211_OFDM_MODULATION   (1<<1)
 
@@ -377,9 +362,6 @@
 #define IEEE80211_NUM_CCK_RATES	            4
 #define IEEE80211_OFDM_SHIFT_MASK_A         4
 
-
-
-
 /* NOTE: This data is for statistical purposes; not all hardware provides this
  *       information for frames received.  Not setting these will not cause
  *       any adverse affects. */
@@ -388,7 +370,7 @@
 	s8 rssi;
 	u8 signal;
 	u8 noise;
-	u16 rate; /* in 100 kbps */
+	u16 rate;		/* in 100 kbps */
 	u8 received_channel;
 	u8 control;
 	u8 mask;
@@ -439,38 +421,44 @@
 
 #include "ieee80211_crypt.h"
 
-#define SEC_KEY_1         (1<<0)
-#define SEC_KEY_2         (1<<1)
-#define SEC_KEY_3         (1<<2)
-#define SEC_KEY_4         (1<<3)
-#define SEC_ACTIVE_KEY    (1<<4)
-#define SEC_AUTH_MODE     (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL         (1<<7)
-#define SEC_ENABLED       (1<<8)
+#define SEC_KEY_1		(1<<0)
+#define SEC_KEY_2		(1<<1)
+#define SEC_KEY_3		(1<<2)
+#define SEC_KEY_4		(1<<3)
+#define SEC_ACTIVE_KEY		(1<<4)
+#define SEC_AUTH_MODE		(1<<5)
+#define SEC_UNICAST_GROUP	(1<<6)
+#define SEC_LEVEL		(1<<7)
+#define SEC_ENABLED		(1<<8)
+#define SEC_ENCRYPT		(1<<9)
 
-#define SEC_LEVEL_0      0 /* None */
-#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
-#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
-#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
+#define SEC_LEVEL_0		0	/* None */
+#define SEC_LEVEL_1		1	/* WEP 40 and 104 bit */
+#define SEC_LEVEL_2		2	/* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP	3	/* Level 1 + CKIP */
+#define SEC_LEVEL_3		4	/* Level 2 + CCMP */
 
-#define WEP_KEYS 4
-#define WEP_KEY_LEN 13
+#define SEC_ALG_NONE		0
+#define SEC_ALG_WEP		1
+#define SEC_ALG_TKIP		2
+#define SEC_ALG_CCMP		3
+
+#define WEP_KEYS		4
+#define WEP_KEY_LEN		13
+#define SCM_KEY_LEN		32
+#define SCM_TEMPORAL_KEY_LENGTH	16
 
 struct ieee80211_security {
 	u16 active_key:2,
-            enabled:1,
-	    auth_mode:2,
-            auth_algo:4,
-            unicast_uses_group:1;
+	    enabled:1,
+	    auth_mode:2, auth_algo:4, unicast_uses_group:1, encrypt:1;
+	u8 encode_alg[WEP_KEYS];
 	u8 key_sizes[WEP_KEYS];
-	u8 keys[WEP_KEYS][WEP_KEY_LEN];
+	u8 keys[WEP_KEYS][SCM_KEY_LEN];
 	u8 level;
 	u16 flags;
 } __attribute__ ((packed));
 
-
 /*
 
  802.11 data frame from AP
@@ -494,7 +482,7 @@
 	MFIE_TYPE_RATES = 1,
 	MFIE_TYPE_FH_SET = 2,
 	MFIE_TYPE_DS_SET = 3,
-	MFIE_TYPE_CF_SET =  4,
+	MFIE_TYPE_CF_SET = 4,
 	MFIE_TYPE_TIM = 5,
 	MFIE_TYPE_IBSS_SET = 6,
 	MFIE_TYPE_COUNTRY = 7,
@@ -516,11 +504,75 @@
 	MFIE_TYPE_RSN = 48,
 	MFIE_TYPE_RATES_EX = 50,
 	MFIE_TYPE_GENERIC = 221,
+	MFIE_TYPE_QOS_PARAMETER = 222,
 };
 
-struct ieee80211_info_element_hdr {
-	u8 id;
-	u8 len;
+/* Minimal header; can be used for passing 802.11 frames with sufficient
+ * information to determine what type of underlying data type is actually
+ * stored in the data. */
+struct ieee80211_hdr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_1addr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_2addr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_4addr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addrqos {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 payload[0];
+	__le16 qos_ctl;
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_4addrqos {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	u8 payload[0];
+	__le16 qos_ctl;
 } __attribute__ ((packed));
 
 struct ieee80211_info_element {
@@ -546,49 +598,77 @@
 	u16 status;
 */
 
-struct ieee80211_authentication {
+struct ieee80211_auth {
 	struct ieee80211_hdr_3addr header;
 	__le16 algorithm;
 	__le16 transaction;
 	__le16 status;
-	struct ieee80211_info_element info_element;
+	/* challenge */
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
+struct ieee80211_disassoc {
+	struct ieee80211_hdr_3addr header;
+	__le16 reason;
+} __attribute__ ((packed));
+
+/* Alias deauth for disassoc */
+#define ieee80211_deauth ieee80211_disassoc
+
+struct ieee80211_probe_request {
+	struct ieee80211_hdr_3addr header;
+	/* SSID, supported rates */
+	struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
 
 struct ieee80211_probe_response {
 	struct ieee80211_hdr_3addr header;
 	u32 time_stamp[2];
 	__le16 beacon_interval;
 	__le16 capability;
-	struct ieee80211_info_element info_element;
+	/* SSID, supported rates, FH params, DS params,
+	 * CF params, IBSS params, TIM (if beacon), RSN */
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-struct ieee80211_assoc_request_frame {
+/* Alias beacon for probe_response */
+#define ieee80211_beacon ieee80211_probe_response
+
+struct ieee80211_assoc_request {
+	struct ieee80211_hdr_3addr header;
+	__le16 capability;
+	__le16 listen_interval;
+	/* SSID, supported rates, RSN */
+	struct ieee80211_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct ieee80211_reassoc_request {
+	struct ieee80211_hdr_3addr header;
 	__le16 capability;
 	__le16 listen_interval;
 	u8 current_ap[ETH_ALEN];
-	struct ieee80211_info_element info_element;
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-struct ieee80211_assoc_response_frame {
+struct ieee80211_assoc_response {
 	struct ieee80211_hdr_3addr header;
 	__le16 capability;
 	__le16 status;
 	__le16 aid;
-	struct ieee80211_info_element info_element; /* supported rates */
+	/* supported rates */
+	struct ieee80211_info_element info_element[0];
 } __attribute__ ((packed));
 
-
 struct ieee80211_txb {
 	u8 nr_frags;
 	u8 encrypted;
-	u16 reserved;
-	u16 frag_size;
-	u16 payload_size;
+	u8 rts_included;
+	u8 reserved;
+	__le16 frag_size;
+	__le16 payload_size;
 	struct sk_buff *fragments[0];
 };
 
-
 /* SWEEP TABLE ENTRIES NUMBER */
 #define MAX_SWEEP_TAB_ENTRIES		  42
 #define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
@@ -604,9 +684,68 @@
 
 #define MAX_WPA_IE_LEN 64
 
-#define NETWORK_EMPTY_ESSID (1<<0)
-#define NETWORK_HAS_OFDM    (1<<1)
-#define NETWORK_HAS_CCK     (1<<2)
+#define NETWORK_EMPTY_ESSID    (1<<0)
+#define NETWORK_HAS_OFDM       (1<<1)
+#define NETWORK_HAS_CCK        (1<<2)
+
+/* QoS structure */
+#define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
+#define NETWORK_HAS_QOS_INFORMATION     (1<<4)
+#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
+
+#define QOS_QUEUE_NUM                   4
+#define QOS_OUI_LEN                     3
+#define QOS_OUI_TYPE                    2
+#define QOS_ELEMENT_ID                  221
+#define QOS_OUI_INFO_SUB_TYPE           0
+#define QOS_OUI_PARAM_SUB_TYPE          1
+#define QOS_VERSION_1                   1
+#define QOS_AIFSN_MIN_VALUE             2
+
+struct ieee80211_qos_information_element {
+	u8 elementID;
+	u8 length;
+	u8 qui[QOS_OUI_LEN];
+	u8 qui_type;
+	u8 qui_subtype;
+	u8 version;
+	u8 ac_info;
+} __attribute__ ((packed));
+
+struct ieee80211_qos_ac_parameter {
+	u8 aci_aifsn;
+	u8 ecw_min_max;
+	__le16 tx_op_limit;
+} __attribute__ ((packed));
+
+struct ieee80211_qos_parameter_info {
+	struct ieee80211_qos_information_element info_element;
+	u8 reserved;
+	struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct ieee80211_qos_parameters {
+	__le16 cw_min[QOS_QUEUE_NUM];
+	__le16 cw_max[QOS_QUEUE_NUM];
+	u8 aifs[QOS_QUEUE_NUM];
+	u8 flag[QOS_QUEUE_NUM];
+	__le16 tx_op_limit[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct ieee80211_qos_data {
+	struct ieee80211_qos_parameters parameters;
+	int active;
+	int supported;
+	u8 param_count;
+	u8 old_param_count;
+};
+
+struct ieee80211_tim_parameters {
+	u8 tim_count;
+	u8 tim_period;
+} __attribute__ ((packed));
+
+/*******************************************************/
 
 struct ieee80211_network {
 	/* These entries are used to identify a unique network */
@@ -616,6 +755,8 @@
 	u8 ssid[IW_ESSID_MAX_SIZE + 1];
 	u8 ssid_len;
 
+	struct ieee80211_qos_data qos_data;
+
 	/* These are network statistics */
 	struct ieee80211_rx_stats stats;
 	u16 capability;
@@ -631,10 +772,12 @@
 	u16 beacon_interval;
 	u16 listen_interval;
 	u16 atim_window;
+	u8 erp_value;
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	size_t wpa_ie_len;
 	u8 rsn_ie[MAX_WPA_IE_LEN];
 	size_t rsn_ie_len;
+	struct ieee80211_tim_parameters tim;
 	struct list_head list;
 };
 
@@ -651,17 +794,52 @@
 #define DEFAULT_MAX_SCAN_AGE (15 * HZ)
 #define DEFAULT_FTS 2346
 
-
 #define CFG_IEEE80211_RESERVE_FCS (1<<0)
 #define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+#define CFG_IEEE80211_RTS (1<<2)
+
+#define IEEE80211_24GHZ_MIN_CHANNEL 1
+#define IEEE80211_24GHZ_MAX_CHANNEL 14
+#define IEEE80211_24GHZ_CHANNELS    14
+
+#define IEEE80211_52GHZ_MIN_CHANNEL 36
+#define IEEE80211_52GHZ_MAX_CHANNEL 165
+#define IEEE80211_52GHZ_CHANNELS    32
+
+enum {
+	IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
+	IEEE80211_CH_B_ONLY = (1 << 2),
+	IEEE80211_CH_NO_IBSS = (1 << 3),
+	IEEE80211_CH_UNIFORM_SPREADING = (1 << 4),
+	IEEE80211_CH_RADAR_DETECT = (1 << 5),
+	IEEE80211_CH_INVALID = (1 << 6),
+};
+
+struct ieee80211_channel {
+	u32 freq;
+	u8 channel;
+	u8 flags;
+	u8 max_power;
+};
+
+struct ieee80211_geo {
+	u8 name[4];
+	u8 bg_channels;
+	u8 a_channels;
+	struct ieee80211_channel bg[IEEE80211_24GHZ_CHANNELS];
+	struct ieee80211_channel a[IEEE80211_52GHZ_CHANNELS];
+};
 
 struct ieee80211_device {
 	struct net_device *dev;
+	struct ieee80211_security sec;
 
 	/* Bookkeeping structures */
 	struct net_device_stats stats;
 	struct ieee80211_stats ieee_stats;
 
+	struct ieee80211_geo geo;
+
 	/* Probe / Beacon management */
 	struct list_head network_free_list;
 	struct list_head network_list;
@@ -669,62 +847,102 @@
 	int scans;
 	int scan_age;
 
-	int iw_mode; /* operating mode (IW_MODE_*) */
+	int iw_mode;		/* operating mode (IW_MODE_*) */
+	struct iw_spy_data spy_data;	/* iwspy support */
 
 	spinlock_t lock;
 
-	int tx_headroom; /* Set to size of any additional room needed at front
-			  * of allocated Tx SKBs */
+	int tx_headroom;	/* Set to size of any additional room needed at front
+				 * of allocated Tx SKBs */
 	u32 config;
 
 	/* WEP and other encryption related settings at the device level */
-	int open_wep; /* Set to 1 to allow unencrypted frames */
+	int open_wep;		/* Set to 1 to allow unencrypted frames */
 
-	int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+	int reset_on_keychange;	/* Set to 1 if the HW needs to be reset on
 				 * WEP key changes */
 
 	/* If the host performs {en,de}cryption, then set to 1 */
 	int host_encrypt;
+	int host_encrypt_msdu;
 	int host_decrypt;
-	int ieee802_1x; /* is IEEE 802.1X used */
+	/* host performs multicast decryption */
+	int host_mc_decrypt;
+
+	int host_open_frag;
+	int host_build_iv;
+	int ieee802_1x;		/* is IEEE 802.1X used */
 
 	/* WPA data */
 	int wpa_enabled;
 	int drop_unencrypted;
-	int tkip_countermeasures;
 	int privacy_invoked;
 	size_t wpa_ie_len;
 	u8 *wpa_ie;
 
 	struct list_head crypt_deinit_list;
 	struct ieee80211_crypt_data *crypt[WEP_KEYS];
-	int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+	int tx_keyidx;		/* default TX key index (crypt[tx_keyidx]) */
 	struct timer_list crypt_deinit_timer;
+	int crypt_quiesced;
 
-	int bcrx_sta_key; /* use individual keys to override default keys even
-			   * with RX of broad/multicast frames */
+	int bcrx_sta_key;	/* use individual keys to override default keys even
+				 * with RX of broad/multicast frames */
 
 	/* Fragmentation structures */
 	struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN];
 	unsigned int frag_next_idx;
-	u16 fts; /* Fragmentation Threshold */
+	u16 fts;		/* Fragmentation Threshold */
+	u16 rts;		/* RTS threshold */
 
 	/* Association info */
 	u8 bssid[ETH_ALEN];
 
 	enum ieee80211_state state;
 
-	int mode;       /* A, B, G */
-	int modulation; /* CCK, OFDM */
-	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
-	int abg_ture;   /* ABG flag              */
+	int mode;		/* A, B, G */
+	int modulation;		/* CCK, OFDM */
+	int freq_band;		/* 2.4Ghz, 5.2Ghz, Mixed */
+	int abg_true;		/* ABG flag              */
+
+	int perfect_rssi;
+	int worst_rssi;
 
 	/* Callback functions */
-	void (*set_security)(struct net_device *dev,
-			     struct ieee80211_security *sec);
-	int (*hard_start_xmit)(struct ieee80211_txb *txb,
-			       struct net_device *dev);
-	int (*reset_port)(struct net_device *dev);
+	void (*set_security) (struct net_device * dev,
+			      struct ieee80211_security * sec);
+	int (*hard_start_xmit) (struct ieee80211_txb * txb,
+				struct net_device * dev, int pri);
+	int (*reset_port) (struct net_device * dev);
+	int (*is_queue_full) (struct net_device * dev, int pri);
+
+	int (*handle_management) (struct net_device * dev,
+				  struct ieee80211_network * network, u16 type);
+
+	/* Typical STA methods */
+	int (*handle_auth) (struct net_device * dev,
+			    struct ieee80211_auth * auth);
+	int (*handle_deauth) (struct net_device * dev,
+			      struct ieee80211_auth * auth);
+	int (*handle_disassoc) (struct net_device * dev,
+				struct ieee80211_disassoc * assoc);
+	int (*handle_beacon) (struct net_device * dev,
+			      struct ieee80211_beacon * beacon,
+			      struct ieee80211_network * network);
+	int (*handle_probe_response) (struct net_device * dev,
+				      struct ieee80211_probe_response * resp,
+				      struct ieee80211_network * network);
+	int (*handle_probe_request) (struct net_device * dev,
+				     struct ieee80211_probe_request * req,
+				     struct ieee80211_rx_stats * stats);
+	int (*handle_assoc_response) (struct net_device * dev,
+				      struct ieee80211_assoc_response * resp,
+				      struct ieee80211_network * network);
+
+	/* Typical AP methods */
+	int (*handle_assoc_request) (struct net_device * dev);
+	int (*handle_reassoc_request) (struct net_device * dev,
+				       struct ieee80211_reassoc_request * req);
 
 	/* This must be the last item so that it points to the data
 	 * allocated beyond this structure by alloc_ieee80211 */
@@ -736,12 +954,12 @@
 #define IEEE_G            (1<<2)
 #define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
 
-extern inline void *ieee80211_priv(struct net_device *dev)
+static inline void *ieee80211_priv(struct net_device *dev)
 {
 	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
 }
 
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
 {
 	/* Single white space is for Linksys APs */
 	if (essid_len == 1 && essid[0] == ' ')
@@ -757,7 +975,8 @@
 	return 1;
 }
 
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
+					  int mode)
 {
 	/*
 	 * It is possible for both access points and our device to support
@@ -783,14 +1002,17 @@
 	return 0;
 }
 
-extern inline int ieee80211_get_hdrlen(u16 fc)
+static inline int ieee80211_get_hdrlen(u16 fc)
 {
 	int hdrlen = IEEE80211_3ADDR_LEN;
+	u16 stype = WLAN_FC_GET_STYPE(fc);
 
 	switch (WLAN_FC_GET_TYPE(fc)) {
 	case IEEE80211_FTYPE_DATA:
 		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
 			hdrlen = IEEE80211_4ADDR_LEN;
+		if (stype & IEEE80211_STYPE_QOS_DATA)
+			hdrlen += 2;
 		break;
 	case IEEE80211_FTYPE_CTL:
 		switch (WLAN_FC_GET_STYPE(fc)) {
@@ -808,7 +1030,48 @@
 	return hdrlen;
 }
 
+static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
+{
+	switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
+	case IEEE80211_1ADDR_LEN:
+		return ((struct ieee80211_hdr_1addr *)hdr)->payload;
+	case IEEE80211_2ADDR_LEN:
+		return ((struct ieee80211_hdr_2addr *)hdr)->payload;
+	case IEEE80211_3ADDR_LEN:
+		return ((struct ieee80211_hdr_3addr *)hdr)->payload;
+	case IEEE80211_4ADDR_LEN:
+		return ((struct ieee80211_hdr_4addr *)hdr)->payload;
+	}
 
+}
+
+static inline int ieee80211_is_ofdm_rate(u8 rate)
+{
+	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+	case IEEE80211_OFDM_RATE_6MB:
+	case IEEE80211_OFDM_RATE_9MB:
+	case IEEE80211_OFDM_RATE_12MB:
+	case IEEE80211_OFDM_RATE_18MB:
+	case IEEE80211_OFDM_RATE_24MB:
+	case IEEE80211_OFDM_RATE_36MB:
+	case IEEE80211_OFDM_RATE_48MB:
+	case IEEE80211_OFDM_RATE_54MB:
+		return 1;
+	}
+	return 0;
+}
+
+static inline int ieee80211_is_cck_rate(u8 rate)
+{
+	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
+	case IEEE80211_CCK_RATE_1MB:
+	case IEEE80211_CCK_RATE_2MB:
+	case IEEE80211_CCK_RATE_5MB:
+	case IEEE80211_CCK_RATE_11MB:
+		return 1;
+	}
+	return 0;
+}
 
 /* ieee80211.c */
 extern void free_ieee80211(struct net_device *dev);
@@ -817,18 +1080,30 @@
 extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
 
 /* ieee80211_tx.c */
-extern int ieee80211_xmit(struct sk_buff *skb,
-			  struct net_device *dev);
+extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
-
+extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
+			      struct ieee80211_hdr *frame, int len);
 
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-			     struct ieee80211_hdr *header,
+			     struct ieee80211_hdr_4addr *header,
 			     struct ieee80211_rx_stats *stats);
 
+/* ieee80211_geo.c */
+extern const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device
+						     *ieee);
+extern int ieee80211_set_geo(struct ieee80211_device *ieee,
+			     const struct ieee80211_geo *geo);
+
+extern int ieee80211_is_valid_channel(struct ieee80211_device *ieee,
+				      u8 channel);
+extern int ieee80211_channel_to_index(struct ieee80211_device *ieee,
+				      u8 channel);
+extern u8 ieee80211_freq_to_channel(struct ieee80211_device *ieee, u32 freq);
+
 /* ieee80211_wx.c */
 extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 				 struct iw_request_info *info,
@@ -839,17 +1114,21 @@
 extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
 				   struct iw_request_info *info,
 				   union iwreq_data *wrqu, char *key);
+extern int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu, char *extra);
+extern int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+				      struct iw_request_info *info,
+				      union iwreq_data *wrqu, char *extra);
 
-
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
+static inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
 {
 	ieee->scans++;
 }
 
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
+static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
 {
 	return ieee->scans;
 }
 
-
-#endif /* IEEE80211_H */
+#endif				/* IEEE80211_H */
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index b58a3bc..0a1c2d8 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -25,16 +25,22 @@
 
 #include <linux/skbuff.h>
 
+enum {
+	IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
+};
+
 struct ieee80211_crypto_ops {
 	const char *name;
 
 	/* init new crypto context (e.g., allocate private data space,
 	 * select IV, etc.); returns NULL on failure or pointer to allocated
 	 * private data on success */
-	void * (*init)(int keyidx);
+	void *(*init) (int keyidx);
 
 	/* deinitialize crypto context and free allocated private data */
-	void (*deinit)(void *priv);
+	void (*deinit) (void *priv);
+
+	int (*build_iv) (struct sk_buff * skb, int hdr_len, void *priv);
 
 	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
 	 * value from decrypt_mpdu is passed as the keyidx value for
@@ -42,34 +48,39 @@
 	 * encryption; if not, error will be returned; these functions are
 	 * called for all MPDUs (i.e., fragments).
 	 */
-	int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+	int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
+	int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv);
 
 	/* These functions are called for full MSDUs, i.e. full frames.
 	 * These can be NULL if full MSDU operations are not needed. */
-	int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
-			    void *priv);
+	int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv);
+	int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len,
+			     void *priv);
 
-	int (*set_key)(void *key, int len, u8 *seq, void *priv);
-	int (*get_key)(void *key, int len, u8 *seq, void *priv);
+	int (*set_key) (void *key, int len, u8 * seq, void *priv);
+	int (*get_key) (void *key, int len, u8 * seq, void *priv);
 
 	/* procfs handler for printing out key information and possible
 	 * statistics */
-	char * (*print_stats)(char *p, void *priv);
+	char *(*print_stats) (char *p, void *priv);
+
+	/* Crypto specific flag get/set for configuration settings */
+	unsigned long (*get_flags) (void *priv);
+	unsigned long (*set_flags) (unsigned long flags, void *priv);
 
 	/* maximum number of bytes added by encryption; encrypt buf is
 	 * allocated with extra_prefix_len bytes, copy of in_buf, and
 	 * extra_postfix_len; encrypt need not use all this space, but
 	 * the result must start at the beginning of the buffer and correct
 	 * length must be returned */
-	int extra_prefix_len, extra_postfix_len;
+	int extra_mpdu_prefix_len, extra_mpdu_postfix_len;
+	int extra_msdu_prefix_len, extra_msdu_postfix_len;
 
 	struct module *owner;
 };
 
 struct ieee80211_crypt_data {
-	struct list_head list; /* delayed deletion list */
+	struct list_head list;	/* delayed deletion list */
 	struct ieee80211_crypto_ops *ops;
 	void *priv;
 	atomic_t refcnt;
@@ -77,10 +88,11 @@
 
 int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
 int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
+struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
 void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
 void ieee80211_crypt_deinit_handler(unsigned long);
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
 				    struct ieee80211_crypt_data **crypt);
+void ieee80211_crypt_quiescing(struct ieee80211_device *ieee);
 
 #endif
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
new file mode 100644
index 0000000..429b738
--- /dev/null
+++ b/include/net/ieee80211_radiotap.h
@@ -0,0 +1,231 @@
+/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
+
+/*-
+ * Copyright (c) 2003, 2004 David Young.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of David Young may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
+ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * Modifications to fit into the linux IEEE 802.11 stack,
+ * Mike Kershaw (dragorn@kismetwireless.net)
+ */
+
+#ifndef IEEE80211RADIOTAP_H
+#define IEEE80211RADIOTAP_H
+
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+
+/* Radiotap header version (from official NetBSD feed) */
+#define IEEE80211RADIOTAP_VERSION	"1.5"
+/* Base version of the radiotap packet header data */
+#define PKTHDR_RADIOTAP_VERSION		0
+
+/* A generic radio capture format is desirable. There is one for
+ * Linux, but it is neither rigidly defined (there were not even
+ * units given for some fields) nor easily extensible.
+ *
+ * I suggest the following extensible radio capture format. It is
+ * based on a bitmap indicating which fields are present.
+ *
+ * I am trying to describe precisely what the application programmer
+ * should expect in the following, and for that reason I tell the
+ * units and origin of each measurement (where it applies), or else I
+ * use sufficiently weaselly language ("is a monotonically nondecreasing
+ * function of...") that I cannot set false expectations for lawyerly
+ * readers.
+ */
+
+/* XXX tcpdump/libpcap do not tolerate variable-length headers,
+ * yet, so we pad every radiotap header to 64 bytes. Ugh.
+ */
+#define IEEE80211_RADIOTAP_HDRLEN	64
+
+/* The radio capture header precedes the 802.11 header. */
+struct ieee80211_radiotap_header {
+	u8 it_version;		/* Version 0. Only increases
+				 * for drastic changes,
+				 * introduction of compatible
+				 * new fields does not count.
+				 */
+	u8 it_pad;
+	u16 it_len;		/* length of the whole
+				 * header in bytes, including
+				 * it_version, it_pad,
+				 * it_len, and data fields.
+				 */
+	u32 it_present;		/* A bitmap telling which
+				 * fields are present. Set bit 31
+				 * (0x80000000) to extend the
+				 * bitmap by another 32 bits.
+				 * Additional extensions are made
+				 * by setting bit 31.
+				 */
+};
+
+/* Name                                 Data type       Units
+ * ----                                 ---------       -----
+ *
+ * IEEE80211_RADIOTAP_TSFT              u64       microseconds
+ *
+ *      Value in microseconds of the MAC's 64-bit 802.11 Time
+ *      Synchronization Function timer when the first bit of the
+ *      MPDU arrived at the MAC. For received frames, only.
+ *
+ * IEEE80211_RADIOTAP_CHANNEL           2 x u16   MHz, bitmap
+ *
+ *      Tx/Rx frequency in MHz, followed by flags (see below).
+ *
+ * IEEE80211_RADIOTAP_FHSS              u16       see below
+ *
+ *      For frequency-hopping radios, the hop set (first byte)
+ *      and pattern (second byte).
+ *
+ * IEEE80211_RADIOTAP_RATE              u8        500kb/s
+ *
+ *      Tx/Rx data rate
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF signal power at the antenna, decibel difference from
+ *      one milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      RF noise power at the antenna, decibel difference from one
+ *      milliwatt.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8        decibel (dB)
+ *
+ *      RF signal power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference.
+ *
+ * IEEE80211_RADIOTAP_DB_ANTNOISE       u8        decibel (dB)
+ *
+ *      RF noise power at the antenna, decibel difference from an
+ *      arbitrary, fixed reference point.
+ *
+ * IEEE80211_RADIOTAP_LOCK_QUALITY      u16       unitless
+ *
+ *      Quality of Barker code lock. Unitless. Monotonically
+ *      nondecreasing with "better" lock strength. Called "Signal
+ *      Quality" in datasheets.  (Is there a standard way to measure
+ *      this?)
+ *
+ * IEEE80211_RADIOTAP_TX_ATTENUATION    u16       unitless
+ *
+ *      Transmit power expressed as unitless distance from max
+ *      power set at factory calibration.  0 is max power.
+ *      Monotonically nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u16       decibels (dB)
+ *
+ *      Transmit power expressed as decibel distance from max power
+ *      set at factory calibration.  0 is max power.  Monotonically
+ *      nondecreasing with lower power levels.
+ *
+ * IEEE80211_RADIOTAP_DBM_TX_POWER      int8_t          decibels from
+ *                                                      one milliwatt (dBm)
+ *
+ *      Transmit power expressed as dBm (decibels from a 1 milliwatt
+ *      reference). This is the absolute power level measured at
+ *      the antenna port.
+ *
+ * IEEE80211_RADIOTAP_FLAGS             u8        bitmap
+ *
+ *      Properties of transmitted and received frames. See flags
+ *      defined below.
+ *
+ * IEEE80211_RADIOTAP_ANTENNA           u8        antenna index
+ *
+ *      Unitless indication of the Rx/Tx antenna for this packet.
+ *      The first antenna is antenna 0.
+ *
+ * IEEE80211_RADIOTAP_FCS           	u32       data
+ *
+ *	FCS from frame in network byte order.
+ */
+enum ieee80211_radiotap_type {
+	IEEE80211_RADIOTAP_TSFT = 0,
+	IEEE80211_RADIOTAP_FLAGS = 1,
+	IEEE80211_RADIOTAP_RATE = 2,
+	IEEE80211_RADIOTAP_CHANNEL = 3,
+	IEEE80211_RADIOTAP_FHSS = 4,
+	IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+	IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+	IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+	IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+	IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+	IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+	IEEE80211_RADIOTAP_ANTENNA = 11,
+	IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+	IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+	IEEE80211_RADIOTAP_EXT = 31,
+};
+
+/* Channel flags. */
+#define	IEEE80211_CHAN_TURBO	0x0010	/* Turbo channel */
+#define	IEEE80211_CHAN_CCK	0x0020	/* CCK channel */
+#define	IEEE80211_CHAN_OFDM	0x0040	/* OFDM channel */
+#define	IEEE80211_CHAN_2GHZ	0x0080	/* 2 GHz spectrum channel. */
+#define	IEEE80211_CHAN_5GHZ	0x0100	/* 5 GHz spectrum channel */
+#define	IEEE80211_CHAN_PASSIVE	0x0200	/* Only passive scan allowed */
+#define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
+#define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
+						 * during CFP
+						 */
+#define	IEEE80211_RADIOTAP_F_SHORTPRE	0x02	/* sent/received
+						 * with short
+						 * preamble
+						 */
+#define	IEEE80211_RADIOTAP_F_WEP	0x04	/* sent/received
+						 * with WEP encryption
+						 */
+#define	IEEE80211_RADIOTAP_F_FRAG	0x08	/* sent/received
+						 * with fragmentation
+						 */
+#define	IEEE80211_RADIOTAP_F_FCS	0x10	/* frame includes FCS */
+#define	IEEE80211_RADIOTAP_F_DATAPAD	0x20	/* frame has padding between
+						 * 802.11 header and payload
+						 * (to 32-bit boundary)
+						 */
+
+/* Ugly macro to convert literal channel numbers into their mhz equivalents
+ * There are certianly some conditions that will break this (like feeding it '30')
+ * but they shouldn't arise since nothing talks on channel 30. */
+#define ieee80211chan2mhz(x) \
+	(((x) <= 14) ? \
+	(((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
+	((x) + 1000) * 5)
+
+#endif				/* IEEE80211_RADIOTAP_H */
diff --git a/include/net/netrom.h b/include/net/netrom.h
index a6bf6e0..a5ee53b 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -136,8 +136,7 @@
 static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
 {
 	if (atomic_dec_and_test(&nr_neigh->refcount)) {
-		if (nr_neigh->digipeat != NULL)
-			kfree(nr_neigh->digipeat);
+		kfree(nr_neigh->digipeat);
 		kfree(nr_neigh);
 	}
 }
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 1c5f19f..f1c3bc5 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -171,10 +171,10 @@
  */
 
 enum sctp_sinfo_flags {
-	MSG_UNORDERED = 1,  /* Send/receive message unordered. */
-	MSG_ADDR_OVER = 2,  /* Override the primary destination. */
-	MSG_ABORT=4,        /* Send an ABORT message to the peer. */
-	/* MSG_EOF is already defined per socket.h */
+	SCTP_UNORDERED = 1,  /* Send/receive message unordered. */
+	SCTP_ADDR_OVER = 2,  /* Override the primary destination. */
+	SCTP_ABORT=4,        /* Send an ABORT message to the peer. */
+	SCTP_EOF=MSG_FIN,    /* Initiate graceful shutdown process. */	
 };
 
 
diff --git a/include/net/sock.h b/include/net/sock.h
index ecb7552..e0498bd 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -207,7 +207,7 @@
 	struct sk_buff_head	sk_write_queue;
 	int			sk_wmem_queued;
 	int			sk_forward_alloc;
-	unsigned int		sk_allocation;
+	gfp_t			sk_allocation;
 	int			sk_sndbuf;
 	int			sk_route_caps;
 	unsigned long 		sk_flags;
diff --git a/include/net/syncppp.h b/include/net/syncppp.h
index 614cb6b..877efa4 100644
--- a/include/net/syncppp.h
+++ b/include/net/syncppp.h
@@ -86,7 +86,6 @@
 
 void sppp_attach (struct ppp_device *pd);
 void sppp_detach (struct net_device *dev);
-void sppp_input (struct net_device *dev, struct sk_buff *m);
 int sppp_do_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
 struct sk_buff *sppp_dequeue (struct net_device *dev);
 int sppp_isempty (struct net_device *dev);
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index c8592c7..e788bbc 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -17,6 +17,7 @@
 
 #include <linux/config.h>
 #include <linux/device.h>
+#include <linux/sched.h>	/* task_struct, completion */
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
index 5308683..0a9fcd5 100644
--- a/include/rdma/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
@@ -109,7 +109,6 @@
 
 struct ib_cm_req_event_param {
 	struct ib_cm_id		*listen_id;
-	struct ib_device	*device;
 	u8			port;
 
 	struct ib_sa_path_rec	*primary_path;
@@ -220,7 +219,6 @@
 
 struct ib_cm_sidr_req_event_param {
 	struct ib_cm_id		*listen_id;
-	struct ib_device	*device;
 	u8			port;
 	u16			pkey;
 };
@@ -284,6 +282,7 @@
 struct ib_cm_id {
 	ib_cm_handler		cm_handler;
 	void			*context;
+	struct ib_device	*device;
 	__be64			service_id;
 	__be64			service_mask;
 	enum ib_cm_state	state;		/* internal CM/debug use */
@@ -295,6 +294,8 @@
 
 /**
  * ib_create_cm_id - Allocate a communication identifier.
+ * @device: Device associated with the cm_id.  All related communication will
+ * be associated with the specified device.
  * @cm_handler: Callback invoked to notify the user of CM events.
  * @context: User specified context associated with the communication
  *   identifier.
@@ -302,7 +303,8 @@
  * Communication identifiers are used to track connection states, service
  * ID resolution requests, and listen requests.
  */
-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
+				 ib_cm_handler cm_handler,
 				 void *context);
 
 /**
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 4172e68..2c13350 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -109,10 +109,14 @@
 #define IB_QP_SET_QKEY	0x80000000
 
 enum {
+	IB_MGMT_MAD_HDR = 24,
 	IB_MGMT_MAD_DATA = 232,
+	IB_MGMT_RMPP_HDR = 36,
 	IB_MGMT_RMPP_DATA = 220,
+	IB_MGMT_VENDOR_HDR = 40,
 	IB_MGMT_VENDOR_DATA = 216,
-	IB_MGMT_SA_DATA = 200
+	IB_MGMT_SA_HDR = 56,
+	IB_MGMT_SA_DATA = 200,
 };
 
 struct ib_mad_hdr {
@@ -203,26 +207,25 @@
 
 /**
  * ib_mad_send_buf - MAD data buffer and work request for sends.
- * @mad: References an allocated MAD data buffer.  The size of the data
- *   buffer is specified in the @send_wr.length field.
- * @mapping: DMA mapping information.
+ * @next: A pointer used to chain together MADs for posting.
+ * @mad: References an allocated MAD data buffer.
  * @mad_agent: MAD agent that allocated the buffer.
+ * @ah: The address handle to use when sending the MAD.
  * @context: User-controlled context fields.
- * @send_wr: An initialized work request structure used when sending the MAD.
- *   The wr_id field of the work request is initialized to reference this
- *   data structure.
- * @sge: A scatter-gather list referenced by the work request.
+ * @timeout_ms: Time to wait for a response.
+ * @retries: Number of times to retry a request for a response.
  *
  * Users are responsible for initializing the MAD buffer itself, with the
  * exception of specifying the payload length field in any RMPP MAD.
  */
 struct ib_mad_send_buf {
-	struct ib_mad		*mad;
-	DECLARE_PCI_UNMAP_ADDR(mapping)
+	struct ib_mad_send_buf	*next;
+	void			*mad;
 	struct ib_mad_agent	*mad_agent;
+	struct ib_ah		*ah;
 	void			*context[2];
-	struct ib_send_wr	send_wr;
-	struct ib_sge		sge;
+	int			timeout_ms;
+	int			retries;
 };
 
 /**
@@ -287,7 +290,7 @@
  * or @mad_send_wc.
  */
 typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent,
-				     struct ib_send_wr *send_wr,
+				     struct ib_mad_send_buf *send_buf,
 				     struct ib_mad_send_wc *mad_send_wc);
 
 /**
@@ -334,13 +337,13 @@
 
 /**
  * ib_mad_send_wc - MAD send completion information.
- * @wr_id: Work request identifier associated with the send MAD request.
+ * @send_buf: Send MAD data buffer associated with the send MAD request.
  * @status: Completion status.
  * @vendor_err: Optional vendor error information returned with a failed
  *   request.
  */
 struct ib_mad_send_wc {
-	u64			wr_id;
+	struct ib_mad_send_buf	*send_buf;
 	enum ib_wc_status	status;
 	u32			vendor_err;
 };
@@ -366,7 +369,7 @@
  * @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.
  * @mad_len: The length of the received MAD, without duplicated headers.
  *
- * For received response, the wr_id field of the wc is set to the wr_id
+ * For received response, the wr_id contains a pointer to the ib_mad_send_buf
  *   for the corresponding send request.
  */
 struct ib_mad_recv_wc {
@@ -463,9 +466,9 @@
 /**
  * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated
  *   with the registered client.
- * @mad_agent: Specifies the associated registration to post the send to.
- * @send_wr: Specifies the information needed to send the MAD(s).
- * @bad_send_wr: Specifies the MAD on which an error was encountered.
+ * @send_buf: Specifies the information needed to send the MAD(s).
+ * @bad_send_buf: Specifies the MAD on which an error was encountered.  This
+ *   parameter is optional if only a single MAD is posted.
  *
  * Sent MADs are not guaranteed to complete in the order that they were posted.
  *
@@ -479,9 +482,8 @@
  * defined data being transferred.  The paylen_newwin field should be
  * specified in network-byte order.
  */
-int ib_post_send_mad(struct ib_mad_agent *mad_agent,
-		     struct ib_send_wr *send_wr,
-		     struct ib_send_wr **bad_send_wr);
+int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
+		     struct ib_mad_send_buf **bad_send_buf);
 
 /**
  * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer.
@@ -507,23 +509,25 @@
 /**
  * ib_cancel_mad - Cancels an outstanding send MAD operation.
  * @mad_agent: Specifies the registration associated with sent MAD.
- * @wr_id: Indicates the work request identifier of the MAD to cancel.
+ * @send_buf: Indicates the MAD to cancel.
  *
  * MADs will be returned to the user through the corresponding
  * ib_mad_send_handler.
  */
-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id);
+void ib_cancel_mad(struct ib_mad_agent *mad_agent,
+		   struct ib_mad_send_buf *send_buf);
 
 /**
  * ib_modify_mad - Modifies an outstanding send MAD operation.
  * @mad_agent: Specifies the registration associated with sent MAD.
- * @wr_id: Indicates the work request identifier of the MAD to modify.
+ * @send_buf: Indicates the MAD to modify.
  * @timeout_ms: New timeout value for sent MAD.
  *
  * This call will reset the timeout value for a sent MAD to the specified
  * value.
  */
-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms);
+int ib_modify_mad(struct ib_mad_agent *mad_agent,
+		  struct ib_mad_send_buf *send_buf, u32 timeout_ms);
 
 /**
  * ib_redirect_mad_qp - Registers a QP for MAD services.
@@ -572,7 +576,6 @@
  * @remote_qpn: Specifies the QPN of the receiving node.
  * @pkey_index: Specifies which PKey the MAD will be sent using.  This field
  *   is valid only if the remote_qpn is QP 1.
- * @ah: References the address handle used to transfer to the remote node.
  * @rmpp_active: Indicates if the send will enable RMPP.
  * @hdr_len: Indicates the size of the data header of the MAD.  This length
  *   should include the common MAD header, RMPP header, plus any class
@@ -582,11 +585,10 @@
  *   additional padding that may be necessary.
  * @gfp_mask: GFP mask used for the memory allocation.
  *
- * This is a helper routine that may be used to allocate a MAD.  Users are
- * not required to allocate outbound MADs using this call.  The returned
- * MAD send buffer will reference a data buffer usable for sending a MAD, along
+ * This routine allocates a MAD for sending.  The returned MAD send buffer
+ * will reference a data buffer usable for sending a MAD, along
  * with an initialized work request structure.  Users may modify the returned
- * MAD data buffer or work request before posting the send.
+ * MAD data buffer before posting the send.
  *
  * The returned data buffer will be cleared.  Users are responsible for
  * initializing the common MAD and any class specific headers.  If @rmpp_active
@@ -594,7 +596,7 @@
  */
 struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
 					    u32 remote_qpn, u16 pkey_index,
-					    struct ib_ah *ah, int rmpp_active,
+					    int rmpp_active,
 					    int hdr_len, int data_len,
 					    gfp_t gfp_mask);
 
diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h
index e4d1654..3037588 100644
--- a/include/rdma/ib_user_cm.h
+++ b/include/rdma/ib_user_cm.h
@@ -38,7 +38,7 @@
 
 #include <linux/types.h>
 
-#define IB_USER_CM_ABI_VERSION 2
+#define IB_USER_CM_ABI_VERSION 3
 
 enum {
 	IB_USER_CM_CMD_CREATE_ID,
@@ -299,8 +299,6 @@
 };
 
 struct ib_ucm_req_event_resp {
-	/* device */
-	/* port */
 	struct ib_ucm_path_rec primary_path;
 	struct ib_ucm_path_rec alternate_path;
 	__be64                 remote_ca_guid;
@@ -316,6 +314,7 @@
 	__u8  retry_count;
 	__u8  rnr_retry_count;
 	__u8  srq;
+	__u8  port;
 };
 
 struct ib_ucm_rep_event_resp {
@@ -353,10 +352,9 @@
 };
 
 struct ib_ucm_sidr_req_event_resp {
-	/* device */
-	/* port */
 	__u16 pkey;
-	__u8  reserved[2];
+	__u8  port;
+	__u8  reserved;
 };
 
 struct ib_ucm_sidr_rep_event_resp {
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index fd85725..072f3a2 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005 PathScale, 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
@@ -42,15 +43,12 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define IB_USER_VERBS_ABI_VERSION	2
+#define IB_USER_VERBS_ABI_VERSION	3
 
 enum {
-	IB_USER_VERBS_CMD_QUERY_PARAMS,
 	IB_USER_VERBS_CMD_GET_CONTEXT,
 	IB_USER_VERBS_CMD_QUERY_DEVICE,
 	IB_USER_VERBS_CMD_QUERY_PORT,
-	IB_USER_VERBS_CMD_QUERY_GID,
-	IB_USER_VERBS_CMD_QUERY_PKEY,
 	IB_USER_VERBS_CMD_ALLOC_PD,
 	IB_USER_VERBS_CMD_DEALLOC_PD,
 	IB_USER_VERBS_CMD_CREATE_AH,
@@ -65,6 +63,7 @@
 	IB_USER_VERBS_CMD_ALLOC_MW,
 	IB_USER_VERBS_CMD_BIND_MW,
 	IB_USER_VERBS_CMD_DEALLOC_MW,
+	IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,
 	IB_USER_VERBS_CMD_CREATE_CQ,
 	IB_USER_VERBS_CMD_RESIZE_CQ,
 	IB_USER_VERBS_CMD_DESTROY_CQ,
@@ -90,8 +89,11 @@
  * 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.
+ * Specifically:
+ *  - Do not use pointer types -- pass pointers in __u64 instead.
+ *  - Make sure that any structure larger than 4 bytes is padded to a
+ *    multiple of 8 bytes.  Otherwise the structure size will be
+ *    different between 32-bit and 64-bit architectures.
  */
 
 struct ib_uverbs_async_event_desc {
@@ -118,27 +120,14 @@
 	__u16 out_words;
 };
 
-/*
- * No driver_data for "query params" command, since this is intended
- * to be a core function with no possible device dependence.
- */
-struct ib_uverbs_query_params {
-	__u64 response;
-};
-
-struct ib_uverbs_query_params_resp {
-	__u32 num_cq_events;
-};
-
 struct ib_uverbs_get_context {
 	__u64 response;
-	__u64 cq_fd_tab;
 	__u64 driver_data[0];
 };
 
 struct ib_uverbs_get_context_resp {
 	__u32 async_fd;
-	__u32 reserved;
+	__u32 num_comp_vectors;
 };
 
 struct ib_uverbs_query_device {
@@ -220,31 +209,6 @@
 	__u8  reserved[3];
 };
 
-struct ib_uverbs_query_gid {
-	__u64 response;
-	__u8  port_num;
-	__u8  index;
-	__u8  reserved[6];
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_gid_resp {
-	__u8  gid[16];
-};
-
-struct ib_uverbs_query_pkey {
-	__u64 response;
-	__u8  port_num;
-	__u8  index;
-	__u8  reserved[6];
-	__u64 driver_data[0];
-};
-
-struct ib_uverbs_query_pkey_resp {
-	__u16 pkey;
-	__u16 reserved;
-};
-
 struct ib_uverbs_alloc_pd {
 	__u64 response;
 	__u64 driver_data[0];
@@ -278,11 +242,21 @@
 	__u32 mr_handle;
 };
 
+struct ib_uverbs_create_comp_channel {
+	__u64 response;
+};
+
+struct ib_uverbs_create_comp_channel_resp {
+	__u32 fd;
+};
+
 struct ib_uverbs_create_cq {
 	__u64 response;
 	__u64 user_handle;
 	__u32 cqe;
-	__u32 event_handler;
+	__u32 comp_vector;
+	__s32 comp_channel;
+	__u32 reserved;
 	__u64 driver_data[0];
 };
 
@@ -291,6 +265,41 @@
 	__u32 cqe;
 };
 
+struct ib_uverbs_poll_cq {
+	__u64 response;
+	__u32 cq_handle;
+	__u32 ne;
+};
+
+struct ib_uverbs_wc {
+	__u64 wr_id;
+	__u32 status;
+	__u32 opcode;
+	__u32 vendor_err;
+	__u32 byte_len;
+	__u32 imm_data;
+	__u32 qp_num;
+	__u32 src_qp;
+	__u32 wc_flags;
+	__u16 pkey_index;
+	__u16 slid;
+	__u8 sl;
+	__u8 dlid_path_bits;
+	__u8 port_num;
+	__u8 reserved;
+};
+
+struct ib_uverbs_poll_cq_resp {
+	__u32 count;
+	__u32 reserved;
+	struct ib_uverbs_wc wc[0];
+};
+
+struct ib_uverbs_req_notify_cq {
+	__u32 cq_handle;
+	__u32 solicited_only;
+};
+
 struct ib_uverbs_destroy_cq {
 	__u64 response;
 	__u32 cq_handle;
@@ -388,6 +397,127 @@
 	__u32 events_reported;
 };
 
+/*
+ * The ib_uverbs_sge structure isn't used anywhere, since we assume
+ * the ib_sge structure is packed the same way on 32-bit and 64-bit
+ * architectures in both kernel and user space.  It's just here to
+ * document the ABI.
+ */
+struct ib_uverbs_sge {
+	__u64 addr;
+	__u32 length;
+	__u32 lkey;
+};
+
+struct ib_uverbs_send_wr {
+	__u64 wr_id; 
+	__u32 num_sge;
+	__u32 opcode;
+	__u32 send_flags;
+	__u32 imm_data;
+	union {
+		struct {
+			__u64 remote_addr;
+			__u32 rkey;
+			__u32 reserved;
+		} rdma;
+		struct {
+			__u64 remote_addr;
+			__u64 compare_add;
+			__u64 swap;
+			__u32 rkey;
+			__u32 reserved;
+		} atomic;
+		struct {
+			__u32 ah;
+			__u32 remote_qpn;
+			__u32 remote_qkey;
+			__u32 reserved;
+		} ud;
+	} wr;
+};
+
+struct ib_uverbs_post_send {
+	__u64 response;
+	__u32 qp_handle;
+	__u32 wr_count;
+	__u32 sge_count;
+	__u32 wqe_size;
+	struct ib_uverbs_send_wr send_wr[0];
+};
+
+struct ib_uverbs_post_send_resp {
+	__u32 bad_wr;
+};
+
+struct ib_uverbs_recv_wr {
+	__u64 wr_id;
+	__u32 num_sge;
+	__u32 reserved;
+};
+
+struct ib_uverbs_post_recv {
+	__u64 response;
+	__u32 qp_handle;
+	__u32 wr_count;
+	__u32 sge_count;
+	__u32 wqe_size;
+	struct ib_uverbs_recv_wr recv_wr[0];
+};
+
+struct ib_uverbs_post_recv_resp {
+	__u32 bad_wr;
+};
+
+struct ib_uverbs_post_srq_recv {
+	__u64 response;
+	__u32 srq_handle;
+	__u32 wr_count;
+	__u32 sge_count;
+	__u32 wqe_size;
+	struct ib_uverbs_recv_wr recv[0];
+};
+
+struct ib_uverbs_post_srq_recv_resp {
+	__u32 bad_wr;
+};
+
+struct ib_uverbs_global_route {
+	__u8  dgid[16];
+	__u32 flow_label;    
+	__u8  sgid_index;
+	__u8  hop_limit;
+	__u8  traffic_class;
+	__u8  reserved;
+};
+
+struct ib_uverbs_ah_attr {
+	struct ib_uverbs_global_route grh;
+	__u16 dlid;
+	__u8  sl;
+	__u8  src_path_bits;
+	__u8  static_rate;
+	__u8  is_global;
+	__u8  port_num;
+	__u8  reserved;
+};
+
+struct ib_uverbs_create_ah {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 reserved;
+	struct ib_uverbs_ah_attr attr;
+};
+
+struct ib_uverbs_create_ah_resp {
+	__u32 ah_handle;
+};
+
+struct ib_uverbs_destroy_ah {
+	__u32 ah_handle;
+};
+
 struct ib_uverbs_attach_mcast {
 	__u8  gid[16];
 	__u32 qp_handle;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index e6f4c9e..f72d46d 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -595,11 +595,8 @@
 		} atomic;
 		struct {
 			struct ib_ah *ah;
-			struct ib_mad_hdr *mad_hdr;
 			u32	remote_qpn;
 			u32	remote_qkey;
-			int	timeout_ms; /* valid for MADs only */
-			int	retries;    /* valid for MADs only */
 			u16	pkey_index; /* valid for GSI only */
 			u8	port_num;   /* valid for DR SMPs on switch only */
 		} ud;
@@ -951,6 +948,9 @@
 		IB_DEV_UNREGISTERED
 	}                            reg_state;
 
+	u64			     uverbs_cmd_mask;
+	int			     uverbs_abi_ver;
+
 	u8                           node_type;
 	u8                           phys_port_cnt;
 };
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index b361172..6cb1e27 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -116,6 +116,9 @@
 /* values for service action in */
 #define	SAI_READ_CAPACITY_16  0x10
 
+/* Values for T10/04-262r7 */
+#define	ATA_16		      0x85	/* 16-byte pass-thru */
+#define	ATA_12		      0xa1	/* 12-byte pass-thru */
 
 /*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index bed4b7c..7529f43 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -4,6 +4,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/timer.h>
 
 struct request;
 struct scatterlist;
@@ -146,7 +147,7 @@
 #define SCSI_STATE_MLQUEUE         0x100b
 
 
-extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, int);
+extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
 extern void scsi_put_command(struct scsi_cmnd *);
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index 6a14002..2539deb 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -45,7 +45,7 @@
  					   level driver) of this request */
 };
 
-extern struct scsi_request *scsi_allocate_request(struct scsi_device *, int);
+extern struct scsi_request *scsi_allocate_request(struct scsi_device *, gfp_t);
 extern void scsi_release_request(struct scsi_request *);
 extern void scsi_wait_req(struct scsi_request *, const void *cmnd,
 			  void *buffer, unsigned bufflen,
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index b0d4454..c04405b 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -28,6 +28,7 @@
 #define SCSI_TRANSPORT_FC_H
 
 #include <linux/config.h>
+#include <linux/sched.h>
 
 struct scsi_transport_template;
 
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 3a2fd2c..83489c3 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -111,7 +111,7 @@
 int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
 
 /* basic memory allocation functions */
-void *snd_malloc_pages(size_t size, unsigned int gfp_flags);
+void *snd_malloc_pages(size_t size, gfp_t gfp_flags);
 void snd_free_pages(void *ptr, size_t size);
 
 #endif /* __SOUND_MEMALLOC_H */
diff --git a/init/Kconfig b/init/Kconfig
index d5a1a12..3dcbd5b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -60,8 +60,8 @@
 	default 32 if !USERMODE
 	default 128 if USERMODE
 	help
-	  This is the value of the two limits on the number of argument and of
-	  env.var passed to init from the kernel command line.
+	  Maximum of each of the number of arguments and environment
+	  variables passed to init from the kernel command line.
 
 endmenu
 
diff --git a/init/main.c b/init/main.c
index f142d40..4075d97 100644
--- a/init/main.c
+++ b/init/main.c
@@ -64,10 +64,6 @@
 #endif
 #endif
 
-#ifdef CONFIG_X86_LOCAL_APIC
-#include <asm/smp.h>
-#endif
-
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -314,14 +310,7 @@
 
 #ifndef CONFIG_SMP
 
-#ifdef CONFIG_X86_LOCAL_APIC
-static void __init smp_init(void)
-{
-	APIC_init_uniprocessor();
-}
-#else
 #define smp_init()	do { } while (0)
-#endif
 
 static inline void setup_per_cpu_areas(void) { }
 static inline void smp_prepare_cpus(unsigned int maxcpus) { }
diff --git a/ipc/shm.c b/ipc/shm.c
index dca9048..b58c651 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -233,10 +233,11 @@
 	shp->id = shm_buildid(id,shp->shm_perm.seq);
 	shp->shm_file = file;
 	file->f_dentry->d_inode->i_ino = shp->id;
-	if (shmflg & SHM_HUGETLB)
-		set_file_hugepages(file);
-	else
+
+	/* Hugetlb ops would have already been assigned. */
+	if (!(shmflg & SHM_HUGETLB))
 		file->f_op = &shm_file_operations;
+
 	shm_tot += numpages;
 	shm_unlock(shp);
 	return shp->id;
diff --git a/kernel/Makefile b/kernel/Makefile
index ff4dc02..4f5a145 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -22,7 +22,6 @@
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_CPUSETS) += cpuset.o
 obj-$(CONFIG_IKCONFIG) += configs.o
-obj-$(CONFIG_IKCONFIG_PROC) += configs.o
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
@@ -32,6 +31,7 @@
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_SECCOMP) += seccomp.o
+obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 
 ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff --git a/kernel/acct.c b/kernel/acct.c
index b756f52..2e3f4a4 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -553,7 +553,7 @@
 		if (delta == 0)
 			return;
 		tsk->acct_stimexpd = tsk->stime;
-		tsk->acct_rss_mem1 += delta * get_mm_counter(tsk->mm, rss);
+		tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
 		tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
 	}
 }
diff --git a/kernel/audit.c b/kernel/audit.c
index aefa73a..0c56320 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -133,7 +133,7 @@
 	struct list_head     list;
 	struct sk_buff       *skb;	/* formatted skb ready to send */
 	struct audit_context *ctx;	/* NULL or associated context */
-	int		     gfp_mask;
+	gfp_t		     gfp_mask;
 };
 
 static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
@@ -647,7 +647,7 @@
  * will be written at syscall exit.  If there is no associated task, tsk
  * should be NULL. */
 
-struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,
+struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
 				     int type)
 {
 	struct audit_buffer	*ab	= NULL;
@@ -879,7 +879,7 @@
 /* Log an audit record.  This is a convenience function that calls
  * audit_log_start, audit_log_vformat, and audit_log_end.  It may be
  * called in any context. */
-void audit_log(struct audit_context *ctx, int gfp_mask, int type, 
+void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, 
 	       const char *fmt, ...)
 {
 	struct audit_buffer *ab;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 88696f6..d8a6850 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -803,7 +803,7 @@
 	up_read(&mm->mmap_sem);
 }
 
-static void audit_log_exit(struct audit_context *context, unsigned int gfp_mask)
+static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
 {
 	int i;
 	struct audit_buffer *ab;
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 53d8263..3619e93 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -17,6 +17,7 @@
 
 /* This protects CPUs going up and down... */
 DECLARE_MUTEX(cpucontrol);
+EXPORT_SYMBOL_GPL(cpucontrol);
 
 static struct notifier_block *cpu_chain;
 
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 28176d0..5a737ed 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -32,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/kmod.h>
 #include <linux/list.h>
+#include <linux/mempolicy.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/mount.h>
@@ -60,6 +61,9 @@
 	cpumask_t cpus_allowed;		/* CPUs allowed to tasks in cpuset */
 	nodemask_t mems_allowed;	/* Memory Nodes allowed to tasks */
 
+	/*
+	 * Count is atomic so can incr (fork) or decr (exit) without a lock.
+	 */
 	atomic_t count;			/* count tasks using this cpuset */
 
 	/*
@@ -142,80 +146,91 @@
 static struct super_block *cpuset_sb = NULL;
 
 /*
- * cpuset_sem should be held by anyone who is depending on the children
- * or sibling lists of any cpuset, or performing non-atomic operations
- * on the flags or *_allowed values of a cpuset, such as raising the
- * CS_REMOVED flag bit iff it is not already raised, or reading and
- * conditionally modifying the *_allowed values.  One kernel global
- * cpuset semaphore should be sufficient - these things don't change
- * that much.
+ * We have two global cpuset semaphores below.  They can nest.
+ * It is ok to first take manage_sem, then nest callback_sem.  We also
+ * require taking task_lock() when dereferencing a tasks cpuset pointer.
+ * See "The task_lock() exception", at the end of this comment.
  *
- * The code that modifies cpusets holds cpuset_sem across the entire
- * operation, from cpuset_common_file_write() down, single threading
- * all cpuset modifications (except for counter manipulations from
- * fork and exit) across the system.  This presumes that cpuset
- * modifications are rare - better kept simple and safe, even if slow.
+ * A task must hold both semaphores to modify cpusets.  If a task
+ * holds manage_sem, then it blocks others wanting that semaphore,
+ * ensuring that it is the only task able to also acquire callback_sem
+ * and be able to modify cpusets.  It can perform various checks on
+ * the cpuset structure first, knowing nothing will change.  It can
+ * also allocate memory while just holding manage_sem.  While it is
+ * performing these checks, various callback routines can briefly
+ * acquire callback_sem to query cpusets.  Once it is ready to make
+ * the changes, it takes callback_sem, blocking everyone else.
  *
- * The code that reads cpusets, such as in cpuset_common_file_read()
- * and below, only holds cpuset_sem across small pieces of code, such
- * as when reading out possibly multi-word cpumasks and nodemasks, as
- * the risks are less, and the desire for performance a little greater.
- * The proc_cpuset_show() routine needs to hold cpuset_sem to insure
- * that no cs->dentry is NULL, as it walks up the cpuset tree to root.
+ * Calls to the kernel memory allocator can not be made while holding
+ * callback_sem, as that would risk double tripping on callback_sem
+ * from one of the callbacks into the cpuset code from within
+ * __alloc_pages().
  *
- * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't
- * (usually) grab cpuset_sem.  These are the two most performance
- * critical pieces of code here.  The exception occurs on exit(),
- * when a task in a notify_on_release cpuset exits.  Then cpuset_sem
+ * If a task is only holding callback_sem, then it has read-only
+ * access to cpusets.
+ *
+ * The task_struct fields mems_allowed and mems_generation may only
+ * be accessed in the context of that task, so require no locks.
+ *
+ * Any task can increment and decrement the count field without lock.
+ * So in general, code holding manage_sem or callback_sem can't rely
+ * on the count field not changing.  However, if the count goes to
+ * zero, then only attach_task(), which holds both semaphores, can
+ * increment it again.  Because a count of zero means that no tasks
+ * are currently attached, therefore there is no way a task attached
+ * to that cpuset can fork (the other way to increment the count).
+ * So code holding manage_sem or callback_sem can safely assume that
+ * if the count is zero, it will stay zero.  Similarly, if a task
+ * holds manage_sem or callback_sem on a cpuset with zero count, it
+ * knows that the cpuset won't be removed, as cpuset_rmdir() needs
+ * both of those semaphores.
+ *
+ * A possible optimization to improve parallelism would be to make
+ * callback_sem a R/W semaphore (rwsem), allowing the callback routines
+ * to proceed in parallel, with read access, until the holder of
+ * manage_sem needed to take this rwsem for exclusive write access
+ * and modify some cpusets.
+ *
+ * The cpuset_common_file_write handler for operations that modify
+ * the cpuset hierarchy holds manage_sem across the entire operation,
+ * single threading all such cpuset modifications across the system.
+ *
+ * The cpuset_common_file_read() handlers only hold callback_sem across
+ * small pieces of code, such as when reading out possibly multi-word
+ * cpumasks and nodemasks.
+ *
+ * The fork and exit callbacks cpuset_fork() and cpuset_exit(), don't
+ * (usually) take either semaphore.  These are the two most performance
+ * critical pieces of code here.  The exception occurs on cpuset_exit(),
+ * when a task in a notify_on_release cpuset exits.  Then manage_sem
  * is taken, and if the cpuset count is zero, a usermode call made
  * to /sbin/cpuset_release_agent with the name of the cpuset (path
  * relative to the root of cpuset file system) as the argument.
  *
- * A cpuset can only be deleted if both its 'count' of using tasks is
- * zero, and its list of 'children' cpusets is empty.  Since all tasks
- * in the system use _some_ cpuset, and since there is always at least
- * one task in the system (init, pid == 1), therefore, top_cpuset
- * always has either children cpusets and/or using tasks.  So no need
- * for any special hack to ensure that top_cpuset cannot be deleted.
+ * A cpuset can only be deleted if both its 'count' of using tasks
+ * is zero, and its list of 'children' cpusets is empty.  Since all
+ * tasks in the system use _some_ cpuset, and since there is always at
+ * least one task in the system (init, pid == 1), therefore, top_cpuset
+ * always has either children cpusets and/or using tasks.  So we don't
+ * need a special hack to ensure that top_cpuset cannot be deleted.
+ *
+ * The above "Tale of Two Semaphores" would be complete, but for:
+ *
+ *	The task_lock() exception
+ *
+ * The need for this exception arises from the action of attach_task(),
+ * which overwrites one tasks cpuset pointer with another.  It does
+ * so using both semaphores, however there are several performance
+ * critical places that need to reference task->cpuset without the
+ * expense of grabbing a system global semaphore.  Therefore except as
+ * noted below, when dereferencing or, as in attach_task(), modifying
+ * a tasks cpuset pointer we use task_lock(), which acts on a spinlock
+ * (task->alloc_lock) already in the task_struct routinely used for
+ * such matters.
  */
 
-static DECLARE_MUTEX(cpuset_sem);
-static struct task_struct *cpuset_sem_owner;
-static int cpuset_sem_depth;
-
-/*
- * The global cpuset semaphore cpuset_sem can be needed by the
- * memory allocator to update a tasks mems_allowed (see the calls
- * to cpuset_update_current_mems_allowed()) or to walk up the
- * cpuset hierarchy to find a mem_exclusive cpuset see the calls
- * to cpuset_excl_nodes_overlap()).
- *
- * But if the memory allocation is being done by cpuset.c code, it
- * usually already holds cpuset_sem.  Double tripping on a kernel
- * semaphore deadlocks the current task, and any other task that
- * subsequently tries to obtain the lock.
- *
- * Run all up's and down's on cpuset_sem through the following
- * wrappers, which will detect this nested locking, and avoid
- * deadlocking.
- */
-
-static inline void cpuset_down(struct semaphore *psem)
-{
-	if (cpuset_sem_owner != current) {
-		down(psem);
-		cpuset_sem_owner = current;
-	}
-	cpuset_sem_depth++;
-}
-
-static inline void cpuset_up(struct semaphore *psem)
-{
-	if (--cpuset_sem_depth == 0) {
-		cpuset_sem_owner = NULL;
-		up(psem);
-	}
-}
+static DECLARE_MUTEX(manage_sem);
+static DECLARE_MUTEX(callback_sem);
 
 /*
  * A couple of forward declarations required, due to cyclic reference loop:
@@ -390,7 +405,7 @@
 }
 
 /*
- * Call with cpuset_sem held.  Writes path of cpuset into buf.
+ * Call with manage_sem held.  Writes path of cpuset into buf.
  * Returns 0 on success, -errno on error.
  */
 
@@ -442,10 +457,11 @@
  * status of the /sbin/cpuset_release_agent task, so no sense holding
  * our caller up for that.
  *
- * The simple act of forking that task might require more memory,
- * which might need cpuset_sem.  So this routine must be called while
- * cpuset_sem is not held, to avoid a possible deadlock.  See also
- * comments for check_for_release(), below.
+ * When we had only one cpuset semaphore, we had to call this
+ * without holding it, to avoid deadlock when call_usermodehelper()
+ * allocated memory.  With two locks, we could now call this while
+ * holding manage_sem, but we still don't, so as to minimize
+ * the time manage_sem is held.
  */
 
 static void cpuset_release_agent(const char *pathbuf)
@@ -477,15 +493,15 @@
  * cs is notify_on_release() and now both the user count is zero and
  * the list of children is empty, prepare cpuset path in a kmalloc'd
  * buffer, to be returned via ppathbuf, so that the caller can invoke
- * cpuset_release_agent() with it later on, once cpuset_sem is dropped.
- * Call here with cpuset_sem held.
+ * cpuset_release_agent() with it later on, once manage_sem is dropped.
+ * Call here with manage_sem held.
  *
  * This check_for_release() routine is responsible for kmalloc'ing
  * pathbuf.  The above cpuset_release_agent() is responsible for
  * kfree'ing pathbuf.  The caller of these routines is responsible
  * for providing a pathbuf pointer, initialized to NULL, then
- * calling check_for_release() with cpuset_sem held and the address
- * of the pathbuf pointer, then dropping cpuset_sem, then calling
+ * calling check_for_release() with manage_sem held and the address
+ * of the pathbuf pointer, then dropping manage_sem, then calling
  * cpuset_release_agent() with pathbuf, as set by check_for_release().
  */
 
@@ -516,7 +532,7 @@
  * One way or another, we guarantee to return some non-empty subset
  * of cpu_online_map.
  *
- * Call with cpuset_sem held.
+ * Call with callback_sem held.
  */
 
 static void guarantee_online_cpus(const struct cpuset *cs, cpumask_t *pmask)
@@ -540,7 +556,7 @@
  * One way or another, we guarantee to return some non-empty subset
  * of node_online_map.
  *
- * Call with cpuset_sem held.
+ * Call with callback_sem held.
  */
 
 static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
@@ -555,22 +571,47 @@
 }
 
 /*
- * Refresh current tasks mems_allowed and mems_generation from
- * current tasks cpuset.  Call with cpuset_sem held.
+ * Refresh current tasks mems_allowed and mems_generation from current
+ * tasks cpuset.
  *
- * This routine is needed to update the per-task mems_allowed
- * data, within the tasks context, when it is trying to allocate
- * memory (in various mm/mempolicy.c routines) and notices
- * that some other task has been modifying its cpuset.
+ * Call without callback_sem or task_lock() held.  May be called with
+ * or without manage_sem held.  Will acquire task_lock() and might
+ * acquire callback_sem during call.
+ *
+ * The task_lock() is required to dereference current->cpuset safely.
+ * Without it, we could pick up the pointer value of current->cpuset
+ * in one instruction, and then attach_task could give us a different
+ * cpuset, and then the cpuset we had could be removed and freed,
+ * and then on our next instruction, we could dereference a no longer
+ * valid cpuset pointer to get its mems_generation field.
+ *
+ * This routine is needed to update the per-task mems_allowed data,
+ * within the tasks context, when it is trying to allocate memory
+ * (in various mm/mempolicy.c routines) and notices that some other
+ * task has been modifying its cpuset.
  */
 
 static void refresh_mems(void)
 {
-	struct cpuset *cs = current->cpuset;
+	int my_cpusets_mem_gen;
 
-	if (current->cpuset_mems_generation != cs->mems_generation) {
+	task_lock(current);
+	my_cpusets_mem_gen = current->cpuset->mems_generation;
+	task_unlock(current);
+
+	if (current->cpuset_mems_generation != my_cpusets_mem_gen) {
+		struct cpuset *cs;
+		nodemask_t oldmem = current->mems_allowed;
+
+		down(&callback_sem);
+		task_lock(current);
+		cs = current->cpuset;
 		guarantee_online_mems(cs, &current->mems_allowed);
 		current->cpuset_mems_generation = cs->mems_generation;
+		task_unlock(current);
+		up(&callback_sem);
+		if (!nodes_equal(oldmem, current->mems_allowed))
+			numa_policy_rebind(&oldmem, &current->mems_allowed);
 	}
 }
 
@@ -579,7 +620,7 @@
  *
  * One cpuset is a subset of another if all its allowed CPUs and
  * Memory Nodes are a subset of the other, and its exclusive flags
- * are only set if the other's are set.
+ * are only set if the other's are set.  Call holding manage_sem.
  */
 
 static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
@@ -597,7 +638,7 @@
  * If we replaced the flag and mask values of the current cpuset
  * (cur) with those values in the trial cpuset (trial), would
  * our various subset and exclusive rules still be valid?  Presumes
- * cpuset_sem held.
+ * manage_sem held.
  *
  * 'cur' is the address of an actual, in-use cpuset.  Operations
  * such as list traversal that depend on the actual address of the
@@ -651,7 +692,7 @@
  *    exclusive child cpusets
  * Build these two partitions by calling partition_sched_domains
  *
- * Call with cpuset_sem held.  May nest a call to the
+ * Call with manage_sem held.  May nest a call to the
  * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
  */
 
@@ -696,6 +737,10 @@
 	unlock_cpu_hotplug();
 }
 
+/*
+ * Call with manage_sem held.  May take callback_sem during call.
+ */
+
 static int update_cpumask(struct cpuset *cs, char *buf)
 {
 	struct cpuset trialcs;
@@ -712,12 +757,18 @@
 	if (retval < 0)
 		return retval;
 	cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
+	down(&callback_sem);
 	cs->cpus_allowed = trialcs.cpus_allowed;
+	up(&callback_sem);
 	if (is_cpu_exclusive(cs) && !cpus_unchanged)
 		update_cpu_domains(cs);
 	return 0;
 }
 
+/*
+ * Call with manage_sem held.  May take callback_sem during call.
+ */
+
 static int update_nodemask(struct cpuset *cs, char *buf)
 {
 	struct cpuset trialcs;
@@ -732,9 +783,11 @@
 		return -ENOSPC;
 	retval = validate_change(cs, &trialcs);
 	if (retval == 0) {
+		down(&callback_sem);
 		cs->mems_allowed = trialcs.mems_allowed;
 		atomic_inc(&cpuset_mems_generation);
 		cs->mems_generation = atomic_read(&cpuset_mems_generation);
+		up(&callback_sem);
 	}
 	return retval;
 }
@@ -745,6 +798,8 @@
  *						CS_NOTIFY_ON_RELEASE)
  * cs:	the cpuset to update
  * buf:	the buffer where we read the 0 or 1
+ *
+ * Call with manage_sem held.
  */
 
 static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
@@ -766,16 +821,27 @@
 		return err;
 	cpu_exclusive_changed =
 		(is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
+	down(&callback_sem);
 	if (turning_on)
 		set_bit(bit, &cs->flags);
 	else
 		clear_bit(bit, &cs->flags);
+	up(&callback_sem);
 
 	if (cpu_exclusive_changed)
                 update_cpu_domains(cs);
 	return 0;
 }
 
+/*
+ * Attack task specified by pid in 'pidbuf' to cpuset 'cs', possibly
+ * writing the path of the old cpuset in 'ppathbuf' if it needs to be
+ * notified on release.
+ *
+ * Call holding manage_sem.  May take callback_sem and task_lock of
+ * the task 'pid' during call.
+ */
+
 static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
 {
 	pid_t pid;
@@ -792,7 +858,7 @@
 		read_lock(&tasklist_lock);
 
 		tsk = find_task_by_pid(pid);
-		if (!tsk) {
+		if (!tsk || tsk->flags & PF_EXITING) {
 			read_unlock(&tasklist_lock);
 			return -ESRCH;
 		}
@@ -810,10 +876,13 @@
 		get_task_struct(tsk);
 	}
 
+	down(&callback_sem);
+
 	task_lock(tsk);
 	oldcs = tsk->cpuset;
 	if (!oldcs) {
 		task_unlock(tsk);
+		up(&callback_sem);
 		put_task_struct(tsk);
 		return -ESRCH;
 	}
@@ -824,6 +893,7 @@
 	guarantee_online_cpus(cs, &cpus);
 	set_cpus_allowed(tsk, cpus);
 
+	up(&callback_sem);
 	put_task_struct(tsk);
 	if (atomic_dec_and_test(&oldcs->count))
 		check_for_release(oldcs, ppathbuf);
@@ -867,7 +937,7 @@
 	}
 	buffer[nbytes] = 0;	/* nul-terminate */
 
-	cpuset_down(&cpuset_sem);
+	down(&manage_sem);
 
 	if (is_removed(cs)) {
 		retval = -ENODEV;
@@ -901,7 +971,7 @@
 	if (retval == 0)
 		retval = nbytes;
 out2:
-	cpuset_up(&cpuset_sem);
+	up(&manage_sem);
 	cpuset_release_agent(pathbuf);
 out1:
 	kfree(buffer);
@@ -941,9 +1011,9 @@
 {
 	cpumask_t mask;
 
-	cpuset_down(&cpuset_sem);
+	down(&callback_sem);
 	mask = cs->cpus_allowed;
-	cpuset_up(&cpuset_sem);
+	up(&callback_sem);
 
 	return cpulist_scnprintf(page, PAGE_SIZE, mask);
 }
@@ -952,9 +1022,9 @@
 {
 	nodemask_t mask;
 
-	cpuset_down(&cpuset_sem);
+	down(&callback_sem);
 	mask = cs->mems_allowed;
-	cpuset_up(&cpuset_sem);
+	up(&callback_sem);
 
 	return nodelist_scnprintf(page, PAGE_SIZE, mask);
 }
@@ -995,7 +1065,6 @@
 		goto out;
 	}
 	*s++ = '\n';
-	*s = '\0';
 
 	retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
 out:
@@ -1048,6 +1117,21 @@
 	return 0;
 }
 
+/*
+ * cpuset_rename - Only allow simple rename of directories in place.
+ */
+static int cpuset_rename(struct inode *old_dir, struct dentry *old_dentry,
+                  struct inode *new_dir, struct dentry *new_dentry)
+{
+	if (!S_ISDIR(old_dentry->d_inode->i_mode))
+		return -ENOTDIR;
+	if (new_dentry->d_inode)
+		return -EEXIST;
+	if (old_dir != new_dir)
+		return -EIO;
+	return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
+}
+
 static struct file_operations cpuset_file_operations = {
 	.read = cpuset_file_read,
 	.write = cpuset_file_write,
@@ -1060,6 +1144,7 @@
 	.lookup = simple_lookup,
 	.mkdir = cpuset_mkdir,
 	.rmdir = cpuset_rmdir,
+	.rename = cpuset_rename,
 };
 
 static int cpuset_create_file(struct dentry *dentry, int mode)
@@ -1163,7 +1248,9 @@
 
 /*
  * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'.
- * Return actual number of pids loaded.
+ * Return actual number of pids loaded.  No need to task_lock(p)
+ * when reading out p->cpuset, as we don't really care if it changes
+ * on the next cycle, and we are not going to try to dereference it.
  */
 static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
 {
@@ -1205,6 +1292,12 @@
 	return cnt;
 }
 
+/*
+ * Handle an open on 'tasks' file.  Prepare a buffer listing the
+ * process id's of tasks currently attached to the cpuset being opened.
+ *
+ * Does not require any specific cpuset semaphores, and does not take any.
+ */
 static int cpuset_tasks_open(struct inode *unused, struct file *file)
 {
 	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
@@ -1352,7 +1445,8 @@
 	if (!cs)
 		return -ENOMEM;
 
-	cpuset_down(&cpuset_sem);
+	down(&manage_sem);
+	refresh_mems();
 	cs->flags = 0;
 	if (notify_on_release(parent))
 		set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
@@ -1366,25 +1460,27 @@
 
 	cs->parent = parent;
 
+	down(&callback_sem);
 	list_add(&cs->sibling, &cs->parent->children);
+	up(&callback_sem);
 
 	err = cpuset_create_dir(cs, name, mode);
 	if (err < 0)
 		goto err;
 
 	/*
-	 * Release cpuset_sem before cpuset_populate_dir() because it
+	 * Release manage_sem before cpuset_populate_dir() because it
 	 * will down() this new directory's i_sem and if we race with
 	 * another mkdir, we might deadlock.
 	 */
-	cpuset_up(&cpuset_sem);
+	up(&manage_sem);
 
 	err = cpuset_populate_dir(cs->dentry);
 	/* If err < 0, we have a half-filled directory - oh well ;) */
 	return 0;
 err:
 	list_del(&cs->sibling);
-	cpuset_up(&cpuset_sem);
+	up(&manage_sem);
 	kfree(cs);
 	return err;
 }
@@ -1406,29 +1502,32 @@
 
 	/* the vfs holds both inode->i_sem already */
 
-	cpuset_down(&cpuset_sem);
+	down(&manage_sem);
+	refresh_mems();
 	if (atomic_read(&cs->count) > 0) {
-		cpuset_up(&cpuset_sem);
+		up(&manage_sem);
 		return -EBUSY;
 	}
 	if (!list_empty(&cs->children)) {
-		cpuset_up(&cpuset_sem);
+		up(&manage_sem);
 		return -EBUSY;
 	}
 	parent = cs->parent;
+	down(&callback_sem);
 	set_bit(CS_REMOVED, &cs->flags);
 	if (is_cpu_exclusive(cs))
 		update_cpu_domains(cs);
 	list_del(&cs->sibling);	/* delete my sibling from parent->children */
-	if (list_empty(&parent->children))
-		check_for_release(parent, &pathbuf);
 	spin_lock(&cs->dentry->d_lock);
 	d = dget(cs->dentry);
 	cs->dentry = NULL;
 	spin_unlock(&d->d_lock);
 	cpuset_d_remove_dir(d);
 	dput(d);
-	cpuset_up(&cpuset_sem);
+	up(&callback_sem);
+	if (list_empty(&parent->children))
+		check_for_release(parent, &pathbuf);
+	up(&manage_sem);
 	cpuset_release_agent(pathbuf);
 	return 0;
 }
@@ -1488,16 +1587,26 @@
  * cpuset_fork - attach newly forked task to its parents cpuset.
  * @tsk: pointer to task_struct of forking parent process.
  *
- * Description: By default, on fork, a task inherits its
- * parent's cpuset.  The pointer to the shared cpuset is
- * automatically copied in fork.c by dup_task_struct().
- * This cpuset_fork() routine need only increment the usage
- * counter in that cpuset.
+ * Description: A task inherits its parent's cpuset at fork().
+ *
+ * A pointer to the shared cpuset was automatically copied in fork.c
+ * by dup_task_struct().  However, we ignore that copy, since it was
+ * not made under the protection of task_lock(), so might no longer be
+ * a valid cpuset pointer.  attach_task() might have already changed
+ * current->cpuset, allowing the previously referenced cpuset to
+ * be removed and freed.  Instead, we task_lock(current) and copy
+ * its present value of current->cpuset for our freshly forked child.
+ *
+ * At the point that cpuset_fork() is called, 'current' is the parent
+ * task, and the passed argument 'child' points to the child task.
  **/
 
-void cpuset_fork(struct task_struct *tsk)
+void cpuset_fork(struct task_struct *child)
 {
-	atomic_inc(&tsk->cpuset->count);
+	task_lock(current);
+	child->cpuset = current->cpuset;
+	atomic_inc(&child->cpuset->count);
+	task_unlock(current);
 }
 
 /**
@@ -1506,35 +1615,42 @@
  *
  * Description: Detach cpuset from @tsk and release it.
  *
- * Note that cpusets marked notify_on_release force every task
- * in them to take the global cpuset_sem semaphore when exiting.
- * This could impact scaling on very large systems.  Be reluctant
- * to use notify_on_release cpusets where very high task exit
- * scaling is required on large systems.
+ * Note that cpusets marked notify_on_release force every task in
+ * them to take the global manage_sem semaphore when exiting.
+ * This could impact scaling on very large systems.  Be reluctant to
+ * use notify_on_release cpusets where very high task exit scaling
+ * is required on large systems.
  *
- * Don't even think about derefencing 'cs' after the cpuset use
- * count goes to zero, except inside a critical section guarded
- * by the cpuset_sem semaphore.  If you don't hold cpuset_sem,
- * then a zero cpuset use count is a license to any other task to
- * nuke the cpuset immediately.
+ * Don't even think about derefencing 'cs' after the cpuset use count
+ * goes to zero, except inside a critical section guarded by manage_sem
+ * or callback_sem.   Otherwise a zero cpuset use count is a license to
+ * any other task to nuke the cpuset immediately, via cpuset_rmdir().
+ *
+ * This routine has to take manage_sem, not callback_sem, because
+ * it is holding that semaphore while calling check_for_release(),
+ * which calls kmalloc(), so can't be called holding callback__sem().
+ *
+ * We don't need to task_lock() this reference to tsk->cpuset,
+ * because tsk is already marked PF_EXITING, so attach_task() won't
+ * mess with it.
  **/
 
 void cpuset_exit(struct task_struct *tsk)
 {
 	struct cpuset *cs;
 
-	task_lock(tsk);
+	BUG_ON(!(tsk->flags & PF_EXITING));
+
 	cs = tsk->cpuset;
 	tsk->cpuset = NULL;
-	task_unlock(tsk);
 
 	if (notify_on_release(cs)) {
 		char *pathbuf = NULL;
 
-		cpuset_down(&cpuset_sem);
+		down(&manage_sem);
 		if (atomic_dec_and_test(&cs->count))
 			check_for_release(cs, &pathbuf);
-		cpuset_up(&cpuset_sem);
+		up(&manage_sem);
 		cpuset_release_agent(pathbuf);
 	} else {
 		atomic_dec(&cs->count);
@@ -1555,11 +1671,11 @@
 {
 	cpumask_t mask;
 
-	cpuset_down(&cpuset_sem);
+	down(&callback_sem);
 	task_lock((struct task_struct *)tsk);
 	guarantee_online_cpus(tsk->cpuset, &mask);
 	task_unlock((struct task_struct *)tsk);
-	cpuset_up(&cpuset_sem);
+	up(&callback_sem);
 
 	return mask;
 }
@@ -1575,19 +1691,28 @@
  * If the current tasks cpusets mems_allowed changed behind our backs,
  * update current->mems_allowed and mems_generation to the new value.
  * Do not call this routine if in_interrupt().
+ *
+ * Call without callback_sem or task_lock() held.  May be called
+ * with or without manage_sem held.  Unless exiting, it will acquire
+ * task_lock().  Also might acquire callback_sem during call to
+ * refresh_mems().
  */
 
 void cpuset_update_current_mems_allowed(void)
 {
-	struct cpuset *cs = current->cpuset;
+	struct cpuset *cs;
+	int need_to_refresh = 0;
 
+	task_lock(current);
+	cs = current->cpuset;
 	if (!cs)
-		return;		/* task is exiting */
-	if (current->cpuset_mems_generation != cs->mems_generation) {
-		cpuset_down(&cpuset_sem);
+		goto done;
+	if (current->cpuset_mems_generation != cs->mems_generation)
+		need_to_refresh = 1;
+done:
+	task_unlock(current);
+	if (need_to_refresh)
 		refresh_mems();
-		cpuset_up(&cpuset_sem);
-	}
 }
 
 /**
@@ -1621,7 +1746,7 @@
 
 /*
  * nearest_exclusive_ancestor() - Returns the nearest mem_exclusive
- * ancestor to the specified cpuset.  Call while holding cpuset_sem.
+ * ancestor to the specified cpuset.  Call holding callback_sem.
  * If no ancestor is mem_exclusive (an unusual configuration), then
  * returns the root cpuset.
  */
@@ -1648,12 +1773,12 @@
  * GFP_KERNEL allocations are not so marked, so can escape to the
  * nearest mem_exclusive ancestor cpuset.
  *
- * Scanning up parent cpusets requires cpuset_sem.  The __alloc_pages()
+ * Scanning up parent cpusets requires callback_sem.  The __alloc_pages()
  * routine only calls here with __GFP_HARDWALL bit _not_ set if
  * it's a GFP_KERNEL allocation, and all nodes in the current tasks
  * mems_allowed came up empty on the first pass over the zonelist.
  * So only GFP_KERNEL allocations, if all nodes in the cpuset are
- * short of memory, might require taking the cpuset_sem semaphore.
+ * short of memory, might require taking the callback_sem semaphore.
  *
  * The first loop over the zonelist in mm/page_alloc.c:__alloc_pages()
  * calls here with __GFP_HARDWALL always set in gfp_mask, enforcing
@@ -1685,14 +1810,16 @@
 		return 0;
 
 	/* Not hardwall and node outside mems_allowed: scan up cpusets */
-	cpuset_down(&cpuset_sem);
-	cs = current->cpuset;
-	if (!cs)
-		goto done;		/* current task exiting */
-	cs = nearest_exclusive_ancestor(cs);
+	down(&callback_sem);
+
+	if (current->flags & PF_EXITING) /* Let dying task have memory */
+		return 1;
+	task_lock(current);
+	cs = nearest_exclusive_ancestor(current->cpuset);
+	task_unlock(current);
+
 	allowed = node_isset(node, cs->mems_allowed);
-done:
-	cpuset_up(&cpuset_sem);
+	up(&callback_sem);
 	return allowed;
 }
 
@@ -1705,7 +1832,7 @@
  * determine if task @p's memory usage might impact the memory
  * available to the current task.
  *
- * Acquires cpuset_sem - not suitable for calling from a fast path.
+ * Acquires callback_sem - not suitable for calling from a fast path.
  **/
 
 int cpuset_excl_nodes_overlap(const struct task_struct *p)
@@ -1713,18 +1840,27 @@
 	const struct cpuset *cs1, *cs2;	/* my and p's cpuset ancestors */
 	int overlap = 0;		/* do cpusets overlap? */
 
-	cpuset_down(&cpuset_sem);
-	cs1 = current->cpuset;
-	if (!cs1)
-		goto done;		/* current task exiting */
-	cs2 = p->cpuset;
-	if (!cs2)
-		goto done;		/* task p is exiting */
-	cs1 = nearest_exclusive_ancestor(cs1);
-	cs2 = nearest_exclusive_ancestor(cs2);
+	down(&callback_sem);
+
+	task_lock(current);
+	if (current->flags & PF_EXITING) {
+		task_unlock(current);
+		goto done;
+	}
+	cs1 = nearest_exclusive_ancestor(current->cpuset);
+	task_unlock(current);
+
+	task_lock((struct task_struct *)p);
+	if (p->flags & PF_EXITING) {
+		task_unlock((struct task_struct *)p);
+		goto done;
+	}
+	cs2 = nearest_exclusive_ancestor(p->cpuset);
+	task_unlock((struct task_struct *)p);
+
 	overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
 done:
-	cpuset_up(&cpuset_sem);
+	up(&callback_sem);
 
 	return overlap;
 }
@@ -1733,6 +1869,10 @@
  * proc_cpuset_show()
  *  - Print tasks cpuset path into seq_file.
  *  - Used for /proc/<pid>/cpuset.
+ *  - No need to task_lock(tsk) on this tsk->cpuset reference, as it
+ *    doesn't really matter if tsk->cpuset changes after we read it,
+ *    and we take manage_sem, keeping attach_task() from changing it
+ *    anyway.
  */
 
 static int proc_cpuset_show(struct seq_file *m, void *v)
@@ -1747,10 +1887,8 @@
 		return -ENOMEM;
 
 	tsk = m->private;
-	cpuset_down(&cpuset_sem);
-	task_lock(tsk);
+	down(&manage_sem);
 	cs = tsk->cpuset;
-	task_unlock(tsk);
 	if (!cs) {
 		retval = -EINVAL;
 		goto out;
@@ -1762,7 +1900,7 @@
 	seq_puts(m, buf);
 	seq_putc(m, '\n');
 out:
-	cpuset_up(&cpuset_sem);
+	up(&manage_sem);
 	kfree(buf);
 	return retval;
 }
diff --git a/kernel/exit.c b/kernel/exit.c
index 3b25b18..537394b 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -547,7 +547,7 @@
 
 	if (p->pdeath_signal)
 		/* We already hold the tasklist_lock here.  */
-		group_send_sig_info(p->pdeath_signal, (void *) 0, p);
+		group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
 
 	/* Move the child from its dying parent to the new one.  */
 	if (unlikely(traced)) {
@@ -591,8 +591,8 @@
 		int pgrp = process_group(p);
 
 		if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) {
-			__kill_pg_info(SIGHUP, (void *)1, pgrp);
-			__kill_pg_info(SIGCONT, (void *)1, pgrp);
+			__kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp);
+			__kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp);
 		}
 	}
 }
@@ -727,8 +727,8 @@
 	    (t->signal->session == tsk->signal->session) &&
 	    will_become_orphaned_pgrp(process_group(tsk), tsk) &&
 	    has_stopped_jobs(process_group(tsk))) {
-		__kill_pg_info(SIGHUP, (void *)1, process_group(tsk));
-		__kill_pg_info(SIGCONT, (void *)1, process_group(tsk));
+		__kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk));
+		__kill_pg_info(SIGCONT, SEND_SIG_PRIV, process_group(tsk));
 	}
 
 	/* Let father know we died 
@@ -783,10 +783,6 @@
 	/* If the process is dead, release it - nobody will wait for it */
 	if (state == EXIT_DEAD)
 		release_task(tsk);
-
-	/* PF_DEAD causes final put_task_struct after we schedule. */
-	preempt_disable();
-	tsk->flags |= PF_DEAD;
 }
 
 fastcall NORET_TYPE void do_exit(long code)
@@ -839,7 +835,10 @@
 				preempt_count());
 
 	acct_update_integrals(tsk);
-	update_mem_hiwater(tsk);
+	if (tsk->mm) {
+		update_hiwater_rss(tsk->mm);
+		update_hiwater_vm(tsk->mm);
+	}
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
 	if (group_dead) {
  		del_timer_sync(&tsk->signal->real_timer);
@@ -870,7 +869,11 @@
 	tsk->mempolicy = NULL;
 #endif
 
-	BUG_ON(!(current->flags & PF_DEAD));
+	/* PF_DEAD causes final put_task_struct after we schedule. */
+	preempt_disable();
+	BUG_ON(tsk->flags & PF_DEAD);
+	tsk->flags |= PF_DEAD;
+
 	schedule();
 	BUG();
 	/* Avoid "noreturn function does return".  */
@@ -1380,6 +1383,15 @@
 
 			switch (p->state) {
 			case TASK_TRACED:
+				/*
+				 * When we hit the race with PTRACE_ATTACH,
+				 * we will not report this child.  But the
+				 * race means it has not yet been moved to
+				 * our ptrace_children list, so we need to
+				 * set the flag here to avoid a spurious ECHILD
+				 * when the race happens with the only child.
+				 */
+				flag = 1;
 				if (!my_ptrace_child(p))
 					continue;
 				/*FALLTHROUGH*/
diff --git a/kernel/fork.c b/kernel/fork.c
index 280bd44..8a06961 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -182,37 +182,37 @@
 }
 
 #ifdef CONFIG_MMU
-static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
+static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 {
-	struct vm_area_struct * mpnt, *tmp, **pprev;
+	struct vm_area_struct *mpnt, *tmp, **pprev;
 	struct rb_node **rb_link, *rb_parent;
 	int retval;
 	unsigned long charge;
 	struct mempolicy *pol;
 
 	down_write(&oldmm->mmap_sem);
-	flush_cache_mm(current->mm);
+	flush_cache_mm(oldmm);
+	down_write(&mm->mmap_sem);
+
 	mm->locked_vm = 0;
 	mm->mmap = NULL;
 	mm->mmap_cache = NULL;
 	mm->free_area_cache = oldmm->mmap_base;
 	mm->cached_hole_size = ~0UL;
 	mm->map_count = 0;
-	set_mm_counter(mm, rss, 0);
-	set_mm_counter(mm, anon_rss, 0);
 	cpus_clear(mm->cpu_vm_mask);
 	mm->mm_rb = RB_ROOT;
 	rb_link = &mm->mm_rb.rb_node;
 	rb_parent = NULL;
 	pprev = &mm->mmap;
 
-	for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
+	for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) {
 		struct file *file;
 
 		if (mpnt->vm_flags & VM_DONTCOPY) {
 			long pages = vma_pages(mpnt);
 			mm->total_vm -= pages;
-			__vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file,
+			vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file,
 								-pages);
 			continue;
 		}
@@ -253,12 +253,8 @@
 		}
 
 		/*
-		 * Link in the new vma and copy the page table entries:
-		 * link in first so that swapoff can see swap entries.
-		 * Note that, exceptionally, here the vma is inserted
-		 * without holding mm->mmap_sem.
+		 * Link in the new vma and copy the page table entries.
 		 */
-		spin_lock(&mm->page_table_lock);
 		*pprev = tmp;
 		pprev = &tmp->vm_next;
 
@@ -267,8 +263,7 @@
 		rb_parent = &tmp->vm_rb;
 
 		mm->map_count++;
-		retval = copy_page_range(mm, current->mm, tmp);
-		spin_unlock(&mm->page_table_lock);
+		retval = copy_page_range(mm, oldmm, tmp);
 
 		if (tmp->vm_ops && tmp->vm_ops->open)
 			tmp->vm_ops->open(tmp);
@@ -277,9 +272,9 @@
 			goto out;
 	}
 	retval = 0;
-
 out:
-	flush_tlb_mm(current->mm);
+	up_write(&mm->mmap_sem);
+	flush_tlb_mm(oldmm);
 	up_write(&oldmm->mmap_sem);
 	return retval;
 fail_nomem_policy:
@@ -323,6 +318,8 @@
 	INIT_LIST_HEAD(&mm->mmlist);
 	mm->core_waiters = 0;
 	mm->nr_ptes = 0;
+	set_mm_counter(mm, file_rss, 0);
+	set_mm_counter(mm, anon_rss, 0);
 	spin_lock_init(&mm->page_table_lock);
 	rwlock_init(&mm->ioctx_list_lock);
 	mm->ioctx_list = NULL;
@@ -499,7 +496,7 @@
 	if (retval)
 		goto free_pt;
 
-	mm->hiwater_rss = get_mm_counter(mm,rss);
+	mm->hiwater_rss = get_mm_rss(mm);
 	mm->hiwater_vm = mm->total_vm;
 
 good_mm:
diff --git a/kernel/futex.c b/kernel/futex.c
index ca05fe6..3b4d5ad 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -205,15 +205,13 @@
 	/*
 	 * Do a quick atomic lookup first - this is the fastpath.
 	 */
-	spin_lock(&current->mm->page_table_lock);
-	page = follow_page(mm, uaddr, 0);
+	page = follow_page(mm, uaddr, FOLL_TOUCH|FOLL_GET);
 	if (likely(page != NULL)) {
 		key->shared.pgoff =
 			page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-		spin_unlock(&current->mm->page_table_lock);
+		put_page(page);
 		return 0;
 	}
-	spin_unlock(&current->mm->page_table_lock);
 
 	/*
 	 * Do it the general way.
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 13bcec1..39277dd 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -18,6 +18,7 @@
 #include <linux/fs.h>
 #include <linux/err.h>
 #include <linux/proc_fs.h>
+#include <linux/sched.h>	/* for cond_resched */
 #include <linux/mm.h>
 
 #include <asm/sections.h>
diff --git a/kernel/kexec.c b/kernel/kexec.c
index cdd4dcd..2c95848 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -90,7 +90,7 @@
 static int kimage_is_destination_range(struct kimage *image,
 				       unsigned long start, unsigned long end);
 static struct page *kimage_alloc_page(struct kimage *image,
-				       unsigned int gfp_mask,
+				       gfp_t gfp_mask,
 				       unsigned long dest);
 
 static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
@@ -326,8 +326,7 @@
 	return 0;
 }
 
-static struct page *kimage_alloc_pages(unsigned int gfp_mask,
-					unsigned int order)
+static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
 {
 	struct page *pages;
 
@@ -335,7 +334,7 @@
 	if (pages) {
 		unsigned int count, i;
 		pages->mapping = NULL;
-		pages->private = order;
+		set_page_private(pages, order);
 		count = 1 << order;
 		for (i = 0; i < count; i++)
 			SetPageReserved(pages + i);
@@ -348,7 +347,7 @@
 {
 	unsigned int order, count, i;
 
-	order = page->private;
+	order = page_private(page);
 	count = 1 << order;
 	for (i = 0; i < count; i++)
 		ClearPageReserved(page + i);
@@ -654,7 +653,7 @@
 }
 
 static struct page *kimage_alloc_page(struct kimage *image,
-					unsigned int gfp_mask,
+					gfp_t gfp_mask,
 					unsigned long destination)
 {
 	/*
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 44166e3..51a8920 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -131,14 +131,14 @@
 static int ____call_usermodehelper(void *data)
 {
 	struct subprocess_info *sub_info = data;
-	struct key *old_session;
+	struct key *new_session, *old_session;
 	int retval;
 
 	/* Unblock all signals and set the session keyring. */
-	key_get(sub_info->ring);
+	new_session = key_get(sub_info->ring);
 	flush_signals(current);
 	spin_lock_irq(&current->sighand->siglock);
-	old_session = __install_session_keyring(current, sub_info->ring);
+	old_session = __install_session_keyring(current, new_session);
 	flush_signal_handlers(current, 1);
 	sigemptyset(&current->blocked);
 	recalc_sigpending();
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index f3ea492..ce4915d 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -35,6 +35,7 @@
 #include <linux/spinlock.h>
 #include <linux/hash.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <asm-generic/sections.h>
diff --git a/kernel/kthread.c b/kernel/kthread.c
index f50f174..e75950a 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -165,6 +165,12 @@
 
 int kthread_stop(struct task_struct *k)
 {
+	return kthread_stop_sem(k, NULL);
+}
+EXPORT_SYMBOL(kthread_stop);
+
+int kthread_stop_sem(struct task_struct *k, struct semaphore *s)
+{
 	int ret;
 
 	down(&kthread_stop_lock);
@@ -178,7 +184,10 @@
 
 	/* Now set kthread_should_stop() to true, and wake it up. */
 	kthread_stop_info.k = k;
-	wake_up_process(k);
+	if (s)
+		up(s);
+	else
+		wake_up_process(k);
 	put_task_struct(k);
 
 	/* Once it dies, reset stop ptr, gather result and we're done. */
@@ -189,7 +198,7 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(kthread_stop);
+EXPORT_SYMBOL(kthread_stop_sem);
 
 static __init int helper_init(void)
 {
diff --git a/kernel/params.c b/kernel/params.c
index 1a8614b..47ba695 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 #if 0
 #define DEBUGP printk
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index bf374fc..91a8942 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1225,7 +1225,7 @@
 		/*
 		 * The task was cleaned up already, no future firings.
 		 */
-		return;
+		goto out;
 
 	/*
 	 * Fetch the current sample and update the timer's expiry time.
@@ -1235,7 +1235,7 @@
 		bump_cpu_timer(timer, now);
 		if (unlikely(p->exit_state)) {
 			clear_dead_task(timer, now);
-			return;
+			goto out;
 		}
 		read_lock(&tasklist_lock); /* arm_timer needs it.  */
 	} else {
@@ -1248,8 +1248,7 @@
 			put_task_struct(p);
 			timer->it.cpu.task = p = NULL;
 			timer->it.cpu.expires.sched = 0;
-			read_unlock(&tasklist_lock);
-			return;
+			goto out_unlock;
 		} else if (unlikely(p->exit_state) && thread_group_empty(p)) {
 			/*
 			 * We've noticed that the thread is dead, but
@@ -1257,8 +1256,7 @@
 			 * drop our task ref.
 			 */
 			clear_dead_task(timer, now);
-			read_unlock(&tasklist_lock);
-			return;
+			goto out_unlock;
 		}
 		cpu_clock_sample_group(timer->it_clock, p, &now);
 		bump_cpu_timer(timer, now);
@@ -1270,7 +1268,13 @@
 	 */
 	arm_timer(timer, now);
 
+out_unlock:
 	read_unlock(&tasklist_lock);
+
+out:
+	timer->it_overrun_last = timer->it_overrun;
+	timer->it_overrun = -1;
+	++timer->it_requeue_pending;
 }
 
 /*
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index dda3cda..ea55c7a 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -1295,13 +1295,6 @@
 	return error;
 }
 
-static void nanosleep_wake_up(unsigned long __data)
-{
-	struct task_struct *p = (struct task_struct *) __data;
-
-	wake_up_process(p);
-}
-
 /*
  * The standard says that an absolute nanosleep call MUST wake up at
  * the requested time in spite of clock settings.  Here is what we do:
@@ -1442,7 +1435,6 @@
 			 int flags, struct timespec *tsave)
 {
 	struct timespec t, dum;
-	struct timer_list new_timer;
 	DECLARE_WAITQUEUE(abs_wqueue, current);
 	u64 rq_time = (u64)0;
 	s64 left;
@@ -1451,10 +1443,6 @@
 	    &current_thread_info()->restart_block;
 
 	abs_wqueue.flags = 0;
-	init_timer(&new_timer);
-	new_timer.expires = 0;
-	new_timer.data = (unsigned long) current;
-	new_timer.function = nanosleep_wake_up;
 	abs = flags & TIMER_ABSTIME;
 
 	if (restart_block->fn == clock_nanosleep_restart) {
@@ -1490,13 +1478,8 @@
 		if (left < (s64)0)
 			break;
 
-		new_timer.expires = jiffies + left;
-		__set_current_state(TASK_INTERRUPTIBLE);
-		add_timer(&new_timer);
+		schedule_timeout_interruptible(left);
 
-		schedule();
-
-		del_timer_sync(&new_timer);
 		left = rq_time - get_jiffies_64();
 	} while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING));
 
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 2f438d0..c71eb45 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -4,7 +4,7 @@
 endif
 
 obj-y				:= main.o process.o console.o pm.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o disk.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o disk.o snapshot.o
 
 obj-$(CONFIG_SUSPEND_SMP)	+= smp.o
 
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 761956e..027322a 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -30,7 +30,6 @@
 extern int swsusp_read(void);
 extern void swsusp_close(void);
 extern int swsusp_resume(void);
-extern int swsusp_free(void);
 
 
 static int noresume = 0;
@@ -93,10 +92,7 @@
 	printk("Freeing memory...  ");
 	while ((tmp = shrink_all_memory(10000))) {
 		pages += tmp;
-		printk("\b%c", p[i]);
-		i++;
-		if (i > 3)
-			i = 0;
+		printk("\b%c", p[i++ % 4]);
 	}
 	printk("\bdone (%li pages freed)\n", pages);
 }
@@ -178,13 +174,12 @@
 		goto Done;
 
 	if (in_suspend) {
+		device_resume();
 		pr_debug("PM: writing image.\n");
 		error = swsusp_write();
 		if (!error)
 			power_down(pm_disk_mode);
 		else {
-		/* swsusp_write can not fail in device_resume,
-		   no need to do second device_resume */
 			swsusp_free();
 			unprepare_processes();
 			return error;
@@ -252,14 +247,17 @@
 
 	pr_debug("PM: Reading swsusp image.\n");
 
-	if ((error = swsusp_read()))
-		goto Cleanup;
+	if ((error = swsusp_read())) {
+		swsusp_free();
+		goto Thaw;
+	}
 
 	pr_debug("PM: Preparing devices for restore.\n");
 
 	if ((error = device_suspend(PMSG_FREEZE))) {
 		printk("Some devices failed to suspend\n");
-		goto Free;
+		swsusp_free();
+		goto Thaw;
 	}
 
 	mb();
@@ -268,9 +266,7 @@
 	swsusp_resume();
 	pr_debug("PM: Restore failed, recovering.n");
 	device_resume();
- Free:
-	swsusp_free();
- Cleanup:
+ Thaw:
 	unprepare_processes();
  Done:
 	/* For success case, the suspend path will release the lock */
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 22bdc93..18d7d69 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -167,6 +167,8 @@
 {
 	int error;
 
+	if (pm_ops->valid && !pm_ops->valid(state))
+		return -ENODEV;
 	if (down_trylock(&pm_sem))
 		return -EBUSY;
 
@@ -236,7 +238,8 @@
 	char * s = buf;
 
 	for (i = 0; i < PM_SUSPEND_MAX; i++) {
-		if (pm_states[i])
+		if (pm_states[i] && pm_ops && (!pm_ops->valid
+			||(pm_ops->valid && pm_ops->valid(i))))
 			s += sprintf(s,"%s ",pm_states[i]);
 	}
 	s += sprintf(s,"\n");
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 6748de2..d4fd96a 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -53,3 +53,20 @@
 
 extern int pm_prepare_console(void);
 extern void pm_restore_console(void);
+
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+extern unsigned int nr_copy_pages;
+extern suspend_pagedir_t *pagedir_nosave;
+extern suspend_pagedir_t *pagedir_save;
+
+extern asmlinkage int swsusp_arch_suspend(void);
+extern asmlinkage int swsusp_arch_resume(void);
+
+extern int restore_highmem(void);
+extern struct pbe * alloc_pagedir(unsigned nr_pages);
+extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages);
+extern void swsusp_free(void);
+extern int enough_swap(unsigned nr_pages);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
new file mode 100644
index 0000000..42a6287
--- /dev/null
+++ b/kernel/power/snapshot.c
@@ -0,0 +1,435 @@
+/*
+ * linux/kernel/power/snapshot.c
+ *
+ * This file provide system snapshot/restore functionality.
+ *
+ * Copyright (C) 1998-2005 Pavel Machek <pavel@suse.cz>
+ *
+ * This file is released under the GPLv2, and is based on swsusp.c.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/suspend.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/syscalls.h>
+#include <linux/console.h>
+#include <linux/highmem.h>
+
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/io.h>
+
+#include "power.h"
+
+#ifdef CONFIG_HIGHMEM
+struct highmem_page {
+	char *data;
+	struct page *page;
+	struct highmem_page *next;
+};
+
+static struct highmem_page *highmem_copy;
+
+static int save_highmem_zone(struct zone *zone)
+{
+	unsigned long zone_pfn;
+	mark_free_pages(zone);
+	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
+		struct page *page;
+		struct highmem_page *save;
+		void *kaddr;
+		unsigned long pfn = zone_pfn + zone->zone_start_pfn;
+
+		if (!(pfn%1000))
+			printk(".");
+		if (!pfn_valid(pfn))
+			continue;
+		page = pfn_to_page(pfn);
+		/*
+		 * This condition results from rvmalloc() sans vmalloc_32()
+		 * and architectural memory reservations. This should be
+		 * corrected eventually when the cases giving rise to this
+		 * are better understood.
+		 */
+		if (PageReserved(page)) {
+			printk("highmem reserved page?!\n");
+			continue;
+		}
+		BUG_ON(PageNosave(page));
+		if (PageNosaveFree(page))
+			continue;
+		save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC);
+		if (!save)
+			return -ENOMEM;
+		save->next = highmem_copy;
+		save->page = page;
+		save->data = (void *) get_zeroed_page(GFP_ATOMIC);
+		if (!save->data) {
+			kfree(save);
+			return -ENOMEM;
+		}
+		kaddr = kmap_atomic(page, KM_USER0);
+		memcpy(save->data, kaddr, PAGE_SIZE);
+		kunmap_atomic(kaddr, KM_USER0);
+		highmem_copy = save;
+	}
+	return 0;
+}
+
+
+static int save_highmem(void)
+{
+	struct zone *zone;
+	int res = 0;
+
+	pr_debug("swsusp: Saving Highmem\n");
+	for_each_zone (zone) {
+		if (is_highmem(zone))
+			res = save_highmem_zone(zone);
+		if (res)
+			return res;
+	}
+	return 0;
+}
+
+int restore_highmem(void)
+{
+	printk("swsusp: Restoring Highmem\n");
+	while (highmem_copy) {
+		struct highmem_page *save = highmem_copy;
+		void *kaddr;
+		highmem_copy = save->next;
+
+		kaddr = kmap_atomic(save->page, KM_USER0);
+		memcpy(kaddr, save->data, PAGE_SIZE);
+		kunmap_atomic(kaddr, KM_USER0);
+		free_page((long) save->data);
+		kfree(save);
+	}
+	return 0;
+}
+#else
+static int save_highmem(void) { return 0; }
+int restore_highmem(void) { return 0; }
+#endif /* CONFIG_HIGHMEM */
+
+
+static int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+	unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
+	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
+
+/**
+ *	saveable - Determine whether a page should be cloned or not.
+ *	@pfn:	The page
+ *
+ *	We save a page if it's Reserved, and not in the range of pages
+ *	statically defined as 'unsaveable', or if it isn't reserved, and
+ *	isn't part of a free chunk of pages.
+ */
+
+static int saveable(struct zone *zone, unsigned long *zone_pfn)
+{
+	unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
+	struct page *page;
+
+	if (!pfn_valid(pfn))
+		return 0;
+
+	page = pfn_to_page(pfn);
+	BUG_ON(PageReserved(page) && PageNosave(page));
+	if (PageNosave(page))
+		return 0;
+	if (PageReserved(page) && pfn_is_nosave(pfn)) {
+		pr_debug("[nosave pfn 0x%lx]", pfn);
+		return 0;
+	}
+	if (PageNosaveFree(page))
+		return 0;
+
+	return 1;
+}
+
+static unsigned count_data_pages(void)
+{
+	struct zone *zone;
+	unsigned long zone_pfn;
+	unsigned n;
+
+	n = 0;
+	for_each_zone (zone) {
+		if (is_highmem(zone))
+			continue;
+		mark_free_pages(zone);
+		for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
+			n += saveable(zone, &zone_pfn);
+	}
+	return n;
+}
+
+static void copy_data_pages(struct pbe *pblist)
+{
+	struct zone *zone;
+	unsigned long zone_pfn;
+	struct pbe *pbe, *p;
+
+	pbe = pblist;
+	for_each_zone (zone) {
+		if (is_highmem(zone))
+			continue;
+		mark_free_pages(zone);
+		/* This is necessary for swsusp_free() */
+		for_each_pb_page (p, pblist)
+			SetPageNosaveFree(virt_to_page(p));
+		for_each_pbe (p, pblist)
+			SetPageNosaveFree(virt_to_page(p->address));
+		for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
+			if (saveable(zone, &zone_pfn)) {
+				struct page *page;
+				page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
+				BUG_ON(!pbe);
+				pbe->orig_address = (unsigned long)page_address(page);
+				/* copy_page is not usable for copying task structs. */
+				memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
+				pbe = pbe->next;
+			}
+		}
+	}
+	BUG_ON(pbe);
+}
+
+
+/**
+ *	free_pagedir - free pages allocated with alloc_pagedir()
+ */
+
+static void free_pagedir(struct pbe *pblist)
+{
+	struct pbe *pbe;
+
+	while (pblist) {
+		pbe = (pblist + PB_PAGE_SKIP)->next;
+		ClearPageNosave(virt_to_page(pblist));
+		ClearPageNosaveFree(virt_to_page(pblist));
+		free_page((unsigned long)pblist);
+		pblist = pbe;
+	}
+}
+
+/**
+ *	fill_pb_page - Create a list of PBEs on a given memory page
+ */
+
+static inline void fill_pb_page(struct pbe *pbpage)
+{
+	struct pbe *p;
+
+	p = pbpage;
+	pbpage += PB_PAGE_SKIP;
+	do
+		p->next = p + 1;
+	while (++p < pbpage);
+}
+
+/**
+ *	create_pbe_list - Create a list of PBEs on top of a given chain
+ *	of memory pages allocated with alloc_pagedir()
+ */
+
+void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
+{
+	struct pbe *pbpage, *p;
+	unsigned num = PBES_PER_PAGE;
+
+	for_each_pb_page (pbpage, pblist) {
+		if (num >= nr_pages)
+			break;
+
+		fill_pb_page(pbpage);
+		num += PBES_PER_PAGE;
+	}
+	if (pbpage) {
+		for (num -= PBES_PER_PAGE - 1, p = pbpage; num < nr_pages; p++, num++)
+			p->next = p + 1;
+		p->next = NULL;
+	}
+	pr_debug("create_pbe_list(): initialized %d PBEs\n", num);
+}
+
+static void *alloc_image_page(void)
+{
+	void *res = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
+	if (res) {
+		SetPageNosave(virt_to_page(res));
+		SetPageNosaveFree(virt_to_page(res));
+	}
+	return res;
+}
+
+/**
+ *	alloc_pagedir - Allocate the page directory.
+ *
+ *	First, determine exactly how many pages we need and
+ *	allocate them.
+ *
+ *	We arrange the pages in a chain: each page is an array of PBES_PER_PAGE
+ *	struct pbe elements (pbes) and the last element in the page points
+ *	to the next page.
+ *
+ *	On each page we set up a list of struct_pbe elements.
+ */
+
+struct pbe *alloc_pagedir(unsigned nr_pages)
+{
+	unsigned num;
+	struct pbe *pblist, *pbe;
+
+	if (!nr_pages)
+		return NULL;
+
+	pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages);
+	pblist = alloc_image_page();
+	/* FIXME: rewrite this ugly loop */
+	for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages;
+        		pbe = pbe->next, num += PBES_PER_PAGE) {
+		pbe += PB_PAGE_SKIP;
+		pbe->next = alloc_image_page();
+	}
+	if (!pbe) { /* get_zeroed_page() failed */
+		free_pagedir(pblist);
+		pblist = NULL;
+        }
+	return pblist;
+}
+
+/**
+ * Free pages we allocated for suspend. Suspend pages are alocated
+ * before atomic copy, so we need to free them after resume.
+ */
+
+void swsusp_free(void)
+{
+	struct zone *zone;
+	unsigned long zone_pfn;
+
+	for_each_zone(zone) {
+		for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
+			if (pfn_valid(zone_pfn + zone->zone_start_pfn)) {
+				struct page * page;
+				page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
+				if (PageNosave(page) && PageNosaveFree(page)) {
+					ClearPageNosave(page);
+					ClearPageNosaveFree(page);
+					free_page((long) page_address(page));
+				}
+			}
+	}
+}
+
+
+/**
+ *	enough_free_mem - Make sure we enough free memory to snapshot.
+ *
+ *	Returns TRUE or FALSE after checking the number of available
+ *	free pages.
+ */
+
+static int enough_free_mem(unsigned nr_pages)
+{
+	pr_debug("swsusp: available memory: %u pages\n", nr_free_pages());
+	return nr_free_pages() > (nr_pages + PAGES_FOR_IO +
+		(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
+}
+
+
+static struct pbe *swsusp_alloc(unsigned nr_pages)
+{
+	struct pbe *pblist, *p;
+
+	if (!(pblist = alloc_pagedir(nr_pages))) {
+		printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
+		return NULL;
+	}
+	create_pbe_list(pblist, nr_pages);
+
+	for_each_pbe (p, pblist) {
+		p->address = (unsigned long)alloc_image_page();
+		if (!p->address) {
+			printk(KERN_ERR "suspend: Allocating image pages failed.\n");
+			swsusp_free();
+			return NULL;
+		}
+	}
+
+	return pblist;
+}
+
+asmlinkage int swsusp_save(void)
+{
+	unsigned nr_pages;
+
+	pr_debug("swsusp: critical section: \n");
+	if (save_highmem()) {
+		printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n");
+		restore_highmem();
+		return -ENOMEM;
+	}
+
+	drain_local_pages();
+	nr_pages = count_data_pages();
+	printk("swsusp: Need to copy %u pages\n", nr_pages);
+
+	pr_debug("swsusp: pages needed: %u + %lu + %u, free: %u\n",
+		 nr_pages,
+		 (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE,
+		 PAGES_FOR_IO, nr_free_pages());
+
+	/* This is needed because of the fixed size of swsusp_info */
+	if (MAX_PBES < (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE)
+		return -ENOSPC;
+
+	if (!enough_free_mem(nr_pages)) {
+		printk(KERN_ERR "swsusp: Not enough free memory\n");
+		return -ENOMEM;
+	}
+
+	if (!enough_swap(nr_pages)) {
+		printk(KERN_ERR "swsusp: Not enough free swap\n");
+		return -ENOSPC;
+	}
+
+	pagedir_nosave = swsusp_alloc(nr_pages);
+	if (!pagedir_nosave)
+		return -ENOMEM;
+
+	/* During allocating of suspend pagedir, new cold pages may appear.
+	 * Kill them.
+	 */
+	drain_local_pages();
+	copy_data_pages(pagedir_nosave);
+
+	/*
+	 * End of critical section. From now on, we can write to memory,
+	 * but we should not touch disk. This specially means we must _not_
+	 * touch swap space! Except we must write out our image of course.
+	 */
+
+	nr_copy_pages = nr_pages;
+
+	printk("swsusp: critical section/: done (%d pages copied)\n", nr_pages);
+	return 0;
+}
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 2d5c456..12db1d2 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -1,11 +1,10 @@
 /*
  * linux/kernel/power/swsusp.c
  *
- * This file is to realize architecture-independent
- * machine suspend feature using pretty near only high-level routines
+ * This file provides code to write suspend image to swap and read it back.
  *
  * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
- * Copyright (C) 1998,2001-2004 Pavel Machek <pavel@suse.cz>
+ * Copyright (C) 1998,2001-2005 Pavel Machek <pavel@suse.cz>
  *
  * This file is released under the GPLv2.
  *
@@ -47,11 +46,7 @@
 #include <linux/utsname.h>
 #include <linux/version.h>
 #include <linux/delay.h>
-#include <linux/reboot.h>
 #include <linux/bitops.h>
-#include <linux/vt_kern.h>
-#include <linux/kbd_kern.h>
-#include <linux/keyboard.h>
 #include <linux/spinlock.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
@@ -63,10 +58,8 @@
 #include <linux/swapops.h>
 #include <linux/bootmem.h>
 #include <linux/syscalls.h>
-#include <linux/console.h>
 #include <linux/highmem.h>
 #include <linux/bio.h>
-#include <linux/mount.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -84,16 +77,10 @@
 #define MAXKEY 32
 #define MAXIV  32
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
-/* Variables to be preserved over suspend */
-static int nr_copy_pages_check;
-
 extern char resume_file[];
 
 /* Local variables that should not be affected by save */
-static unsigned int nr_copy_pages __nosavedata = 0;
+unsigned int nr_copy_pages __nosavedata = 0;
 
 /* Suspend pagedir is allocated before final copy, therefore it
    must be freed after resume
@@ -109,7 +96,7 @@
    MMU hardware.
  */
 suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
-static suspend_pagedir_t *pagedir_save;
+suspend_pagedir_t *pagedir_save;
 
 #define SWSUSP_SIG	"S1SUSPEND"
 
@@ -124,12 +111,6 @@
 static struct swsusp_info swsusp_info;
 
 /*
- * XXX: We try to keep some more pages free so that I/O operations succeed
- * without paging. Might this be more?
- */
-#define PAGES_FOR_IO	512
-
-/*
  * Saving part...
  */
 
@@ -552,346 +533,6 @@
 	goto Done;
 }
 
-
-#ifdef CONFIG_HIGHMEM
-struct highmem_page {
-	char *data;
-	struct page *page;
-	struct highmem_page *next;
-};
-
-static struct highmem_page *highmem_copy;
-
-static int save_highmem_zone(struct zone *zone)
-{
-	unsigned long zone_pfn;
-	mark_free_pages(zone);
-	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
-		struct page *page;
-		struct highmem_page *save;
-		void *kaddr;
-		unsigned long pfn = zone_pfn + zone->zone_start_pfn;
-
-		if (!(pfn%1000))
-			printk(".");
-		if (!pfn_valid(pfn))
-			continue;
-		page = pfn_to_page(pfn);
-		/*
-		 * This condition results from rvmalloc() sans vmalloc_32()
-		 * and architectural memory reservations. This should be
-		 * corrected eventually when the cases giving rise to this
-		 * are better understood.
-		 */
-		if (PageReserved(page)) {
-			printk("highmem reserved page?!\n");
-			continue;
-		}
-		BUG_ON(PageNosave(page));
-		if (PageNosaveFree(page))
-			continue;
-		save = kmalloc(sizeof(struct highmem_page), GFP_ATOMIC);
-		if (!save)
-			return -ENOMEM;
-		save->next = highmem_copy;
-		save->page = page;
-		save->data = (void *) get_zeroed_page(GFP_ATOMIC);
-		if (!save->data) {
-			kfree(save);
-			return -ENOMEM;
-		}
-		kaddr = kmap_atomic(page, KM_USER0);
-		memcpy(save->data, kaddr, PAGE_SIZE);
-		kunmap_atomic(kaddr, KM_USER0);
-		highmem_copy = save;
-	}
-	return 0;
-}
-#endif /* CONFIG_HIGHMEM */
-
-
-static int save_highmem(void)
-{
-#ifdef CONFIG_HIGHMEM
-	struct zone *zone;
-	int res = 0;
-
-	pr_debug("swsusp: Saving Highmem\n");
-	for_each_zone (zone) {
-		if (is_highmem(zone))
-			res = save_highmem_zone(zone);
-		if (res)
-			return res;
-	}
-#endif
-	return 0;
-}
-
-static int restore_highmem(void)
-{
-#ifdef CONFIG_HIGHMEM
-	printk("swsusp: Restoring Highmem\n");
-	while (highmem_copy) {
-		struct highmem_page *save = highmem_copy;
-		void *kaddr;
-		highmem_copy = save->next;
-
-		kaddr = kmap_atomic(save->page, KM_USER0);
-		memcpy(kaddr, save->data, PAGE_SIZE);
-		kunmap_atomic(kaddr, KM_USER0);
-		free_page((long) save->data);
-		kfree(save);
-	}
-#endif
-	return 0;
-}
-
-
-static int pfn_is_nosave(unsigned long pfn)
-{
-	unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
-	unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
-	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
-}
-
-/**
- *	saveable - Determine whether a page should be cloned or not.
- *	@pfn:	The page
- *
- *	We save a page if it's Reserved, and not in the range of pages
- *	statically defined as 'unsaveable', or if it isn't reserved, and
- *	isn't part of a free chunk of pages.
- */
-
-static int saveable(struct zone * zone, unsigned long * zone_pfn)
-{
-	unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
-	struct page * page;
-
-	if (!pfn_valid(pfn))
-		return 0;
-
-	page = pfn_to_page(pfn);
-	BUG_ON(PageReserved(page) && PageNosave(page));
-	if (PageNosave(page))
-		return 0;
-	if (PageReserved(page) && pfn_is_nosave(pfn)) {
-		pr_debug("[nosave pfn 0x%lx]", pfn);
-		return 0;
-	}
-	if (PageNosaveFree(page))
-		return 0;
-
-	return 1;
-}
-
-static void count_data_pages(void)
-{
-	struct zone *zone;
-	unsigned long zone_pfn;
-
-	nr_copy_pages = 0;
-
-	for_each_zone (zone) {
-		if (is_highmem(zone))
-			continue;
-		mark_free_pages(zone);
-		for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
-			nr_copy_pages += saveable(zone, &zone_pfn);
-	}
-}
-
-
-static void copy_data_pages(void)
-{
-	struct zone *zone;
-	unsigned long zone_pfn;
-	struct pbe * pbe = pagedir_nosave;
-
-	pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages);
-	for_each_zone (zone) {
-		if (is_highmem(zone))
-			continue;
-		mark_free_pages(zone);
-		for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
-			if (saveable(zone, &zone_pfn)) {
-				struct page * page;
-				page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
-				BUG_ON(!pbe);
-				pbe->orig_address = (long) page_address(page);
-				/* copy_page is not usable for copying task structs. */
-				memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
-				pbe = pbe->next;
-			}
-		}
-	}
-	BUG_ON(pbe);
-}
-
-
-/**
- *	calc_nr - Determine the number of pages needed for a pbe list.
- */
-
-static int calc_nr(int nr_copy)
-{
-	return nr_copy + (nr_copy+PBES_PER_PAGE-2)/(PBES_PER_PAGE-1);
-}
-
-/**
- *	free_pagedir - free pages allocated with alloc_pagedir()
- */
-
-static inline void free_pagedir(struct pbe *pblist)
-{
-	struct pbe *pbe;
-
-	while (pblist) {
-		pbe = (pblist + PB_PAGE_SKIP)->next;
-		free_page((unsigned long)pblist);
-		pblist = pbe;
-	}
-}
-
-/**
- *	fill_pb_page - Create a list of PBEs on a given memory page
- */
-
-static inline void fill_pb_page(struct pbe *pbpage)
-{
-	struct pbe *p;
-
-	p = pbpage;
-	pbpage += PB_PAGE_SKIP;
-	do
-		p->next = p + 1;
-	while (++p < pbpage);
-}
-
-/**
- *	create_pbe_list - Create a list of PBEs on top of a given chain
- *	of memory pages allocated with alloc_pagedir()
- */
-
-static void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
-{
-	struct pbe *pbpage, *p;
-	unsigned num = PBES_PER_PAGE;
-
-	for_each_pb_page (pbpage, pblist) {
-		if (num >= nr_pages)
-			break;
-
-		fill_pb_page(pbpage);
-		num += PBES_PER_PAGE;
-	}
-	if (pbpage) {
-		for (num -= PBES_PER_PAGE - 1, p = pbpage; num < nr_pages; p++, num++)
-			p->next = p + 1;
-		p->next = NULL;
-	}
-	pr_debug("create_pbe_list(): initialized %d PBEs\n", num);
-}
-
-/**
- *	alloc_pagedir - Allocate the page directory.
- *
- *	First, determine exactly how many pages we need and
- *	allocate them.
- *
- *	We arrange the pages in a chain: each page is an array of PBES_PER_PAGE
- *	struct pbe elements (pbes) and the last element in the page points
- *	to the next page.
- *
- *	On each page we set up a list of struct_pbe elements.
- */
-
-static struct pbe * alloc_pagedir(unsigned nr_pages)
-{
-	unsigned num;
-	struct pbe *pblist, *pbe;
-
-	if (!nr_pages)
-		return NULL;
-
-	pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages);
-	pblist = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
-	for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages;
-        		pbe = pbe->next, num += PBES_PER_PAGE) {
-		pbe += PB_PAGE_SKIP;
-		pbe->next = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
-	}
-	if (!pbe) { /* get_zeroed_page() failed */
-		free_pagedir(pblist);
-		pblist = NULL;
-        }
-	return pblist;
-}
-
-/**
- *	free_image_pages - Free pages allocated for snapshot
- */
-
-static void free_image_pages(void)
-{
-	struct pbe * p;
-
-	for_each_pbe (p, pagedir_save) {
-		if (p->address) {
-			ClearPageNosave(virt_to_page(p->address));
-			free_page(p->address);
-			p->address = 0;
-		}
-	}
-}
-
-/**
- *	alloc_image_pages - Allocate pages for the snapshot.
- */
-
-static int alloc_image_pages(void)
-{
-	struct pbe * p;
-
-	for_each_pbe (p, pagedir_save) {
-		p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
-		if (!p->address)
-			return -ENOMEM;
-		SetPageNosave(virt_to_page(p->address));
-	}
-	return 0;
-}
-
-/* Free pages we allocated for suspend. Suspend pages are alocated
- * before atomic copy, so we need to free them after resume.
- */
-void swsusp_free(void)
-{
-	BUG_ON(PageNosave(virt_to_page(pagedir_save)));
-	BUG_ON(PageNosaveFree(virt_to_page(pagedir_save)));
-	free_image_pages();
-	free_pagedir(pagedir_save);
-}
-
-
-/**
- *	enough_free_mem - Make sure we enough free memory to snapshot.
- *
- *	Returns TRUE or FALSE after checking the number of available
- *	free pages.
- */
-
-static int enough_free_mem(void)
-{
-	if (nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
-		pr_debug("swsusp: Not enough free pages: Have %d\n",
-			 nr_free_pages());
-		return 0;
-	}
-	return 1;
-}
-
-
 /**
  *	enough_swap - Make sure we have enough swap to save the image.
  *
@@ -902,87 +543,14 @@
  *	We should only consider resume_device.
  */
 
-static int enough_swap(void)
+int enough_swap(unsigned nr_pages)
 {
 	struct sysinfo i;
 
 	si_swapinfo(&i);
-	if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO))  {
-		pr_debug("swsusp: Not enough swap. Need %ld\n",i.freeswap);
-		return 0;
-	}
-	return 1;
-}
-
-static int swsusp_alloc(void)
-{
-	int error;
-
-	pagedir_nosave = NULL;
-	nr_copy_pages = calc_nr(nr_copy_pages);
-	nr_copy_pages_check = nr_copy_pages;
-
-	pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
-		 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
-
-	if (!enough_free_mem())
-		return -ENOMEM;
-
-	if (!enough_swap())
-		return -ENOSPC;
-
-	if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE +
-	    !!(nr_copy_pages % PBES_PER_PAGE))
-		return -ENOSPC;
-
-	if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
-		printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
-		return -ENOMEM;
-	}
-	create_pbe_list(pagedir_save, nr_copy_pages);
-	pagedir_nosave = pagedir_save;
-	if ((error = alloc_image_pages())) {
-		printk(KERN_ERR "suspend: Allocating image pages failed.\n");
-		swsusp_free();
-		return error;
-	}
-
-	return 0;
-}
-
-static int suspend_prepare_image(void)
-{
-	int error;
-
-	pr_debug("swsusp: critical section: \n");
-	if (save_highmem()) {
-		printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n");
-		restore_highmem();
-		return -ENOMEM;
-	}
-
-	drain_local_pages();
-	count_data_pages();
-	printk("swsusp: Need to copy %u pages\n", nr_copy_pages);
-
-	error = swsusp_alloc();
-	if (error)
-		return error;
-
-	/* During allocating of suspend pagedir, new cold pages may appear.
-	 * Kill them.
-	 */
-	drain_local_pages();
-	copy_data_pages();
-
-	/*
-	 * End of critical section. From now on, we can write to memory,
-	 * but we should not touch disk. This specially means we must _not_
-	 * touch swap space! Except we must write out our image of course.
-	 */
-
-	printk("swsusp: critical section/: done (%d pages copied)\n", nr_copy_pages );
-	return 0;
+	pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
+	return i.freeswap > (nr_pages + PAGES_FOR_IO +
+		(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
 }
 
 
@@ -994,7 +562,7 @@
 int swsusp_write(void)
 {
 	int error;
-	device_resume();
+
 	lock_swapdevices();
 	error = write_suspend_image();
 	/* This will unlock ignored swap devices since writing is finished */
@@ -1004,14 +572,6 @@
 }
 
 
-extern asmlinkage int swsusp_arch_suspend(void);
-extern asmlinkage int swsusp_arch_resume(void);
-
-
-asmlinkage int swsusp_save(void)
-{
-	return suspend_prepare_image();
-}
 
 int swsusp_suspend(void)
 {
@@ -1043,7 +603,6 @@
 		printk(KERN_ERR "Error %d suspending\n", error);
 	/* Restore control flow magically appears here */
 	restore_processor_state();
-	BUG_ON (nr_copy_pages_check != nr_copy_pages);
 	restore_highmem();
 	device_power_up();
 	local_irq_enable();
@@ -1063,6 +622,11 @@
 	 * execution continues at place where swsusp_arch_suspend was called
          */
 	BUG_ON(!error);
+	/* The only reason why swsusp_arch_resume() can fail is memory being
+	 * very tight, so we have to free it as soon as we can to avoid
+	 * subsequent failures
+	 */
+	swsusp_free();
 	restore_processor_state();
 	restore_highmem();
 	touch_softlockup_watchdog();
@@ -1078,54 +642,28 @@
  *
  *	We don't know which pages are usable until we allocate them.
  *
- *	Allocated but unusable (ie eaten) memory pages are linked together
- *	to create a list, so that we can free them easily
- *
- *	We could have used a type other than (void *)
- *	for this purpose, but ...
+ *	Allocated but unusable (ie eaten) memory pages are marked so that
+ *	swsusp_free() can release them
  */
-static void **eaten_memory = NULL;
 
-static inline void eat_page(void *page)
-{
-	void **c;
-
-	c = eaten_memory;
-	eaten_memory = page;
-	*eaten_memory = c;
-}
-
-unsigned long get_usable_page(unsigned gfp_mask)
+unsigned long get_safe_page(gfp_t gfp_mask)
 {
 	unsigned long m;
 
-	m = get_zeroed_page(gfp_mask);
-	while (!PageNosaveFree(virt_to_page(m))) {
-		eat_page((void *)m);
+	do {
 		m = get_zeroed_page(gfp_mask);
-		if (!m)
-			break;
+		if (m && PageNosaveFree(virt_to_page(m)))
+			/* This is for swsusp_free() */
+			SetPageNosave(virt_to_page(m));
+	} while (m && PageNosaveFree(virt_to_page(m)));
+	if (m) {
+		/* This is for swsusp_free() */
+		SetPageNosave(virt_to_page(m));
+		SetPageNosaveFree(virt_to_page(m));
 	}
 	return m;
 }
 
-void free_eaten_memory(void)
-{
-	unsigned long m;
-	void **c;
-	int i = 0;
-
-	c = eaten_memory;
-	while (c) {
-		m = (unsigned long)c;
-		c = *c;
-		free_page(m);
-		i++;
-	}
-	eaten_memory = NULL;
-	pr_debug("swsusp: %d unused pages freed\n", i);
-}
-
 /**
  *	check_pagedir - We ensure here that pages that the PBEs point to
  *	won't collide with pages where we're going to restore from the loaded
@@ -1143,7 +681,7 @@
 		p->address = 0UL;
 
 	for_each_pbe (p, pblist) {
-		p->address = get_usable_page(GFP_ATOMIC);
+		p->address = get_safe_page(GFP_ATOMIC);
 		if (!p->address)
 			return -ENOMEM;
 	}
@@ -1162,7 +700,7 @@
 	unsigned long zone_pfn;
 	struct pbe *pbpage, *tail, *p;
 	void *m;
-	int rel = 0, error = 0;
+	int rel = 0;
 
 	if (!pblist) /* a sanity check */
 		return NULL;
@@ -1170,41 +708,37 @@
 	pr_debug("swsusp: Relocating pagedir (%lu pages to check)\n",
 			swsusp_info.pagedir_pages);
 
-	/* Set page flags */
+	/* Clear page flags */
 
 	for_each_zone (zone) {
         	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
-                	SetPageNosaveFree(pfn_to_page(zone_pfn +
+        		if (pfn_valid(zone_pfn + zone->zone_start_pfn))
+                		ClearPageNosaveFree(pfn_to_page(zone_pfn +
 					zone->zone_start_pfn));
 	}
 
-	/* Clear orig addresses */
+	/* Mark orig addresses */
 
 	for_each_pbe (p, pblist)
-		ClearPageNosaveFree(virt_to_page(p->orig_address));
+		SetPageNosaveFree(virt_to_page(p->orig_address));
 
 	tail = pblist + PB_PAGE_SKIP;
 
 	/* Relocate colliding pages */
 
 	for_each_pb_page (pbpage, pblist) {
-		if (!PageNosaveFree(virt_to_page((unsigned long)pbpage))) {
-			m = (void *)get_usable_page(GFP_ATOMIC | __GFP_COLD);
-			if (!m) {
-				error = -ENOMEM;
-				break;
-			}
+		if (PageNosaveFree(virt_to_page((unsigned long)pbpage))) {
+			m = (void *)get_safe_page(GFP_ATOMIC | __GFP_COLD);
+			if (!m)
+				return NULL;
 			memcpy(m, (void *)pbpage, PAGE_SIZE);
 			if (pbpage == pblist)
 				pblist = (struct pbe *)m;
 			else
 				tail->next = (struct pbe *)m;
-
-			eat_page((void *)pbpage);
 			pbpage = (struct pbe *)m;
 
 			/* We have to link the PBEs again */
-
 			for (p = pbpage; p < pbpage + PB_PAGE_SKIP; p++)
 				if (p->next) /* needed to save the end */
 					p->next = p + 1;
@@ -1214,15 +748,13 @@
 		tail = pbpage + PB_PAGE_SKIP;
 	}
 
-	if (error) {
-		printk("\nswsusp: Out of memory\n\n");
-		free_pagedir(pblist);
-		free_eaten_memory();
-		pblist = NULL;
-		/* Is this even worth handling? It should never ever happen, and we
-		   have just lost user's state, anyway... */
-	} else
-		printk("swsusp: Relocated %d pages\n", rel);
+	/* This is for swsusp_free() */
+	for_each_pb_page (pbpage, pblist) {
+		SetPageNosave(virt_to_page(pbpage));
+		SetPageNosaveFree(virt_to_page(pbpage));
+	}
+
+	printk("swsusp: Relocated %d pages\n", rel);
 
 	return pblist;
 }
@@ -1440,9 +972,7 @@
 			break;
 	}
 
-	if (error)
-		free_pagedir(pblist);
-	else
+	if (!error)
 		BUG_ON(i != swsusp_info.pagedir_pages);
 
 	return error;
@@ -1485,15 +1015,6 @@
 	if (!error)
 		error = data_read(pagedir_nosave);
 
-	if (error) { /* We fail cleanly */
-		free_eaten_memory();
-		for_each_pbe (p, pagedir_nosave)
-			if (p->address) {
-				free_page(p->address);
-				p->address = 0UL;
-			}
-		free_pagedir(pagedir_nosave);
-	}
 	return error;
 }
 
diff --git a/kernel/printk.c b/kernel/printk.c
index 4b8f0f9..3cb9708 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -10,7 +10,7 @@
  * elsewhere, in preparation for a serial line console (someday).
  * Ted Ts'o, 2/11/93.
  * Modified for sysctl support, 1/8/97, Chris Horn.
- * Fixed SMP synchronization, 08/08/99, Manfred Spraul 
+ * Fixed SMP synchronization, 08/08/99, Manfred Spraul
  *     manfreds@colorfullife.com
  * Rewrote bits to get rid of console_lock
  *	01Mar01 Andrew Morton <andrewm@uow.edu.au>
@@ -148,7 +148,7 @@
 	if (!strcmp(str, "ttyb"))
 		strcpy(name, "ttyS1");
 #endif
-	for(s = name; *s; s++)
+	for (s = name; *s; s++)
 		if ((*s >= '0' && *s <= '9') || *s == ',')
 			break;
 	idx = simple_strtoul(s, NULL, 10);
@@ -169,11 +169,11 @@
 		size = roundup_pow_of_two(size);
 	if (size > log_buf_len) {
 		unsigned long start, dest_idx, offset;
-		char * new_log_buf;
+		char *new_log_buf;
 
 		new_log_buf = alloc_bootmem(size);
 		if (!new_log_buf) {
-			printk("log_buf_len: allocation failed\n");
+			printk(KERN_WARNING "log_buf_len: allocation failed\n");
 			goto out;
 		}
 
@@ -193,10 +193,9 @@
 		log_end -= offset;
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 
-		printk("log_buf_len: %d\n", log_buf_len);
+		printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);
 	}
 out:
-
 	return 1;
 }
 
@@ -217,7 +216,7 @@
  *	9 -- Return number of unread characters in the log buffer
  *     10 -- Return size of the log buffer
  */
-int do_syslog(int type, char __user * buf, int len)
+int do_syslog(int type, char __user *buf, int len)
 {
 	unsigned long i, j, limit, count;
 	int do_clear = 0;
@@ -244,7 +243,8 @@
 			error = -EFAULT;
 			goto out;
 		}
-		error = wait_event_interruptible(log_wait, (log_start - log_end));
+		error = wait_event_interruptible(log_wait,
+							(log_start - log_end));
 		if (error)
 			goto out;
 		i = 0;
@@ -264,7 +264,7 @@
 			error = i;
 		break;
 	case 4:		/* Read/clear last kernel messages */
-		do_clear = 1; 
+		do_clear = 1;
 		/* FALL THRU */
 	case 3:		/* Read last kernel messages */
 		error = -EINVAL;
@@ -288,11 +288,11 @@
 		limit = log_end;
 		/*
 		 * __put_user() could sleep, and while we sleep
-		 * printk() could overwrite the messages 
+		 * printk() could overwrite the messages
 		 * we try to copy to user space. Therefore
 		 * the messages are copied in reverse. <manfreds>
 		 */
-		for(i = 0; i < count && !error; i++) {
+		for (i = 0; i < count && !error; i++) {
 			j = limit-1-i;
 			if (j + log_buf_len < log_end)
 				break;
@@ -306,10 +306,10 @@
 		if (error)
 			break;
 		error = i;
-		if(i != count) {
+		if (i != count) {
 			int offset = count-error;
 			/* buffer overflow during copy, correct user buffer. */
-			for(i=0;i<error;i++) {
+			for (i = 0; i < error; i++) {
 				if (__get_user(c,&buf[i+offset]) ||
 				    __put_user(c,&buf[i])) {
 					error = -EFAULT;
@@ -351,7 +351,7 @@
 	return error;
 }
 
-asmlinkage long sys_syslog(int type, char __user * buf, int len)
+asmlinkage long sys_syslog(int type, char __user *buf, int len)
 {
 	return do_syslog(type, buf, len);
 }
@@ -404,21 +404,19 @@
 	cur_index = start;
 	start_print = start;
 	while (cur_index != end) {
-		if (	msg_level < 0 &&
-			((end - cur_index) > 2) &&
-			LOG_BUF(cur_index + 0) == '<' &&
-			LOG_BUF(cur_index + 1) >= '0' &&
-			LOG_BUF(cur_index + 1) <= '7' &&
-			LOG_BUF(cur_index + 2) == '>')
-		{
+		if (msg_level < 0 && ((end - cur_index) > 2) &&
+				LOG_BUF(cur_index + 0) == '<' &&
+				LOG_BUF(cur_index + 1) >= '0' &&
+				LOG_BUF(cur_index + 1) <= '7' &&
+				LOG_BUF(cur_index + 2) == '>') {
 			msg_level = LOG_BUF(cur_index + 1) - '0';
 			cur_index += 3;
 			start_print = cur_index;
 		}
 		while (cur_index != end) {
 			char c = LOG_BUF(cur_index);
-			cur_index++;
 
+			cur_index++;
 			if (c == '\n') {
 				if (msg_level < 0) {
 					/*
@@ -461,7 +459,7 @@
 	static unsigned long oops_timestamp;
 
 	if (time_after_eq(jiffies, oops_timestamp) &&
-			!time_after(jiffies, oops_timestamp + 30*HZ))
+			!time_after(jiffies, oops_timestamp + 30 * HZ))
 		return;
 
 	oops_timestamp = jiffies;
@@ -495,7 +493,7 @@
 
 /*
  * This is printk.  It can be called from any context.  We want it to work.
- * 
+ *
  * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
  * call the console drivers.  If we fail to get the semaphore we place the output
  * into the log buffer and return.  The current holder of the console_sem will
@@ -639,13 +637,19 @@
 
 #else
 
-asmlinkage long sys_syslog(int type, char __user * buf, int len)
+asmlinkage long sys_syslog(int type, char __user *buf, int len)
 {
 	return 0;
 }
 
-int do_syslog(int type, char __user * buf, int len) { return 0; }
-static void call_console_drivers(unsigned long start, unsigned long end) {}
+int do_syslog(int type, char __user *buf, int len)
+{
+	return 0;
+}
+
+static void call_console_drivers(unsigned long start, unsigned long end)
+{
+}
 
 #endif
 
@@ -851,9 +855,9 @@
  * print any messages that were printed by the kernel before the
  * console driver was initialized.
  */
-void register_console(struct console * console)
+void register_console(struct console *console)
 {
-	int     i;
+	int i;
 	unsigned long flags;
 
 	if (preferred_console < 0)
@@ -878,7 +882,8 @@
 	 *	See if this console matches one we selected on
 	 *	the command line.
 	 */
-	for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
+	for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
+			i++) {
 		if (strcmp(console_cmdline[i].name, console->name) != 0)
 			continue;
 		if (console->index >= 0 &&
@@ -933,9 +938,9 @@
 }
 EXPORT_SYMBOL(register_console);
 
-int unregister_console(struct console * console)
+int unregister_console(struct console *console)
 {
-        struct console *a,*b;
+        struct console *a, *b;
 	int res = 1;
 
 	acquire_console_sem();
@@ -949,10 +954,10 @@
 				b->next = a->next;
 				res = 0;
 				break;
-			}  
+			}
 		}
 	}
-	
+
 	/* If last console is removed, we re-enable picking the first
 	 * one that gets registered. Without that, pmac early boot console
 	 * would prevent fbcon from taking over.
@@ -994,7 +999,7 @@
 int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
 {
 	static DEFINE_SPINLOCK(ratelimit_lock);
-	static unsigned long toks = 10*5*HZ;
+	static unsigned long toks = 10 * 5 * HZ;
 	static unsigned long last_msg;
 	static int missed;
 	unsigned long flags;
@@ -1007,6 +1012,7 @@
 		toks = ratelimit_burst * ratelimit_jiffies;
 	if (toks >= ratelimit_jiffies) {
 		int lost = missed;
+
 		missed = 0;
 		toks -= ratelimit_jiffies;
 		spin_unlock_irqrestore(&ratelimit_lock, flags);
@@ -1021,7 +1027,7 @@
 EXPORT_SYMBOL(__printk_ratelimit);
 
 /* minimum time in jiffies between messages */
-int printk_ratelimit_jiffies = 5*HZ;
+int printk_ratelimit_jiffies = 5 * HZ;
 
 /* number of messages we send before ratelimiting */
 int printk_ratelimit_burst = 10;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 019e04e..863eee8 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -56,6 +56,10 @@
 			signal_wake_up(child, 1);
 		}
 	}
+	if (child->signal->flags & SIGNAL_GROUP_EXIT) {
+		sigaddset(&child->pending.signal, SIGKILL);
+		signal_wake_up(child, 1);
+	}
 	spin_unlock(&child->sighand->siglock);
 }
 
@@ -77,8 +81,7 @@
 		SET_LINKS(child);
 	}
 
-	if (child->state == TASK_TRACED)
-		ptrace_untrace(child);
+	ptrace_untrace(child);
 }
 
 /*
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 2559d4b..c4d159a 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -154,6 +154,15 @@
 }
 
 /*
+ * Return the number of RCU batches processed thus far.  Useful
+ * for debug and statistics.
+ */
+long rcu_batches_completed(void)
+{
+	return rcu_ctrlblk.completed;
+}
+
+/*
  * Invoke the completed RCU callbacks. They are expected to be in
  * a per-cpu list.
  */
@@ -501,6 +510,7 @@
 }
 
 module_param(maxbatch, int, 0);
+EXPORT_SYMBOL_GPL(rcu_batches_completed);
 EXPORT_SYMBOL(call_rcu);  /* WARNING: GPL-only in April 2006. */
 EXPORT_SYMBOL(call_rcu_bh);  /* WARNING: GPL-only in April 2006. */
 EXPORT_SYMBOL_GPL(synchronize_rcu);
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
new file mode 100644
index 0000000..9b58f1e
--- /dev/null
+++ b/kernel/rcutorture.c
@@ -0,0 +1,492 @@
+/*
+ * Read-Copy Update /proc-based torture test facility
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2005
+ *
+ * Authors: Paul E. McKenney <paulmck@us.ibm.com>
+ *
+ * See also:  Documentation/RCU/torture.txt
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/rcupdate.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/rcuref.h>
+#include <linux/cpu.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/byteorder/swabb.h>
+#include <linux/stat.h>
+
+MODULE_LICENSE("GPL");
+
+static int nreaders = -1;	/* # reader threads, defaults to 4*ncpus */
+static int stat_interval = 0;	/* Interval between stats, in seconds. */
+				/*  Defaults to "only at end of test". */
+static int verbose = 0;		/* Print more debug info. */
+
+MODULE_PARM(nreaders, "i");
+MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
+MODULE_PARM(stat_interval, "i");
+MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
+MODULE_PARM(verbose, "i");
+MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
+#define TORTURE_FLAG "rcutorture: "
+#define PRINTK_STRING(s) \
+	do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0)
+#define VERBOSE_PRINTK_STRING(s) \
+	do { if (verbose) printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0)
+#define VERBOSE_PRINTK_ERRSTRING(s) \
+	do { if (verbose) printk(KERN_ALERT TORTURE_FLAG "!!! " s "\n"); } while (0)
+
+static char printk_buf[4096];
+
+static int nrealreaders;
+static struct task_struct *writer_task;
+static struct task_struct **reader_tasks;
+static struct task_struct *stats_task;
+
+#define RCU_TORTURE_PIPE_LEN 10
+
+struct rcu_torture {
+	struct rcu_head rtort_rcu;
+	int rtort_pipe_count;
+	struct list_head rtort_free;
+};
+
+static int fullstop = 0;	/* stop generating callbacks at test end. */
+static LIST_HEAD(rcu_torture_freelist);
+static struct rcu_torture *rcu_torture_current = NULL;
+static long rcu_torture_current_version = 0;
+static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
+static DEFINE_SPINLOCK(rcu_torture_lock);
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
+	{ 0 };
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) =
+	{ 0 };
+static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
+atomic_t n_rcu_torture_alloc;
+atomic_t n_rcu_torture_alloc_fail;
+atomic_t n_rcu_torture_free;
+
+/*
+ * Allocate an element from the rcu_tortures pool.
+ */
+struct rcu_torture *
+rcu_torture_alloc(void)
+{
+	struct list_head *p;
+
+	spin_lock(&rcu_torture_lock);
+	if (list_empty(&rcu_torture_freelist)) {
+		atomic_inc(&n_rcu_torture_alloc_fail);
+		spin_unlock(&rcu_torture_lock);
+		return NULL;
+	}
+	atomic_inc(&n_rcu_torture_alloc);
+	p = rcu_torture_freelist.next;
+	list_del_init(p);
+	spin_unlock(&rcu_torture_lock);
+	return container_of(p, struct rcu_torture, rtort_free);
+}
+
+/*
+ * Free an element to the rcu_tortures pool.
+ */
+static void
+rcu_torture_free(struct rcu_torture *p)
+{
+	atomic_inc(&n_rcu_torture_free);
+	spin_lock(&rcu_torture_lock);
+	list_add_tail(&p->rtort_free, &rcu_torture_freelist);
+	spin_unlock(&rcu_torture_lock);
+}
+
+static void
+rcu_torture_cb(struct rcu_head *p)
+{
+	int i;
+	struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
+
+	if (fullstop) {
+		/* Test is ending, just drop callbacks on the floor. */
+		/* The next initialization will pick up the pieces. */
+		return;
+	}
+	i = rp->rtort_pipe_count;
+	if (i > RCU_TORTURE_PIPE_LEN)
+		i = RCU_TORTURE_PIPE_LEN;
+	atomic_inc(&rcu_torture_wcount[i]);
+	if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN)
+		rcu_torture_free(rp);
+	else
+		call_rcu(p, rcu_torture_cb);
+}
+
+struct rcu_random_state {
+	unsigned long rrs_state;
+	unsigned long rrs_count;
+};
+
+#define RCU_RANDOM_MULT 39916801  /* prime */
+#define RCU_RANDOM_ADD	479001701 /* prime */
+#define RCU_RANDOM_REFRESH 10000
+
+#define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 }
+
+/*
+ * Crude but fast random-number generator.  Uses a linear congruential
+ * generator, with occasional help from get_random_bytes().
+ */
+static long
+rcu_random(struct rcu_random_state *rrsp)
+{
+	long refresh;
+
+	if (--rrsp->rrs_count < 0) {
+		get_random_bytes(&refresh, sizeof(refresh));
+		rrsp->rrs_state += refresh;
+		rrsp->rrs_count = RCU_RANDOM_REFRESH;
+	}
+	rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD;
+	return swahw32(rrsp->rrs_state);
+}
+
+/*
+ * RCU torture writer kthread.  Repeatedly substitutes a new structure
+ * for that pointed to by rcu_torture_current, freeing the old structure
+ * after a series of grace periods (the "pipeline").
+ */
+static int
+rcu_torture_writer(void *arg)
+{
+	int i;
+	long oldbatch = rcu_batches_completed();
+	struct rcu_torture *rp;
+	struct rcu_torture *old_rp;
+	static DEFINE_RCU_RANDOM(rand);
+
+	VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
+	do {
+		schedule_timeout_uninterruptible(1);
+		if (rcu_batches_completed() == oldbatch)
+			continue;
+		if ((rp = rcu_torture_alloc()) == NULL)
+			continue;
+		rp->rtort_pipe_count = 0;
+		udelay(rcu_random(&rand) & 0x3ff);
+		old_rp = rcu_torture_current;
+		rcu_assign_pointer(rcu_torture_current, rp);
+		smp_wmb();
+		if (old_rp != NULL) {
+			i = old_rp->rtort_pipe_count;
+			if (i > RCU_TORTURE_PIPE_LEN)
+				i = RCU_TORTURE_PIPE_LEN;
+			atomic_inc(&rcu_torture_wcount[i]);
+			old_rp->rtort_pipe_count++;
+			call_rcu(&old_rp->rtort_rcu, rcu_torture_cb);
+		}
+		rcu_torture_current_version++;
+		oldbatch = rcu_batches_completed();
+	} while (!kthread_should_stop() && !fullstop);
+	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
+	while (!kthread_should_stop())
+		schedule_timeout_uninterruptible(1);
+	return 0;
+}
+
+/*
+ * RCU torture reader kthread.  Repeatedly dereferences rcu_torture_current,
+ * incrementing the corresponding element of the pipeline array.  The
+ * counter in the element should never be greater than 1, otherwise, the
+ * RCU implementation is broken.
+ */
+static int
+rcu_torture_reader(void *arg)
+{
+	int completed;
+	DEFINE_RCU_RANDOM(rand);
+	struct rcu_torture *p;
+	int pipe_count;
+
+	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
+	do {
+		rcu_read_lock();
+		completed = rcu_batches_completed();
+		p = rcu_dereference(rcu_torture_current);
+		if (p == NULL) {
+			/* Wait for rcu_torture_writer to get underway */
+			rcu_read_unlock();
+			schedule_timeout_interruptible(HZ);
+			continue;
+		}
+		udelay(rcu_random(&rand) & 0x7f);
+		preempt_disable();
+		pipe_count = p->rtort_pipe_count;
+		if (pipe_count > RCU_TORTURE_PIPE_LEN) {
+			/* Should not happen, but... */
+			pipe_count = RCU_TORTURE_PIPE_LEN;
+		}
+		++__get_cpu_var(rcu_torture_count)[pipe_count];
+		completed = rcu_batches_completed() - completed;
+		if (completed > RCU_TORTURE_PIPE_LEN) {
+			/* Should not happen, but... */
+			completed = RCU_TORTURE_PIPE_LEN;
+		}
+		++__get_cpu_var(rcu_torture_batch)[completed];
+		preempt_enable();
+		rcu_read_unlock();
+		schedule();
+	} while (!kthread_should_stop() && !fullstop);
+	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
+	while (!kthread_should_stop())
+		schedule_timeout_uninterruptible(1);
+	return 0;
+}
+
+/*
+ * Create an RCU-torture statistics message in the specified buffer.
+ */
+static int
+rcu_torture_printk(char *page)
+{
+	int cnt = 0;
+	int cpu;
+	int i;
+	long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
+	long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
+
+	for_each_cpu(cpu) {
+		for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+			pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i];
+			batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i];
+		}
+	}
+	for (i = RCU_TORTURE_PIPE_LEN - 1; i >= 0; i--) {
+		if (pipesummary[i] != 0)
+			break;
+	}
+	cnt += sprintf(&page[cnt], "rcutorture: ");
+	cnt += sprintf(&page[cnt],
+		       "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d",
+		       rcu_torture_current,
+		       rcu_torture_current_version,
+		       list_empty(&rcu_torture_freelist),
+		       atomic_read(&n_rcu_torture_alloc),
+		       atomic_read(&n_rcu_torture_alloc_fail),
+		       atomic_read(&n_rcu_torture_free));
+	cnt += sprintf(&page[cnt], "\nrcutorture: ");
+	if (i > 1)
+		cnt += sprintf(&page[cnt], "!!! ");
+	cnt += sprintf(&page[cnt], "Reader Pipe: ");
+	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
+		cnt += sprintf(&page[cnt], " %ld", pipesummary[i]);
+	cnt += sprintf(&page[cnt], "\nrcutorture: ");
+	cnt += sprintf(&page[cnt], "Reader Batch: ");
+	for (i = 0; i < RCU_TORTURE_PIPE_LEN; i++)
+		cnt += sprintf(&page[cnt], " %ld", batchsummary[i]);
+	cnt += sprintf(&page[cnt], "\nrcutorture: ");
+	cnt += sprintf(&page[cnt], "Free-Block Circulation: ");
+	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+		cnt += sprintf(&page[cnt], " %d",
+			       atomic_read(&rcu_torture_wcount[i]));
+	}
+	cnt += sprintf(&page[cnt], "\n");
+	return cnt;
+}
+
+/*
+ * Print torture statistics.  Caller must ensure that there is only
+ * one call to this function at a given time!!!  This is normally
+ * accomplished by relying on the module system to only have one copy
+ * of the module loaded, and then by giving the rcu_torture_stats
+ * kthread full control (or the init/cleanup functions when rcu_torture_stats
+ * thread is not running).
+ */
+static void
+rcu_torture_stats_print(void)
+{
+	int cnt;
+
+	cnt = rcu_torture_printk(printk_buf);
+	printk(KERN_ALERT "%s", printk_buf);
+}
+
+/*
+ * Periodically prints torture statistics, if periodic statistics printing
+ * was specified via the stat_interval module parameter.
+ *
+ * No need to worry about fullstop here, since this one doesn't reference
+ * volatile state or register callbacks.
+ */
+static int
+rcu_torture_stats(void *arg)
+{
+	VERBOSE_PRINTK_STRING("rcu_torture_stats task started");
+	do {
+		schedule_timeout_interruptible(stat_interval * HZ);
+		rcu_torture_stats_print();
+	} while (!kthread_should_stop());
+	VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping");
+	return 0;
+}
+
+static void
+rcu_torture_cleanup(void)
+{
+	int i;
+
+	fullstop = 1;
+	if (writer_task != NULL) {
+		VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
+		kthread_stop(writer_task);
+	}
+	writer_task = NULL;
+
+	if (reader_tasks != NULL) {
+		for (i = 0; i < nrealreaders; i++) {
+			if (reader_tasks[i] != NULL) {
+				VERBOSE_PRINTK_STRING(
+					"Stopping rcu_torture_reader task");
+				kthread_stop(reader_tasks[i]);
+			}
+			reader_tasks[i] = NULL;
+		}
+		kfree(reader_tasks);
+		reader_tasks = NULL;
+	}
+	rcu_torture_current = NULL;
+
+	if (stats_task != NULL) {
+		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
+		kthread_stop(stats_task);
+	}
+	stats_task = NULL;
+
+	/* Wait for all RCU callbacks to fire.  */
+
+	for (i = 0; i < RCU_TORTURE_PIPE_LEN; i++)
+		synchronize_rcu();
+	rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
+	PRINTK_STRING("--- End of test");
+}
+
+static int
+rcu_torture_init(void)
+{
+	int i;
+	int cpu;
+	int firsterr = 0;
+
+	/* Process args and tell the world that the torturer is on the job. */
+
+	if (nreaders >= 0)
+		nrealreaders = nreaders;
+	else
+		nrealreaders = 2 * num_online_cpus();
+	printk(KERN_ALERT TORTURE_FLAG
+	       "--- Start of test: nreaders=%d stat_interval=%d verbose=%d\n",
+	       nrealreaders, stat_interval, verbose);
+	fullstop = 0;
+
+	/* Set up the freelist. */
+
+	INIT_LIST_HEAD(&rcu_torture_freelist);
+	for (i = 0; i < sizeof(rcu_tortures) / sizeof(rcu_tortures[0]); i++) {
+		list_add_tail(&rcu_tortures[i].rtort_free,
+			      &rcu_torture_freelist);
+	}
+
+	/* Initialize the statistics so that each run gets its own numbers. */
+
+	rcu_torture_current = NULL;
+	rcu_torture_current_version = 0;
+	atomic_set(&n_rcu_torture_alloc, 0);
+	atomic_set(&n_rcu_torture_alloc_fail, 0);
+	atomic_set(&n_rcu_torture_free, 0);
+	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
+		atomic_set(&rcu_torture_wcount[i], 0);
+	for_each_cpu(cpu) {
+		for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+			per_cpu(rcu_torture_count, cpu)[i] = 0;
+			per_cpu(rcu_torture_batch, cpu)[i] = 0;
+		}
+	}
+
+	/* Start up the kthreads. */
+
+	VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task");
+	writer_task = kthread_run(rcu_torture_writer, NULL,
+				  "rcu_torture_writer");
+	if (IS_ERR(writer_task)) {
+		firsterr = PTR_ERR(writer_task);
+		VERBOSE_PRINTK_ERRSTRING("Failed to create writer");
+		writer_task = NULL;
+		goto unwind;
+	}
+	reader_tasks = kmalloc(nrealreaders * sizeof(reader_tasks[0]),
+			       GFP_KERNEL);
+	if (reader_tasks == NULL) {
+		VERBOSE_PRINTK_ERRSTRING("out of memory");
+		firsterr = -ENOMEM;
+		goto unwind;
+	}
+	for (i = 0; i < nrealreaders; i++) {
+		VERBOSE_PRINTK_STRING("Creating rcu_torture_reader task");
+		reader_tasks[i] = kthread_run(rcu_torture_reader, NULL,
+					      "rcu_torture_reader");
+		if (IS_ERR(reader_tasks[i])) {
+			firsterr = PTR_ERR(reader_tasks[i]);
+			VERBOSE_PRINTK_ERRSTRING("Failed to create reader");
+			reader_tasks[i] = NULL;
+			goto unwind;
+		}
+	}
+	if (stat_interval > 0) {
+		VERBOSE_PRINTK_STRING("Creating rcu_torture_stats task");
+		stats_task = kthread_run(rcu_torture_stats, NULL,
+					"rcu_torture_stats");
+		if (IS_ERR(stats_task)) {
+			firsterr = PTR_ERR(stats_task);
+			VERBOSE_PRINTK_ERRSTRING("Failed to create stats");
+			stats_task = NULL;
+			goto unwind;
+		}
+	}
+	return 0;
+
+unwind:
+	rcu_torture_cleanup();
+	return firsterr;
+}
+
+module_init(rcu_torture_init);
+module_exit(rcu_torture_cleanup);
diff --git a/kernel/sched.c b/kernel/sched.c
index 1e5cafd..340dd23 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2511,8 +2511,6 @@
 		cpustat->idle = cputime64_add(cpustat->idle, tmp);
 	/* Account for system time used */
 	acct_update_integrals(p);
-	/* Update rss highwater mark */
-	update_mem_hiwater(p);
 }
 
 /*
@@ -3879,7 +3877,6 @@
 
 #ifndef CONFIG_SMP
 cpumask_t cpu_online_map = CPU_MASK_ALL;
-EXPORT_SYMBOL_GPL(cpu_online_map);
 cpumask_t cpu_possible_map = CPU_MASK_ALL;
 #endif
 
diff --git a/kernel/signal.c b/kernel/signal.c
index f2b96b0..1bf3c39 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -277,7 +277,6 @@
 	} else {
 		INIT_LIST_HEAD(&q->list);
 		q->flags = 0;
-		q->lock = NULL;
 		q->user = get_uid(t->user);
 	}
 	return(q);
@@ -406,6 +405,8 @@
 
 void exit_signal(struct task_struct *tsk)
 {
+	atomic_dec(&tsk->signal->live);
+
 	write_lock_irq(&tasklist_lock);
 	__exit_signal(tsk);
 	write_unlock_irq(&tasklist_lock);
@@ -650,8 +651,7 @@
 	if (!valid_signal(sig))
 		return error;
 	error = -EPERM;
-	if ((!info || ((unsigned long)info != 1 &&
-			(unsigned long)info != 2 && SI_FROMUSER(info)))
+	if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
 	    && ((sig != SIGCONT) ||
 		(current->signal->session != t->signal->session))
 	    && (current->euid ^ t->suid) && (current->euid ^ t->uid)
@@ -788,7 +788,7 @@
 	 * fast-pathed signals for kernel-internal things like SIGSTOP
 	 * or SIGKILL.
 	 */
-	if ((unsigned long)info == 2)
+	if (info == SEND_SIG_FORCED)
 		goto out_set;
 
 	/* Real-time signals must be queued if sent by sigqueue, or
@@ -800,19 +800,19 @@
 	   pass on the info struct.  */
 
 	q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
-					     ((unsigned long) info < 2 ||
+					     (is_si_special(info) ||
 					      info->si_code >= 0)));
 	if (q) {
 		list_add_tail(&q->list, &signals->list);
 		switch ((unsigned long) info) {
-		case 0:
+		case (unsigned long) SEND_SIG_NOINFO:
 			q->info.si_signo = sig;
 			q->info.si_errno = 0;
 			q->info.si_code = SI_USER;
 			q->info.si_pid = current->pid;
 			q->info.si_uid = current->uid;
 			break;
-		case 1:
+		case (unsigned long) SEND_SIG_PRIV:
 			q->info.si_signo = sig;
 			q->info.si_errno = 0;
 			q->info.si_code = SI_KERNEL;
@@ -823,20 +823,13 @@
 			copy_siginfo(&q->info, info);
 			break;
 		}
-	} else {
-		if (sig >= SIGRTMIN && info && (unsigned long)info != 1
-		   && info->si_code != SI_USER)
+	} else if (!is_si_special(info)) {
+		if (sig >= SIGRTMIN && info->si_code != SI_USER)
 		/*
 		 * Queue overflow, abort.  We may abort if the signal was rt
 		 * and sent by user using something other than kill().
 		 */
 			return -EAGAIN;
-		if (((unsigned long)info > 1) && (info->si_code == SI_TIMER))
-			/*
-			 * Set up a return to indicate that we dropped 
-			 * the signal.
-			 */
-			ret = info->si_sys_private;
 	}
 
 out_set:
@@ -857,12 +850,6 @@
 		BUG();
 	assert_spin_locked(&t->sighand->siglock);
 
-	if (((unsigned long)info > 2) && (info->si_code == SI_TIMER))
-		/*
-		 * Set up a return to indicate that we dropped the signal.
-		 */
-		ret = info->si_sys_private;
-
 	/* Short-circuit ignored signals.  */
 	if (sig_ignored(t, sig))
 		goto out;
@@ -892,11 +879,13 @@
 	int ret;
 
 	spin_lock_irqsave(&t->sighand->siglock, flags);
-	if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
+	if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
 		t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
-		sigdelset(&t->blocked, sig);
-		recalc_sigpending_tsk(t);
 	}
+	if (sigismember(&t->blocked, sig)) {
+		sigdelset(&t->blocked, sig);
+	}
+	recalc_sigpending_tsk(t);
 	ret = specific_send_sig_info(sig, info, t);
 	spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
@@ -906,15 +895,7 @@
 void
 force_sig_specific(int sig, struct task_struct *t)
 {
-	unsigned long int flags;
-
-	spin_lock_irqsave(&t->sighand->siglock, flags);
-	if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN)
-		t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
-	sigdelset(&t->blocked, sig);
-	recalc_sigpending_tsk(t);
-	specific_send_sig_info(sig, (void *)2, t);
-	spin_unlock_irqrestore(&t->sighand->siglock, flags);
+	force_sig_info(sig, SEND_SIG_FORCED, t);
 }
 
 /*
@@ -1049,12 +1030,6 @@
 	assert_spin_locked(&p->sighand->siglock);
 	handle_stop_signal(sig, p);
 
-	if (((unsigned long)info > 2) && (info->si_code == SI_TIMER))
-		/*
-		 * Set up a return to indicate that we dropped the signal.
-		 */
-		ret = info->si_sys_private;
-
 	/* Short-circuit ignored signals.  */
 	if (sig_ignored(p, sig))
 		return ret;
@@ -1107,8 +1082,8 @@
 		if (t != p->group_leader)
 			t->exit_signal = -1;
 
+		/* SIGKILL will be handled before any pending SIGSTOP */
 		sigaddset(&t->pending.signal, SIGKILL);
-		rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
 		signal_wake_up(t, 1);
 	}
 }
@@ -1284,10 +1259,13 @@
 	return ret;
 }
 
+#define __si_special(priv) \
+	((priv) ? SEND_SIG_PRIV : SEND_SIG_NOINFO)
+
 int
 send_sig(int sig, struct task_struct *p, int priv)
 {
-	return send_sig_info(sig, (void*)(long)(priv != 0), p);
+	return send_sig_info(sig, __si_special(priv), p);
 }
 
 /*
@@ -1307,7 +1285,7 @@
 void
 force_sig(int sig, struct task_struct *p)
 {
-	force_sig_info(sig, (void*)1L, p);
+	force_sig_info(sig, SEND_SIG_PRIV, p);
 }
 
 /*
@@ -1332,13 +1310,13 @@
 int
 kill_pg(pid_t pgrp, int sig, int priv)
 {
-	return kill_pg_info(sig, (void *)(long)(priv != 0), pgrp);
+	return kill_pg_info(sig, __si_special(priv), pgrp);
 }
 
 int
 kill_proc(pid_t pid, int sig, int priv)
 {
-	return kill_proc_info(sig, (void *)(long)(priv != 0), pid);
+	return kill_proc_info(sig, __si_special(priv), pid);
 }
 
 /*
@@ -1369,11 +1347,12 @@
 	 * pending queue.
 	 */
 	if (unlikely(!list_empty(&q->list))) {
-		read_lock(&tasklist_lock);  
-		spin_lock_irqsave(q->lock, flags);
+		spinlock_t *lock = &current->sighand->siglock;
+		read_lock(&tasklist_lock);
+		spin_lock_irqsave(lock, flags);
 		if (!list_empty(&q->list))
 			list_del_init(&q->list);
-		spin_unlock_irqrestore(q->lock, flags);
+		spin_unlock_irqrestore(lock, flags);
 		read_unlock(&tasklist_lock);
 	}
 	q->flags &= ~SIGQUEUE_PREALLOC;
@@ -1412,7 +1391,6 @@
 		goto out;
 	}
 
-	q->lock = &p->sighand->siglock;
 	list_add_tail(&q->list, &p->pending.list);
 	sigaddset(&p->pending.signal, sig);
 	if (!sigismember(&p->blocked, sig))
@@ -1460,7 +1438,6 @@
 	 * We always use the shared queue for process-wide signals,
 	 * to avoid several races.
 	 */
-	q->lock = &p->sighand->siglock;
 	list_add_tail(&q->list, &p->signal->shared_pending.list);
 	sigaddset(&p->signal->shared_pending.signal, sig);
 
@@ -1879,9 +1856,9 @@
 			/* Let the debugger run.  */
 			ptrace_stop(signr, signr, info);
 
-			/* We're back.  Did the debugger cancel the sig?  */
+			/* We're back.  Did the debugger cancel the sig or group_exit? */
 			signr = current->exit_code;
-			if (signr == 0)
+			if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT)
 				continue;
 
 			current->exit_code = 0;
@@ -2283,6 +2260,39 @@
 	return kill_something_info(sig, &info, pid);
 }
 
+static int do_tkill(int tgid, int pid, int sig)
+{
+	int error;
+	struct siginfo info;
+	struct task_struct *p;
+
+	error = -ESRCH;
+	info.si_signo = sig;
+	info.si_errno = 0;
+	info.si_code = SI_TKILL;
+	info.si_pid = current->tgid;
+	info.si_uid = current->uid;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	if (p && (tgid <= 0 || p->tgid == tgid)) {
+		error = check_kill_permission(sig, &info, p);
+		/*
+		 * The null signal is a permissions and process existence
+		 * probe.  No signal is actually delivered.
+		 */
+		if (!error && sig && p->sighand) {
+			spin_lock_irq(&p->sighand->siglock);
+			handle_stop_signal(sig, p);
+			error = specific_send_sig_info(sig, &info, p);
+			spin_unlock_irq(&p->sighand->siglock);
+		}
+	}
+	read_unlock(&tasklist_lock);
+
+	return error;
+}
+
 /**
  *  sys_tgkill - send signal to one specific thread
  *  @tgid: the thread group ID of the thread
@@ -2295,38 +2305,11 @@
  */
 asmlinkage long sys_tgkill(int tgid, int pid, int sig)
 {
-	struct siginfo info;
-	int error;
-	struct task_struct *p;
-
 	/* This is only valid for single tasks */
 	if (pid <= 0 || tgid <= 0)
 		return -EINVAL;
 
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code = SI_TKILL;
-	info.si_pid = current->tgid;
-	info.si_uid = current->uid;
-
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	error = -ESRCH;
-	if (p && (p->tgid == tgid)) {
-		error = check_kill_permission(sig, &info, p);
-		/*
-		 * The null signal is a permissions and process existence
-		 * probe.  No signal is actually delivered.
-		 */
-		if (!error && sig && p->sighand) {
-			spin_lock_irq(&p->sighand->siglock);
-			handle_stop_signal(sig, p);
-			error = specific_send_sig_info(sig, &info, p);
-			spin_unlock_irq(&p->sighand->siglock);
-		}
-	}
-	read_unlock(&tasklist_lock);
-	return error;
+	return do_tkill(tgid, pid, sig);
 }
 
 /*
@@ -2335,38 +2318,11 @@
 asmlinkage long
 sys_tkill(int pid, int sig)
 {
-	struct siginfo info;
-	int error;
-	struct task_struct *p;
-
 	/* This is only valid for single tasks */
 	if (pid <= 0)
 		return -EINVAL;
 
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code = SI_TKILL;
-	info.si_pid = current->tgid;
-	info.si_uid = current->uid;
-
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	error = -ESRCH;
-	if (p) {
-		error = check_kill_permission(sig, &info, p);
-		/*
-		 * The null signal is a permissions and process existence
-		 * probe.  No signal is actually delivered.
-		 */
-		if (!error && sig && p->sighand) {
-			spin_lock_irq(&p->sighand->siglock);
-			handle_stop_signal(sig, p);
-			error = specific_send_sig_info(sig, &info, p);
-			spin_unlock_irq(&p->sighand->siglock);
-		}
-	}
-	read_unlock(&tasklist_lock);
-	return error;
+	return do_tkill(0, pid, sig);
 }
 
 asmlinkage long
diff --git a/kernel/time.c b/kernel/time.c
index 40c2410..245d595 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -338,30 +338,20 @@
 		        if (mtemp >= MINSEC) {
 			    ltemp = (time_offset / mtemp) << (SHIFT_USEC -
 							      SHIFT_UPDATE);
-			    if (ltemp < 0)
-			        time_freq -= -ltemp >> SHIFT_KH;
-			    else
-			        time_freq += ltemp >> SHIFT_KH;
+			    time_freq += shift_right(ltemp, SHIFT_KH);
 			} else /* calibration interval too short (p. 12) */
 				result = TIME_ERROR;
 		    } else {	/* PLL mode */
 		        if (mtemp < MAXSEC) {
 			    ltemp *= mtemp;
-			    if (ltemp < 0)
-			        time_freq -= -ltemp >> (time_constant +
-							time_constant +
-							SHIFT_KF - SHIFT_USEC);
-			    else
-			        time_freq += ltemp >> (time_constant +
+			    time_freq += shift_right(ltemp,(time_constant +
 						       time_constant +
-						       SHIFT_KF - SHIFT_USEC);
+						       SHIFT_KF - SHIFT_USEC));
 			} else /* calibration interval too long (p. 12) */
 				result = TIME_ERROR;
 		    }
-		    if (time_freq > time_tolerance)
-		        time_freq = time_tolerance;
-		    else if (time_freq < -time_tolerance)
-		        time_freq = -time_tolerance;
+		    time_freq = min(time_freq, time_tolerance);
+		    time_freq = max(time_freq, -time_tolerance);
 		} /* STA_PLL || STA_PPSTIME */
 	    } /* txc->modes & ADJ_OFFSET */
 	    if (txc->modes & ADJ_TICK) {
@@ -384,10 +374,7 @@
 	if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
 	    txc->offset	   = save_adjust;
 	else {
-	    if (time_offset < 0)
-		txc->offset = -(-time_offset >> SHIFT_UPDATE);
-	    else
-		txc->offset = time_offset >> SHIFT_UPDATE;
+	    txc->offset = shift_right(time_offset, SHIFT_UPDATE);
 	}
 	txc->freq	   = time_freq + pps_freq;
 	txc->maxerror	   = time_maxerror;
@@ -532,6 +519,7 @@
 	clock_was_set();
 	return 0;
 }
+EXPORT_SYMBOL(do_settimeofday);
 
 void do_gettimeofday (struct timeval *tv)
 {
diff --git a/kernel/timer.c b/kernel/timer.c
index 3ba10fa..fd74268 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -46,6 +46,10 @@
 #define time_interpolator_update(x)
 #endif
 
+u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
 /*
  * per-CPU timer vector definitions:
  */
@@ -91,30 +95,6 @@
 #endif
 }
 
-static void check_timer_failed(struct timer_list *timer)
-{
-	static int whine_count;
-	if (whine_count < 16) {
-		whine_count++;
-		printk("Uninitialised timer!\n");
-		printk("This is just a warning.  Your computer is OK\n");
-		printk("function=0x%p, data=0x%lx\n",
-			timer->function, timer->data);
-		dump_stack();
-	}
-	/*
-	 * Now fix it up
-	 */
-	timer->magic = TIMER_MAGIC;
-}
-
-static inline void check_timer(struct timer_list *timer)
-{
-	if (timer->magic != TIMER_MAGIC)
-		check_timer_failed(timer);
-}
-
-
 static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
 {
 	unsigned long expires = timer->expires;
@@ -177,7 +157,6 @@
 {
 	timer->entry.next = NULL;
 	timer->base = &per_cpu(tvec_bases, raw_smp_processor_id()).t_base;
-	timer->magic = TIMER_MAGIC;
 }
 EXPORT_SYMBOL(init_timer);
 
@@ -230,7 +209,6 @@
 	int ret = 0;
 
 	BUG_ON(!timer->function);
-	check_timer(timer);
 
 	base = lock_timer_base(timer, &flags);
 
@@ -283,9 +261,6 @@
   	unsigned long flags;
 
   	BUG_ON(timer_pending(timer) || !timer->function);
-
-	check_timer(timer);
-
 	spin_lock_irqsave(&base->t_base.lock, flags);
 	timer->base = &base->t_base;
 	internal_add_timer(base, timer);
@@ -316,8 +291,6 @@
 {
 	BUG_ON(!timer->function);
 
-	check_timer(timer);
-
 	/*
 	 * This is a common optimization triggered by the
 	 * networking code - if the timer is re-modified
@@ -348,8 +321,6 @@
 	unsigned long flags;
 	int ret = 0;
 
-	check_timer(timer);
-
 	if (timer_pending(timer)) {
 		base = lock_timer_base(timer, &flags);
 		if (timer_pending(timer)) {
@@ -412,8 +383,6 @@
  */
 int del_timer_sync(struct timer_list *timer)
 {
-	check_timer(timer);
-
 	for (;;) {
 		int ret = try_to_del_timer_sync(timer);
 		if (ret >= 0)
@@ -632,134 +601,118 @@
  */
 static void second_overflow(void)
 {
-    long ltemp;
+	long ltemp;
 
-    /* Bump the maxerror field */
-    time_maxerror += time_tolerance >> SHIFT_USEC;
-    if ( time_maxerror > NTP_PHASE_LIMIT ) {
-	time_maxerror = NTP_PHASE_LIMIT;
-	time_status |= STA_UNSYNC;
-    }
-
-    /*
-     * Leap second processing. If in leap-insert state at
-     * the end of the day, the system clock is set back one
-     * second; if in leap-delete state, the system clock is
-     * set ahead one second. The microtime() routine or
-     * external clock driver will insure that reported time
-     * is always monotonic. The ugly divides should be
-     * replaced.
-     */
-    switch (time_state) {
-
-    case TIME_OK:
-	if (time_status & STA_INS)
-	    time_state = TIME_INS;
-	else if (time_status & STA_DEL)
-	    time_state = TIME_DEL;
-	break;
-
-    case TIME_INS:
-	if (xtime.tv_sec % 86400 == 0) {
-	    xtime.tv_sec--;
-	    wall_to_monotonic.tv_sec++;
-	    /* The timer interpolator will make time change gradually instead
-	     * of an immediate jump by one second.
-	     */
-	    time_interpolator_update(-NSEC_PER_SEC);
-	    time_state = TIME_OOP;
-	    clock_was_set();
-	    printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
+	/* Bump the maxerror field */
+	time_maxerror += time_tolerance >> SHIFT_USEC;
+	if (time_maxerror > NTP_PHASE_LIMIT) {
+		time_maxerror = NTP_PHASE_LIMIT;
+		time_status |= STA_UNSYNC;
 	}
-	break;
 
-    case TIME_DEL:
-	if ((xtime.tv_sec + 1) % 86400 == 0) {
-	    xtime.tv_sec++;
-	    wall_to_monotonic.tv_sec--;
-	    /* Use of time interpolator for a gradual change of time */
-	    time_interpolator_update(NSEC_PER_SEC);
-	    time_state = TIME_WAIT;
-	    clock_was_set();
-	    printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
+	/*
+	 * Leap second processing. If in leap-insert state at the end of the
+	 * day, the system clock is set back one second; if in leap-delete
+	 * state, the system clock is set ahead one second. The microtime()
+	 * routine or external clock driver will insure that reported time is
+	 * always monotonic. The ugly divides should be replaced.
+	 */
+	switch (time_state) {
+	case TIME_OK:
+		if (time_status & STA_INS)
+			time_state = TIME_INS;
+		else if (time_status & STA_DEL)
+			time_state = TIME_DEL;
+		break;
+	case TIME_INS:
+		if (xtime.tv_sec % 86400 == 0) {
+			xtime.tv_sec--;
+			wall_to_monotonic.tv_sec++;
+			/*
+			 * The timer interpolator will make time change
+			 * gradually instead of an immediate jump by one second
+			 */
+			time_interpolator_update(-NSEC_PER_SEC);
+			time_state = TIME_OOP;
+			clock_was_set();
+			printk(KERN_NOTICE "Clock: inserting leap second "
+					"23:59:60 UTC\n");
+		}
+		break;
+	case TIME_DEL:
+		if ((xtime.tv_sec + 1) % 86400 == 0) {
+			xtime.tv_sec++;
+			wall_to_monotonic.tv_sec--;
+			/*
+			 * Use of time interpolator for a gradual change of
+			 * time
+			 */
+			time_interpolator_update(NSEC_PER_SEC);
+			time_state = TIME_WAIT;
+			clock_was_set();
+			printk(KERN_NOTICE "Clock: deleting leap second "
+					"23:59:59 UTC\n");
+		}
+		break;
+	case TIME_OOP:
+		time_state = TIME_WAIT;
+		break;
+	case TIME_WAIT:
+		if (!(time_status & (STA_INS | STA_DEL)))
+		time_state = TIME_OK;
 	}
-	break;
 
-    case TIME_OOP:
-	time_state = TIME_WAIT;
-	break;
-
-    case TIME_WAIT:
-	if (!(time_status & (STA_INS | STA_DEL)))
-	    time_state = TIME_OK;
-    }
-
-    /*
-     * Compute the phase adjustment for the next second. In
-     * PLL mode, the offset is reduced by a fixed factor
-     * times the time constant. In FLL mode the offset is
-     * used directly. In either mode, the maximum phase
-     * adjustment for each second is clamped so as to spread
-     * the adjustment over not more than the number of
-     * seconds between updates.
-     */
-    if (time_offset < 0) {
-	ltemp = -time_offset;
-	if (!(time_status & STA_FLL))
-	    ltemp >>= SHIFT_KG + time_constant;
-	if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
-	    ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
-	time_offset += ltemp;
-	time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
-    } else {
+	/*
+	 * Compute the phase adjustment for the next second. In PLL mode, the
+	 * offset is reduced by a fixed factor times the time constant. In FLL
+	 * mode the offset is used directly. In either mode, the maximum phase
+	 * adjustment for each second is clamped so as to spread the adjustment
+	 * over not more than the number of seconds between updates.
+	 */
 	ltemp = time_offset;
 	if (!(time_status & STA_FLL))
-	    ltemp >>= SHIFT_KG + time_constant;
-	if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
-	    ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
+		ltemp = shift_right(ltemp, SHIFT_KG + time_constant);
+	ltemp = min(ltemp, (MAXPHASE / MINSEC) << SHIFT_UPDATE);
+	ltemp = max(ltemp, -(MAXPHASE / MINSEC) << SHIFT_UPDATE);
 	time_offset -= ltemp;
 	time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
-    }
 
-    /*
-     * Compute the frequency estimate and additional phase
-     * adjustment due to frequency error for the next
-     * second. When the PPS signal is engaged, gnaw on the
-     * watchdog counter and update the frequency computed by
-     * the pll and the PPS signal.
-     */
-    pps_valid++;
-    if (pps_valid == PPS_VALID) {	/* PPS signal lost */
-	pps_jitter = MAXTIME;
-	pps_stabil = MAXFREQ;
-	time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
-			 STA_PPSWANDER | STA_PPSERROR);
-    }
-    ltemp = time_freq + pps_freq;
-    if (ltemp < 0)
-	time_adj -= -ltemp >>
-	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
-    else
-	time_adj += ltemp >>
-	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
+	/*
+	 * Compute the frequency estimate and additional phase adjustment due
+	 * to frequency error for the next second. When the PPS signal is
+	 * engaged, gnaw on the watchdog counter and update the frequency
+	 * computed by the pll and the PPS signal.
+	 */
+	pps_valid++;
+	if (pps_valid == PPS_VALID) {	/* PPS signal lost */
+		pps_jitter = MAXTIME;
+		pps_stabil = MAXFREQ;
+		time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
+				STA_PPSWANDER | STA_PPSERROR);
+	}
+	ltemp = time_freq + pps_freq;
+	time_adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
 
 #if HZ == 100
-    /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
-     * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
-     */
-    if (time_adj < 0)
-	time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
-    else
-	time_adj += (time_adj >> 2) + (time_adj >> 5);
+	/*
+	 * Compensate for (HZ==100) != (1 << SHIFT_HZ).  Add 25% and 3.125% to
+	 * get 128.125; => only 0.125% error (p. 14)
+	 */
+	time_adj += shift_right(time_adj, 2) + shift_right(time_adj, 5);
+#endif
+#if HZ == 250
+	/*
+	 * Compensate for (HZ==250) != (1 << SHIFT_HZ).  Add 1.5625% and
+	 * 0.78125% to get 255.85938; => only 0.05% error (p. 14)
+	 */
+	time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7);
 #endif
 #if HZ == 1000
-    /* Compensate for (HZ==1000) != (1 << SHIFT_HZ).
-     * Add 1.5625% and 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
-     */
-    if (time_adj < 0)
-	time_adj -= (-time_adj >> 6) + (-time_adj >> 7);
-    else
-	time_adj += (time_adj >> 6) + (time_adj >> 7);
+	/*
+	 * Compensate for (HZ==1000) != (1 << SHIFT_HZ).  Add 1.5625% and
+	 * 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
+	 */
+	time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7);
 #endif
 }
 
@@ -768,23 +721,20 @@
 {
 	long time_adjust_step, delta_nsec;
 
-	if ( (time_adjust_step = time_adjust) != 0 ) {
-	    /* We are doing an adjtime thing. 
-	     *
-	     * Prepare time_adjust_step to be within bounds.
-	     * Note that a positive time_adjust means we want the clock
-	     * to run faster.
-	     *
-	     * Limit the amount of the step to be in the range
-	     * -tickadj .. +tickadj
-	     */
-	     if (time_adjust > tickadj)
-		time_adjust_step = tickadj;
-	     else if (time_adjust < -tickadj)
-		time_adjust_step = -tickadj;
+	if ((time_adjust_step = time_adjust) != 0 ) {
+		/*
+		 * We are doing an adjtime thing.  Prepare time_adjust_step to
+		 * be within bounds.  Note that a positive time_adjust means we
+		 * want the clock to run faster.
+		 *
+		 * Limit the amount of the step to be in the range
+		 * -tickadj .. +tickadj
+		 */
+		time_adjust_step = min(time_adjust_step, (long)tickadj);
+		time_adjust_step = max(time_adjust_step, (long)-tickadj);
 
-	    /* Reduce by this step the amount of time left  */
-	    time_adjust -= time_adjust_step;
+		/* Reduce by this step the amount of time left  */
+		time_adjust -= time_adjust_step;
 	}
 	delta_nsec = tick_nsec + time_adjust_step * 1000;
 	/*
@@ -792,13 +742,8 @@
 	 * advance the tick more.
 	 */
 	time_phase += time_adj;
-	if (time_phase <= -FINENSEC) {
-		long ltemp = -time_phase >> (SHIFT_SCALE - 10);
-		time_phase += ltemp << (SHIFT_SCALE - 10);
-		delta_nsec -= ltemp;
-	}
-	else if (time_phase >= FINENSEC) {
-		long ltemp = time_phase >> (SHIFT_SCALE - 10);
+	if ((time_phase >= FINENSEC) || (time_phase <= -FINENSEC)) {
+		long ltemp = shift_right(time_phase, (SHIFT_SCALE - 10));
 		time_phase -= ltemp << (SHIFT_SCALE - 10);
 		delta_nsec += ltemp;
 	}
@@ -1128,8 +1073,8 @@
 		if (timeout < 0)
 		{
 			printk(KERN_ERR "schedule_timeout: wrong timeout "
-			       "value %lx from %p\n", timeout,
-			       __builtin_return_address(0));
+				"value %lx from %p\n", timeout,
+				__builtin_return_address(0));
 			current->state = TASK_RUNNING;
 			goto out;
 		}
@@ -1137,12 +1082,8 @@
 
 	expire = timeout + jiffies;
 
-	init_timer(&timer);
-	timer.expires = expire;
-	timer.data = (unsigned long) current;
-	timer.function = process_timeout;
-
-	add_timer(&timer);
+	setup_timer(&timer, process_timeout, (unsigned long)current);
+	__mod_timer(&timer, expire);
 	schedule();
 	del_singleshot_timer_sync(&timer);
 
@@ -1159,15 +1100,15 @@
  */
 signed long __sched schedule_timeout_interruptible(signed long timeout)
 {
-       __set_current_state(TASK_INTERRUPTIBLE);
-       return schedule_timeout(timeout);
+	__set_current_state(TASK_INTERRUPTIBLE);
+	return schedule_timeout(timeout);
 }
 EXPORT_SYMBOL(schedule_timeout_interruptible);
 
 signed long __sched schedule_timeout_uninterruptible(signed long timeout)
 {
-       __set_current_state(TASK_UNINTERRUPTIBLE);
-       return schedule_timeout(timeout);
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	return schedule_timeout(timeout);
 }
 EXPORT_SYMBOL(schedule_timeout_uninterruptible);
 
@@ -1507,16 +1448,18 @@
 	if (!time_interpolator)
 		return;
 
-	/* The interpolator compensates for late ticks by accumulating
-         * the late time in time_interpolator->offset. A tick earlier than
-	 * expected will lead to a reset of the offset and a corresponding
-	 * jump of the clock forward. Again this only works if the
-	 * interpolator clock is running slightly slower than the regular clock
-	 * and the tuning logic insures that.
-         */
+	/*
+	 * The interpolator compensates for late ticks by accumulating the late
+	 * time in time_interpolator->offset. A tick earlier than expected will
+	 * lead to a reset of the offset and a corresponding jump of the clock
+	 * forward. Again this only works if the interpolator clock is running
+	 * slightly slower than the regular clock and the tuning logic insures
+	 * that.
+	 */
 
 	counter = time_interpolator_get_counter(1);
-	offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
+	offset = time_interpolator->offset +
+			GET_TI_NSECS(counter, time_interpolator);
 
 	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
 		time_interpolator->offset = offset - delta_nsec;
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 91bacb1..7cee222 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -12,6 +12,8 @@
  *   Andrew Morton <andrewm@uow.edu.au>
  *   Kai Petzke <wpp@marie.physik.tu-berlin.de>
  *   Theodore Ts'o <tytso@mit.edu>
+ *
+ * Made to use alloc_percpu by Christoph Lameter <clameter@sgi.com>.
  */
 
 #include <linux/module.h>
@@ -57,7 +59,7 @@
  * per-CPU workqueues:
  */
 struct workqueue_struct {
-	struct cpu_workqueue_struct cpu_wq[NR_CPUS];
+	struct cpu_workqueue_struct *cpu_wq;
 	const char *name;
 	struct list_head list; 	/* Empty if single thread */
 };
@@ -102,7 +104,7 @@
 		if (unlikely(is_single_threaded(wq)))
 			cpu = 0;
 		BUG_ON(!list_empty(&work->entry));
-		__queue_work(wq->cpu_wq + cpu, work);
+		__queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 		ret = 1;
 	}
 	put_cpu();
@@ -118,7 +120,7 @@
 	if (unlikely(is_single_threaded(wq)))
 		cpu = 0;
 
-	__queue_work(wq->cpu_wq + cpu, work);
+	__queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 }
 
 int fastcall queue_delayed_work(struct workqueue_struct *wq,
@@ -265,13 +267,13 @@
 
 	if (is_single_threaded(wq)) {
 		/* Always use cpu 0's area. */
-		flush_cpu_workqueue(wq->cpu_wq + 0);
+		flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, 0));
 	} else {
 		int cpu;
 
 		lock_cpu_hotplug();
 		for_each_online_cpu(cpu)
-			flush_cpu_workqueue(wq->cpu_wq + cpu);
+			flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
 		unlock_cpu_hotplug();
 	}
 }
@@ -279,7 +281,7 @@
 static struct task_struct *create_workqueue_thread(struct workqueue_struct *wq,
 						   int cpu)
 {
-	struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
+	struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
 	struct task_struct *p;
 
 	spin_lock_init(&cwq->lock);
@@ -312,6 +314,7 @@
 	if (!wq)
 		return NULL;
 
+	wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
 	wq->name = name;
 	/* We don't need the distraction of CPUs appearing and vanishing. */
 	lock_cpu_hotplug();
@@ -353,7 +356,7 @@
 	unsigned long flags;
 	struct task_struct *p;
 
-	cwq = wq->cpu_wq + cpu;
+	cwq = per_cpu_ptr(wq->cpu_wq, cpu);
 	spin_lock_irqsave(&cwq->lock, flags);
 	p = cwq->thread;
 	cwq->thread = NULL;
@@ -380,6 +383,7 @@
 		spin_unlock(&workqueue_lock);
 	}
 	unlock_cpu_hotplug();
+	free_percpu(wq->cpu_wq);
 	kfree(wq);
 }
 
@@ -458,7 +462,7 @@
 
 	BUG_ON(!keventd_wq);
 
-	cwq = keventd_wq->cpu_wq + cpu;
+	cwq = per_cpu_ptr(keventd_wq->cpu_wq, cpu);
 	if (current == cwq->thread)
 		ret = 1;
 
@@ -470,7 +474,7 @@
 /* Take the work from this (downed) CPU. */
 static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
 {
-	struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu;
+	struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
 	LIST_HEAD(list);
 	struct work_struct *work;
 
@@ -481,7 +485,7 @@
 		printk("Taking work for %s\n", wq->name);
 		work = list_entry(list.next,struct work_struct,entry);
 		list_del(&work->entry);
-		__queue_work(wq->cpu_wq + smp_processor_id(), work);
+		__queue_work(per_cpu_ptr(wq->cpu_wq, smp_processor_id()), work);
 	}
 	spin_unlock_irq(&cwq->lock);
 }
@@ -508,15 +512,18 @@
 	case CPU_ONLINE:
 		/* Kick off worker threads. */
 		list_for_each_entry(wq, &workqueues, list) {
-			kthread_bind(wq->cpu_wq[hotcpu].thread, hotcpu);
-			wake_up_process(wq->cpu_wq[hotcpu].thread);
+			struct cpu_workqueue_struct *cwq;
+
+			cwq = per_cpu_ptr(wq->cpu_wq, hotcpu);
+			kthread_bind(cwq->thread, hotcpu);
+			wake_up_process(cwq->thread);
 		}
 		break;
 
 	case CPU_UP_CANCELED:
 		list_for_each_entry(wq, &workqueues, list) {
 			/* Unbind so it can run. */
-			kthread_bind(wq->cpu_wq[hotcpu].thread,
+			kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread,
 				     smp_processor_id());
 			cleanup_workqueue_thread(wq, hotcpu);
 		}
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 016e89a..156822e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -128,7 +128,7 @@
 config DEBUG_BUGVERBOSE
 	bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
 	depends on BUG
-	depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64) || FRV
+	depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV
 	default !EMBEDDED
 	help
 	  Say Y here to make BUG() panics output the file name and line number
@@ -168,13 +168,34 @@
 
 	  If unsure, say N.
 
+config DEBUG_VM
+	bool "Debug VM"
+	depends on DEBUG_KERNEL
+	help
+	  Enable this to debug the virtual-memory system.
+
+	  If unsure, say N.
+
 config FRAME_POINTER
 	bool "Compile the kernel with frame pointers"
 	depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
 	default y if DEBUG_INFO && UML
 	help
 	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it might give very useful debugging information
-	  on some architectures or you use external debuggers.
+	  and slower, but it might give very useful debugging information on
+	  some architectures or if you use external debuggers.
 	  If you don't debug the kernel, you can say N.
 
+config RCU_TORTURE_TEST
+	tristate "torture tests for RCU"
+	depends on DEBUG_KERNEL
+	default n
+	help
+	  This option provides a kernel module that runs torture tests
+	  on the RCU infrastructure.  The kernel module may be built
+	  after the fact on the running kernel to be tested, if desired.
+
+	  Say Y here if you want RCU torture tests to start automatically
+	  at boot time (you probably don't).
+	  Say M if you want the RCU torture tests to build as a module.
+	  Say N if you are unsure.
diff --git a/lib/bitmap.c b/lib/bitmap.c
index fb9371f..23d3b11 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -511,6 +511,172 @@
 }
 EXPORT_SYMBOL(bitmap_parselist);
 
+/*
+ * bitmap_pos_to_ord(buf, pos, bits)
+ *	@buf: pointer to a bitmap
+ *	@pos: a bit position in @buf (0 <= @pos < @bits)
+ *	@bits: number of valid bit positions in @buf
+ *
+ * Map the bit at position @pos in @buf (of length @bits) to the
+ * ordinal of which set bit it is.  If it is not set or if @pos
+ * is not a valid bit position, map to zero (0).
+ *
+ * If for example, just bits 4 through 7 are set in @buf, then @pos
+ * values 4 through 7 will get mapped to 0 through 3, respectively,
+ * and other @pos values will get mapped to 0.  When @pos value 7
+ * gets mapped to (returns) @ord value 3 in this example, that means
+ * that bit 7 is the 3rd (starting with 0th) set bit in @buf.
+ *
+ * The bit positions 0 through @bits are valid positions in @buf.
+ */
+static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
+{
+	int ord = 0;
+
+	if (pos >= 0 && pos < bits) {
+		int i;
+
+		for (i = find_first_bit(buf, bits);
+		     i < pos;
+		     i = find_next_bit(buf, bits, i + 1))
+	     		ord++;
+		if (i > pos)
+			ord = 0;
+	}
+	return ord;
+}
+
+/**
+ * bitmap_ord_to_pos(buf, ord, bits)
+ *	@buf: pointer to bitmap
+ *	@ord: ordinal bit position (n-th set bit, n >= 0)
+ *	@bits: number of valid bit positions in @buf
+ *
+ * Map the ordinal offset of bit @ord in @buf to its position in @buf.
+ * If @ord is not the ordinal offset of a set bit in @buf, map to zero (0).
+ *
+ * If for example, just bits 4 through 7 are set in @buf, then @ord
+ * values 0 through 3 will get mapped to 4 through 7, respectively,
+ * and all other @ord valuds will get mapped to 0.  When @ord value 3
+ * gets mapped to (returns) @pos value 7 in this example, that means
+ * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
+ *
+ * The bit positions 0 through @bits are valid positions in @buf.
+ */
+static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
+{
+	int pos = 0;
+
+	if (ord >= 0 && ord < bits) {
+		int i;
+
+		for (i = find_first_bit(buf, bits);
+		     i < bits && ord > 0;
+		     i = find_next_bit(buf, bits, i + 1))
+	     		ord--;
+		if (i < bits && ord == 0)
+			pos = i;
+	}
+
+	return pos;
+}
+
+/**
+ * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap
+ *	@src: subset to be remapped
+ *	@dst: remapped result
+ *	@old: defines domain of map
+ *	@new: defines range of map
+ *	@bits: number of bits in each of these bitmaps
+ *
+ * Let @old and @new define a mapping of bit positions, such that
+ * whatever position is held by the n-th set bit in @old is mapped
+ * to the n-th set bit in @new.  In the more general case, allowing
+ * for the possibility that the weight 'w' of @new is less than the
+ * weight of @old, map the position of the n-th set bit in @old to
+ * the position of the m-th set bit in @new, where m == n % w.
+ *
+ * If either of the @old and @new bitmaps are empty, or if@src and @dst
+ * point to the same location, then this routine does nothing.
+ *
+ * The positions of unset bits in @old are mapped to the position of
+ * the first set bit in @new.
+ *
+ * Apply the above specified mapping to @src, placing the result in
+ * @dst, clearing any bits previously set in @dst.
+ *
+ * The resulting value of @dst will have either the same weight as
+ * @src, or less weight in the general case that the mapping wasn't
+ * injective due to the weight of @new being less than that of @old.
+ * The resulting value of @dst will never have greater weight than
+ * that of @src, except perhaps in the case that one of the above
+ * conditions was not met and this routine just returned.
+ *
+ * For example, lets say that @old has bits 4 through 7 set, and
+ * @new has bits 12 through 15 set.  This defines the mapping of bit
+ * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
+ * bit positions to 12 (the first set bit in @new.  So if say @src
+ * comes into this routine with bits 1, 5 and 7 set, then @dst should
+ * leave with bits 12, 13 and 15 set.
+ */
+void bitmap_remap(unsigned long *dst, const unsigned long *src,
+		const unsigned long *old, const unsigned long *new,
+		int bits)
+{
+	int s;
+
+	if (bitmap_weight(old, bits) == 0)
+		return;
+	if (bitmap_weight(new, bits) == 0)
+		return;
+	if (dst == src)		/* following doesn't handle inplace remaps */
+		return;
+
+	bitmap_zero(dst, bits);
+	for (s = find_first_bit(src, bits);
+	     s < bits;
+	     s = find_next_bit(src, bits, s + 1)) {
+	     	int x = bitmap_pos_to_ord(old, s, bits);
+		int y = bitmap_ord_to_pos(new, x, bits);
+		set_bit(y, dst);
+	}
+}
+EXPORT_SYMBOL(bitmap_remap);
+
+/**
+ * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit
+ *	@oldbit - bit position to be mapped
+ *      @old: defines domain of map
+ *      @new: defines range of map
+ *      @bits: number of bits in each of these bitmaps
+ *
+ * Let @old and @new define a mapping of bit positions, such that
+ * whatever position is held by the n-th set bit in @old is mapped
+ * to the n-th set bit in @new.  In the more general case, allowing
+ * for the possibility that the weight 'w' of @new is less than the
+ * weight of @old, map the position of the n-th set bit in @old to
+ * the position of the m-th set bit in @new, where m == n % w.
+ *
+ * The positions of unset bits in @old are mapped to the position of
+ * the first set bit in @new.
+ *
+ * Apply the above specified mapping to bit position @oldbit, returning
+ * the new bit position.
+ *
+ * For example, lets say that @old has bits 4 through 7 set, and
+ * @new has bits 12 through 15 set.  This defines the mapping of bit
+ * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
+ * bit positions to 12 (the first set bit in @new.  So if say @oldbit
+ * is 5, then this routine returns 13.
+ */
+int bitmap_bitremap(int oldbit, const unsigned long *old,
+				const unsigned long *new, int bits)
+{
+	int x = bitmap_pos_to_ord(old, oldbit, bits);
+	return bitmap_ord_to_pos(new, x, bits);
+}
+EXPORT_SYMBOL(bitmap_bitremap);
+
 /**
  *	bitmap_find_free_region - find a contiguous aligned mem region
  *	@bitmap: an array of unsigned longs corresponding to the bitmap
diff --git a/lib/extable.c b/lib/extable.c
index 3f677a8..18df57c 100644
--- a/lib/extable.c
+++ b/lib/extable.c
@@ -16,9 +16,6 @@
 #include <linux/sort.h>
 #include <asm/uaccess.h>
 
-extern struct exception_table_entry __start___ex_table[];
-extern struct exception_table_entry __stop___ex_table[];
-
 #ifndef ARCH_HAS_SORT_EXTABLE
 /*
  * The exception table needs to be sorted so that the binary
diff --git a/lib/idr.c b/lib/idr.c
index d4df21d..d226259 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -6,20 +6,20 @@
  * Modified by George Anzinger to reuse immediately and to use
  * find bit instructions.  Also removed _irq on spinlocks.
  *
- * Small id to pointer translation service.  
+ * Small id to pointer translation service.
  *
- * It uses a radix tree like structure as a sparse array indexed 
+ * It uses a radix tree like structure as a sparse array indexed
  * by the id to obtain the pointer.  The bitmap makes allocating
- * a new id quick.  
+ * a new id quick.
  *
  * You call it to allocate an id (an int) an associate with that id a
  * pointer or what ever, we treat it as a (void *).  You can pass this
  * id to a user for him to pass back at a later time.  You then pass
  * that id to this code and it returns your pointer.
 
- * You can release ids at any time. When all ids are released, most of 
+ * You can release ids at any time. When all ids are released, most of
  * the memory is returned (we keep IDR_FREE_MAX) in a local pool so we
- * don't need to go to the memory "store" during an id allocate, just 
+ * don't need to go to the memory "store" during an id allocate, just
  * so you don't need to be too concerned about locking and conflicts
  * with the slab allocator.
  */
@@ -72,12 +72,12 @@
  * If the system is REALLY out of memory this function returns 0,
  * otherwise 1.
  */
-int idr_pre_get(struct idr *idp, unsigned gfp_mask)
+int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
 	while (idp->id_free_cnt < IDR_FREE_MAX) {
 		struct idr_layer *new;
 		new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
-		if(new == NULL)
+		if (new == NULL)
 			return (0);
 		free_layer(idp, new);
 	}
@@ -107,7 +107,7 @@
 		if (m == IDR_SIZE) {
 			/* no space available go back to previous layer. */
 			l++;
-			id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
+			id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
 			if (!(p = pa[l])) {
 				*starting_id = id;
 				return -2;
@@ -161,7 +161,7 @@
 {
 	struct idr_layer *p, *new;
 	int layers, v, id;
-	
+
 	id = starting_id;
 build_up:
 	p = idp->top;
@@ -225,6 +225,7 @@
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
 	int rv;
+
 	rv = idr_get_new_above_int(idp, ptr, starting_id);
 	/*
 	 * This is a cheap hack until the IDR code can be fixed to
@@ -259,6 +260,7 @@
 int idr_get_new(struct idr *idp, void *ptr, int *id)
 {
 	int rv;
+
 	rv = idr_get_new_above_int(idp, ptr, 0);
 	/*
 	 * This is a cheap hack until the IDR code can be fixed to
@@ -306,11 +308,10 @@
 			free_layer(idp, **paa);
 			**paa-- = NULL;
 		}
-		if ( ! *paa )
+		if (!*paa)
 			idp->layers = 0;
-	} else {
+	} else
 		idr_remove_warning(id);
-	}
 }
 
 /**
@@ -326,9 +327,8 @@
 	id &= MAX_ID_MASK;
 
 	sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
-	if ( idp->top && idp->top->count == 1 && 
-	     (idp->layers > 1) &&
-	     idp->top->ary[0]){  // We can drop a layer
+	if (idp->top && idp->top->count == 1 && (idp->layers > 1) &&
+	    idp->top->ary[0]) {  // We can drop a layer
 
 		p = idp->top->ary[0];
 		idp->top->bitmap = idp->top->count = 0;
@@ -337,7 +337,6 @@
 		--idp->layers;
 	}
 	while (idp->id_free_cnt >= IDR_FREE_MAX) {
-		
 		p = alloc_layer(idp);
 		kmem_cache_free(idr_layer_cache, p);
 		return;
@@ -391,8 +390,8 @@
 }
 EXPORT_SYMBOL(idr_find);
 
-static void idr_cache_ctor(void * idr_layer, 
-			   kmem_cache_t *idr_layer_cache, unsigned long flags)
+static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache,
+		unsigned long flags)
 {
 	memset(idr_layer, 0, sizeof(struct idr_layer));
 }
@@ -400,7 +399,7 @@
 static  int init_id_cache(void)
 {
 	if (!idr_layer_cache)
-		idr_layer_cache = kmem_cache_create("idr_layer_cache", 
+		idr_layer_cache = kmem_cache_create("idr_layer_cache",
 			sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL);
 	return 0;
 }
diff --git a/lib/kobject.c b/lib/kobject.c
index dd0917d..a181abe 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/stat.h>
+#include <linux/slab.h>
 
 /**
  *	populate_dir - populate directory with attributes.
@@ -100,7 +101,7 @@
  * @kobj:	kobject in question, with which to build the path
  * @gfp_mask:	the allocation type used to allocate the path
  */
-char *kobject_get_path(struct kobject *kobj, int gfp_mask)
+char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
 {
 	char *path;
 	int len;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 04ca442..3ab3754 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -54,7 +54,7 @@
 static struct sock *uevent_sock;
 
 /**
- * send_uevent - notify userspace by sending event trough netlink socket
+ * send_uevent - notify userspace by sending event through netlink socket
  *
  * @signal: signal name
  * @obj: object path (kobject)
@@ -62,7 +62,7 @@
  * @gfp_mask:
  */
 static int send_uevent(const char *signal, const char *obj,
-		       char **envp, int gfp_mask)
+		       char **envp, gfp_t gfp_mask)
 {
 	struct sk_buff *skb;
 	char *pos;
@@ -98,7 +98,7 @@
 }
 
 static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action, 
-			     struct attribute *attr, int gfp_mask)
+			     struct attribute *attr, gfp_t gfp_mask)
 {
 	char *path;
 	char *attrpath;
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index 42c08ef..eddc9b3 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -5,6 +5,7 @@
  */
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/sched.h>
 
 unsigned int debug_smp_processor_id(void)
 {
diff --git a/lib/sort.c b/lib/sort.c
index ddc4d35..5f3b51f 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sort.h>
+#include <linux/slab.h>
 
 static void u32_swap(void *a, void *b, int size)
 {
diff --git a/lib/string.c b/lib/string.c
index d886ef1..037a48a 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -36,11 +36,13 @@
 	/* Yes, Virginia, it had better be unsigned */
 	unsigned char c1, c2;
 
-	c1 = 0;	c2 = 0;
+	c1 = c2 = 0;
 	if (len) {
 		do {
-			c1 = *s1; c2 = *s2;
-			s1++; s2++;
+			c1 = *s1;
+			c2 = *s2;
+			s1++;
+			s2++;
 			if (!c1)
 				break;
 			if (!c2)
@@ -55,7 +57,6 @@
 	}
 	return (int)c1 - (int)c2;
 }
-
 EXPORT_SYMBOL(strnicmp);
 #endif
 
@@ -66,7 +67,7 @@
  * @src: Where to copy the string from
  */
 #undef strcpy
-char * strcpy(char * dest,const char *src)
+char *strcpy(char *dest, const char *src)
 {
 	char *tmp = dest;
 
@@ -91,12 +92,13 @@
  * count, the remainder of @dest will be padded with %NUL.
  *
  */
-char * strncpy(char * dest,const char *src,size_t count)
+char *strncpy(char *dest, const char *src, size_t count)
 {
 	char *tmp = dest;
 
 	while (count) {
-		if ((*tmp = *src) != 0) src++;
+		if ((*tmp = *src) != 0)
+			src++;
 		tmp++;
 		count--;
 	}
@@ -122,7 +124,7 @@
 	size_t ret = strlen(src);
 
 	if (size) {
-		size_t len = (ret >= size) ? size-1 : ret;
+		size_t len = (ret >= size) ? size - 1 : ret;
 		memcpy(dest, src, len);
 		dest[len] = '\0';
 	}
@@ -138,7 +140,7 @@
  * @src: The string to append to it
  */
 #undef strcat
-char * strcat(char * dest, const char * src)
+char *strcat(char *dest, const char *src)
 {
 	char *tmp = dest;
 
@@ -146,7 +148,6 @@
 		dest++;
 	while ((*dest++ = *src++) != '\0')
 		;
-
 	return tmp;
 }
 EXPORT_SYMBOL(strcat);
@@ -162,7 +163,7 @@
  * Note that in contrast to strncpy, strncat ensures the result is
  * terminated.
  */
-char * strncat(char *dest, const char *src, size_t count)
+char *strncat(char *dest, const char *src, size_t count)
 {
 	char *tmp = dest;
 
@@ -176,7 +177,6 @@
 			}
 		}
 	}
-
 	return tmp;
 }
 EXPORT_SYMBOL(strncat);
@@ -216,15 +216,14 @@
  * @ct: Another string
  */
 #undef strcmp
-int strcmp(const char * cs,const char * ct)
+int strcmp(const char *cs, const char *ct)
 {
-	register signed char __res;
+	signed char __res;
 
 	while (1) {
 		if ((__res = *cs - *ct++) != 0 || !*cs++)
 			break;
 	}
-
 	return __res;
 }
 EXPORT_SYMBOL(strcmp);
@@ -237,16 +236,15 @@
  * @ct: Another string
  * @count: The maximum number of bytes to compare
  */
-int strncmp(const char * cs,const char * ct,size_t count)
+int strncmp(const char *cs, const char *ct, size_t count)
 {
-	register signed char __res = 0;
+	signed char __res = 0;
 
 	while (count) {
 		if ((__res = *cs - *ct++) != 0 || !*cs++)
 			break;
 		count--;
 	}
-
 	return __res;
 }
 EXPORT_SYMBOL(strncmp);
@@ -258,12 +256,12 @@
  * @s: The string to be searched
  * @c: The character to search for
  */
-char * strchr(const char * s, int c)
+char *strchr(const char *s, int c)
 {
-	for(; *s != (char) c; ++s)
+	for (; *s != (char)c; ++s)
 		if (*s == '\0')
 			return NULL;
-	return (char *) s;
+	return (char *)s;
 }
 EXPORT_SYMBOL(strchr);
 #endif
@@ -274,7 +272,7 @@
  * @s: The string to be searched
  * @c: The character to search for
  */
-char * strrchr(const char * s, int c)
+char *strrchr(const char *s, int c)
 {
        const char *p = s + strlen(s);
        do {
@@ -296,8 +294,8 @@
 char *strnchr(const char *s, size_t count, int c)
 {
 	for (; count-- && *s != '\0'; ++s)
-		if (*s == (char) c)
-			return (char *) s;
+		if (*s == (char)c)
+			return (char *)s;
 	return NULL;
 }
 EXPORT_SYMBOL(strnchr);
@@ -308,7 +306,7 @@
  * strlen - Find the length of a string
  * @s: The string to be sized
  */
-size_t strlen(const char * s)
+size_t strlen(const char *s)
 {
 	const char *sc;
 
@@ -325,7 +323,7 @@
  * @s: The string to be sized
  * @count: The maximum number of bytes to search
  */
-size_t strnlen(const char * s, size_t count)
+size_t strnlen(const char *s, size_t count)
 {
 	const char *sc;
 
@@ -358,7 +356,6 @@
 			return count;
 		++count;
 	}
-
 	return count;
 }
 
@@ -384,9 +381,8 @@
 		}
 		++count;
 	}
-
 	return count;
-}	
+}
 EXPORT_SYMBOL(strcspn);
 
 #ifndef __HAVE_ARCH_STRPBRK
@@ -395,14 +391,14 @@
  * @cs: The string to be searched
  * @ct: The characters to search for
  */
-char * strpbrk(const char * cs,const char * ct)
+char *strpbrk(const char *cs, const char *ct)
 {
-	const char *sc1,*sc2;
+	const char *sc1, *sc2;
 
-	for( sc1 = cs; *sc1 != '\0'; ++sc1) {
-		for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+	for (sc1 = cs; *sc1 != '\0'; ++sc1) {
+		for (sc2 = ct; *sc2 != '\0'; ++sc2) {
 			if (*sc1 == *sc2)
-				return (char *) sc1;
+				return (char *)sc1;
 		}
 	}
 	return NULL;
@@ -422,9 +418,10 @@
  * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
  * Same semantics, slimmer shape. ;)
  */
-char * strsep(char **s, const char *ct)
+char *strsep(char **s, const char *ct)
 {
-	char *sbegin = *s, *end;
+	char *sbegin = *s;
+	char *end;
 
 	if (sbegin == NULL)
 		return NULL;
@@ -433,10 +430,8 @@
 	if (end)
 		*end++ = '\0';
 	*s = end;
-
 	return sbegin;
 }
-
 EXPORT_SYMBOL(strsep);
 #endif
 
@@ -449,13 +444,12 @@
  *
  * Do not use memset() to access IO space, use memset_io() instead.
  */
-void * memset(void * s,int c,size_t count)
+void *memset(void *s, int c, size_t count)
 {
-	char *xs = (char *) s;
+	char *xs = s;
 
 	while (count--)
 		*xs++ = c;
-
 	return s;
 }
 EXPORT_SYMBOL(memset);
@@ -471,13 +465,13 @@
  * You should not use this function to access IO space, use memcpy_toio()
  * or memcpy_fromio() instead.
  */
-void * memcpy(void * dest,const void *src,size_t count)
+void *memcpy(void *dest, const void *src, size_t count)
 {
-	char *tmp = (char *) dest, *s = (char *) src;
+	char *tmp = dest;
+	char *s = src;
 
 	while (count--)
 		*tmp++ = *s++;
-
 	return dest;
 }
 EXPORT_SYMBOL(memcpy);
@@ -492,23 +486,24 @@
  *
  * Unlike memcpy(), memmove() copes with overlapping areas.
  */
-void * memmove(void * dest,const void *src,size_t count)
+void *memmove(void *dest, const void *src, size_t count)
 {
-	char *tmp, *s;
+	char *tmp;
+	const char *s;
 
 	if (dest <= src) {
-		tmp = (char *) dest;
-		s = (char *) src;
+		tmp = dest;
+		s = src;
 		while (count--)
 			*tmp++ = *s++;
-		}
-	else {
-		tmp = (char *) dest + count;
-		s = (char *) src + count;
+	} else {
+		tmp = dest;
+		tmp += count;
+		s = src;
+		s += count;
 		while (count--)
 			*--tmp = *--s;
-		}
-
+	}
 	return dest;
 }
 EXPORT_SYMBOL(memmove);
@@ -522,12 +517,12 @@
  * @count: The size of the area.
  */
 #undef memcmp
-int memcmp(const void * cs,const void * ct,size_t count)
+int memcmp(const void *cs, const void *ct, size_t count)
 {
 	const unsigned char *su1, *su2;
 	int res = 0;
 
-	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
 		if ((res = *su1 - *su2) != 0)
 			break;
 	return res;
@@ -545,17 +540,17 @@
  * returns the address of the first occurrence of @c, or 1 byte past
  * the area if @c is not found
  */
-void * memscan(void * addr, int c, size_t size)
+void *memscan(void *addr, int c, size_t size)
 {
-	unsigned char * p = (unsigned char *) addr;
+	unsigned char *p = addr;
 
 	while (size) {
 		if (*p == c)
-			return (void *) p;
+			return (void *)p;
 		p++;
 		size--;
 	}
-  	return (void *) p;
+  	return (void *)p;
 }
 EXPORT_SYMBOL(memscan);
 #endif
@@ -566,18 +561,18 @@
  * @s1: The string to be searched
  * @s2: The string to search for
  */
-char * strstr(const char * s1,const char * s2)
+char *strstr(const char *s1, const char *s2)
 {
 	int l1, l2;
 
 	l2 = strlen(s2);
 	if (!l2)
-		return (char *) s1;
+		return (char *)s1;
 	l1 = strlen(s1);
 	while (l1 >= l2) {
 		l1--;
-		if (!memcmp(s1,s2,l2))
-			return (char *) s1;
+		if (!memcmp(s1, s2, l2))
+			return (char *)s1;
 		s1++;
 	}
 	return NULL;
@@ -600,7 +595,7 @@
 	const unsigned char *p = s;
 	while (n-- != 0) {
         	if ((unsigned char)c == *p++) {
-			return (void *)(p-1);
+			return (void *)(p - 1);
 		}
 	}
 	return NULL;
diff --git a/lib/textsearch.c b/lib/textsearch.c
index 1e934c1..6f3093e 100644
--- a/lib/textsearch.c
+++ b/lib/textsearch.c
@@ -254,7 +254,7 @@
  *         parameters or a ERR_PTR().
  */
 struct ts_config *textsearch_prepare(const char *algo, const void *pattern,
-				     unsigned int len, int gfp_mask, int flags)
+				     unsigned int len, gfp_t gfp_mask, int flags)
 {
 	int err = -ENOENT;
 	struct ts_config *conf;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index e4e9031..b07db5c 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -23,6 +23,7 @@
 #include <linux/ctype.h>
 #include <linux/kernel.h>
 
+#include <asm/page.h>		/* for PAGE_SIZE */
 #include <asm/div64.h>
 
 /**
diff --git a/mm/Kconfig b/mm/Kconfig
index 391ffc5..1a4473fc 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -111,3 +111,24 @@
 config SPARSEMEM_EXTREME
 	def_bool y
 	depends on SPARSEMEM && !SPARSEMEM_STATIC
+
+# eventually, we can have this option just 'select SPARSEMEM'
+config MEMORY_HOTPLUG
+	bool "Allow for memory hot-add"
+	depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND
+
+comment "Memory hotplug is currently incompatible with Software Suspend"
+	depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
+
+# Heavily threaded applications may benefit from splitting the mm-wide
+# page_table_lock, so that faults on different parts of the user address
+# space can be handled with less contention: split it at this NR_CPUS.
+# Default to 4 for wider testing, though 8 might be more appropriate.
+# ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock.
+# PA-RISC's debug spinlock_t is too large for the 32-bit struct page.
+#
+config SPLIT_PTLOCK_CPUS
+	int
+	default "4096" if ARM && !CPU_CACHE_VIPT
+	default "4096" if PARISC && DEBUG_SPINLOCK && !64BIT
+	default "4"
diff --git a/mm/Makefile b/mm/Makefile
index 4cd69e3..2fa6d2c 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -18,5 +18,5 @@
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SHMEM) += shmem.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
-
+obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index a58699b..e8c5671 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -305,6 +305,7 @@
 				if (j + 16 < BITS_PER_LONG)
 					prefetchw(page + j + 16);
 				__ClearPageReserved(page + j);
+				set_page_count(page + j, 0);
 			}
 			__free_pages(page, order);
 			i += BITS_PER_LONG;
diff --git a/mm/filemap.c b/mm/filemap.c
index b534657..5d6e4c2 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -66,7 +66,7 @@
  *
  *  ->mmap_sem
  *    ->i_mmap_lock
- *      ->page_table_lock	(various places, mainly in mmap.c)
+ *      ->page_table_lock or pte_lock	(various, mainly in memory.c)
  *        ->mapping->tree_lock	(arch-dependent flush_dcache_mmap_lock)
  *
  *  ->mmap_sem
@@ -86,9 +86,9 @@
  *    ->anon_vma.lock		(vma_adjust)
  *
  *  ->anon_vma.lock
- *    ->page_table_lock		(anon_vma_prepare and various)
+ *    ->page_table_lock or pte_lock	(anon_vma_prepare and various)
  *
- *  ->page_table_lock
+ *  ->page_table_lock or pte_lock
  *    ->swap_lock		(try_to_unmap_one)
  *    ->private_lock		(try_to_unmap_one)
  *    ->tree_lock		(try_to_unmap_one)
@@ -152,7 +152,7 @@
 	 * in the ->sync_page() methods make essential use of the
 	 * page_mapping(), merely passing the page down to the backing
 	 * device's unplug functions when it's non-NULL, which in turn
-	 * ignore it for all cases but swap, where only page->private is
+	 * ignore it for all cases but swap, where only page_private(page) is
 	 * of interest. When page_mapping() does go NULL, the entire
 	 * call stack gracefully ignores the page and returns.
 	 * -- wli
@@ -377,7 +377,7 @@
  * This function does not add the page to the LRU.  The caller must do that.
  */
 int add_to_page_cache(struct page *page, struct address_space *mapping,
-		pgoff_t offset, int gfp_mask)
+		pgoff_t offset, gfp_t gfp_mask)
 {
 	int error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
 
@@ -401,7 +401,7 @@
 EXPORT_SYMBOL(add_to_page_cache);
 
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
-				pgoff_t offset, int gfp_mask)
+				pgoff_t offset, gfp_t gfp_mask)
 {
 	int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
 	if (ret == 0)
@@ -591,7 +591,7 @@
  * memory exhaustion.
  */
 struct page *find_or_create_page(struct address_space *mapping,
-		unsigned long index, unsigned int gfp_mask)
+		unsigned long index, gfp_t gfp_mask)
 {
 	struct page *page, *cached_page = NULL;
 	int err;
@@ -683,7 +683,7 @@
 grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
 {
 	struct page *page = find_get_page(mapping, index);
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 
 	if (page) {
 		if (!TestSetPageLocked(page))
@@ -1030,8 +1030,8 @@
 			desc.error = 0;
 			do_generic_file_read(filp,ppos,&desc,file_read_actor);
 			retval += desc.written;
-			if (!retval) {
-				retval = desc.error;
+			if (desc.error) {
+				retval = retval ?: desc.error;
 				break;
 			}
 		}
@@ -1520,7 +1520,7 @@
 			page_cache_release(page);
 			return err;
 		}
-	} else {
+	} else if (vma->vm_flags & VM_NONLINEAR) {
 		/* No page was found just because we can't read it in now (being
 		 * here implies nonblock != 0), but the page may exist, so set
 		 * the PTE to fault it in later. */
@@ -1537,6 +1537,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(filemap_populate);
 
 struct vm_operations_struct generic_file_vm_ops = {
 	.nopage		= filemap_nopage,
@@ -1555,7 +1556,6 @@
 	vma->vm_ops = &generic_file_vm_ops;
 	return 0;
 }
-EXPORT_SYMBOL(filemap_populate);
 
 /*
  * This is for filesystems which do not implement ->writepage.
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 8c199f5..9cf687e 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -174,6 +174,8 @@
 	unsigned long address;
 	pte_t *pte;
 	pte_t pteval;
+	spinlock_t *ptl;
+	struct page *page;
 
 	spin_lock(&mapping->i_mmap_lock);
 	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
@@ -181,19 +183,17 @@
 		address = vma->vm_start +
 			((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
 		BUG_ON(address < vma->vm_start || address >= vma->vm_end);
-		/*
-		 * We need the page_table_lock to protect us from page faults,
-		 * munmap, fork, etc...
-		 */
-		pte = page_check_address(ZERO_PAGE(address), mm,
-					 address);
-		if (!IS_ERR(pte)) {
+		page = ZERO_PAGE(address);
+		pte = page_check_address(page, mm, address, &ptl);
+		if (pte) {
 			/* Nuke the page table entry. */
 			flush_cache_page(vma, address, pte_pfn(*pte));
 			pteval = ptep_clear_flush(vma, address, pte);
+			page_remove_rmap(page);
+			dec_mm_counter(mm, file_rss);
 			BUG_ON(pte_dirty(pteval));
-			pte_unmap(pte);
-			spin_unlock(&mm->page_table_lock);
+			pte_unmap_unlock(pte, ptl);
+			page_cache_release(page);
 		}
 	}
 	spin_unlock(&mapping->i_mmap_lock);
@@ -228,7 +228,7 @@
 
 	page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0);
 	if (!IS_ERR(page)) {
-		return page;
+		goto out;
 	}
 	if (PTR_ERR(page) != -ENODATA)
 		return NULL;
@@ -249,6 +249,8 @@
 		page = ZERO_PAGE(address);
 	}
 
+out:
+	page_cache_get(page);
 	return page;
 }
 
diff --git a/mm/fremap.c b/mm/fremap.c
index ab23a06..d862be3 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -20,33 +20,32 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-static inline void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
+static int zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long addr, pte_t *ptep)
 {
 	pte_t pte = *ptep;
+	struct page *page = NULL;
 
-	if (pte_none(pte))
-		return;
 	if (pte_present(pte)) {
 		unsigned long pfn = pte_pfn(pte);
-
 		flush_cache_page(vma, addr, pfn);
 		pte = ptep_clear_flush(vma, addr, ptep);
-		if (pfn_valid(pfn)) {
-			struct page *page = pfn_to_page(pfn);
-			if (!PageReserved(page)) {
-				if (pte_dirty(pte))
-					set_page_dirty(page);
-				page_remove_rmap(page);
-				page_cache_release(page);
-				dec_mm_counter(mm, rss);
-			}
+		if (unlikely(!pfn_valid(pfn))) {
+			print_bad_pte(vma, pte, addr);
+			goto out;
 		}
+		page = pfn_to_page(pfn);
+		if (pte_dirty(pte))
+			set_page_dirty(page);
+		page_remove_rmap(page);
+		page_cache_release(page);
 	} else {
 		if (!pte_file(pte))
 			free_swap_and_cache(pte_to_swp_entry(pte));
 		pte_clear(mm, addr, ptep);
 	}
+out:
+	return !!page;
 }
 
 /*
@@ -64,21 +63,20 @@
 	pud_t *pud;
 	pgd_t *pgd;
 	pte_t pte_val;
+	spinlock_t *ptl;
+
+	BUG_ON(vma->vm_flags & VM_RESERVED);
 
 	pgd = pgd_offset(mm, addr);
-	spin_lock(&mm->page_table_lock);
-	
 	pud = pud_alloc(mm, pgd, addr);
 	if (!pud)
-		goto err_unlock;
-
+		goto out;
 	pmd = pmd_alloc(mm, pud, addr);
 	if (!pmd)
-		goto err_unlock;
-
-	pte = pte_alloc_map(mm, pmd, addr);
+		goto out;
+	pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
 	if (!pte)
-		goto err_unlock;
+		goto out;
 
 	/*
 	 * This page may have been truncated. Tell the
@@ -88,29 +86,27 @@
 	inode = vma->vm_file->f_mapping->host;
 	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (!page->mapping || page->index >= size)
-		goto err_unlock;
+		goto unlock;
 	err = -ENOMEM;
 	if (page_mapcount(page) > INT_MAX/2)
-		goto err_unlock;
+		goto unlock;
 
-	zap_pte(mm, vma, addr, pte);
+	if (pte_none(*pte) || !zap_pte(mm, vma, addr, pte))
+		inc_mm_counter(mm, file_rss);
 
-	inc_mm_counter(mm,rss);
 	flush_icache_page(vma, page);
 	set_pte_at(mm, addr, pte, mk_pte(page, prot));
 	page_add_file_rmap(page);
 	pte_val = *pte;
-	pte_unmap(pte);
 	update_mmu_cache(vma, addr, pte_val);
-
 	err = 0;
-err_unlock:
-	spin_unlock(&mm->page_table_lock);
+unlock:
+	pte_unmap_unlock(pte, ptl);
+out:
 	return err;
 }
 EXPORT_SYMBOL(install_page);
 
-
 /*
  * Install a file pte to a given virtual memory address, release any
  * previously existing mapping.
@@ -124,37 +120,35 @@
 	pud_t *pud;
 	pgd_t *pgd;
 	pte_t pte_val;
+	spinlock_t *ptl;
+
+	BUG_ON(vma->vm_flags & VM_RESERVED);
 
 	pgd = pgd_offset(mm, addr);
-	spin_lock(&mm->page_table_lock);
-	
 	pud = pud_alloc(mm, pgd, addr);
 	if (!pud)
-		goto err_unlock;
-
+		goto out;
 	pmd = pmd_alloc(mm, pud, addr);
 	if (!pmd)
-		goto err_unlock;
-
-	pte = pte_alloc_map(mm, pmd, addr);
+		goto out;
+	pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
 	if (!pte)
-		goto err_unlock;
+		goto out;
 
-	zap_pte(mm, vma, addr, pte);
+	if (!pte_none(*pte) && zap_pte(mm, vma, addr, pte)) {
+		update_hiwater_rss(mm);
+		dec_mm_counter(mm, file_rss);
+	}
 
 	set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
 	pte_val = *pte;
-	pte_unmap(pte);
 	update_mmu_cache(vma, addr, pte_val);
-	spin_unlock(&mm->page_table_lock);
-	return 0;
-
-err_unlock:
-	spin_unlock(&mm->page_table_lock);
+	pte_unmap_unlock(pte, ptl);
+	err = 0;
+out:
 	return err;
 }
 
-
 /***
  * sys_remap_file_pages - remap arbitrary pages of a shared backing store
  *                        file within an existing vma.
diff --git a/mm/highmem.c b/mm/highmem.c
index 90e1861e..ce2e7e8 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -30,11 +30,9 @@
 
 static mempool_t *page_pool, *isa_page_pool;
 
-static void *page_pool_alloc(gfp_t gfp_mask, void *data)
+static void *page_pool_alloc_isa(gfp_t gfp_mask, void *data)
 {
-	unsigned int gfp = gfp_mask | (unsigned int) (long) data;
-
-	return alloc_page(gfp);
+	return alloc_page(gfp_mask | GFP_DMA);
 }
 
 static void page_pool_free(void *page, void *data)
@@ -51,6 +49,12 @@
  *  n means that there are (n-1) current users of it.
  */
 #ifdef CONFIG_HIGHMEM
+
+static void *page_pool_alloc(gfp_t gfp_mask, void *data)
+{
+	return alloc_page(gfp_mask);
+}
+
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(kmap_lock);
@@ -267,7 +271,7 @@
 	if (isa_page_pool)
 		return 0;
 
-	isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc, page_pool_free, (void *) __GFP_DMA);
+	isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc_isa, page_pool_free, NULL);
 	if (!isa_page_pool)
 		BUG();
 
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 61d3806..c9b4336 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -277,19 +277,23 @@
 	unsigned long addr;
 
 	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+		src_pte = huge_pte_offset(src, addr);
+		if (!src_pte)
+			continue;
 		dst_pte = huge_pte_alloc(dst, addr);
 		if (!dst_pte)
 			goto nomem;
+		spin_lock(&dst->page_table_lock);
 		spin_lock(&src->page_table_lock);
-		src_pte = huge_pte_offset(src, addr);
-		if (src_pte && !pte_none(*src_pte)) {
+		if (!pte_none(*src_pte)) {
 			entry = *src_pte;
 			ptepage = pte_page(entry);
 			get_page(ptepage);
-			add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
+			add_mm_counter(dst, file_rss, HPAGE_SIZE / PAGE_SIZE);
 			set_huge_pte_at(dst, addr, dst_pte, entry);
 		}
 		spin_unlock(&src->page_table_lock);
+		spin_unlock(&dst->page_table_lock);
 	}
 	return 0;
 
@@ -310,12 +314,14 @@
 	BUG_ON(start & ~HPAGE_MASK);
 	BUG_ON(end & ~HPAGE_MASK);
 
+	spin_lock(&mm->page_table_lock);
+
+	/* Update high watermark before we lower rss */
+	update_hiwater_rss(mm);
+
 	for (address = start; address < end; address += HPAGE_SIZE) {
 		ptep = huge_pte_offset(mm, address);
-		if (! ptep)
-			/* This can happen on truncate, or if an
-			 * mmap() is aborted due to an error before
-			 * the prefault */
+		if (!ptep)
 			continue;
 
 		pte = huge_ptep_get_and_clear(mm, address, ptep);
@@ -324,96 +330,99 @@
 
 		page = pte_page(pte);
 		put_page(page);
-		add_mm_counter(mm, rss,  - (HPAGE_SIZE / PAGE_SIZE));
+		add_mm_counter(mm, file_rss, (int) -(HPAGE_SIZE / PAGE_SIZE));
 	}
+
+	spin_unlock(&mm->page_table_lock);
 	flush_tlb_range(vma, start, end);
 }
 
-void zap_hugepage_range(struct vm_area_struct *vma,
-			unsigned long start, unsigned long length)
+static struct page *find_lock_huge_page(struct address_space *mapping,
+			unsigned long idx)
 {
-	struct mm_struct *mm = vma->vm_mm;
+	struct page *page;
+	int err;
+	struct inode *inode = mapping->host;
+	unsigned long size;
 
-	spin_lock(&mm->page_table_lock);
-	unmap_hugepage_range(vma, start, start + length);
-	spin_unlock(&mm->page_table_lock);
-}
+retry:
+	page = find_lock_page(mapping, idx);
+	if (page)
+		goto out;
 
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
+	/* Check to make sure the mapping hasn't been truncated */
+	size = i_size_read(inode) >> HPAGE_SHIFT;
+	if (idx >= size)
+		goto out;
 
-	WARN_ON(!is_vm_hugetlb_page(vma));
-	BUG_ON(vma->vm_start & ~HPAGE_MASK);
-	BUG_ON(vma->vm_end & ~HPAGE_MASK);
+	if (hugetlb_get_quota(mapping))
+		goto out;
+	page = alloc_huge_page();
+	if (!page) {
+		hugetlb_put_quota(mapping);
+		goto out;
+	}
 
-	hugetlb_prefault_arch_hook(mm);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				free_huge_page(page);
-				goto out;
-			}
-		}
-		add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-		set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page));
+	err = add_to_page_cache(page, mapping, idx, GFP_KERNEL);
+	if (err) {
+		put_page(page);
+		hugetlb_put_quota(mapping);
+		if (err == -EEXIST)
+			goto retry;
+		page = NULL;
 	}
 out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
+	return page;
 }
 
-/*
- * On ia64 at least, it is possible to receive a hugetlb fault from a
- * stale zero entry left in the TLB from earlier hardware prefetching.
- * Low-level arch code should already have flushed the stale entry as
- * part of its fault handling, but we do need to accept this minor fault
- * and return successfully.  Whereas the "normal" case is that this is
- * an access to a hugetlb page which has been truncated off since mmap.
- */
 int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, int write_access)
 {
 	int ret = VM_FAULT_SIGBUS;
+	unsigned long idx;
+	unsigned long size;
 	pte_t *pte;
+	struct page *page;
+	struct address_space *mapping;
+
+	pte = huge_pte_alloc(mm, address);
+	if (!pte)
+		goto out;
+
+	mapping = vma->vm_file->f_mapping;
+	idx = ((address - vma->vm_start) >> HPAGE_SHIFT)
+		+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+
+	/*
+	 * Use page lock to guard against racing truncation
+	 * before we get page_table_lock.
+	 */
+	page = find_lock_huge_page(mapping, idx);
+	if (!page)
+		goto out;
 
 	spin_lock(&mm->page_table_lock);
-	pte = huge_pte_offset(mm, address);
-	if (pte && !pte_none(*pte))
-		ret = VM_FAULT_MINOR;
+	size = i_size_read(mapping->host) >> HPAGE_SHIFT;
+	if (idx >= size)
+		goto backout;
+
+	ret = VM_FAULT_MINOR;
+	if (!pte_none(*pte))
+		goto backout;
+
+	add_mm_counter(mm, file_rss, HPAGE_SIZE / PAGE_SIZE);
+	set_huge_pte_at(mm, address, pte, make_huge_pte(vma, page));
 	spin_unlock(&mm->page_table_lock);
+	unlock_page(page);
+out:
 	return ret;
+
+backout:
+	spin_unlock(&mm->page_table_lock);
+	hugetlb_put_quota(mapping);
+	unlock_page(page);
+	put_page(page);
+	goto out;
 }
 
 int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -423,34 +432,36 @@
 	unsigned long vpfn, vaddr = *position;
 	int remainder = *length;
 
-	BUG_ON(!is_vm_hugetlb_page(vma));
-
 	vpfn = vaddr/PAGE_SIZE;
 	spin_lock(&mm->page_table_lock);
 	while (vaddr < vma->vm_end && remainder) {
+		pte_t *pte;
+		struct page *page;
+
+		/*
+		 * Some archs (sparc64, sh*) have multiple pte_ts to
+		 * each hugepage.  We have to make * sure we get the
+		 * first, for the page indexing below to work.
+		 */
+		pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+
+		if (!pte || pte_none(*pte)) {
+			int ret;
+
+			spin_unlock(&mm->page_table_lock);
+			ret = hugetlb_fault(mm, vma, vaddr, 0);
+			spin_lock(&mm->page_table_lock);
+			if (ret == VM_FAULT_MINOR)
+				continue;
+
+			remainder = 0;
+			if (!i)
+				i = -EFAULT;
+			break;
+		}
 
 		if (pages) {
-			pte_t *pte;
-			struct page *page;
-
-			/* Some archs (sparc64, sh*) have multiple
-			 * pte_ts to each hugepage.  We have to make
-			 * sure we get the first, for the page
-			 * indexing below to work. */
-			pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
-
-			/* the hugetlb file might have been truncated */
-			if (!pte || pte_none(*pte)) {
-				remainder = 0;
-				if (!i)
-					i = -EFAULT;
-				break;
-			}
-
 			page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
-			WARN_ON(!PageCompound(page));
-
 			get_page(page);
 			pages[i] = page;
 		}
diff --git a/mm/madvise.c b/mm/madvise.c
index 20e075d..17aaf3e 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -126,7 +126,7 @@
 			     unsigned long start, unsigned long end)
 {
 	*prev = vma;
-	if ((vma->vm_flags & VM_LOCKED) || is_vm_hugetlb_page(vma))
+	if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_RESERVED))
 		return -EINVAL;
 
 	if (unlikely(vma->vm_flags & VM_NONLINEAR)) {
diff --git a/mm/memory.c b/mm/memory.c
index 1db40e9..0f60baf 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -114,6 +114,7 @@
 {
 	struct page *page = pmd_page(*pmd);
 	pmd_clear(pmd);
+	pte_lock_deinit(page);
 	pte_free_tlb(tlb, page);
 	dec_page_state(nr_page_table_pages);
 	tlb->mm->nr_ptes--;
@@ -249,7 +250,7 @@
 		free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
 	} while (pgd++, addr = next, addr != end);
 
-	if (!tlb_is_full_mm(*tlb))
+	if (!(*tlb)->fullmm)
 		flush_tlb_pgtables((*tlb)->mm, start, end);
 }
 
@@ -260,6 +261,12 @@
 		struct vm_area_struct *next = vma->vm_next;
 		unsigned long addr = vma->vm_start;
 
+		/*
+		 * Hide vma from rmap and vmtruncate before freeing pgtables
+		 */
+		anon_vma_unlink(vma);
+		unlink_file_vma(vma);
+
 		if (is_hugepage_only_range(vma->vm_mm, addr, HPAGE_SIZE)) {
 			hugetlb_free_pgd_range(tlb, addr, vma->vm_end,
 				floor, next? next->vm_start: ceiling);
@@ -272,6 +279,8 @@
 							HPAGE_SIZE)) {
 				vma = next;
 				next = vma->vm_next;
+				anon_vma_unlink(vma);
+				unlink_file_vma(vma);
 			}
 			free_pgd_range(tlb, addr, vma->vm_end,
 				floor, next? next->vm_start: ceiling);
@@ -280,72 +289,78 @@
 	}
 }
 
-pte_t fastcall *pte_alloc_map(struct mm_struct *mm, pmd_t *pmd,
-				unsigned long address)
+int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
 {
-	if (!pmd_present(*pmd)) {
-		struct page *new;
+	struct page *new = pte_alloc_one(mm, address);
+	if (!new)
+		return -ENOMEM;
 
-		spin_unlock(&mm->page_table_lock);
-		new = pte_alloc_one(mm, address);
-		spin_lock(&mm->page_table_lock);
-		if (!new)
-			return NULL;
-		/*
-		 * Because we dropped the lock, we should re-check the
-		 * entry, as somebody else could have populated it..
-		 */
-		if (pmd_present(*pmd)) {
-			pte_free(new);
-			goto out;
-		}
+	pte_lock_init(new);
+	spin_lock(&mm->page_table_lock);
+	if (pmd_present(*pmd)) {	/* Another has populated it */
+		pte_lock_deinit(new);
+		pte_free(new);
+	} else {
 		mm->nr_ptes++;
 		inc_page_state(nr_page_table_pages);
 		pmd_populate(mm, pmd, new);
 	}
-out:
-	return pte_offset_map(pmd, address);
+	spin_unlock(&mm->page_table_lock);
+	return 0;
 }
 
-pte_t fastcall * pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
+int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
 {
-	if (!pmd_present(*pmd)) {
-		pte_t *new;
+	pte_t *new = pte_alloc_one_kernel(&init_mm, address);
+	if (!new)
+		return -ENOMEM;
 
-		spin_unlock(&mm->page_table_lock);
-		new = pte_alloc_one_kernel(mm, address);
-		spin_lock(&mm->page_table_lock);
-		if (!new)
-			return NULL;
+	spin_lock(&init_mm.page_table_lock);
+	if (pmd_present(*pmd))		/* Another has populated it */
+		pte_free_kernel(new);
+	else
+		pmd_populate_kernel(&init_mm, pmd, new);
+	spin_unlock(&init_mm.page_table_lock);
+	return 0;
+}
 
-		/*
-		 * Because we dropped the lock, we should re-check the
-		 * entry, as somebody else could have populated it..
-		 */
-		if (pmd_present(*pmd)) {
-			pte_free_kernel(new);
-			goto out;
-		}
-		pmd_populate_kernel(mm, pmd, new);
-	}
-out:
-	return pte_offset_kernel(pmd, address);
+static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss)
+{
+	if (file_rss)
+		add_mm_counter(mm, file_rss, file_rss);
+	if (anon_rss)
+		add_mm_counter(mm, anon_rss, anon_rss);
+}
+
+/*
+ * This function is called to print an error when a pte in a
+ * !VM_RESERVED region is found pointing to an invalid pfn (which
+ * is an error.
+ *
+ * The calling function must still handle the error.
+ */
+void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr)
+{
+	printk(KERN_ERR "Bad pte = %08llx, process = %s, "
+			"vm_flags = %lx, vaddr = %lx\n",
+		(long long)pte_val(pte),
+		(vma->vm_mm == current->mm ? current->comm : "???"),
+		vma->vm_flags, vaddr);
+	dump_stack();
 }
 
 /*
  * copy one vm_area from one task to the other. Assumes the page tables
  * already present in the new task to be cleared in the whole range
  * covered by this vma.
- *
- * dst->page_table_lock is held on entry and exit,
- * but may be dropped within p[mg]d_alloc() and pte_alloc_map().
  */
 
 static inline void
 copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
-		pte_t *dst_pte, pte_t *src_pte, unsigned long vm_flags,
-		unsigned long addr)
+		pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma,
+		unsigned long addr, int *rss)
 {
+	unsigned long vm_flags = vma->vm_flags;
 	pte_t pte = *src_pte;
 	struct page *page;
 	unsigned long pfn;
@@ -357,29 +372,32 @@
 			/* make sure dst_mm is on swapoff's mmlist. */
 			if (unlikely(list_empty(&dst_mm->mmlist))) {
 				spin_lock(&mmlist_lock);
-				list_add(&dst_mm->mmlist, &src_mm->mmlist);
+				if (list_empty(&dst_mm->mmlist))
+					list_add(&dst_mm->mmlist,
+						 &src_mm->mmlist);
 				spin_unlock(&mmlist_lock);
 			}
 		}
-		set_pte_at(dst_mm, addr, dst_pte, pte);
-		return;
+		goto out_set_pte;
 	}
 
+	/* If the region is VM_RESERVED, the mapping is not
+	 * mapped via rmap - duplicate the pte as is.
+	 */
+	if (vm_flags & VM_RESERVED)
+		goto out_set_pte;
+
 	pfn = pte_pfn(pte);
-	/* the pte points outside of valid memory, the
-	 * mapping is assumed to be good, meaningful
-	 * and not mapped via rmap - duplicate the
-	 * mapping as is.
+	/* If the pte points outside of valid memory but
+	 * the region is not VM_RESERVED, we have a problem.
 	 */
-	page = NULL;
-	if (pfn_valid(pfn))
-		page = pfn_to_page(pfn);
-
-	if (!page || PageReserved(page)) {
-		set_pte_at(dst_mm, addr, dst_pte, pte);
-		return;
+	if (unlikely(!pfn_valid(pfn))) {
+		print_bad_pte(vma, pte, addr);
+		goto out_set_pte; /* try to do something sane */
 	}
 
+	page = pfn_to_page(pfn);
+
 	/*
 	 * If it's a COW mapping, write protect it both
 	 * in the parent and the child
@@ -397,11 +415,11 @@
 		pte = pte_mkclean(pte);
 	pte = pte_mkold(pte);
 	get_page(page);
-	inc_mm_counter(dst_mm, rss);
-	if (PageAnon(page))
-		inc_mm_counter(dst_mm, anon_rss);
-	set_pte_at(dst_mm, addr, dst_pte, pte);
 	page_dup_rmap(page);
+	rss[!!PageAnon(page)]++;
+
+out_set_pte:
+	set_pte_at(dst_mm, addr, dst_pte, pte);
 }
 
 static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
@@ -409,38 +427,44 @@
 		unsigned long addr, unsigned long end)
 {
 	pte_t *src_pte, *dst_pte;
-	unsigned long vm_flags = vma->vm_flags;
-	int progress;
+	spinlock_t *src_ptl, *dst_ptl;
+	int progress = 0;
+	int rss[2];
 
 again:
-	dst_pte = pte_alloc_map(dst_mm, dst_pmd, addr);
+	rss[1] = rss[0] = 0;
+	dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
 	if (!dst_pte)
 		return -ENOMEM;
 	src_pte = pte_offset_map_nested(src_pmd, addr);
+	src_ptl = pte_lockptr(src_mm, src_pmd);
+	spin_lock(src_ptl);
 
-	progress = 0;
-	spin_lock(&src_mm->page_table_lock);
 	do {
 		/*
 		 * We are holding two locks at this point - either of them
 		 * could generate latencies in another task on another CPU.
 		 */
-		if (progress >= 32 && (need_resched() ||
-		    need_lockbreak(&src_mm->page_table_lock) ||
-		    need_lockbreak(&dst_mm->page_table_lock)))
-			break;
+		if (progress >= 32) {
+			progress = 0;
+			if (need_resched() ||
+			    need_lockbreak(src_ptl) ||
+			    need_lockbreak(dst_ptl))
+				break;
+		}
 		if (pte_none(*src_pte)) {
 			progress++;
 			continue;
 		}
-		copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, vm_flags, addr);
+		copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, vma, addr, rss);
 		progress += 8;
 	} while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
-	spin_unlock(&src_mm->page_table_lock);
 
+	spin_unlock(src_ptl);
 	pte_unmap_nested(src_pte - 1);
-	pte_unmap(dst_pte - 1);
-	cond_resched_lock(&dst_mm->page_table_lock);
+	add_mm_rss(dst_mm, rss[0], rss[1]);
+	pte_unmap_unlock(dst_pte - 1, dst_ptl);
+	cond_resched();
 	if (addr != end)
 		goto again;
 	return 0;
@@ -525,24 +549,30 @@
 	return 0;
 }
 
-static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
+static void zap_pte_range(struct mmu_gather *tlb,
+				struct vm_area_struct *vma, pmd_t *pmd,
 				unsigned long addr, unsigned long end,
 				struct zap_details *details)
 {
+	struct mm_struct *mm = tlb->mm;
 	pte_t *pte;
+	spinlock_t *ptl;
+	int file_rss = 0;
+	int anon_rss = 0;
 
-	pte = pte_offset_map(pmd, addr);
+	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	do {
 		pte_t ptent = *pte;
 		if (pte_none(ptent))
 			continue;
 		if (pte_present(ptent)) {
 			struct page *page = NULL;
-			unsigned long pfn = pte_pfn(ptent);
-			if (pfn_valid(pfn)) {
-				page = pfn_to_page(pfn);
-				if (PageReserved(page))
-					page = NULL;
+			if (!(vma->vm_flags & VM_RESERVED)) {
+				unsigned long pfn = pte_pfn(ptent);
+				if (unlikely(!pfn_valid(pfn)))
+					print_bad_pte(vma, ptent, addr);
+				else
+					page = pfn_to_page(pfn);
 			}
 			if (unlikely(details) && page) {
 				/*
@@ -562,7 +592,7 @@
 				     page->index > details->last_index))
 					continue;
 			}
-			ptent = ptep_get_and_clear_full(tlb->mm, addr, pte,
+			ptent = ptep_get_and_clear_full(mm, addr, pte,
 							tlb->fullmm);
 			tlb_remove_tlb_entry(tlb, pte, addr);
 			if (unlikely(!page))
@@ -570,15 +600,17 @@
 			if (unlikely(details) && details->nonlinear_vma
 			    && linear_page_index(details->nonlinear_vma,
 						addr) != page->index)
-				set_pte_at(tlb->mm, addr, pte,
+				set_pte_at(mm, addr, pte,
 					   pgoff_to_pte(page->index));
-			if (pte_dirty(ptent))
-				set_page_dirty(page);
 			if (PageAnon(page))
-				dec_mm_counter(tlb->mm, anon_rss);
-			else if (pte_young(ptent))
-				mark_page_accessed(page);
-			tlb->freed++;
+				anon_rss--;
+			else {
+				if (pte_dirty(ptent))
+					set_page_dirty(page);
+				if (pte_young(ptent))
+					mark_page_accessed(page);
+				file_rss--;
+			}
 			page_remove_rmap(page);
 			tlb_remove_page(tlb, page);
 			continue;
@@ -591,12 +623,15 @@
 			continue;
 		if (!pte_file(ptent))
 			free_swap_and_cache(pte_to_swp_entry(ptent));
-		pte_clear_full(tlb->mm, addr, pte, tlb->fullmm);
+		pte_clear_full(mm, addr, pte, tlb->fullmm);
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
+
+	add_mm_rss(mm, file_rss, anon_rss);
+	pte_unmap_unlock(pte - 1, ptl);
 }
 
-static inline void zap_pmd_range(struct mmu_gather *tlb, pud_t *pud,
+static inline void zap_pmd_range(struct mmu_gather *tlb,
+				struct vm_area_struct *vma, pud_t *pud,
 				unsigned long addr, unsigned long end,
 				struct zap_details *details)
 {
@@ -608,11 +643,12 @@
 		next = pmd_addr_end(addr, end);
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		zap_pte_range(tlb, pmd, addr, next, details);
+		zap_pte_range(tlb, vma, pmd, addr, next, details);
 	} while (pmd++, addr = next, addr != end);
 }
 
-static inline void zap_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+static inline void zap_pud_range(struct mmu_gather *tlb,
+				struct vm_area_struct *vma, pgd_t *pgd,
 				unsigned long addr, unsigned long end,
 				struct zap_details *details)
 {
@@ -624,7 +660,7 @@
 		next = pud_addr_end(addr, end);
 		if (pud_none_or_clear_bad(pud))
 			continue;
-		zap_pmd_range(tlb, pud, addr, next, details);
+		zap_pmd_range(tlb, vma, pud, addr, next, details);
 	} while (pud++, addr = next, addr != end);
 }
 
@@ -645,7 +681,7 @@
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
-		zap_pud_range(tlb, pgd, addr, next, details);
+		zap_pud_range(tlb, vma, pgd, addr, next, details);
 	} while (pgd++, addr = next, addr != end);
 	tlb_end_vma(tlb, vma);
 }
@@ -660,7 +696,6 @@
 /**
  * unmap_vmas - unmap a range of memory covered by a list of vma's
  * @tlbp: address of the caller's struct mmu_gather
- * @mm: the controlling mm_struct
  * @vma: the starting vma
  * @start_addr: virtual address at which to start unmapping
  * @end_addr: virtual address at which to end unmapping
@@ -669,10 +704,10 @@
  *
  * Returns the end address of the unmapping (restart addr if interrupted).
  *
- * Unmap all pages in the vma list.  Called under page_table_lock.
+ * Unmap all pages in the vma list.
  *
- * We aim to not hold page_table_lock for too long (for scheduling latency
- * reasons).  So zap pages in ZAP_BLOCK_SIZE bytecounts.  This means we need to
+ * We aim to not hold locks for too long (for scheduling latency reasons).
+ * So zap pages in ZAP_BLOCK_SIZE bytecounts.  This means we need to
  * return the ending mmu_gather to the caller.
  *
  * Only addresses between `start' and `end' will be unmapped.
@@ -684,7 +719,7 @@
  * ensure that any thus-far unmapped pages are flushed before unmap_vmas()
  * drops the lock and schedules.
  */
-unsigned long unmap_vmas(struct mmu_gather **tlbp, struct mm_struct *mm,
+unsigned long unmap_vmas(struct mmu_gather **tlbp,
 		struct vm_area_struct *vma, unsigned long start_addr,
 		unsigned long end_addr, unsigned long *nr_accounted,
 		struct zap_details *details)
@@ -694,7 +729,7 @@
 	int tlb_start_valid = 0;
 	unsigned long start = start_addr;
 	spinlock_t *i_mmap_lock = details? details->i_mmap_lock: NULL;
-	int fullmm = tlb_is_full_mm(*tlbp);
+	int fullmm = (*tlbp)->fullmm;
 
 	for ( ; vma && vma->vm_start < end_addr; vma = vma->vm_next) {
 		unsigned long end;
@@ -734,19 +769,15 @@
 			tlb_finish_mmu(*tlbp, tlb_start, start);
 
 			if (need_resched() ||
-				need_lockbreak(&mm->page_table_lock) ||
 				(i_mmap_lock && need_lockbreak(i_mmap_lock))) {
 				if (i_mmap_lock) {
-					/* must reset count of rss freed */
-					*tlbp = tlb_gather_mmu(mm, fullmm);
+					*tlbp = NULL;
 					goto out;
 				}
-				spin_unlock(&mm->page_table_lock);
 				cond_resched();
-				spin_lock(&mm->page_table_lock);
 			}
 
-			*tlbp = tlb_gather_mmu(mm, fullmm);
+			*tlbp = tlb_gather_mmu(vma->vm_mm, fullmm);
 			tlb_start_valid = 0;
 			zap_bytes = ZAP_BLOCK_SIZE;
 		}
@@ -770,123 +801,93 @@
 	unsigned long end = address + size;
 	unsigned long nr_accounted = 0;
 
-	if (is_vm_hugetlb_page(vma)) {
-		zap_hugepage_range(vma, address, size);
-		return end;
-	}
-
 	lru_add_drain();
-	spin_lock(&mm->page_table_lock);
 	tlb = tlb_gather_mmu(mm, 0);
-	end = unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
-	tlb_finish_mmu(tlb, address, end);
-	spin_unlock(&mm->page_table_lock);
+	update_hiwater_rss(mm);
+	end = unmap_vmas(&tlb, vma, address, end, &nr_accounted, details);
+	if (tlb)
+		tlb_finish_mmu(tlb, address, end);
 	return end;
 }
 
 /*
  * Do a quick page-table lookup for a single page.
- * mm->page_table_lock must be held.
  */
-static struct page *__follow_page(struct mm_struct *mm, unsigned long address,
-			int read, int write, int accessed)
+struct page *follow_page(struct mm_struct *mm, unsigned long address,
+			unsigned int flags)
 {
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *ptep, pte;
+	spinlock_t *ptl;
 	unsigned long pfn;
 	struct page *page;
 
-	page = follow_huge_addr(mm, address, write);
-	if (! IS_ERR(page))
-		return page;
+	page = follow_huge_addr(mm, address, flags & FOLL_WRITE);
+	if (!IS_ERR(page)) {
+		BUG_ON(flags & FOLL_GET);
+		goto out;
+	}
 
+	page = NULL;
 	pgd = pgd_offset(mm, address);
 	if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-		goto out;
+		goto no_page_table;
 
 	pud = pud_offset(pgd, address);
 	if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-		goto out;
+		goto no_page_table;
 	
 	pmd = pmd_offset(pud, address);
 	if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
-		goto out;
-	if (pmd_huge(*pmd))
-		return follow_huge_pmd(mm, address, pmd, write);
+		goto no_page_table;
 
-	ptep = pte_offset_map(pmd, address);
+	if (pmd_huge(*pmd)) {
+		BUG_ON(flags & FOLL_GET);
+		page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
+		goto out;
+	}
+
+	ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
 	if (!ptep)
 		goto out;
 
 	pte = *ptep;
-	pte_unmap(ptep);
-	if (pte_present(pte)) {
-		if (write && !pte_write(pte))
-			goto out;
-		if (read && !pte_read(pte))
-			goto out;
-		pfn = pte_pfn(pte);
-		if (pfn_valid(pfn)) {
-			page = pfn_to_page(pfn);
-			if (accessed) {
-				if (write && !pte_dirty(pte) &&!PageDirty(page))
-					set_page_dirty(page);
-				mark_page_accessed(page);
-			}
-			return page;
-		}
+	if (!pte_present(pte))
+		goto unlock;
+	if ((flags & FOLL_WRITE) && !pte_write(pte))
+		goto unlock;
+	pfn = pte_pfn(pte);
+	if (!pfn_valid(pfn))
+		goto unlock;
+
+	page = pfn_to_page(pfn);
+	if (flags & FOLL_GET)
+		get_page(page);
+	if (flags & FOLL_TOUCH) {
+		if ((flags & FOLL_WRITE) &&
+		    !pte_dirty(pte) && !PageDirty(page))
+			set_page_dirty(page);
+		mark_page_accessed(page);
 	}
-
+unlock:
+	pte_unmap_unlock(ptep, ptl);
 out:
-	return NULL;
-}
+	return page;
 
-inline struct page *
-follow_page(struct mm_struct *mm, unsigned long address, int write)
-{
-	return __follow_page(mm, address, 0, write, 1);
-}
-
-/*
- * check_user_page_readable() can be called frm niterrupt context by oprofile,
- * so we need to avoid taking any non-irq-safe locks
- */
-int check_user_page_readable(struct mm_struct *mm, unsigned long address)
-{
-	return __follow_page(mm, address, 1, 0, 0) != NULL;
-}
-EXPORT_SYMBOL(check_user_page_readable);
-
-static inline int
-untouched_anonymous_page(struct mm_struct* mm, struct vm_area_struct *vma,
-			 unsigned long address)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-
-	/* Check if the vma is for an anonymous mapping. */
-	if (vma->vm_ops && vma->vm_ops->nopage)
-		return 0;
-
-	/* Check if page directory entry exists. */
-	pgd = pgd_offset(mm, address);
-	if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-		return 1;
-
-	pud = pud_offset(pgd, address);
-	if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-		return 1;
-
-	/* Check if page middle directory entry exists. */
-	pmd = pmd_offset(pud, address);
-	if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
-		return 1;
-
-	/* There is a pte slot for 'address' in 'mm'. */
-	return 0;
+no_page_table:
+	/*
+	 * When core dumping an enormous anonymous area that nobody
+	 * has touched so far, we don't want to allocate page tables.
+	 */
+	if (flags & FOLL_ANON) {
+		page = ZERO_PAGE(address);
+		if (flags & FOLL_GET)
+			get_page(page);
+		BUG_ON(flags & FOLL_WRITE);
+	}
+	return page;
 }
 
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
@@ -894,18 +895,19 @@
 		struct page **pages, struct vm_area_struct **vmas)
 {
 	int i;
-	unsigned int flags;
+	unsigned int vm_flags;
 
 	/* 
 	 * Require read or write permissions.
 	 * If 'force' is set, we only require the "MAY" flags.
 	 */
-	flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
-	flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+	vm_flags  = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+	vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 	i = 0;
 
 	do {
-		struct vm_area_struct *	vma;
+		struct vm_area_struct *vma;
+		unsigned int foll_flags;
 
 		vma = find_extend_vma(mm, start);
 		if (!vma && in_gate_area(tsk, start)) {
@@ -945,8 +947,8 @@
 			continue;
 		}
 
-		if (!vma || (vma->vm_flags & VM_IO)
-				|| !(flags & vma->vm_flags))
+		if (!vma || (vma->vm_flags & (VM_IO | VM_RESERVED))
+				|| !(vm_flags & vma->vm_flags))
 			return i ? : -EFAULT;
 
 		if (is_vm_hugetlb_page(vma)) {
@@ -954,29 +956,25 @@
 						&start, &len, i);
 			continue;
 		}
-		spin_lock(&mm->page_table_lock);
+
+		foll_flags = FOLL_TOUCH;
+		if (pages)
+			foll_flags |= FOLL_GET;
+		if (!write && !(vma->vm_flags & VM_LOCKED) &&
+		    (!vma->vm_ops || !vma->vm_ops->nopage))
+			foll_flags |= FOLL_ANON;
+
 		do {
-			int write_access = write;
 			struct page *page;
 
-			cond_resched_lock(&mm->page_table_lock);
-			while (!(page = follow_page(mm, start, write_access))) {
+			if (write)
+				foll_flags |= FOLL_WRITE;
+
+			cond_resched();
+			while (!(page = follow_page(mm, start, foll_flags))) {
 				int ret;
-
-				/*
-				 * Shortcut for anonymous pages. We don't want
-				 * to force the creation of pages tables for
-				 * insanely big anonymously mapped areas that
-				 * nobody touched so far. This is important
-				 * for doing a core dump for these mappings.
-				 */
-				if (!write && untouched_anonymous_page(mm,vma,start)) {
-					page = ZERO_PAGE(start);
-					break;
-				}
-				spin_unlock(&mm->page_table_lock);
-				ret = __handle_mm_fault(mm, vma, start, write_access);
-
+				ret = __handle_mm_fault(mm, vma, start,
+						foll_flags & FOLL_WRITE);
 				/*
 				 * The VM_FAULT_WRITE bit tells us that do_wp_page has
 				 * broken COW when necessary, even if maybe_mkwrite
@@ -984,7 +982,7 @@
 				 * subsequent page lookups as if they were reads.
 				 */
 				if (ret & VM_FAULT_WRITE)
-					write_access = 0;
+					foll_flags &= ~FOLL_WRITE;
 				
 				switch (ret & ~VM_FAULT_WRITE) {
 				case VM_FAULT_MINOR:
@@ -1000,13 +998,10 @@
 				default:
 					BUG();
 				}
-				spin_lock(&mm->page_table_lock);
 			}
 			if (pages) {
 				pages[i] = page;
 				flush_dcache_page(page);
-				if (!PageReserved(page))
-					page_cache_get(page);
 			}
 			if (vmas)
 				vmas[i] = vma;
@@ -1014,7 +1009,6 @@
 			start += PAGE_SIZE;
 			len--;
 		} while (len && start < vma->vm_end);
-		spin_unlock(&mm->page_table_lock);
 	} while (len);
 	return i;
 }
@@ -1024,16 +1018,21 @@
 			unsigned long addr, unsigned long end, pgprot_t prot)
 {
 	pte_t *pte;
+	spinlock_t *ptl;
 
-	pte = pte_alloc_map(mm, pmd, addr);
+	pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
 	if (!pte)
 		return -ENOMEM;
 	do {
-		pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(addr), prot));
+		struct page *page = ZERO_PAGE(addr);
+		pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
+		page_cache_get(page);
+		page_add_file_rmap(page);
+		inc_mm_counter(mm, file_rss);
 		BUG_ON(!pte_none(*pte));
 		set_pte_at(mm, addr, pte, zero_pte);
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
+	pte_unmap_unlock(pte - 1, ptl);
 	return 0;
 }
 
@@ -1083,14 +1082,12 @@
 	BUG_ON(addr >= end);
 	pgd = pgd_offset(mm, addr);
 	flush_cache_range(vma, addr, end);
-	spin_lock(&mm->page_table_lock);
 	do {
 		next = pgd_addr_end(addr, end);
 		err = zeromap_pud_range(mm, pgd, addr, next, prot);
 		if (err)
 			break;
 	} while (pgd++, addr = next, addr != end);
-	spin_unlock(&mm->page_table_lock);
 	return err;
 }
 
@@ -1104,17 +1101,17 @@
 			unsigned long pfn, pgprot_t prot)
 {
 	pte_t *pte;
+	spinlock_t *ptl;
 
-	pte = pte_alloc_map(mm, pmd, addr);
+	pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
 	if (!pte)
 		return -ENOMEM;
 	do {
 		BUG_ON(!pte_none(*pte));
-		if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
-			set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
+		set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
 		pfn++;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
+	pte_unmap_unlock(pte - 1, ptl);
 	return 0;
 }
 
@@ -1173,8 +1170,8 @@
 	 * rest of the world about it:
 	 *   VM_IO tells people not to look at these pages
 	 *	(accesses can have side effects).
-	 *   VM_RESERVED tells swapout not to try to touch
-	 *	this region.
+	 *   VM_RESERVED tells the core MM not to "manage" these pages
+         *	(e.g. refcount, mapcount, try to swap them out).
 	 */
 	vma->vm_flags |= VM_IO | VM_RESERVED;
 
@@ -1182,7 +1179,6 @@
 	pfn -= addr >> PAGE_SHIFT;
 	pgd = pgd_offset(mm, addr);
 	flush_cache_range(vma, addr, end);
-	spin_lock(&mm->page_table_lock);
 	do {
 		next = pgd_addr_end(addr, end);
 		err = remap_pud_range(mm, pgd, addr, next,
@@ -1190,12 +1186,36 @@
 		if (err)
 			break;
 	} while (pgd++, addr = next, addr != end);
-	spin_unlock(&mm->page_table_lock);
 	return err;
 }
 EXPORT_SYMBOL(remap_pfn_range);
 
 /*
+ * handle_pte_fault chooses page fault handler according to an entry
+ * which was read non-atomically.  Before making any commitment, on
+ * those architectures or configurations (e.g. i386 with PAE) which
+ * might give a mix of unmatched parts, do_swap_page and do_file_page
+ * must check under lock before unmapping the pte and proceeding
+ * (but do_wp_page is only called after already making such a check;
+ * and do_anonymous_page and do_no_page can safely check later on).
+ */
+static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd,
+				pte_t *page_table, pte_t orig_pte)
+{
+	int same = 1;
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+	if (sizeof(pte_t) > sizeof(unsigned long)) {
+		spinlock_t *ptl = pte_lockptr(mm, pmd);
+		spin_lock(ptl);
+		same = pte_same(*page_table, orig_pte);
+		spin_unlock(ptl);
+	}
+#endif
+	pte_unmap(page_table);
+	return same;
+}
+
+/*
  * Do pte_mkwrite, but only if the vma says VM_WRITE.  We do this when
  * servicing faults for write access.  In the normal case, do always want
  * pte_mkwrite.  But get_user_pages can cause write faults for mappings
@@ -1209,28 +1229,10 @@
 }
 
 /*
- * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
- */
-static inline void break_cow(struct vm_area_struct * vma, struct page * new_page, unsigned long address, 
-		pte_t *page_table)
-{
-	pte_t entry;
-
-	entry = maybe_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)),
-			      vma);
-	ptep_establish(vma, address, page_table, entry);
-	update_mmu_cache(vma, address, entry);
-	lazy_mmu_prot_update(entry);
-}
-
-/*
  * This routine handles present pages, when users try to write
  * to a shared page. It is done by copying the page to a new address
  * and decrementing the shared-page counter for the old page.
  *
- * Goto-purists beware: the only reason for goto's here is that it results
- * in better assembly code.. The "default" path will see no jumps at all.
- *
  * Note that this routine assumes that the protection checks have been
  * done by the caller (the low-level page fault routine in most cases).
  * Thus we can safely just mark it writable once we've done any necessary
@@ -1240,28 +1242,28 @@
  * change only once the write actually happens. This avoids a few races,
  * and potentially makes it more efficient.
  *
- * We hold the mm semaphore and the page_table_lock on entry and exit
- * with the page_table_lock released.
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), with pte both mapped and locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
-	unsigned long address, pte_t *page_table, pmd_t *pmd, pte_t pte)
+static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
+		unsigned long address, pte_t *page_table, pmd_t *pmd,
+		spinlock_t *ptl, pte_t orig_pte)
 {
 	struct page *old_page, *new_page;
-	unsigned long pfn = pte_pfn(pte);
+	unsigned long pfn = pte_pfn(orig_pte);
 	pte_t entry;
-	int ret;
+	int ret = VM_FAULT_MINOR;
+
+	BUG_ON(vma->vm_flags & VM_RESERVED);
 
 	if (unlikely(!pfn_valid(pfn))) {
 		/*
-		 * This should really halt the system so it can be debugged or
-		 * at least the kernel stops what it's doing before it corrupts
-		 * data, but for the moment just pretend this is OOM.
+		 * Page table corrupted: show pte and kill process.
 		 */
-		pte_unmap(page_table);
-		printk(KERN_ERR "do_wp_page: bogus page at address %08lx\n",
-				address);
-		spin_unlock(&mm->page_table_lock);
-		return VM_FAULT_OOM;
+		print_bad_pte(vma, orig_pte, address);
+		ret = VM_FAULT_OOM;
+		goto unlock;
 	}
 	old_page = pfn_to_page(pfn);
 
@@ -1270,52 +1272,51 @@
 		unlock_page(old_page);
 		if (reuse) {
 			flush_cache_page(vma, address, pfn);
-			entry = maybe_mkwrite(pte_mkyoung(pte_mkdirty(pte)),
-					      vma);
+			entry = pte_mkyoung(orig_pte);
+			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 			ptep_set_access_flags(vma, address, page_table, entry, 1);
 			update_mmu_cache(vma, address, entry);
 			lazy_mmu_prot_update(entry);
-			pte_unmap(page_table);
-			spin_unlock(&mm->page_table_lock);
-			return VM_FAULT_MINOR|VM_FAULT_WRITE;
+			ret |= VM_FAULT_WRITE;
+			goto unlock;
 		}
 	}
-	pte_unmap(page_table);
 
 	/*
 	 * Ok, we need to copy. Oh, well..
 	 */
-	if (!PageReserved(old_page))
-		page_cache_get(old_page);
-	spin_unlock(&mm->page_table_lock);
+	page_cache_get(old_page);
+	pte_unmap_unlock(page_table, ptl);
 
 	if (unlikely(anon_vma_prepare(vma)))
-		goto no_new_page;
+		goto oom;
 	if (old_page == ZERO_PAGE(address)) {
 		new_page = alloc_zeroed_user_highpage(vma, address);
 		if (!new_page)
-			goto no_new_page;
+			goto oom;
 	} else {
 		new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
 		if (!new_page)
-			goto no_new_page;
+			goto oom;
 		copy_user_highpage(new_page, old_page, address);
 	}
+
 	/*
 	 * Re-check the pte - we dropped the lock
 	 */
-	ret = VM_FAULT_MINOR;
-	spin_lock(&mm->page_table_lock);
-	page_table = pte_offset_map(pmd, address);
-	if (likely(pte_same(*page_table, pte))) {
-		if (PageAnon(old_page))
-			dec_mm_counter(mm, anon_rss);
-		if (PageReserved(old_page))
-			inc_mm_counter(mm, rss);
-		else
-			page_remove_rmap(old_page);
+	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+	if (likely(pte_same(*page_table, orig_pte))) {
+		page_remove_rmap(old_page);
+		if (!PageAnon(old_page)) {
+			inc_mm_counter(mm, anon_rss);
+			dec_mm_counter(mm, file_rss);
+		}
 		flush_cache_page(vma, address, pfn);
-		break_cow(vma, new_page, address, page_table);
+		entry = mk_pte(new_page, vma->vm_page_prot);
+		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+		ptep_establish(vma, address, page_table, entry);
+		update_mmu_cache(vma, address, entry);
+		lazy_mmu_prot_update(entry);
 		lru_cache_add_active(new_page);
 		page_add_anon_rmap(new_page, vma, address);
 
@@ -1323,13 +1324,12 @@
 		new_page = old_page;
 		ret |= VM_FAULT_WRITE;
 	}
-	pte_unmap(page_table);
 	page_cache_release(new_page);
 	page_cache_release(old_page);
-	spin_unlock(&mm->page_table_lock);
+unlock:
+	pte_unmap_unlock(page_table, ptl);
 	return ret;
-
-no_new_page:
+oom:
 	page_cache_release(old_page);
 	return VM_FAULT_OOM;
 }
@@ -1399,13 +1399,6 @@
 
 	restart_addr = zap_page_range(vma, start_addr,
 					end_addr - start_addr, details);
-
-	/*
-	 * We cannot rely on the break test in unmap_vmas:
-	 * on the one hand, we don't want to restart our loop
-	 * just because that broke out for the page_table_lock;
-	 * on the other hand, it does no test when vma is small.
-	 */
 	need_break = need_resched() ||
 			need_lockbreak(details->i_mmap_lock);
 
@@ -1654,38 +1647,37 @@
 }
 
 /*
- * We hold the mm semaphore and the page_table_lock on entry and
- * should release the pagetable lock on exit..
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int do_swap_page(struct mm_struct * mm,
-	struct vm_area_struct * vma, unsigned long address,
-	pte_t *page_table, pmd_t *pmd, pte_t orig_pte, int write_access)
+static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
+		unsigned long address, pte_t *page_table, pmd_t *pmd,
+		int write_access, pte_t orig_pte)
 {
+	spinlock_t *ptl;
 	struct page *page;
-	swp_entry_t entry = pte_to_swp_entry(orig_pte);
+	swp_entry_t entry;
 	pte_t pte;
 	int ret = VM_FAULT_MINOR;
 
-	pte_unmap(page_table);
-	spin_unlock(&mm->page_table_lock);
+	if (!pte_unmap_same(mm, pmd, page_table, orig_pte))
+		goto out;
+
+	entry = pte_to_swp_entry(orig_pte);
 	page = lookup_swap_cache(entry);
 	if (!page) {
  		swapin_readahead(entry, address, vma);
  		page = read_swap_cache_async(entry, vma, address);
 		if (!page) {
 			/*
-			 * Back out if somebody else faulted in this pte while
-			 * we released the page table lock.
+			 * Back out if somebody else faulted in this pte
+			 * while we released the pte lock.
 			 */
-			spin_lock(&mm->page_table_lock);
-			page_table = pte_offset_map(pmd, address);
+			page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 			if (likely(pte_same(*page_table, orig_pte)))
 				ret = VM_FAULT_OOM;
-			else
-				ret = VM_FAULT_MINOR;
-			pte_unmap(page_table);
-			spin_unlock(&mm->page_table_lock);
-			goto out;
+			goto unlock;
 		}
 
 		/* Had to read the page from swap area: Major fault */
@@ -1698,15 +1690,11 @@
 	lock_page(page);
 
 	/*
-	 * Back out if somebody else faulted in this pte while we
-	 * released the page table lock.
+	 * Back out if somebody else already faulted in this pte.
 	 */
-	spin_lock(&mm->page_table_lock);
-	page_table = pte_offset_map(pmd, address);
-	if (unlikely(!pte_same(*page_table, orig_pte))) {
-		ret = VM_FAULT_MINOR;
+	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+	if (unlikely(!pte_same(*page_table, orig_pte)))
 		goto out_nomap;
-	}
 
 	if (unlikely(!PageUptodate(page))) {
 		ret = VM_FAULT_SIGBUS;
@@ -1715,7 +1703,7 @@
 
 	/* The page isn't present yet, go ahead with the fault. */
 
-	inc_mm_counter(mm, rss);
+	inc_mm_counter(mm, anon_rss);
 	pte = mk_pte(page, vma->vm_page_prot);
 	if (write_access && can_share_swap_page(page)) {
 		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
@@ -1733,7 +1721,7 @@
 
 	if (write_access) {
 		if (do_wp_page(mm, vma, address,
-				page_table, pmd, pte) == VM_FAULT_OOM)
+				page_table, pmd, ptl, pte) == VM_FAULT_OOM)
 			ret = VM_FAULT_OOM;
 		goto out;
 	}
@@ -1741,74 +1729,76 @@
 	/* No need to invalidate - it was non-present before */
 	update_mmu_cache(vma, address, pte);
 	lazy_mmu_prot_update(pte);
-	pte_unmap(page_table);
-	spin_unlock(&mm->page_table_lock);
+unlock:
+	pte_unmap_unlock(page_table, ptl);
 out:
 	return ret;
 out_nomap:
-	pte_unmap(page_table);
-	spin_unlock(&mm->page_table_lock);
+	pte_unmap_unlock(page_table, ptl);
 	unlock_page(page);
 	page_cache_release(page);
-	goto out;
+	return ret;
 }
 
 /*
- * We are called with the MM semaphore and page_table_lock
- * spinlock held to protect against concurrent faults in
- * multithreaded programs. 
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int
-do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
-		pte_t *page_table, pmd_t *pmd, int write_access,
-		unsigned long addr)
+static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
+		unsigned long address, pte_t *page_table, pmd_t *pmd,
+		int write_access)
 {
+	struct page *page;
+	spinlock_t *ptl;
 	pte_t entry;
-	struct page * page = ZERO_PAGE(addr);
 
-	/* Read-only mapping of ZERO_PAGE. */
-	entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
-
-	/* ..except if it's a write access */
 	if (write_access) {
 		/* Allocate our own private page. */
 		pte_unmap(page_table);
-		spin_unlock(&mm->page_table_lock);
 
 		if (unlikely(anon_vma_prepare(vma)))
-			goto no_mem;
-		page = alloc_zeroed_user_highpage(vma, addr);
+			goto oom;
+		page = alloc_zeroed_user_highpage(vma, address);
 		if (!page)
-			goto no_mem;
+			goto oom;
 
-		spin_lock(&mm->page_table_lock);
-		page_table = pte_offset_map(pmd, addr);
+		entry = mk_pte(page, vma->vm_page_prot);
+		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 
-		if (!pte_none(*page_table)) {
-			pte_unmap(page_table);
-			page_cache_release(page);
-			spin_unlock(&mm->page_table_lock);
-			goto out;
-		}
-		inc_mm_counter(mm, rss);
-		entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
-							 vma->vm_page_prot)),
-				      vma);
+		page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+		if (!pte_none(*page_table))
+			goto release;
+		inc_mm_counter(mm, anon_rss);
 		lru_cache_add_active(page);
 		SetPageReferenced(page);
-		page_add_anon_rmap(page, vma, addr);
+		page_add_anon_rmap(page, vma, address);
+	} else {
+		/* Map the ZERO_PAGE - vm_page_prot is readonly */
+		page = ZERO_PAGE(address);
+		page_cache_get(page);
+		entry = mk_pte(page, vma->vm_page_prot);
+
+		ptl = pte_lockptr(mm, pmd);
+		spin_lock(ptl);
+		if (!pte_none(*page_table))
+			goto release;
+		inc_mm_counter(mm, file_rss);
+		page_add_file_rmap(page);
 	}
 
-	set_pte_at(mm, addr, page_table, entry);
-	pte_unmap(page_table);
+	set_pte_at(mm, address, page_table, entry);
 
 	/* No need to invalidate - it was non-present before */
-	update_mmu_cache(vma, addr, entry);
+	update_mmu_cache(vma, address, entry);
 	lazy_mmu_prot_update(entry);
-	spin_unlock(&mm->page_table_lock);
-out:
+unlock:
+	pte_unmap_unlock(page_table, ptl);
 	return VM_FAULT_MINOR;
-no_mem:
+release:
+	page_cache_release(page);
+	goto unlock;
+oom:
 	return VM_FAULT_OOM;
 }
 
@@ -1821,25 +1811,23 @@
  * As this is called only for pages that do not currently exist, we
  * do not need to flush old virtual caches or the TLB.
  *
- * This is called with the MM semaphore held and the page table
- * spinlock held. Exit with the spinlock released.
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int
-do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
-	unsigned long address, int write_access, pte_t *page_table, pmd_t *pmd)
+static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
+		unsigned long address, pte_t *page_table, pmd_t *pmd,
+		int write_access)
 {
-	struct page * new_page;
+	spinlock_t *ptl;
+	struct page *new_page;
 	struct address_space *mapping = NULL;
 	pte_t entry;
 	unsigned int sequence = 0;
 	int ret = VM_FAULT_MINOR;
 	int anon = 0;
 
-	if (!vma->vm_ops || !vma->vm_ops->nopage)
-		return do_anonymous_page(mm, vma, page_table,
-					pmd, write_access, address);
 	pte_unmap(page_table);
-	spin_unlock(&mm->page_table_lock);
 
 	if (vma->vm_file) {
 		mapping = vma->vm_file->f_mapping;
@@ -1847,7 +1835,6 @@
 		smp_rmb(); /* serializes i_size against truncate_count */
 	}
 retry:
-	cond_resched();
 	new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret);
 	/*
 	 * No smp_rmb is needed here as long as there's a full
@@ -1880,19 +1867,20 @@
 		anon = 1;
 	}
 
-	spin_lock(&mm->page_table_lock);
+	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 	/*
 	 * For a file-backed vma, someone could have truncated or otherwise
 	 * invalidated this page.  If unmap_mapping_range got called,
 	 * retry getting the page.
 	 */
 	if (mapping && unlikely(sequence != mapping->truncate_count)) {
-		sequence = mapping->truncate_count;
-		spin_unlock(&mm->page_table_lock);
+		pte_unmap_unlock(page_table, ptl);
 		page_cache_release(new_page);
+		cond_resched();
+		sequence = mapping->truncate_count;
+		smp_rmb();
 		goto retry;
 	}
-	page_table = pte_offset_map(pmd, address);
 
 	/*
 	 * This silly early PAGE_DIRTY setting removes a race
@@ -1906,68 +1894,67 @@
 	 */
 	/* Only go through if we didn't race with anybody else... */
 	if (pte_none(*page_table)) {
-		if (!PageReserved(new_page))
-			inc_mm_counter(mm, rss);
-
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
 		if (write_access)
 			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 		set_pte_at(mm, address, page_table, entry);
 		if (anon) {
+			inc_mm_counter(mm, anon_rss);
 			lru_cache_add_active(new_page);
 			page_add_anon_rmap(new_page, vma, address);
-		} else
+		} else if (!(vma->vm_flags & VM_RESERVED)) {
+			inc_mm_counter(mm, file_rss);
 			page_add_file_rmap(new_page);
-		pte_unmap(page_table);
+		}
 	} else {
 		/* One of our sibling threads was faster, back out. */
-		pte_unmap(page_table);
 		page_cache_release(new_page);
-		spin_unlock(&mm->page_table_lock);
-		goto out;
+		goto unlock;
 	}
 
 	/* no need to invalidate: a not-present page shouldn't be cached */
 	update_mmu_cache(vma, address, entry);
 	lazy_mmu_prot_update(entry);
-	spin_unlock(&mm->page_table_lock);
-out:
+unlock:
+	pte_unmap_unlock(page_table, ptl);
 	return ret;
 oom:
 	page_cache_release(new_page);
-	ret = VM_FAULT_OOM;
-	goto out;
+	return VM_FAULT_OOM;
 }
 
 /*
  * Fault of a previously existing named mapping. Repopulate the pte
  * from the encoded file_pte if possible. This enables swappable
  * nonlinear vmas.
+ *
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int do_file_page(struct mm_struct * mm, struct vm_area_struct * vma,
-	unsigned long address, int write_access, pte_t *pte, pmd_t *pmd)
+static int do_file_page(struct mm_struct *mm, struct vm_area_struct *vma,
+		unsigned long address, pte_t *page_table, pmd_t *pmd,
+		int write_access, pte_t orig_pte)
 {
-	unsigned long pgoff;
+	pgoff_t pgoff;
 	int err;
 
-	BUG_ON(!vma->vm_ops || !vma->vm_ops->nopage);
-	/*
-	 * Fall back to the linear mapping if the fs does not support
-	 * ->populate:
-	 */
-	if (!vma->vm_ops->populate ||
-			(write_access && !(vma->vm_flags & VM_SHARED))) {
-		pte_clear(mm, address, pte);
-		return do_no_page(mm, vma, address, write_access, pte, pmd);
+	if (!pte_unmap_same(mm, pmd, page_table, orig_pte))
+		return VM_FAULT_MINOR;
+
+	if (unlikely(!(vma->vm_flags & VM_NONLINEAR))) {
+		/*
+		 * Page table corrupted: show pte and kill process.
+		 */
+		print_bad_pte(vma, orig_pte, address);
+		return VM_FAULT_OOM;
 	}
+	/* We can then assume vm->vm_ops && vma->vm_ops->populate */
 
-	pgoff = pte_to_pgoff(*pte);
-
-	pte_unmap(pte);
-	spin_unlock(&mm->page_table_lock);
-
-	err = vma->vm_ops->populate(vma, address & PAGE_MASK, PAGE_SIZE, vma->vm_page_prot, pgoff, 0);
+	pgoff = pte_to_pgoff(orig_pte);
+	err = vma->vm_ops->populate(vma, address & PAGE_MASK, PAGE_SIZE,
+					vma->vm_page_prot, pgoff, 0);
 	if (err == -ENOMEM)
 		return VM_FAULT_OOM;
 	if (err)
@@ -1984,56 +1971,68 @@
  * with external mmu caches can use to update those (ie the Sparc or
  * PowerPC hashed page tables that act as extended TLBs).
  *
- * Note the "page_table_lock". It is to protect against kswapd removing
- * pages from under us. Note that kswapd only ever _removes_ pages, never
- * adds them. As such, once we have noticed that the page is not present,
- * we can drop the lock early.
- *
- * The adding of pages is protected by the MM semaphore (which we hold),
- * so we don't need to worry about a page being suddenly been added into
- * our VM.
- *
- * We enter with the pagetable spinlock held, we are supposed to
- * release it when done.
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
 static inline int handle_pte_fault(struct mm_struct *mm,
-	struct vm_area_struct * vma, unsigned long address,
-	int write_access, pte_t *pte, pmd_t *pmd)
+		struct vm_area_struct *vma, unsigned long address,
+		pte_t *pte, pmd_t *pmd, int write_access)
 {
 	pte_t entry;
+	pte_t old_entry;
+	spinlock_t *ptl;
 
-	entry = *pte;
+	old_entry = entry = *pte;
 	if (!pte_present(entry)) {
-		/*
-		 * If it truly wasn't present, we know that kswapd
-		 * and the PTE updates will not touch it later. So
-		 * drop the lock.
-		 */
-		if (pte_none(entry))
-			return do_no_page(mm, vma, address, write_access, pte, pmd);
+		if (pte_none(entry)) {
+			if (!vma->vm_ops || !vma->vm_ops->nopage)
+				return do_anonymous_page(mm, vma, address,
+					pte, pmd, write_access);
+			return do_no_page(mm, vma, address,
+					pte, pmd, write_access);
+		}
 		if (pte_file(entry))
-			return do_file_page(mm, vma, address, write_access, pte, pmd);
-		return do_swap_page(mm, vma, address, pte, pmd, entry, write_access);
+			return do_file_page(mm, vma, address,
+					pte, pmd, write_access, entry);
+		return do_swap_page(mm, vma, address,
+					pte, pmd, write_access, entry);
 	}
 
+	ptl = pte_lockptr(mm, pmd);
+	spin_lock(ptl);
+	if (unlikely(!pte_same(*pte, entry)))
+		goto unlock;
 	if (write_access) {
 		if (!pte_write(entry))
-			return do_wp_page(mm, vma, address, pte, pmd, entry);
+			return do_wp_page(mm, vma, address,
+					pte, pmd, ptl, entry);
 		entry = pte_mkdirty(entry);
 	}
 	entry = pte_mkyoung(entry);
-	ptep_set_access_flags(vma, address, pte, entry, write_access);
-	update_mmu_cache(vma, address, entry);
-	lazy_mmu_prot_update(entry);
-	pte_unmap(pte);
-	spin_unlock(&mm->page_table_lock);
+	if (!pte_same(old_entry, entry)) {
+		ptep_set_access_flags(vma, address, pte, entry, write_access);
+		update_mmu_cache(vma, address, entry);
+		lazy_mmu_prot_update(entry);
+	} else {
+		/*
+		 * This is needed only for protection faults but the arch code
+		 * is not yet telling us if this is a protection fault or not.
+		 * This still avoids useless tlb flushes for .text page faults
+		 * with threads.
+		 */
+		if (write_access)
+			flush_tlb_page(vma, address);
+	}
+unlock:
+	pte_unmap_unlock(pte, ptl);
 	return VM_FAULT_MINOR;
 }
 
 /*
  * By the time we get here, we already hold the mm semaphore
  */
-int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
+int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 		unsigned long address, int write_access)
 {
 	pgd_t *pgd;
@@ -2048,100 +2047,66 @@
 	if (unlikely(is_vm_hugetlb_page(vma)))
 		return hugetlb_fault(mm, vma, address, write_access);
 
-	/*
-	 * We need the page table lock to synchronize with kswapd
-	 * and the SMP-safe atomic PTE updates.
-	 */
 	pgd = pgd_offset(mm, address);
-	spin_lock(&mm->page_table_lock);
-
 	pud = pud_alloc(mm, pgd, address);
 	if (!pud)
-		goto oom;
-
+		return VM_FAULT_OOM;
 	pmd = pmd_alloc(mm, pud, address);
 	if (!pmd)
-		goto oom;
-
+		return VM_FAULT_OOM;
 	pte = pte_alloc_map(mm, pmd, address);
 	if (!pte)
-		goto oom;
-	
-	return handle_pte_fault(mm, vma, address, write_access, pte, pmd);
+		return VM_FAULT_OOM;
 
- oom:
-	spin_unlock(&mm->page_table_lock);
-	return VM_FAULT_OOM;
+	return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
 }
 
 #ifndef __PAGETABLE_PUD_FOLDED
 /*
  * Allocate page upper directory.
- *
- * We've already handled the fast-path in-line, and we own the
- * page table lock.
+ * We've already handled the fast-path in-line.
  */
-pud_t fastcall *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
 {
-	pud_t *new;
-
-	spin_unlock(&mm->page_table_lock);
-	new = pud_alloc_one(mm, address);
-	spin_lock(&mm->page_table_lock);
+	pud_t *new = pud_alloc_one(mm, address);
 	if (!new)
-		return NULL;
+		return -ENOMEM;
 
-	/*
-	 * Because we dropped the lock, we should re-check the
-	 * entry, as somebody else could have populated it..
-	 */
-	if (pgd_present(*pgd)) {
+	spin_lock(&mm->page_table_lock);
+	if (pgd_present(*pgd))		/* Another has populated it */
 		pud_free(new);
-		goto out;
-	}
-	pgd_populate(mm, pgd, new);
- out:
-	return pud_offset(pgd, address);
+	else
+		pgd_populate(mm, pgd, new);
+	spin_unlock(&mm->page_table_lock);
+	return 0;
 }
 #endif /* __PAGETABLE_PUD_FOLDED */
 
 #ifndef __PAGETABLE_PMD_FOLDED
 /*
  * Allocate page middle directory.
- *
- * We've already handled the fast-path in-line, and we own the
- * page table lock.
+ * We've already handled the fast-path in-line.
  */
-pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
+int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
 {
-	pmd_t *new;
-
-	spin_unlock(&mm->page_table_lock);
-	new = pmd_alloc_one(mm, address);
-	spin_lock(&mm->page_table_lock);
+	pmd_t *new = pmd_alloc_one(mm, address);
 	if (!new)
-		return NULL;
+		return -ENOMEM;
 
-	/*
-	 * Because we dropped the lock, we should re-check the
-	 * entry, as somebody else could have populated it..
-	 */
+	spin_lock(&mm->page_table_lock);
 #ifndef __ARCH_HAS_4LEVEL_HACK
-	if (pud_present(*pud)) {
+	if (pud_present(*pud))		/* Another has populated it */
 		pmd_free(new);
-		goto out;
-	}
-	pud_populate(mm, pud, new);
+	else
+		pud_populate(mm, pud, new);
 #else
-	if (pgd_present(*pud)) {
+	if (pgd_present(*pud))		/* Another has populated it */
 		pmd_free(new);
-		goto out;
-	}
-	pgd_populate(mm, pud, new);
+	else
+		pgd_populate(mm, pud, new);
 #endif /* __ARCH_HAS_4LEVEL_HACK */
-
- out:
-	return pmd_offset(pud, address);
+	spin_unlock(&mm->page_table_lock);
+	return 0;
 }
 #endif /* __PAGETABLE_PMD_FOLDED */
 
@@ -2206,22 +2171,6 @@
 
 EXPORT_SYMBOL(vmalloc_to_pfn);
 
-/*
- * update_mem_hiwater
- *	- update per process rss and vm high water data
- */
-void update_mem_hiwater(struct task_struct *tsk)
-{
-	if (tsk->mm) {
-		unsigned long rss = get_mm_counter(tsk->mm, rss);
-
-		if (tsk->mm->hiwater_rss < rss)
-			tsk->mm->hiwater_rss = rss;
-		if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
-			tsk->mm->hiwater_vm = tsk->mm->total_vm;
-	}
-}
-
 #if !defined(__HAVE_ARCH_GATE_AREA)
 
 #if defined(AT_SYSINFO_EHDR)
@@ -2233,7 +2182,7 @@
 	gate_vma.vm_start = FIXADDR_USER_START;
 	gate_vma.vm_end = FIXADDR_USER_END;
 	gate_vma.vm_page_prot = PAGE_READONLY;
-	gate_vma.vm_flags = 0;
+	gate_vma.vm_flags = VM_RESERVED;
 	return 0;
 }
 __initcall(gate_vma_init);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
new file mode 100644
index 0000000..431a64f
--- /dev/null
+++ b/mm/memory_hotplug.c
@@ -0,0 +1,138 @@
+/*
+ *  linux/mm/memory_hotplug.c
+ *
+ *  Copyright (C)
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/interrupt.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/pagevec.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/cpu.h>
+#include <linux/memory.h>
+#include <linux/memory_hotplug.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+
+#include <asm/tlbflush.h>
+
+extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
+			  unsigned long size);
+static void __add_zone(struct zone *zone, unsigned long phys_start_pfn)
+{
+	struct pglist_data *pgdat = zone->zone_pgdat;
+	int nr_pages = PAGES_PER_SECTION;
+	int nid = pgdat->node_id;
+	int zone_type;
+
+	zone_type = zone - pgdat->node_zones;
+	memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn);
+	zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages);
+}
+
+extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
+				  int nr_pages);
+static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
+{
+	struct pglist_data *pgdat = zone->zone_pgdat;
+	int nr_pages = PAGES_PER_SECTION;
+	int ret;
+
+	ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages);
+
+	if (ret < 0)
+		return ret;
+
+	__add_zone(zone, phys_start_pfn);
+	return register_new_memory(__pfn_to_section(phys_start_pfn));
+}
+
+/*
+ * Reasonably generic function for adding memory.  It is
+ * expected that archs that support memory hotplug will
+ * call this function after deciding the zone to which to
+ * add the new pages.
+ */
+int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
+		 unsigned long nr_pages)
+{
+	unsigned long i;
+	int err = 0;
+
+	for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) {
+		err = __add_section(zone, phys_start_pfn + i);
+
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+static void grow_zone_span(struct zone *zone,
+		unsigned long start_pfn, unsigned long end_pfn)
+{
+	unsigned long old_zone_end_pfn;
+
+	zone_span_writelock(zone);
+
+	old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
+	if (start_pfn < zone->zone_start_pfn)
+		zone->zone_start_pfn = start_pfn;
+
+	if (end_pfn > old_zone_end_pfn)
+		zone->spanned_pages = end_pfn - zone->zone_start_pfn;
+
+	zone_span_writeunlock(zone);
+}
+
+static void grow_pgdat_span(struct pglist_data *pgdat,
+		unsigned long start_pfn, unsigned long end_pfn)
+{
+	unsigned long old_pgdat_end_pfn =
+		pgdat->node_start_pfn + pgdat->node_spanned_pages;
+
+	if (start_pfn < pgdat->node_start_pfn)
+		pgdat->node_start_pfn = start_pfn;
+
+	if (end_pfn > old_pgdat_end_pfn)
+		pgdat->node_spanned_pages = end_pfn - pgdat->node_spanned_pages;
+}
+
+int online_pages(unsigned long pfn, unsigned long nr_pages)
+{
+	unsigned long i;
+	unsigned long flags;
+	unsigned long onlined_pages = 0;
+	struct zone *zone;
+
+	/*
+	 * This doesn't need a lock to do pfn_to_page().
+	 * The section can't be removed here because of the
+	 * memory_block->state_sem.
+	 */
+	zone = page_zone(pfn_to_page(pfn));
+	pgdat_resize_lock(zone->zone_pgdat, &flags);
+	grow_zone_span(zone, pfn, pfn + nr_pages);
+	grow_pgdat_span(zone->zone_pgdat, pfn, pfn + nr_pages);
+	pgdat_resize_unlock(zone->zone_pgdat, &flags);
+
+	for (i = 0; i < nr_pages; i++) {
+		struct page *page = pfn_to_page(pfn + i);
+		online_page(page);
+		onlined_pages++;
+	}
+	zone->present_pages += onlined_pages;
+
+	setup_per_zone_pages_min();
+
+	return 0;
+}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 37af443..5abc57c 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2,6 +2,7 @@
  * Simple NUMA memory policy for the Linux kernel.
  *
  * Copyright 2003,2004 Andi Kleen, SuSE Labs.
+ * (C) Copyright 2005 Christoph Lameter, Silicon Graphics, Inc.
  * Subject to the GNU Public License, version 2.
  *
  * NUMA policy allows the user to give hints in which node(s) memory should
@@ -17,13 +18,19 @@
  *                offset into the backing object or offset into the mapping
  *                for anonymous memory. For process policy an process counter
  *                is used.
+ *
  * bind           Only allocate memory on a specific set of nodes,
  *                no fallback.
+ *                FIXME: memory is allocated starting with the first node
+ *                to the last. It would be better if bind would truly restrict
+ *                the allocation to memory nodes instead
+ *
  * preferred       Try a specific node first before normal fallback.
  *                As a special case node -1 here means do the allocation
  *                on the local CPU. This is normally identical to default,
  *                but useful to set in a VMA when you have a non default
  *                process policy.
+ *
  * default        Allocate on the local node first, or when on a VMA
  *                use the process policy. This is what Linux always did
  *		  in a NUMA aware kernel and still does by, ahem, default.
@@ -93,23 +100,10 @@
 	.policy = MPOL_DEFAULT,
 };
 
-/* Check if all specified nodes are online */
-static int nodes_online(unsigned long *nodes)
-{
-	DECLARE_BITMAP(online2, MAX_NUMNODES);
-
-	bitmap_copy(online2, nodes_addr(node_online_map), MAX_NUMNODES);
-	if (bitmap_empty(online2, MAX_NUMNODES))
-		set_bit(0, online2);
-	if (!bitmap_subset(nodes, online2, MAX_NUMNODES))
-		return -EINVAL;
-	return 0;
-}
-
 /* Do sanity checking on a policy */
-static int mpol_check_policy(int mode, unsigned long *nodes)
+static int mpol_check_policy(int mode, nodemask_t *nodes)
 {
-	int empty = bitmap_empty(nodes, MAX_NUMNODES);
+	int empty = nodes_empty(*nodes);
 
 	switch (mode) {
 	case MPOL_DEFAULT:
@@ -124,71 +118,20 @@
 			return -EINVAL;
 		break;
 	}
-	return nodes_online(nodes);
+	return nodes_subset(*nodes, node_online_map) ? 0 : -EINVAL;
 }
-
-/* Copy a node mask from user space. */
-static int get_nodes(unsigned long *nodes, unsigned long __user *nmask,
-		     unsigned long maxnode, int mode)
-{
-	unsigned long k;
-	unsigned long nlongs;
-	unsigned long endmask;
-
-	--maxnode;
-	bitmap_zero(nodes, MAX_NUMNODES);
-	if (maxnode == 0 || !nmask)
-		return 0;
-
-	nlongs = BITS_TO_LONGS(maxnode);
-	if ((maxnode % BITS_PER_LONG) == 0)
-		endmask = ~0UL;
-	else
-		endmask = (1UL << (maxnode % BITS_PER_LONG)) - 1;
-
-	/* When the user specified more nodes than supported just check
-	   if the non supported part is all zero. */
-	if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
-		if (nlongs > PAGE_SIZE/sizeof(long))
-			return -EINVAL;
-		for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
-			unsigned long t;
-			if (get_user(t,  nmask + k))
-				return -EFAULT;
-			if (k == nlongs - 1) {
-				if (t & endmask)
-					return -EINVAL;
-			} else if (t)
-				return -EINVAL;
-		}
-		nlongs = BITS_TO_LONGS(MAX_NUMNODES);
-		endmask = ~0UL;
-	}
-
-	if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long)))
-		return -EFAULT;
-	nodes[nlongs-1] &= endmask;
-	/* Update current mems_allowed */
-	cpuset_update_current_mems_allowed();
-	/* Ignore nodes not set in current->mems_allowed */
-	cpuset_restrict_to_mems_allowed(nodes);
-	return mpol_check_policy(mode, nodes);
-}
-
 /* Generate a custom zonelist for the BIND policy. */
-static struct zonelist *bind_zonelist(unsigned long *nodes)
+static struct zonelist *bind_zonelist(nodemask_t *nodes)
 {
 	struct zonelist *zl;
 	int num, max, nd;
 
-	max = 1 + MAX_NR_ZONES * bitmap_weight(nodes, MAX_NUMNODES);
+	max = 1 + MAX_NR_ZONES * nodes_weight(*nodes);
 	zl = kmalloc(sizeof(void *) * max, GFP_KERNEL);
 	if (!zl)
 		return NULL;
 	num = 0;
-	for (nd = find_first_bit(nodes, MAX_NUMNODES);
-	     nd < MAX_NUMNODES;
-	     nd = find_next_bit(nodes, MAX_NUMNODES, 1+nd)) {
+	for_each_node_mask(nd, *nodes) {
 		int k;
 		for (k = MAX_NR_ZONES-1; k >= 0; k--) {
 			struct zone *z = &NODE_DATA(nd)->node_zones[k];
@@ -199,17 +142,16 @@
 				policy_zone = k;
 		}
 	}
-	BUG_ON(num >= max);
 	zl->zones[num] = NULL;
 	return zl;
 }
 
 /* Create a new policy */
-static struct mempolicy *mpol_new(int mode, unsigned long *nodes)
+static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
 {
 	struct mempolicy *policy;
 
-	PDprintk("setting mode %d nodes[0] %lx\n", mode, nodes[0]);
+	PDprintk("setting mode %d nodes[0] %lx\n", mode, nodes_addr(*nodes)[0]);
 	if (mode == MPOL_DEFAULT)
 		return NULL;
 	policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
@@ -218,10 +160,10 @@
 	atomic_set(&policy->refcnt, 1);
 	switch (mode) {
 	case MPOL_INTERLEAVE:
-		bitmap_copy(policy->v.nodes, nodes, MAX_NUMNODES);
+		policy->v.nodes = *nodes;
 		break;
 	case MPOL_PREFERRED:
-		policy->v.preferred_node = find_first_bit(nodes, MAX_NUMNODES);
+		policy->v.preferred_node = first_node(*nodes);
 		if (policy->v.preferred_node >= MAX_NUMNODES)
 			policy->v.preferred_node = -1;
 		break;
@@ -238,14 +180,14 @@
 }
 
 /* Ensure all existing pages follow the policy. */
-static int check_pte_range(struct mm_struct *mm, pmd_t *pmd,
-		unsigned long addr, unsigned long end, unsigned long *nodes)
+static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+		unsigned long addr, unsigned long end, nodemask_t *nodes)
 {
 	pte_t *orig_pte;
 	pte_t *pte;
+	spinlock_t *ptl;
 
-	spin_lock(&mm->page_table_lock);
-	orig_pte = pte = pte_offset_map(pmd, addr);
+	orig_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	do {
 		unsigned long pfn;
 		unsigned int nid;
@@ -253,19 +195,20 @@
 		if (!pte_present(*pte))
 			continue;
 		pfn = pte_pfn(*pte);
-		if (!pfn_valid(pfn))
+		if (!pfn_valid(pfn)) {
+			print_bad_pte(vma, *pte, addr);
 			continue;
+		}
 		nid = pfn_to_nid(pfn);
-		if (!test_bit(nid, nodes))
+		if (!node_isset(nid, *nodes))
 			break;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(orig_pte);
-	spin_unlock(&mm->page_table_lock);
+	pte_unmap_unlock(orig_pte, ptl);
 	return addr != end;
 }
 
-static inline int check_pmd_range(struct mm_struct *mm, pud_t *pud,
-		unsigned long addr, unsigned long end, unsigned long *nodes)
+static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud,
+		unsigned long addr, unsigned long end, nodemask_t *nodes)
 {
 	pmd_t *pmd;
 	unsigned long next;
@@ -275,14 +218,14 @@
 		next = pmd_addr_end(addr, end);
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		if (check_pte_range(mm, pmd, addr, next, nodes))
+		if (check_pte_range(vma, pmd, addr, next, nodes))
 			return -EIO;
 	} while (pmd++, addr = next, addr != end);
 	return 0;
 }
 
-static inline int check_pud_range(struct mm_struct *mm, pgd_t *pgd,
-		unsigned long addr, unsigned long end, unsigned long *nodes)
+static inline int check_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
+		unsigned long addr, unsigned long end, nodemask_t *nodes)
 {
 	pud_t *pud;
 	unsigned long next;
@@ -292,24 +235,24 @@
 		next = pud_addr_end(addr, end);
 		if (pud_none_or_clear_bad(pud))
 			continue;
-		if (check_pmd_range(mm, pud, addr, next, nodes))
+		if (check_pmd_range(vma, pud, addr, next, nodes))
 			return -EIO;
 	} while (pud++, addr = next, addr != end);
 	return 0;
 }
 
-static inline int check_pgd_range(struct mm_struct *mm,
-		unsigned long addr, unsigned long end, unsigned long *nodes)
+static inline int check_pgd_range(struct vm_area_struct *vma,
+		unsigned long addr, unsigned long end, nodemask_t *nodes)
 {
 	pgd_t *pgd;
 	unsigned long next;
 
-	pgd = pgd_offset(mm, addr);
+	pgd = pgd_offset(vma->vm_mm, addr);
 	do {
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
-		if (check_pud_range(mm, pgd, addr, next, nodes))
+		if (check_pud_range(vma, pgd, addr, next, nodes))
 			return -EIO;
 	} while (pgd++, addr = next, addr != end);
 	return 0;
@@ -318,7 +261,7 @@
 /* Step 1: check the range */
 static struct vm_area_struct *
 check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
-	    unsigned long *nodes, unsigned long flags)
+	    nodemask_t *nodes, unsigned long flags)
 {
 	int err;
 	struct vm_area_struct *first, *vma, *prev;
@@ -326,6 +269,8 @@
 	first = find_vma(mm, start);
 	if (!first)
 		return ERR_PTR(-EFAULT);
+	if (first->vm_flags & VM_RESERVED)
+		return ERR_PTR(-EACCES);
 	prev = NULL;
 	for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) {
 		if (!vma->vm_next && vma->vm_end < end)
@@ -338,8 +283,7 @@
 				endvma = end;
 			if (vma->vm_start > start)
 				start = vma->vm_start;
-			err = check_pgd_range(vma->vm_mm,
-					   start, endvma, nodes);
+			err = check_pgd_range(vma, start, endvma, nodes);
 			if (err) {
 				first = ERR_PTR(err);
 				break;
@@ -393,17 +337,25 @@
 	return err;
 }
 
-/* Change policy for a memory range */
-asmlinkage long sys_mbind(unsigned long start, unsigned long len,
-			  unsigned long mode,
-			  unsigned long __user *nmask, unsigned long maxnode,
-			  unsigned flags)
+static int contextualize_policy(int mode, nodemask_t *nodes)
+{
+	if (!nodes)
+		return 0;
+
+	/* Update current mems_allowed */
+	cpuset_update_current_mems_allowed();
+	/* Ignore nodes not set in current->mems_allowed */
+	cpuset_restrict_to_mems_allowed(nodes->bits);
+	return mpol_check_policy(mode, nodes);
+}
+
+long do_mbind(unsigned long start, unsigned long len,
+		unsigned long mode, nodemask_t *nmask, unsigned long flags)
 {
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	struct mempolicy *new;
 	unsigned long end;
-	DECLARE_BITMAP(nodes, MAX_NUMNODES);
 	int err;
 
 	if ((flags & ~(unsigned long)(MPOL_MF_STRICT)) || mode > MPOL_MAX)
@@ -418,20 +370,17 @@
 		return -EINVAL;
 	if (end == start)
 		return 0;
-
-	err = get_nodes(nodes, nmask, maxnode, mode);
-	if (err)
-		return err;
-
-	new = mpol_new(mode, nodes);
+	if (mpol_check_policy(mode, nmask))
+		return -EINVAL;
+	new = mpol_new(mode, nmask);
 	if (IS_ERR(new))
 		return PTR_ERR(new);
 
 	PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
-			mode,nodes[0]);
+			mode,nodes_addr(nodes)[0]);
 
 	down_write(&mm->mmap_sem);
-	vma = check_range(mm, start, end, nodes, flags);
+	vma = check_range(mm, start, end, nmask, flags);
 	err = PTR_ERR(vma);
 	if (!IS_ERR(vma))
 		err = mbind_range(vma, start, end, new);
@@ -441,50 +390,45 @@
 }
 
 /* Set the process memory policy */
-asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
-				   unsigned long maxnode)
+long do_set_mempolicy(int mode, nodemask_t *nodes)
 {
-	int err;
 	struct mempolicy *new;
-	DECLARE_BITMAP(nodes, MAX_NUMNODES);
 
-	if (mode < 0 || mode > MPOL_MAX)
+	if (contextualize_policy(mode, nodes))
 		return -EINVAL;
-	err = get_nodes(nodes, nmask, maxnode, mode);
-	if (err)
-		return err;
 	new = mpol_new(mode, nodes);
 	if (IS_ERR(new))
 		return PTR_ERR(new);
 	mpol_free(current->mempolicy);
 	current->mempolicy = new;
 	if (new && new->policy == MPOL_INTERLEAVE)
-		current->il_next = find_first_bit(new->v.nodes, MAX_NUMNODES);
+		current->il_next = first_node(new->v.nodes);
 	return 0;
 }
 
 /* Fill a zone bitmap for a policy */
-static void get_zonemask(struct mempolicy *p, unsigned long *nodes)
+static void get_zonemask(struct mempolicy *p, nodemask_t *nodes)
 {
 	int i;
 
-	bitmap_zero(nodes, MAX_NUMNODES);
+	nodes_clear(*nodes);
 	switch (p->policy) {
 	case MPOL_BIND:
 		for (i = 0; p->v.zonelist->zones[i]; i++)
-			__set_bit(p->v.zonelist->zones[i]->zone_pgdat->node_id, nodes);
+			node_set(p->v.zonelist->zones[i]->zone_pgdat->node_id,
+				*nodes);
 		break;
 	case MPOL_DEFAULT:
 		break;
 	case MPOL_INTERLEAVE:
-		bitmap_copy(nodes, p->v.nodes, MAX_NUMNODES);
+		*nodes = p->v.nodes;
 		break;
 	case MPOL_PREFERRED:
 		/* or use current node instead of online map? */
 		if (p->v.preferred_node < 0)
-			bitmap_copy(nodes, nodes_addr(node_online_map), MAX_NUMNODES);
+			*nodes = node_online_map;
 		else
-			__set_bit(p->v.preferred_node, nodes);
+			node_set(p->v.preferred_node, *nodes);
 		break;
 	default:
 		BUG();
@@ -504,37 +448,18 @@
 	return err;
 }
 
-/* Copy a kernel node mask to user space */
-static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
-			      void *nodes, unsigned nbytes)
-{
-	unsigned long copy = ALIGN(maxnode-1, 64) / 8;
-
-	if (copy > nbytes) {
-		if (copy > PAGE_SIZE)
-			return -EINVAL;
-		if (clear_user((char __user *)mask + nbytes, copy - nbytes))
-			return -EFAULT;
-		copy = nbytes;
-	}
-	return copy_to_user(mask, nodes, copy) ? -EFAULT : 0;
-}
-
 /* Retrieve NUMA policy */
-asmlinkage long sys_get_mempolicy(int __user *policy,
-				  unsigned long __user *nmask,
-				  unsigned long maxnode,
-				  unsigned long addr, unsigned long flags)
+long do_get_mempolicy(int *policy, nodemask_t *nmask,
+			unsigned long addr, unsigned long flags)
 {
-	int err, pval;
+	int err;
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma = NULL;
 	struct mempolicy *pol = current->mempolicy;
 
+	cpuset_update_current_mems_allowed();
 	if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR))
 		return -EINVAL;
-	if (nmask != NULL && maxnode < MAX_NUMNODES)
-		return -EINVAL;
 	if (flags & MPOL_F_ADDR) {
 		down_read(&mm->mmap_sem);
 		vma = find_vma_intersection(mm, addr, addr+1);
@@ -557,31 +482,25 @@
 			err = lookup_node(mm, addr);
 			if (err < 0)
 				goto out;
-			pval = err;
+			*policy = err;
 		} else if (pol == current->mempolicy &&
 				pol->policy == MPOL_INTERLEAVE) {
-			pval = current->il_next;
+			*policy = current->il_next;
 		} else {
 			err = -EINVAL;
 			goto out;
 		}
 	} else
-		pval = pol->policy;
+		*policy = pol->policy;
 
 	if (vma) {
 		up_read(&current->mm->mmap_sem);
 		vma = NULL;
 	}
 
-	if (policy && put_user(pval, policy))
-		return -EFAULT;
-
 	err = 0;
-	if (nmask) {
-		DECLARE_BITMAP(nodes, MAX_NUMNODES);
-		get_zonemask(pol, nodes);
-		err = copy_nodes_to_user(nmask, maxnode, nodes, sizeof(nodes));
-	}
+	if (nmask)
+		get_zonemask(pol, nmask);
 
  out:
 	if (vma)
@@ -589,6 +508,126 @@
 	return err;
 }
 
+/*
+ * User space interface with variable sized bitmaps for nodelists.
+ */
+
+/* Copy a node mask from user space. */
+static int get_nodes(nodemask_t *nodes, unsigned long __user *nmask,
+		     unsigned long maxnode)
+{
+	unsigned long k;
+	unsigned long nlongs;
+	unsigned long endmask;
+
+	--maxnode;
+	nodes_clear(*nodes);
+	if (maxnode == 0 || !nmask)
+		return 0;
+
+	nlongs = BITS_TO_LONGS(maxnode);
+	if ((maxnode % BITS_PER_LONG) == 0)
+		endmask = ~0UL;
+	else
+		endmask = (1UL << (maxnode % BITS_PER_LONG)) - 1;
+
+	/* When the user specified more nodes than supported just check
+	   if the non supported part is all zero. */
+	if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
+		if (nlongs > PAGE_SIZE/sizeof(long))
+			return -EINVAL;
+		for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
+			unsigned long t;
+			if (get_user(t, nmask + k))
+				return -EFAULT;
+			if (k == nlongs - 1) {
+				if (t & endmask)
+					return -EINVAL;
+			} else if (t)
+				return -EINVAL;
+		}
+		nlongs = BITS_TO_LONGS(MAX_NUMNODES);
+		endmask = ~0UL;
+	}
+
+	if (copy_from_user(nodes_addr(*nodes), nmask, nlongs*sizeof(unsigned long)))
+		return -EFAULT;
+	nodes_addr(*nodes)[nlongs-1] &= endmask;
+	return 0;
+}
+
+/* Copy a kernel node mask to user space */
+static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
+			      nodemask_t *nodes)
+{
+	unsigned long copy = ALIGN(maxnode-1, 64) / 8;
+	const int nbytes = BITS_TO_LONGS(MAX_NUMNODES) * sizeof(long);
+
+	if (copy > nbytes) {
+		if (copy > PAGE_SIZE)
+			return -EINVAL;
+		if (clear_user((char __user *)mask + nbytes, copy - nbytes))
+			return -EFAULT;
+		copy = nbytes;
+	}
+	return copy_to_user(mask, nodes_addr(*nodes), copy) ? -EFAULT : 0;
+}
+
+asmlinkage long sys_mbind(unsigned long start, unsigned long len,
+			unsigned long mode,
+			unsigned long __user *nmask, unsigned long maxnode,
+			unsigned flags)
+{
+	nodemask_t nodes;
+	int err;
+
+	err = get_nodes(&nodes, nmask, maxnode);
+	if (err)
+		return err;
+	return do_mbind(start, len, mode, &nodes, flags);
+}
+
+/* Set the process memory policy */
+asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
+		unsigned long maxnode)
+{
+	int err;
+	nodemask_t nodes;
+
+	if (mode < 0 || mode > MPOL_MAX)
+		return -EINVAL;
+	err = get_nodes(&nodes, nmask, maxnode);
+	if (err)
+		return err;
+	return do_set_mempolicy(mode, &nodes);
+}
+
+/* Retrieve NUMA policy */
+asmlinkage long sys_get_mempolicy(int __user *policy,
+				unsigned long __user *nmask,
+				unsigned long maxnode,
+				unsigned long addr, unsigned long flags)
+{
+	int err, pval;
+	nodemask_t nodes;
+
+	if (nmask != NULL && maxnode < MAX_NUMNODES)
+		return -EINVAL;
+
+	err = do_get_mempolicy(&pval, &nodes, addr, flags);
+
+	if (err)
+		return err;
+
+	if (policy && put_user(pval, policy))
+		return -EFAULT;
+
+	if (nmask)
+		err = copy_nodes_to_user(nmask, maxnode, &nodes);
+
+	return err;
+}
+
 #ifdef CONFIG_COMPAT
 
 asmlinkage long compat_sys_get_mempolicy(int __user *policy,
@@ -649,15 +688,15 @@
 	long err = 0;
 	unsigned long __user *nm = NULL;
 	unsigned long nr_bits, alloc_size;
-	DECLARE_BITMAP(bm, MAX_NUMNODES);
+	nodemask_t bm;
 
 	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
 	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
 	if (nmask) {
-		err = compat_get_bitmap(bm, nmask, nr_bits);
+		err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits);
 		nm = compat_alloc_user_space(alloc_size);
-		err |= copy_to_user(nm, bm, alloc_size);
+		err |= copy_to_user(nm, nodes_addr(bm), alloc_size);
 	}
 
 	if (err)
@@ -676,7 +715,7 @@
 
 	if (vma) {
 		if (vma->vm_ops && vma->vm_ops->get_policy)
-		        pol = vma->vm_ops->get_policy(vma, addr);
+			pol = vma->vm_ops->get_policy(vma, addr);
 		else if (vma->vm_policy &&
 				vma->vm_policy->policy != MPOL_DEFAULT)
 			pol = vma->vm_policy;
@@ -700,7 +739,7 @@
 	case MPOL_BIND:
 		/* Lower zones don't get a policy applied */
 		/* Careful: current->mems_allowed might have moved */
-		if ((gfp & GFP_ZONEMASK) >= policy_zone)
+		if (gfp_zone(gfp) >= policy_zone)
 			if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
 				return policy->v.zonelist;
 		/*FALL THROUGH*/
@@ -712,7 +751,7 @@
 		nd = 0;
 		BUG();
 	}
-	return NODE_DATA(nd)->node_zonelists + (gfp & GFP_ZONEMASK);
+	return NODE_DATA(nd)->node_zonelists + gfp_zone(gfp);
 }
 
 /* Do dynamic interleaving for a process */
@@ -722,10 +761,9 @@
 	struct task_struct *me = current;
 
 	nid = me->il_next;
-	BUG_ON(nid >= MAX_NUMNODES);
-	next = find_next_bit(policy->v.nodes, MAX_NUMNODES, 1+nid);
+	next = next_node(nid, policy->v.nodes);
 	if (next >= MAX_NUMNODES)
-		next = find_first_bit(policy->v.nodes, MAX_NUMNODES);
+		next = first_node(policy->v.nodes);
 	me->il_next = next;
 	return nid;
 }
@@ -734,30 +772,28 @@
 static unsigned offset_il_node(struct mempolicy *pol,
 		struct vm_area_struct *vma, unsigned long off)
 {
-	unsigned nnodes = bitmap_weight(pol->v.nodes, MAX_NUMNODES);
+	unsigned nnodes = nodes_weight(pol->v.nodes);
 	unsigned target = (unsigned)off % nnodes;
 	int c;
 	int nid = -1;
 
 	c = 0;
 	do {
-		nid = find_next_bit(pol->v.nodes, MAX_NUMNODES, nid+1);
+		nid = next_node(nid, pol->v.nodes);
 		c++;
 	} while (c <= target);
-	BUG_ON(nid >= MAX_NUMNODES);
-	BUG_ON(!test_bit(nid, pol->v.nodes));
 	return nid;
 }
 
 /* Allocate a page in interleaved policy.
    Own path because it needs to do special accounting. */
-static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, unsigned nid)
+static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
+					unsigned nid)
 {
 	struct zonelist *zl;
 	struct page *page;
 
-	BUG_ON(!node_online(nid));
-	zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
+	zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp);
 	page = __alloc_pages(gfp, order, zl);
 	if (page && page_zone(page) == zl->zones[0]) {
 		zone_pcp(zl->zones[0],get_cpu())->interleave_hit++;
@@ -799,8 +835,6 @@
 		unsigned nid;
 		if (vma) {
 			unsigned long off;
-			BUG_ON(addr >= vma->vm_end);
-			BUG_ON(addr < vma->vm_start);
 			off = vma->vm_pgoff;
 			off += (addr - vma->vm_start) >> PAGE_SHIFT;
 			nid = offset_il_node(pol, vma, off);
@@ -878,7 +912,7 @@
 	case MPOL_DEFAULT:
 		return 1;
 	case MPOL_INTERLEAVE:
-		return bitmap_equal(a->v.nodes, b->v.nodes, MAX_NUMNODES);
+		return nodes_equal(a->v.nodes, b->v.nodes);
 	case MPOL_PREFERRED:
 		return a->v.preferred_node == b->v.preferred_node;
 	case MPOL_BIND: {
@@ -1117,7 +1151,7 @@
 	PDprintk("set_shared_policy %lx sz %lu %d %lx\n",
 		 vma->vm_pgoff,
 		 sz, npol? npol->policy : -1,
-		npol ? npol->v.nodes[0] : -1);
+		npol ? nodes_addr(npol->v.nodes)[0] : -1);
 
 	if (npol) {
 		new = sp_alloc(vma->vm_pgoff, vma->vm_pgoff + sz, npol);
@@ -1164,14 +1198,75 @@
 	/* Set interleaving policy for system init. This way not all
 	   the data structures allocated at system boot end up in node zero. */
 
-	if (sys_set_mempolicy(MPOL_INTERLEAVE, nodes_addr(node_online_map),
-							MAX_NUMNODES) < 0)
+	if (do_set_mempolicy(MPOL_INTERLEAVE, &node_online_map))
 		printk("numa_policy_init: interleaving failed\n");
 }
 
-/* Reset policy of current process to default.
- * Assumes fs == KERNEL_DS */
+/* Reset policy of current process to default */
 void numa_default_policy(void)
 {
-	sys_set_mempolicy(MPOL_DEFAULT, NULL, 0);
+	do_set_mempolicy(MPOL_DEFAULT, NULL);
+}
+
+/* Migrate a policy to a different set of nodes */
+static void rebind_policy(struct mempolicy *pol, const nodemask_t *old,
+							const nodemask_t *new)
+{
+	nodemask_t tmp;
+
+	if (!pol)
+		return;
+
+	switch (pol->policy) {
+	case MPOL_DEFAULT:
+		break;
+	case MPOL_INTERLEAVE:
+		nodes_remap(tmp, pol->v.nodes, *old, *new);
+		pol->v.nodes = tmp;
+		current->il_next = node_remap(current->il_next, *old, *new);
+		break;
+	case MPOL_PREFERRED:
+		pol->v.preferred_node = node_remap(pol->v.preferred_node,
+								*old, *new);
+		break;
+	case MPOL_BIND: {
+		nodemask_t nodes;
+		struct zone **z;
+		struct zonelist *zonelist;
+
+		nodes_clear(nodes);
+		for (z = pol->v.zonelist->zones; *z; z++)
+			node_set((*z)->zone_pgdat->node_id, nodes);
+		nodes_remap(tmp, nodes, *old, *new);
+		nodes = tmp;
+
+		zonelist = bind_zonelist(&nodes);
+
+		/* If no mem, then zonelist is NULL and we keep old zonelist.
+		 * If that old zonelist has no remaining mems_allowed nodes,
+		 * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT.
+		 */
+
+		if (zonelist) {
+			/* Good - got mem - substitute new zonelist */
+			kfree(pol->v.zonelist);
+			pol->v.zonelist = zonelist;
+		}
+		break;
+	}
+	default:
+		BUG();
+		break;
+	}
+}
+
+/*
+ * Someone moved this task to different nodes.  Fixup mempolicies.
+ *
+ * TODO - fixup current->mm->vma and shmfs/tmpfs/hugetlbfs policies as well,
+ * once we have a cpuset mechanism to mark which cpuset subtree is migrating.
+ */
+void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new)
+{
+	rebind_policy(current->mempolicy, old, new);
 }
diff --git a/mm/mempool.c b/mm/mempool.c
index 9e377ea..1a99b80 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -205,7 +205,7 @@
 	void *element;
 	unsigned long flags;
 	wait_queue_t wait;
-	unsigned int gfp_temp;
+	gfp_t gfp_temp;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
diff --git a/mm/mmap.c b/mm/mmap.c
index fa11d91..320dda1 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -181,26 +181,36 @@
 }
 
 /*
- * Remove one vm structure and free it.
+ * Unlink a file-based vm structure from its prio_tree, to hide
+ * vma from rmap and vmtruncate before freeing its page tables.
  */
-static void remove_vm_struct(struct vm_area_struct *vma)
+void unlink_file_vma(struct vm_area_struct *vma)
 {
 	struct file *file = vma->vm_file;
 
-	might_sleep();
 	if (file) {
 		struct address_space *mapping = file->f_mapping;
 		spin_lock(&mapping->i_mmap_lock);
 		__remove_shared_vm_struct(vma, file, mapping);
 		spin_unlock(&mapping->i_mmap_lock);
 	}
+}
+
+/*
+ * Close a vm structure and free it, returning the next.
+ */
+static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
+{
+	struct vm_area_struct *next = vma->vm_next;
+
+	might_sleep();
 	if (vma->vm_ops && vma->vm_ops->close)
 		vma->vm_ops->close(vma);
-	if (file)
-		fput(file);
-	anon_vma_unlink(vma);
+	if (vma->vm_file)
+		fput(vma->vm_file);
 	mpol_free(vma_policy(vma));
 	kmem_cache_free(vm_area_cachep, vma);
+	return next;
 }
 
 asmlinkage unsigned long sys_brk(unsigned long brk)
@@ -832,7 +842,7 @@
 }
 
 #ifdef CONFIG_PROC_FS
-void __vm_stat_account(struct mm_struct *mm, unsigned long flags,
+void vm_stat_account(struct mm_struct *mm, unsigned long flags,
 						struct file *file, long pages)
 {
 	const unsigned long stack_flags
@@ -1070,6 +1080,17 @@
 		error = file->f_op->mmap(file, vma);
 		if (error)
 			goto unmap_and_free_vma;
+		if ((vma->vm_flags & (VM_SHARED | VM_WRITE | VM_RESERVED))
+						== (VM_WRITE | VM_RESERVED)) {
+			printk(KERN_WARNING "program %s is using MAP_PRIVATE, "
+				"PROT_WRITE mmap of VM_RESERVED memory, which "
+				"is deprecated. Please report this to "
+				"linux-kernel@vger.kernel.org\n",current->comm);
+			if (vma->vm_ops && vma->vm_ops->close)
+				vma->vm_ops->close(vma);
+			error = -EACCES;
+			goto unmap_and_free_vma;
+		}
 	} else if (vm_flags & VM_SHARED) {
 		error = shmem_zero_setup(vma);
 		if (error)
@@ -1110,7 +1131,7 @@
 	}
 out:	
 	mm->total_vm += len >> PAGE_SHIFT;
-	__vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
+	vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
 	if (vm_flags & VM_LOCKED) {
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
@@ -1475,15 +1496,19 @@
 	mm->total_vm += grow;
 	if (vma->vm_flags & VM_LOCKED)
 		mm->locked_vm += grow;
-	__vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
+	vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
 	return 0;
 }
 
-#ifdef CONFIG_STACK_GROWSUP
+#if defined(CONFIG_STACK_GROWSUP) || defined(CONFIG_IA64)
 /*
- * vma is the first one with address > vma->vm_end.  Have to extend vma.
+ * PA-RISC uses this for its stack; IA64 for its Register Backing Store.
+ * vma is the last one with address > vma->vm_end.  Have to extend vma.
  */
-int expand_stack(struct vm_area_struct * vma, unsigned long address)
+#ifdef CONFIG_STACK_GROWSUP
+static inline
+#endif
+int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 {
 	int error;
 
@@ -1521,6 +1546,13 @@
 	anon_vma_unlock(vma);
 	return error;
 }
+#endif /* CONFIG_STACK_GROWSUP || CONFIG_IA64 */
+
+#ifdef CONFIG_STACK_GROWSUP
+int expand_stack(struct vm_area_struct *vma, unsigned long address)
+{
+	return expand_upwards(vma, address);
+}
 
 struct vm_area_struct *
 find_extend_vma(struct mm_struct *mm, unsigned long addr)
@@ -1603,36 +1635,24 @@
 }
 #endif
 
-/* Normal function to fix up a mapping
- * This function is the default for when an area has no specific
- * function.  This may be used as part of a more specific routine.
- *
- * By the time this function is called, the area struct has been
- * removed from the process mapping list.
- */
-static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
-{
-	size_t len = area->vm_end - area->vm_start;
-
-	area->vm_mm->total_vm -= len >> PAGE_SHIFT;
-	if (area->vm_flags & VM_LOCKED)
-		area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
-	vm_stat_unaccount(area);
-	remove_vm_struct(area);
-}
-
 /*
- * Update the VMA and inode share lists.
- *
- * Ok - we have the memory areas we should free on the 'free' list,
+ * Ok - we have the memory areas we should free on the vma list,
  * so release them, and do the vma updates.
+ *
+ * Called with the mm semaphore held.
  */
-static void unmap_vma_list(struct mm_struct *mm, struct vm_area_struct *vma)
+static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma)
 {
+	/* Update high watermark before we lower total_vm */
+	update_hiwater_vm(mm);
 	do {
-		struct vm_area_struct *next = vma->vm_next;
-		unmap_vma(mm, vma);
-		vma = next;
+		long nrpages = vma_pages(vma);
+
+		mm->total_vm -= nrpages;
+		if (vma->vm_flags & VM_LOCKED)
+			mm->locked_vm -= nrpages;
+		vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages);
+		vma = remove_vma(vma);
 	} while (vma);
 	validate_mm(mm);
 }
@@ -1651,14 +1671,13 @@
 	unsigned long nr_accounted = 0;
 
 	lru_add_drain();
-	spin_lock(&mm->page_table_lock);
 	tlb = tlb_gather_mmu(mm, 0);
-	unmap_vmas(&tlb, mm, vma, start, end, &nr_accounted, NULL);
+	update_hiwater_rss(mm);
+	unmap_vmas(&tlb, vma, start, end, &nr_accounted, NULL);
 	vm_unacct_memory(nr_accounted);
 	free_pgtables(&tlb, vma, prev? prev->vm_end: FIRST_USER_ADDRESS,
 				 next? next->vm_start: 0);
 	tlb_finish_mmu(tlb, start, end);
-	spin_unlock(&mm->page_table_lock);
 }
 
 /*
@@ -1799,7 +1818,7 @@
 	unmap_region(mm, vma, prev, start, end);
 
 	/* Fix up all other VM information */
-	unmap_vma_list(mm, vma);
+	remove_vma_list(mm, vma);
 
 	return 0;
 }
@@ -1821,7 +1840,7 @@
 
 static inline void verify_mm_writelocked(struct mm_struct *mm)
 {
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_VM
 	if (unlikely(down_read_trylock(&mm->mmap_sem))) {
 		WARN_ON(1);
 		up_read(&mm->mmap_sem);
@@ -1933,34 +1952,21 @@
 	unsigned long end;
 
 	lru_add_drain();
-
-	spin_lock(&mm->page_table_lock);
-
 	flush_cache_mm(mm);
 	tlb = tlb_gather_mmu(mm, 1);
+	/* Don't update_hiwater_rss(mm) here, do_exit already did */
 	/* Use -1 here to ensure all VMAs in the mm are unmapped */
-	end = unmap_vmas(&tlb, mm, vma, 0, -1, &nr_accounted, NULL);
+	end = unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL);
 	vm_unacct_memory(nr_accounted);
 	free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
 	tlb_finish_mmu(tlb, 0, end);
 
-	mm->mmap = mm->mmap_cache = NULL;
-	mm->mm_rb = RB_ROOT;
-	set_mm_counter(mm, rss, 0);
-	mm->total_vm = 0;
-	mm->locked_vm = 0;
-
-	spin_unlock(&mm->page_table_lock);
-
 	/*
-	 * Walk the list again, actually closing and freeing it
-	 * without holding any MM locks.
+	 * Walk the list again, actually closing and freeing it,
+	 * with preemption enabled, without holding any MM locks.
 	 */
-	while (vma) {
-		struct vm_area_struct *next = vma->vm_next;
-		remove_vm_struct(vma);
-		vma = next;
-	}
+	while (vma)
+		vma = remove_vma(vma);
 
 	BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
 }
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 57577f6..17a2b52 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -29,8 +29,9 @@
 		unsigned long addr, unsigned long end, pgprot_t newprot)
 {
 	pte_t *pte;
+	spinlock_t *ptl;
 
-	pte = pte_offset_map(pmd, addr);
+	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	do {
 		if (pte_present(*pte)) {
 			pte_t ptent;
@@ -44,7 +45,7 @@
 			lazy_mmu_prot_update(ptent);
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
+	pte_unmap_unlock(pte - 1, ptl);
 }
 
 static inline void change_pmd_range(struct mm_struct *mm, pud_t *pud,
@@ -88,7 +89,6 @@
 	BUG_ON(addr >= end);
 	pgd = pgd_offset(mm, addr);
 	flush_cache_range(vma, addr, end);
-	spin_lock(&mm->page_table_lock);
 	do {
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
@@ -96,7 +96,6 @@
 		change_pud_range(mm, pgd, addr, next, newprot);
 	} while (pgd++, addr = next, addr != end);
 	flush_tlb_range(vma, start, end);
-	spin_unlock(&mm->page_table_lock);
 }
 
 static int
@@ -125,6 +124,14 @@
 	 * a MAP_NORESERVE private mapping to writable will now reserve.
 	 */
 	if (newflags & VM_WRITE) {
+		if (oldflags & VM_RESERVED) {
+			BUG_ON(oldflags & VM_WRITE);
+			printk(KERN_WARNING "program %s is using MAP_PRIVATE, "
+				"PROT_WRITE mprotect of VM_RESERVED memory, "
+				"which is deprecated. Please report this to "
+				"linux-kernel@vger.kernel.org\n",current->comm);
+			return -EACCES;
+		}
 		if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) {
 			charged = nrpages;
 			if (security_vm_enough_memory(charged))
@@ -168,8 +175,8 @@
 	vma->vm_flags = newflags;
 	vma->vm_page_prot = newprot;
 	change_protection(vma, start, end, newprot);
-	__vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
-	__vm_stat_account(mm, newflags, vma->vm_file, nrpages);
+	vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
+	vm_stat_account(mm, newflags, vma->vm_file, nrpages);
 	return 0;
 
 fail:
diff --git a/mm/mremap.c b/mm/mremap.c
index f343fc7..b535438 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -22,35 +22,7 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-static pte_t *get_one_pte_map_nested(struct mm_struct *mm, unsigned long addr)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte = NULL;
-
-	pgd = pgd_offset(mm, addr);
-	if (pgd_none_or_clear_bad(pgd))
-		goto end;
-
-	pud = pud_offset(pgd, addr);
-	if (pud_none_or_clear_bad(pud))
-		goto end;
-
-	pmd = pmd_offset(pud, addr);
-	if (pmd_none_or_clear_bad(pmd))
-		goto end;
-
-	pte = pte_offset_map_nested(pmd, addr);
-	if (pte_none(*pte)) {
-		pte_unmap_nested(pte);
-		pte = NULL;
-	}
-end:
-	return pte;
-}
-
-static pte_t *get_one_pte_map(struct mm_struct *mm, unsigned long addr)
+static pmd_t *get_old_pmd(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -68,35 +40,39 @@
 	if (pmd_none_or_clear_bad(pmd))
 		return NULL;
 
-	return pte_offset_map(pmd, addr);
+	return pmd;
 }
 
-static inline pte_t *alloc_one_pte_map(struct mm_struct *mm, unsigned long addr)
+static pmd_t *alloc_new_pmd(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
-	pte_t *pte = NULL;
 
 	pgd = pgd_offset(mm, addr);
-
 	pud = pud_alloc(mm, pgd, addr);
 	if (!pud)
 		return NULL;
+
 	pmd = pmd_alloc(mm, pud, addr);
-	if (pmd)
-		pte = pte_alloc_map(mm, pmd, addr);
-	return pte;
+	if (!pmd)
+		return NULL;
+
+	if (!pmd_present(*pmd) && __pte_alloc(mm, pmd, addr))
+		return NULL;
+
+	return pmd;
 }
 
-static int
-move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
-		struct vm_area_struct *new_vma, unsigned long new_addr)
+static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
+		unsigned long old_addr, unsigned long old_end,
+		struct vm_area_struct *new_vma, pmd_t *new_pmd,
+		unsigned long new_addr)
 {
 	struct address_space *mapping = NULL;
 	struct mm_struct *mm = vma->vm_mm;
-	int error = 0;
-	pte_t *src, *dst;
+	pte_t *old_pte, *new_pte, pte;
+	spinlock_t *old_ptl, *new_ptl;
 
 	if (vma->vm_file) {
 		/*
@@ -111,74 +87,69 @@
 		    new_vma->vm_truncate_count != vma->vm_truncate_count)
 			new_vma->vm_truncate_count = 0;
 	}
-	spin_lock(&mm->page_table_lock);
 
-	src = get_one_pte_map_nested(mm, old_addr);
-	if (src) {
-		/*
-		 * Look to see whether alloc_one_pte_map needs to perform a
-		 * memory allocation.  If it does then we need to drop the
-		 * atomic kmap
-		 */
-		dst = get_one_pte_map(mm, new_addr);
-		if (unlikely(!dst)) {
-			pte_unmap_nested(src);
-			if (mapping)
-				spin_unlock(&mapping->i_mmap_lock);
-			dst = alloc_one_pte_map(mm, new_addr);
-			if (mapping && !spin_trylock(&mapping->i_mmap_lock)) {
-				spin_unlock(&mm->page_table_lock);
-				spin_lock(&mapping->i_mmap_lock);
-				spin_lock(&mm->page_table_lock);
-			}
-			src = get_one_pte_map_nested(mm, old_addr);
-		}
-		/*
-		 * Since alloc_one_pte_map can drop and re-acquire
-		 * page_table_lock, we should re-check the src entry...
-		 */
-		if (src) {
-			if (dst) {
-				pte_t pte;
-				pte = ptep_clear_flush(vma, old_addr, src);
+	/*
+	 * We don't have to worry about the ordering of src and dst
+	 * pte locks because exclusive mmap_sem prevents deadlock.
+	 */
+	old_pte = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl);
+ 	new_pte = pte_offset_map_nested(new_pmd, new_addr);
+	new_ptl = pte_lockptr(mm, new_pmd);
+	if (new_ptl != old_ptl)
+		spin_lock(new_ptl);
 
-				/* ZERO_PAGE can be dependant on virtual addr */
-				pte = move_pte(pte, new_vma->vm_page_prot,
-							old_addr, new_addr);
-				set_pte_at(mm, new_addr, dst, pte);
-			} else
-				error = -ENOMEM;
-			pte_unmap_nested(src);
-		}
-		if (dst)
-			pte_unmap(dst);
+	for (; old_addr < old_end; old_pte++, old_addr += PAGE_SIZE,
+				   new_pte++, new_addr += PAGE_SIZE) {
+		if (pte_none(*old_pte))
+			continue;
+		pte = ptep_clear_flush(vma, old_addr, old_pte);
+		/* ZERO_PAGE can be dependant on virtual addr */
+		pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
+		set_pte_at(mm, new_addr, new_pte, pte);
 	}
-	spin_unlock(&mm->page_table_lock);
+
+	if (new_ptl != old_ptl)
+		spin_unlock(new_ptl);
+	pte_unmap_nested(new_pte - 1);
+	pte_unmap_unlock(old_pte - 1, old_ptl);
 	if (mapping)
 		spin_unlock(&mapping->i_mmap_lock);
-	return error;
 }
 
+#define LATENCY_LIMIT	(64 * PAGE_SIZE)
+
 static unsigned long move_page_tables(struct vm_area_struct *vma,
 		unsigned long old_addr, struct vm_area_struct *new_vma,
 		unsigned long new_addr, unsigned long len)
 {
-	unsigned long offset;
+	unsigned long extent, next, old_end;
+	pmd_t *old_pmd, *new_pmd;
 
-	flush_cache_range(vma, old_addr, old_addr + len);
+	old_end = old_addr + len;
+	flush_cache_range(vma, old_addr, old_end);
 
-	/*
-	 * This is not the clever way to do this, but we're taking the
-	 * easy way out on the assumption that most remappings will be
-	 * only a few pages.. This also makes error recovery easier.
-	 */
-	for (offset = 0; offset < len; offset += PAGE_SIZE) {
-		if (move_one_page(vma, old_addr + offset,
-				new_vma, new_addr + offset) < 0)
-			break;
+	for (; old_addr < old_end; old_addr += extent, new_addr += extent) {
 		cond_resched();
+		next = (old_addr + PMD_SIZE) & PMD_MASK;
+		if (next - 1 > old_end)
+			next = old_end;
+		extent = next - old_addr;
+		old_pmd = get_old_pmd(vma->vm_mm, old_addr);
+		if (!old_pmd)
+			continue;
+		new_pmd = alloc_new_pmd(vma->vm_mm, new_addr);
+		if (!new_pmd)
+			break;
+		next = (new_addr + PMD_SIZE) & PMD_MASK;
+		if (extent > next - new_addr)
+			extent = next - new_addr;
+		if (extent > LATENCY_LIMIT)
+			extent = LATENCY_LIMIT;
+		move_ptes(vma, old_pmd, old_addr, old_addr + extent,
+				new_vma, new_pmd, new_addr);
 	}
-	return offset;
+
+	return len + old_addr - old_end;	/* how much done */
 }
 
 static unsigned long move_vma(struct vm_area_struct *vma,
@@ -191,6 +162,7 @@
 	unsigned long new_pgoff;
 	unsigned long moved_len;
 	unsigned long excess = 0;
+	unsigned long hiwater_vm;
 	int split = 0;
 
 	/*
@@ -229,17 +201,24 @@
 	}
 
 	/*
-	 * if we failed to move page tables we still do total_vm increment
-	 * since do_munmap() will decrement it by old_len == new_len
+	 * If we failed to move page tables we still do total_vm increment
+	 * since do_munmap() will decrement it by old_len == new_len.
+	 *
+	 * Since total_vm is about to be raised artificially high for a
+	 * moment, we need to restore high watermark afterwards: if stats
+	 * are taken meanwhile, total_vm and hiwater_vm appear too high.
+	 * If this were a serious issue, we'd add a flag to do_munmap().
 	 */
+	hiwater_vm = mm->hiwater_vm;
 	mm->total_vm += new_len >> PAGE_SHIFT;
-	__vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
+	vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
 
 	if (do_munmap(mm, old_addr, old_len) < 0) {
 		/* OOM: unable to split vma, just get accounts right */
 		vm_unacct_memory(excess >> PAGE_SHIFT);
 		excess = 0;
 	}
+	mm->hiwater_vm = hiwater_vm;
 
 	/* Restore VM_ACCOUNT if one or two pieces of vma left */
 	if (excess) {
@@ -269,6 +248,7 @@
 	unsigned long old_len, unsigned long new_len,
 	unsigned long flags, unsigned long new_addr)
 {
+	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long ret = -EINVAL;
 	unsigned long charged = 0;
@@ -309,7 +289,7 @@
 		if ((addr <= new_addr) && (addr+old_len) > new_addr)
 			goto out;
 
-		ret = do_munmap(current->mm, new_addr, new_len);
+		ret = do_munmap(mm, new_addr, new_len);
 		if (ret)
 			goto out;
 	}
@@ -320,7 +300,7 @@
 	 * do_munmap does all the needed commit accounting
 	 */
 	if (old_len >= new_len) {
-		ret = do_munmap(current->mm, addr+new_len, old_len - new_len);
+		ret = do_munmap(mm, addr+new_len, old_len - new_len);
 		if (ret && old_len != new_len)
 			goto out;
 		ret = addr;
@@ -333,7 +313,7 @@
 	 * Ok, we need to grow..  or relocate.
 	 */
 	ret = -EFAULT;
-	vma = find_vma(current->mm, addr);
+	vma = find_vma(mm, addr);
 	if (!vma || vma->vm_start > addr)
 		goto out;
 	if (is_vm_hugetlb_page(vma)) {
@@ -349,14 +329,14 @@
 	}
 	if (vma->vm_flags & VM_LOCKED) {
 		unsigned long locked, lock_limit;
-		locked = current->mm->locked_vm << PAGE_SHIFT;
+		locked = mm->locked_vm << PAGE_SHIFT;
 		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += new_len - old_len;
 		ret = -EAGAIN;
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			goto out;
 	}
-	if (!may_expand_vm(current->mm, (new_len - old_len) >> PAGE_SHIFT)) {
+	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) {
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -383,11 +363,10 @@
 			vma_adjust(vma, vma->vm_start,
 				addr + new_len, vma->vm_pgoff, NULL);
 
-			current->mm->total_vm += pages;
-			__vm_stat_account(vma->vm_mm, vma->vm_flags,
-							vma->vm_file, pages);
+			mm->total_vm += pages;
+			vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages);
 			if (vma->vm_flags & VM_LOCKED) {
-				current->mm->locked_vm += pages;
+				mm->locked_vm += pages;
 				make_pages_present(addr + old_len,
 						   addr + new_len);
 			}
diff --git a/mm/msync.c b/mm/msync.c
index d0f5a1b..0e040e9 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -17,40 +17,48 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
-/*
- * Called with mm->page_table_lock held to protect against other
- * threads/the swapper from ripping pte's out from under us.
- */
-
-static void sync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+static void msync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 				unsigned long addr, unsigned long end)
 {
 	pte_t *pte;
+	spinlock_t *ptl;
+	int progress = 0;
 
-	pte = pte_offset_map(pmd, addr);
+again:
+	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	do {
 		unsigned long pfn;
 		struct page *page;
 
+		if (progress >= 64) {
+			progress = 0;
+			if (need_resched() || need_lockbreak(ptl))
+				break;
+		}
+		progress++;
 		if (!pte_present(*pte))
 			continue;
 		if (!pte_maybe_dirty(*pte))
 			continue;
 		pfn = pte_pfn(*pte);
-		if (!pfn_valid(pfn))
+		if (unlikely(!pfn_valid(pfn))) {
+			print_bad_pte(vma, *pte, addr);
 			continue;
+		}
 		page = pfn_to_page(pfn);
-		if (PageReserved(page))
-			continue;
 
 		if (ptep_clear_flush_dirty(vma, addr, pte) ||
 		    page_test_and_clear_dirty(page))
 			set_page_dirty(page);
+		progress += 3;
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
+	pte_unmap_unlock(pte - 1, ptl);
+	cond_resched();
+	if (addr != end)
+		goto again;
 }
 
-static inline void sync_pmd_range(struct vm_area_struct *vma, pud_t *pud,
+static inline void msync_pmd_range(struct vm_area_struct *vma, pud_t *pud,
 				unsigned long addr, unsigned long end)
 {
 	pmd_t *pmd;
@@ -61,11 +69,11 @@
 		next = pmd_addr_end(addr, end);
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		sync_pte_range(vma, pmd, addr, next);
+		msync_pte_range(vma, pmd, addr, next);
 	} while (pmd++, addr = next, addr != end);
 }
 
-static inline void sync_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
+static inline void msync_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
 				unsigned long addr, unsigned long end)
 {
 	pud_t *pud;
@@ -76,59 +84,35 @@
 		next = pud_addr_end(addr, end);
 		if (pud_none_or_clear_bad(pud))
 			continue;
-		sync_pmd_range(vma, pud, addr, next);
+		msync_pmd_range(vma, pud, addr, next);
 	} while (pud++, addr = next, addr != end);
 }
 
-static void sync_page_range(struct vm_area_struct *vma,
+static void msync_page_range(struct vm_area_struct *vma,
 				unsigned long addr, unsigned long end)
 {
-	struct mm_struct *mm = vma->vm_mm;
 	pgd_t *pgd;
 	unsigned long next;
 
 	/* For hugepages we can't go walking the page table normally,
 	 * but that's ok, hugetlbfs is memory based, so we don't need
-	 * to do anything more on an msync() */
-	if (is_vm_hugetlb_page(vma))
+	 * to do anything more on an msync().
+	 * Can't do anything with VM_RESERVED regions either.
+	 */
+	if (vma->vm_flags & (VM_HUGETLB|VM_RESERVED))
 		return;
 
 	BUG_ON(addr >= end);
-	pgd = pgd_offset(mm, addr);
+	pgd = pgd_offset(vma->vm_mm, addr);
 	flush_cache_range(vma, addr, end);
-	spin_lock(&mm->page_table_lock);
 	do {
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
-		sync_pud_range(vma, pgd, addr, next);
+		msync_pud_range(vma, pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
-	spin_unlock(&mm->page_table_lock);
 }
 
-#ifdef CONFIG_PREEMPT
-static inline void filemap_sync(struct vm_area_struct *vma,
-				unsigned long addr, unsigned long end)
-{
-	const size_t chunk = 64 * 1024;	/* bytes */
-	unsigned long next;
-
-	do {
-		next = addr + chunk;
-		if (next > end || next < addr)
-			next = end;
-		sync_page_range(vma, addr, next);
-		cond_resched();
-	} while (addr = next, addr != end);
-}
-#else
-static inline void filemap_sync(struct vm_area_struct *vma,
-				unsigned long addr, unsigned long end)
-{
-	sync_page_range(vma, addr, end);
-}
-#endif
-
 /*
  * MS_SYNC syncs the entire file - including mappings.
  *
@@ -150,7 +134,7 @@
 		return -EBUSY;
 
 	if (file && (vma->vm_flags & VM_SHARED)) {
-		filemap_sync(vma, addr, end);
+		msync_page_range(vma, addr, end);
 
 		if (flags & MS_SYNC) {
 			struct address_space *mapping = file->f_mapping;
diff --git a/mm/nommu.c b/mm/nommu.c
index 0ef241a..d1e076a 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -931,6 +931,8 @@
 	realalloc -= kobjsize(vml);
 	askedalloc -= sizeof(*vml);
 	kfree(vml);
+
+	update_hiwater_vm(mm);
 	mm->total_vm -= len >> PAGE_SHIFT;
 
 #ifdef DEBUG
@@ -1047,7 +1049,8 @@
 
 EXPORT_SYMBOL(find_vma);
 
-struct page * follow_page(struct mm_struct *mm, unsigned long addr, int write)
+struct page *follow_page(struct mm_struct *mm, unsigned long address,
+			unsigned int foll_flags)
 {
 	return NULL;
 }
@@ -1078,19 +1081,6 @@
 {
 }
 
-void update_mem_hiwater(struct task_struct *tsk)
-{
-	unsigned long rss;
-
-	if (likely(tsk->mm)) {
-		rss = get_mm_counter(tsk->mm, rss);
-		if (tsk->mm->hiwater_rss < rss)
-			tsk->mm->hiwater_rss = rss;
-		if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
-			tsk->mm->hiwater_vm = tsk->mm->total_vm;
-	}
-}
-
 void unmap_mapping_range(struct address_space *mapping,
 			 loff_t const holebegin, loff_t const holelen,
 			 int even_cows)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e1d3d77..2dbdd98 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -33,6 +33,7 @@
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
+#include <linux/memory_hotplug.h>
 #include <linux/nodemask.h>
 #include <linux/vmalloc.h>
 
@@ -78,21 +79,44 @@
 unsigned long __initdata nr_kernel_pages;
 unsigned long __initdata nr_all_pages;
 
+static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
+{
+	int ret = 0;
+	unsigned seq;
+	unsigned long pfn = page_to_pfn(page);
+
+	do {
+		seq = zone_span_seqbegin(zone);
+		if (pfn >= zone->zone_start_pfn + zone->spanned_pages)
+			ret = 1;
+		else if (pfn < zone->zone_start_pfn)
+			ret = 1;
+	} while (zone_span_seqretry(zone, seq));
+
+	return ret;
+}
+
+static int page_is_consistent(struct zone *zone, struct page *page)
+{
+#ifdef CONFIG_HOLES_IN_ZONE
+	if (!pfn_valid(page_to_pfn(page)))
+		return 0;
+#endif
+	if (zone != page_zone(page))
+		return 0;
+
+	return 1;
+}
 /*
  * Temporary debugging check for pages not lying within a given zone.
  */
 static int bad_range(struct zone *zone, struct page *page)
 {
-	if (page_to_pfn(page) >= zone->zone_start_pfn + zone->spanned_pages)
+	if (page_outside_zone_boundaries(zone, page))
 		return 1;
-	if (page_to_pfn(page) < zone->zone_start_pfn)
+	if (!page_is_consistent(zone, page))
 		return 1;
-#ifdef CONFIG_HOLES_IN_ZONE
-	if (!pfn_valid(page_to_pfn(page)))
-		return 1;
-#endif
-	if (zone != page_zone(page))
-		return 1;
+
 	return 0;
 }
 
@@ -114,7 +138,8 @@
 			1 << PG_reclaim |
 			1 << PG_slab    |
 			1 << PG_swapcache |
-			1 << PG_writeback);
+			1 << PG_writeback |
+			1 << PG_reserved );
 	set_page_count(page, 0);
 	reset_page_mapcount(page);
 	page->mapping = NULL;
@@ -153,7 +178,7 @@
 		struct page *p = page + i;
 
 		SetPageCompound(p);
-		p->private = (unsigned long)page;
+		set_page_private(p, (unsigned long)page);
 	}
 }
 
@@ -173,7 +198,7 @@
 
 		if (!PageCompound(p))
 			bad_page(__FUNCTION__, page);
-		if (p->private != (unsigned long)page)
+		if (page_private(p) != (unsigned long)page)
 			bad_page(__FUNCTION__, page);
 		ClearPageCompound(p);
 	}
@@ -186,18 +211,18 @@
  * So, we don't need atomic page->flags operations here.
  */
 static inline unsigned long page_order(struct page *page) {
-	return page->private;
+	return page_private(page);
 }
 
 static inline void set_page_order(struct page *page, int order) {
-	page->private = order;
+	set_page_private(page, order);
 	__SetPagePrivate(page);
 }
 
 static inline void rmv_page_order(struct page *page)
 {
 	__ClearPagePrivate(page);
-	page->private = 0;
+	set_page_private(page, 0);
 }
 
 /*
@@ -237,14 +262,13 @@
  * (a) the buddy is free &&
  * (b) the buddy is on the buddy system &&
  * (c) a page and its buddy have the same order.
- * for recording page's order, we use page->private and PG_private.
+ * for recording page's order, we use page_private(page) and PG_private.
  *
  */
 static inline int page_is_buddy(struct page *page, int order)
 {
        if (PagePrivate(page)           &&
            (page_order(page) == order) &&
-           !PageReserved(page)         &&
             page_count(page) == 0)
                return 1;
        return 0;
@@ -264,7 +288,7 @@
  * parts of the VM system.
  * At each level, we keep a list of pages, which are heads of continuous
  * free pages of length of (1 << order) and marked with PG_Private.Page's
- * order is recorded in page->private field.
+ * order is recorded in page_private(page) field.
  * So when we are allocating or freeing one, we can derive the state of the
  * other.  That is, if we allocate a small block, and both were   
  * free, the remainder of the region must be split into blocks.   
@@ -327,7 +351,8 @@
 			1 << PG_reclaim	|
 			1 << PG_slab	|
 			1 << PG_swapcache |
-			1 << PG_writeback )))
+			1 << PG_writeback |
+			1 << PG_reserved )))
 		bad_page(function, page);
 	if (PageDirty(page))
 		__ClearPageDirty(page);
@@ -455,13 +480,14 @@
 			1 << PG_reclaim	|
 			1 << PG_slab    |
 			1 << PG_swapcache |
-			1 << PG_writeback )))
+			1 << PG_writeback |
+			1 << PG_reserved )))
 		bad_page(__FUNCTION__, page);
 
 	page->flags &= ~(1 << PG_uptodate | 1 << PG_error |
 			1 << PG_referenced | 1 << PG_arch_1 |
 			1 << PG_checked | 1 << PG_mappedtodisk);
-	page->private = 0;
+	set_page_private(page, 0);
 	set_page_refs(page, order);
 	kernel_map_pages(page, 1 << order, 1);
 }
@@ -734,7 +760,7 @@
  * of the allocation.
  */
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
-		      int classzone_idx, int can_try_harder, int gfp_high)
+		      int classzone_idx, int can_try_harder, gfp_t gfp_high)
 {
 	/* free_pages my go negative - that's OK */
 	long min = mark, free_pages = z->free_pages - (1 << order) + 1;
@@ -777,7 +803,7 @@
 __alloc_pages(gfp_t gfp_mask, unsigned int order,
 		struct zonelist *zonelist)
 {
-	const int wait = gfp_mask & __GFP_WAIT;
+	const gfp_t wait = gfp_mask & __GFP_WAIT;
 	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;
@@ -996,7 +1022,7 @@
 	 * get_zeroed_page() returns a 32-bit address, which cannot represent
 	 * a highmem page
 	 */
-	BUG_ON(gfp_mask & __GFP_HIGHMEM);
+	BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);
 
 	page = alloc_pages(gfp_mask | __GFP_ZERO, 0);
 	if (page)
@@ -1016,7 +1042,7 @@
 
 fastcall void __free_pages(struct page *page, unsigned int order)
 {
-	if (!PageReserved(page) && put_page_testzero(page)) {
+	if (put_page_testzero(page)) {
 		if (order == 0)
 			free_hot_page(page);
 		else
@@ -1089,7 +1115,7 @@
  */
 unsigned int nr_free_buffer_pages(void)
 {
-	return nr_free_zone_pages(GFP_USER & GFP_ZONEMASK);
+	return nr_free_zone_pages(gfp_zone(GFP_USER));
 }
 
 /*
@@ -1097,7 +1123,7 @@
  */
 unsigned int nr_free_pagecache_pages(void)
 {
-	return nr_free_zone_pages(GFP_HIGHUSER & GFP_ZONEMASK);
+	return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
 }
 
 #ifdef CONFIG_HIGHMEM
@@ -1305,12 +1331,9 @@
 		} else
 			printk("\n");
 
-		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+		for_each_cpu(cpu) {
 			struct per_cpu_pageset *pageset;
 
-			if (!cpu_possible(cpu))
-				continue;
-
 			pageset = zone_pcp(zone, cpu);
 
 			for (temperature = 0; temperature < 2; temperature++)
@@ -1428,6 +1451,16 @@
 	return j;
 }
 
+static inline int highest_zone(int zone_bits)
+{
+	int res = ZONE_NORMAL;
+	if (zone_bits & (__force int)__GFP_HIGHMEM)
+		res = ZONE_HIGHMEM;
+	if (zone_bits & (__force int)__GFP_DMA)
+		res = ZONE_DMA;
+	return res;
+}
+
 #ifdef CONFIG_NUMA
 #define MAX_NODE_LOAD (num_online_nodes())
 static int __initdata node_load[MAX_NUMNODES];
@@ -1524,11 +1557,7 @@
 			zonelist = pgdat->node_zonelists + i;
 			for (j = 0; zonelist->zones[j] != NULL; j++);
 
-			k = ZONE_NORMAL;
-			if (i & __GFP_HIGHMEM)
-				k = ZONE_HIGHMEM;
-			if (i & __GFP_DMA)
-				k = ZONE_DMA;
+			k = highest_zone(i);
 
 	 		j = build_zonelists_node(NODE_DATA(node), zonelist, j, k);
 			zonelist->zones[j] = NULL;
@@ -1549,12 +1578,7 @@
 		zonelist = pgdat->node_zonelists + i;
 
 		j = 0;
-		k = ZONE_NORMAL;
-		if (i & __GFP_HIGHMEM)
-			k = ZONE_HIGHMEM;
-		if (i & __GFP_DMA)
-			k = ZONE_DMA;
-
+		k = highest_zone(i);
  		j = build_zonelists_node(pgdat, zonelist, j, k);
  		/*
  		 * Now we build the zonelist so that it contains the zones
@@ -1659,7 +1683,7 @@
  * up by free_all_bootmem() once the early boot process is
  * done. Non-atomic initialization, single-pass.
  */
-void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 		unsigned long start_pfn)
 {
 	struct page *page;
@@ -1673,7 +1697,7 @@
 			continue;
 		page = pfn_to_page(pfn);
 		set_page_links(page, zone, nid, pfn);
-		set_page_count(page, 0);
+		set_page_count(page, 1);
 		reset_page_mapcount(page);
 		SetPageReserved(page);
 		INIT_LIST_HEAD(&page->lru);
@@ -1720,29 +1744,29 @@
 
 	/*
 	 * The per-cpu-pages pools are set to around 1000th of the
-	 * size of the zone.  But no more than 1/4 of a meg - there's
-	 * no point in going beyond the size of L2 cache.
+	 * size of the zone.  But no more than 1/2 of a meg.
 	 *
 	 * OK, so we don't know how big the cache is.  So guess.
 	 */
 	batch = zone->present_pages / 1024;
-	if (batch * PAGE_SIZE > 256 * 1024)
-		batch = (256 * 1024) / PAGE_SIZE;
+	if (batch * PAGE_SIZE > 512 * 1024)
+		batch = (512 * 1024) / PAGE_SIZE;
 	batch /= 4;		/* We effectively *= 4 below */
 	if (batch < 1)
 		batch = 1;
 
 	/*
-	 * Clamp the batch to a 2^n - 1 value. Having a power
-	 * of 2 value was found to be more likely to have
-	 * suboptimal cache aliasing properties in some cases.
+	 * We will be trying to allcoate bigger chunks of contiguous
+	 * memory of the order of fls(batch).  This should result in
+	 * better cache coloring.
 	 *
-	 * For example if 2 tasks are alternately allocating
-	 * batches of pages, one task can end up with a lot
-	 * of pages of one half of the possible page colors
-	 * and the other with pages of the other colors.
+	 * A sanity check also to ensure that batch is still in limits.
 	 */
-	batch = (1 << fls(batch + batch/2)) - 1;
+	batch = (1 << fls(batch + batch/2));
+
+	if (fls(batch) >= (PAGE_SHIFT + MAX_ORDER - 2))
+		batch = PAGE_SHIFT + ((MAX_ORDER - 1 - PAGE_SHIFT)/2);
+
 	return batch;
 }
 
@@ -1754,7 +1778,7 @@
 
 	pcp = &p->pcp[0];		/* hot */
 	pcp->count = 0;
-	pcp->low = 2 * batch;
+	pcp->low = 0;
 	pcp->high = 6 * batch;
 	pcp->batch = max(1UL, 1 * batch);
 	INIT_LIST_HEAD(&pcp->list);
@@ -1763,7 +1787,7 @@
 	pcp->count = 0;
 	pcp->low = 0;
 	pcp->high = 2 * batch;
-	pcp->batch = max(1UL, 1 * batch);
+	pcp->batch = max(1UL, batch/2);
 	INIT_LIST_HEAD(&pcp->list);
 }
 
@@ -1872,6 +1896,60 @@
 
 #endif
 
+static __devinit
+void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
+{
+	int i;
+	struct pglist_data *pgdat = zone->zone_pgdat;
+
+	/*
+	 * The per-page waitqueue mechanism uses hashed waitqueues
+	 * per zone.
+	 */
+	zone->wait_table_size = wait_table_size(zone_size_pages);
+	zone->wait_table_bits =	wait_table_bits(zone->wait_table_size);
+	zone->wait_table = (wait_queue_head_t *)
+		alloc_bootmem_node(pgdat, zone->wait_table_size
+					* sizeof(wait_queue_head_t));
+
+	for(i = 0; i < zone->wait_table_size; ++i)
+		init_waitqueue_head(zone->wait_table + i);
+}
+
+static __devinit void zone_pcp_init(struct zone *zone)
+{
+	int cpu;
+	unsigned long batch = zone_batchsize(zone);
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+#ifdef CONFIG_NUMA
+		/* Early boot. Slab allocator not functional yet */
+		zone->pageset[cpu] = &boot_pageset[cpu];
+		setup_pageset(&boot_pageset[cpu],0);
+#else
+		setup_pageset(zone_pcp(zone,cpu), batch);
+#endif
+	}
+	printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%lu\n",
+		zone->name, zone->present_pages, batch);
+}
+
+static __devinit void init_currently_empty_zone(struct zone *zone,
+		unsigned long zone_start_pfn, unsigned long size)
+{
+	struct pglist_data *pgdat = zone->zone_pgdat;
+
+	zone_wait_table_init(zone, size);
+	pgdat->nr_zones = zone_idx(zone) + 1;
+
+	zone->zone_mem_map = pfn_to_page(zone_start_pfn);
+	zone->zone_start_pfn = zone_start_pfn;
+
+	memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn);
+
+	zone_init_free_lists(pgdat, zone, zone->spanned_pages);
+}
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -1881,10 +1959,11 @@
 static void __init free_area_init_core(struct pglist_data *pgdat,
 		unsigned long *zones_size, unsigned long *zholes_size)
 {
-	unsigned long i, j;
-	int cpu, nid = pgdat->node_id;
+	unsigned long j;
+	int nid = pgdat->node_id;
 	unsigned long zone_start_pfn = pgdat->node_start_pfn;
 
+	pgdat_resize_init(pgdat);
 	pgdat->nr_zones = 0;
 	init_waitqueue_head(&pgdat->kswapd_wait);
 	pgdat->kswapd_max_order = 0;
@@ -1892,7 +1971,6 @@
 	for (j = 0; j < MAX_NR_ZONES; j++) {
 		struct zone *zone = pgdat->node_zones + j;
 		unsigned long size, realsize;
-		unsigned long batch;
 
 		realsize = size = zones_size[j];
 		if (zholes_size)
@@ -1907,24 +1985,13 @@
 		zone->name = zone_names[j];
 		spin_lock_init(&zone->lock);
 		spin_lock_init(&zone->lru_lock);
+		zone_seqlock_init(zone);
 		zone->zone_pgdat = pgdat;
 		zone->free_pages = 0;
 
 		zone->temp_priority = zone->prev_priority = DEF_PRIORITY;
 
-		batch = zone_batchsize(zone);
-
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-#ifdef CONFIG_NUMA
-			/* Early boot. Slab allocator not functional yet */
-			zone->pageset[cpu] = &boot_pageset[cpu];
-			setup_pageset(&boot_pageset[cpu],0);
-#else
-			setup_pageset(zone_pcp(zone,cpu), batch);
-#endif
-		}
-		printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%lu\n",
-				zone_names[j], realsize, batch);
+		zone_pcp_init(zone);
 		INIT_LIST_HEAD(&zone->active_list);
 		INIT_LIST_HEAD(&zone->inactive_list);
 		zone->nr_scan_active = 0;
@@ -1935,32 +2002,9 @@
 		if (!size)
 			continue;
 
-		/*
-		 * The per-page waitqueue mechanism uses hashed waitqueues
-		 * per zone.
-		 */
-		zone->wait_table_size = wait_table_size(size);
-		zone->wait_table_bits =
-			wait_table_bits(zone->wait_table_size);
-		zone->wait_table = (wait_queue_head_t *)
-			alloc_bootmem_node(pgdat, zone->wait_table_size
-						* sizeof(wait_queue_head_t));
-
-		for(i = 0; i < zone->wait_table_size; ++i)
-			init_waitqueue_head(zone->wait_table + i);
-
-		pgdat->nr_zones = j+1;
-
-		zone->zone_mem_map = pfn_to_page(zone_start_pfn);
-		zone->zone_start_pfn = zone_start_pfn;
-
-		memmap_init(size, nid, j, zone_start_pfn);
-
 		zonetable_add(zone, nid, j, zone_start_pfn, size);
-
+		init_currently_empty_zone(zone, zone_start_pfn, size);
 		zone_start_pfn += size;
-
-		zone_init_free_lists(pgdat, zone, zone->spanned_pages);
 	}
 }
 
@@ -2360,7 +2404,7 @@
  *	that the pages_{min,low,high} values for each zone are set correctly 
  *	with respect to min_free_kbytes.
  */
-static void setup_per_zone_pages_min(void)
+void setup_per_zone_pages_min(void)
 {
 	unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
 	unsigned long lowmem_pages = 0;
diff --git a/mm/page_io.c b/mm/page_io.c
index 330e00d..bb2b0d5 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -91,7 +91,8 @@
 		unlock_page(page);
 		goto out;
 	}
-	bio = get_swap_bio(GFP_NOIO, page->private, page, end_swap_bio_write);
+	bio = get_swap_bio(GFP_NOIO, page_private(page), page,
+				end_swap_bio_write);
 	if (bio == NULL) {
 		set_page_dirty(page);
 		unlock_page(page);
@@ -115,7 +116,8 @@
 
 	BUG_ON(!PageLocked(page));
 	ClearPageUptodate(page);
-	bio = get_swap_bio(GFP_KERNEL, page->private, page, end_swap_bio_read);
+	bio = get_swap_bio(GFP_KERNEL, page_private(page), page,
+				end_swap_bio_read);
 	if (bio == NULL) {
 		unlock_page(page);
 		ret = -ENOMEM;
diff --git a/mm/pdflush.c b/mm/pdflush.c
index d678195..52822c9 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>		// Needed by writeback.h
 #include <linux/writeback.h>	// Prototypes pdflush_operation()
 #include <linux/kthread.h>
+#include <linux/cpuset.h>
 
 
 /*
@@ -170,12 +171,24 @@
 static int pdflush(void *dummy)
 {
 	struct pdflush_work my_work;
+	cpumask_t cpus_allowed;
 
 	/*
 	 * pdflush can spend a lot of time doing encryption via dm-crypt.  We
 	 * don't want to do that at keventd's priority.
 	 */
 	set_user_nice(current, 0);
+
+	/*
+	 * Some configs put our parent kthread in a limited cpuset,
+	 * which kthread() overrides, forcing cpus_allowed == CPU_MASK_ALL.
+	 * Our needs are more modest - cut back to our cpusets cpus_allowed.
+	 * This is needed as pdflush's are dynamically created and destroyed.
+	 * The boottime pdflush's are easily placed w/o these 2 lines.
+	 */
+	cpus_allowed = cpuset_cpus_allowed(current);
+	set_cpus_allowed(current, cpus_allowed);
+
 	return __pdflush(&my_work);
 }
 
diff --git a/mm/rmap.c b/mm/rmap.c
index 450f524..914d04b 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -32,7 +32,7 @@
  *   page->flags PG_locked (lock_page)
  *     mapping->i_mmap_lock
  *       anon_vma->lock
- *         mm->page_table_lock
+ *         mm->page_table_lock or pte_lock
  *           zone->lru_lock (in mark_page_accessed)
  *           swap_lock (in swap_duplicate, swap_info_get)
  *             mmlist_lock (in mmput, drain_mmlist and others)
@@ -244,37 +244,44 @@
 /*
  * Check that @page is mapped at @address into @mm.
  *
- * On success returns with mapped pte and locked mm->page_table_lock.
+ * On success returns with pte mapped and locked.
  */
 pte_t *page_check_address(struct page *page, struct mm_struct *mm,
-			  unsigned long address)
+			  unsigned long address, spinlock_t **ptlp)
 {
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
+	spinlock_t *ptl;
 
-	/*
-	 * We need the page_table_lock to protect us from page faults,
-	 * munmap, fork, etc...
-	 */
-	spin_lock(&mm->page_table_lock);
 	pgd = pgd_offset(mm, address);
-	if (likely(pgd_present(*pgd))) {
-		pud = pud_offset(pgd, address);
-		if (likely(pud_present(*pud))) {
-			pmd = pmd_offset(pud, address);
-			if (likely(pmd_present(*pmd))) {
-				pte = pte_offset_map(pmd, address);
-				if (likely(pte_present(*pte) &&
-					   page_to_pfn(page) == pte_pfn(*pte)))
-					return pte;
-				pte_unmap(pte);
-			}
-		}
+	if (!pgd_present(*pgd))
+		return NULL;
+
+	pud = pud_offset(pgd, address);
+	if (!pud_present(*pud))
+		return NULL;
+
+	pmd = pmd_offset(pud, address);
+	if (!pmd_present(*pmd))
+		return NULL;
+
+	pte = pte_offset_map(pmd, address);
+	/* Make a quick check before getting the lock */
+	if (!pte_present(*pte)) {
+		pte_unmap(pte);
+		return NULL;
 	}
-	spin_unlock(&mm->page_table_lock);
-	return ERR_PTR(-ENOENT);
+
+	ptl = pte_lockptr(mm, pmd);
+	spin_lock(ptl);
+	if (pte_present(*pte) && page_to_pfn(page) == pte_pfn(*pte)) {
+		*ptlp = ptl;
+		return pte;
+	}
+	pte_unmap_unlock(pte, ptl);
+	return NULL;
 }
 
 /*
@@ -287,24 +294,28 @@
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
 	pte_t *pte;
+	spinlock_t *ptl;
 	int referenced = 0;
 
 	address = vma_address(page, vma);
 	if (address == -EFAULT)
 		goto out;
 
-	pte = page_check_address(page, mm, address);
-	if (!IS_ERR(pte)) {
-		if (ptep_clear_flush_young(vma, address, pte))
-			referenced++;
+	pte = page_check_address(page, mm, address, &ptl);
+	if (!pte)
+		goto out;
 
-		if (mm != current->mm && !ignore_token && has_swap_token(mm))
-			referenced++;
+	if (ptep_clear_flush_young(vma, address, pte))
+		referenced++;
 
-		(*mapcount)--;
-		pte_unmap(pte);
-		spin_unlock(&mm->page_table_lock);
-	}
+	/* Pretend the page is referenced if the task has the
+	   swap token and is in the middle of a page fault. */
+	if (mm != current->mm && !ignore_token && has_swap_token(mm) &&
+			rwsem_is_locked(&mm->mmap_sem))
+		referenced++;
+
+	(*mapcount)--;
+	pte_unmap_unlock(pte, ptl);
 out:
 	return referenced;
 }
@@ -434,15 +445,11 @@
  * @vma:	the vm area in which the mapping is added
  * @address:	the user virtual address mapped
  *
- * The caller needs to hold the mm->page_table_lock.
+ * The caller needs to hold the pte lock.
  */
 void page_add_anon_rmap(struct page *page,
 	struct vm_area_struct *vma, unsigned long address)
 {
-	BUG_ON(PageReserved(page));
-
-	inc_mm_counter(vma->vm_mm, anon_rss);
-
 	if (atomic_inc_and_test(&page->_mapcount)) {
 		struct anon_vma *anon_vma = vma->anon_vma;
 
@@ -461,13 +468,12 @@
  * page_add_file_rmap - add pte mapping to a file page
  * @page: the page to add the mapping to
  *
- * The caller needs to hold the mm->page_table_lock.
+ * The caller needs to hold the pte lock.
  */
 void page_add_file_rmap(struct page *page)
 {
 	BUG_ON(PageAnon(page));
-	if (!pfn_valid(page_to_pfn(page)) || PageReserved(page))
-		return;
+	BUG_ON(!pfn_valid(page_to_pfn(page)));
 
 	if (atomic_inc_and_test(&page->_mapcount))
 		inc_page_state(nr_mapped);
@@ -477,12 +483,10 @@
  * page_remove_rmap - take down pte mapping from a page
  * @page: page to remove mapping from
  *
- * Caller needs to hold the mm->page_table_lock.
+ * The caller needs to hold the pte lock.
  */
 void page_remove_rmap(struct page *page)
 {
-	BUG_ON(PageReserved(page));
-
 	if (atomic_add_negative(-1, &page->_mapcount)) {
 		BUG_ON(page_mapcount(page) < 0);
 		/*
@@ -510,14 +514,15 @@
 	unsigned long address;
 	pte_t *pte;
 	pte_t pteval;
+	spinlock_t *ptl;
 	int ret = SWAP_AGAIN;
 
 	address = vma_address(page, vma);
 	if (address == -EFAULT)
 		goto out;
 
-	pte = page_check_address(page, mm, address);
-	if (IS_ERR(pte))
+	pte = page_check_address(page, mm, address, &ptl);
+	if (!pte)
 		goto out;
 
 	/*
@@ -541,8 +546,11 @@
 	if (pte_dirty(pteval))
 		set_page_dirty(page);
 
+	/* Update high watermark before we lower rss */
+	update_hiwater_rss(mm);
+
 	if (PageAnon(page)) {
-		swp_entry_t entry = { .val = page->private };
+		swp_entry_t entry = { .val = page_private(page) };
 		/*
 		 * Store the swap location in the pte.
 		 * See handle_pte_fault() ...
@@ -551,21 +559,21 @@
 		swap_duplicate(entry);
 		if (list_empty(&mm->mmlist)) {
 			spin_lock(&mmlist_lock);
-			list_add(&mm->mmlist, &init_mm.mmlist);
+			if (list_empty(&mm->mmlist))
+				list_add(&mm->mmlist, &init_mm.mmlist);
 			spin_unlock(&mmlist_lock);
 		}
 		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
 		BUG_ON(pte_file(*pte));
 		dec_mm_counter(mm, anon_rss);
-	}
+	} else
+		dec_mm_counter(mm, file_rss);
 
-	dec_mm_counter(mm, rss);
 	page_remove_rmap(page);
 	page_cache_release(page);
 
 out_unmap:
-	pte_unmap(pte);
-	spin_unlock(&mm->page_table_lock);
+	pte_unmap_unlock(pte, ptl);
 out:
 	return ret;
 }
@@ -599,19 +607,14 @@
 	pgd_t *pgd;
 	pud_t *pud;
 	pmd_t *pmd;
-	pte_t *pte, *original_pte;
+	pte_t *pte;
 	pte_t pteval;
+	spinlock_t *ptl;
 	struct page *page;
 	unsigned long address;
 	unsigned long end;
 	unsigned long pfn;
 
-	/*
-	 * We need the page_table_lock to protect us from page faults,
-	 * munmap, fork, etc...
-	 */
-	spin_lock(&mm->page_table_lock);
-
 	address = (vma->vm_start + cursor) & CLUSTER_MASK;
 	end = address + CLUSTER_SIZE;
 	if (address < vma->vm_start)
@@ -621,30 +624,33 @@
 
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
-		goto out_unlock;
+		return;
 
 	pud = pud_offset(pgd, address);
 	if (!pud_present(*pud))
-		goto out_unlock;
+		return;
 
 	pmd = pmd_offset(pud, address);
 	if (!pmd_present(*pmd))
-		goto out_unlock;
+		return;
 
-	for (original_pte = pte = pte_offset_map(pmd, address);
-			address < end; pte++, address += PAGE_SIZE) {
+	pte = pte_offset_map_lock(mm, pmd, address, &ptl);
 
+	/* Update high watermark before we lower rss */
+	update_hiwater_rss(mm);
+
+	for (; address < end; pte++, address += PAGE_SIZE) {
 		if (!pte_present(*pte))
 			continue;
 
 		pfn = pte_pfn(*pte);
-		if (!pfn_valid(pfn))
+		if (unlikely(!pfn_valid(pfn))) {
+			print_bad_pte(vma, *pte, address);
 			continue;
+		}
 
 		page = pfn_to_page(pfn);
 		BUG_ON(PageAnon(page));
-		if (PageReserved(page))
-			continue;
 
 		if (ptep_clear_flush_young(vma, address, pte))
 			continue;
@@ -663,13 +669,10 @@
 
 		page_remove_rmap(page);
 		page_cache_release(page);
-		dec_mm_counter(mm, rss);
+		dec_mm_counter(mm, file_rss);
 		(*mapcount)--;
 	}
-
-	pte_unmap(original_pte);
-out_unlock:
-	spin_unlock(&mm->page_table_lock);
+	pte_unmap_unlock(pte - 1, ptl);
 }
 
 static int try_to_unmap_anon(struct page *page)
@@ -806,7 +809,6 @@
 {
 	int ret;
 
-	BUG_ON(PageReserved(page));
 	BUG_ON(!PageLocked(page));
 
 	if (PageAnon(page))
diff --git a/mm/shmem.c b/mm/shmem.c
index ea064d8..dc25565 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -71,9 +71,6 @@
 /* Pretend that each entry is of this size in directory's i_size */
 #define BOGO_DIRENT_SIZE 20
 
-/* Keep swapped page count in private field of indirect struct page */
-#define nr_swapped		private
-
 /* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
 enum sgp_type {
 	SGP_QUICK,	/* don't try more than file page cache lookup */
@@ -85,7 +82,7 @@
 static int shmem_getpage(struct inode *inode, unsigned long idx,
 			 struct page **pagep, enum sgp_type sgp, int *type);
 
-static inline struct page *shmem_dir_alloc(unsigned int gfp_mask)
+static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
 {
 	/*
 	 * The above definition of ENTRIES_PER_PAGE, and the use of
@@ -324,8 +321,10 @@
 
 	entry->val = value;
 	info->swapped += incdec;
-	if ((unsigned long)(entry - info->i_direct) >= SHMEM_NR_DIRECT)
-		kmap_atomic_to_page(entry)->nr_swapped += incdec;
+	if ((unsigned long)(entry - info->i_direct) >= SHMEM_NR_DIRECT) {
+		struct page *page = kmap_atomic_to_page(entry);
+		set_page_private(page, page_private(page) + incdec);
+	}
 }
 
 /*
@@ -368,9 +367,8 @@
 
 		spin_unlock(&info->lock);
 		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping) | __GFP_ZERO);
-		if (page) {
-			page->nr_swapped = 0;
-		}
+		if (page)
+			set_page_private(page, 0);
 		spin_lock(&info->lock);
 
 		if (!page) {
@@ -561,7 +559,7 @@
 			diroff = 0;
 		}
 		subdir = dir[diroff];
-		if (subdir && subdir->nr_swapped) {
+		if (subdir && page_private(subdir)) {
 			size = limit - idx;
 			if (size > ENTRIES_PER_PAGE)
 				size = ENTRIES_PER_PAGE;
@@ -572,10 +570,10 @@
 			nr_swaps_freed += freed;
 			if (offset)
 				spin_lock(&info->lock);
-			subdir->nr_swapped -= freed;
+			set_page_private(subdir, page_private(subdir) - freed);
 			if (offset)
 				spin_unlock(&info->lock);
-			BUG_ON(subdir->nr_swapped > offset);
+			BUG_ON(page_private(subdir) > offset);
 		}
 		if (offset)
 			offset = 0;
@@ -743,7 +741,7 @@
 			dir = shmem_dir_map(subdir);
 		}
 		subdir = *dir;
-		if (subdir && subdir->nr_swapped) {
+		if (subdir && page_private(subdir)) {
 			ptr = shmem_swp_map(subdir);
 			size = limit - idx;
 			if (size > ENTRIES_PER_PAGE)
@@ -898,7 +896,7 @@
 }
 
 static struct page *
-shmem_alloc_page(unsigned long gfp, struct shmem_inode_info *info,
+shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
 		 unsigned long idx)
 {
 	struct vm_area_struct pvma;
@@ -1201,7 +1199,7 @@
 				page_cache_release(page);
 				return err;
 			}
-		} else {
+		} else if (vma->vm_flags & VM_NONLINEAR) {
 			/* No page was found just because we can't read it in
 			 * now (being here implies nonblock != 0), but the page
 			 * may exist, so set the PTE to fault it in later. */
@@ -1506,8 +1504,10 @@
 			 */
 			if (!offset)
 				mark_page_accessed(page);
-		} else
+		} else {
 			page = ZERO_PAGE(0);
+			page_cache_get(page);
+		}
 
 		/*
 		 * Ok, we have the page, and it's up-to-date, so
diff --git a/mm/slab.c b/mm/slab.c
index d05c678..22bfb0b2 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -386,7 +386,7 @@
 	unsigned int		gfporder;
 
 	/* force GFP flags, e.g. GFP_DMA */
-	unsigned int		gfpflags;
+	gfp_t			gfpflags;
 
 	size_t			colour;		/* cache colouring range */
 	unsigned int		colour_off;	/* colour offset */
@@ -2117,7 +2117,7 @@
 	slabp->free = 0;
 }
 
-static void kmem_flagcheck(kmem_cache_t *cachep, unsigned int flags)
+static void kmem_flagcheck(kmem_cache_t *cachep, gfp_t flags)
 {
 	if (flags & SLAB_DMA) {
 		if (!(cachep->gfpflags & GFP_DMA))
@@ -2152,7 +2152,7 @@
 	struct slab	*slabp;
 	void		*objp;
 	size_t		 offset;
-	unsigned int	 local_flags;
+	gfp_t	 	 local_flags;
 	unsigned long	 ctor_flags;
 	struct kmem_list3 *l3;
 
@@ -2419,6 +2419,7 @@
 			next = slab_bufctl(slabp)[slabp->free];
 #if DEBUG
 			slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
+			WARN_ON(numa_node_id() != slabp->nodeid);
 #endif
 		       	slabp->free = next;
 		}
@@ -2546,7 +2547,7 @@
 /*
  * A interface to enable slab creation on nodeid
  */
-static void *__cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
+static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
 {
 	struct list_head *entry;
  	struct slab *slabp;
@@ -2633,8 +2634,10 @@
 		check_spinlock_acquired_node(cachep, node);
 		check_slabp(cachep, slabp);
 
-
 #if DEBUG
+		/* Verify that the slab belongs to the intended node */
+		WARN_ON(slabp->nodeid != node);
+
 		if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
 			printk(KERN_ERR "slab: double free detected in cache "
 					"'%s', objp %p\n", cachep->name, objp);
diff --git a/mm/sparse.c b/mm/sparse.c
index 347249a..72079b5 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -5,8 +5,10 @@
 #include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <linux/bootmem.h>
+#include <linux/highmem.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/vmalloc.h>
 #include <asm/dma.h>
 
 /*
@@ -72,6 +74,31 @@
 }
 #endif
 
+/*
+ * Although written for the SPARSEMEM_EXTREME case, this happens
+ * to also work for the flat array case becase
+ * NR_SECTION_ROOTS==NR_MEM_SECTIONS.
+ */
+int __section_nr(struct mem_section* ms)
+{
+	unsigned long root_nr;
+	struct mem_section* root;
+
+	for (root_nr = 0;
+	     root_nr < NR_MEM_SECTIONS;
+	     root_nr += SECTIONS_PER_ROOT) {
+		root = __nr_to_section(root_nr);
+
+		if (!root)
+			continue;
+
+		if ((ms >= root) && (ms < (root + SECTIONS_PER_ROOT)))
+		     break;
+	}
+
+	return (root_nr * SECTIONS_PER_ROOT) + (ms - root);
+}
+
 /* Record a memory area against a node. */
 void memory_present(int nid, unsigned long start, unsigned long end)
 {
@@ -162,6 +189,45 @@
 	return NULL;
 }
 
+static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
+{
+	struct page *page, *ret;
+	unsigned long memmap_size = sizeof(struct page) * nr_pages;
+
+	page = alloc_pages(GFP_KERNEL, get_order(memmap_size));
+	if (page)
+		goto got_map_page;
+
+	ret = vmalloc(memmap_size);
+	if (ret)
+		goto got_map_ptr;
+
+	return NULL;
+got_map_page:
+	ret = (struct page *)pfn_to_kaddr(page_to_pfn(page));
+got_map_ptr:
+	memset(ret, 0, memmap_size);
+
+	return ret;
+}
+
+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))
+		vfree(memmap);
+	else
+		free_pages((unsigned long)memmap,
+			   get_order(sizeof(struct page) * nr_pages));
+}
+
 /*
  * Allocate the accumulated non-linear sections, allocate a mem_map
  * for each and record the physical to section mapping.
@@ -187,14 +253,37 @@
  * set.  If this is <=0, then that means that the passed-in
  * map was not consumed and must be freed.
  */
-int sparse_add_one_section(unsigned long start_pfn, int nr_pages, struct page *map)
+int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
+			   int nr_pages)
 {
-	struct mem_section *ms = __pfn_to_section(start_pfn);
+	unsigned long section_nr = pfn_to_section_nr(start_pfn);
+	struct pglist_data *pgdat = zone->zone_pgdat;
+	struct mem_section *ms;
+	struct page *memmap;
+	unsigned long flags;
+	int ret;
 
-	if (ms->section_mem_map & SECTION_MARKED_PRESENT)
-		return -EEXIST;
+	/*
+	 * no locking for this, because it does its own
+	 * plus, it does a kmalloc
+	 */
+	sparse_index_init(section_nr, pgdat->node_id);
+	memmap = __kmalloc_section_memmap(nr_pages);
 
+	pgdat_resize_lock(pgdat, &flags);
+
+	ms = __pfn_to_section(start_pfn);
+	if (ms->section_mem_map & SECTION_MARKED_PRESENT) {
+		ret = -EEXIST;
+		goto out;
+	}
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
-	return sparse_init_one_section(ms, pfn_to_section_nr(start_pfn), map);
+	ret = sparse_init_one_section(ms, section_nr, memmap);
+
+	if (ret <= 0)
+		__kfree_section_memmap(memmap, nr_pages);
+out:
+	pgdat_resize_unlock(pgdat, &flags);
+	return ret;
 }
diff --git a/mm/swap.c b/mm/swap.c
index 7771d28..96387e2 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -39,7 +39,7 @@
 void put_page(struct page *page)
 {
 	if (unlikely(PageCompound(page))) {
-		page = (struct page *)page->private;
+		page = (struct page *)page_private(page);
 		if (put_page_testzero(page)) {
 			void (*dtor)(struct page *page);
 
@@ -48,7 +48,7 @@
 		}
 		return;
 	}
-	if (!PageReserved(page) && put_page_testzero(page))
+	if (put_page_testzero(page))
 		__page_cache_release(page);
 }
 EXPORT_SYMBOL(put_page);
@@ -215,7 +215,7 @@
 		struct page *page = pages[i];
 		struct zone *pagezone;
 
-		if (PageReserved(page) || !put_page_testzero(page))
+		if (!put_page_testzero(page))
 			continue;
 
 		pagezone = page_zone(page);
@@ -270,7 +270,6 @@
 	struct pagevec pages_to_free;
 
 	pagevec_init(&pages_to_free, pvec->cold);
-	pages_to_free.cold = pvec->cold;
 	for (i = 0; i < pagevec_count(pvec); i++) {
 		struct page *page = pvec->pages[i];
 
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 132164f..dfd9a46 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -83,7 +83,7 @@
 			page_cache_get(page);
 			SetPageLocked(page);
 			SetPageSwapCache(page);
-			page->private = entry.val;
+			set_page_private(page, entry.val);
 			total_swapcache_pages++;
 			pagecache_acct(1);
 		}
@@ -126,8 +126,8 @@
 	BUG_ON(PageWriteback(page));
 	BUG_ON(PagePrivate(page));
 
-	radix_tree_delete(&swapper_space.page_tree, page->private);
-	page->private = 0;
+	radix_tree_delete(&swapper_space.page_tree, page_private(page));
+	set_page_private(page, 0);
 	ClearPageSwapCache(page);
 	total_swapcache_pages--;
 	pagecache_acct(-1);
@@ -197,7 +197,7 @@
 {
 	swp_entry_t entry;
 
-	entry.val = page->private;
+	entry.val = page_private(page);
 
 	write_lock_irq(&swapper_space.tree_lock);
 	__delete_from_swap_cache(page);
@@ -259,8 +259,7 @@
 
 /* 
  * Perform a free_page(), also freeing any swap cache associated with
- * this page if it is the last user of the page. Can not do a lock_page,
- * as we are holding the page_table_lock spinlock.
+ * this page if it is the last user of the page.
  */
 void free_page_and_swap_cache(struct page *page)
 {
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 1dcaeda..8970c0b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -61,7 +61,7 @@
 	swp_entry_t entry;
 
 	down_read(&swap_unplug_sem);
-	entry.val = page->private;
+	entry.val = page_private(page);
 	if (PageSwapCache(page)) {
 		struct block_device *bdev = swap_info[swp_type(entry)].bdev;
 		struct backing_dev_info *bdi;
@@ -69,8 +69,8 @@
 		/*
 		 * If the page is removed from swapcache from under us (with a
 		 * racy try_to_unuse/swapoff) we need an additional reference
-		 * count to avoid reading garbage from page->private above. If
-		 * the WARN_ON triggers during a swapoff it maybe the race
+		 * count to avoid reading garbage from page_private(page) above.
+		 * If the WARN_ON triggers during a swapoff it maybe the race
 		 * condition and it's harmless. However if it triggers without
 		 * swapoff it signals a problem.
 		 */
@@ -294,7 +294,7 @@
 	struct swap_info_struct *p;
 	swp_entry_t entry;
 
-	entry.val = page->private;
+	entry.val = page_private(page);
 	p = swap_info_get(entry);
 	if (p) {
 		/* Subtract the 1 for the swap cache itself */
@@ -339,7 +339,7 @@
 	if (page_count(page) != 2) /* 2: us + cache */
 		return 0;
 
-	entry.val = page->private;
+	entry.val = page_private(page);
 	p = swap_info_get(entry);
 	if (!p)
 		return 0;
@@ -398,17 +398,14 @@
 }
 
 /*
- * Always set the resulting pte to be nowrite (the same as COW pages
- * after one process has exited).  We don't know just how many PTEs will
- * share this swap entry, so be cautious and let do_wp_page work out
- * what to do if a write is requested later.
- *
- * vma->vm_mm->page_table_lock is held.
+ * No need to decide whether this PTE shares the swap entry with others,
+ * 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,
 		unsigned long addr, swp_entry_t entry, struct page *page)
 {
-	inc_mm_counter(vma->vm_mm, rss);
+	inc_mm_counter(vma->vm_mm, anon_rss);
 	get_page(page);
 	set_pte_at(vma->vm_mm, addr, pte,
 		   pte_mkold(mk_pte(page, vma->vm_page_prot)));
@@ -425,23 +422,25 @@
 				unsigned long addr, unsigned long end,
 				swp_entry_t entry, struct page *page)
 {
-	pte_t *pte;
 	pte_t swp_pte = swp_entry_to_pte(entry);
+	pte_t *pte;
+	spinlock_t *ptl;
+	int found = 0;
 
-	pte = pte_offset_map(pmd, addr);
+	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	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);
-			pte_unmap(pte);
-			return 1;
+			unuse_pte(vma, pte++, addr, entry, page);
+			found = 1;
+			break;
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap(pte - 1);
-	return 0;
+	pte_unmap_unlock(pte - 1, ptl);
+	return found;
 }
 
 static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud,
@@ -523,12 +522,10 @@
 		down_read(&mm->mmap_sem);
 		lock_page(page);
 	}
-	spin_lock(&mm->page_table_lock);
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
 		if (vma->anon_vma && unuse_vma(vma, entry, page))
 			break;
 	}
-	spin_unlock(&mm->page_table_lock);
 	up_read(&mm->mmap_sem);
 	/*
 	 * Currently unuse_mm cannot fail, but leave error handling
@@ -1045,7 +1042,7 @@
 	BUG_ON(!PageLocked(page));	/* It pins the swap_info_struct */
 
 	if (PageSwapCache(page)) {
-		swp_entry_t entry = { .val = page->private };
+		swp_entry_t entry = { .val = page_private(page) };
 		struct swap_info_struct *sis;
 
 		sis = get_swap_info_struct(swp_type(entry));
diff --git a/mm/thrash.c b/mm/thrash.c
index 11461f7..eff3c18 100644
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -19,7 +19,7 @@
 struct mm_struct * swap_token_mm = &init_mm;
 
 #define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2)
-#define SWAP_TOKEN_TIMEOUT	0
+#define SWAP_TOKEN_TIMEOUT	(300 * HZ)
 /*
  * Currently disabled; Needs further code to work at HZ * 300.
  */
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
index c13a216..b58abcf 100644
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -31,11 +31,14 @@
 
 static int __init init_tmpfs(void)
 {
-	register_filesystem(&tmpfs_fs_type);
+	BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
+
 #ifdef CONFIG_TMPFS
 	devfs_mk_dir("shm");
 #endif
 	shm_mnt = kern_mount(&tmpfs_fs_type);
+	BUG_ON(IS_ERR(shm_mnt));
+
 	return 0;
 }
 module_init(init_tmpfs)
diff --git a/mm/truncate.c b/mm/truncate.c
index 60c8764..29c18f6 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -13,18 +13,9 @@
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
 #include <linux/buffer_head.h>	/* grr. try_to_release_page,
-				   block_invalidatepage */
+				   do_invalidatepage */
 
 
-static int do_invalidatepage(struct page *page, unsigned long offset)
-{
-	int (*invalidatepage)(struct page *, unsigned long);
-	invalidatepage = page->mapping->a_ops->invalidatepage;
-	if (invalidatepage == NULL)
-		invalidatepage = block_invalidatepage;
-	return (*invalidatepage)(page, offset);
-}
-
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
 	memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 1150229..54a90e8 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -5,6 +5,7 @@
  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  *  SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
  *  Major rework to support vmap/vunmap, Christoph Hellwig, SGI, August 2002
+ *  Numa awareness, Christoph Lameter, SGI, June 2005
  */
 
 #include <linux/mm.h>
@@ -88,7 +89,7 @@
 {
 	pte_t *pte;
 
-	pte = pte_alloc_kernel(&init_mm, pmd, addr);
+	pte = pte_alloc_kernel(pmd, addr);
 	if (!pte)
 		return -ENOMEM;
 	do {
@@ -146,20 +147,18 @@
 
 	BUG_ON(addr >= end);
 	pgd = pgd_offset_k(addr);
-	spin_lock(&init_mm.page_table_lock);
 	do {
 		next = pgd_addr_end(addr, end);
 		err = vmap_pud_range(pgd, addr, next, prot, pages);
 		if (err)
 			break;
 	} while (pgd++, addr = next, addr != end);
-	spin_unlock(&init_mm.page_table_lock);
 	flush_cache_vmap((unsigned long) area->addr, end);
 	return err;
 }
 
-struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
-				unsigned long start, unsigned long end)
+struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags,
+				unsigned long start, unsigned long end, int node)
 {
 	struct vm_struct **p, *tmp, *area;
 	unsigned long align = 1;
@@ -178,7 +177,7 @@
 	addr = ALIGN(start, align);
 	size = PAGE_ALIGN(size);
 
-	area = kmalloc(sizeof(*area), GFP_KERNEL);
+	area = kmalloc_node(sizeof(*area), GFP_KERNEL, node);
 	if (unlikely(!area))
 		return NULL;
 
@@ -231,6 +230,12 @@
 	return NULL;
 }
 
+struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
+				unsigned long start, unsigned long end)
+{
+	return __get_vm_area_node(size, flags, start, end, -1);
+}
+
 /**
  *	get_vm_area  -  reserve a contingous kernel virtual area
  *
@@ -246,6 +251,11 @@
 	return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END);
 }
 
+struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags, int node)
+{
+	return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node);
+}
+
 /* Caller must hold vmlist_lock */
 struct vm_struct *__remove_vm_area(void *addr)
 {
@@ -342,7 +352,6 @@
 	BUG_ON(in_interrupt());
 	__vunmap(addr, 1);
 }
-
 EXPORT_SYMBOL(vfree);
 
 /**
@@ -360,7 +369,6 @@
 	BUG_ON(in_interrupt());
 	__vunmap(addr, 0);
 }
-
 EXPORT_SYMBOL(vunmap);
 
 /**
@@ -392,10 +400,10 @@
 
 	return area->addr;
 }
-
 EXPORT_SYMBOL(vmap);
 
-void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
+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;
@@ -406,9 +414,9 @@
 	area->nr_pages = nr_pages;
 	/* Please note that the recursion is strictly bounded. */
 	if (array_size > PAGE_SIZE)
-		pages = __vmalloc(array_size, gfp_mask, PAGE_KERNEL);
+		pages = __vmalloc_node(array_size, gfp_mask, PAGE_KERNEL, node);
 	else
-		pages = kmalloc(array_size, (gfp_mask & ~__GFP_HIGHMEM));
+		pages = kmalloc_node(array_size, (gfp_mask & ~__GFP_HIGHMEM), node);
 	area->pages = pages;
 	if (!area->pages) {
 		remove_vm_area(area->addr);
@@ -418,7 +426,10 @@
 	memset(area->pages, 0, array_size);
 
 	for (i = 0; i < area->nr_pages; i++) {
-		area->pages[i] = alloc_page(gfp_mask);
+		if (node < 0)
+			area->pages[i] = alloc_page(gfp_mask);
+		else
+			area->pages[i] = alloc_pages_node(node, gfp_mask, 0);
 		if (unlikely(!area->pages[i])) {
 			/* Successfully allocated i pages, free them in __vunmap() */
 			area->nr_pages = i;
@@ -435,18 +446,25 @@
 	return NULL;
 }
 
+void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
+{
+	return __vmalloc_area_node(area, gfp_mask, prot, -1);
+}
+
 /**
- *	__vmalloc  -  allocate virtually contiguous memory
+ *	__vmalloc_node  -  allocate virtually contiguous memory
  *
  *	@size:		allocation size
  *	@gfp_mask:	flags for the page level allocator
  *	@prot:		protection mask for the allocated pages
+ *	@node		node to use for allocation or -1
  *
  *	Allocate enough pages to cover @size from the page level
  *	allocator with @gfp_mask flags.  Map them into contiguous
  *	kernel virtual space, using a pagetable protection of @prot.
  */
-void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+			int node)
 {
 	struct vm_struct *area;
 
@@ -454,13 +472,18 @@
 	if (!size || (size >> PAGE_SHIFT) > num_physpages)
 		return NULL;
 
-	area = get_vm_area(size, VM_ALLOC);
+	area = get_vm_area_node(size, VM_ALLOC, node);
 	if (!area)
 		return NULL;
 
-	return __vmalloc_area(area, gfp_mask, prot);
+	return __vmalloc_area_node(area, gfp_mask, prot, node);
 }
+EXPORT_SYMBOL(__vmalloc_node);
 
+void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return __vmalloc_node(size, gfp_mask, prot, -1);
+}
 EXPORT_SYMBOL(__vmalloc);
 
 /**
@@ -478,9 +501,26 @@
 {
        return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
 }
-
 EXPORT_SYMBOL(vmalloc);
 
+/**
+ *	vmalloc_node  -  allocate memory on a specific node
+ *
+ *	@size:		allocation size
+ *	@node;		numa node
+ *
+ *	Allocate enough pages to cover @size from the page level
+ *	allocator and map them into contiguous kernel virtual space.
+ *
+ *	For tight cotrol over page level allocator and protection flags
+ *	use __vmalloc() instead.
+ */
+void *vmalloc_node(unsigned long size, int node)
+{
+       return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node);
+}
+EXPORT_SYMBOL(vmalloc_node);
+
 #ifndef PAGE_KERNEL_EXEC
 # define PAGE_KERNEL_EXEC PAGE_KERNEL
 #endif
@@ -515,7 +555,6 @@
 {
 	return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL);
 }
-
 EXPORT_SYMBOL(vmalloc_32);
 
 long vread(char *buf, char *addr, unsigned long count)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 64f9570..135bf8c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -70,7 +70,7 @@
 	unsigned int priority;
 
 	/* This context's GFP mask */
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 
 	int may_writepage;
 
@@ -186,7 +186,7 @@
  *
  * Returns the number of slab objects which we shrunk.
  */
-static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
+static int shrink_slab(unsigned long scanned, gfp_t gfp_mask,
 			unsigned long lru_pages)
 {
 	struct shrinker *shrinker;
@@ -417,7 +417,9 @@
 		 * Anonymous process memory has backing store?
 		 * Try to allocate it some swap space here.
 		 */
-		if (PageAnon(page) && !PageSwapCache(page) && sc->may_swap) {
+		if (PageAnon(page) && !PageSwapCache(page)) {
+			if (!sc->may_swap)
+				goto keep_locked;
 			if (!add_to_swap(page))
 				goto activate_locked;
 		}
@@ -519,7 +521,7 @@
 
 #ifdef CONFIG_SWAP
 		if (PageSwapCache(page)) {
-			swp_entry_t swap = { .val = page->private };
+			swp_entry_t swap = { .val = page_private(page) };
 			__delete_from_swap_cache(page);
 			write_unlock_irq(&mapping->tree_lock);
 			swap_free(swap);
@@ -926,7 +928,7 @@
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
  */
-int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
+int try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
 {
 	int priority;
 	int ret = 0;
@@ -1338,7 +1340,7 @@
 /*
  * Try to free up some pages from this zone through reclaim.
  */
-int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
+int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 {
 	struct scan_control sc;
 	int nr_pages = 1 << order;
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 12b4334..0353206 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -308,12 +308,6 @@
 	.create	= bt_sock_create,
 };
 
-extern int hci_sock_init(void);
-extern int hci_sock_cleanup(void);
-
-extern int bt_sysfs_init(void);
-extern int bt_sysfs_cleanup(void);
-
 static int __init bt_init(void)
 {
 	BT_INFO("Core ver %s", VERSION);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 55dc42e..cf0df1c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -87,7 +87,7 @@
 	return notifier_chain_unregister(&hci_notifier, nb);
 }
 
-void hci_notify(struct hci_dev *hdev, int event)
+static void hci_notify(struct hci_dev *hdev, int event)
 {
 	notifier_call_chain(&hci_notifier, event, hdev);
 }
@@ -1347,7 +1347,7 @@
 	kfree_skb(skb);
 }
 
-void hci_rx_task(unsigned long arg)
+static void hci_rx_task(unsigned long arg)
 {
 	struct hci_dev *hdev = (struct hci_dev *) arg;
 	struct sk_buff *skb;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 32ef797..799e448 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -66,20 +66,20 @@
 	/* Packet types */
 	0x10,
 	/* Events */
-	{ 0x1000d9fe, 0x0000300c },
+	{ 0x1000d9fe, 0x0000b00c },
 	/* Commands */
 	{
 		{ 0x0 },
 		/* OGF_LINK_CTL */
-		{ 0xbe000006, 0x00000001, 0x0000, 0x00 },
+		{ 0xbe000006, 0x00000001, 0x000000, 0x00 },
 		/* OGF_LINK_POLICY */
-		{ 0x00005200, 0x00000000, 0x0000, 0x00 },
+		{ 0x00005200, 0x00000000, 0x000000, 0x00 },
 		/* OGF_HOST_CTL */
-		{ 0xaab00200, 0x2b402aaa, 0x0154, 0x00 },
+		{ 0xaab00200, 0x2b402aaa, 0x020154, 0x00 },
 		/* OGF_INFO_PARAM */
-		{ 0x000002be, 0x00000000, 0x0000, 0x00 },
+		{ 0x000002be, 0x00000000, 0x000000, 0x00 },
 		/* OGF_STATUS_PARAM */
-		{ 0x000000ea, 0x00000000, 0x0000, 0x00 }
+		{ 0x000000ea, 0x00000000, 0x000000, 0x00 }
 	}
 };
 
diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig
index 4e958f7..edfea77 100644
--- a/net/bluetooth/hidp/Kconfig
+++ b/net/bluetooth/hidp/Kconfig
@@ -1,6 +1,6 @@
 config BT_HIDP
 	tristate "HIDP protocol support"
-	depends on BT && BT_L2CAP
+	depends on BT && BT_L2CAP && (BROKEN || !S390)
 	select INPUT
 	help
 	  HIDP (Human Interface Device Protocol) is a transport layer
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index de8af5f..860444a 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -520,7 +520,7 @@
 
 	if (session->input) {
 		input_unregister_device(session->input);
-		kfree(session->input);
+		session->input = NULL;
 	}
 
 	up_write(&hidp_session_sem);
@@ -536,6 +536,8 @@
 
 	input->private = session;
 
+	input->name = "Bluetooth HID Boot Protocol Device";
+
 	input->id.bustype = BUS_BLUETOOTH;
 	input->id.vendor  = req->vendor;
 	input->id.product = req->product;
@@ -582,16 +584,15 @@
 		return -ENOTUNIQ;
 
 	session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
-	if (!session) 
+	if (!session)
 		return -ENOMEM;
 	memset(session, 0, sizeof(struct hidp_session));
 
-	session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
+	session->input = input_allocate_device();
 	if (!session->input) {
 		kfree(session);
 		return -ENOMEM;
 	}
-	memset(session->input, 0, sizeof(struct input_dev));
 
 	down_write(&hidp_session_sem);
 
@@ -651,8 +652,10 @@
 
 	__hidp_unlink_session(session);
 
-	if (session->input)
+	if (session->input) {
 		input_unregister_device(session->input);
+		session->input = NULL; /* don't try to free it here */
+	}
 
 failed:
 	up_write(&hidp_session_sem);
diff --git a/net/bluetooth/rfcomm/Makefile b/net/bluetooth/rfcomm/Makefile
index aecec45..fe07988 100644
--- a/net/bluetooth/rfcomm/Makefile
+++ b/net/bluetooth/rfcomm/Makefile
@@ -4,5 +4,5 @@
 
 obj-$(CONFIG_BT_RFCOMM) += rfcomm.o
 
-rfcomm-y			:= core.o sock.o crc.o
+rfcomm-y			:= core.o sock.o
 rfcomm-$(CONFIG_BT_RFCOMM_TTY)	+= tty.o
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 35adce6..c3d56ea 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -133,6 +133,49 @@
 
 /* ---- RFCOMM FCS computation ---- */
 
+/* reversed, 8-bit, poly=0x07 */
+static unsigned char rfcomm_crc_table[256] = { 
+	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
+	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
+	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
+	0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
+
+	0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
+	0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+	0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
+	0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
+
+	0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
+	0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
+	0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
+	0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+
+	0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
+	0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
+	0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
+	0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
+
+	0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
+	0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+	0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
+	0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
+
+	0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
+	0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
+	0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
+	0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+
+	0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
+	0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
+	0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
+	0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
+
+	0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
+	0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+	0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
+	0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
+};
+
 /* CRC on 2 bytes */
 #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
 
diff --git a/net/bluetooth/rfcomm/crc.c b/net/bluetooth/rfcomm/crc.c
deleted file mode 100644
index 1011bc4..0000000
--- a/net/bluetooth/rfcomm/crc.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* 
-   RFCOMM implementation for Linux Bluetooth stack (BlueZ).
-   Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
-   Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.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;
-
-   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 OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
-   SOFTWARE IS DISCLAIMED.
-*/
-
-/*
- * RFCOMM FCS calculation.
- *
- * $Id: crc.c,v 1.2 2002/09/21 09:54:32 holtmann Exp $
- */
-
-/* reversed, 8-bit, poly=0x07 */
-unsigned char rfcomm_crc_table[256] = { 
-	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
-	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
-	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
-	0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
-
-	0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
-	0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
-	0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
-	0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
-
-	0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
-	0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
-	0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
-	0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
-
-	0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
-	0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
-	0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
-	0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
-
-	0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
-	0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
-	0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
-	0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
-
-	0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
-	0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
-	0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
-	0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
-
-	0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
-	0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
-	0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
-	0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
-
-	0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
-	0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
-	0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
-	0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
-};
diff --git a/net/core/dev.c b/net/core/dev.c
index a44eeef..8d15415 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2717,6 +2717,20 @@
 		       dev->name);
 		dev->features &= ~NETIF_F_TSO;
 	}
+	if (dev->features & NETIF_F_UFO) {
+		if (!(dev->features & NETIF_F_HW_CSUM)) {
+			printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
+					"NETIF_F_HW_CSUM feature.\n",
+							dev->name);
+			dev->features &= ~NETIF_F_UFO;
+		}
+		if (!(dev->features & NETIF_F_SG)) {
+			printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
+					"NETIF_F_SG feature.\n",
+					dev->name);
+			dev->features &= ~NETIF_F_UFO;
+		}
+	}
 
 	/*
 	 *	nil rebuild_header routine,
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 404b761..0350586 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -93,6 +93,20 @@
 }
  
 
+u32 ethtool_op_get_ufo(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_UFO) != 0;
+}
+
+int ethtool_op_set_ufo(struct net_device *dev, u32 data)
+{
+	if (data)
+		dev->features |= NETIF_F_UFO;
+	else
+		dev->features &= ~NETIF_F_UFO;
+	return 0;
+}
+
 /* Handlers for each ethtool command */
 
 static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -483,6 +497,11 @@
 			return err;
 	}
 
+	if (!data && dev->ethtool_ops->set_ufo) {
+		err = dev->ethtool_ops->set_ufo(dev, 0);
+		if (err)
+			return err;
+	}
 	return dev->ethtool_ops->set_sg(dev, data);
 }
 
@@ -569,6 +588,32 @@
 	return dev->ethtool_ops->set_tso(dev, edata.data);
 }
 
+static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata = { ETHTOOL_GTSO };
+
+	if (!dev->ethtool_ops->get_ufo)
+		return -EOPNOTSUPP;
+	edata.data = dev->ethtool_ops->get_ufo(dev);
+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
+		 return -EFAULT;
+	return 0;
+}
+static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (!dev->ethtool_ops->set_ufo)
+		return -EOPNOTSUPP;
+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
+		return -EFAULT;
+	if (edata.data && !(dev->features & NETIF_F_SG))
+		return -EINVAL;
+	if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
+		return -EINVAL;
+	return dev->ethtool_ops->set_ufo(dev, edata.data);
+}
+
 static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_test test;
@@ -854,6 +899,12 @@
 	case ETHTOOL_GPERMADDR:
 		rc = ethtool_get_perm_addr(dev, useraddr);
 		break;
+	case ETHTOOL_GUFO:
+		rc = ethtool_get_ufo(dev, useraddr);
+		break;
+	case ETHTOOL_SUFO:
+		rc = ethtool_set_ufo(dev, useraddr);
+		break;
 	default:
 		rc =  -EOPNOTSUPP;
 	}
@@ -882,3 +933,5 @@
 EXPORT_SYMBOL(ethtool_op_set_tso);
 EXPORT_SYMBOL(ethtool_op_set_tx_csum);
 EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
+EXPORT_SYMBOL(ethtool_op_set_ufo);
+EXPORT_SYMBOL(ethtool_op_get_ufo);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 1dcf7fa..e68700f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1625,12 +1625,9 @@
 
 		memset(&ndst, 0, sizeof(ndst));
 
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		for_each_cpu(cpu) {
 			struct neigh_statistics	*st;
 
-			if (!cpu_possible(cpu))
-				continue;
-
 			st = per_cpu_ptr(tbl->stats, cpu);
 			ndst.ndts_allocs		+= st->allocs;
 			ndst.ndts_destroys		+= st->destroys;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 5f043d3..7fc3e9e 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -75,7 +75,7 @@
  * By design there should only be *one* "controlling" process. In practice 
  * multiple write accesses gives unpredictable result. Understood by "write" 
  * to /proc gives result code thats should be read be the "writer".
- * For pratical use this should be no problem.
+ * For practical use this should be no problem.
  *
  * Note when adding devices to a specific CPU there good idea to also assign 
  * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
@@ -96,7 +96,7 @@
  * New xmit() return, do_div and misc clean up by Stephen Hemminger 
  * <shemminger@osdl.org> 040923
  *
- * Rany Dunlap fixed u64 printk compiler waring 
+ * Randy Dunlap fixed u64 printk compiler waring 
  *
  * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
  * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
@@ -137,6 +137,7 @@
 #include <linux/ipv6.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/wait.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
@@ -151,7 +152,7 @@
 #include <asm/timex.h>
 
 
-#define VERSION  "pktgen v2.62: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.63: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a) 
@@ -177,8 +178,8 @@
 #define T_REMDEV      (1<<3)  /* Remove all devs */
 
 /* Locks */
-#define   thread_lock()        spin_lock(&_thread_lock)
-#define   thread_unlock()      spin_unlock(&_thread_lock)
+#define   thread_lock()        down(&pktgen_sem)
+#define   thread_unlock()      up(&pktgen_sem)
 
 /* If lock -- can be removed after some work */
 #define   if_lock(t)           spin_lock(&(t->if_lock));
@@ -186,7 +187,9 @@
 
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
-#define PG_PROC_DIR "net/pktgen"
+#define PG_PROC_DIR "pktgen"
+#define PGCTRL	    "pgctrl"
+static struct proc_dir_entry *pg_proc_dir = NULL;
 
 #define MAX_CFLOWS  65536
 
@@ -202,11 +205,8 @@
 	 * Try to keep frequent/infrequent used vars. separated.
 	 */
 
-        char ifname[32];
-        struct proc_dir_entry *proc_ent;
+        char ifname[IFNAMSIZ];
         char result[512];
-        /* proc file names */
-        char fname[80];
 
         struct pktgen_thread* pg_thread; /* the owner */
         struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
@@ -244,7 +244,7 @@
         __u32 seq_num;
         
         int clone_skb; /* Use multiple SKBs during packet gen.  If this number
-                          * is greater than 1, then that many coppies of the same
+                          * is greater than 1, then that many copies of the same
                           * packet will be sent before a new packet is allocated.
                           * For instance, if you want to send 1024 identical packets
                           * before creating a new packet, set clone_skb to 1024.
@@ -330,8 +330,6 @@
         struct pktgen_dev *if_list;           /* All device here */
         struct pktgen_thread* next;
         char name[32];
-        char fname[128]; /* name of proc file */
-        struct proc_dir_entry *proc_ent;
         char result[512];
         u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
         
@@ -396,7 +394,7 @@
 
 /* End of hacks to deal with 64-bit math on x86 */
 
-/** Convert to miliseconds */
+/** Convert to milliseconds */
 static inline __u64 tv_to_ms(const struct timeval* tv) 
 {
         __u64 ms = tv->tv_usec / 1000;
@@ -425,7 +423,7 @@
 {
         __u64 tmp = n;
 /*
- * How do we know if the architectrure we are running on
+ * How do we know if the architecture we are running on
  * supports division with 64 bit base?
  * 
  */
@@ -473,16 +471,6 @@
 
 static char version[] __initdata = VERSION;
 
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf, size_t count, loff_t *ppos);
-static ssize_t proc_pgctrl_write(struct file* file, const char __user * buf, size_t count, loff_t *ppos);
-static int proc_if_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-
-static int proc_thread_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-static int proc_if_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int proc_thread_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int create_proc_dir(void);
-static int remove_proc_dir(void);
-
 static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
 static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
 static struct pktgen_thread* pktgen_find_thread(const char* name);
@@ -503,83 +491,41 @@
 static int pg_clone_skb_d = 0;
 static int debug = 0;
 
-static DEFINE_SPINLOCK(_thread_lock);
+static DECLARE_MUTEX(pktgen_sem);
 static struct pktgen_thread *pktgen_threads = NULL;
 
-static char module_fname[128];
-static struct proc_dir_entry *module_proc_ent = NULL;
-
 static struct notifier_block pktgen_notifier_block = {
 	.notifier_call = pktgen_device_event,
 };
 
-static struct file_operations pktgen_fops = {
-        .read     = proc_pgctrl_read,
-        .write    = proc_pgctrl_write,
-	/*  .ioctl    = pktgen_ioctl, later maybe */
-};
-
 /*
  * /proc handling functions 
  *
  */
 
-static struct proc_dir_entry *pg_proc_dir = NULL;
-static int proc_pgctrl_read_eof=0;
-
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf,
-                                 size_t count, loff_t *ppos)
+static int pgctrl_show(struct seq_file *seq, void *v)
 { 
-	char data[200];
-	int len = 0;
-
-	if(proc_pgctrl_read_eof) {
-		proc_pgctrl_read_eof=0;
-		len = 0;
-		goto out;
-	}
-
-	sprintf(data, "%s", VERSION); 
-
-	len = strlen(data);
-
-	if(len > count) {
-		len =-EFAULT;
-		goto out;
-	}  	
-
-	if (copy_to_user(buf, data, len)) {
-		len =-EFAULT;
-		goto out;
-	}  
-
-	*ppos += len;
-	proc_pgctrl_read_eof=1; /* EOF next call */
-
- out:
-	return len;
+	seq_puts(seq, VERSION);
+	return 0;
 }
 
-static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
-				 size_t count, loff_t *ppos)
+static ssize_t pgctrl_write(struct file* file,const char __user * buf,
+			    size_t count, loff_t *ppos)
 {
-	char *data = NULL;
 	int err = 0;
+	char data[128];
 
         if (!capable(CAP_NET_ADMIN)){
                 err = -EPERM;
 		goto out;
         }
 
-	data = (void*)vmalloc ((unsigned int)count);
+	if (count > sizeof(data))
+		count = sizeof(data);
 
-	if(!data) {
-		err = -ENOMEM;
-		goto out;
-	}
 	if (copy_from_user(data, buf, count)) {
-		err =-EFAULT;
-		goto out_free;
+		err = -EFAULT;
+		goto out;
 	}  
 	data[count-1] = 0; /* Make string */
 
@@ -594,31 +540,40 @@
 
 	err = count;
 
- out_free:
-	vfree (data);
  out:
         return err;
 }
 
-static int proc_if_read(char *buf , char **start, off_t offset,
-                           int len, int *eof, void *data)
+static int pgctrl_open(struct inode *inode, struct file *file)
 {
-	char *p;
+	return single_open(file, pgctrl_show, PDE(inode)->data);
+}
+
+static struct file_operations pktgen_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pgctrl_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pgctrl_write,
+	.release  = single_release,
+};
+
+static int pktgen_if_show(struct seq_file *seq, void *v)
+{
 	int i;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+        struct pktgen_dev *pkt_dev = seq->private;
         __u64 sa;
         __u64 stopped;
         __u64 now = getCurUs();
         
-	p = buf;
-	p += sprintf(p, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
-		     (unsigned long long) pkt_dev->count,
-		     pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
+	seq_printf(seq, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
+		   (unsigned long long) pkt_dev->count,
+		   pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
 
-	p += sprintf(p, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
-                     pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
+	seq_printf(seq, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
+		   pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
 
-	p += sprintf(p, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
+	seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
 
 
 	if(pkt_dev->flags & F_IPV6) {
@@ -626,19 +581,19 @@
 		fmt_ip6(b1,  pkt_dev->in6_saddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_saddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_saddr.s6_addr);
-		p += sprintf(p, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
+		seq_printf(seq, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
 
 		fmt_ip6(b1,  pkt_dev->in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_daddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_daddr.s6_addr);
-		p += sprintf(p, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
+		seq_printf(seq, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
 
 	} 
 	else 
-		p += sprintf(p, "     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
-                     pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
+		seq_printf(seq,"     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
+			   pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
 
-        p += sprintf(p, "     src_mac: ");
+	seq_puts(seq, "     src_mac: ");
 
 	if ((pkt_dev->src_mac[0] == 0) && 
 	    (pkt_dev->src_mac[1] == 0) && 
@@ -648,89 +603,89 @@
 	    (pkt_dev->src_mac[5] == 0)) 
 
 		for (i = 0; i < 6; i++) 
-			p += sprintf(p, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
+			seq_printf(seq,  "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
 
 	else 
 		for (i = 0; i < 6; i++) 
-			p += sprintf(p, "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
+			seq_printf(seq,  "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
 
-        p += sprintf(p, "dst_mac: ");
+        seq_printf(seq,  "dst_mac: ");
 	for (i = 0; i < 6; i++) 
-		p += sprintf(p, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
+		seq_printf(seq,  "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
 
-        p += sprintf(p, "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
-                     pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
-                     pkt_dev->udp_dst_max);
+        seq_printf(seq,  "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
+		   pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
+		   pkt_dev->udp_dst_max);
 
-        p += sprintf(p, "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
-                     pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
+        seq_printf(seq,  "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
+		   pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
 
 
         if (pkt_dev->flags &  F_IPV6) 
-                p += sprintf(p, "IPV6  ");
+                seq_printf(seq,  "IPV6  ");
 
         if (pkt_dev->flags &  F_IPSRC_RND) 
-                p += sprintf(p, "IPSRC_RND  ");
+                seq_printf(seq,  "IPSRC_RND  ");
 
         if (pkt_dev->flags & F_IPDST_RND) 
-                p += sprintf(p, "IPDST_RND  ");
+                seq_printf(seq,  "IPDST_RND  ");
         
         if (pkt_dev->flags & F_TXSIZE_RND) 
-                p += sprintf(p, "TXSIZE_RND  ");
+                seq_printf(seq,  "TXSIZE_RND  ");
         
         if (pkt_dev->flags & F_UDPSRC_RND) 
-                p += sprintf(p, "UDPSRC_RND  ");
+                seq_printf(seq,  "UDPSRC_RND  ");
         
         if (pkt_dev->flags & F_UDPDST_RND) 
-                p += sprintf(p, "UDPDST_RND  ");
+                seq_printf(seq,  "UDPDST_RND  ");
         
         if (pkt_dev->flags & F_MACSRC_RND) 
-                p += sprintf(p, "MACSRC_RND  ");
+                seq_printf(seq,  "MACSRC_RND  ");
         
         if (pkt_dev->flags & F_MACDST_RND) 
-                p += sprintf(p, "MACDST_RND  ");
+                seq_printf(seq,  "MACDST_RND  ");
 
         
-        p += sprintf(p, "\n");
+        seq_puts(seq,  "\n");
         
         sa = pkt_dev->started_at;
         stopped = pkt_dev->stopped_at;
         if (pkt_dev->running) 
                 stopped = now; /* not really stopped, more like last-running-at */
         
-        p += sprintf(p, "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
-		     (unsigned long long) pkt_dev->sofar,
-		     (unsigned long long) pkt_dev->errors,
-		     (unsigned long long) sa,
-		     (unsigned long long) stopped, 
-		     (unsigned long long) pkt_dev->idle_acc);
+        seq_printf(seq,  "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
+		   (unsigned long long) pkt_dev->sofar,
+		   (unsigned long long) pkt_dev->errors,
+		   (unsigned long long) sa,
+		   (unsigned long long) stopped,
+		   (unsigned long long) pkt_dev->idle_acc);
 
-        p += sprintf(p, "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
-                     pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset);
+        seq_printf(seq,  "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
+		   pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
+		   pkt_dev->cur_src_mac_offset);
 
 	if(pkt_dev->flags & F_IPV6) {
 		char b1[128], b2[128];
 		fmt_ip6(b1,  pkt_dev->cur_in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->cur_in6_saddr.s6_addr);
-		p += sprintf(p, "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
+		seq_printf(seq,  "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
 	} 
 	else 
-		p += sprintf(p, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
-                     pkt_dev->cur_saddr, pkt_dev->cur_daddr);
+		seq_printf(seq,  "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
+			   pkt_dev->cur_saddr, pkt_dev->cur_daddr);
 
 
-	p += sprintf(p, "     cur_udp_dst: %d  cur_udp_src: %d\n",
-                     pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
+	seq_printf(seq,  "     cur_udp_dst: %d  cur_udp_src: %d\n",
+		   pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
 
-	p += sprintf(p, "     flows: %u\n", pkt_dev->nflows);
+	seq_printf(seq,  "     flows: %u\n", pkt_dev->nflows);
 
 	if (pkt_dev->result[0])
-		p += sprintf(p, "Result: %s\n", pkt_dev->result);
+		seq_printf(seq,  "Result: %s\n", pkt_dev->result);
 	else
-		p += sprintf(p, "Result: Idle\n");
-	*eof = 1;
+		seq_printf(seq,  "Result: Idle\n");
 
-	return p - buf;
+	return 0;
 }
 
 
@@ -802,13 +757,14 @@
 	return i;
 }
 
-static int proc_if_write(struct file *file, const char __user *user_buffer,
-                            unsigned long count, void *data)
+static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer,
+			       size_t count, loff_t *offset)
 {
+	struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_dev *pkt_dev = seq->private;
 	int i = 0, max, len;
 	char name[16], valstr[32];
 	unsigned long value = 0;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
         char* pg_result = NULL;
         int tmp = 0;
 	char buf[128];
@@ -849,7 +805,8 @@
                 if (copy_from_user(tb, user_buffer, count))
 			return -EFAULT;
                 tb[count] = 0;
-		printk("pktgen: %s,%lu  buffer -:%s:-\n", name, count, tb);
+		printk("pktgen: %s,%lu  buffer -:%s:-\n", name,
+		       (unsigned long) count, tb);
         }
 
 	if (!strcmp(name, "min_pkt_size")) {
@@ -1335,92 +1292,98 @@
 	return -EINVAL;
 }
 
-static int proc_thread_read(char *buf , char **start, off_t offset,
-                               int len, int *eof, void *data)
+static int pktgen_if_open(struct inode *inode, struct file *file)
 {
-	char *p;
-        struct pktgen_thread *t = (struct pktgen_thread*)(data);
+	return single_open(file, pktgen_if_show, PDE(inode)->data);
+}
+
+static struct file_operations pktgen_if_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pktgen_if_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pktgen_if_write,
+	.release  = single_release,
+};
+
+static int pktgen_thread_show(struct seq_file *seq, void *v)
+{
+        struct pktgen_thread *t = seq->private;
         struct pktgen_dev *pkt_dev = NULL;
 
+	BUG_ON(!t);
 
-        if (!t) {
-                printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
-                return -EINVAL;
-        }
-
-	p = buf;
-	p += sprintf(p, "Name: %s  max_before_softirq: %d\n",
+	seq_printf(seq, "Name: %s  max_before_softirq: %d\n",
                      t->name, t->max_before_softirq);
 
-        p += sprintf(p, "Running: ");
+        seq_printf(seq, "Running: ");
         
         if_lock(t);
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
 		if(pkt_dev->running)
-			p += sprintf(p, "%s ", pkt_dev->ifname);
+			seq_printf(seq, "%s ", pkt_dev->ifname);
         
-        p += sprintf(p, "\nStopped: ");
+        seq_printf(seq, "\nStopped: ");
 
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
 		if(!pkt_dev->running)
-			p += sprintf(p, "%s ", pkt_dev->ifname);
+			seq_printf(seq, "%s ", pkt_dev->ifname);
 
 	if (t->result[0])
-		p += sprintf(p, "\nResult: %s\n", t->result);
+		seq_printf(seq, "\nResult: %s\n", t->result);
 	else
-		p += sprintf(p, "\nResult: NA\n");
-
-	*eof = 1;
+		seq_printf(seq, "\nResult: NA\n");
 
         if_unlock(t);
 
-	return p - buf;
+	return 0;
 }
 
-static int proc_thread_write(struct file *file, const char __user *user_buffer,
-                                unsigned long count, void *data)
+static ssize_t pktgen_thread_write(struct file *file,
+				   const char __user *user_buffer,
+				   size_t count, loff_t *offset)
 {
+	struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_thread *t = seq->private;
 	int i = 0, max, len, ret;
 	char name[40];
-        struct pktgen_thread *t;
         char *pg_result;
         unsigned long value = 0;
-        
+
 	if (count < 1) {
 		//	sprintf(pg_result, "Wrong command format");
 		return -EINVAL;
 	}
-  
+
 	max = count - i;
         len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0) 
-		return len; 
-     
+        if (len < 0)
+		return len;
+
 	i += len;
-  
+
 	/* Read variable name */
 
 	len = strn_len(&user_buffer[i], sizeof(name) - 1);
-        if (len < 0)  
-		return len; 
+        if (len < 0)
+		return len;
 	
 	memset(name, 0, sizeof(name));
 	if (copy_from_user(name, &user_buffer[i], len))
 		return -EFAULT;
 	i += len;
-  
+
 	max = count -i;
 	len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0)  
-		return len; 
-	
+        if (len < 0)
+		return len;
+
 	i += len;
 
-	if (debug) 
-		printk("pktgen: t=%s, count=%lu\n", name, count);
-        
+	if (debug)
+		printk("pktgen: t=%s, count=%lu\n", name,
+		       (unsigned long) count);
 
-        t = (struct pktgen_thread*)(data);
 	if(!t) {
 		printk("pktgen: ERROR: No thread\n");
 		ret = -EINVAL;
@@ -1474,21 +1437,19 @@
 	return ret;
 }
 
-static int create_proc_dir(void)
+static int pktgen_thread_open(struct inode *inode, struct file *file)
 {
-	pg_proc_dir = proc_mkdir(PG_PROC_DIR, NULL);
-        
-        if (!pg_proc_dir) 
-                return -ENODEV;
-        
-        return 0;
+	return single_open(file, pktgen_thread_show, PDE(inode)->data);
 }
 
-static int remove_proc_dir(void)
-{
-        remove_proc_entry(PG_PROC_DIR, NULL);
-        return 0;
-}
+static struct file_operations pktgen_thread_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pktgen_thread_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pktgen_thread_write,
+	.release  = single_release,
+};
 
 /* Think find or remove for NN */
 static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
@@ -1702,7 +1663,7 @@
 	start = now = getCurUs();
 	printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
 	while (now < spin_until_us) {
-		/* TODO: optimise sleeping behavior */
+		/* TODO: optimize sleeping behavior */
 		if (spin_until_us - now > jiffies_to_usecs(1)+1)
 			schedule_timeout_interruptible(1);
 		else if (spin_until_us - now > 100) {
@@ -2361,7 +2322,7 @@
 		pktgen_stop(t);
 		t = t->next;
 	}
-       thread_unlock();
+	thread_unlock();
 }
 
 static int thread_is_running(struct pktgen_thread *t )
@@ -2552,10 +2513,9 @@
 
 	struct pktgen_thread *tmp = pktgen_threads;
 
-        if (strlen(t->fname))
-                remove_proc_entry(t->fname, NULL);
+	remove_proc_entry(t->name, pg_proc_dir);
 
-       thread_lock();
+	thread_lock();
 
 	if (tmp == t)
 		pktgen_threads = tmp->next;
@@ -2825,7 +2785,7 @@
         if_lock(t);
 
         for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
-                if (strcmp(pkt_dev->ifname, ifname) == 0) {
+                if (strncmp(pkt_dev->ifname, ifname, IFNAMSIZ) == 0) {
                         break;
                 }
         }
@@ -2864,74 +2824,70 @@
 static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 
 {
         struct pktgen_dev *pkt_dev;
+	struct proc_dir_entry *pe;
 	
 	/* We don't allow a device to be on several threads */
 
-	if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
-						   
-		pkt_dev = kmalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
-                if (!pkt_dev) 
-                        return -ENOMEM;
-
-                memset(pkt_dev, 0, sizeof(struct pktgen_dev));
-
-		pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
-		if (pkt_dev->flows == NULL) {
-			kfree(pkt_dev);
-			return -ENOMEM;
-		}
-		memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
-
-		pkt_dev->min_pkt_size = ETH_ZLEN;
-                pkt_dev->max_pkt_size = ETH_ZLEN;
-                pkt_dev->nfrags = 0;
-                pkt_dev->clone_skb = pg_clone_skb_d;
-                pkt_dev->delay_us = pg_delay_d / 1000;
-                pkt_dev->delay_ns = pg_delay_d % 1000;
-                pkt_dev->count = pg_count_d;
-                pkt_dev->sofar = 0;
-                pkt_dev->udp_src_min = 9; /* sink port */
-                pkt_dev->udp_src_max = 9;
-                pkt_dev->udp_dst_min = 9;
-                pkt_dev->udp_dst_max = 9;
-
-                strncpy(pkt_dev->ifname, ifname, 31);
-                sprintf(pkt_dev->fname, "%s/%s", PG_PROC_DIR, ifname);
-
-                if (! pktgen_setup_dev(pkt_dev)) {
-                        printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
-			if (pkt_dev->flows)
-				vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -ENODEV;
-                }
-
-                pkt_dev->proc_ent = create_proc_entry(pkt_dev->fname, 0600, NULL);
-                if (!pkt_dev->proc_ent) {
-                        printk("pktgen: cannot create %s procfs entry.\n", pkt_dev->fname);
-			if (pkt_dev->flows)
-				vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -EINVAL;
-                }
-                pkt_dev->proc_ent->read_proc = proc_if_read;
-                pkt_dev->proc_ent->write_proc = proc_if_write;
-                pkt_dev->proc_ent->data = (void*)(pkt_dev);
-		pkt_dev->proc_ent->owner = THIS_MODULE;
-
-                return add_dev_to_thread(t, pkt_dev);
-        }
-        else {
+	pkt_dev = __pktgen_NN_threads(ifname, FIND);
+	if (pkt_dev) {
                 printk("pktgen: ERROR: interface already used.\n");
                 return -EBUSY;
         }
+
+	pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
+	if (!pkt_dev)
+		return -ENOMEM;
+
+	pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
+	if (pkt_dev->flows == NULL) {
+		kfree(pkt_dev);
+		return -ENOMEM;
+	}
+	memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
+
+	pkt_dev->min_pkt_size = ETH_ZLEN;
+	pkt_dev->max_pkt_size = ETH_ZLEN;
+	pkt_dev->nfrags = 0;
+	pkt_dev->clone_skb = pg_clone_skb_d;
+	pkt_dev->delay_us = pg_delay_d / 1000;
+	pkt_dev->delay_ns = pg_delay_d % 1000;
+	pkt_dev->count = pg_count_d;
+	pkt_dev->sofar = 0;
+	pkt_dev->udp_src_min = 9; /* sink port */
+	pkt_dev->udp_src_max = 9;
+	pkt_dev->udp_dst_min = 9;
+	pkt_dev->udp_dst_max = 9;
+
+	strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
+
+	if (! pktgen_setup_dev(pkt_dev)) {
+		printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
+		if (pkt_dev->flows)
+			vfree(pkt_dev->flows);
+		kfree(pkt_dev);
+		return -ENODEV;
+	}
+
+	pe = create_proc_entry(ifname, 0600, pg_proc_dir);
+	if (!pe) {
+		printk("pktgen: cannot create %s/%s procfs entry.\n",
+		       PG_PROC_DIR, ifname);
+		if (pkt_dev->flows)
+			vfree(pkt_dev->flows);
+		kfree(pkt_dev);
+		return -EINVAL;
+	}
+	pe->proc_fops = &pktgen_if_fops;
+	pe->data = pkt_dev;
+
+	return add_dev_to_thread(t, pkt_dev);
 }
 
 static struct pktgen_thread *pktgen_find_thread(const char* name) 
 {
         struct pktgen_thread *t = NULL;
 
-       thread_lock();
+	thread_lock();
 
         t = pktgen_threads;
         while (t) {
@@ -2947,6 +2903,7 @@
 static int pktgen_create_thread(const char* name, int cpu) 
 {
         struct pktgen_thread *t = NULL;
+	struct proc_dir_entry *pe;
 
         if (strlen(name) > 31) {
                 printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
@@ -2958,28 +2915,26 @@
                 return -EINVAL;
         }
 
-        t = (struct pktgen_thread*)(kmalloc(sizeof(struct pktgen_thread), GFP_KERNEL));
+        t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
         if (!t) {
                 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
                 return -ENOMEM;
         }
 
-        memset(t, 0, sizeof(struct pktgen_thread));
         strcpy(t->name, name);
         spin_lock_init(&t->if_lock);
 	t->cpu = cpu;
         
-        sprintf(t->fname, "%s/%s", PG_PROC_DIR, t->name);
-        t->proc_ent = create_proc_entry(t->fname, 0600, NULL);
-        if (!t->proc_ent) {
-                printk("pktgen: cannot create %s procfs entry.\n", t->fname);
+        pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+        if (!pe) {
+                printk("pktgen: cannot create %s/%s procfs entry.\n",
+		       PG_PROC_DIR, t->name);
                 kfree(t);
                 return -EINVAL;
         }
-        t->proc_ent->read_proc = proc_thread_read;
-        t->proc_ent->write_proc = proc_thread_write;
-        t->proc_ent->data = (void*)(t);
-        t->proc_ent->owner = THIS_MODULE;
+
+	pe->proc_fops = &pktgen_thread_fops;
+	pe->data = t;
 
         t->next = pktgen_threads;
         pktgen_threads = t;
@@ -3034,8 +2989,7 @@
 
         /* Clean up proc file system */
 
-        if (strlen(pkt_dev->fname)) 
-                remove_proc_entry(pkt_dev->fname, NULL);
+	remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
 
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
@@ -3046,31 +3000,31 @@
 static int __init pg_init(void) 
 {
 	int cpu;
+	struct proc_dir_entry *pe;
+
 	printk(version);
 
-        module_fname[0] = 0;
+	pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
+	if (!pg_proc_dir)
+		return -ENODEV;
+	pg_proc_dir->owner = THIS_MODULE;
 
-	create_proc_dir();
-
-        sprintf(module_fname, "%s/pgctrl", PG_PROC_DIR);
-        module_proc_ent = create_proc_entry(module_fname, 0600, NULL);
-        if (!module_proc_ent) {
-                printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
+	pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
+        if (pe == NULL) {
+		printk("pktgen: ERROR: cannot create %s procfs entry.\n", PGCTRL);
+		proc_net_remove(PG_PROC_DIR);
                 return -EINVAL;
         }
 
-        module_proc_ent->proc_fops =  &pktgen_fops;
-        module_proc_ent->data = NULL;
+        pe->proc_fops = &pktgen_fops;
+        pe->data      = NULL;
 
 	/* Register us to receive netdevice events */
 	register_netdevice_notifier(&pktgen_notifier_block);
         
-	for (cpu = 0; cpu < NR_CPUS ; cpu++) {
+	for_each_online_cpu(cpu) {
 		char buf[30];
 
-		if (!cpu_online(cpu))
-			continue;
-
                 sprintf(buf, "kpktgend_%i", cpu);
                 pktgen_create_thread(buf, cpu);
         }
@@ -3095,10 +3049,8 @@
 	unregister_netdevice_notifier(&pktgen_notifier_block);
 
         /* Clean up proc file system */
-
-        remove_proc_entry(module_fname, NULL);
-        
-	remove_proc_dir();
+	remove_proc_entry(PGCTRL, pg_proc_dir);
+	proc_net_remove(PG_PROC_DIR);
 }
 
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 02cd4cd..95501e4 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -122,6 +122,8 @@
  *	__alloc_skb	-	allocate a network buffer
  *	@size: size to allocate
  *	@gfp_mask: allocation mask
+ *	@fclone: allocate from fclone cache instead of head cache
+ *		and allocate a cloned (child) skb
  *
  *	Allocate a new &sk_buff. The returned buffer has no headroom and a
  *	tail room of size bytes. The object has a reference count of one.
@@ -174,6 +176,8 @@
 	skb_shinfo(skb)->tso_size = 0;
 	skb_shinfo(skb)->tso_segs = 0;
 	skb_shinfo(skb)->frag_list = NULL;
+	skb_shinfo(skb)->ufo_size = 0;
+	skb_shinfo(skb)->ip6_frag_id = 0;
 out:
 	return skb;
 nodata:
@@ -1694,6 +1698,78 @@
 	return textsearch_find(config, state);
 }
 
+/**
+ * skb_append_datato_frags: - append the user data to a skb
+ * @sk: sock  structure
+ * @skb: skb structure to be appened with user data.
+ * @getfrag: call back function to be used for getting the user data
+ * @from: pointer to user message iov
+ * @length: length of the iov message
+ *
+ * Description: This procedure append the user data in the fragment part
+ * of the skb if any page alloc fails user this procedure returns  -ENOMEM
+ */
+int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
+			int getfrag(void *from, char *to, int offset,
+					int len, int odd, struct sk_buff *skb),
+			void *from, int length)
+{
+	int frg_cnt = 0;
+	skb_frag_t *frag = NULL;
+	struct page *page = NULL;
+	int copy, left;
+	int offset = 0;
+	int ret;
+
+	do {
+		/* Return error if we don't have space for new frag */
+		frg_cnt = skb_shinfo(skb)->nr_frags;
+		if (frg_cnt >= MAX_SKB_FRAGS)
+			return -EFAULT;
+
+		/* allocate a new page for next frag */
+		page = alloc_pages(sk->sk_allocation, 0);
+
+		/* If alloc_page fails just return failure and caller will
+		 * free previous allocated pages by doing kfree_skb()
+		 */
+		if (page == NULL)
+			return -ENOMEM;
+
+		/* initialize the next frag */
+		sk->sk_sndmsg_page = page;
+		sk->sk_sndmsg_off = 0;
+		skb_fill_page_desc(skb, frg_cnt, page, 0, 0);
+		skb->truesize += PAGE_SIZE;
+		atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
+
+		/* get the new initialized frag */
+		frg_cnt = skb_shinfo(skb)->nr_frags;
+		frag = &skb_shinfo(skb)->frags[frg_cnt - 1];
+
+		/* copy the user data to page */
+		left = PAGE_SIZE - frag->page_offset;
+		copy = (length > left)? left : length;
+
+		ret = getfrag(from, (page_address(frag->page) +
+			    frag->page_offset + frag->size),
+			    offset, copy, 0, skb);
+		if (ret < 0)
+			return -EFAULT;
+
+		/* copy was successful so update the size parameters */
+		sk->sk_sndmsg_off += copy;
+		frag->size += copy;
+		skb->len += copy;
+		skb->data_len += copy;
+		offset += copy;
+		length -= copy;
+
+	} while (length > 0);
+
+	return 0;
+}
+
 void __init skb_init(void)
 {
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1745,3 +1821,4 @@
 EXPORT_SYMBOL(skb_seq_read);
 EXPORT_SYMBOL(skb_abort_seq_read);
 EXPORT_SYMBOL(skb_find_text);
+EXPORT_SYMBOL(skb_append_datato_frags);
diff --git a/net/core/sock.c b/net/core/sock.c
index 1c52fe8..9602ceb 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -940,7 +940,7 @@
 					    int noblock, int *errcode)
 {
 	struct sk_buff *skb;
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 	long timeo;
 	int err;
 
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 2925074..d59f86f 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -495,7 +495,7 @@
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct sk_buff *skb;
-	const unsigned int prio = active ? GFP_KERNEL : GFP_ATOMIC;
+	const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
 
 	skb = alloc_skb(sk->sk_prot->max_header, prio);
 	if (skb == NULL)
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 1186dc4..3f25cad 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -719,22 +719,9 @@
 	if (saddr->sdn_flags & ~SDF_WILD)
 		return -EINVAL;
 
-#if 1
 	if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
 	    (saddr->sdn_flags & SDF_WILD)))
 		return -EACCES;
-#else
-	/*
-	 * Maybe put the default actions in the default security ops for
-	 * dn_prot_sock ? Would be nice if the capable call would go there
-	 * too.
-	 */
-	if (security_dn_prot_sock(saddr) &&
-	    !capable(CAP_NET_BIND_SERVICE) || 
-	    saddr->sdn_objnum || (saddr->sdn_flags & SDF_WILD))
-		return -EACCES;
-#endif
-
 
 	if (!(saddr->sdn_flags & SDF_WILD)) {
 		if (dn_ntohs(saddr->sdn_nodeaddrl)) {
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 68a5ca8..e245773 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -146,19 +146,6 @@
 	return 0;
 }
 
-static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b)
-{
-	const unsigned short *dest = (unsigned short *) __a;
-	const unsigned short *devaddr = (unsigned short *) __b;
-	unsigned int res;
-
-	BUILD_BUG_ON(ETH_ALEN != 6);
-	res = ((dest[0] ^ devaddr[0]) |
-	       (dest[1] ^ devaddr[1]) |
-	       (dest[2] ^ devaddr[2])) != 0;
-
-	return res;
-}
 
 /*
  *	Determine the packet's protocol ID. The rule here is that we 
@@ -176,7 +163,7 @@
 	eth = eth_hdr(skb);
 	
 	if (*eth->h_dest&1) {
-		if (!compare_eth_addr(eth->h_dest, dev->broadcast))
+		if (!compare_ether_addr(eth->h_dest, dev->broadcast))
 			skb->pkt_type = PACKET_BROADCAST;
 		else
 			skb->pkt_type = PACKET_MULTICAST;
@@ -191,7 +178,7 @@
 	 */
 	 
 	else if(1 /*dev->flags&IFF_PROMISC*/) {
-		if (unlikely(compare_eth_addr(eth->h_dest, dev->dev_addr)))
+		if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr)))
 			skb->pkt_type = PACKET_OTHERHOST;
 	}
 	
diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
index a6ccac5..f988417 100644
--- a/net/ieee80211/Makefile
+++ b/net/ieee80211/Makefile
@@ -7,5 +7,6 @@
 	ieee80211_module.o \
 	ieee80211_tx.o \
 	ieee80211_rx.o \
-	ieee80211_wx.o
+	ieee80211_wx.o \
+	ieee80211_geo.o
 
diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index 61a9d92..f3b6aa3 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -41,6 +41,12 @@
 {
 	struct list_head *ptr, *n;
 	struct ieee80211_crypt_data *entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+
+	if (list_empty(&ieee->crypt_deinit_list))
+		goto unlock;
 
 	for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
 	     ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
@@ -57,6 +63,18 @@
 		}
 		kfree(entry);
 	}
+      unlock:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+/* After this, crypt_deinit_list won't accept new members */
+void ieee80211_crypt_quiescing(struct ieee80211_device *ieee)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+	ieee->crypt_quiesced = 1;
+	spin_unlock_irqrestore(&ieee->lock, flags);
 }
 
 void ieee80211_crypt_deinit_handler(unsigned long data)
@@ -64,16 +82,16 @@
 	struct ieee80211_device *ieee = (struct ieee80211_device *)data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ieee->lock, flags);
 	ieee80211_crypt_deinit_entries(ieee, 0);
-	if (!list_empty(&ieee->crypt_deinit_list)) {
+
+	spin_lock_irqsave(&ieee->lock, flags);
+	if (!list_empty(&ieee->crypt_deinit_list) && !ieee->crypt_quiesced) {
 		printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
 		       "deletion list\n", ieee->dev->name);
 		ieee->crypt_deinit_timer.expires = jiffies + HZ;
 		add_timer(&ieee->crypt_deinit_timer);
 	}
 	spin_unlock_irqrestore(&ieee->lock, flags);
-
 }
 
 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
@@ -93,10 +111,12 @@
 	 * locking. */
 
 	spin_lock_irqsave(&ieee->lock, flags);
-	list_add(&tmp->list, &ieee->crypt_deinit_list);
-	if (!timer_pending(&ieee->crypt_deinit_timer)) {
-		ieee->crypt_deinit_timer.expires = jiffies + HZ;
-		add_timer(&ieee->crypt_deinit_timer);
+	if (!ieee->crypt_quiesced) {
+		list_add(&tmp->list, &ieee->crypt_deinit_list);
+		if (!timer_pending(&ieee->crypt_deinit_timer)) {
+			ieee->crypt_deinit_timer.expires = jiffies + HZ;
+			add_timer(&ieee->crypt_deinit_timer);
+		}
 	}
 	spin_unlock_irqrestore(&ieee->lock, flags);
 }
@@ -191,18 +211,18 @@
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_null = {
-	.name			= "NULL",
-	.init			= ieee80211_crypt_null_init,
-	.deinit			= ieee80211_crypt_null_deinit,
-	.encrypt_mpdu		= NULL,
-	.decrypt_mpdu		= NULL,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= NULL,
-	.get_key		= NULL,
-	.extra_prefix_len	= 0,
-	.extra_postfix_len	= 0,
-	.owner			= THIS_MODULE,
+	.name = "NULL",
+	.init = ieee80211_crypt_null_init,
+	.deinit = ieee80211_crypt_null_deinit,
+	.encrypt_mpdu = NULL,
+	.decrypt_mpdu = NULL,
+	.encrypt_msdu = NULL,
+	.decrypt_msdu = NULL,
+	.set_key = NULL,
+	.get_key = NULL,
+	.extra_mpdu_prefix_len = 0,
+	.extra_mpdu_postfix_len = 0,
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_init(void)
@@ -249,6 +269,7 @@
 EXPORT_SYMBOL(ieee80211_crypt_deinit_entries);
 EXPORT_SYMBOL(ieee80211_crypt_deinit_handler);
 EXPORT_SYMBOL(ieee80211_crypt_delayed_deinit);
+EXPORT_SYMBOL(ieee80211_crypt_quiescing);
 
 EXPORT_SYMBOL(ieee80211_register_crypto_ops);
 EXPORT_SYMBOL(ieee80211_unregister_crypto_ops);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 8fc13f4..05a853c 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -119,7 +119,7 @@
 }
 
 static void ccmp_init_blocks(struct crypto_tfm *tfm,
-			     struct ieee80211_hdr *hdr,
+			     struct ieee80211_hdr_4addr *hdr,
 			     u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
 {
 	u8 *pos, qc = 0;
@@ -191,26 +191,18 @@
 	ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
 }
 
-static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static int ieee80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct ieee80211_ccmp_data *key = priv;
-	int data_len, i, blocks, last, len;
-	u8 *pos, *mic;
-	struct ieee80211_hdr *hdr;
-	u8 *b0 = key->tx_b0;
-	u8 *b = key->tx_b;
-	u8 *e = key->tx_e;
-	u8 *s0 = key->tx_s0;
+	int i;
+	u8 *pos;
 
-	if (skb_headroom(skb) < CCMP_HDR_LEN ||
-	    skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+	if (skb_headroom(skb) < CCMP_HDR_LEN || skb->len < hdr_len)
 		return -1;
 
-	data_len = skb->len - hdr_len;
 	pos = skb_push(skb, CCMP_HDR_LEN);
 	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
 	pos += hdr_len;
-	mic = skb_put(skb, CCMP_MIC_LEN);
 
 	i = CCMP_PN_LEN - 1;
 	while (i >= 0) {
@@ -229,7 +221,31 @@
 	*pos++ = key->tx_pn[1];
 	*pos++ = key->tx_pn[0];
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	return CCMP_HDR_LEN;
+}
+
+static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct ieee80211_ccmp_data *key = priv;
+	int data_len, i, blocks, last, len;
+	u8 *pos, *mic;
+	struct ieee80211_hdr_4addr *hdr;
+	u8 *b0 = key->tx_b0;
+	u8 *b = key->tx_b;
+	u8 *e = key->tx_e;
+	u8 *s0 = key->tx_s0;
+
+	if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
+		return -1;
+
+	data_len = skb->len - hdr_len;
+	len = ieee80211_ccmp_hdr(skb, hdr_len, priv);
+	if (len < 0)
+		return -1;
+
+	pos = skb->data + hdr_len + CCMP_HDR_LEN;
+	mic = skb_put(skb, CCMP_MIC_LEN);
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
 
 	blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
@@ -258,7 +274,7 @@
 {
 	struct ieee80211_ccmp_data *key = priv;
 	u8 keyidx, *pos;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u8 *b0 = key->rx_b0;
 	u8 *b = key->rx_b;
 	u8 *a = key->rx_a;
@@ -272,7 +288,7 @@
 		return -1;
 	}
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	pos = skb->data + hdr_len;
 	keyidx = pos[3];
 	if (!(keyidx & (1 << 5))) {
@@ -426,19 +442,20 @@
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
-	.name			= "CCMP",
-	.init			= ieee80211_ccmp_init,
-	.deinit			= ieee80211_ccmp_deinit,
-	.encrypt_mpdu		= ieee80211_ccmp_encrypt,
-	.decrypt_mpdu		= ieee80211_ccmp_decrypt,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= ieee80211_ccmp_set_key,
-	.get_key		= ieee80211_ccmp_get_key,
-	.print_stats		= ieee80211_ccmp_print_stats,
-	.extra_prefix_len	= CCMP_HDR_LEN,
-	.extra_postfix_len	= CCMP_MIC_LEN,
-	.owner			= THIS_MODULE,
+	.name = "CCMP",
+	.init = ieee80211_ccmp_init,
+	.deinit = ieee80211_ccmp_deinit,
+	.build_iv = ieee80211_ccmp_hdr,
+	.encrypt_mpdu = ieee80211_ccmp_encrypt,
+	.decrypt_mpdu = ieee80211_ccmp_decrypt,
+	.encrypt_msdu = NULL,
+	.decrypt_msdu = NULL,
+	.set_key = ieee80211_ccmp_set_key,
+	.get_key = ieee80211_ccmp_get_key,
+	.print_stats = ieee80211_ccmp_print_stats,
+	.extra_mpdu_prefix_len = CCMP_HDR_LEN,
+	.extra_mpdu_postfix_len = CCMP_MIC_LEN,
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_ccmp_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index d4f9164..2e34f29 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -59,8 +59,24 @@
 
 	/* scratch buffers for virt_to_page() (crypto API) */
 	u8 rx_hdr[16], tx_hdr[16];
+
+	unsigned long flags;
 };
 
+static unsigned long ieee80211_tkip_set_flags(unsigned long flags, void *priv)
+{
+	struct ieee80211_tkip_data *_priv = priv;
+	unsigned long old_flags = _priv->flags;
+	_priv->flags = flags;
+	return old_flags;
+}
+
+static unsigned long ieee80211_tkip_get_flags(void *priv)
+{
+	struct ieee80211_tkip_data *_priv = priv;
+	return _priv->flags;
+}
+
 static void *ieee80211_tkip_init(int key_idx)
 {
 	struct ieee80211_tkip_data *priv;
@@ -69,6 +85,7 @@
 	if (priv == NULL)
 		goto fail;
 	memset(priv, 0, sizeof(*priv));
+
 	priv->key_idx = key_idx;
 
 	priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
@@ -255,25 +272,27 @@
 #endif
 }
 
-static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+static u8 *ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct ieee80211_tkip_data *tkey = priv;
 	int len;
-	u8 rc4key[16], *pos, *icv;
-	struct ieee80211_hdr *hdr;
+	u8 *rc4key, *pos, *icv;
+	struct ieee80211_hdr_4addr *hdr;
 	u32 crc;
-	struct scatterlist sg;
 
-	if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
-	    skb->len < hdr_len)
-		return -1;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	if (skb_headroom(skb) < 8 || skb->len < hdr_len)
+		return NULL;
+
 	if (!tkey->tx_phase1_done) {
 		tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
 				   tkey->tx_iv32);
 		tkey->tx_phase1_done = 1;
 	}
+	rc4key = kmalloc(16, GFP_ATOMIC);
+	if (!rc4key)
+		return NULL;
 	tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
 
 	len = skb->len - hdr_len;
@@ -282,9 +301,9 @@
 	pos += hdr_len;
 	icv = skb_put(skb, 4);
 
-	*pos++ = rc4key[0];
-	*pos++ = rc4key[1];
-	*pos++ = rc4key[2];
+	*pos++ = *rc4key;
+	*pos++ = *(rc4key + 1);
+	*pos++ = *(rc4key + 2);
 	*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */ ;
 	*pos++ = tkey->tx_iv32 & 0xff;
 	*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
@@ -297,6 +316,38 @@
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
+	return rc4key;
+}
+
+static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct ieee80211_tkip_data *tkey = priv;
+	int len;
+	const u8 *rc4key;
+	u8 *pos;
+	struct scatterlist sg;
+
+	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
+		if (net_ratelimit()) {
+			struct ieee80211_hdr_4addr *hdr =
+			    (struct ieee80211_hdr_4addr *)skb->data;
+			printk(KERN_DEBUG "TKIP countermeasures: dropped "
+			       "TX packet to " MAC_FMT "\n",
+			       MAC_ARG(hdr->addr1));
+		}
+		return -1;
+	}
+
+	if (skb_tailroom(skb) < 4 || skb->len < hdr_len)
+		return -1;
+
+	len = skb->len - hdr_len;
+	pos = skb->data + hdr_len;
+
+	rc4key = ieee80211_tkip_hdr(skb, hdr_len, priv);
+	if (!rc4key)
+		return -1;
+
 	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
 	sg.page = virt_to_page(pos);
 	sg.offset = offset_in_page(pos);
@@ -319,16 +370,26 @@
 	u8 keyidx, *pos;
 	u32 iv32;
 	u16 iv16;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	u8 icv[4];
 	u32 crc;
 	struct scatterlist sg;
 	int plen;
 
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
+
+	if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "TKIP countermeasures: dropped "
+			       "received packet from " MAC_FMT "\n",
+			       MAC_ARG(hdr->addr2));
+		}
+		return -1;
+	}
+
 	if (skb->len < hdr_len + 8 + 4)
 		return -1;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
 	pos = skb->data + hdr_len;
 	keyidx = pos[3];
 	if (!(keyidx & (1 << 5))) {
@@ -441,9 +502,9 @@
 
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
-	struct ieee80211_hdr *hdr11;
+	struct ieee80211_hdr_4addr *hdr11;
 
-	hdr11 = (struct ieee80211_hdr *)skb->data;
+	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
 	switch (le16_to_cpu(hdr11->frame_ctl) &
 		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
 	case IEEE80211_FCTL_TODS:
@@ -490,9 +551,9 @@
 	return 0;
 }
 
-#if WIRELESS_EXT >= 18
 static void ieee80211_michael_mic_failure(struct net_device *dev,
-					  struct ieee80211_hdr *hdr, int keyidx)
+					  struct ieee80211_hdr_4addr *hdr,
+					  int keyidx)
 {
 	union iwreq_data wrqu;
 	struct iw_michaelmicfailure ev;
@@ -510,28 +571,6 @@
 	wrqu.data.length = sizeof(ev);
 	wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev);
 }
-#elif WIRELESS_EXT >= 15
-static void ieee80211_michael_mic_failure(struct net_device *dev,
-					  struct ieee80211_hdr *hdr, int keyidx)
-{
-	union iwreq_data wrqu;
-	char buf[128];
-
-	/* TODO: needed parameters: count, keyid, key type, TSC */
-	sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
-		MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
-		MAC_ARG(hdr->addr2));
-	memset(&wrqu, 0, sizeof(wrqu));
-	wrqu.data.length = strlen(buf);
-	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
-}
-#else				/* WIRELESS_EXT >= 15 */
-static inline void ieee80211_michael_mic_failure(struct net_device *dev,
-						 struct ieee80211_hdr *hdr,
-						 int keyidx)
-{
-}
-#endif				/* WIRELESS_EXT >= 15 */
 
 static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
 					int hdr_len, void *priv)
@@ -547,8 +586,8 @@
 			skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
 		return -1;
 	if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
-		struct ieee80211_hdr *hdr;
-		hdr = (struct ieee80211_hdr *)skb->data;
+		struct ieee80211_hdr_4addr *hdr;
+		hdr = (struct ieee80211_hdr_4addr *)skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
 		       "MSDU from " MAC_FMT " keyidx=%d\n",
 		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
@@ -654,19 +693,22 @@
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
-	.name			= "TKIP",
-	.init			= ieee80211_tkip_init,
-	.deinit			= ieee80211_tkip_deinit,
-	.encrypt_mpdu		= ieee80211_tkip_encrypt,
-	.decrypt_mpdu		= ieee80211_tkip_decrypt,
-	.encrypt_msdu		= ieee80211_michael_mic_add,
-	.decrypt_msdu		= ieee80211_michael_mic_verify,
-	.set_key		= ieee80211_tkip_set_key,
-	.get_key		= ieee80211_tkip_get_key,
-	.print_stats		= ieee80211_tkip_print_stats,
-	.extra_prefix_len	= 4 + 4,	/* IV + ExtIV */
-	.extra_postfix_len	= 8 + 4,	/* MIC + ICV */
-	.owner			= THIS_MODULE,
+	.name = "TKIP",
+	.init = ieee80211_tkip_init,
+	.deinit = ieee80211_tkip_deinit,
+	.encrypt_mpdu = ieee80211_tkip_encrypt,
+	.decrypt_mpdu = ieee80211_tkip_decrypt,
+	.encrypt_msdu = ieee80211_michael_mic_add,
+	.decrypt_msdu = ieee80211_michael_mic_verify,
+	.set_key = ieee80211_tkip_set_key,
+	.get_key = ieee80211_tkip_get_key,
+	.print_stats = ieee80211_tkip_print_stats,
+	.extra_mpdu_prefix_len = 4 + 4,	/* IV + ExtIV */
+	.extra_mpdu_postfix_len = 4,	/* ICV */
+	.extra_msdu_postfix_len = 8,	/* MIC */
+	.get_flags = ieee80211_tkip_get_flags,
+	.set_flags = ieee80211_tkip_set_flags,
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_tkip_init(void)
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index b4d2514..7c08ed2 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -229,19 +229,19 @@
 }
 
 static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
-	.name			= "WEP",
-	.init			= prism2_wep_init,
-	.deinit			= prism2_wep_deinit,
-	.encrypt_mpdu		= prism2_wep_encrypt,
-	.decrypt_mpdu		= prism2_wep_decrypt,
-	.encrypt_msdu		= NULL,
-	.decrypt_msdu		= NULL,
-	.set_key		= prism2_wep_set_key,
-	.get_key		= prism2_wep_get_key,
-	.print_stats		= prism2_wep_print_stats,
-	.extra_prefix_len	= 4,	/* IV */
-	.extra_postfix_len	= 4,	/* ICV */
-	.owner			= THIS_MODULE,
+	.name = "WEP",
+	.init = prism2_wep_init,
+	.deinit = prism2_wep_deinit,
+	.encrypt_mpdu = prism2_wep_encrypt,
+	.decrypt_mpdu = prism2_wep_decrypt,
+	.encrypt_msdu = NULL,
+	.decrypt_msdu = NULL,
+	.set_key = prism2_wep_set_key,
+	.get_key = prism2_wep_get_key,
+	.print_stats = prism2_wep_print_stats,
+	.extra_mpdu_prefix_len = 4,	/* IV */
+	.extra_mpdu_postfix_len = 4,	/* ICV */
+	.owner = THIS_MODULE,
 };
 
 static int __init ieee80211_crypto_wep_init(void)
diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c
new file mode 100644
index 0000000..c4b54ef
--- /dev/null
+++ b/net/ieee80211/ieee80211_geo.c
@@ -0,0 +1,141 @@
+/******************************************************************************
+
+  Copyright(c) 2005 Intel Corporation. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2 of the GNU General Public License as
+  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., 59
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin@linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+
+#include <net/ieee80211.h>
+
+int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
+{
+	int i;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+	if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+		for (i = 0; i < ieee->geo.bg_channels; i++)
+			/* NOTE: If G mode is currently supported but
+			 * this is a B only channel, we don't see it
+			 * as valid. */
+			if ((ieee->geo.bg[i].channel == channel) &&
+			    (!(ieee->mode & IEEE_G) ||
+			     !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
+				return IEEE80211_24GHZ_BAND;
+
+	if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+		for (i = 0; i < ieee->geo.a_channels; i++)
+			if (ieee->geo.a[i].channel == channel)
+				return IEEE80211_52GHZ_BAND;
+
+	return 0;
+}
+
+int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
+{
+	int i;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+	if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+		for (i = 0; i < ieee->geo.bg_channels; i++)
+			if (ieee->geo.bg[i].channel == channel)
+				return i;
+
+	if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+		for (i = 0; i < ieee->geo.a_channels; i++)
+			if (ieee->geo.a[i].channel == channel)
+				return i;
+
+	return -1;
+}
+
+u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
+{
+	int i;
+
+	/* Driver needs to initialize the geography map before using
+	 * these helper functions */
+	BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
+
+	freq /= 100000;
+
+	if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+		for (i = 0; i < ieee->geo.bg_channels; i++)
+			if (ieee->geo.bg[i].freq == freq)
+				return ieee->geo.bg[i].channel;
+
+	if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+		for (i = 0; i < ieee->geo.a_channels; i++)
+			if (ieee->geo.a[i].freq == freq)
+				return ieee->geo.a[i].channel;
+
+	return 0;
+}
+
+int ieee80211_set_geo(struct ieee80211_device *ieee,
+		      const struct ieee80211_geo *geo)
+{
+	memcpy(ieee->geo.name, geo->name, 3);
+	ieee->geo.name[3] = '\0';
+	ieee->geo.bg_channels = geo->bg_channels;
+	ieee->geo.a_channels = geo->a_channels;
+	memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
+	       sizeof(struct ieee80211_channel));
+	memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
+	       sizeof(struct ieee80211_channel));
+	return 0;
+}
+
+const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
+{
+	return &ieee->geo;
+}
+
+EXPORT_SYMBOL(ieee80211_is_valid_channel);
+EXPORT_SYMBOL(ieee80211_freq_to_channel);
+EXPORT_SYMBOL(ieee80211_channel_to_index);
+EXPORT_SYMBOL(ieee80211_set_geo);
+EXPORT_SYMBOL(ieee80211_get_geo);
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 6059e9e..f66d792 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -1,6 +1,6 @@
 /*******************************************************************************
 
-  Copyright(c) 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
 
   Portions of this file are based on the WEP enablement code provided by the
   Host AP project hostap-drivers v0.1.3
@@ -53,12 +53,15 @@
 
 #include <net/ieee80211.h>
 
-MODULE_DESCRIPTION("802.11 data/management/control stack");
-MODULE_AUTHOR
-    ("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
-MODULE_LICENSE("GPL");
+#define DRV_DESCRIPTION "802.11 data/management/control stack"
+#define DRV_NAME        "ieee80211"
+#define DRV_VERSION	IEEE80211_VERSION
+#define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
 
-#define DRV_NAME "ieee80211"
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
 
 static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
 {
@@ -126,26 +129,34 @@
 
 	/* Default fragmentation threshold is maximum payload size */
 	ieee->fts = DEFAULT_FTS;
+	ieee->rts = DEFAULT_FTS;
 	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
 	ieee->open_wep = 1;
 
 	/* Default to enabling full open WEP with host based encrypt/decrypt */
 	ieee->host_encrypt = 1;
 	ieee->host_decrypt = 1;
+	ieee->host_mc_decrypt = 1;
+
+	/* Host fragementation in Open mode. Default is enabled.
+	 * Note: host fragmentation is always enabled if host encryption
+	 * is enabled. For cards can do hardware encryption, they must do
+	 * hardware fragmentation as well. So we don't need a variable
+	 * like host_enc_frag. */
+	ieee->host_open_frag = 1;
 	ieee->ieee802_1x = 1;	/* Default to supporting 802.1x */
 
 	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
 	init_timer(&ieee->crypt_deinit_timer);
 	ieee->crypt_deinit_timer.data = (unsigned long)ieee;
 	ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
+	ieee->crypt_quiesced = 0;
 
 	spin_lock_init(&ieee->lock);
 
 	ieee->wpa_enabled = 0;
-	ieee->tkip_countermeasures = 0;
 	ieee->drop_unencrypted = 0;
 	ieee->privacy_invoked = 0;
-	ieee->ieee802_1x = 1;
 
 	return dev;
 
@@ -161,6 +172,7 @@
 
 	int i;
 
+	ieee80211_crypt_quiescing(ieee);
 	del_timer_sync(&ieee->crypt_deinit_timer);
 	ieee80211_crypt_deinit_entries(ieee, 1);
 
@@ -195,38 +207,26 @@
 static int store_debug_level(struct file *file, const char __user * buffer,
 			     unsigned long count, void *data)
 {
-	char buf[] = "0x00000000";
-	char *p = (char *)buf;
+	char buf[] = "0x00000000\n";
+	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
 	unsigned long val;
 
-	if (count > sizeof(buf) - 1)
-		count = sizeof(buf) - 1;
-
-	if (copy_from_user(buf, buffer, count))
+	if (copy_from_user(buf, buffer, len))
 		return count;
-	buf[count] = 0;
-	/*
-	 * what a FPOS...  What, sscanf(buf, "%i", &val) would be too
-	 * scary?
-	 */
-	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
-		p++;
-		if (p[0] == 'x' || p[0] == 'X')
-			p++;
-		val = simple_strtoul(p, &p, 16);
-	} else
-		val = simple_strtoul(p, &p, 10);
-	if (p == buf)
+	buf[len] = 0;
+	if (sscanf(buf, "%li", &val) != 1)
 		printk(KERN_INFO DRV_NAME
 		       ": %s is not in hex or decimal form.\n", buf);
 	else
 		ieee80211_debug_level = val;
 
-	return strlen(buf);
+	return strnlen(buf, len);
 }
+#endif				/* CONFIG_IEEE80211_DEBUG */
 
 static int __init ieee80211_init(void)
 {
+#ifdef CONFIG_IEEE80211_DEBUG
 	struct proc_dir_entry *e;
 
 	ieee80211_debug_level = debug;
@@ -246,26 +246,33 @@
 	e->read_proc = show_debug_level;
 	e->write_proc = store_debug_level;
 	e->data = NULL;
+#endif				/* CONFIG_IEEE80211_DEBUG */
+
+	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
 
 	return 0;
 }
 
 static void __exit ieee80211_exit(void)
 {
+#ifdef CONFIG_IEEE80211_DEBUG
 	if (ieee80211_proc) {
 		remove_proc_entry("debug_level", ieee80211_proc);
 		remove_proc_entry(DRV_NAME, proc_net);
 		ieee80211_proc = NULL;
 	}
+#endif				/* CONFIG_IEEE80211_DEBUG */
 }
 
+#ifdef CONFIG_IEEE80211_DEBUG
 #include <linux/moduleparam.h>
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
+#endif				/* CONFIG_IEEE80211_DEBUG */
 
 module_exit(ieee80211_exit);
 module_init(ieee80211_init);
-#endif
 
 const char *escape_essid(const char *essid, u8 essid_len)
 {
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index f7dcd85..ce694cf 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
  * <jkmaline@cc.hut.fi>
  * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- * Copyright (c) 2004, Intel Corporation
+ * Copyright (c) 2004-2005, Intel Corporation
  *
  * 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
@@ -87,7 +87,7 @@
 
 /* Called only as a tasklet (software IRQ) */
 static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
-						struct ieee80211_hdr *hdr)
+						struct ieee80211_hdr_4addr *hdr)
 {
 	struct sk_buff *skb = NULL;
 	u16 sc;
@@ -101,7 +101,7 @@
 	if (frag == 0) {
 		/* Reserve enough space to fit maximum frame length */
 		skb = dev_alloc_skb(ieee->dev->mtu +
-				    sizeof(struct ieee80211_hdr) +
+				    sizeof(struct ieee80211_hdr_4addr) +
 				    8 /* LLC */  +
 				    2 /* alignment */  +
 				    8 /* WEP */  + ETH_ALEN /* WDS */ );
@@ -138,7 +138,7 @@
 
 /* Called only as a tasklet (software IRQ) */
 static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
-					   struct ieee80211_hdr *hdr)
+					   struct ieee80211_hdr_4addr *hdr)
 {
 	u16 sc;
 	unsigned int seq;
@@ -176,7 +176,7 @@
 		       ieee->dev->name);
 		return 0;
 /*
-  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *)
+  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
   skb->data);*/
 	}
 
@@ -232,13 +232,13 @@
 {
 	struct net_device *dev = ieee->dev;
 	u16 fc, ethertype;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 	u8 *pos;
 
 	if (skb->len < 24)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_3addr *)skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	/* check that the frame is unicast frame to us */
@@ -271,26 +271,15 @@
 ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
 			   struct ieee80211_crypt_data *crypt)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 	int res, hdrlen;
 
 	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_3addr *)skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(hdr->addr2));
-		}
-		return -1;
-	}
-#endif
-
 	atomic_inc(&crypt->refcnt);
 	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
 	atomic_dec(&crypt->refcnt);
@@ -314,13 +303,13 @@
 				struct sk_buff *skb, int keyidx,
 				struct ieee80211_crypt_data *crypt)
 {
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_3addr *hdr;
 	int res, hdrlen;
 
 	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
 		return 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_3addr *)skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
 	atomic_inc(&crypt->refcnt);
@@ -343,7 +332,7 @@
 		 struct ieee80211_rx_stats *rx_stats)
 {
 	struct net_device *dev = ieee->dev;
-	struct ieee80211_hdr *hdr;
+	struct ieee80211_hdr_4addr *hdr;
 	size_t hdrlen;
 	u16 fc, type, stype, sc;
 	struct net_device_stats *stats;
@@ -363,7 +352,7 @@
 	struct ieee80211_crypt_data *crypt = NULL;
 	int keyidx = 0;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	stats = &ieee->stats;
 
 	if (skb->len < 10) {
@@ -378,35 +367,51 @@
 	frag = WLAN_GET_SEQ_FRAG(sc);
 	hdrlen = ieee80211_get_hdrlen(fc);
 
-#ifdef NOT_YET
-#if WIRELESS_EXT > 15
 	/* Put this code here so that we avoid duplicating it in all
 	 * Rx paths. - Jean II */
 #ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
 	/* If spy monitoring on */
-	if (iface->spy_data.spy_number > 0) {
+	if (ieee->spy_data.spy_number > 0) {
 		struct iw_quality wstats;
-		wstats.level = rx_stats->signal;
-		wstats.noise = rx_stats->noise;
-		wstats.updated = 6;	/* No qual value */
+
+		wstats.updated = 0;
+		if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
+			wstats.level = rx_stats->rssi;
+			wstats.updated |= IW_QUAL_LEVEL_UPDATED;
+		} else
+			wstats.updated |= IW_QUAL_LEVEL_INVALID;
+
+		if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
+			wstats.noise = rx_stats->noise;
+			wstats.updated |= IW_QUAL_NOISE_UPDATED;
+		} else
+			wstats.updated |= IW_QUAL_NOISE_INVALID;
+
+		if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
+			wstats.qual = rx_stats->signal;
+			wstats.updated |= IW_QUAL_QUAL_UPDATED;
+		} else
+			wstats.updated |= IW_QUAL_QUAL_INVALID;
+
 		/* Update spy records */
-		wireless_spy_update(dev, hdr->addr2, &wstats);
+		wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
 	}
 #endif				/* IW_WIRELESS_SPY */
-#endif				/* WIRELESS_EXT > 15 */
+
+#ifdef NOT_YET
 	hostap_update_rx_stats(local->ap, hdr, rx_stats);
 #endif
 
-#if WIRELESS_EXT > 15
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
 		ieee80211_monitor_rx(ieee, skb, rx_stats);
 		stats->rx_packets++;
 		stats->rx_bytes += skb->len;
 		return 1;
 	}
-#endif
 
-	if (ieee->host_decrypt) {
+	if ((is_multicast_ether_addr(hdr->addr1) ||
+	     is_broadcast_ether_addr(hdr->addr2)) ? ieee->host_mc_decrypt :
+	    ieee->host_decrypt) {
 		int idx = 0;
 		if (skb->len >= hdrlen + 3)
 			idx = skb->data[hdrlen + 3] >> 6;
@@ -531,6 +536,9 @@
 
 	/* Nullfunc frames may have PS-bit set, so they must be passed to
 	 * hostap_handle_sta_rx() before being dropped here. */
+
+	stype &= ~IEEE80211_STYPE_QOS_DATA;
+
 	if (stype != IEEE80211_STYPE_DATA &&
 	    stype != IEEE80211_STYPE_DATA_CFACK &&
 	    stype != IEEE80211_STYPE_DATA_CFPOLL &&
@@ -549,7 +557,7 @@
 	    (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
 		goto rx_dropped;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 
 	/* skb: hdr + (possibly fragmented) plaintext payload */
 	// PR: FIXME: hostap has additional conditions in the "if" below:
@@ -603,7 +611,7 @@
 		/* this was the last fragment and the frame will be
 		 * delivered, so remove skb from fragment cache */
 		skb = frag_skb;
-		hdr = (struct ieee80211_hdr *)skb->data;
+		hdr = (struct ieee80211_hdr_4addr *)skb->data;
 		ieee80211_frag_cache_invalidate(ieee, hdr);
 	}
 
@@ -613,7 +621,7 @@
 	    ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
 		goto rx_dropped;
 
-	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
 		if (		/*ieee->ieee802_1x && */
 			   ieee80211_is_eapol_frame(ieee, skb)) {
@@ -755,69 +763,179 @@
 
 #define MGMT_FRAME_FIXED_PART_LENGTH		0x24
 
-static inline int ieee80211_is_ofdm_rate(u8 rate)
+static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
+
+/*
+* Make ther structure we read from the beacon packet has
+* the right values
+*/
+static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
+				     *info_element, int sub_type)
 {
-	switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
-	case IEEE80211_OFDM_RATE_6MB:
-	case IEEE80211_OFDM_RATE_9MB:
-	case IEEE80211_OFDM_RATE_12MB:
-	case IEEE80211_OFDM_RATE_18MB:
-	case IEEE80211_OFDM_RATE_24MB:
-	case IEEE80211_OFDM_RATE_36MB:
-	case IEEE80211_OFDM_RATE_48MB:
-	case IEEE80211_OFDM_RATE_54MB:
-		return 1;
-	}
+
+	if (info_element->qui_subtype != sub_type)
+		return -1;
+	if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
+		return -1;
+	if (info_element->qui_type != QOS_OUI_TYPE)
+		return -1;
+	if (info_element->version != QOS_VERSION_1)
+		return -1;
+
 	return 0;
 }
 
-static inline int ieee80211_network_init(struct ieee80211_device *ieee,
-					 struct ieee80211_probe_response
-					 *beacon,
-					 struct ieee80211_network *network,
-					 struct ieee80211_rx_stats *stats)
+/*
+ * Parse a QoS parameter element
+ */
+static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
+					    *element_param, struct ieee80211_info_element
+					    *info_element)
 {
+	int ret = 0;
+	u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
+
+	if ((info_element == NULL) || (element_param == NULL))
+		return -1;
+
+	if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
+		memcpy(element_param->info_element.qui, info_element->data,
+		       info_element->len);
+		element_param->info_element.elementID = info_element->id;
+		element_param->info_element.length = info_element->len;
+	} else
+		ret = -1;
+	if (ret == 0)
+		ret = ieee80211_verify_qos_info(&element_param->info_element,
+						QOS_OUI_PARAM_SUB_TYPE);
+	return ret;
+}
+
+/*
+ * Parse a QoS information element
+ */
+static int ieee80211_read_qos_info_element(struct
+					   ieee80211_qos_information_element
+					   *element_info, struct ieee80211_info_element
+					   *info_element)
+{
+	int ret = 0;
+	u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
+
+	if (element_info == NULL)
+		return -1;
+	if (info_element == NULL)
+		return -1;
+
+	if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
+		memcpy(element_info->qui, info_element->data,
+		       info_element->len);
+		element_info->elementID = info_element->id;
+		element_info->length = info_element->len;
+	} else
+		ret = -1;
+
+	if (ret == 0)
+		ret = ieee80211_verify_qos_info(element_info,
+						QOS_OUI_INFO_SUB_TYPE);
+	return ret;
+}
+
+/*
+ * Write QoS parameters from the ac parameters.
+ */
+static int ieee80211_qos_convert_ac_to_parameters(struct
+						  ieee80211_qos_parameter_info
+						  *param_elm, struct
+						  ieee80211_qos_parameters
+						  *qos_param)
+{
+	int rc = 0;
+	int i;
+	struct ieee80211_qos_ac_parameter *ac_params;
+	u32 txop;
+	u8 cw_min;
+	u8 cw_max;
+
+	for (i = 0; i < QOS_QUEUE_NUM; i++) {
+		ac_params = &(param_elm->ac_params_record[i]);
+
+		qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
+		qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
+
+		cw_min = ac_params->ecw_min_max & 0x0F;
+		qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);
+
+		cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
+		qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);
+
+		qos_param->flag[i] =
+		    (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
+
+		txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
+		qos_param->tx_op_limit[i] = (u16) txop;
+	}
+	return rc;
+}
+
+/*
+ * we have a generic data element which it may contain QoS information or
+ * parameters element. check the information element length to decide
+ * which type to read
+ */
+static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
+					     *info_element,
+					     struct ieee80211_network *network)
+{
+	int rc = 0;
+	struct ieee80211_qos_parameters *qos_param = NULL;
+	struct ieee80211_qos_information_element qos_info_element;
+
+	rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
+
+	if (rc == 0) {
+		network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
+		network->flags |= NETWORK_HAS_QOS_INFORMATION;
+	} else {
+		struct ieee80211_qos_parameter_info param_element;
+
+		rc = ieee80211_read_qos_param_element(&param_element,
+						      info_element);
+		if (rc == 0) {
+			qos_param = &(network->qos_data.parameters);
+			ieee80211_qos_convert_ac_to_parameters(&param_element,
+							       qos_param);
+			network->flags |= NETWORK_HAS_QOS_PARAMETERS;
+			network->qos_data.param_count =
+			    param_element.info_element.ac_info & 0x0F;
+		}
+	}
+
+	if (rc == 0) {
+		IEEE80211_DEBUG_QOS("QoS is supported\n");
+		network->qos_data.supported = 1;
+	}
+	return rc;
+}
+
+static int ieee80211_parse_info_param(struct ieee80211_info_element
+				      *info_element, u16 length,
+				      struct ieee80211_network *network)
+{
+	u8 i;
 #ifdef CONFIG_IEEE80211_DEBUG
 	char rates_str[64];
 	char *p;
 #endif
-	struct ieee80211_info_element *info_element;
-	u16 left;
-	u8 i;
 
-	/* Pull out fixed field data */
-	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
-	network->capability = beacon->capability;
-	network->last_scanned = jiffies;
-	network->time_stamp[0] = beacon->time_stamp[0];
-	network->time_stamp[1] = beacon->time_stamp[1];
-	network->beacon_interval = beacon->beacon_interval;
-	/* Where to pull this? beacon->listen_interval; */
-	network->listen_interval = 0x0A;
-	network->rates_len = network->rates_ex_len = 0;
-	network->last_associate = 0;
-	network->ssid_len = 0;
-	network->flags = 0;
-	network->atim_window = 0;
-
-	if (stats->freq == IEEE80211_52GHZ_BAND) {
-		/* for A band (No DS info) */
-		network->channel = stats->received_channel;
-	} else
-		network->flags |= NETWORK_HAS_CCK;
-
-	network->wpa_ie_len = 0;
-	network->rsn_ie_len = 0;
-
-	info_element = &beacon->info_element;
-	left = stats->len - ((void *)info_element - (void *)beacon);
-	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
-		if (sizeof(struct ieee80211_info_element_hdr) +
-		    info_element->len > left) {
-			IEEE80211_DEBUG_SCAN
-			    ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
-			     info_element->len +
-			     sizeof(struct ieee80211_info_element), left);
+	while (length >= sizeof(*info_element)) {
+		if (sizeof(*info_element) + info_element->len > length) {
+			IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
+					     "info_element->len + 2 > left : "
+					     "info_element->len+2=%zd left=%d, id=%d.\n",
+					     info_element->len +
+					     sizeof(*info_element),
+					     length, info_element->id);
 			return 1;
 		}
 
@@ -837,7 +955,7 @@
 				memset(network->ssid + network->ssid_len, 0,
 				       IW_ESSID_MAX_SIZE - network->ssid_len);
 
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
 					     network->ssid, network->ssid_len);
 			break;
 
@@ -845,15 +963,14 @@
 #ifdef CONFIG_IEEE80211_DEBUG
 			p = rates_str;
 #endif
-			network->rates_len =
-			    min(info_element->len, MAX_RATES_LENGTH);
+			network->rates_len = min(info_element->len,
+						 MAX_RATES_LENGTH);
 			for (i = 0; i < network->rates_len; i++) {
 				network->rates[i] = info_element->data[i];
 #ifdef CONFIG_IEEE80211_DEBUG
-				p += snprintf(p,
-					      sizeof(rates_str) - (p -
-								   rates_str),
-					      "%02X ", network->rates[i]);
+				p += snprintf(p, sizeof(rates_str) -
+					      (p - rates_str), "%02X ",
+					      network->rates[i]);
 #endif
 				if (ieee80211_is_ofdm_rate
 				    (info_element->data[i])) {
@@ -865,7 +982,7 @@
 				}
 			}
 
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
 					     rates_str, network->rates_len);
 			break;
 
@@ -873,15 +990,14 @@
 #ifdef CONFIG_IEEE80211_DEBUG
 			p = rates_str;
 #endif
-			network->rates_ex_len =
-			    min(info_element->len, MAX_RATES_EX_LENGTH);
+			network->rates_ex_len = min(info_element->len,
+						    MAX_RATES_EX_LENGTH);
 			for (i = 0; i < network->rates_ex_len; i++) {
 				network->rates_ex[i] = info_element->data[i];
 #ifdef CONFIG_IEEE80211_DEBUG
-				p += snprintf(p,
-					      sizeof(rates_str) - (p -
-								   rates_str),
-					      "%02X ", network->rates[i]);
+				p += snprintf(p, sizeof(rates_str) -
+					      (p - rates_str), "%02X ",
+					      network->rates[i]);
 #endif
 				if (ieee80211_is_ofdm_rate
 				    (info_element->data[i])) {
@@ -893,40 +1009,51 @@
 				}
 			}
 
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
 					     rates_str, network->rates_ex_len);
 			break;
 
 		case MFIE_TYPE_DS_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
 					     info_element->data[0]);
-			if (stats->freq == IEEE80211_24GHZ_BAND)
-				network->channel = info_element->data[0];
+			network->channel = info_element->data[0];
 			break;
 
 		case MFIE_TYPE_FH_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
 			break;
 
 		case MFIE_TYPE_CF_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
 			break;
 
 		case MFIE_TYPE_TIM:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
+			break;
+
+		case MFIE_TYPE_ERP_INFO:
+			network->erp_value = info_element->data[0];
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
+					     network->erp_value);
 			break;
 
 		case MFIE_TYPE_IBSS_SET:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
+			network->atim_window = info_element->data[0];
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
+					     network->atim_window);
 			break;
 
 		case MFIE_TYPE_CHALLENGE:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
 			break;
 
 		case MFIE_TYPE_GENERIC:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
 					     info_element->len);
+			if (!ieee80211_parse_qos_info_param_IE(info_element,
+							       network))
+				break;
+
 			if (info_element->len >= 4 &&
 			    info_element->data[0] == 0x00 &&
 			    info_element->data[1] == 0x50 &&
@@ -940,7 +1067,7 @@
 			break;
 
 		case MFIE_TYPE_RSN:
-			IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
+			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
 					     info_element->len);
 			network->rsn_ie_len = min(info_element->len + 2,
 						  MAX_WPA_IE_LEN);
@@ -948,18 +1075,127 @@
 			       network->rsn_ie_len);
 			break;
 
+		case MFIE_TYPE_QOS_PARAMETER:
+			printk(KERN_ERR
+			       "QoS Error need to parse QOS_PARAMETER IE\n");
+			break;
+
 		default:
-			IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
+			IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
 					     info_element->id);
 			break;
 		}
 
-		left -= sizeof(struct ieee80211_info_element_hdr) +
-		    info_element->len;
-		info_element = (struct ieee80211_info_element *)
-		    &info_element->data[info_element->len];
+		length -= sizeof(*info_element) + info_element->len;
+		info_element =
+		    (struct ieee80211_info_element *)&info_element->
+		    data[info_element->len];
 	}
 
+	return 0;
+}
+
+static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
+				       *frame, struct ieee80211_rx_stats *stats)
+{
+	struct ieee80211_network network_resp;
+	struct ieee80211_network *network = &network_resp;
+	struct net_device *dev = ieee->dev;
+
+	network->flags = 0;
+	network->qos_data.active = 0;
+	network->qos_data.supported = 0;
+	network->qos_data.param_count = 0;
+	network->qos_data.old_param_count = 0;
+
+	//network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
+	network->atim_window = le16_to_cpu(frame->aid);
+	network->listen_interval = le16_to_cpu(frame->status);
+	memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
+	network->capability = le16_to_cpu(frame->capability);
+	network->last_scanned = jiffies;
+	network->rates_len = network->rates_ex_len = 0;
+	network->last_associate = 0;
+	network->ssid_len = 0;
+	network->erp_value =
+	    (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
+
+	if (stats->freq == IEEE80211_52GHZ_BAND) {
+		/* for A band (No DS info) */
+		network->channel = stats->received_channel;
+	} else
+		network->flags |= NETWORK_HAS_CCK;
+
+	network->wpa_ie_len = 0;
+	network->rsn_ie_len = 0;
+
+	if (ieee80211_parse_info_param
+	    (frame->info_element, stats->len - sizeof(*frame), network))
+		return 1;
+
+	network->mode = 0;
+	if (stats->freq == IEEE80211_52GHZ_BAND)
+		network->mode = IEEE_A;
+	else {
+		if (network->flags & NETWORK_HAS_OFDM)
+			network->mode |= IEEE_G;
+		if (network->flags & NETWORK_HAS_CCK)
+			network->mode |= IEEE_B;
+	}
+
+	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
+		network->flags |= NETWORK_EMPTY_ESSID;
+
+	memcpy(&network->stats, stats, sizeof(network->stats));
+
+	if (ieee->handle_assoc_response != NULL)
+		ieee->handle_assoc_response(dev, frame, network);
+
+	return 0;
+}
+
+/***************************************************/
+
+static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
+					 *beacon,
+					 struct ieee80211_network *network,
+					 struct ieee80211_rx_stats *stats)
+{
+	network->qos_data.active = 0;
+	network->qos_data.supported = 0;
+	network->qos_data.param_count = 0;
+	network->qos_data.old_param_count = 0;
+
+	/* Pull out fixed field data */
+	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+	network->capability = le16_to_cpu(beacon->capability);
+	network->last_scanned = jiffies;
+	network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
+	network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
+	network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
+	/* Where to pull this? beacon->listen_interval; */
+	network->listen_interval = 0x0A;
+	network->rates_len = network->rates_ex_len = 0;
+	network->last_associate = 0;
+	network->ssid_len = 0;
+	network->flags = 0;
+	network->atim_window = 0;
+	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+	    0x3 : 0x0;
+
+	if (stats->freq == IEEE80211_52GHZ_BAND) {
+		/* for A band (No DS info) */
+		network->channel = stats->received_channel;
+	} else
+		network->flags |= NETWORK_HAS_CCK;
+
+	network->wpa_ie_len = 0;
+	network->rsn_ie_len = 0;
+
+	if (ieee80211_parse_info_param
+	    (beacon->info_element, stats->len - sizeof(*beacon), network))
+		return 1;
+
 	network->mode = 0;
 	if (stats->freq == IEEE80211_52GHZ_BAND)
 		network->mode = IEEE_A;
@@ -1002,6 +1238,9 @@
 static inline void update_network(struct ieee80211_network *dst,
 				  struct ieee80211_network *src)
 {
+	int qos_active;
+	u8 old_param;
+
 	memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
 	dst->capability = src->capability;
 	memcpy(dst->rates, src->rates, src->rates_len);
@@ -1017,6 +1256,7 @@
 	dst->beacon_interval = src->beacon_interval;
 	dst->listen_interval = src->listen_interval;
 	dst->atim_window = src->atim_window;
+	dst->erp_value = src->erp_value;
 
 	memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
 	dst->wpa_ie_len = src->wpa_ie_len;
@@ -1024,22 +1264,48 @@
 	dst->rsn_ie_len = src->rsn_ie_len;
 
 	dst->last_scanned = jiffies;
+	qos_active = src->qos_data.active;
+	old_param = dst->qos_data.old_param_count;
+	if (dst->flags & NETWORK_HAS_QOS_MASK)
+		memcpy(&dst->qos_data, &src->qos_data,
+		       sizeof(struct ieee80211_qos_data));
+	else {
+		dst->qos_data.supported = src->qos_data.supported;
+		dst->qos_data.param_count = src->qos_data.param_count;
+	}
+
+	if (dst->qos_data.supported == 1) {
+		if (dst->ssid_len)
+			IEEE80211_DEBUG_QOS
+			    ("QoS the network %s is QoS supported\n",
+			     dst->ssid);
+		else
+			IEEE80211_DEBUG_QOS
+			    ("QoS the network is QoS supported\n");
+	}
+	dst->qos_data.active = qos_active;
+	dst->qos_data.old_param_count = old_param;
+
 	/* dst->last_associate is not overwritten */
 }
 
+static inline int is_beacon(int fc)
+{
+	return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
+}
+
 static inline void ieee80211_process_probe_response(struct ieee80211_device
-						    *ieee,
-						    struct
+						    *ieee, struct
 						    ieee80211_probe_response
-						    *beacon,
-						    struct ieee80211_rx_stats
+						    *beacon, struct ieee80211_rx_stats
 						    *stats)
 {
+	struct net_device *dev = ieee->dev;
 	struct ieee80211_network network;
 	struct ieee80211_network *target;
 	struct ieee80211_network *oldest = NULL;
 #ifdef CONFIG_IEEE80211_DEBUG
-	struct ieee80211_info_element *info_element = &beacon->info_element;
+	struct ieee80211_info_element *info_element = beacon->info_element;
 #endif
 	unsigned long flags;
 
@@ -1070,10 +1336,10 @@
 				     escape_essid(info_element->data,
 						  info_element->len),
 				     MAC_ARG(beacon->header.addr3),
-				     WLAN_FC_GET_STYPE(beacon->header.
-						       frame_ctl) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
+				     is_beacon(le16_to_cpu
+					       (beacon->header.
+						frame_ctl)) ?
+				     "BEACON" : "PROBE RESPONSE");
 		return;
 	}
 
@@ -1122,10 +1388,10 @@
 				     escape_essid(network.ssid,
 						  network.ssid_len),
 				     MAC_ARG(network.bssid),
-				     WLAN_FC_GET_STYPE(beacon->header.
-						       frame_ctl) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
+				     is_beacon(le16_to_cpu
+					       (beacon->header.
+						frame_ctl)) ?
+				     "BEACON" : "PROBE RESPONSE");
 #endif
 		memcpy(target, &network, sizeof(*target));
 		list_add_tail(&target->list, &ieee->network_list);
@@ -1134,34 +1400,60 @@
 				     escape_essid(target->ssid,
 						  target->ssid_len),
 				     MAC_ARG(target->bssid),
-				     WLAN_FC_GET_STYPE(beacon->header.
-						       frame_ctl) ==
-				     IEEE80211_STYPE_PROBE_RESP ?
-				     "PROBE RESPONSE" : "BEACON");
+				     is_beacon(le16_to_cpu
+					       (beacon->header.
+						frame_ctl)) ?
+				     "BEACON" : "PROBE RESPONSE");
 		update_network(target, &network);
 	}
 
 	spin_unlock_irqrestore(&ieee->lock, flags);
+
+	if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
+		if (ieee->handle_beacon != NULL)
+			ieee->handle_beacon(dev, beacon, &network);
+	} else {
+		if (ieee->handle_probe_response != NULL)
+			ieee->handle_probe_response(dev, beacon, &network);
+	}
 }
 
 void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-		      struct ieee80211_hdr *header,
+		      struct ieee80211_hdr_4addr *header,
 		      struct ieee80211_rx_stats *stats)
 {
-	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+	switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
 	case IEEE80211_STYPE_ASSOC_RESP:
 		IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
+		ieee80211_handle_assoc_resp(ieee,
+					    (struct ieee80211_assoc_response *)
+					    header, stats);
 		break;
 
 	case IEEE80211_STYPE_REASSOC_RESP:
 		IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
+		break;
+
+	case IEEE80211_STYPE_PROBE_REQ:
+		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
+
+		if (ieee->handle_probe_request != NULL)
+			ieee->handle_probe_request(ieee->dev,
+						   (struct
+						    ieee80211_probe_request *)
+						   header, stats);
 		break;
 
 	case IEEE80211_STYPE_PROBE_RESP:
 		IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		IEEE80211_DEBUG_SCAN("Probe response\n");
 		ieee80211_process_probe_response(ieee,
 						 (struct
@@ -1171,20 +1463,46 @@
 
 	case IEEE80211_STYPE_BEACON:
 		IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		IEEE80211_DEBUG_SCAN("Beacon\n");
 		ieee80211_process_probe_response(ieee,
 						 (struct
 						  ieee80211_probe_response *)
 						 header, stats);
 		break;
+	case IEEE80211_STYPE_AUTH:
 
+		IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
+
+		if (ieee->handle_auth != NULL)
+			ieee->handle_auth(ieee->dev,
+					  (struct ieee80211_auth *)header);
+		break;
+
+	case IEEE80211_STYPE_DISASSOC:
+		if (ieee->handle_disassoc != NULL)
+			ieee->handle_disassoc(ieee->dev,
+					      (struct ieee80211_disassoc *)
+					      header);
+		break;
+
+	case IEEE80211_STYPE_DEAUTH:
+		printk("DEAUTH from AP\n");
+		if (ieee->handle_deauth != NULL)
+			ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
+					    header);
+		break;
 	default:
 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
-				     WLAN_FC_GET_STYPE(header->frame_ctl));
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		IEEE80211_WARNING("%s: Unknown management packet: %d\n",
 				  ieee->dev->name,
-				  WLAN_FC_GET_STYPE(header->frame_ctl));
+				  WLAN_FC_GET_STYPE(le16_to_cpu
+						    (header->frame_ctl)));
 		break;
 	}
 }
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index eed07bb..95ccbad 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License as
@@ -128,7 +128,7 @@
 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
 static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
 
-static inline int ieee80211_put_snap(u8 * data, u16 h_proto)
+static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
 {
 	struct ieee80211_snap_hdr *snap;
 	u8 *oui;
@@ -157,31 +157,14 @@
 	struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
 	int res;
 
-#ifdef CONFIG_IEEE80211_CRYPT_TKIP
-	struct ieee80211_hdr *header;
-
-	if (ieee->tkip_countermeasures &&
-	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
-		header = (struct ieee80211_hdr *)frag->data;
-		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(header->addr1));
-		}
+	if (crypt == NULL)
 		return -1;
-	}
-#endif
+
 	/* To encrypt, frame format is:
 	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
-
-	// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
-	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
-	 * call both MSDU and MPDU encryption functions from here. */
 	atomic_inc(&crypt->refcnt);
 	res = 0;
-	if (crypt->ops->encrypt_msdu)
-		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
-	if (res == 0 && crypt->ops->encrypt_mpdu)
+	if (crypt->ops && crypt->ops->encrypt_mpdu)
 		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
 
 	atomic_dec(&crypt->refcnt);
@@ -207,7 +190,7 @@
 }
 
 static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
-						 gfp_t gfp_mask)
+						 int headroom, gfp_t gfp_mask)
 {
 	struct ieee80211_txb *txb;
 	int i;
@@ -221,11 +204,13 @@
 	txb->frag_size = txb_size;
 
 	for (i = 0; i < nr_frags; i++) {
-		txb->fragments[i] = dev_alloc_skb(txb_size);
+		txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
+						    gfp_mask);
 		if (unlikely(!txb->fragments[i])) {
 			i--;
 			break;
 		}
+		skb_reserve(txb->fragments[i], headroom);
 	}
 	if (unlikely(i != nr_frags)) {
 		while (i >= 0)
@@ -236,25 +221,31 @@
 	return txb;
 }
 
-/* SKBs are added to the ieee->tx_queue. */
+/* Incoming skb is converted to a txb which consists of
+ * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	struct ieee80211_txb *txb = NULL;
-	struct ieee80211_hdr *frag_hdr;
-	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
+	struct ieee80211_hdr_3addr *frag_hdr;
+	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
+	    rts_required;
 	unsigned long flags;
 	struct net_device_stats *stats = &ieee->stats;
-	int ether_type, encrypt;
+	int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
-	struct ieee80211_hdr header = {	/* Ensure zero initialized */
+	struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
 		.duration_id = 0,
 		.seq_ctl = 0
 	};
 	u8 dest[ETH_ALEN], src[ETH_ALEN];
-
 	struct ieee80211_crypt_data *crypt;
+	int priority = skb->priority;
+	int snapped = 0;
+
+	if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
+		return NETDEV_TX_BUSY;
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
@@ -276,7 +267,11 @@
 	crypt = ieee->crypt[ieee->tx_keyidx];
 
 	encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
-	    ieee->host_encrypt && crypt && crypt->ops;
+	    ieee->sec.encrypt;
+
+	host_encrypt = ieee->host_encrypt && encrypt && crypt;
+	host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
+	host_build_iv = ieee->host_build_iv && encrypt && crypt;
 
 	if (!encrypt && ieee->ieee802_1x &&
 	    ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
@@ -285,8 +280,8 @@
 	}
 
 	/* Save source and destination addresses */
-	memcpy(&dest, skb->data, ETH_ALEN);
-	memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN);
+	memcpy(dest, skb->data, ETH_ALEN);
+	memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
 
 	/* Advance the SKB to the start of the payload */
 	skb_pull(skb, sizeof(struct ethhdr));
@@ -294,7 +289,7 @@
 	/* Determine total amount of storage required for TXB packets */
 	bytes = skb->len + SNAP_SIZE + sizeof(u16);
 
-	if (encrypt)
+	if (host_encrypt)
 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
 		    IEEE80211_FCTL_PROTECTED;
 	else
@@ -302,70 +297,144 @@
 
 	if (ieee->iw_mode == IW_MODE_INFRA) {
 		fc |= IEEE80211_FCTL_TODS;
-		/* To DS: Addr1 = BSSID, Addr2 = SA,
-		   Addr3 = DA */
-		memcpy(&header.addr1, ieee->bssid, ETH_ALEN);
-		memcpy(&header.addr2, &src, ETH_ALEN);
-		memcpy(&header.addr3, &dest, ETH_ALEN);
+		/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
+		memcpy(header.addr1, ieee->bssid, ETH_ALEN);
+		memcpy(header.addr2, src, ETH_ALEN);
+		memcpy(header.addr3, dest, ETH_ALEN);
 	} else if (ieee->iw_mode == IW_MODE_ADHOC) {
-		/* not From/To DS: Addr1 = DA, Addr2 = SA,
-		   Addr3 = BSSID */
-		memcpy(&header.addr1, dest, ETH_ALEN);
-		memcpy(&header.addr2, src, ETH_ALEN);
-		memcpy(&header.addr3, ieee->bssid, ETH_ALEN);
+		/* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
+		memcpy(header.addr1, dest, ETH_ALEN);
+		memcpy(header.addr2, src, ETH_ALEN);
+		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
 	}
 	header.frame_ctl = cpu_to_le16(fc);
 	hdr_len = IEEE80211_3ADDR_LEN;
 
-	/* Determine fragmentation size based on destination (multicast
-	 * and broadcast are not fragmented) */
-	if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest))
-		frag_size = MAX_FRAG_THRESHOLD;
-	else
-		frag_size = ieee->fts;
+	/* Encrypt msdu first on the whole data packet. */
+	if ((host_encrypt || host_encrypt_msdu) &&
+	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
+		int res = 0;
+		int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
+		    crypt->ops->extra_msdu_postfix_len;
+		struct sk_buff *skb_new = dev_alloc_skb(len);
 
-	/* Determine amount of payload per fragment.  Regardless of if
-	 * this stack is providing the full 802.11 header, one will
-	 * eventually be affixed to this fragment -- so we must account for
-	 * it when determining the amount of payload space. */
-	bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
-	if (ieee->config &
-	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
-		bytes_per_frag -= IEEE80211_FCS_LEN;
+		if (unlikely(!skb_new))
+			goto failed;
 
-	/* Each fragment may need to have room for encryptiong pre/postfix */
-	if (encrypt)
-		bytes_per_frag -= crypt->ops->extra_prefix_len +
-		    crypt->ops->extra_postfix_len;
+		skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
+		memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
+		snapped = 1;
+		ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
+				    ether_type);
+		memcpy(skb_put(skb_new, skb->len), skb->data, skb->len);
+		res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
+		if (res < 0) {
+			IEEE80211_ERROR("msdu encryption failed\n");
+			dev_kfree_skb_any(skb_new);
+			goto failed;
+		}
+		dev_kfree_skb_any(skb);
+		skb = skb_new;
+		bytes += crypt->ops->extra_msdu_prefix_len +
+		    crypt->ops->extra_msdu_postfix_len;
+		skb_pull(skb, hdr_len);
+	}
 
-	/* Number of fragments is the total bytes_per_frag /
-	 * payload_per_fragment */
-	nr_frags = bytes / bytes_per_frag;
-	bytes_last_frag = bytes % bytes_per_frag;
-	if (bytes_last_frag)
+	if (host_encrypt || ieee->host_open_frag) {
+		/* Determine fragmentation size based on destination (multicast
+		 * and broadcast are not fragmented) */
+		if (is_multicast_ether_addr(dest) ||
+		    is_broadcast_ether_addr(dest))
+			frag_size = MAX_FRAG_THRESHOLD;
+		else
+			frag_size = ieee->fts;
+
+		/* Determine amount of payload per fragment.  Regardless of if
+		 * this stack is providing the full 802.11 header, one will
+		 * eventually be affixed to this fragment -- so we must account
+		 * for it when determining the amount of payload space. */
+		bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN;
+		if (ieee->config &
+		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+			bytes_per_frag -= IEEE80211_FCS_LEN;
+
+		/* Each fragment may need to have room for encryptiong
+		 * pre/postfix */
+		if (host_encrypt)
+			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
+			    crypt->ops->extra_mpdu_postfix_len;
+
+		/* Number of fragments is the total
+		 * bytes_per_frag / payload_per_fragment */
+		nr_frags = bytes / bytes_per_frag;
+		bytes_last_frag = bytes % bytes_per_frag;
+		if (bytes_last_frag)
+			nr_frags++;
+		else
+			bytes_last_frag = bytes_per_frag;
+	} else {
+		nr_frags = 1;
+		bytes_per_frag = bytes_last_frag = bytes;
+		frag_size = bytes + IEEE80211_3ADDR_LEN;
+	}
+
+	rts_required = (frag_size > ieee->rts
+			&& ieee->config & CFG_IEEE80211_RTS);
+	if (rts_required)
 		nr_frags++;
-	else
-		bytes_last_frag = bytes_per_frag;
 
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
 	 * postfix, header, FCS, etc.) */
-	txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
+	txb = ieee80211_alloc_txb(nr_frags, frag_size,
+				  ieee->tx_headroom, GFP_ATOMIC);
 	if (unlikely(!txb)) {
 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
 		       ieee->dev->name);
 		goto failed;
 	}
 	txb->encrypted = encrypt;
-	txb->payload_size = bytes;
+	if (host_encrypt)
+		txb->payload_size = frag_size * (nr_frags - 1) +
+		    bytes_last_frag;
+	else
+		txb->payload_size = bytes;
 
-	for (i = 0; i < nr_frags; i++) {
+	if (rts_required) {
+		skb_frag = txb->fragments[0];
+		frag_hdr =
+		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+
+		/*
+		 * Set header frame_ctl to the RTS.
+		 */
+		header.frame_ctl =
+		    cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
+		memcpy(frag_hdr, &header, hdr_len);
+
+		/*
+		 * Restore header frame_ctl to the original data setting.
+		 */
+		header.frame_ctl = cpu_to_le16(fc);
+
+		if (ieee->config &
+		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+			skb_put(skb_frag, 4);
+
+		txb->rts_included = 1;
+		i = 1;
+	} else
+		i = 0;
+
+	for (; i < nr_frags; i++) {
 		skb_frag = txb->fragments[i];
 
-		if (encrypt)
-			skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
+		if (host_encrypt || host_build_iv)
+			skb_reserve(skb_frag,
+				    crypt->ops->extra_mpdu_prefix_len);
 
-		frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len);
+		frag_hdr =
+		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
 		memcpy(frag_hdr, &header, hdr_len);
 
 		/* If this is not the last fragment, then add the MOREFRAGS
@@ -379,11 +448,10 @@
 			bytes = bytes_last_frag;
 		}
 
-		/* Put a SNAP header on the first fragment */
-		if (i == 0) {
-			ieee80211_put_snap(skb_put
-					   (skb_frag, SNAP_SIZE + sizeof(u16)),
-					   ether_type);
+		if (i == 0 && !snapped) {
+			ieee80211_copy_snap(skb_put
+					    (skb_frag, SNAP_SIZE + sizeof(u16)),
+					    ether_type);
 			bytes -= SNAP_SIZE + sizeof(u16);
 		}
 
@@ -394,8 +462,19 @@
 
 		/* Encryption routine will move the header forward in order
 		 * to insert the IV between the header and the payload */
-		if (encrypt)
+		if (host_encrypt)
 			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+		else if (host_build_iv) {
+			struct ieee80211_crypt_data *crypt;
+
+			crypt = ieee->crypt[ieee->tx_keyidx];
+			atomic_inc(&crypt->refcnt);
+			if (crypt->ops->build_iv)
+				crypt->ops->build_iv(skb_frag, hdr_len,
+						     crypt->priv);
+			atomic_dec(&crypt->refcnt);
+		}
+
 		if (ieee->config &
 		    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 			skb_put(skb_frag, 4);
@@ -407,11 +486,20 @@
 	dev_kfree_skb_any(skb);
 
 	if (txb) {
-		if ((*ieee->hard_start_xmit) (txb, dev) == 0) {
+		int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
+		if (ret == 0) {
 			stats->tx_packets++;
 			stats->tx_bytes += txb->payload_size;
 			return 0;
 		}
+
+		if (ret == NETDEV_TX_BUSY) {
+			printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
+			       "driver should report queue full via "
+			       "ieee_device->is_queue_full.\n",
+			       ieee->dev->name);
+		}
+
 		ieee80211_txb_free(txb);
 	}
 
@@ -422,7 +510,72 @@
 	netif_stop_queue(dev);
 	stats->tx_errors++;
 	return 1;
-
 }
 
+/* Incoming 802.11 strucure is converted to a TXB
+ * a block of 802.11 fragment packets (stored as skbs) */
+int ieee80211_tx_frame(struct ieee80211_device *ieee,
+		       struct ieee80211_hdr *frame, int len)
+{
+	struct ieee80211_txb *txb = NULL;
+	unsigned long flags;
+	struct net_device_stats *stats = &ieee->stats;
+	struct sk_buff *skb_frag;
+	int priority = -1;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+
+	/* If there is no driver handler to take the TXB, dont' bother
+	 * creating it... */
+	if (!ieee->hard_start_xmit) {
+		printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
+		goto success;
+	}
+
+	if (unlikely(len < 24)) {
+		printk(KERN_WARNING "%s: skb too small (%d).\n",
+		       ieee->dev->name, len);
+		goto success;
+	}
+
+	/* When we allocate the TXB we allocate enough space for the reserve
+	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
+	 * postfix, header, FCS, etc.) */
+	txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
+	if (unlikely(!txb)) {
+		printk(KERN_WARNING "%s: Could not allocate TXB\n",
+		       ieee->dev->name);
+		goto failed;
+	}
+	txb->encrypted = 0;
+	txb->payload_size = len;
+
+	skb_frag = txb->fragments[0];
+
+	memcpy(skb_put(skb_frag, len), frame, len);
+
+	if (ieee->config &
+	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+		skb_put(skb_frag, 4);
+
+      success:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+
+	if (txb) {
+		if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
+			stats->tx_packets++;
+			stats->tx_bytes += txb->payload_size;
+			return 0;
+		}
+		ieee80211_txb_free(txb);
+	}
+	return 0;
+
+      failed:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	stats->tx_errors++;
+	return 1;
+}
+
+EXPORT_SYMBOL(ieee80211_tx_frame);
 EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 94882f3..1ce7af9 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
 
   Portions of this file are based on the WEP enablement code provided by the
   Host AP project hostap-drivers v0.1.3
@@ -32,6 +32,7 @@
 
 #include <linux/kmod.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 
 #include <net/ieee80211.h>
 #include <linux/wireless.h>
@@ -140,18 +141,41 @@
 		start = iwe_stream_add_point(start, stop, &iwe, custom);
 
 	/* Add quality statistics */
-	/* TODO: Fix these values... */
 	iwe.cmd = IWEVQUAL;
-	iwe.u.qual.qual = network->stats.signal;
-	iwe.u.qual.level = network->stats.rssi;
-	iwe.u.qual.noise = network->stats.noise;
-	iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
-	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
-		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
-	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
+	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+	    IW_QUAL_NOISE_UPDATED;
+
+	if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
+		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
+		    IW_QUAL_LEVEL_INVALID;
+		iwe.u.qual.qual = 0;
+		iwe.u.qual.level = 0;
+	} else {
+		iwe.u.qual.level = network->stats.rssi;
+		if (ieee->perfect_rssi == ieee->worst_rssi)
+			iwe.u.qual.qual = 100;
+		else
+			iwe.u.qual.qual =
+			    (100 *
+			     (ieee->perfect_rssi - ieee->worst_rssi) *
+			     (ieee->perfect_rssi - ieee->worst_rssi) -
+			     (ieee->perfect_rssi - network->stats.rssi) *
+			     (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
+			      62 * (ieee->perfect_rssi - network->stats.rssi))) /
+			    ((ieee->perfect_rssi - ieee->worst_rssi) *
+			     (ieee->perfect_rssi - ieee->worst_rssi));
+		if (iwe.u.qual.qual > 100)
+			iwe.u.qual.qual = 100;
+		else if (iwe.u.qual.qual < 1)
+			iwe.u.qual.qual = 0;
+	}
+
+	if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
 		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
-	if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
-		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
+		iwe.u.qual.noise = 0;
+	} else {
+		iwe.u.qual.noise = network->stats.noise;
+	}
 
 	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
 
@@ -162,7 +186,7 @@
 	if (iwe.u.data.length)
 		start = iwe_stream_add_point(start, stop, &iwe, custom);
 
-	if (ieee->wpa_enabled && network->wpa_ie_len) {
+	if (network->wpa_ie_len) {
 		char buf[MAX_WPA_IE_LEN * 2 + 30];
 
 		u8 *p = buf;
@@ -177,7 +201,7 @@
 		start = iwe_stream_add_point(start, stop, &iwe, buf);
 	}
 
-	if (ieee->wpa_enabled && network->rsn_ie_len) {
+	if (network->rsn_ie_len) {
 		char buf[MAX_WPA_IE_LEN * 2 + 30];
 
 		u8 *p = buf;
@@ -197,8 +221,8 @@
 	iwe.cmd = IWEVCUSTOM;
 	p = custom;
 	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-		      " Last beacon: %lums ago",
-		      (jiffies - network->last_scanned) / (HZ / 100));
+		      " Last beacon: %dms ago",
+		      jiffies_to_msecs(jiffies - network->last_scanned));
 	iwe.u.data.length = p - custom;
 	if (iwe.u.data.length)
 		start = iwe_stream_add_point(start, stop, &iwe, custom);
@@ -228,13 +252,13 @@
 			ev = ipw2100_translate_scan(ieee, ev, stop, network);
 		else
 			IEEE80211_DEBUG_SCAN("Not showing network '%s ("
-					     MAC_FMT ")' due to age (%lums).\n",
+					     MAC_FMT ")' due to age (%dms).\n",
 					     escape_essid(network->ssid,
 							  network->ssid_len),
 					     MAC_ARG(network->bssid),
-					     (jiffies -
-					      network->last_scanned) / (HZ /
-									100));
+					     jiffies_to_msecs(jiffies -
+							      network->
+							      last_scanned));
 	}
 
 	spin_unlock_irqrestore(&ieee->lock, flags);
@@ -258,6 +282,7 @@
 	};
 	int i, key, key_provided, len;
 	struct ieee80211_crypt_data **crypt;
+	int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
 
 	IEEE80211_DEBUG_WX("SET_ENCODE\n");
 
@@ -298,15 +323,17 @@
 
 		if (i == WEP_KEYS) {
 			sec.enabled = 0;
+			sec.encrypt = 0;
 			sec.level = SEC_LEVEL_0;
-			sec.flags |= SEC_ENABLED | SEC_LEVEL;
+			sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
 		}
 
 		goto done;
 	}
 
 	sec.enabled = 1;
-	sec.flags |= SEC_ENABLED;
+	sec.encrypt = 1;
+	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
 
 	if (*crypt != NULL && (*crypt)->ops != NULL &&
 	    strcmp((*crypt)->ops->name, "WEP") != 0) {
@@ -315,7 +342,7 @@
 		ieee80211_crypt_delayed_deinit(ieee, crypt);
 	}
 
-	if (*crypt == NULL) {
+	if (*crypt == NULL && host_crypto) {
 		struct ieee80211_crypt_data *new_crypt;
 
 		/* take WEP into use */
@@ -355,49 +382,56 @@
 				   key, escape_essid(sec.keys[key], len),
 				   erq->length, len);
 		sec.key_sizes[key] = len;
-		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
-				       (*crypt)->priv);
+		if (*crypt)
+			(*crypt)->ops->set_key(sec.keys[key], len, NULL,
+					       (*crypt)->priv);
 		sec.flags |= (1 << key);
 		/* This ensures a key will be activated if no key is
 		 * explicitely set */
 		if (key == sec.active_key)
 			sec.flags |= SEC_ACTIVE_KEY;
-	} else {
-		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
-					     NULL, (*crypt)->priv);
-		if (len == 0) {
-			/* Set a default key of all 0 */
-			IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
-					   key);
-			memset(sec.keys[key], 0, 13);
-			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
-					       (*crypt)->priv);
-			sec.key_sizes[key] = 13;
-			sec.flags |= (1 << key);
-		}
 
+	} else {
+		if (host_crypto) {
+			len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+						     NULL, (*crypt)->priv);
+			if (len == 0) {
+				/* Set a default key of all 0 */
+				IEEE80211_DEBUG_WX("Setting key %d to all "
+						   "zero.\n", key);
+				memset(sec.keys[key], 0, 13);
+				(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+						       (*crypt)->priv);
+				sec.key_sizes[key] = 13;
+				sec.flags |= (1 << key);
+			}
+		}
 		/* No key data - just set the default TX key index */
 		if (key_provided) {
-			IEEE80211_DEBUG_WX
-			    ("Setting key %d to default Tx key.\n", key);
+			IEEE80211_DEBUG_WX("Setting key %d to default Tx "
+					   "key.\n", key);
 			ieee->tx_keyidx = key;
 			sec.active_key = key;
 			sec.flags |= SEC_ACTIVE_KEY;
 		}
 	}
-
-      done:
-	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
-	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
-	sec.flags |= SEC_AUTH_MODE;
-	IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
-			   "OPEN" : "SHARED KEY");
+	if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
+		ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+		sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
+		    WLAN_AUTH_SHARED_KEY;
+		sec.flags |= SEC_AUTH_MODE;
+		IEEE80211_DEBUG_WX("Auth: %s\n",
+				   sec.auth_mode == WLAN_AUTH_OPEN ?
+				   "OPEN" : "SHARED KEY");
+	}
 
 	/* For now we just support WEP, so only set that security level...
 	 * TODO: When WPA is added this is one place that needs to change */
 	sec.flags |= SEC_LEVEL;
 	sec.level = SEC_LEVEL_1;	/* 40 and 104 bit WEP */
+	sec.encode_alg[key] = SEC_ALG_WEP;
 
+      done:
 	if (ieee->set_security)
 		ieee->set_security(dev, &sec);
 
@@ -422,6 +456,7 @@
 	struct iw_point *erq = &(wrqu->encoding);
 	int len, key;
 	struct ieee80211_crypt_data *crypt;
+	struct ieee80211_security *sec = &ieee->sec;
 
 	IEEE80211_DEBUG_WX("GET_ENCODE\n");
 
@@ -436,23 +471,16 @@
 	crypt = ieee->crypt[key];
 	erq->flags = key + 1;
 
-	if (crypt == NULL || crypt->ops == NULL) {
+	if (!sec->enabled) {
 		erq->length = 0;
 		erq->flags |= IW_ENCODE_DISABLED;
 		return 0;
 	}
 
-	if (strcmp(crypt->ops->name, "WEP") != 0) {
-		/* only WEP is supported with wireless extensions, so just
-		 * report that encryption is used */
-		erq->length = 0;
-		erq->flags |= IW_ENCODE_ENABLED;
-		return 0;
-	}
+	len = sec->key_sizes[key];
+	memcpy(keybuf, sec->keys[key], len);
 
-	len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv);
 	erq->length = (len >= 0 ? len : 0);
-
 	erq->flags |= IW_ENCODE_ENABLED;
 
 	if (ieee->open_wep)
@@ -463,6 +491,240 @@
 	return 0;
 }
 
+int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct net_device *dev = ieee->dev;
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	int i, idx, ret = 0;
+	int group_key = 0;
+	const char *alg, *module;
+	struct ieee80211_crypto_ops *ops;
+	struct ieee80211_crypt_data **crypt;
+
+	struct ieee80211_security sec = {
+		.flags = 0,
+	};
+
+	idx = encoding->flags & IW_ENCODE_INDEX;
+	if (idx) {
+		if (idx < 1 || idx > WEP_KEYS)
+			return -EINVAL;
+		idx--;
+	} else
+		idx = ieee->tx_keyidx;
+
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+		crypt = &ieee->crypt[idx];
+		group_key = 1;
+	} else {
+		if (idx != 0)
+			return -EINVAL;
+		if (ieee->iw_mode == IW_MODE_INFRA)
+			crypt = &ieee->crypt[idx];
+		else
+			return -EINVAL;
+	}
+
+	sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
+	if ((encoding->flags & IW_ENCODE_DISABLED) ||
+	    ext->alg == IW_ENCODE_ALG_NONE) {
+		if (*crypt)
+			ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+		for (i = 0; i < WEP_KEYS; i++)
+			if (ieee->crypt[i] != NULL)
+				break;
+
+		if (i == WEP_KEYS) {
+			sec.enabled = 0;
+			sec.encrypt = 0;
+			sec.level = SEC_LEVEL_0;
+			sec.flags |= SEC_LEVEL;
+		}
+		goto done;
+	}
+
+	sec.enabled = 1;
+	sec.encrypt = 1;
+
+	if (group_key ? !ieee->host_mc_decrypt :
+	    !(ieee->host_encrypt || ieee->host_decrypt ||
+	      ieee->host_encrypt_msdu))
+		goto skip_host_crypt;
+
+	switch (ext->alg) {
+	case IW_ENCODE_ALG_WEP:
+		alg = "WEP";
+		module = "ieee80211_crypt_wep";
+		break;
+	case IW_ENCODE_ALG_TKIP:
+		alg = "TKIP";
+		module = "ieee80211_crypt_tkip";
+		break;
+	case IW_ENCODE_ALG_CCMP:
+		alg = "CCMP";
+		module = "ieee80211_crypt_ccmp";
+		break;
+	default:
+		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+				   dev->name, ext->alg);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ops = ieee80211_get_crypto_ops(alg);
+	if (ops == NULL) {
+		request_module(module);
+		ops = ieee80211_get_crypto_ops(alg);
+	}
+	if (ops == NULL) {
+		IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+				   dev->name, ext->alg);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (*crypt == NULL || (*crypt)->ops != ops) {
+		struct ieee80211_crypt_data *new_crypt;
+
+		ieee80211_crypt_delayed_deinit(ieee, crypt);
+
+		new_crypt = (struct ieee80211_crypt_data *)
+		    kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+		if (new_crypt == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
+		new_crypt->ops = ops;
+		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+			new_crypt->priv = new_crypt->ops->init(idx);
+		if (new_crypt->priv == NULL) {
+			kfree(new_crypt);
+			ret = -EINVAL;
+			goto done;
+		}
+		*crypt = new_crypt;
+	}
+
+	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+				   (*crypt)->priv) < 0) {
+		IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
+		ret = -EINVAL;
+		goto done;
+	}
+
+      skip_host_crypt:
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+		ieee->tx_keyidx = idx;
+		sec.active_key = idx;
+		sec.flags |= SEC_ACTIVE_KEY;
+	}
+
+	if (ext->alg != IW_ENCODE_ALG_NONE) {
+		memcpy(sec.keys[idx], ext->key, ext->key_len);
+		sec.key_sizes[idx] = ext->key_len;
+		sec.flags |= (1 << idx);
+		if (ext->alg == IW_ENCODE_ALG_WEP) {
+			sec.encode_alg[idx] = SEC_ALG_WEP;
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_1;
+		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+			sec.encode_alg[idx] = SEC_ALG_TKIP;
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_2;
+		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+			sec.encode_alg[idx] = SEC_ALG_CCMP;
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_3;
+		}
+		/* Don't set sec level for group keys. */
+		if (group_key)
+			sec.flags &= ~SEC_LEVEL;
+	}
+      done:
+	if (ieee->set_security)
+		ieee->set_security(ieee->dev, &sec);
+
+	/*
+	 * Do not reset port if card is in Managed mode since resetting will
+	 * generate new IEEE 802.11 authentication which may end up in looping
+	 * with IEEE 802.1X. If your hardware requires a reset after WEP
+	 * configuration (for example... Prism2), implement the reset_port in
+	 * the callbacks structures used to initialize the 802.11 stack.
+	 */
+	if (ieee->reset_on_keychange &&
+	    ieee->iw_mode != IW_MODE_INFRA &&
+	    ieee->reset_port && ieee->reset_port(dev)) {
+		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct ieee80211_security *sec = &ieee->sec;
+	int idx, max_key_len;
+
+	max_key_len = encoding->length - sizeof(*ext);
+	if (max_key_len < 0)
+		return -EINVAL;
+
+	idx = encoding->flags & IW_ENCODE_INDEX;
+	if (idx) {
+		if (idx < 1 || idx > WEP_KEYS)
+			return -EINVAL;
+		idx--;
+	} else
+		idx = ieee->tx_keyidx;
+
+	if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
+			return -EINVAL;
+
+	encoding->flags = idx + 1;
+	memset(ext, 0, sizeof(*ext));
+
+	if (!sec->enabled) {
+		ext->alg = IW_ENCODE_ALG_NONE;
+		ext->key_len = 0;
+		encoding->flags |= IW_ENCODE_DISABLED;
+	} else {
+		if (sec->encode_alg[idx] == SEC_ALG_WEP)
+			ext->alg = IW_ENCODE_ALG_WEP;
+		else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
+			ext->alg = IW_ENCODE_ALG_TKIP;
+		else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
+			ext->alg = IW_ENCODE_ALG_CCMP;
+		else
+			return -EINVAL;
+
+		ext->key_len = sec->key_sizes[idx];
+		memcpy(ext->key, sec->keys[idx], ext->key_len);
+		encoding->flags |= IW_ENCODE_ENABLED;
+		if (ext->key_len &&
+		    (ext->alg == IW_ENCODE_ALG_TKIP ||
+		     ext->alg == IW_ENCODE_ALG_CCMP))
+			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
+EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
+
 EXPORT_SYMBOL(ieee80211_wx_get_scan);
 EXPORT_SYMBOL(ieee80211_wx_set_encode);
 EXPORT_SYMBOL(ieee80211_wx_get_encode);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 74f2207..4ec4b2c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -715,6 +715,7 @@
 			break;
 		ret = 0;
 		if (ifa->ifa_mask != sin->sin_addr.s_addr) {
+			u32 old_mask = ifa->ifa_mask;
 			inet_del_ifa(in_dev, ifap, 0);
 			ifa->ifa_mask = sin->sin_addr.s_addr;
 			ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
@@ -728,7 +729,7 @@
 			if ((dev->flags & IFF_BROADCAST) &&
 			    (ifa->ifa_prefixlen < 31) &&
 			    (ifa->ifa_broadcast ==
-			     (ifa->ifa_local|~ifa->ifa_mask))) {
+			     (ifa->ifa_local|~old_mask))) {
 				ifa->ifa_broadcast = (ifa->ifa_local |
 						      ~sin->sin_addr.s_addr);
 			}
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index e61bc71..990633c 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -591,7 +591,7 @@
 		break;
 	case NETDEV_DOWN:
 		fib_del_ifaddr(ifa);
-		if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+		if (ifa->ifa_dev->ifa_list == NULL) {
 			/* Last address was deleted from this interface.
 			   Disable IP.
 			 */
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 0093ea0..66247f3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2404,7 +2404,7 @@
 		prefix = htonl(l->key);
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-			const struct fib_info *fi = rcu_dereference(fa->fa_info);
+			const struct fib_info *fi = fa->fa_info;
 			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
 
 			if (fa->fa_type == RTN_BROADCAST
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 90dca71..175e093 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1108,12 +1108,9 @@
 	struct inet_sock *inet;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		int err;
 
-		if (!cpu_possible(i))
-			continue;
-
 		err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
 				       &per_cpu(__icmp_socket, i));
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 1ad5202..1775823 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -275,7 +275,8 @@
 {
 	IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 
-	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+	if (skb->len > dst_mtu(skb->dst) &&
+		!(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
 		return ip_fragment(skb, ip_finish_output);
 	else
 		return ip_finish_output(skb);
@@ -688,6 +689,60 @@
 	return csum;
 }
 
+inline int ip_ufo_append_data(struct sock *sk,
+			int getfrag(void *from, char *to, int offset, int len,
+			       int odd, struct sk_buff *skb),
+			void *from, int length, int hh_len, int fragheaderlen,
+			int transhdrlen, int mtu,unsigned int flags)
+{
+	struct sk_buff *skb;
+	int err;
+
+	/* There is support for UDP fragmentation offload by network
+	 * device, so create one single skb packet containing complete
+	 * udp datagram
+	 */
+	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+		skb = sock_alloc_send_skb(sk,
+			hh_len + fragheaderlen + transhdrlen + 20,
+			(flags & MSG_DONTWAIT), &err);
+
+		if (skb == NULL)
+			return err;
+
+		/* reserve space for Hardware header */
+		skb_reserve(skb, hh_len);
+
+		/* create space for UDP/IP header */
+		skb_put(skb,fragheaderlen + transhdrlen);
+
+		/* initialize network header pointer */
+		skb->nh.raw = skb->data;
+
+		/* initialize protocol header pointer */
+		skb->h.raw = skb->data + fragheaderlen;
+
+		skb->ip_summed = CHECKSUM_HW;
+		skb->csum = 0;
+		sk->sk_sndmsg_off = 0;
+	}
+
+	err = skb_append_datato_frags(sk,skb, getfrag, from,
+			       (length - transhdrlen));
+	if (!err) {
+		/* specify the length of each IP datagram fragment*/
+		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
+		__skb_queue_tail(&sk->sk_write_queue, skb);
+
+		return 0;
+	}
+	/* There is not enough support do UFO ,
+	 * so follow normal path
+	 */
+	kfree_skb(skb);
+	return err;
+}
+
 /*
  *	ip_append_data() and ip_append_page() can make one large IP datagram
  *	from many pieces of data. Each pieces will be holded on the socket
@@ -777,6 +832,15 @@
 		csummode = CHECKSUM_HW;
 
 	inet->cork.length += length;
+	if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+			(rt->u.dst.dev->features & NETIF_F_UFO)) {
+
+		if(ip_ufo_append_data(sk, getfrag, from, length, hh_len,
+			       fragheaderlen, transhdrlen, mtu, flags))
+			goto error;
+
+		return 0;
+	}
 
 	/* So, what's going on in the loop below?
 	 *
@@ -1008,14 +1072,23 @@
 		return -EINVAL;
 
 	inet->cork.length += size;
+	if ((sk->sk_protocol == IPPROTO_UDP) &&
+	    (rt->u.dst.dev->features & NETIF_F_UFO))
+		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
+
 
 	while (size > 0) {
 		int i;
 
-		/* Check if the remaining data fits into current packet. */
-		len = mtu - skb->len;
-		if (len < size)
-			len = maxfraglen - skb->len;
+		if (skb_shinfo(skb)->ufo_size)
+			len = size;
+		else {
+
+			/* Check if the remaining data fits into current packet. */
+			len = mtu - skb->len;
+			if (len < size)
+				len = maxfraglen - skb->len;
+		}
 		if (len <= 0) {
 			struct sk_buff *skb_prev;
 			char *data;
@@ -1023,10 +1096,7 @@
 			int alloclen;
 
 			skb_prev = skb;
-			if (skb_prev)
-				fraggap = skb_prev->len - maxfraglen;
-			else
-				fraggap = 0;
+			fraggap = skb_prev->len - maxfraglen;
 
 			alloclen = fragheaderlen + hh_len + fraggap + 15;
 			skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 07a80b5..422ab68 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -50,7 +50,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
-#define IP_CONNTRACK_VERSION	"2.3"
+#define IP_CONNTRACK_VERSION	"2.4"
 
 #if 0
 #define DEBUGP printk
@@ -148,16 +148,20 @@
 static int ip_conntrack_hash_rnd_initted;
 static unsigned int ip_conntrack_hash_rnd;
 
-static u_int32_t
-hash_conntrack(const struct ip_conntrack_tuple *tuple)
+static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
+			    unsigned int size, unsigned int rnd)
 {
-#if 0
-	dump_tuple(tuple);
-#endif
 	return (jhash_3words(tuple->src.ip,
 	                     (tuple->dst.ip ^ tuple->dst.protonum),
 	                     (tuple->src.u.all | (tuple->dst.u.all << 16)),
-	                     ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
+	                     rnd) % size);
+}
+
+static u_int32_t
+hash_conntrack(const struct ip_conntrack_tuple *tuple)
+{
+	return __hash_conntrack(tuple, ip_conntrack_htable_size,
+				ip_conntrack_hash_rnd);
 }
 
 int
@@ -1341,14 +1345,13 @@
 	return 1;
 }
 
-static void free_conntrack_hash(void)
+static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size)
 {
-	if (ip_conntrack_vmalloc)
-		vfree(ip_conntrack_hash);
+	if (vmalloced)
+		vfree(hash);
 	else
-		free_pages((unsigned long)ip_conntrack_hash, 
-			   get_order(sizeof(struct list_head)
-				     * ip_conntrack_htable_size));
+		free_pages((unsigned long)hash, 
+			   get_order(sizeof(struct list_head) * size));
 }
 
 void ip_conntrack_flush()
@@ -1378,12 +1381,83 @@
 	ip_conntrack_flush();
 	kmem_cache_destroy(ip_conntrack_cachep);
 	kmem_cache_destroy(ip_conntrack_expect_cachep);
-	free_conntrack_hash();
+	free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+			    ip_conntrack_htable_size);
 	nf_unregister_sockopt(&so_getorigdst);
 }
 
-static int hashsize;
-module_param(hashsize, int, 0400);
+static struct list_head *alloc_hashtable(int size, int *vmalloced)
+{
+	struct list_head *hash;
+	unsigned int i;
+
+	*vmalloced = 0; 
+	hash = (void*)__get_free_pages(GFP_KERNEL, 
+				       get_order(sizeof(struct list_head)
+						 * size));
+	if (!hash) { 
+		*vmalloced = 1;
+		printk(KERN_WARNING"ip_conntrack: falling back to vmalloc.\n");
+		hash = vmalloc(sizeof(struct list_head) * size);
+	}
+
+	if (hash)
+		for (i = 0; i < size; i++)
+			INIT_LIST_HEAD(&hash[i]);
+
+	return hash;
+}
+
+int set_hashsize(const char *val, struct kernel_param *kp)
+{
+	int i, bucket, hashsize, vmalloced;
+	int old_vmalloced, old_size;
+	int rnd;
+	struct list_head *hash, *old_hash;
+	struct ip_conntrack_tuple_hash *h;
+
+	/* On boot, we can set this without any fancy locking. */
+	if (!ip_conntrack_htable_size)
+		return param_set_int(val, kp);
+
+	hashsize = simple_strtol(val, NULL, 0);
+	if (!hashsize)
+		return -EINVAL;
+
+	hash = alloc_hashtable(hashsize, &vmalloced);
+	if (!hash)
+		return -ENOMEM;
+
+	/* We have to rehash for the new table anyway, so we also can 
+	 * use a new random seed */
+	get_random_bytes(&rnd, 4);
+
+	write_lock_bh(&ip_conntrack_lock);
+	for (i = 0; i < ip_conntrack_htable_size; i++) {
+		while (!list_empty(&ip_conntrack_hash[i])) {
+			h = list_entry(ip_conntrack_hash[i].next,
+				       struct ip_conntrack_tuple_hash, list);
+			list_del(&h->list);
+			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
+			list_add_tail(&h->list, &hash[bucket]);
+		}
+	}
+	old_size = ip_conntrack_htable_size;
+	old_vmalloced = ip_conntrack_vmalloc;
+	old_hash = ip_conntrack_hash;
+
+	ip_conntrack_htable_size = hashsize;
+	ip_conntrack_vmalloc = vmalloced;
+	ip_conntrack_hash = hash;
+	ip_conntrack_hash_rnd = rnd;
+	write_unlock_bh(&ip_conntrack_lock);
+
+	free_conntrack_hash(old_hash, old_vmalloced, old_size);
+	return 0;
+}
+
+module_param_call(hashsize, set_hashsize, param_get_uint,
+		  &ip_conntrack_htable_size, 0600);
 
 int __init ip_conntrack_init(void)
 {
@@ -1392,9 +1466,7 @@
 
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
 	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
- 	if (hashsize) {
- 		ip_conntrack_htable_size = hashsize;
- 	} else {
+ 	if (!ip_conntrack_htable_size) {
 		ip_conntrack_htable_size
 			= (((num_physpages << PAGE_SHIFT) / 16384)
 			   / sizeof(struct list_head));
@@ -1416,20 +1488,8 @@
 		return ret;
 	}
 
-	/* AK: the hash table is twice as big than needed because it
-	   uses list_head.  it would be much nicer to caches to use a
-	   single pointer list head here. */
-	ip_conntrack_vmalloc = 0; 
-	ip_conntrack_hash 
-		=(void*)__get_free_pages(GFP_KERNEL, 
-					 get_order(sizeof(struct list_head)
-						   *ip_conntrack_htable_size));
-	if (!ip_conntrack_hash) { 
-		ip_conntrack_vmalloc = 1;
-		printk(KERN_WARNING "ip_conntrack: falling back to vmalloc.\n");
-		ip_conntrack_hash = vmalloc(sizeof(struct list_head)
-					    * ip_conntrack_htable_size);
-	}
+	ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
+					    &ip_conntrack_vmalloc);
 	if (!ip_conntrack_hash) {
 		printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
 		goto err_unreg_sockopt;
@@ -1461,9 +1521,6 @@
 	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
 	write_unlock_bh(&ip_conntrack_lock);
 
-	for (i = 0; i < ip_conntrack_htable_size; i++)
-		INIT_LIST_HEAD(&ip_conntrack_hash[i]);
-
 	/* For use by ipt_REJECT */
 	ip_ct_attach = ip_conntrack_attach;
 
@@ -1478,7 +1535,8 @@
 err_free_conntrack_slab:
 	kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
-	free_conntrack_hash();
+	free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+			    ip_conntrack_htable_size);
 err_unreg_sockopt:
 	nf_unregister_sockopt(&so_getorigdst);
 
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index f5909a4..e19c2a5 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -48,7 +48,7 @@
 		      unsigned int hook_mask)
 {
 	if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
-		printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n.",
+		printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n",
 		       matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
 		return 0;
 	}
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index f7943ba..a65e508 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -90,9 +90,7 @@
 	unsigned long res = 0;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
 		res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
 	}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a970b47..41edc14 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -75,7 +75,7 @@
 #ifdef CONFIG_IPV6_PRIVACY
 #include <linux/random.h>
 #include <linux/crypto.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 #endif
 
 #include <asm/uaccess.h>
@@ -1217,12 +1217,8 @@
 	struct net_device *dev;
 	struct scatterlist sg[2];
 
-	sg[0].page = virt_to_page(idev->entropy);
-	sg[0].offset = offset_in_page(idev->entropy);
-	sg[0].length = 8;
-	sg[1].page = virt_to_page(idev->work_eui64);
-	sg[1].offset = offset_in_page(idev->work_eui64);
-	sg[1].length = 8;
+	sg_set_buf(&sg[0], idev->entropy, 8);
+	sg_set_buf(&sg[1], idev->work_eui64, 8);
 
 	dev = idev->dev;
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index b7185fb..23e5403 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -700,10 +700,7 @@
 	struct sock *sk;
 	int err, i, j;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
 				       &per_cpu(__icmpv6_socket, i));
 		if (err < 0) {
@@ -749,9 +746,7 @@
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		sock_release(per_cpu(__icmpv6_socket, i));
 	}
 	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 563b442..614296a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -147,7 +147,8 @@
 
 int ip6_output(struct sk_buff *skb)
 {
-	if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
+	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
+				dst_allfrag(skb->dst))
 		return ip6_fragment(skb, ip6_output2);
 	else
 		return ip6_output2(skb);
@@ -768,6 +769,65 @@
 	*dst = NULL;
 	return err;
 }
+inline int ip6_ufo_append_data(struct sock *sk,
+			int getfrag(void *from, char *to, int offset, int len,
+			int odd, struct sk_buff *skb),
+			void *from, int length, int hh_len, int fragheaderlen,
+			int transhdrlen, int mtu,unsigned int flags)
+
+{
+	struct sk_buff *skb;
+	int err;
+
+	/* There is support for UDP large send offload by network
+	 * device, so create one single skb packet containing complete
+	 * udp datagram
+	 */
+	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+		skb = sock_alloc_send_skb(sk,
+			hh_len + fragheaderlen + transhdrlen + 20,
+			(flags & MSG_DONTWAIT), &err);
+		if (skb == NULL)
+			return -ENOMEM;
+
+		/* reserve space for Hardware header */
+		skb_reserve(skb, hh_len);
+
+		/* create space for UDP/IP header */
+		skb_put(skb,fragheaderlen + transhdrlen);
+
+		/* initialize network header pointer */
+		skb->nh.raw = skb->data;
+
+		/* initialize protocol header pointer */
+		skb->h.raw = skb->data + fragheaderlen;
+
+		skb->ip_summed = CHECKSUM_HW;
+		skb->csum = 0;
+		sk->sk_sndmsg_off = 0;
+	}
+
+	err = skb_append_datato_frags(sk,skb, getfrag, from,
+				      (length - transhdrlen));
+	if (!err) {
+		struct frag_hdr fhdr;
+
+		/* specify the length of each IP datagram fragment*/
+		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 
+						sizeof(struct frag_hdr);
+		ipv6_select_ident(skb, &fhdr);
+		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+		__skb_queue_tail(&sk->sk_write_queue, skb);
+
+		return 0;
+	}
+	/* There is not enough support do UPD LSO,
+	 * so follow normal path
+	 */
+	kfree_skb(skb);
+
+	return err;
+}
 
 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	int offset, int len, int odd, struct sk_buff *skb),
@@ -860,6 +920,15 @@
 	 */
 
 	inet->cork.length += length;
+	if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
+
+		if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len,
+				fragheaderlen, transhdrlen, mtu, flags))
+			goto error;
+
+		return 0;
+	}
 
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
 		goto alloc_new_skb;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 39a96c7..c4f2a0e 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -164,7 +164,7 @@
 #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
 #define MLDV2_EXP(thresh, nbmant, nbexp, value) \
 	((value) < (thresh) ? (value) : \
-	((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \
+	((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \
 	(MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp))))
 
 #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 334a596..50a13e7 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -140,9 +140,7 @@
         unsigned long res = 0;
         int i;
  
-        for (i = 0; i < NR_CPUS; i++) {
-                if (!cpu_possible(i))
-                        continue;
+        for_each_cpu(i) {
                 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
         }
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 678c3f2..5ca2835 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -740,11 +740,8 @@
 
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
 {
-	struct netlink_sock *nlk;
 	int len = skb->len;
 
-	nlk = nlk_sk(sk);
-
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk, len);
 	sock_put(sk);
@@ -827,7 +824,7 @@
 	int failure;
 	int congested;
 	int delivered;
-	unsigned int allocation;
+	gfp_t allocation;
 	struct sk_buff *skb, *skb2;
 };
 
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index e556d92..b18fe50 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -727,7 +727,7 @@
 		}
 		if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
 			return -EINVAL;
-		if (rose_route.ndigis > 8) /* No more than 8 digipeats */
+		if (rose_route.ndigis > AX25_MAX_DIGIS)
 			return -EINVAL;
 		err = rose_add_node(&rose_route, dev);
 		dev_put(dev);
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index b74f777..6e4dc28 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -69,9 +69,7 @@
 	unsigned long res = 0;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		res +=
 		    *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
 					 sizeof (unsigned long) * nr));
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 10e82ec..660c61b 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -554,7 +554,7 @@
 	dp.ppid   = sinfo->sinfo_ppid;
 
 	/* Set the flags for an unordered send.  */
-	if (sinfo->sinfo_flags & MSG_UNORDERED) {
+	if (sinfo->sinfo_flags & SCTP_UNORDERED) {
 		flags |= SCTP_DATA_UNORDERED;
 		dp.ssn = 0;
 	} else
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 02e068d..b529af5 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1010,6 +1010,19 @@
 					err = -EAGAIN;
 					goto out_free;
 				}
+			} else {
+				/*
+				 * If an unprivileged user inherits a 1-many 
+				 * style socket with open associations on a 
+				 * privileged port, it MAY be permitted to 
+				 * accept new associations, but it SHOULD NOT 
+				 * be permitted to open new associations.
+				 */
+				if (ep->base.bind_addr.port < PROT_SOCK &&
+				    !capable(CAP_NET_BIND_SERVICE)) {
+					err = -EACCES;
+					goto out_free;
+				}
 			}
 
 			scope = sctp_scope(&to);
@@ -1389,27 +1402,27 @@
 	SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n",
 			  msg_len, sinfo_flags);
 
-	/* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */
-	if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) {
+	/* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */
+	if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) {
 		err = -EINVAL;
 		goto out_nounlock;
 	}
 
-	/* If MSG_EOF is set, no data can be sent. Disallow sending zero
-	 * length messages when MSG_EOF|MSG_ABORT is not set.
-	 * If MSG_ABORT is set, the message length could be non zero with
+	/* If SCTP_EOF is set, no data can be sent. Disallow sending zero
+	 * length messages when SCTP_EOF|SCTP_ABORT is not set.
+	 * If SCTP_ABORT is set, the message length could be non zero with
 	 * the msg_iov set to the user abort reason.
  	 */
-	if (((sinfo_flags & MSG_EOF) && (msg_len > 0)) ||
-	    (!(sinfo_flags & (MSG_EOF|MSG_ABORT)) && (msg_len == 0))) {
+	if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) ||
+	    (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) {
 		err = -EINVAL;
 		goto out_nounlock;
 	}
 
-	/* If MSG_ADDR_OVER is set, there must be an address
+	/* If SCTP_ADDR_OVER is set, there must be an address
 	 * specified in msg_name.
 	 */
-	if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) {
+	if ((sinfo_flags & SCTP_ADDR_OVER) && (!msg->msg_name)) {
 		err = -EINVAL;
 		goto out_nounlock;
 	}
@@ -1458,14 +1471,14 @@
 			goto out_unlock;
 		}
 
-		if (sinfo_flags & MSG_EOF) {
+		if (sinfo_flags & SCTP_EOF) {
 			SCTP_DEBUG_PRINTK("Shutting down association: %p\n",
 					  asoc);
 			sctp_primitive_SHUTDOWN(asoc, NULL);
 			err = 0;
 			goto out_unlock;
 		}
-		if (sinfo_flags & MSG_ABORT) {
+		if (sinfo_flags & SCTP_ABORT) {
 			SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
 			sctp_primitive_ABORT(asoc, msg);
 			err = 0;
@@ -1477,7 +1490,7 @@
 	if (!asoc) {
 		SCTP_DEBUG_PRINTK("There is no association yet.\n");
 
-		if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
+		if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) {
 			err = -EINVAL;
 			goto out_unlock;
 		}
@@ -1515,6 +1528,19 @@
 				err = -EAGAIN;
 				goto out_unlock;
 			}
+		} else {
+			/*
+			 * If an unprivileged user inherits a one-to-many
+			 * style socket with open associations on a privileged
+			 * port, it MAY be permitted to accept new associations,
+			 * but it SHOULD NOT be permitted to open new
+			 * associations.
+			 */
+			if (ep->base.bind_addr.port < PROT_SOCK &&
+			    !capable(CAP_NET_BIND_SERVICE)) {
+				err = -EACCES;
+				goto out_unlock;
+			}
 		}
 
 		scope = sctp_scope(&to);
@@ -1611,10 +1637,10 @@
 
 	/* If an address is passed with the sendto/sendmsg call, it is used
 	 * to override the primary destination address in the TCP model, or
-	 * when MSG_ADDR_OVER flag is set in the UDP model.
+	 * when SCTP_ADDR_OVER flag is set in the UDP model.
 	 */
 	if ((sctp_style(sk, TCP) && msg_name) ||
-	    (sinfo_flags & MSG_ADDR_OVER)) {
+	    (sinfo_flags & SCTP_ADDR_OVER)) {
 		chunk_tp = sctp_assoc_lookup_paddr(asoc, &to);
 		if (!chunk_tp) {
 			err = -EINVAL;
@@ -2306,16 +2332,14 @@
 		return -EINVAL;
 	if (get_user(val, (int __user *)optval))
 		return -EFAULT;
-	if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
+	if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
 		return -EINVAL;
 	sp->user_frag = val;
 
-	if (val) {
-		/* Update the frag_point of the existing associations. */
-		list_for_each(pos, &(sp->ep->asocs)) {
-			asoc = list_entry(pos, struct sctp_association, asocs);
-			asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 
-		}
+	/* Update the frag_point of the existing associations. */
+	list_for_each(pos, &(sp->ep->asocs)) {
+		asoc = list_entry(pos, struct sctp_association, asocs);
+		asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 
 	}
 
 	return 0;
@@ -2384,14 +2408,14 @@
 static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
 					  int optlen)
 {
-	__u32 val;
+	struct sctp_setadaption adaption;
 
-	if (optlen < sizeof(__u32))
+	if (optlen != sizeof(struct sctp_setadaption))
 		return -EINVAL;
-	if (copy_from_user(&val, optval, sizeof(__u32)))
+	if (copy_from_user(&adaption, optval, optlen)) 
 		return -EFAULT;
 
-	sctp_sk(sk)->adaption_ind = val;
+	sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind;
 
 	return 0;
 }
@@ -3672,17 +3696,15 @@
 static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
 				  char __user *optval, int __user *optlen)
 {
-	__u32 val;
+	struct sctp_setadaption adaption;
 
-	if (len < sizeof(__u32))
+	if (len != sizeof(struct sctp_setadaption))
 		return -EINVAL;
 
-	len = sizeof(__u32);
-	val = sctp_sk(sk)->adaption_ind;
-	if (put_user(len, optlen))
+	adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind;
+	if (copy_to_user(optval, &adaption, len))
 		return -EFAULT;
-	if (copy_to_user(optval, &val, len))
-		return -EFAULT;
+
 	return 0;
 }
 
@@ -4640,8 +4662,8 @@
 
 			/* Minimally, validate the sinfo_flags. */
 			if (cmsgs->info->sinfo_flags &
-			    ~(MSG_UNORDERED | MSG_ADDR_OVER |
-			      MSG_ABORT | MSG_EOF))
+			    ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+			      SCTP_ABORT | SCTP_EOF))
 				return -EINVAL;
 			break;
 
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 057e7fa..e049f41 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -698,7 +698,7 @@
 	event->ssn = ntohs(chunk->subh.data_hdr->ssn);
 	event->ppid = chunk->subh.data_hdr->ppid;
 	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
-		event->flags |= MSG_UNORDERED;
+		event->flags |= SCTP_UNORDERED;
 		event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
 	}
 	event->tsn = ntohl(chunk->subh.data_hdr->tsn);
@@ -824,7 +824,7 @@
 	 *
 	 * recvmsg() flags:
 	 *
-	 * MSG_UNORDERED - This flag is present when the message was sent
+	 * SCTP_UNORDERED - This flag is present when the message was sent
 	 *                 non-ordered.
 	 */
 	sinfo.sinfo_flags = event->flags;
@@ -839,7 +839,7 @@
 	 * This field will hold the current cumulative TSN as
 	 * known by the underlying SCTP layer.  Note this field is
 	 * ignored when sending and only valid for a receive
-	 * operation when sinfo_flags are set to MSG_UNORDERED.
+	 * operation when sinfo_flags are set to SCTP_UNORDERED.
 	 */
 	sinfo.sinfo_cumtsn = event->cumtsn;
 	/* sinfo_assoc_id: sizeof (sctp_assoc_t)
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 46a2ce0..cdcab9c 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -6,7 +6,7 @@
 obj-$(CONFIG_SUNRPC) += sunrpc.o
 obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 
-sunrpc-y := clnt.o xprt.o sched.o \
+sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
 	    auth.o auth_null.o auth_unix.o \
 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
 	    pmap_clnt.o timer.o xdr.o \
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 505e2d4..a415d99 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/socket.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/spinlock.h>
 
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
index fe1b874..f3431a7 100644
--- a/net/sunrpc/auth_gss/Makefile
+++ b/net/sunrpc/auth_gss/Makefile
@@ -10,7 +10,7 @@
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
-	gss_krb5_seqnum.o
+	gss_krb5_seqnum.o gss_krb5_wrap.o
 
 obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 2f7b867..f44f46f 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -42,9 +42,8 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sched.h>
+#include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/auth_gss.h>
@@ -846,10 +845,8 @@
 
 	/* We compute the checksum for the verifier over the xdr-encoded bytes
 	 * starting with the xid and ending at the end of the credential: */
-	iov.iov_base = req->rq_snd_buf.head[0].iov_base;
-	if (task->tk_client->cl_xprt->stream)
-		/* See clnt.c:call_header() */
-		iov.iov_base += 4;
+	iov.iov_base = xprt_skip_transport_header(task->tk_xprt,
+					req->rq_snd_buf.head[0].iov_base);
 	iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;
 	xdr_buf_from_iov(&iov, &verf_buf);
 
@@ -857,9 +854,7 @@
 	*p++ = htonl(RPC_AUTH_GSS);
 
 	mic.data = (u8 *)(p + 1);
-	maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-			       GSS_C_QOP_DEFAULT, 
-			       &verf_buf, &mic);
+	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	} else if (maj_stat != 0) {
@@ -890,10 +885,8 @@
 gss_validate(struct rpc_task *task, u32 *p)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
-	struct gss_cred	*gss_cred = container_of(cred, struct gss_cred,
-						gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
-	u32		seq, qop_state;
+	u32		seq;
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
 	struct xdr_netobj mic;
@@ -914,23 +907,14 @@
 	mic.data = (u8 *)p;
 	mic.len = len;
 
-	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state);
+	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat)
 		goto out_bad;
-       switch (gss_cred->gc_service) {
-       case RPC_GSS_SVC_NONE:
-	       /* verifier data, flavor, length: */
-	       task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
-	       break;
-       case RPC_GSS_SVC_INTEGRITY:
-	       /* verifier data, flavor, length, length, sequence number: */
-	       task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
-	       break;
-       case RPC_GSS_SVC_PRIVACY:
-	       goto out_bad;
-       }
+	/* We leave it to unwrap to calculate au_rslack. For now we just
+	 * calculate the length of the verifier: */
+	task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
 	gss_put_ctx(ctx);
 	dprintk("RPC: %4u GSS gss_validate: gss_verify_mic succeeded.\n",
 			task->tk_pid);
@@ -975,8 +959,7 @@
 	p = iov->iov_base + iov->iov_len;
 	mic.data = (u8 *)(p + 1);
 
-	maj_stat = gss_get_mic(ctx->gc_gss_ctx,
-			GSS_C_QOP_DEFAULT, &integ_buf, &mic);
+	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
 	status = -EIO; /* XXX? */
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
@@ -990,6 +973,113 @@
 	return 0;
 }
 
+static void
+priv_release_snd_buf(struct rpc_rqst *rqstp)
+{
+	int i;
+
+	for (i=0; i < rqstp->rq_enc_pages_num; i++)
+		__free_page(rqstp->rq_enc_pages[i]);
+	kfree(rqstp->rq_enc_pages);
+}
+
+static int
+alloc_enc_pages(struct rpc_rqst *rqstp)
+{
+	struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
+	int first, last, i;
+
+	if (snd_buf->page_len == 0) {
+		rqstp->rq_enc_pages_num = 0;
+		return 0;
+	}
+
+	first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
+	last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_CACHE_SHIFT;
+	rqstp->rq_enc_pages_num = last - first + 1 + 1;
+	rqstp->rq_enc_pages
+		= kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *),
+				GFP_NOFS);
+	if (!rqstp->rq_enc_pages)
+		goto out;
+	for (i=0; i < rqstp->rq_enc_pages_num; i++) {
+		rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS);
+		if (rqstp->rq_enc_pages[i] == NULL)
+			goto out_free;
+	}
+	rqstp->rq_release_snd_buf = priv_release_snd_buf;
+	return 0;
+out_free:
+	for (i--; i >= 0; i--) {
+		__free_page(rqstp->rq_enc_pages[i]);
+	}
+out:
+	return -EAGAIN;
+}
+
+static inline int
+gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+		kxdrproc_t encode, struct rpc_rqst *rqstp, u32 *p, void *obj)
+{
+	struct xdr_buf	*snd_buf = &rqstp->rq_snd_buf;
+	u32		offset;
+	u32             maj_stat;
+	int		status;
+	u32		*opaque_len;
+	struct page	**inpages;
+	int		first;
+	int		pad;
+	struct kvec	*iov;
+	char		*tmp;
+
+	opaque_len = p++;
+	offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
+	*p++ = htonl(rqstp->rq_seqno);
+
+	status = encode(rqstp, p, obj);
+	if (status)
+		return status;
+
+	status = alloc_enc_pages(rqstp);
+	if (status)
+		return status;
+	first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
+	inpages = snd_buf->pages + first;
+	snd_buf->pages = rqstp->rq_enc_pages;
+	snd_buf->page_base -= first << PAGE_CACHE_SHIFT;
+	/* Give the tail its own page, in case we need extra space in the
+	 * head when wrapping: */
+	if (snd_buf->page_len || snd_buf->tail[0].iov_len) {
+		tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]);
+		memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
+		snd_buf->tail[0].iov_base = tmp;
+	}
+	maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
+	/* RPC_SLACK_SPACE should prevent this ever happening: */
+	BUG_ON(snd_buf->len > snd_buf->buflen);
+        status = -EIO;
+	/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
+	 * done anyway, so it's safe to put the request on the wire: */
+	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+	else if (maj_stat)
+		return status;
+
+	*opaque_len = htonl(snd_buf->len - offset);
+	/* guess whether we're in the head or the tail: */
+	if (snd_buf->page_len || snd_buf->tail[0].iov_len)
+		iov = snd_buf->tail;
+	else
+		iov = snd_buf->head;
+	p = iov->iov_base + iov->iov_len;
+	pad = 3 - ((snd_buf->len - offset - 1) & 3);
+	memset(p, 0, pad);
+	iov->iov_len += pad;
+	snd_buf->len += pad;
+
+	return 0;
+}
+
 static int
 gss_wrap_req(struct rpc_task *task,
 	     kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
@@ -1017,6 +1107,8 @@
 								rqstp, p, obj);
 			break;
        		case RPC_GSS_SVC_PRIVACY:
+			status = gss_wrap_req_priv(cred, ctx, encode,
+					rqstp, p, obj);
 			break;
 	}
 out:
@@ -1054,8 +1146,7 @@
 	if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
 		return status;
 
-	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
-			&mic, NULL);
+	maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
 	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat != GSS_S_COMPLETE)
@@ -1063,6 +1154,35 @@
 	return 0;
 }
 
+static inline int
+gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
+		struct rpc_rqst *rqstp, u32 **p)
+{
+	struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
+	u32 offset;
+	u32 opaque_len;
+	u32 maj_stat;
+	int status = -EIO;
+
+	opaque_len = ntohl(*(*p)++);
+	offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base;
+	if (offset + opaque_len > rcv_buf->len)
+		return status;
+	/* remove padding: */
+	rcv_buf->len = offset + opaque_len;
+
+	maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
+	if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+	if (maj_stat != GSS_S_COMPLETE)
+		return status;
+	if (ntohl(*(*p)++) != rqstp->rq_seqno)
+		return status;
+
+	return 0;
+}
+
+
 static int
 gss_unwrap_resp(struct rpc_task *task,
 		kxdrproc_t decode, void *rqstp, u32 *p, void *obj)
@@ -1071,6 +1191,9 @@
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
 			gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
+	u32		*savedp = p;
+	struct kvec	*head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
+	int		savedlen = head->iov_len;
 	int             status = -EIO;
 
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA)
@@ -1084,8 +1207,14 @@
 				goto out;
 			break;
        		case RPC_GSS_SVC_PRIVACY:
+			status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
+			if (status)
+				goto out;
 			break;
 	}
+	/* take into account extra slack for integrity and privacy cases: */
+	task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
+						+ (savedlen - head->iov_len);
 out_decode:
 	status = decode(rqstp, p, obj);
 out:
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index ee6ae74..97c981f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -37,7 +37,7 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 #include <linux/crypto.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
@@ -75,9 +75,7 @@
 		memcpy(local_iv, iv, crypto_tfm_alg_ivsize(tfm));
 
 	memcpy(out, in, length);
-	sg[0].page = virt_to_page(out);
-	sg[0].offset = offset_in_page(out);
-	sg[0].length = length;
+	sg_set_buf(sg, out, length);
 
 	ret = crypto_cipher_encrypt_iv(tfm, sg, sg, length, local_iv);
 
@@ -117,9 +115,7 @@
 		memcpy(local_iv,iv, crypto_tfm_alg_ivsize(tfm));
 
 	memcpy(out, in, length);
-	sg[0].page = virt_to_page(out);
-	sg[0].offset = offset_in_page(out);
-	sg[0].length = length;
+	sg_set_buf(sg, out, length);
 
 	ret = crypto_cipher_decrypt_iv(tfm, sg, sg, length, local_iv);
 
@@ -132,24 +128,91 @@
 
 EXPORT_SYMBOL(krb5_decrypt);
 
-static void
-buf_to_sg(struct scatterlist *sg, char *ptr, int len) {
-	sg->page = virt_to_page(ptr);
-	sg->offset = offset_in_page(ptr);
-	sg->length = len;
+static int
+process_xdr_buf(struct xdr_buf *buf, int offset, int len,
+		int (*actor)(struct scatterlist *, void *), void *data)
+{
+	int i, page_len, thislen, page_offset, ret = 0;
+	struct scatterlist	sg[1];
+
+	if (offset >= buf->head[0].iov_len) {
+		offset -= buf->head[0].iov_len;
+	} else {
+		thislen = buf->head[0].iov_len - offset;
+		if (thislen > len)
+			thislen = len;
+		sg_set_buf(sg, buf->head[0].iov_base + offset, thislen);
+		ret = actor(sg, data);
+		if (ret)
+			goto out;
+		offset = 0;
+		len -= thislen;
+	}
+	if (len == 0)
+		goto out;
+
+	if (offset >= buf->page_len) {
+		offset -= buf->page_len;
+	} else {
+		page_len = buf->page_len - offset;
+		if (page_len > len)
+			page_len = len;
+		len -= page_len;
+		page_offset = (offset + buf->page_base) & (PAGE_CACHE_SIZE - 1);
+		i = (offset + buf->page_base) >> PAGE_CACHE_SHIFT;
+		thislen = PAGE_CACHE_SIZE - page_offset;
+		do {
+			if (thislen > page_len)
+				thislen = page_len;
+			sg->page = buf->pages[i];
+			sg->offset = page_offset;
+			sg->length = thislen;
+			ret = actor(sg, data);
+			if (ret)
+				goto out;
+			page_len -= thislen;
+			i++;
+			page_offset = 0;
+			thislen = PAGE_CACHE_SIZE;
+		} while (page_len != 0);
+		offset = 0;
+	}
+	if (len == 0)
+		goto out;
+
+	if (offset < buf->tail[0].iov_len) {
+		thislen = buf->tail[0].iov_len - offset;
+		if (thislen > len)
+			thislen = len;
+		sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen);
+		ret = actor(sg, data);
+		len -= thislen;
+	}
+	if (len != 0)
+		ret = -EINVAL;
+out:
+	return ret;
+}
+
+static int
+checksummer(struct scatterlist *sg, void *data)
+{
+	struct crypto_tfm *tfm = (struct crypto_tfm *)data;
+
+	crypto_digest_update(tfm, sg, 1);
+
+	return 0;
 }
 
 /* checksum the plaintext data and hdrlen bytes of the token header */
 s32
 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
-		   struct xdr_netobj *cksum)
+		   int body_offset, struct xdr_netobj *cksum)
 {
 	char                            *cksumname;
 	struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
 	struct scatterlist              sg[1];
 	u32                             code = GSS_S_FAILURE;
-	int				len, thislen, offset;
-	int				i;
 
 	switch (cksumtype) {
 		case CKSUMTYPE_RSA_MD5:
@@ -167,35 +230,10 @@
 		goto out;
 
 	crypto_digest_init(tfm);
-	buf_to_sg(sg, header, hdrlen);
+	sg_set_buf(sg, header, hdrlen);
 	crypto_digest_update(tfm, sg, 1);
-	if (body->head[0].iov_len) {
-		buf_to_sg(sg, body->head[0].iov_base, body->head[0].iov_len);
-		crypto_digest_update(tfm, sg, 1);
-	}
-
-	len = body->page_len;
-	if (len != 0) {
-		offset = body->page_base & (PAGE_CACHE_SIZE - 1);
-		i = body->page_base >> PAGE_CACHE_SHIFT;
-		thislen = PAGE_CACHE_SIZE - offset;
-		do {
-			if (thislen > len)
-				thislen = len;
-			sg->page = body->pages[i];
-			sg->offset = offset;
-			sg->length = thislen;
-			crypto_digest_update(tfm, sg, 1);
-			len -= thislen;
-			i++;
-			offset = 0;
-			thislen = PAGE_CACHE_SIZE;
-		} while(len != 0);
-	}
-	if (body->tail[0].iov_len) {
-		buf_to_sg(sg, body->tail[0].iov_base, body->tail[0].iov_len);
-		crypto_digest_update(tfm, sg, 1);
-	}
+	process_xdr_buf(body, body_offset, body->len - body_offset,
+			checksummer, tfm);
 	crypto_digest_final(tfm, cksum->data);
 	code = 0;
 out:
@@ -204,3 +242,154 @@
 }
 
 EXPORT_SYMBOL(make_checksum);
+
+struct encryptor_desc {
+	u8 iv[8]; /* XXX hard-coded blocksize */
+	struct crypto_tfm *tfm;
+	int pos;
+	struct xdr_buf *outbuf;
+	struct page **pages;
+	struct scatterlist infrags[4];
+	struct scatterlist outfrags[4];
+	int fragno;
+	int fraglen;
+};
+
+static int
+encryptor(struct scatterlist *sg, void *data)
+{
+	struct encryptor_desc *desc = data;
+	struct xdr_buf *outbuf = desc->outbuf;
+	struct page *in_page;
+	int thislen = desc->fraglen + sg->length;
+	int fraglen, ret;
+	int page_pos;
+
+	/* Worst case is 4 fragments: head, end of page 1, start
+	 * of page 2, tail.  Anything more is a bug. */
+	BUG_ON(desc->fragno > 3);
+	desc->infrags[desc->fragno] = *sg;
+	desc->outfrags[desc->fragno] = *sg;
+
+	page_pos = desc->pos - outbuf->head[0].iov_len;
+	if (page_pos >= 0 && page_pos < outbuf->page_len) {
+		/* pages are not in place: */
+		int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT;
+		in_page = desc->pages[i];
+	} else {
+		in_page = sg->page;
+	}
+	desc->infrags[desc->fragno].page = in_page;
+	desc->fragno++;
+	desc->fraglen += sg->length;
+	desc->pos += sg->length;
+
+	fraglen = thislen & 7; /* XXX hardcoded blocksize */
+	thislen -= fraglen;
+
+	if (thislen == 0)
+		return 0;
+
+	ret = crypto_cipher_encrypt_iv(desc->tfm, desc->outfrags, desc->infrags,
+					thislen, desc->iv);
+	if (ret)
+		return ret;
+	if (fraglen) {
+		desc->outfrags[0].page = sg->page;
+		desc->outfrags[0].offset = sg->offset + sg->length - fraglen;
+		desc->outfrags[0].length = fraglen;
+		desc->infrags[0] = desc->outfrags[0];
+		desc->infrags[0].page = in_page;
+		desc->fragno = 1;
+		desc->fraglen = fraglen;
+	} else {
+		desc->fragno = 0;
+		desc->fraglen = 0;
+	}
+	return 0;
+}
+
+int
+gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset,
+		struct page **pages)
+{
+	int ret;
+	struct encryptor_desc desc;
+
+	BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
+
+	memset(desc.iv, 0, sizeof(desc.iv));
+	desc.tfm = tfm;
+	desc.pos = offset;
+	desc.outbuf = buf;
+	desc.pages = pages;
+	desc.fragno = 0;
+	desc.fraglen = 0;
+
+	ret = process_xdr_buf(buf, offset, buf->len - offset, encryptor, &desc);
+	return ret;
+}
+
+EXPORT_SYMBOL(gss_encrypt_xdr_buf);
+
+struct decryptor_desc {
+	u8 iv[8]; /* XXX hard-coded blocksize */
+	struct crypto_tfm *tfm;
+	struct scatterlist frags[4];
+	int fragno;
+	int fraglen;
+};
+
+static int
+decryptor(struct scatterlist *sg, void *data)
+{
+	struct decryptor_desc *desc = data;
+	int thislen = desc->fraglen + sg->length;
+	int fraglen, ret;
+
+	/* Worst case is 4 fragments: head, end of page 1, start
+	 * of page 2, tail.  Anything more is a bug. */
+	BUG_ON(desc->fragno > 3);
+	desc->frags[desc->fragno] = *sg;
+	desc->fragno++;
+	desc->fraglen += sg->length;
+
+	fraglen = thislen & 7; /* XXX hardcoded blocksize */
+	thislen -= fraglen;
+
+	if (thislen == 0)
+		return 0;
+
+	ret = crypto_cipher_decrypt_iv(desc->tfm, desc->frags, desc->frags,
+					thislen, desc->iv);
+	if (ret)
+		return ret;
+	if (fraglen) {
+		desc->frags[0].page = sg->page;
+		desc->frags[0].offset = sg->offset + sg->length - fraglen;
+		desc->frags[0].length = fraglen;
+		desc->fragno = 1;
+		desc->fraglen = fraglen;
+	} else {
+		desc->fragno = 0;
+		desc->fraglen = 0;
+	}
+	return 0;
+}
+
+int
+gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset)
+{
+	struct decryptor_desc desc;
+
+	/* XXXJBF: */
+	BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0);
+
+	memset(desc.iv, 0, sizeof(desc.iv));
+	desc.tfm = tfm;
+	desc.fragno = 0;
+	desc.fraglen = 0;
+	return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc);
+}
+
+EXPORT_SYMBOL(gss_decrypt_xdr_buf);
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 606a8a8..5f1f806 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -39,7 +39,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/auth.h>
-#include <linux/in.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/crypto.h>
@@ -191,43 +190,12 @@
 	kfree(kctx);
 }
 
-static u32
-gss_verify_mic_kerberos(struct gss_ctx		*ctx,
-			struct xdr_buf		*message,
-			struct xdr_netobj	*mic_token,
-			u32			*qstate) {
-	u32 maj_stat = 0;
-	int qop_state;
-	struct krb5_ctx *kctx = ctx->internal_ctx_id;
-
-	maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state,
-				   KG_TOK_MIC_MSG);
-	if (!maj_stat && qop_state)
-	    *qstate = qop_state;
-
-	dprintk("RPC:      gss_verify_mic_kerberos returning %d\n", maj_stat);
-	return maj_stat;
-}
-
-static u32
-gss_get_mic_kerberos(struct gss_ctx	*ctx,
-		     u32		qop,
-		     struct xdr_buf 	*message,
-		     struct xdr_netobj	*mic_token) {
-	u32 err = 0;
-	struct krb5_ctx *kctx = ctx->internal_ctx_id;
-
-	err = krb5_make_token(kctx, qop, message, mic_token, KG_TOK_MIC_MSG);
-
-	dprintk("RPC:      gss_get_mic_kerberos returning %d\n",err);
-
-	return err;
-}
-
 static struct gss_api_ops gss_kerberos_ops = {
 	.gss_import_sec_context	= gss_import_sec_context_kerberos,
 	.gss_get_mic		= gss_get_mic_kerberos,
 	.gss_verify_mic		= gss_verify_mic_kerberos,
+	.gss_wrap		= gss_wrap_kerberos,
+	.gss_unwrap		= gss_unwrap_kerberos,
 	.gss_delete_sec_context	= gss_delete_sec_context_kerberos,
 };
 
@@ -242,6 +210,11 @@
 		.service = RPC_GSS_SVC_INTEGRITY,
 		.name = "krb5i",
 	},
+	[2] = {
+		.pseudoflavor = RPC_AUTH_GSS_KRB5P,
+		.service = RPC_GSS_SVC_PRIVACY,
+		.name = "krb5p",
+	},
 };
 
 static struct gss_api_mech gss_kerberos_mech = {
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index afeeb87..13f8ae9 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -70,22 +70,13 @@
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
-static inline int
-gss_krb5_padding(int blocksize, int length) {
-	/* Most of the code is block-size independent but in practice we
-	 * use only 8: */
-	BUG_ON(blocksize != 8);
-	return 8 - (length & 7);
-}
-
 u32
-krb5_make_token(struct krb5_ctx *ctx, int qop_req,
-		   struct xdr_buf *text, struct xdr_netobj *token,
-		   int toktype)
+gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+		struct xdr_netobj *token)
 {
+	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
 	s32			checksum_type;
 	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
-	int			blocksize = 0, tmsglen;
 	unsigned char		*ptr, *krb5_hdr, *msg_start;
 	s32			now;
 
@@ -93,9 +84,6 @@
 
 	now = get_seconds();
 
-	if (qop_req != 0)
-		goto out_err;
-
 	switch (ctx->signalg) {
 		case SGN_ALG_DES_MAC_MD5:
 			checksum_type = CKSUMTYPE_RSA_MD5;
@@ -111,21 +99,13 @@
 		goto out_err;
 	}
 
-	if (toktype == KG_TOK_WRAP_MSG) {
-		blocksize = crypto_tfm_alg_blocksize(ctx->enc);
-		tmsglen = blocksize + text->len
-			+ gss_krb5_padding(blocksize, blocksize + text->len);
-	} else {
-		tmsglen = 0;
-	}
-
-	token->len = g_token_size(&ctx->mech_used, 22 + tmsglen);
+	token->len = g_token_size(&ctx->mech_used, 22);
 
 	ptr = token->data;
-	g_make_token_header(&ctx->mech_used, 22 + tmsglen, &ptr);
+	g_make_token_header(&ctx->mech_used, 22, &ptr);
 
-	*ptr++ = (unsigned char) ((toktype>>8)&0xff);
-	*ptr++ = (unsigned char) (toktype&0xff);
+	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
 
 	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
 	krb5_hdr = ptr - 2;
@@ -133,17 +113,9 @@
 
 	*(u16 *)(krb5_hdr + 2) = htons(ctx->signalg);
 	memset(krb5_hdr + 4, 0xff, 4);
-	if (toktype == KG_TOK_WRAP_MSG)
-		*(u16 *)(krb5_hdr + 4) = htons(ctx->sealalg);
 
-	if (toktype == KG_TOK_WRAP_MSG) {
-		/* XXX removing support for now */
-		goto out_err;
-	} else { /* Sign only.  */
-		if (make_checksum(checksum_type, krb5_hdr, 8, text,
-				       &md5cksum))
+	if (make_checksum(checksum_type, krb5_hdr, 8, text, 0, &md5cksum))
 			goto out_err;
-	}
 
 	switch (ctx->signalg) {
 	case SGN_ALG_DES_MAC_MD5:
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 8767fc5..2030475 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -68,21 +68,14 @@
 #endif
 
 
-/* message_buffer is an input if toktype is MIC and an output if it is WRAP:
- * If toktype is MIC: read_token is a mic token, and message_buffer is the
- *   data that the mic was supposedly taken over.
- * If toktype is WRAP: read_token is a wrap token, and message_buffer is used
- *   to return the decrypted data.
- */
+/* read_token is a mic token, and message_buffer is the data that the mic was
+ * supposedly taken over. */
 
-/* XXX will need to change prototype and/or just split into a separate function
- * when we add privacy (because read_token will be in pages too). */
 u32
-krb5_read_token(struct krb5_ctx *ctx,
-		struct xdr_netobj *read_token,
-		struct xdr_buf *message_buffer,
-		int *qop_state, int toktype)
+gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+		struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
 {
+	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
 	int			signalg;
 	int			sealalg;
 	s32			checksum_type;
@@ -100,16 +93,12 @@
 					read_token->len))
 		goto out;
 
-	if ((*ptr++ != ((toktype>>8)&0xff)) || (*ptr++ != (toktype&0xff)))
+	if ((*ptr++ != ((KG_TOK_MIC_MSG>>8)&0xff)) ||
+	    (*ptr++ != ( KG_TOK_MIC_MSG    &0xff))   )
 		goto out;
 
 	/* XXX sanity-check bodysize?? */
 
-	if (toktype == KG_TOK_WRAP_MSG) {
-		/* XXX gone */
-		goto out;
-	}
-
 	/* get the sign and seal algorithms */
 
 	signalg = ptr[0] + (ptr[1] << 8);
@@ -120,14 +109,7 @@
 	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
 		goto out;
 
-	if (((toktype != KG_TOK_WRAP_MSG) && (sealalg != 0xffff)) ||
-	    ((toktype == KG_TOK_WRAP_MSG) && (sealalg == 0xffff)))
-		goto out;
-
-	/* in the current spec, there is only one valid seal algorithm per
-	   key type, so a simple comparison is ok */
-
-	if ((toktype == KG_TOK_WRAP_MSG) && !(sealalg == ctx->sealalg))
+	if (sealalg != 0xffff)
 		goto out;
 
 	/* there are several mappings of seal algorithms to sign algorithms,
@@ -154,7 +136,7 @@
 	switch (signalg) {
 	case SGN_ALG_DES_MAC_MD5:
 		ret = make_checksum(checksum_type, ptr - 2, 8,
-					 message_buffer, &md5cksum);
+					 message_buffer, 0, &md5cksum);
 		if (ret)
 			goto out;
 
@@ -175,9 +157,6 @@
 
 	/* it got through unscathed.  Make sure the context is unexpired */
 
-	if (qop_state)
-		*qop_state = GSS_C_QOP_DEFAULT;
-
 	now = get_seconds();
 
 	ret = GSS_S_CONTEXT_EXPIRED;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
new file mode 100644
index 0000000..af777cf
--- /dev/null
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -0,0 +1,363 @@
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_krb5.h>
+#include <linux/random.h>
+#include <linux/pagemap.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY	RPCDBG_AUTH
+#endif
+
+static inline int
+gss_krb5_padding(int blocksize, int length)
+{
+	/* Most of the code is block-size independent but currently we
+	 * use only 8: */
+	BUG_ON(blocksize != 8);
+	return 8 - (length & 7);
+}
+
+static inline void
+gss_krb5_add_padding(struct xdr_buf *buf, int offset, int blocksize)
+{
+	int padding = gss_krb5_padding(blocksize, buf->len - offset);
+	char *p;
+	struct kvec *iov;
+
+	if (buf->page_len || buf->tail[0].iov_len)
+		iov = &buf->tail[0];
+	else
+		iov = &buf->head[0];
+	p = iov->iov_base + iov->iov_len;
+	iov->iov_len += padding;
+	buf->len += padding;
+	memset(p, padding, padding);
+}
+
+static inline int
+gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
+{
+	u8 *ptr;
+	u8 pad;
+	int len = buf->len;
+
+	if (len <= buf->head[0].iov_len) {
+		pad = *(u8 *)(buf->head[0].iov_base + len - 1);
+		if (pad > buf->head[0].iov_len)
+			return -EINVAL;
+		buf->head[0].iov_len -= pad;
+		goto out;
+	} else
+		len -= buf->head[0].iov_len;
+	if (len <= buf->page_len) {
+		int last = (buf->page_base + len - 1)
+					>>PAGE_CACHE_SHIFT;
+		int offset = (buf->page_base + len - 1)
+					& (PAGE_CACHE_SIZE - 1);
+		ptr = kmap_atomic(buf->pages[last], KM_SKB_SUNRPC_DATA);
+		pad = *(ptr + offset);
+		kunmap_atomic(ptr, KM_SKB_SUNRPC_DATA);
+		goto out;
+	} else
+		len -= buf->page_len;
+	BUG_ON(len > buf->tail[0].iov_len);
+	pad = *(u8 *)(buf->tail[0].iov_base + len - 1);
+out:
+	/* XXX: NOTE: we do not adjust the page lengths--they represent
+	 * a range of data in the real filesystem page cache, and we need
+	 * to know that range so the xdr code can properly place read data.
+	 * However adjusting the head length, as we do above, is harmless.
+	 * In the case of a request that fits into a single page, the server
+	 * also uses length and head length together to determine the original
+	 * start of the request to copy the request for deferal; so it's
+	 * easier on the server if we adjust head and tail length in tandem.
+	 * It's not really a problem that we don't fool with the page and
+	 * tail lengths, though--at worst badly formed xdr might lead the
+	 * server to attempt to parse the padding.
+	 * XXX: Document all these weird requirements for gss mechanism
+	 * wrap/unwrap functions. */
+	if (pad > blocksize)
+		return -EINVAL;
+	if (buf->len > pad)
+		buf->len -= pad;
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static inline void
+make_confounder(char *p, int blocksize)
+{
+	static u64 i = 0;
+	u64 *q = (u64 *)p;
+
+	/* rfc1964 claims this should be "random".  But all that's really
+	 * necessary is that it be unique.  And not even that is necessary in
+	 * our case since our "gssapi" implementation exists only to support
+	 * rpcsec_gss, so we know that the only buffers we will ever encrypt
+	 * already begin with a unique sequence number.  Just to hedge my bets
+	 * I'll make a half-hearted attempt at something unique, but ensuring
+	 * uniqueness would mean worrying about atomicity and rollover, and I
+	 * don't care enough. */
+
+	BUG_ON(blocksize != 8);
+	*q = i++;
+}
+
+/* Assumptions: the head and tail of inbuf are ours to play with.
+ * The pages, however, may be real pages in the page cache and we replace
+ * them with scratch pages from **pages before writing to them. */
+/* XXX: obviously the above should be documentation of wrap interface,
+ * and shouldn't be in this kerberos-specific file. */
+
+/* XXX factor out common code with seal/unseal. */
+
+u32
+gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+		struct xdr_buf *buf, struct page **pages)
+{
+	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
+	s32			checksum_type;
+	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
+	int			blocksize = 0, plainlen;
+	unsigned char		*ptr, *krb5_hdr, *msg_start;
+	s32			now;
+	int			headlen;
+	struct page		**tmp_pages;
+
+	dprintk("RPC:     gss_wrap_kerberos\n");
+
+	now = get_seconds();
+
+	switch (kctx->signalg) {
+		case SGN_ALG_DES_MAC_MD5:
+			checksum_type = CKSUMTYPE_RSA_MD5;
+			break;
+		default:
+			dprintk("RPC:      gss_krb5_seal: kctx->signalg %d not"
+				" supported\n", kctx->signalg);
+			goto out_err;
+	}
+	if (kctx->sealalg != SEAL_ALG_NONE && kctx->sealalg != SEAL_ALG_DES) {
+		dprintk("RPC:      gss_krb5_seal: kctx->sealalg %d not supported\n",
+			kctx->sealalg);
+		goto out_err;
+	}
+
+	blocksize = crypto_tfm_alg_blocksize(kctx->enc);
+	gss_krb5_add_padding(buf, offset, blocksize);
+	BUG_ON((buf->len - offset) % blocksize);
+	plainlen = blocksize + buf->len - offset;
+
+	headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
+						(buf->len - offset);
+
+	ptr = buf->head[0].iov_base + offset;
+	/* shift data to make room for header. */
+	/* XXX Would be cleverer to encrypt while copying. */
+	/* XXX bounds checking, slack, etc. */
+	memmove(ptr + headlen, ptr, buf->head[0].iov_len - offset);
+	buf->head[0].iov_len += headlen;
+	buf->len += headlen;
+	BUG_ON((buf->len - offset - headlen) % blocksize);
+
+	g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
+
+
+	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+	*ptr++ = (unsigned char) (KG_TOK_WRAP_MSG&0xff);
+
+	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
+	krb5_hdr = ptr - 2;
+	msg_start = krb5_hdr + 24;
+	/* XXXJBF: */ BUG_ON(buf->head[0].iov_base + offset + headlen != msg_start + blocksize);
+
+	*(u16 *)(krb5_hdr + 2) = htons(kctx->signalg);
+	memset(krb5_hdr + 4, 0xff, 4);
+	*(u16 *)(krb5_hdr + 4) = htons(kctx->sealalg);
+
+	make_confounder(msg_start, blocksize);
+
+	/* XXXJBF: UGH!: */
+	tmp_pages = buf->pages;
+	buf->pages = pages;
+	if (make_checksum(checksum_type, krb5_hdr, 8, buf,
+				offset + headlen - blocksize, &md5cksum))
+		goto out_err;
+	buf->pages = tmp_pages;
+
+	switch (kctx->signalg) {
+	case SGN_ALG_DES_MAC_MD5:
+		if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+				  md5cksum.data, md5cksum.len))
+			goto out_err;
+		memcpy(krb5_hdr + 16,
+		       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+		       KRB5_CKSUM_LENGTH);
+
+		dprintk("RPC:      make_seal_token: cksum data: \n");
+		print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
+		break;
+	default:
+		BUG();
+	}
+
+	kfree(md5cksum.data);
+
+	/* XXX would probably be more efficient to compute checksum
+	 * and encrypt at the same time: */
+	if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
+			       kctx->seq_send, krb5_hdr + 16, krb5_hdr + 8)))
+		goto out_err;
+
+	if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
+									pages))
+		goto out_err;
+
+	kctx->seq_send++;
+
+	return ((kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
+out_err:
+	if (md5cksum.data) kfree(md5cksum.data);
+	return GSS_S_FAILURE;
+}
+
+u32
+gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+{
+	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
+	int			signalg;
+	int			sealalg;
+	s32			checksum_type;
+	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
+	s32			now;
+	int			direction;
+	s32			seqnum;
+	unsigned char		*ptr;
+	int			bodysize;
+	u32			ret = GSS_S_DEFECTIVE_TOKEN;
+	void			*data_start, *orig_start;
+	int			data_len;
+	int			blocksize;
+
+	dprintk("RPC:      gss_unwrap_kerberos\n");
+
+	ptr = (u8 *)buf->head[0].iov_base + offset;
+	if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
+					buf->len - offset))
+		goto out;
+
+	if ((*ptr++ != ((KG_TOK_WRAP_MSG>>8)&0xff)) ||
+	    (*ptr++ !=  (KG_TOK_WRAP_MSG    &0xff))   )
+		goto out;
+
+	/* XXX sanity-check bodysize?? */
+
+	/* get the sign and seal algorithms */
+
+	signalg = ptr[0] + (ptr[1] << 8);
+	sealalg = ptr[2] + (ptr[3] << 8);
+
+	/* Sanity checks */
+
+	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
+		goto out;
+
+	if (sealalg == 0xffff)
+		goto out;
+
+	/* in the current spec, there is only one valid seal algorithm per
+	   key type, so a simple comparison is ok */
+
+	if (sealalg != kctx->sealalg)
+		goto out;
+
+	/* there are several mappings of seal algorithms to sign algorithms,
+	   but few enough that we can try them all. */
+
+	if ((kctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
+	    (kctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
+	    (kctx->sealalg == SEAL_ALG_DES3KD &&
+	     signalg != SGN_ALG_HMAC_SHA1_DES3_KD))
+		goto out;
+
+	if (gss_decrypt_xdr_buf(kctx->enc, buf,
+			ptr + 22 - (unsigned char *)buf->head[0].iov_base))
+		goto out;
+
+	/* compute the checksum of the message */
+
+	/* initialize the the cksum */
+	switch (signalg) {
+	case SGN_ALG_DES_MAC_MD5:
+		checksum_type = CKSUMTYPE_RSA_MD5;
+		break;
+	default:
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto out;
+	}
+
+	switch (signalg) {
+	case SGN_ALG_DES_MAC_MD5:
+		ret = make_checksum(checksum_type, ptr - 2, 8, buf,
+			 ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum);
+		if (ret)
+			goto out;
+
+		ret = krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+				   md5cksum.data, md5cksum.len);
+		if (ret)
+			goto out;
+
+		if (memcmp(md5cksum.data + 8, ptr + 14, 8)) {
+			ret = GSS_S_BAD_SIG;
+			goto out;
+		}
+		break;
+	default:
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		goto out;
+	}
+
+	/* it got through unscathed.  Make sure the context is unexpired */
+
+	now = get_seconds();
+
+	ret = GSS_S_CONTEXT_EXPIRED;
+	if (now > kctx->endtime)
+		goto out;
+
+	/* do sequencing checks */
+
+	ret = GSS_S_BAD_SIG;
+	if ((ret = krb5_get_seq_num(kctx->seq, ptr + 14, ptr + 6, &direction,
+				    &seqnum)))
+		goto out;
+
+	if ((kctx->initiate && direction != 0xff) ||
+	    (!kctx->initiate && direction != 0))
+		goto out;
+
+	/* Copy the data back to the right position.  XXX: Would probably be
+	 * better to copy and encrypt at the same time. */
+
+	blocksize = crypto_tfm_alg_blocksize(kctx->enc);
+	data_start = ptr + 22 + blocksize;
+	orig_start = buf->head[0].iov_base + offset;
+	data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+	memmove(orig_start, data_start, data_len);
+	buf->head[0].iov_len -= (data_start - orig_start);
+	buf->len -= (data_start - orig_start);
+
+	ret = GSS_S_DEFECTIVE_TOKEN;
+	if (gss_krb5_remove_padding(buf, blocksize))
+		goto out;
+
+	ret = GSS_S_COMPLETE;
+out:
+	if (md5cksum.data) kfree(md5cksum.data);
+	return ret;
+}
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 9dfb683..b048bf6 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -35,7 +35,6 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
 #include <linux/module.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/gss_asn1.h>
@@ -251,13 +250,11 @@
 
 u32
 gss_get_mic(struct gss_ctx	*context_handle,
-	    u32			qop,
 	    struct xdr_buf	*message,
 	    struct xdr_netobj	*mic_token)
 {
 	 return context_handle->mech_type->gm_ops
 		->gss_get_mic(context_handle,
-			      qop,
 			      message,
 			      mic_token);
 }
@@ -267,16 +264,34 @@
 u32
 gss_verify_mic(struct gss_ctx		*context_handle,
 	       struct xdr_buf		*message,
-	       struct xdr_netobj	*mic_token,
-	       u32			*qstate)
+	       struct xdr_netobj	*mic_token)
 {
 	return context_handle->mech_type->gm_ops
 		->gss_verify_mic(context_handle,
 				 message,
-				 mic_token,
-				 qstate);
+				 mic_token);
 }
 
+u32
+gss_wrap(struct gss_ctx	*ctx_id,
+	 int		offset,
+	 struct xdr_buf	*buf,
+	 struct page	**inpages)
+{
+	return ctx_id->mech_type->gm_ops
+		->gss_wrap(ctx_id, offset, buf, inpages);
+}
+
+u32
+gss_unwrap(struct gss_ctx	*ctx_id,
+	   int			offset,
+	   struct xdr_buf	*buf)
+{
+	return ctx_id->mech_type->gm_ops
+		->gss_unwrap(ctx_id, offset, buf);
+}
+
+
 /* gss_delete_sec_context: free all resources associated with context_handle.
  * Note this differs from the RFC 2744-specified prototype in that we don't
  * bother returning an output token, since it would never be used anyway. */
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 6c97d61..39b3edc 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -224,18 +224,13 @@
 static u32
 gss_verify_mic_spkm3(struct gss_ctx		*ctx,
 			struct xdr_buf		*signbuf,
-			struct xdr_netobj	*checksum,
-			u32		*qstate) {
+			struct xdr_netobj	*checksum)
+{
 	u32 maj_stat = 0;
-	int qop_state = 0;
 	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
 	dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
-	maj_stat = spkm3_read_token(sctx, checksum, signbuf, &qop_state,
-				   SPKM_MIC_TOK);
-
-	if (!maj_stat && qop_state)
-	    *qstate = qop_state;
+	maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 
 	dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
 	return maj_stat;
@@ -243,15 +238,15 @@
 
 static u32
 gss_get_mic_spkm3(struct gss_ctx	*ctx,
-		     u32		qop,
 		     struct xdr_buf	*message_buffer,
-		     struct xdr_netobj	*message_token) {
+		     struct xdr_netobj	*message_token)
+{
 	u32 err = 0;
 	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 
 	dprintk("RPC: gss_get_mic_spkm3\n");
 
-	err = spkm3_make_token(sctx, qop, message_buffer,
+	err = spkm3_make_token(sctx, message_buffer,
 			      message_token, SPKM_MIC_TOK);
 	return err;
 }
@@ -264,8 +259,8 @@
 };
 
 static struct pf_desc gss_spkm3_pfs[] = {
-	{RPC_AUTH_GSS_SPKM, 0, RPC_GSS_SVC_NONE, "spkm3"},
-	{RPC_AUTH_GSS_SPKMI, 0, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
+	{RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
+	{RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
 };
 
 static struct gss_api_mech gss_spkm3_mech = {
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index 2533986..148201e 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -51,7 +51,7 @@
  */
 
 u32
-spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
+spkm3_make_token(struct spkm3_ctx *ctx,
 		   struct xdr_buf * text, struct xdr_netobj * token,
 		   int toktype)
 {
@@ -68,8 +68,6 @@
 	dprintk("RPC: spkm3_make_token\n");
 
 	now = jiffies;
-	if (qop_req != 0)
-		goto out_err;
 
 	if (ctx->ctx_id.len != 16) {
 		dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
index 65ce81b..c3c0d95 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
@@ -52,7 +52,7 @@
 spkm3_read_token(struct spkm3_ctx *ctx,
 		struct xdr_netobj *read_token,    /* checksum */
 		struct xdr_buf *message_buffer, /* signbuf */
-		int *qop_state, int toktype)
+		int toktype)
 {
 	s32			code;
 	struct xdr_netobj	wire_cksum = {.len =0, .data = NULL};
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index e330819..e4ada15 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -566,8 +566,7 @@
 
 	if (rqstp->rq_deferred) /* skip verification of revisited request */
 		return SVC_OK;
-	if (gss_verify_mic(ctx_id, &rpchdr, &checksum, NULL)
-							!= GSS_S_COMPLETE) {
+	if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
 		*authp = rpcsec_gsserr_credproblem;
 		return SVC_DENIED;
 	}
@@ -604,7 +603,7 @@
 	xdr_buf_from_iov(&iov, &verf_data);
 	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
 	mic.data = (u8 *)(p + 1);
-	maj_stat = gss_get_mic(ctx_id, 0, &verf_data, &mic);
+	maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
 	if (maj_stat != GSS_S_COMPLETE)
 		return -1;
 	*p++ = htonl(mic.len);
@@ -710,7 +709,7 @@
 		goto out;
 	if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
 		goto out;
-	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic, NULL);
+	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
 	if (maj_stat != GSS_S_COMPLETE)
 		goto out;
 	if (ntohl(svc_getu32(&buf->head[0])) != seq)
@@ -1012,7 +1011,7 @@
 			resv = &resbuf->tail[0];
 		}
 		mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
-		if (gss_get_mic(gsd->rsci->mechctx, 0, &integ_buf, &mic))
+		if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
 			goto out_err;
 		svc_putu32(resv, htonl(mic.len));
 		memset(mic.data + mic.len, 0,
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 9b72d3a..f56767a 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -7,9 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/module.h>
-#include <linux/in.h>
 #include <linux/utsname.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sched.h>
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 4ff297a..890fb5e 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -9,8 +9,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f17e615..702ede3 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1,5 +1,5 @@
 /*
- *  linux/net/sunrpc/rpcclnt.c
+ *  linux/net/sunrpc/clnt.c
  *
  *  This file contains the high-level RPC interface.
  *  It is modeled as a finite state machine to support both synchronous
@@ -27,7 +27,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/in.h>
 #include <linux/utsname.h>
 
 #include <linux/sunrpc/clnt.h>
@@ -53,6 +52,7 @@
 static void	call_encode(struct rpc_task *task);
 static void	call_decode(struct rpc_task *task);
 static void	call_bind(struct rpc_task *task);
+static void	call_bind_status(struct rpc_task *task);
 static void	call_transmit(struct rpc_task *task);
 static void	call_status(struct rpc_task *task);
 static void	call_refresh(struct rpc_task *task);
@@ -517,15 +517,8 @@
 rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
 {
 	struct rpc_xprt *xprt = clnt->cl_xprt;
-
-	xprt->sndsize = 0;
-	if (sndsize)
-		xprt->sndsize = sndsize + RPC_SLACK_SPACE;
-	xprt->rcvsize = 0;
-	if (rcvsize)
-		xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
-	if (xprt_connected(xprt))
-		xprt_sock_setbufsize(xprt);
+	if (xprt->ops->set_buffer_size)
+		xprt->ops->set_buffer_size(xprt, sndsize, rcvsize);
 }
 
 /*
@@ -685,13 +678,11 @@
 static void
 call_encode(struct rpc_task *task)
 {
-	struct rpc_clnt	*clnt = task->tk_client;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	unsigned int	bufsiz;
 	kxdrproc_t	encode;
-	int		status;
 	u32		*p;
 
 	dprintk("RPC: %4d call_encode (status %d)\n", 
@@ -719,11 +710,15 @@
 		rpc_exit(task, -EIO);
 		return;
 	}
-	if (encode && (status = rpcauth_wrap_req(task, encode, req, p,
-						 task->tk_msg.rpc_argp)) < 0) {
-		printk(KERN_WARNING "%s: can't encode arguments: %d\n",
-				clnt->cl_protname, -status);
-		rpc_exit(task, status);
+	if (encode == NULL)
+		return;
+
+	task->tk_status = rpcauth_wrap_req(task, encode, req, p,
+			task->tk_msg.rpc_argp);
+	if (task->tk_status == -ENOMEM) {
+		/* XXX: Is this sane? */
+		rpc_delay(task, 3*HZ);
+		task->tk_status = -EAGAIN;
 	}
 }
 
@@ -734,43 +729,95 @@
 call_bind(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
 
-	dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
-			xprt, (xprt_connected(xprt) ? "is" : "is not"));
+	dprintk("RPC: %4d call_bind (status %d)\n",
+				task->tk_pid, task->tk_status);
 
-	task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect;
-
+	task->tk_action = call_connect;
 	if (!clnt->cl_port) {
-		task->tk_action = call_connect;
-		task->tk_timeout = RPC_CONNECT_TIMEOUT;
+		task->tk_action = call_bind_status;
+		task->tk_timeout = task->tk_xprt->bind_timeout;
 		rpc_getport(task, clnt);
 	}
 }
 
 /*
- * 4a.	Connect to the RPC server (TCP case)
+ * 4a.	Sort out bind result
+ */
+static void
+call_bind_status(struct rpc_task *task)
+{
+	int status = -EACCES;
+
+	if (task->tk_status >= 0) {
+		dprintk("RPC: %4d call_bind_status (status %d)\n",
+					task->tk_pid, task->tk_status);
+		task->tk_status = 0;
+		task->tk_action = call_connect;
+		return;
+	}
+
+	switch (task->tk_status) {
+	case -EACCES:
+		dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
+				task->tk_pid);
+		rpc_delay(task, 3*HZ);
+		goto retry_bind;
+	case -ETIMEDOUT:
+		dprintk("RPC: %4d rpcbind request timed out\n",
+				task->tk_pid);
+		if (RPC_IS_SOFT(task)) {
+			status = -EIO;
+			break;
+		}
+		goto retry_bind;
+	case -EPFNOSUPPORT:
+		dprintk("RPC: %4d remote rpcbind service unavailable\n",
+				task->tk_pid);
+		break;
+	case -EPROTONOSUPPORT:
+		dprintk("RPC: %4d remote rpcbind version 2 unavailable\n",
+				task->tk_pid);
+		break;
+	default:
+		dprintk("RPC: %4d unrecognized rpcbind error (%d)\n",
+				task->tk_pid, -task->tk_status);
+		status = -EIO;
+		break;
+	}
+
+	rpc_exit(task, status);
+	return;
+
+retry_bind:
+	task->tk_status = 0;
+	task->tk_action = call_bind;
+	return;
+}
+
+/*
+ * 4b.	Connect to the RPC server
  */
 static void
 call_connect(struct rpc_task *task)
 {
-	struct rpc_clnt *clnt = task->tk_client;
+	struct rpc_xprt *xprt = task->tk_xprt;
 
-	dprintk("RPC: %4d call_connect status %d\n",
-				task->tk_pid, task->tk_status);
+	dprintk("RPC: %4d call_connect xprt %p %s connected\n",
+			task->tk_pid, xprt,
+			(xprt_connected(xprt) ? "is" : "is not"));
 
-	if (xprt_connected(clnt->cl_xprt)) {
-		task->tk_action = call_transmit;
-		return;
+	task->tk_action = call_transmit;
+	if (!xprt_connected(xprt)) {
+		task->tk_action = call_connect_status;
+		if (task->tk_status < 0)
+			return;
+		xprt_connect(task);
 	}
-	task->tk_action = call_connect_status;
-	if (task->tk_status < 0)
-		return;
-	xprt_connect(task);
 }
 
 /*
- * 4b. Sort out connect result
+ * 4c.	Sort out connect result
  */
 static void
 call_connect_status(struct rpc_task *task)
@@ -778,6 +825,9 @@
 	struct rpc_clnt *clnt = task->tk_client;
 	int status = task->tk_status;
 
+	dprintk("RPC: %5u call_connect_status (status %d)\n", 
+				task->tk_pid, task->tk_status);
+
 	task->tk_status = 0;
 	if (status >= 0) {
 		clnt->cl_stats->netreconn++;
@@ -785,17 +835,19 @@
 		return;
 	}
 
-	/* Something failed: we may have to rebind */
+	/* Something failed: remote service port may have changed */
 	if (clnt->cl_autobind)
 		clnt->cl_port = 0;
+
 	switch (status) {
 	case -ENOTCONN:
 	case -ETIMEDOUT:
 	case -EAGAIN:
-		task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect;
+		task->tk_action = call_bind;
 		break;
 	default:
 		rpc_exit(task, -EIO);
+		break;
 	}
 }
 
@@ -815,10 +867,12 @@
 	if (task->tk_status != 0)
 		return;
 	/* Encode here so that rpcsec_gss can use correct sequence number. */
-	if (!task->tk_rqstp->rq_bytes_sent)
+	if (task->tk_rqstp->rq_bytes_sent == 0) {
 		call_encode(task);
-	if (task->tk_status < 0)
-		return;
+		/* Did the encode result in an error condition? */
+		if (task->tk_status != 0)
+			goto out_nosend;
+	}
 	xprt_transmit(task);
 	if (task->tk_status < 0)
 		return;
@@ -826,6 +880,10 @@
 		task->tk_action = NULL;
 		rpc_wake_up_task(task);
 	}
+	return;
+out_nosend:
+	/* release socket write lock before attempting to handle error */
+	xprt_abort_transmit(task);
 }
 
 /*
@@ -1020,13 +1078,12 @@
 call_header(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	u32		*p = req->rq_svec[0].iov_base;
 
 	/* FIXME: check buffer size? */
-	if (xprt->stream)
-		*p++ = 0;		/* fill in later */
+
+	p = xprt_skip_transport_header(task->tk_xprt, p);
 	*p++ = req->rq_xid;		/* XID */
 	*p++ = htonl(RPC_CALL);		/* CALL */
 	*p++ = htonl(RPC_VERSION);	/* RPC version */
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 4e81f27..a398575 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -26,7 +26,7 @@
 #define PMAP_GETPORT		3
 
 static struct rpc_procinfo	pmap_procedures[];
-static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
+static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int, int);
 static void			pmap_getport_done(struct rpc_task *);
 static struct rpc_program	pmap_program;
 static DEFINE_SPINLOCK(pmap_lock);
@@ -65,7 +65,7 @@
 	map->pm_binding = 1;
 	spin_unlock(&pmap_lock);
 
-	pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot);
+	pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0);
 	if (IS_ERR(pmap_clnt)) {
 		task->tk_status = PTR_ERR(pmap_clnt);
 		goto bailout;
@@ -112,7 +112,7 @@
 			NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
-	pmap_clnt = pmap_create(hostname, sin, prot);
+	pmap_clnt = pmap_create(hostname, sin, prot, 0);
 	if (IS_ERR(pmap_clnt))
 		return PTR_ERR(pmap_clnt);
 
@@ -171,7 +171,7 @@
 
 	sin.sin_family = AF_INET;
 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
+	pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
 	if (IS_ERR(pmap_clnt)) {
 		error = PTR_ERR(pmap_clnt);
 		dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
@@ -198,7 +198,7 @@
 }
 
 static struct rpc_clnt *
-pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
+pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
 {
 	struct rpc_xprt	*xprt;
 	struct rpc_clnt	*clnt;
@@ -208,6 +208,8 @@
 	if (IS_ERR(xprt))
 		return (struct rpc_clnt *)xprt;
 	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
+	if (!privileged)
+		xprt->resvport = 0;
 
 	/* printk("pmap: create clnt\n"); */
 	clnt = rpc_new_client(xprt, hostname,
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ded6c63..4f188d0 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -76,25 +76,35 @@
 rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
 {
 	struct rpc_inode *rpci = RPC_I(inode);
-	int res = 0;
+	int res = -EPIPE;
 
 	down(&inode->i_sem);
+	if (rpci->ops == NULL)
+		goto out;
 	if (rpci->nreaders) {
 		list_add_tail(&msg->list, &rpci->pipe);
 		rpci->pipelen += msg->len;
+		res = 0;
 	} else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) {
 		if (list_empty(&rpci->pipe))
 			schedule_delayed_work(&rpci->queue_timeout,
 					RPC_UPCALL_TIMEOUT);
 		list_add_tail(&msg->list, &rpci->pipe);
 		rpci->pipelen += msg->len;
-	} else
-		res = -EPIPE;
+		res = 0;
+	}
+out:
 	up(&inode->i_sem);
 	wake_up(&rpci->waitq);
 	return res;
 }
 
+static inline void
+rpc_inode_setowner(struct inode *inode, void *private)
+{
+	RPC_I(inode)->private = private;
+}
+
 static void
 rpc_close_pipes(struct inode *inode)
 {
@@ -111,15 +121,10 @@
 			rpci->ops->release_pipe(inode);
 		rpci->ops = NULL;
 	}
+	rpc_inode_setowner(inode, NULL);
 	up(&inode->i_sem);
 }
 
-static inline void
-rpc_inode_setowner(struct inode *inode, void *private)
-{
-	RPC_I(inode)->private = private;
-}
-
 static struct inode *
 rpc_alloc_inode(struct super_block *sb)
 {
@@ -501,7 +506,6 @@
 			dentry = dvec[--n];
 			if (dentry->d_inode) {
 				rpc_close_pipes(dentry->d_inode);
-				rpc_inode_setowner(dentry->d_inode, NULL);
 				simple_unlink(dir, dentry);
 			}
 			dput(dentry);
@@ -576,10 +580,8 @@
 	int error;
 
 	shrink_dcache_parent(dentry);
-	if (dentry->d_inode) {
+	if (dentry->d_inode)
 		rpc_close_pipes(dentry->d_inode);
-		rpc_inode_setowner(dentry->d_inode, NULL);
-	}
 	if ((error = simple_rmdir(dir, dentry)) != 0)
 		return error;
 	if (!error) {
@@ -732,7 +734,6 @@
 	d_drop(dentry);
 	if (dentry->d_inode) {
 		rpc_close_pipes(dentry->d_inode);
-		rpc_inode_setowner(dentry->d_inode, NULL);
 		error = simple_unlink(dir, dentry);
 	}
 	dput(dentry);
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
new file mode 100644
index 0000000..8f97e90
--- /dev/null
+++ b/net/sunrpc/socklib.c
@@ -0,0 +1,175 @@
+/*
+ * linux/net/sunrpc/socklib.c
+ *
+ * Common socket helper routines for RPC client and server
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/udp.h>
+#include <linux/sunrpc/xdr.h>
+
+
+/**
+ * skb_read_bits - copy some data bits from skb to internal buffer
+ * @desc: sk_buff copy helper
+ * @to: copy destination
+ * @len: number of bytes to copy
+ *
+ * Possibly called several times to iterate over an sk_buff and copy
+ * data out of it.
+ */
+static size_t skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+{
+	if (len > desc->count)
+		len = desc->count;
+	if (skb_copy_bits(desc->skb, desc->offset, to, len))
+		return 0;
+	desc->count -= len;
+	desc->offset += len;
+	return len;
+}
+
+/**
+ * skb_read_and_csum_bits - copy and checksum from skb to buffer
+ * @desc: sk_buff copy helper
+ * @to: copy destination
+ * @len: number of bytes to copy
+ *
+ * Same as skb_read_bits, but calculate a checksum at the same time.
+ */
+static size_t skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
+{
+	unsigned int	csum2, pos;
+
+	if (len > desc->count)
+		len = desc->count;
+	pos = desc->offset;
+	csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
+	desc->csum = csum_block_add(desc->csum, csum2, pos);
+	desc->count -= len;
+	desc->offset += len;
+	return len;
+}
+
+/**
+ * xdr_partial_copy_from_skb - copy data out of an skb
+ * @xdr: target XDR buffer
+ * @base: starting offset
+ * @desc: sk_buff copy helper
+ * @copy_actor: virtual method for copying data
+ *
+ */
+ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, skb_reader_t *desc, skb_read_actor_t copy_actor)
+{
+	struct page	**ppage = xdr->pages;
+	unsigned int	len, pglen = xdr->page_len;
+	ssize_t		copied = 0;
+	int		ret;
+
+	len = xdr->head[0].iov_len;
+	if (base < len) {
+		len -= base;
+		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
+		copied += ret;
+		if (ret != len || !desc->count)
+			goto out;
+		base = 0;
+	} else
+		base -= len;
+
+	if (unlikely(pglen == 0))
+		goto copy_tail;
+	if (unlikely(base >= pglen)) {
+		base -= pglen;
+		goto copy_tail;
+	}
+	if (base || xdr->page_base) {
+		pglen -= base;
+		base += xdr->page_base;
+		ppage += base >> PAGE_CACHE_SHIFT;
+		base &= ~PAGE_CACHE_MASK;
+	}
+	do {
+		char *kaddr;
+
+		/* ACL likes to be lazy in allocating pages - ACLs
+		 * are small by default but can get huge. */
+		if (unlikely(*ppage == NULL)) {
+			*ppage = alloc_page(GFP_ATOMIC);
+			if (unlikely(*ppage == NULL)) {
+				if (copied == 0)
+					copied = -ENOMEM;
+				goto out;
+			}
+		}
+
+		len = PAGE_CACHE_SIZE;
+		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
+		if (base) {
+			len -= base;
+			if (pglen < len)
+				len = pglen;
+			ret = copy_actor(desc, kaddr + base, len);
+			base = 0;
+		} else {
+			if (pglen < len)
+				len = pglen;
+			ret = copy_actor(desc, kaddr, len);
+		}
+		flush_dcache_page(*ppage);
+		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+		copied += ret;
+		if (ret != len || !desc->count)
+			goto out;
+		ppage++;
+	} while ((pglen -= len) != 0);
+copy_tail:
+	len = xdr->tail[0].iov_len;
+	if (base < len)
+		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+out:
+	return copied;
+}
+
+/**
+ * csum_partial_copy_to_xdr - checksum and copy data
+ * @xdr: target XDR buffer
+ * @skb: source skb
+ *
+ * We have set things up such that we perform the checksum of the UDP
+ * packet in parallel with the copies into the RPC client iovec.  -DaveM
+ */
+int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
+{
+	skb_reader_t	desc;
+
+	desc.skb = skb;
+	desc.offset = sizeof(struct udphdr);
+	desc.count = skb->len - desc.offset;
+
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+		goto no_checksum;
+
+	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
+	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+		return -1;
+	if (desc.offset != skb->len) {
+		unsigned int csum2;
+		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
+		desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
+	}
+	if (desc.count)
+		return -1;
+	if ((unsigned short)csum_fold(desc.csum))
+		return -1;
+	return 0;
+no_checksum:
+	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+		return -1;
+	if (desc.count)
+		return -1;
+	return 0;
+}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index ed48ff0..2387e7b 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/sched.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 691dea4..f16e7cd 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -548,9 +548,6 @@
 /*
  * Receive a datagram from a UDP socket.
  */
-extern int
-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb);
-
 static int
 svc_udp_recvfrom(struct svc_rqst *rqstp)
 {
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index 1b9616a..d0c9f46 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -119,8 +119,18 @@
 	return 0;
 }
 
+unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
+EXPORT_SYMBOL(xprt_min_resvport);
+unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
+EXPORT_SYMBOL(xprt_max_resvport);
+
+
 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
+static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
 
 static ctl_table debug_table[] = {
 	{
@@ -177,6 +187,28 @@
 		.extra1		= &min_slot_table_size,
 		.extra2		= &max_slot_table_size
 	},
+	{
+		.ctl_name	= CTL_MIN_RESVPORT,
+		.procname	= "min_resvport",
+		.data		= &xprt_min_resvport,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xprt_min_resvport_limit,
+		.extra2		= &xprt_max_resvport_limit
+	},
+	{
+		.ctl_name	= CTL_MAX_RESVPORT,
+		.procname	= "max_resvport",
+		.data		= &xprt_max_resvport,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &xprt_min_resvport_limit,
+		.extra2		= &xprt_max_resvport_limit
+	},
 	{ .ctl_name = 0 }
 };
 
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index fde16f4..32df433 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -6,15 +6,12 @@
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
+#include <linux/module.h>
 #include <linux/types.h>
-#include <linux/socket.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <net/sock.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
 
@@ -176,178 +173,6 @@
 	xdr->buflen += len;
 }
 
-ssize_t
-xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
-			  skb_reader_t *desc,
-			  skb_read_actor_t copy_actor)
-{
-	struct page	**ppage = xdr->pages;
-	unsigned int	len, pglen = xdr->page_len;
-	ssize_t		copied = 0;
-	int		ret;
-
-	len = xdr->head[0].iov_len;
-	if (base < len) {
-		len -= base;
-		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
-		copied += ret;
-		if (ret != len || !desc->count)
-			goto out;
-		base = 0;
-	} else
-		base -= len;
-
-	if (pglen == 0)
-		goto copy_tail;
-	if (base >= pglen) {
-		base -= pglen;
-		goto copy_tail;
-	}
-	if (base || xdr->page_base) {
-		pglen -= base;
-		base  += xdr->page_base;
-		ppage += base >> PAGE_CACHE_SHIFT;
-		base &= ~PAGE_CACHE_MASK;
-	}
-	do {
-		char *kaddr;
-
-		/* ACL likes to be lazy in allocating pages - ACLs
-		 * are small by default but can get huge. */
-		if (unlikely(*ppage == NULL)) {
-			*ppage = alloc_page(GFP_ATOMIC);
-			if (unlikely(*ppage == NULL)) {
-				if (copied == 0)
-					copied = -ENOMEM;
-				goto out;
-			}
-		}
-
-		len = PAGE_CACHE_SIZE;
-		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
-		if (base) {
-			len -= base;
-			if (pglen < len)
-				len = pglen;
-			ret = copy_actor(desc, kaddr + base, len);
-			base = 0;
-		} else {
-			if (pglen < len)
-				len = pglen;
-			ret = copy_actor(desc, kaddr, len);
-		}
-		flush_dcache_page(*ppage);
-		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
-		copied += ret;
-		if (ret != len || !desc->count)
-			goto out;
-		ppage++;
-	} while ((pglen -= len) != 0);
-copy_tail:
-	len = xdr->tail[0].iov_len;
-	if (base < len)
-		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
-out:
-	return copied;
-}
-
-
-int
-xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
-		struct xdr_buf *xdr, unsigned int base, int msgflags)
-{
-	struct page **ppage = xdr->pages;
-	unsigned int len, pglen = xdr->page_len;
-	int err, ret = 0;
-	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
-
-	len = xdr->head[0].iov_len;
-	if (base < len || (addr != NULL && base == 0)) {
-		struct kvec iov = {
-			.iov_base = xdr->head[0].iov_base + base,
-			.iov_len  = len - base,
-		};
-		struct msghdr msg = {
-			.msg_name    = addr,
-			.msg_namelen = addrlen,
-			.msg_flags   = msgflags,
-		};
-		if (xdr->len > len)
-			msg.msg_flags |= MSG_MORE;
-
-		if (iov.iov_len != 0)
-			err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-		else
-			err = kernel_sendmsg(sock, &msg, NULL, 0, 0);
-		if (ret == 0)
-			ret = err;
-		else if (err > 0)
-			ret += err;
-		if (err != iov.iov_len)
-			goto out;
-		base = 0;
-	} else
-		base -= len;
-
-	if (pglen == 0)
-		goto copy_tail;
-	if (base >= pglen) {
-		base -= pglen;
-		goto copy_tail;
-	}
-	if (base || xdr->page_base) {
-		pglen -= base;
-		base  += xdr->page_base;
-		ppage += base >> PAGE_CACHE_SHIFT;
-		base &= ~PAGE_CACHE_MASK;
-	}
-
-	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
-	do {
-		int flags = msgflags;
-
-		len = PAGE_CACHE_SIZE;
-		if (base)
-			len -= base;
-		if (pglen < len)
-			len = pglen;
-
-		if (pglen != len || xdr->tail[0].iov_len != 0)
-			flags |= MSG_MORE;
-
-		/* Hmm... We might be dealing with highmem pages */
-		if (PageHighMem(*ppage))
-			sendpage = sock_no_sendpage;
-		err = sendpage(sock, *ppage, base, len, flags);
-		if (ret == 0)
-			ret = err;
-		else if (err > 0)
-			ret += err;
-		if (err != len)
-			goto out;
-		base = 0;
-		ppage++;
-	} while ((pglen -= len) != 0);
-copy_tail:
-	len = xdr->tail[0].iov_len;
-	if (base < len) {
-		struct kvec iov = {
-			.iov_base = xdr->tail[0].iov_base + base,
-			.iov_len  = len - base,
-		};
-		struct msghdr msg = {
-			.msg_flags   = msgflags,
-		};
-		err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
-		if (ret == 0)
-			ret = err;
-		else if (err > 0)
-			ret += err;
-	}
-out:
-	return ret;
-}
-
 
 /*
  * Helper routines for doing 'memmove' like operations on a struct xdr_buf
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 3c654e0..6dda386 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -10,12 +10,12 @@
  *	one is available. Otherwise, it sleeps on the backlog queue
  *	(xprt_reserve).
  *  -	Next, the caller puts together the RPC message, stuffs it into
- *	the request struct, and calls xprt_call().
- *  -	xprt_call transmits the message and installs the caller on the
- *	socket's wait list. At the same time, it installs a timer that
+ *	the request struct, and calls xprt_transmit().
+ *  -	xprt_transmit sends the message and installs the caller on the
+ *	transport's wait list. At the same time, it installs a timer that
  *	is run after the packet's timeout has expired.
  *  -	When a packet arrives, the data_ready handler walks the list of
- *	pending requests for that socket. If a matching XID is found, the
+ *	pending requests for that transport. If a matching XID is found, the
  *	caller is woken up, and the timer removed.
  *  -	When no reply arrives within the timeout interval, the timer is
  *	fired by the kernel and runs xprt_timer(). It either adjusts the
@@ -33,36 +33,17 @@
  *
  *  Copyright (C) 1995-1997, Olaf Kirch <okir@monad.swb.de>
  *
- *  TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
- *  TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
- *  TCP NFS related read + write fixes
- *   (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
- *
- *  Rewrite of larges part of the code in order to stabilize TCP stuff.
- *  Fix behaviour when socket buffer is full.
- *   (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no>
+ *  Transport switch API copyright (C) 2005, Chuck Lever <cel@netapp.com>
  */
 
+#include <linux/module.h>
+
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/capability.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <linux/mm.h>
-#include <linux/udp.h>
-#include <linux/tcp.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/file.h>
+#include <linux/interrupt.h>
 #include <linux/workqueue.h>
 #include <linux/random.h>
 
-#include <net/sock.h>
-#include <net/checksum.h>
-#include <net/udp.h>
-#include <net/tcp.h>
+#include <linux/sunrpc/clnt.h>
 
 /*
  * Local variables
@@ -73,93 +54,62 @@
 # define RPCDBG_FACILITY	RPCDBG_XPRT
 #endif
 
-#define XPRT_MAX_BACKOFF	(8)
-#define XPRT_IDLE_TIMEOUT	(5*60*HZ)
-#define XPRT_MAX_RESVPORT	(800)
-
 /*
  * Local functions
  */
 static void	xprt_request_init(struct rpc_task *, struct rpc_xprt *);
 static inline void	do_xprt_reserve(struct rpc_task *);
-static void	xprt_disconnect(struct rpc_xprt *);
 static void	xprt_connect_status(struct rpc_task *task);
-static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
-						struct rpc_timeout *to);
-static struct socket *xprt_create_socket(struct rpc_xprt *, int, int);
-static void	xprt_bind_socket(struct rpc_xprt *, struct socket *);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
 
-static int	xprt_clear_backlog(struct rpc_xprt *xprt);
-
-#ifdef RPC_DEBUG_DATA
 /*
- * Print the buffer contents (first 128 bytes only--just enough for
- * diropres return).
+ * The transport code maintains an estimate on the maximum number of out-
+ * standing RPC requests, using a smoothed version of the congestion
+ * avoidance implemented in 44BSD. This is basically the Van Jacobson
+ * congestion algorithm: If a retransmit occurs, the congestion window is
+ * halved; otherwise, it is incremented by 1/cwnd when
+ *
+ *	-	a reply is received and
+ *	-	a full number of requests are outstanding and
+ *	-	the congestion window hasn't been updated recently.
  */
-static void
-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
-{
-	u8	*buf = (u8 *) packet;
-	int	j;
+#define RPC_CWNDSHIFT		(8U)
+#define RPC_CWNDSCALE		(1U << RPC_CWNDSHIFT)
+#define RPC_INITCWND		RPC_CWNDSCALE
+#define RPC_MAXCWND(xprt)	((xprt)->max_reqs << RPC_CWNDSHIFT)
 
-	dprintk("RPC:      %s\n", msg);
-	for (j = 0; j < count && j < 128; j += 4) {
-		if (!(j & 31)) {
-			if (j)
-				dprintk("\n");
-			dprintk("0x%04x ", j);
-		}
-		dprintk("%02x%02x%02x%02x ",
-			buf[j], buf[j+1], buf[j+2], buf[j+3]);
-	}
-	dprintk("\n");
-}
-#else
-static inline void
-xprt_pktdump(char *msg, u32 *packet, unsigned int count)
-{
-	/* NOP */
-}
-#endif
+#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
 
-/*
- * Look up RPC transport given an INET socket
+/**
+ * xprt_reserve_xprt - serialize write access to transports
+ * @task: task that is requesting access to the transport
+ *
+ * This prevents mixing the payload of separate requests, and prevents
+ * transport connects from colliding with writes.  No congestion control
+ * is provided.
  */
-static inline struct rpc_xprt *
-xprt_from_sock(struct sock *sk)
+int xprt_reserve_xprt(struct rpc_task *task)
 {
-	return (struct rpc_xprt *) sk->sk_user_data;
-}
-
-/*
- * Serialize write access to sockets, in order to prevent different
- * requests from interfering with each other.
- * Also prevents TCP socket connects from colliding with writes.
- */
-static int
-__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
-{
+	struct rpc_xprt	*xprt = task->tk_xprt;
 	struct rpc_rqst *req = task->tk_rqstp;
 
-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) {
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
 		if (task == xprt->snd_task)
 			return 1;
+		if (task == NULL)
+			return 0;
 		goto out_sleep;
 	}
-	if (xprt->nocong || __xprt_get_cong(xprt, task)) {
-		xprt->snd_task = task;
-		if (req) {
-			req->rq_bytes_sent = 0;
-			req->rq_ntrans++;
-		}
-		return 1;
+	xprt->snd_task = task;
+	if (req) {
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
 	}
-	smp_mb__before_clear_bit();
-	clear_bit(XPRT_LOCKED, &xprt->sockstate);
-	smp_mb__after_clear_bit();
+	return 1;
+
 out_sleep:
-	dprintk("RPC: %4d failed to lock socket %p\n", task->tk_pid, xprt);
+	dprintk("RPC: %4d failed to lock transport %p\n",
+			task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
 	if (req && req->rq_ntrans)
@@ -169,26 +119,92 @@
 	return 0;
 }
 
-static inline int
-xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+/*
+ * xprt_reserve_xprt_cong - serialize write access to transports
+ * @task: task that is requesting access to the transport
+ *
+ * Same as xprt_reserve_xprt, but Van Jacobson congestion control is
+ * integrated into the decision of whether a request is allowed to be
+ * woken up and given access to the transport.
+ */
+int xprt_reserve_xprt_cong(struct rpc_task *task)
+{
+	struct rpc_xprt	*xprt = task->tk_xprt;
+	struct rpc_rqst *req = task->tk_rqstp;
+
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
+		if (task == xprt->snd_task)
+			return 1;
+		goto out_sleep;
+	}
+	if (__xprt_get_cong(xprt, task)) {
+		xprt->snd_task = task;
+		if (req) {
+			req->rq_bytes_sent = 0;
+			req->rq_ntrans++;
+		}
+		return 1;
+	}
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_LOCKED, &xprt->state);
+	smp_mb__after_clear_bit();
+out_sleep:
+	dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
+	task->tk_timeout = 0;
+	task->tk_status = -EAGAIN;
+	if (req && req->rq_ntrans)
+		rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+	else
+		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+	return 0;
+}
+
+static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	int retval;
 
-	spin_lock_bh(&xprt->sock_lock);
-	retval = __xprt_lock_write(xprt, task);
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
+	retval = xprt->ops->reserve_xprt(task);
+	spin_unlock_bh(&xprt->transport_lock);
 	return retval;
 }
 
+static void __xprt_lock_write_next(struct rpc_xprt *xprt)
+{
+	struct rpc_task *task;
+	struct rpc_rqst *req;
 
-static void
-__xprt_lock_write_next(struct rpc_xprt *xprt)
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
+		return;
+
+	task = rpc_wake_up_next(&xprt->resend);
+	if (!task) {
+		task = rpc_wake_up_next(&xprt->sending);
+		if (!task)
+			goto out_unlock;
+	}
+
+	req = task->tk_rqstp;
+	xprt->snd_task = task;
+	if (req) {
+		req->rq_bytes_sent = 0;
+		req->rq_ntrans++;
+	}
+	return;
+
+out_unlock:
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_LOCKED, &xprt->state);
+	smp_mb__after_clear_bit();
+}
+
+static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
 {
 	struct rpc_task *task;
 
-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		return;
-	if (!xprt->nocong && RPCXPRT_CONGESTED(xprt))
+	if (RPCXPRT_CONGESTED(xprt))
 		goto out_unlock;
 	task = rpc_wake_up_next(&xprt->resend);
 	if (!task) {
@@ -196,7 +212,7 @@
 		if (!task)
 			goto out_unlock;
 	}
-	if (xprt->nocong || __xprt_get_cong(xprt, task)) {
+	if (__xprt_get_cong(xprt, task)) {
 		struct rpc_rqst *req = task->tk_rqstp;
 		xprt->snd_task = task;
 		if (req) {
@@ -207,87 +223,52 @@
 	}
 out_unlock:
 	smp_mb__before_clear_bit();
-	clear_bit(XPRT_LOCKED, &xprt->sockstate);
+	clear_bit(XPRT_LOCKED, &xprt->state);
 	smp_mb__after_clear_bit();
 }
 
-/*
- * Releases the socket for use by other requests.
+/**
+ * xprt_release_xprt - allow other requests to use a transport
+ * @xprt: transport with other tasks potentially waiting
+ * @task: task that is releasing access to the transport
+ *
+ * Note that "task" can be NULL.  No congestion control is provided.
  */
-static void
-__xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	if (xprt->snd_task == task) {
 		xprt->snd_task = NULL;
 		smp_mb__before_clear_bit();
-		clear_bit(XPRT_LOCKED, &xprt->sockstate);
+		clear_bit(XPRT_LOCKED, &xprt->state);
 		smp_mb__after_clear_bit();
 		__xprt_lock_write_next(xprt);
 	}
 }
 
-static inline void
-xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
+/**
+ * xprt_release_xprt_cong - allow other requests to use a transport
+ * @xprt: transport with other tasks potentially waiting
+ * @task: task that is releasing access to the transport
+ *
+ * Note that "task" can be NULL.  Another task is awoken to use the
+ * transport if the transport's congestion window allows it.
+ */
+void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-	spin_lock_bh(&xprt->sock_lock);
-	__xprt_release_write(xprt, task);
-	spin_unlock_bh(&xprt->sock_lock);
+	if (xprt->snd_task == task) {
+		xprt->snd_task = NULL;
+		smp_mb__before_clear_bit();
+		clear_bit(XPRT_LOCKED, &xprt->state);
+		smp_mb__after_clear_bit();
+		__xprt_lock_write_next_cong(xprt);
+	}
 }
 
-/*
- * Write data to socket.
- */
-static inline int
-xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
+static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-	struct socket	*sock = xprt->sock;
-	struct xdr_buf	*xdr = &req->rq_snd_buf;
-	struct sockaddr *addr = NULL;
-	int addrlen = 0;
-	unsigned int	skip;
-	int		result;
-
-	if (!sock)
-		return -ENOTCONN;
-
-	xprt_pktdump("packet data:",
-				req->rq_svec->iov_base,
-				req->rq_svec->iov_len);
-
-	/* For UDP, we need to provide an address */
-	if (!xprt->stream) {
-		addr = (struct sockaddr *) &xprt->addr;
-		addrlen = sizeof(xprt->addr);
-	}
-	/* Dont repeat bytes */
-	skip = req->rq_bytes_sent;
-
-	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
-	result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
-
-	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
-
-	if (result >= 0)
-		return result;
-
-	switch (result) {
-	case -ECONNREFUSED:
-		/* When the server has died, an ICMP port unreachable message
-		 * prompts ECONNREFUSED.
-		 */
-	case -EAGAIN:
-		break;
-	case -ECONNRESET:
-	case -ENOTCONN:
-	case -EPIPE:
-		/* connection broken */
-		if (xprt->stream)
-			result = -ENOTCONN;
-		break;
-	default:
-		printk(KERN_NOTICE "RPC: sendmsg returned error %d\n", -result);
-	}
-	return result;
+	spin_lock_bh(&xprt->transport_lock);
+	xprt->ops->release_xprt(xprt, task);
+	spin_unlock_bh(&xprt->transport_lock);
 }
 
 /*
@@ -321,26 +302,40 @@
 		return;
 	req->rq_cong = 0;
 	xprt->cong -= RPC_CWNDSCALE;
-	__xprt_lock_write_next(xprt);
+	__xprt_lock_write_next_cong(xprt);
 }
 
-/*
- * Adjust RPC congestion window
+/**
+ * xprt_release_rqst_cong - housekeeping when request is complete
+ * @task: RPC request that recently completed
+ *
+ * Useful for transports that require congestion control.
+ */
+void xprt_release_rqst_cong(struct rpc_task *task)
+{
+	__xprt_put_cong(task->tk_xprt, task->tk_rqstp);
+}
+
+/**
+ * xprt_adjust_cwnd - adjust transport congestion window
+ * @task: recently completed RPC request used to adjust window
+ * @result: result code of completed RPC request
+ *
  * We use a time-smoothed congestion estimator to avoid heavy oscillation.
  */
-static void
-xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
+void xprt_adjust_cwnd(struct rpc_task *task, int result)
 {
-	unsigned long	cwnd;
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = task->tk_xprt;
+	unsigned long cwnd = xprt->cwnd;
 
-	cwnd = xprt->cwnd;
 	if (result >= 0 && cwnd <= xprt->cong) {
 		/* The (cwnd >> 1) term makes sure
 		 * the result gets rounded properly. */
 		cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd;
 		if (cwnd > RPC_MAXCWND(xprt))
 			cwnd = RPC_MAXCWND(xprt);
-		__xprt_lock_write_next(xprt);
+		__xprt_lock_write_next_cong(xprt);
 	} else if (result == -ETIMEDOUT) {
 		cwnd >>= 1;
 		if (cwnd < RPC_CWNDSCALE)
@@ -349,11 +344,89 @@
 	dprintk("RPC:      cong %ld, cwnd was %ld, now %ld\n",
 			xprt->cong, xprt->cwnd, cwnd);
 	xprt->cwnd = cwnd;
+	__xprt_put_cong(xprt, req);
+}
+
+/**
+ * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue
+ * @xprt: transport with waiting tasks
+ * @status: result code to plant in each task before waking it
+ *
+ */
+void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
+{
+	if (status < 0)
+		rpc_wake_up_status(&xprt->pending, status);
+	else
+		rpc_wake_up(&xprt->pending);
+}
+
+/**
+ * xprt_wait_for_buffer_space - wait for transport output buffer to clear
+ * @task: task to be put to sleep
+ *
+ */
+void xprt_wait_for_buffer_space(struct rpc_task *task)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
+
+	task->tk_timeout = req->rq_timeout;
+	rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+}
+
+/**
+ * xprt_write_space - wake the task waiting for transport output buffer space
+ * @xprt: transport with waiting tasks
+ *
+ * Can be called in a soft IRQ context, so xprt_write_space never sleeps.
+ */
+void xprt_write_space(struct rpc_xprt *xprt)
+{
+	if (unlikely(xprt->shutdown))
+		return;
+
+	spin_lock_bh(&xprt->transport_lock);
+	if (xprt->snd_task) {
+		dprintk("RPC:      write space: waking waiting task on xprt %p\n",
+				xprt);
+		rpc_wake_up_task(xprt->snd_task);
+	}
+	spin_unlock_bh(&xprt->transport_lock);
+}
+
+/**
+ * xprt_set_retrans_timeout_def - set a request's retransmit timeout
+ * @task: task whose timeout is to be set
+ *
+ * Set a request's retransmit timeout based on the transport's
+ * default timeout parameters.  Used by transports that don't adjust
+ * the retransmit timeout based on round-trip time estimation.
+ */
+void xprt_set_retrans_timeout_def(struct rpc_task *task)
+{
+	task->tk_timeout = task->tk_rqstp->rq_timeout;
 }
 
 /*
- * Reset the major timeout value
+ * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
+ * @task: task whose timeout is to be set
+ * 
+ * Set a request's retransmit timeout using the RTT estimator.
  */
+void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
+{
+	int timer = task->tk_msg.rpc_proc->p_timer;
+	struct rpc_rtt *rtt = task->tk_client->cl_rtt;
+	struct rpc_rqst *req = task->tk_rqstp;
+	unsigned long max_timeout = req->rq_xprt->timeout.to_maxval;
+
+	task->tk_timeout = rpc_calc_rto(rtt, timer);
+	task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries;
+	if (task->tk_timeout > max_timeout || task->tk_timeout == 0)
+		task->tk_timeout = max_timeout;
+}
+
 static void xprt_reset_majortimeo(struct rpc_rqst *req)
 {
 	struct rpc_timeout *to = &req->rq_xprt->timeout;
@@ -368,8 +441,10 @@
 	req->rq_majortimeo += jiffies;
 }
 
-/*
- * Adjust timeout values etc for next retransmit
+/**
+ * xprt_adjust_timeout - adjust timeout values for next retransmit
+ * @req: RPC request containing parameters to use for the adjustment
+ *
  */
 int xprt_adjust_timeout(struct rpc_rqst *req)
 {
@@ -391,9 +466,9 @@
 		req->rq_retries = 0;
 		xprt_reset_majortimeo(req);
 		/* Reset the RTT counters == "slow start" */
-		spin_lock_bh(&xprt->sock_lock);
+		spin_lock_bh(&xprt->transport_lock);
 		rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
-		spin_unlock_bh(&xprt->sock_lock);
+		spin_unlock_bh(&xprt->transport_lock);
 		pprintk("RPC: %lu timeout\n", jiffies);
 		status = -ETIMEDOUT;
 	}
@@ -405,133 +480,52 @@
 	return status;
 }
 
-/*
- * Close down a transport socket
- */
-static void
-xprt_close(struct rpc_xprt *xprt)
-{
-	struct socket	*sock = xprt->sock;
-	struct sock	*sk = xprt->inet;
-
-	if (!sk)
-		return;
-
-	write_lock_bh(&sk->sk_callback_lock);
-	xprt->inet = NULL;
-	xprt->sock = NULL;
-
-	sk->sk_user_data    = NULL;
-	sk->sk_data_ready   = xprt->old_data_ready;
-	sk->sk_state_change = xprt->old_state_change;
-	sk->sk_write_space  = xprt->old_write_space;
-	write_unlock_bh(&sk->sk_callback_lock);
-
-	sk->sk_no_check	 = 0;
-
-	sock_release(sock);
-}
-
-static void
-xprt_socket_autoclose(void *args)
+static void xprt_autoclose(void *args)
 {
 	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
 
 	xprt_disconnect(xprt);
-	xprt_close(xprt);
+	xprt->ops->close(xprt);
 	xprt_release_write(xprt, NULL);
 }
 
-/*
- * Mark a transport as disconnected
+/**
+ * xprt_disconnect - mark a transport as disconnected
+ * @xprt: transport to flag for disconnect
+ *
  */
-static void
-xprt_disconnect(struct rpc_xprt *xprt)
+void xprt_disconnect(struct rpc_xprt *xprt)
 {
 	dprintk("RPC:      disconnected transport %p\n", xprt);
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	xprt_clear_connected(xprt);
-	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
-	spin_unlock_bh(&xprt->sock_lock);
+	xprt_wake_pending_tasks(xprt, -ENOTCONN);
+	spin_unlock_bh(&xprt->transport_lock);
 }
 
-/*
- * Used to allow disconnection when we've been idle
- */
 static void
 xprt_init_autodisconnect(unsigned long data)
 {
 	struct rpc_xprt *xprt = (struct rpc_xprt *)data;
 
-	spin_lock(&xprt->sock_lock);
+	spin_lock(&xprt->transport_lock);
 	if (!list_empty(&xprt->recv) || xprt->shutdown)
 		goto out_abort;
-	if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate))
+	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
 		goto out_abort;
-	spin_unlock(&xprt->sock_lock);
-	/* Let keventd close the socket */
-	if (test_bit(XPRT_CONNECTING, &xprt->sockstate) != 0)
+	spin_unlock(&xprt->transport_lock);
+	if (xprt_connecting(xprt))
 		xprt_release_write(xprt, NULL);
 	else
 		schedule_work(&xprt->task_cleanup);
 	return;
 out_abort:
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
 }
 
-static void xprt_socket_connect(void *args)
-{
-	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
-	struct socket *sock = xprt->sock;
-	int status = -EIO;
-
-	if (xprt->shutdown || xprt->addr.sin_port == 0)
-		goto out;
-
-	/*
-	 * Start by resetting any existing state
-	 */
-	xprt_close(xprt);
-	sock = xprt_create_socket(xprt, xprt->prot, xprt->resvport);
-	if (sock == NULL) {
-		/* couldn't create socket or bind to reserved port;
-		 * this is likely a permanent error, so cause an abort */
-		goto out;
-	}
-	xprt_bind_socket(xprt, sock);
-	xprt_sock_setbufsize(xprt);
-
-	status = 0;
-	if (!xprt->stream)
-		goto out;
-
-	/*
-	 * Tell the socket layer to start connecting...
-	 */
-	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
-			sizeof(xprt->addr), O_NONBLOCK);
-	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
-			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
-	if (status < 0) {
-		switch (status) {
-			case -EINPROGRESS:
-			case -EALREADY:
-				goto out_clear;
-		}
-	}
-out:
-	if (status < 0)
-		rpc_wake_up_status(&xprt->pending, status);
-	else
-		rpc_wake_up(&xprt->pending);
-out_clear:
-	smp_mb__before_clear_bit();
-	clear_bit(XPRT_CONNECTING, &xprt->sockstate);
-	smp_mb__after_clear_bit();
-}
-
-/*
- * Attempt to connect a TCP socket.
+/**
+ * xprt_connect - schedule a transport connect operation
+ * @task: RPC task that is requesting the connect
  *
  */
 void xprt_connect(struct rpc_task *task)
@@ -552,37 +546,19 @@
 	if (!xprt_lock_write(xprt, task))
 		return;
 	if (xprt_connected(xprt))
-		goto out_write;
+		xprt_release_write(xprt, task);
+	else {
+		if (task->tk_rqstp)
+			task->tk_rqstp->rq_bytes_sent = 0;
 
-	if (task->tk_rqstp)
-		task->tk_rqstp->rq_bytes_sent = 0;
-
-	task->tk_timeout = RPC_CONNECT_TIMEOUT;
-	rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
-	if (!test_and_set_bit(XPRT_CONNECTING, &xprt->sockstate)) {
-		/* Note: if we are here due to a dropped connection
-		 * 	 we delay reconnecting by RPC_REESTABLISH_TIMEOUT/HZ
-		 * 	 seconds
-		 */
-		if (xprt->sock != NULL)
-			schedule_delayed_work(&xprt->sock_connect,
-					RPC_REESTABLISH_TIMEOUT);
-		else {
-			schedule_work(&xprt->sock_connect);
-			if (!RPC_IS_ASYNC(task))
-				flush_scheduled_work();
-		}
+		task->tk_timeout = xprt->connect_timeout;
+		rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+		xprt->ops->connect(task);
 	}
 	return;
- out_write:
-	xprt_release_write(xprt, task);
 }
 
-/*
- * We arrive here when awoken from waiting on connection establishment.
- */
-static void
-xprt_connect_status(struct rpc_task *task)
+static void xprt_connect_status(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
@@ -592,31 +568,42 @@
 		return;
 	}
 
-	/* if soft mounted, just cause this RPC to fail */
-	if (RPC_IS_SOFT(task))
-		task->tk_status = -EIO;
-
 	switch (task->tk_status) {
 	case -ECONNREFUSED:
 	case -ECONNRESET:
+		dprintk("RPC: %4d xprt_connect_status: server %s refused connection\n",
+				task->tk_pid, task->tk_client->cl_server);
+		break;
 	case -ENOTCONN:
-		return;
+		dprintk("RPC: %4d xprt_connect_status: connection broken\n",
+				task->tk_pid);
+		break;
 	case -ETIMEDOUT:
-		dprintk("RPC: %4d xprt_connect_status: timed out\n",
+		dprintk("RPC: %4d xprt_connect_status: connect attempt timed out\n",
 				task->tk_pid);
 		break;
 	default:
-		printk(KERN_ERR "RPC: error %d connecting to server %s\n",
-				-task->tk_status, task->tk_client->cl_server);
+		dprintk("RPC: %4d xprt_connect_status: error %d connecting to server %s\n",
+				task->tk_pid, -task->tk_status, task->tk_client->cl_server);
+		xprt_release_write(xprt, task);
+		task->tk_status = -EIO;
+		return;
 	}
-	xprt_release_write(xprt, task);
+
+	/* if soft mounted, just cause this RPC to fail */
+	if (RPC_IS_SOFT(task)) {
+		xprt_release_write(xprt, task);
+		task->tk_status = -EIO;
+	}
 }
 
-/*
- * Look up the RPC request corresponding to a reply, and then lock it.
+/**
+ * xprt_lookup_rqst - find an RPC request corresponding to an XID
+ * @xprt: transport on which the original request was transmitted
+ * @xid: RPC XID of incoming reply
+ *
  */
-static inline struct rpc_rqst *
-xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
+struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
 {
 	struct list_head *pos;
 	struct rpc_rqst	*req = NULL;
@@ -631,556 +618,68 @@
 	return req;
 }
 
-/*
- * Complete reply received.
- * The TCP code relies on us to remove the request from xprt->pending.
+/**
+ * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
+ * @task: RPC request that recently completed
+ *
  */
-static void
-xprt_complete_rqst(struct rpc_xprt *xprt, struct rpc_rqst *req, int copied)
+void xprt_update_rtt(struct rpc_task *task)
 {
-	struct rpc_task	*task = req->rq_task;
-	struct rpc_clnt *clnt = task->tk_client;
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_rtt *rtt = task->tk_client->cl_rtt;
+	unsigned timer = task->tk_msg.rpc_proc->p_timer;
 
-	/* Adjust congestion window */
-	if (!xprt->nocong) {
-		unsigned timer = task->tk_msg.rpc_proc->p_timer;
-		xprt_adjust_cwnd(xprt, copied);
-		__xprt_put_cong(xprt, req);
-		if (timer) {
-			if (req->rq_ntrans == 1)
-				rpc_update_rtt(clnt->cl_rtt, timer,
-						(long)jiffies - req->rq_xtime);
-			rpc_set_timeo(clnt->cl_rtt, timer, req->rq_ntrans - 1);
-		}
+	if (timer) {
+		if (req->rq_ntrans == 1)
+			rpc_update_rtt(rtt, timer,
+					(long)jiffies - req->rq_xtime);
+		rpc_set_timeo(rtt, timer, req->rq_ntrans - 1);
 	}
+}
 
-#ifdef RPC_PROFILE
-	/* Profile only reads for now */
-	if (copied > 1024) {
-		static unsigned long	nextstat;
-		static unsigned long	pkt_rtt, pkt_len, pkt_cnt;
+/**
+ * xprt_complete_rqst - called when reply processing is complete
+ * @task: RPC request that recently completed
+ * @copied: actual number of bytes received from the transport
+ *
+ * Caller holds transport lock.
+ */
+void xprt_complete_rqst(struct rpc_task *task, int copied)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
 
-		pkt_cnt++;
-		pkt_len += req->rq_slen + copied;
-		pkt_rtt += jiffies - req->rq_xtime;
-		if (time_before(nextstat, jiffies)) {
-			printk("RPC: %lu %ld cwnd\n", jiffies, xprt->cwnd);
-			printk("RPC: %ld %ld %ld %ld stat\n",
-					jiffies, pkt_cnt, pkt_len, pkt_rtt);
-			pkt_rtt = pkt_len = pkt_cnt = 0;
-			nextstat = jiffies + 5 * HZ;
-		}
-	}
-#endif
+	dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
+			task->tk_pid, ntohl(req->rq_xid), copied);
 
-	dprintk("RPC: %4d has input (%d bytes)\n", task->tk_pid, copied);
 	list_del_init(&req->rq_list);
 	req->rq_received = req->rq_private_buf.len = copied;
-
-	/* ... and wake up the process. */
 	rpc_wake_up_task(task);
-	return;
 }
 
-static size_t
-skb_read_bits(skb_reader_t *desc, void *to, size_t len)
+static void xprt_timer(struct rpc_task *task)
 {
-	if (len > desc->count)
-		len = desc->count;
-	if (skb_copy_bits(desc->skb, desc->offset, to, len))
-		return 0;
-	desc->count -= len;
-	desc->offset += len;
-	return len;
-}
-
-static size_t
-skb_read_and_csum_bits(skb_reader_t *desc, void *to, size_t len)
-{
-	unsigned int csum2, pos;
-
-	if (len > desc->count)
-		len = desc->count;
-	pos = desc->offset;
-	csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
-	desc->csum = csum_block_add(desc->csum, csum2, pos);
-	desc->count -= len;
-	desc->offset += len;
-	return len;
-}
-
-/*
- * We have set things up such that we perform the checksum of the UDP
- * packet in parallel with the copies into the RPC client iovec.  -DaveM
- */
-int
-csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
-{
-	skb_reader_t desc;
-
-	desc.skb = skb;
-	desc.offset = sizeof(struct udphdr);
-	desc.count = skb->len - desc.offset;
-
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY)
-		goto no_checksum;
-
-	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
-	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
-		return -1;
-	if (desc.offset != skb->len) {
-		unsigned int csum2;
-		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
-		desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
-	}
-	if (desc.count)
-		return -1;
-	if ((unsigned short)csum_fold(desc.csum))
-		return -1;
-	return 0;
-no_checksum:
-	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
-		return -1;
-	if (desc.count)
-		return -1;
-	return 0;
-}
-
-/*
- * Input handler for RPC replies. Called from a bottom half and hence
- * atomic.
- */
-static void
-udp_data_ready(struct sock *sk, int len)
-{
-	struct rpc_task	*task;
-	struct rpc_xprt	*xprt;
-	struct rpc_rqst *rovr;
-	struct sk_buff	*skb;
-	int err, repsize, copied;
-	u32 _xid, *xp;
-
-	read_lock(&sk->sk_callback_lock);
-	dprintk("RPC:      udp_data_ready...\n");
-	if (!(xprt = xprt_from_sock(sk))) {
-		printk("RPC:      udp_data_ready request not found!\n");
-		goto out;
-	}
-
-	dprintk("RPC:      udp_data_ready client %p\n", xprt);
-
-	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
-		goto out;
-
-	if (xprt->shutdown)
-		goto dropit;
-
-	repsize = skb->len - sizeof(struct udphdr);
-	if (repsize < 4) {
-		printk("RPC: impossible RPC reply size %d!\n", repsize);
-		goto dropit;
-	}
-
-	/* Copy the XID from the skb... */
-	xp = skb_header_pointer(skb, sizeof(struct udphdr),
-				sizeof(_xid), &_xid);
-	if (xp == NULL)
-		goto dropit;
-
-	/* Look up and lock the request corresponding to the given XID */
-	spin_lock(&xprt->sock_lock);
-	rovr = xprt_lookup_rqst(xprt, *xp);
-	if (!rovr)
-		goto out_unlock;
-	task = rovr->rq_task;
-
-	dprintk("RPC: %4d received reply\n", task->tk_pid);
-
-	if ((copied = rovr->rq_private_buf.buflen) > repsize)
-		copied = repsize;
-
-	/* Suck it into the iovec, verify checksum if not done by hw. */
-	if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
-		goto out_unlock;
-
-	/* Something worked... */
-	dst_confirm(skb->dst);
-
-	xprt_complete_rqst(xprt, rovr, copied);
-
- out_unlock:
-	spin_unlock(&xprt->sock_lock);
- dropit:
-	skb_free_datagram(sk, skb);
- out:
-	read_unlock(&sk->sk_callback_lock);
-}
-
-/*
- * Copy from an skb into memory and shrink the skb.
- */
-static inline size_t
-tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
-{
-	if (len > desc->count)
-		len = desc->count;
-	if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
-		dprintk("RPC:      failed to copy %zu bytes from skb. %zu bytes remain\n",
-				len, desc->count);
-		return 0;
-	}
-	desc->offset += len;
-	desc->count -= len;
-	dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
-			len, desc->count);
-	return len;
-}
-
-/*
- * TCP read fragment marker
- */
-static inline void
-tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-	size_t len, used;
-	char *p;
-
-	p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
-	len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
-	used = tcp_copy_data(desc, p, len);
-	xprt->tcp_offset += used;
-	if (used != len)
-		return;
-	xprt->tcp_reclen = ntohl(xprt->tcp_recm);
-	if (xprt->tcp_reclen & 0x80000000)
-		xprt->tcp_flags |= XPRT_LAST_FRAG;
-	else
-		xprt->tcp_flags &= ~XPRT_LAST_FRAG;
-	xprt->tcp_reclen &= 0x7fffffff;
-	xprt->tcp_flags &= ~XPRT_COPY_RECM;
-	xprt->tcp_offset = 0;
-	/* Sanity check of the record length */
-	if (xprt->tcp_reclen < 4) {
-		printk(KERN_ERR "RPC: Invalid TCP record fragment length\n");
-		xprt_disconnect(xprt);
-	}
-	dprintk("RPC:      reading TCP record fragment of length %d\n",
-			xprt->tcp_reclen);
-}
-
-static void
-tcp_check_recm(struct rpc_xprt *xprt)
-{
-	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
-			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
-	if (xprt->tcp_offset == xprt->tcp_reclen) {
-		xprt->tcp_flags |= XPRT_COPY_RECM;
-		xprt->tcp_offset = 0;
-		if (xprt->tcp_flags & XPRT_LAST_FRAG) {
-			xprt->tcp_flags &= ~XPRT_COPY_DATA;
-			xprt->tcp_flags |= XPRT_COPY_XID;
-			xprt->tcp_copied = 0;
-		}
-	}
-}
-
-/*
- * TCP read xid
- */
-static inline void
-tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-	size_t len, used;
-	char *p;
-
-	len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
-	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
-	p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
-	used = tcp_copy_data(desc, p, len);
-	xprt->tcp_offset += used;
-	if (used != len)
-		return;
-	xprt->tcp_flags &= ~XPRT_COPY_XID;
-	xprt->tcp_flags |= XPRT_COPY_DATA;
-	xprt->tcp_copied = 4;
-	dprintk("RPC:      reading reply for XID %08x\n",
-						ntohl(xprt->tcp_xid));
-	tcp_check_recm(xprt);
-}
-
-/*
- * TCP read and complete request
- */
-static inline void
-tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-	struct rpc_rqst *req;
-	struct xdr_buf *rcvbuf;
-	size_t len;
-	ssize_t r;
-
-	/* Find and lock the request corresponding to this xid */
-	spin_lock(&xprt->sock_lock);
-	req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
-	if (!req) {
-		xprt->tcp_flags &= ~XPRT_COPY_DATA;
-		dprintk("RPC:      XID %08x request not found!\n",
-				ntohl(xprt->tcp_xid));
-		spin_unlock(&xprt->sock_lock);
-		return;
-	}
-
-	rcvbuf = &req->rq_private_buf;
-	len = desc->count;
-	if (len > xprt->tcp_reclen - xprt->tcp_offset) {
-		skb_reader_t my_desc;
-
-		len = xprt->tcp_reclen - xprt->tcp_offset;
-		memcpy(&my_desc, desc, sizeof(my_desc));
-		my_desc.count = len;
-		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
-					  &my_desc, tcp_copy_data);
-		desc->count -= r;
-		desc->offset += r;
-	} else
-		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
-					  desc, tcp_copy_data);
-
-	if (r > 0) {
-		xprt->tcp_copied += r;
-		xprt->tcp_offset += r;
-	}
-	if (r != len) {
-		/* Error when copying to the receive buffer,
-		 * usually because we weren't able to allocate
-		 * additional buffer pages. All we can do now
-		 * is turn off XPRT_COPY_DATA, so the request
-		 * will not receive any additional updates,
-		 * and time out.
-		 * Any remaining data from this record will
-		 * be discarded.
-		 */
-		xprt->tcp_flags &= ~XPRT_COPY_DATA;
-		dprintk("RPC:      XID %08x truncated request\n",
-				ntohl(xprt->tcp_xid));
-		dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
-				xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
-		goto out;
-	}
-
-	dprintk("RPC:      XID %08x read %Zd bytes\n",
-			ntohl(xprt->tcp_xid), r);
-	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
-			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
-
-	if (xprt->tcp_copied == req->rq_private_buf.buflen)
-		xprt->tcp_flags &= ~XPRT_COPY_DATA;
-	else if (xprt->tcp_offset == xprt->tcp_reclen) {
-		if (xprt->tcp_flags & XPRT_LAST_FRAG)
-			xprt->tcp_flags &= ~XPRT_COPY_DATA;
-	}
-
-out:
-	if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
-		dprintk("RPC: %4d received reply complete\n",
-				req->rq_task->tk_pid);
-		xprt_complete_rqst(xprt, req, xprt->tcp_copied);
-	}
-	spin_unlock(&xprt->sock_lock);
-	tcp_check_recm(xprt);
-}
-
-/*
- * TCP discard extra bytes from a short read
- */
-static inline void
-tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
-{
-	size_t len;
-
-	len = xprt->tcp_reclen - xprt->tcp_offset;
-	if (len > desc->count)
-		len = desc->count;
-	desc->count -= len;
-	desc->offset += len;
-	xprt->tcp_offset += len;
-	dprintk("RPC:      discarded %Zu bytes\n", len);
-	tcp_check_recm(xprt);
-}
-
-/*
- * TCP record receive routine
- * We first have to grab the record marker, then the XID, then the data.
- */
-static int
-tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
-		unsigned int offset, size_t len)
-{
-	struct rpc_xprt *xprt = rd_desc->arg.data;
-	skb_reader_t desc = {
-		.skb	= skb,
-		.offset	= offset,
-		.count	= len,
-		.csum	= 0
-       	};
-
-	dprintk("RPC:      tcp_data_recv\n");
-	do {
-		/* Read in a new fragment marker if necessary */
-		/* Can we ever really expect to get completely empty fragments? */
-		if (xprt->tcp_flags & XPRT_COPY_RECM) {
-			tcp_read_fraghdr(xprt, &desc);
-			continue;
-		}
-		/* Read in the xid if necessary */
-		if (xprt->tcp_flags & XPRT_COPY_XID) {
-			tcp_read_xid(xprt, &desc);
-			continue;
-		}
-		/* Read in the request data */
-		if (xprt->tcp_flags & XPRT_COPY_DATA) {
-			tcp_read_request(xprt, &desc);
-			continue;
-		}
-		/* Skip over any trailing bytes on short reads */
-		tcp_read_discard(xprt, &desc);
-	} while (desc.count);
-	dprintk("RPC:      tcp_data_recv done\n");
-	return len - desc.count;
-}
-
-static void tcp_data_ready(struct sock *sk, int bytes)
-{
-	struct rpc_xprt *xprt;
-	read_descriptor_t rd_desc;
-
-	read_lock(&sk->sk_callback_lock);
-	dprintk("RPC:      tcp_data_ready...\n");
-	if (!(xprt = xprt_from_sock(sk))) {
-		printk("RPC:      tcp_data_ready socket info not found!\n");
-		goto out;
-	}
-	if (xprt->shutdown)
-		goto out;
-
-	/* We use rd_desc to pass struct xprt to tcp_data_recv */
-	rd_desc.arg.data = xprt;
-	rd_desc.count = 65536;
-	tcp_read_sock(sk, &rd_desc, tcp_data_recv);
-out:
-	read_unlock(&sk->sk_callback_lock);
-}
-
-static void
-tcp_state_change(struct sock *sk)
-{
-	struct rpc_xprt	*xprt;
-
-	read_lock(&sk->sk_callback_lock);
-	if (!(xprt = xprt_from_sock(sk)))
-		goto out;
-	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
-	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
-				sk->sk_state, xprt_connected(xprt),
-				sock_flag(sk, SOCK_DEAD),
-				sock_flag(sk, SOCK_ZAPPED));
-
-	switch (sk->sk_state) {
-	case TCP_ESTABLISHED:
-		spin_lock_bh(&xprt->sock_lock);
-		if (!xprt_test_and_set_connected(xprt)) {
-			/* Reset TCP record info */
-			xprt->tcp_offset = 0;
-			xprt->tcp_reclen = 0;
-			xprt->tcp_copied = 0;
-			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
-			rpc_wake_up(&xprt->pending);
-		}
-		spin_unlock_bh(&xprt->sock_lock);
-		break;
-	case TCP_SYN_SENT:
-	case TCP_SYN_RECV:
-		break;
-	default:
-		xprt_disconnect(xprt);
-		break;
-	}
- out:
-	read_unlock(&sk->sk_callback_lock);
-}
-
-/*
- * Called when more output buffer space is available for this socket.
- * We try not to wake our writers until they can make "significant"
- * progress, otherwise we'll waste resources thrashing sock_sendmsg
- * with a bunch of small requests.
- */
-static void
-xprt_write_space(struct sock *sk)
-{
-	struct rpc_xprt	*xprt;
-	struct socket	*sock;
-
-	read_lock(&sk->sk_callback_lock);
-	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->sk_socket))
-		goto out;
-	if (xprt->shutdown)
-		goto out;
-
-	/* Wait until we have enough socket memory */
-	if (xprt->stream) {
-		/* from net/core/stream.c:sk_stream_write_space */
-		if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
-			goto out;
-	} else {
-		/* from net/core/sock.c:sock_def_write_space */
-		if (!sock_writeable(sk))
-			goto out;
-	}
-
-	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
-		goto out;
-
-	spin_lock_bh(&xprt->sock_lock);
-	if (xprt->snd_task)
-		rpc_wake_up_task(xprt->snd_task);
-	spin_unlock_bh(&xprt->sock_lock);
-out:
-	read_unlock(&sk->sk_callback_lock);
-}
-
-/*
- * RPC receive timeout handler.
- */
-static void
-xprt_timer(struct rpc_task *task)
-{
-	struct rpc_rqst	*req = task->tk_rqstp;
+	struct rpc_rqst *req = task->tk_rqstp;
 	struct rpc_xprt *xprt = req->rq_xprt;
 
-	spin_lock(&xprt->sock_lock);
-	if (req->rq_received)
-		goto out;
+	dprintk("RPC: %4d xprt_timer\n", task->tk_pid);
 
-	xprt_adjust_cwnd(req->rq_xprt, -ETIMEDOUT);
-	__xprt_put_cong(xprt, req);
-
-	dprintk("RPC: %4d xprt_timer (%s request)\n",
-		task->tk_pid, req ? "pending" : "backlogged");
-
-	task->tk_status  = -ETIMEDOUT;
-out:
+	spin_lock(&xprt->transport_lock);
+	if (!req->rq_received) {
+		if (xprt->ops->timer)
+			xprt->ops->timer(task);
+		task->tk_status = -ETIMEDOUT;
+	}
 	task->tk_timeout = 0;
 	rpc_wake_up_task(task);
-	spin_unlock(&xprt->sock_lock);
+	spin_unlock(&xprt->transport_lock);
 }
 
-/*
- * Place the actual RPC call.
- * We have to copy the iovec because sendmsg fiddles with its contents.
+/**
+ * xprt_prepare_transmit - reserve the transport before sending a request
+ * @task: RPC task about to send a request
+ *
  */
-int
-xprt_prepare_transmit(struct rpc_task *task)
+int xprt_prepare_transmit(struct rpc_task *task)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct rpc_xprt	*xprt = req->rq_xprt;
@@ -1191,12 +690,12 @@
 	if (xprt->shutdown)
 		return -EIO;
 
-	spin_lock_bh(&xprt->sock_lock);
+	spin_lock_bh(&xprt->transport_lock);
 	if (req->rq_received && !req->rq_bytes_sent) {
 		err = req->rq_received;
 		goto out_unlock;
 	}
-	if (!__xprt_lock_write(xprt, task)) {
+	if (!xprt->ops->reserve_xprt(task)) {
 		err = -EAGAIN;
 		goto out_unlock;
 	}
@@ -1206,39 +705,42 @@
 		goto out_unlock;
 	}
 out_unlock:
-	spin_unlock_bh(&xprt->sock_lock);
+	spin_unlock_bh(&xprt->transport_lock);
 	return err;
 }
 
 void
-xprt_transmit(struct rpc_task *task)
+xprt_abort_transmit(struct rpc_task *task)
 {
-	struct rpc_clnt *clnt = task->tk_client;
+	struct rpc_xprt	*xprt = task->tk_xprt;
+
+	xprt_release_write(xprt, task);
+}
+
+/**
+ * xprt_transmit - send an RPC request on a transport
+ * @task: controlling RPC task
+ *
+ * We have to copy the iovec because sendmsg fiddles with its contents.
+ */
+void xprt_transmit(struct rpc_task *task)
+{
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct rpc_xprt	*xprt = req->rq_xprt;
-	int status, retry = 0;
-
+	int status;
 
 	dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
 
-	/* set up everything as needed. */
-	/* Write the record marker */
-	if (xprt->stream) {
-		u32	*marker = req->rq_svec[0].iov_base;
-
-		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
-	}
-
 	smp_rmb();
 	if (!req->rq_received) {
 		if (list_empty(&req->rq_list)) {
-			spin_lock_bh(&xprt->sock_lock);
+			spin_lock_bh(&xprt->transport_lock);
 			/* Update the softirq receive buffer */
 			memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
 					sizeof(req->rq_private_buf));
 			/* Add request to the receive list */
 			list_add_tail(&req->rq_list, &xprt->recv);
-			spin_unlock_bh(&xprt->sock_lock);
+			spin_unlock_bh(&xprt->transport_lock);
 			xprt_reset_majortimeo(req);
 			/* Turn off autodisconnect */
 			del_singleshot_timer_sync(&xprt->timer);
@@ -1246,40 +748,19 @@
 	} else if (!req->rq_bytes_sent)
 		return;
 
-	/* Continue transmitting the packet/record. We must be careful
-	 * to cope with writespace callbacks arriving _after_ we have
-	 * called xprt_sendmsg().
-	 */
-	while (1) {
-		req->rq_xtime = jiffies;
-		status = xprt_sendmsg(xprt, req);
-
-		if (status < 0)
-			break;
-
-		if (xprt->stream) {
-			req->rq_bytes_sent += status;
-
-			/* If we've sent the entire packet, immediately
-			 * reset the count of bytes sent. */
-			if (req->rq_bytes_sent >= req->rq_slen) {
-				req->rq_bytes_sent = 0;
-				goto out_receive;
-			}
-		} else {
-			if (status >= req->rq_slen)
-				goto out_receive;
-			status = -EAGAIN;
-			break;
-		}
-
-		dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
-				task->tk_pid, req->rq_slen - req->rq_bytes_sent,
-				req->rq_slen);
-
-		status = -EAGAIN;
-		if (retry++ > 50)
-			break;
+	status = xprt->ops->send_request(task);
+	if (status == 0) {
+		dprintk("RPC: %4d xmit complete\n", task->tk_pid);
+		spin_lock_bh(&xprt->transport_lock);
+		xprt->ops->set_retrans_timeout(task);
+		/* Don't race with disconnect */
+		if (!xprt_connected(xprt))
+			task->tk_status = -ENOTCONN;
+		else if (!req->rq_received)
+			rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+		xprt->ops->release_xprt(xprt, task);
+		spin_unlock_bh(&xprt->transport_lock);
+		return;
 	}
 
 	/* Note: at this point, task->tk_sleeping has not yet been set,
@@ -1289,60 +770,19 @@
 	task->tk_status = status;
 
 	switch (status) {
-	case -EAGAIN:
-		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
-			/* Protect against races with xprt_write_space */
-			spin_lock_bh(&xprt->sock_lock);
-			/* Don't race with disconnect */
-			if (!xprt_connected(xprt))
-				task->tk_status = -ENOTCONN;
-			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
-				task->tk_timeout = req->rq_timeout;
-				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
-			}
-			spin_unlock_bh(&xprt->sock_lock);
-			return;
-		}
-		/* Keep holding the socket if it is blocked */
-		rpc_delay(task, HZ>>4);
-		return;
 	case -ECONNREFUSED:
-		task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
 		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+	case -EAGAIN:
 	case -ENOTCONN:
 		return;
 	default:
-		if (xprt->stream)
-			xprt_disconnect(xprt);
+		break;
 	}
 	xprt_release_write(xprt, task);
 	return;
- out_receive:
-	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
-	/* Set the task's receive timeout value */
-	spin_lock_bh(&xprt->sock_lock);
-	if (!xprt->nocong) {
-		int timer = task->tk_msg.rpc_proc->p_timer;
-		task->tk_timeout = rpc_calc_rto(clnt->cl_rtt, timer);
-		task->tk_timeout <<= rpc_ntimeo(clnt->cl_rtt, timer) + req->rq_retries;
-		if (task->tk_timeout > xprt->timeout.to_maxval || task->tk_timeout == 0)
-			task->tk_timeout = xprt->timeout.to_maxval;
-	} else
-		task->tk_timeout = req->rq_timeout;
-	/* Don't race with disconnect */
-	if (!xprt_connected(xprt))
-		task->tk_status = -ENOTCONN;
-	else if (!req->rq_received)
-		rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
-	__xprt_release_write(xprt, task);
-	spin_unlock_bh(&xprt->sock_lock);
 }
 
-/*
- * Reserve an RPC call slot.
- */
-static inline void
-do_xprt_reserve(struct rpc_task *task)
+static inline void do_xprt_reserve(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
@@ -1362,22 +802,25 @@
 	rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
 }
 
-void
-xprt_reserve(struct rpc_task *task)
+/**
+ * xprt_reserve - allocate an RPC request slot
+ * @task: RPC task requesting a slot allocation
+ *
+ * If no more slots are available, place the task on the transport's
+ * backlog queue.
+ */
+void xprt_reserve(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
 	task->tk_status = -EIO;
 	if (!xprt->shutdown) {
-		spin_lock(&xprt->xprt_lock);
+		spin_lock(&xprt->reserve_lock);
 		do_xprt_reserve(task);
-		spin_unlock(&xprt->xprt_lock);
+		spin_unlock(&xprt->reserve_lock);
 	}
 }
 
-/*
- * Allocate a 'unique' XID
- */
 static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
 	return xprt->xid++;
@@ -1388,11 +831,7 @@
 	get_random_bytes(&xprt->xid, sizeof(xprt->xid));
 }
 
-/*
- * Initialize RPC request
- */
-static void
-xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
+static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 
@@ -1400,128 +839,104 @@
 	req->rq_task	= task;
 	req->rq_xprt    = xprt;
 	req->rq_xid     = xprt_alloc_xid(xprt);
+	req->rq_release_snd_buf = NULL;
 	dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
 			req, ntohl(req->rq_xid));
 }
 
-/*
- * Release an RPC call slot
+/**
+ * xprt_release - release an RPC request slot
+ * @task: task which is finished with the slot
+ *
  */
-void
-xprt_release(struct rpc_task *task)
+void xprt_release(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 	struct rpc_rqst	*req;
 
 	if (!(req = task->tk_rqstp))
 		return;
-	spin_lock_bh(&xprt->sock_lock);
-	__xprt_release_write(xprt, task);
-	__xprt_put_cong(xprt, req);
+	spin_lock_bh(&xprt->transport_lock);
+	xprt->ops->release_xprt(xprt, task);
+	if (xprt->ops->release_request)
+		xprt->ops->release_request(task);
 	if (!list_empty(&req->rq_list))
 		list_del(&req->rq_list);
 	xprt->last_used = jiffies;
 	if (list_empty(&xprt->recv) && !xprt->shutdown)
-		mod_timer(&xprt->timer, xprt->last_used + XPRT_IDLE_TIMEOUT);
-	spin_unlock_bh(&xprt->sock_lock);
+		mod_timer(&xprt->timer,
+				xprt->last_used + xprt->idle_timeout);
+	spin_unlock_bh(&xprt->transport_lock);
 	task->tk_rqstp = NULL;
+	if (req->rq_release_snd_buf)
+		req->rq_release_snd_buf(req);
 	memset(req, 0, sizeof(*req));	/* mark unused */
 
 	dprintk("RPC: %4d release request %p\n", task->tk_pid, req);
 
-	spin_lock(&xprt->xprt_lock);
+	spin_lock(&xprt->reserve_lock);
 	list_add(&req->rq_list, &xprt->free);
-	xprt_clear_backlog(xprt);
-	spin_unlock(&xprt->xprt_lock);
+	rpc_wake_up_next(&xprt->backlog);
+	spin_unlock(&xprt->reserve_lock);
 }
 
-/*
- * Set default timeout parameters
+/**
+ * xprt_set_timeout - set constant RPC timeout
+ * @to: RPC timeout parameters to set up
+ * @retr: number of retries
+ * @incr: amount of increase after each retry
+ *
  */
-static void
-xprt_default_timeout(struct rpc_timeout *to, int proto)
-{
-	if (proto == IPPROTO_UDP)
-		xprt_set_timeout(to, 5,  5 * HZ);
-	else
-		xprt_set_timeout(to, 5, 60 * HZ);
-}
-
-/*
- * Set constant timeout
- */
-void
-xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
+void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
 {
 	to->to_initval   = 
 	to->to_increment = incr;
-	to->to_maxval    = incr * retr;
+	to->to_maxval    = to->to_initval + (incr * retr);
 	to->to_retries   = retr;
 	to->to_exponential = 0;
 }
 
-unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
-unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
-
-/*
- * Initialize an RPC client
- */
-static struct rpc_xprt *
-xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
 {
+	int result;
 	struct rpc_xprt	*xprt;
-	unsigned int entries;
-	size_t slot_table_size;
 	struct rpc_rqst	*req;
 
-	dprintk("RPC:      setting up %s transport...\n",
-				proto == IPPROTO_UDP? "UDP" : "TCP");
-
-	entries = (proto == IPPROTO_TCP)?
-		xprt_tcp_slot_table_entries : xprt_udp_slot_table_entries;
-
 	if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
 		return ERR_PTR(-ENOMEM);
 	memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
-	xprt->max_reqs = entries;
-	slot_table_size = entries * sizeof(xprt->slot[0]);
-	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
-	if (xprt->slot == NULL) {
-		kfree(xprt);
-		return ERR_PTR(-ENOMEM);
-	}
-	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->addr = *ap;
-	xprt->prot = proto;
-	xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
-	if (xprt->stream) {
-		xprt->cwnd = RPC_MAXCWND(xprt);
-		xprt->nocong = 1;
-		xprt->max_payload = (1U << 31) - 1;
-	} else {
-		xprt->cwnd = RPC_INITCWND;
-		xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+
+	switch (proto) {
+	case IPPROTO_UDP:
+		result = xs_setup_udp(xprt, to);
+		break;
+	case IPPROTO_TCP:
+		result = xs_setup_tcp(xprt, to);
+		break;
+	default:
+		printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
+				proto);
+		result = -EIO;
+		break;
 	}
-	spin_lock_init(&xprt->sock_lock);
-	spin_lock_init(&xprt->xprt_lock);
-	init_waitqueue_head(&xprt->cong_wait);
+	if (result) {
+		kfree(xprt);
+		return ERR_PTR(result);
+	}
+
+	spin_lock_init(&xprt->transport_lock);
+	spin_lock_init(&xprt->reserve_lock);
 
 	INIT_LIST_HEAD(&xprt->free);
 	INIT_LIST_HEAD(&xprt->recv);
-	INIT_WORK(&xprt->sock_connect, xprt_socket_connect, xprt);
-	INIT_WORK(&xprt->task_cleanup, xprt_socket_autoclose, xprt);
+	INIT_WORK(&xprt->task_cleanup, xprt_autoclose, xprt);
 	init_timer(&xprt->timer);
 	xprt->timer.function = xprt_init_autodisconnect;
 	xprt->timer.data = (unsigned long) xprt;
 	xprt->last_used = jiffies;
-	xprt->port = XPRT_MAX_RESVPORT;
-
-	/* Set timeout parameters */
-	if (to) {
-		xprt->timeout = *to;
-	} else
-		xprt_default_timeout(&xprt->timeout, xprt->prot);
+	xprt->cwnd = RPC_INITCWND;
 
 	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
 	rpc_init_wait_queue(&xprt->sending, "xprt_sending");
@@ -1529,139 +944,25 @@
 	rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
 
 	/* initialize free list */
-	for (req = &xprt->slot[entries-1]; req >= &xprt->slot[0]; req--)
+	for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
 		list_add(&req->rq_list, &xprt->free);
 
 	xprt_init_xid(xprt);
 
-	/* Check whether we want to use a reserved port */
-	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
-
 	dprintk("RPC:      created transport %p with %u slots\n", xprt,
 			xprt->max_reqs);
 	
 	return xprt;
 }
 
-/*
- * Bind to a reserved port
+/**
+ * xprt_create_proto - create an RPC client transport
+ * @proto: requested transport protocol
+ * @sap: remote peer's address
+ * @to: timeout parameters for new transport
+ *
  */
-static inline int xprt_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
-{
-	struct sockaddr_in myaddr = {
-		.sin_family = AF_INET,
-	};
-	int		err, port;
-
-	/* Were we already bound to a given port? Try to reuse it */
-	port = xprt->port;
-	do {
-		myaddr.sin_port = htons(port);
-		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
-						sizeof(myaddr));
-		if (err == 0) {
-			xprt->port = port;
-			return 0;
-		}
-		if (--port == 0)
-			port = XPRT_MAX_RESVPORT;
-	} while (err == -EADDRINUSE && port != xprt->port);
-
-	printk("RPC: Can't bind to reserved port (%d).\n", -err);
-	return err;
-}
-
-static void
-xprt_bind_socket(struct rpc_xprt *xprt, struct socket *sock)
-{
-	struct sock	*sk = sock->sk;
-
-	if (xprt->inet)
-		return;
-
-	write_lock_bh(&sk->sk_callback_lock);
-	sk->sk_user_data = xprt;
-	xprt->old_data_ready = sk->sk_data_ready;
-	xprt->old_state_change = sk->sk_state_change;
-	xprt->old_write_space = sk->sk_write_space;
-	if (xprt->prot == IPPROTO_UDP) {
-		sk->sk_data_ready = udp_data_ready;
-		sk->sk_no_check = UDP_CSUM_NORCV;
-		xprt_set_connected(xprt);
-	} else {
-		tcp_sk(sk)->nonagle = 1;	/* disable Nagle's algorithm */
-		sk->sk_data_ready = tcp_data_ready;
-		sk->sk_state_change = tcp_state_change;
-		xprt_clear_connected(xprt);
-	}
-	sk->sk_write_space = xprt_write_space;
-
-	/* Reset to new socket */
-	xprt->sock = sock;
-	xprt->inet = sk;
-	write_unlock_bh(&sk->sk_callback_lock);
-
-	return;
-}
-
-/*
- * Set socket buffer length
- */
-void
-xprt_sock_setbufsize(struct rpc_xprt *xprt)
-{
-	struct sock *sk = xprt->inet;
-
-	if (xprt->stream)
-		return;
-	if (xprt->rcvsize) {
-		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
-		sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
-	}
-	if (xprt->sndsize) {
-		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-		sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
-		sk->sk_write_space(sk);
-	}
-}
-
-/*
- * Datastream sockets are created here, but xprt_connect will create
- * and connect stream sockets.
- */
-static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int resvport)
-{
-	struct socket	*sock;
-	int		type, err;
-
-	dprintk("RPC:      xprt_create_socket(%s %d)\n",
-			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
-
-	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
-
-	if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
-		printk("RPC: can't create socket (%d).\n", -err);
-		return NULL;
-	}
-
-	/* If the caller has the capability, bind to a reserved port */
-	if (resvport && xprt_bindresvport(xprt, sock) < 0) {
-		printk("RPC: can't bind to reserved port.\n");
-		goto failed;
-	}
-
-	return sock;
-
-failed:
-	sock_release(sock);
-	return NULL;
-}
-
-/*
- * Create an RPC client transport given the protocol and peer address.
- */
-struct rpc_xprt *
-xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
 {
 	struct rpc_xprt	*xprt;
 
@@ -1673,46 +974,26 @@
 	return xprt;
 }
 
-/*
- * Prepare for transport shutdown.
- */
-static void
-xprt_shutdown(struct rpc_xprt *xprt)
+static void xprt_shutdown(struct rpc_xprt *xprt)
 {
 	xprt->shutdown = 1;
 	rpc_wake_up(&xprt->sending);
 	rpc_wake_up(&xprt->resend);
-	rpc_wake_up(&xprt->pending);
+	xprt_wake_pending_tasks(xprt, -EIO);
 	rpc_wake_up(&xprt->backlog);
-	wake_up(&xprt->cong_wait);
 	del_timer_sync(&xprt->timer);
-
-	/* synchronously wait for connect worker to finish */
-	cancel_delayed_work(&xprt->sock_connect);
-	flush_scheduled_work();
 }
 
-/*
- * Clear the xprt backlog queue
+/**
+ * xprt_destroy - destroy an RPC transport, killing off all requests.
+ * @xprt: transport to destroy
+ *
  */
-static int
-xprt_clear_backlog(struct rpc_xprt *xprt) {
-	rpc_wake_up_next(&xprt->backlog);
-	wake_up(&xprt->cong_wait);
-	return 1;
-}
-
-/*
- * Destroy an RPC transport, killing off all requests.
- */
-int
-xprt_destroy(struct rpc_xprt *xprt)
+int xprt_destroy(struct rpc_xprt *xprt)
 {
 	dprintk("RPC:      destroying transport %p\n", xprt);
 	xprt_shutdown(xprt);
-	xprt_disconnect(xprt);
-	xprt_close(xprt);
-	kfree(xprt->slot);
+	xprt->ops->destroy(xprt);
 	kfree(xprt);
 
 	return 0;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
new file mode 100644
index 0000000..2e15292
--- /dev/null
+++ b/net/sunrpc/xprtsock.c
@@ -0,0 +1,1252 @@
+/*
+ * linux/net/sunrpc/xprtsock.c
+ *
+ * Client-side transport implementation for sockets.
+ *
+ * TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
+ * TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
+ * TCP NFS related read + write fixes
+ *  (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
+ *
+ * Rewrite of larges part of the code in order to stabilize TCP stuff.
+ * Fix behaviour when socket buffer is full.
+ *  (C) 1999 Trond Myklebust <trond.myklebust@fys.uio.no>
+ *
+ * IP socket transport implementation, (C) 2005 Chuck Lever <cel@netapp.com>
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/pagemap.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/mm.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/file.h>
+
+#include <net/sock.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <net/tcp.h>
+
+/*
+ * How many times to try sending a request on a socket before waiting
+ * for the socket buffer to clear.
+ */
+#define XS_SENDMSG_RETRY	(10U)
+
+/*
+ * Time out for an RPC UDP socket connect.  UDP socket connects are
+ * synchronous, but we set a timeout anyway in case of resource
+ * exhaustion on the local host.
+ */
+#define XS_UDP_CONN_TO		(5U * HZ)
+
+/*
+ * Wait duration for an RPC TCP connection to be established.  Solaris
+ * NFS over TCP uses 60 seconds, for example, which is in line with how
+ * long a server takes to reboot.
+ */
+#define XS_TCP_CONN_TO		(60U * HZ)
+
+/*
+ * Wait duration for a reply from the RPC portmapper.
+ */
+#define XS_BIND_TO		(60U * HZ)
+
+/*
+ * Delay if a UDP socket connect error occurs.  This is most likely some
+ * kind of resource problem on the local host.
+ */
+#define XS_UDP_REEST_TO		(2U * HZ)
+
+/*
+ * The reestablish timeout allows clients to delay for a bit before attempting
+ * to reconnect to a server that just dropped our connection.
+ *
+ * We implement an exponential backoff when trying to reestablish a TCP
+ * transport connection with the server.  Some servers like to drop a TCP
+ * connection when they are overworked, so we start with a short timeout and
+ * increase over time if the server is down or not responding.
+ */
+#define XS_TCP_INIT_REEST_TO	(3U * HZ)
+#define XS_TCP_MAX_REEST_TO	(5U * 60 * HZ)
+
+/*
+ * TCP idle timeout; client drops the transport socket if it is idle
+ * for this long.  Note that we also timeout UDP sockets to prevent
+ * holding port numbers when there is no RPC traffic.
+ */
+#define XS_IDLE_DISC_TO		(5U * 60 * HZ)
+
+#ifdef RPC_DEBUG
+# undef  RPC_DEBUG_DATA
+# define RPCDBG_FACILITY	RPCDBG_TRANS
+#endif
+
+#ifdef RPC_DEBUG_DATA
+static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+{
+	u8 *buf = (u8 *) packet;
+	int j;
+
+	dprintk("RPC:      %s\n", msg);
+	for (j = 0; j < count && j < 128; j += 4) {
+		if (!(j & 31)) {
+			if (j)
+				dprintk("\n");
+			dprintk("0x%04x ", j);
+		}
+		dprintk("%02x%02x%02x%02x ",
+			buf[j], buf[j+1], buf[j+2], buf[j+3]);
+	}
+	dprintk("\n");
+}
+#else
+static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
+{
+	/* NOP */
+}
+#endif
+
+#define XS_SENDMSG_FLAGS	(MSG_DONTWAIT | MSG_NOSIGNAL)
+
+static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+{
+	struct kvec iov = {
+		.iov_base	= xdr->head[0].iov_base + base,
+		.iov_len	= len - base,
+	};
+	struct msghdr msg = {
+		.msg_name	= addr,
+		.msg_namelen	= addrlen,
+		.msg_flags	= XS_SENDMSG_FLAGS,
+	};
+
+	if (xdr->len > len)
+		msg.msg_flags |= MSG_MORE;
+
+	if (likely(iov.iov_len))
+		return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+	return kernel_sendmsg(sock, &msg, NULL, 0, 0);
+}
+
+static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
+{
+	struct kvec iov = {
+		.iov_base	= xdr->tail[0].iov_base + base,
+		.iov_len	= len - base,
+	};
+	struct msghdr msg = {
+		.msg_flags	= XS_SENDMSG_FLAGS,
+	};
+
+	return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
+}
+
+/**
+ * xs_sendpages - write pages directly to a socket
+ * @sock: socket to send on
+ * @addr: UDP only -- address of destination
+ * @addrlen: UDP only -- length of destination address
+ * @xdr: buffer containing this request
+ * @base: starting position in the buffer
+ *
+ */
+static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+{
+	struct page **ppage = xdr->pages;
+	unsigned int len, pglen = xdr->page_len;
+	int err, ret = 0;
+	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+
+	if (unlikely(!sock))
+		return -ENOTCONN;
+
+	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+
+	len = xdr->head[0].iov_len;
+	if (base < len || (addr != NULL && base == 0)) {
+		err = xs_send_head(sock, addr, addrlen, xdr, base, len);
+		if (ret == 0)
+			ret = err;
+		else if (err > 0)
+			ret += err;
+		if (err != (len - base))
+			goto out;
+		base = 0;
+	} else
+		base -= len;
+
+	if (unlikely(pglen == 0))
+		goto copy_tail;
+	if (unlikely(base >= pglen)) {
+		base -= pglen;
+		goto copy_tail;
+	}
+	if (base || xdr->page_base) {
+		pglen -= base;
+		base += xdr->page_base;
+		ppage += base >> PAGE_CACHE_SHIFT;
+		base &= ~PAGE_CACHE_MASK;
+	}
+
+	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+	do {
+		int flags = XS_SENDMSG_FLAGS;
+
+		len = PAGE_CACHE_SIZE;
+		if (base)
+			len -= base;
+		if (pglen < len)
+			len = pglen;
+
+		if (pglen != len || xdr->tail[0].iov_len != 0)
+			flags |= MSG_MORE;
+
+		/* Hmm... We might be dealing with highmem pages */
+		if (PageHighMem(*ppage))
+			sendpage = sock_no_sendpage;
+		err = sendpage(sock, *ppage, base, len, flags);
+		if (ret == 0)
+			ret = err;
+		else if (err > 0)
+			ret += err;
+		if (err != len)
+			goto out;
+		base = 0;
+		ppage++;
+	} while ((pglen -= len) != 0);
+copy_tail:
+	len = xdr->tail[0].iov_len;
+	if (base < len) {
+		err = xs_send_tail(sock, xdr, base, len);
+		if (ret == 0)
+			ret = err;
+		else if (err > 0)
+			ret += err;
+	}
+out:
+	return ret;
+}
+
+/**
+ * xs_nospace - place task on wait queue if transmit was incomplete
+ * @task: task to put to sleep
+ *
+ */
+static void xs_nospace(struct rpc_task *task)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
+
+	dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
+			task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+			req->rq_slen);
+
+	if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
+		/* Protect against races with write_space */
+		spin_lock_bh(&xprt->transport_lock);
+
+		/* Don't race with disconnect */
+		if (!xprt_connected(xprt))
+			task->tk_status = -ENOTCONN;
+		else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
+			xprt_wait_for_buffer_space(task);
+
+		spin_unlock_bh(&xprt->transport_lock);
+	} else
+		/* Keep holding the socket if it is blocked */
+		rpc_delay(task, HZ>>4);
+}
+
+/**
+ * xs_udp_send_request - write an RPC request to a UDP socket
+ * @task: address of RPC task that manages the state of an RPC request
+ *
+ * Return values:
+ *        0:	The request has been sent
+ *   EAGAIN:	The socket was blocked, please call again later to
+ *		complete the request
+ * ENOTCONN:	Caller needs to invoke connect logic then call again
+ *    other:	Some other error occured, the request was not sent
+ */
+static int xs_udp_send_request(struct rpc_task *task)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
+	struct xdr_buf *xdr = &req->rq_snd_buf;
+	int status;
+
+	xs_pktdump("packet data:",
+				req->rq_svec->iov_base,
+				req->rq_svec->iov_len);
+
+	req->rq_xtime = jiffies;
+	status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
+				sizeof(xprt->addr), xdr, req->rq_bytes_sent);
+
+	dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
+			xdr->len - req->rq_bytes_sent, status);
+
+	if (likely(status >= (int) req->rq_slen))
+		return 0;
+
+	/* Still some bytes left; set up for a retry later. */
+	if (status > 0)
+		status = -EAGAIN;
+
+	switch (status) {
+	case -ENETUNREACH:
+	case -EPIPE:
+	case -ECONNREFUSED:
+		/* When the server has died, an ICMP port unreachable message
+		 * prompts ECONNREFUSED. */
+		break;
+	case -EAGAIN:
+		xs_nospace(task);
+		break;
+	default:
+		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+			-status);
+		break;
+	}
+
+	return status;
+}
+
+static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf)
+{
+	u32 reclen = buf->len - sizeof(rpc_fraghdr);
+	rpc_fraghdr *base = buf->head[0].iov_base;
+	*base = htonl(RPC_LAST_STREAM_FRAGMENT | reclen);
+}
+
+/**
+ * xs_tcp_send_request - write an RPC request to a TCP socket
+ * @task: address of RPC task that manages the state of an RPC request
+ *
+ * Return values:
+ *        0:	The request has been sent
+ *   EAGAIN:	The socket was blocked, please call again later to
+ *		complete the request
+ * ENOTCONN:	Caller needs to invoke connect logic then call again
+ *    other:	Some other error occured, the request was not sent
+ *
+ * XXX: In the case of soft timeouts, should we eventually give up
+ *	if sendmsg is not able to make progress?
+ */
+static int xs_tcp_send_request(struct rpc_task *task)
+{
+	struct rpc_rqst *req = task->tk_rqstp;
+	struct rpc_xprt *xprt = req->rq_xprt;
+	struct xdr_buf *xdr = &req->rq_snd_buf;
+	int status, retry = 0;
+
+	xs_encode_tcp_record_marker(&req->rq_snd_buf);
+
+	xs_pktdump("packet data:",
+				req->rq_svec->iov_base,
+				req->rq_svec->iov_len);
+
+	/* Continue transmitting the packet/record. We must be careful
+	 * to cope with writespace callbacks arriving _after_ we have
+	 * called sendmsg(). */
+	while (1) {
+		req->rq_xtime = jiffies;
+		status = xs_sendpages(xprt->sock, NULL, 0, xdr,
+						req->rq_bytes_sent);
+
+		dprintk("RPC:      xs_tcp_send_request(%u) = %d\n",
+				xdr->len - req->rq_bytes_sent, status);
+
+		if (unlikely(status < 0))
+			break;
+
+		/* If we've sent the entire packet, immediately
+		 * reset the count of bytes sent. */
+		req->rq_bytes_sent += status;
+		if (likely(req->rq_bytes_sent >= req->rq_slen)) {
+			req->rq_bytes_sent = 0;
+			return 0;
+		}
+
+		status = -EAGAIN;
+		if (retry++ > XS_SENDMSG_RETRY)
+			break;
+	}
+
+	switch (status) {
+	case -EAGAIN:
+		xs_nospace(task);
+		break;
+	case -ECONNREFUSED:
+	case -ECONNRESET:
+	case -ENOTCONN:
+	case -EPIPE:
+		status = -ENOTCONN;
+		break;
+	default:
+		dprintk("RPC:      sendmsg returned unrecognized error %d\n",
+			-status);
+		xprt_disconnect(xprt);
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * xs_close - close a socket
+ * @xprt: transport
+ *
+ * This is used when all requests are complete; ie, no DRC state remains
+ * on the server we want to save.
+ */
+static void xs_close(struct rpc_xprt *xprt)
+{
+	struct socket *sock = xprt->sock;
+	struct sock *sk = xprt->inet;
+
+	if (!sk)
+		return;
+
+	dprintk("RPC:      xs_close xprt %p\n", xprt);
+
+	write_lock_bh(&sk->sk_callback_lock);
+	xprt->inet = NULL;
+	xprt->sock = NULL;
+
+	sk->sk_user_data = NULL;
+	sk->sk_data_ready = xprt->old_data_ready;
+	sk->sk_state_change = xprt->old_state_change;
+	sk->sk_write_space = xprt->old_write_space;
+	write_unlock_bh(&sk->sk_callback_lock);
+
+	sk->sk_no_check = 0;
+
+	sock_release(sock);
+}
+
+/**
+ * xs_destroy - prepare to shutdown a transport
+ * @xprt: doomed transport
+ *
+ */
+static void xs_destroy(struct rpc_xprt *xprt)
+{
+	dprintk("RPC:      xs_destroy xprt %p\n", xprt);
+
+	cancel_delayed_work(&xprt->connect_worker);
+	flush_scheduled_work();
+
+	xprt_disconnect(xprt);
+	xs_close(xprt);
+	kfree(xprt->slot);
+}
+
+static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
+{
+	return (struct rpc_xprt *) sk->sk_user_data;
+}
+
+/**
+ * xs_udp_data_ready - "data ready" callback for UDP sockets
+ * @sk: socket with data to read
+ * @len: how much data to read
+ *
+ */
+static void xs_udp_data_ready(struct sock *sk, int len)
+{
+	struct rpc_task *task;
+	struct rpc_xprt *xprt;
+	struct rpc_rqst *rovr;
+	struct sk_buff *skb;
+	int err, repsize, copied;
+	u32 _xid, *xp;
+
+	read_lock(&sk->sk_callback_lock);
+	dprintk("RPC:      xs_udp_data_ready...\n");
+	if (!(xprt = xprt_from_sock(sk)))
+		goto out;
+
+	if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL)
+		goto out;
+
+	if (xprt->shutdown)
+		goto dropit;
+
+	repsize = skb->len - sizeof(struct udphdr);
+	if (repsize < 4) {
+		dprintk("RPC:      impossible RPC reply size %d!\n", repsize);
+		goto dropit;
+	}
+
+	/* Copy the XID from the skb... */
+	xp = skb_header_pointer(skb, sizeof(struct udphdr),
+				sizeof(_xid), &_xid);
+	if (xp == NULL)
+		goto dropit;
+
+	/* Look up and lock the request corresponding to the given XID */
+	spin_lock(&xprt->transport_lock);
+	rovr = xprt_lookup_rqst(xprt, *xp);
+	if (!rovr)
+		goto out_unlock;
+	task = rovr->rq_task;
+
+	if ((copied = rovr->rq_private_buf.buflen) > repsize)
+		copied = repsize;
+
+	/* Suck it into the iovec, verify checksum if not done by hw. */
+	if (csum_partial_copy_to_xdr(&rovr->rq_private_buf, skb))
+		goto out_unlock;
+
+	/* Something worked... */
+	dst_confirm(skb->dst);
+
+	xprt_adjust_cwnd(task, copied);
+	xprt_update_rtt(task);
+	xprt_complete_rqst(task, copied);
+
+ out_unlock:
+	spin_unlock(&xprt->transport_lock);
+ dropit:
+	skb_free_datagram(sk, skb);
+ out:
+	read_unlock(&sk->sk_callback_lock);
+}
+
+static inline size_t xs_tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
+{
+	if (len > desc->count)
+		len = desc->count;
+	if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
+		dprintk("RPC:      failed to copy %zu bytes from skb. %zu bytes remain\n",
+				len, desc->count);
+		return 0;
+	}
+	desc->offset += len;
+	desc->count -= len;
+	dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
+			len, desc->count);
+	return len;
+}
+
+static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+	size_t len, used;
+	char *p;
+
+	p = ((char *) &xprt->tcp_recm) + xprt->tcp_offset;
+	len = sizeof(xprt->tcp_recm) - xprt->tcp_offset;
+	used = xs_tcp_copy_data(desc, p, len);
+	xprt->tcp_offset += used;
+	if (used != len)
+		return;
+
+	xprt->tcp_reclen = ntohl(xprt->tcp_recm);
+	if (xprt->tcp_reclen & RPC_LAST_STREAM_FRAGMENT)
+		xprt->tcp_flags |= XPRT_LAST_FRAG;
+	else
+		xprt->tcp_flags &= ~XPRT_LAST_FRAG;
+	xprt->tcp_reclen &= RPC_FRAGMENT_SIZE_MASK;
+
+	xprt->tcp_flags &= ~XPRT_COPY_RECM;
+	xprt->tcp_offset = 0;
+
+	/* Sanity check of the record length */
+	if (unlikely(xprt->tcp_reclen < 4)) {
+		dprintk("RPC:      invalid TCP record fragment length\n");
+		xprt_disconnect(xprt);
+		return;
+	}
+	dprintk("RPC:      reading TCP record fragment of length %d\n",
+			xprt->tcp_reclen);
+}
+
+static void xs_tcp_check_recm(struct rpc_xprt *xprt)
+{
+	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
+			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
+	if (xprt->tcp_offset == xprt->tcp_reclen) {
+		xprt->tcp_flags |= XPRT_COPY_RECM;
+		xprt->tcp_offset = 0;
+		if (xprt->tcp_flags & XPRT_LAST_FRAG) {
+			xprt->tcp_flags &= ~XPRT_COPY_DATA;
+			xprt->tcp_flags |= XPRT_COPY_XID;
+			xprt->tcp_copied = 0;
+		}
+	}
+}
+
+static inline void xs_tcp_read_xid(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+	size_t len, used;
+	char *p;
+
+	len = sizeof(xprt->tcp_xid) - xprt->tcp_offset;
+	dprintk("RPC:      reading XID (%Zu bytes)\n", len);
+	p = ((char *) &xprt->tcp_xid) + xprt->tcp_offset;
+	used = xs_tcp_copy_data(desc, p, len);
+	xprt->tcp_offset += used;
+	if (used != len)
+		return;
+	xprt->tcp_flags &= ~XPRT_COPY_XID;
+	xprt->tcp_flags |= XPRT_COPY_DATA;
+	xprt->tcp_copied = 4;
+	dprintk("RPC:      reading reply for XID %08x\n",
+						ntohl(xprt->tcp_xid));
+	xs_tcp_check_recm(xprt);
+}
+
+static inline void xs_tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+	struct rpc_rqst *req;
+	struct xdr_buf *rcvbuf;
+	size_t len;
+	ssize_t r;
+
+	/* Find and lock the request corresponding to this xid */
+	spin_lock(&xprt->transport_lock);
+	req = xprt_lookup_rqst(xprt, xprt->tcp_xid);
+	if (!req) {
+		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+		dprintk("RPC:      XID %08x request not found!\n",
+				ntohl(xprt->tcp_xid));
+		spin_unlock(&xprt->transport_lock);
+		return;
+	}
+
+	rcvbuf = &req->rq_private_buf;
+	len = desc->count;
+	if (len > xprt->tcp_reclen - xprt->tcp_offset) {
+		skb_reader_t my_desc;
+
+		len = xprt->tcp_reclen - xprt->tcp_offset;
+		memcpy(&my_desc, desc, sizeof(my_desc));
+		my_desc.count = len;
+		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+					  &my_desc, xs_tcp_copy_data);
+		desc->count -= r;
+		desc->offset += r;
+	} else
+		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+					  desc, xs_tcp_copy_data);
+
+	if (r > 0) {
+		xprt->tcp_copied += r;
+		xprt->tcp_offset += r;
+	}
+	if (r != len) {
+		/* Error when copying to the receive buffer,
+		 * usually because we weren't able to allocate
+		 * additional buffer pages. All we can do now
+		 * is turn off XPRT_COPY_DATA, so the request
+		 * will not receive any additional updates,
+		 * and time out.
+		 * Any remaining data from this record will
+		 * be discarded.
+		 */
+		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+		dprintk("RPC:      XID %08x truncated request\n",
+				ntohl(xprt->tcp_xid));
+		dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+				xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+		goto out;
+	}
+
+	dprintk("RPC:      XID %08x read %Zd bytes\n",
+			ntohl(xprt->tcp_xid), r);
+	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+
+	if (xprt->tcp_copied == req->rq_private_buf.buflen)
+		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+	else if (xprt->tcp_offset == xprt->tcp_reclen) {
+		if (xprt->tcp_flags & XPRT_LAST_FRAG)
+			xprt->tcp_flags &= ~XPRT_COPY_DATA;
+	}
+
+out:
+	if (!(xprt->tcp_flags & XPRT_COPY_DATA))
+		xprt_complete_rqst(req->rq_task, xprt->tcp_copied);
+	spin_unlock(&xprt->transport_lock);
+	xs_tcp_check_recm(xprt);
+}
+
+static inline void xs_tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
+{
+	size_t len;
+
+	len = xprt->tcp_reclen - xprt->tcp_offset;
+	if (len > desc->count)
+		len = desc->count;
+	desc->count -= len;
+	desc->offset += len;
+	xprt->tcp_offset += len;
+	dprintk("RPC:      discarded %Zu bytes\n", len);
+	xs_tcp_check_recm(xprt);
+}
+
+static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsigned int offset, size_t len)
+{
+	struct rpc_xprt *xprt = rd_desc->arg.data;
+	skb_reader_t desc = {
+		.skb	= skb,
+		.offset	= offset,
+		.count	= len,
+		.csum	= 0
+	};
+
+	dprintk("RPC:      xs_tcp_data_recv started\n");
+	do {
+		/* Read in a new fragment marker if necessary */
+		/* Can we ever really expect to get completely empty fragments? */
+		if (xprt->tcp_flags & XPRT_COPY_RECM) {
+			xs_tcp_read_fraghdr(xprt, &desc);
+			continue;
+		}
+		/* Read in the xid if necessary */
+		if (xprt->tcp_flags & XPRT_COPY_XID) {
+			xs_tcp_read_xid(xprt, &desc);
+			continue;
+		}
+		/* Read in the request data */
+		if (xprt->tcp_flags & XPRT_COPY_DATA) {
+			xs_tcp_read_request(xprt, &desc);
+			continue;
+		}
+		/* Skip over any trailing bytes on short reads */
+		xs_tcp_read_discard(xprt, &desc);
+	} while (desc.count);
+	dprintk("RPC:      xs_tcp_data_recv done\n");
+	return len - desc.count;
+}
+
+/**
+ * xs_tcp_data_ready - "data ready" callback for TCP sockets
+ * @sk: socket with data to read
+ * @bytes: how much data to read
+ *
+ */
+static void xs_tcp_data_ready(struct sock *sk, int bytes)
+{
+	struct rpc_xprt *xprt;
+	read_descriptor_t rd_desc;
+
+	read_lock(&sk->sk_callback_lock);
+	dprintk("RPC:      xs_tcp_data_ready...\n");
+	if (!(xprt = xprt_from_sock(sk)))
+		goto out;
+	if (xprt->shutdown)
+		goto out;
+
+	/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
+	rd_desc.arg.data = xprt;
+	rd_desc.count = 65536;
+	tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+out:
+	read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * xs_tcp_state_change - callback to handle TCP socket state changes
+ * @sk: socket whose state has changed
+ *
+ */
+static void xs_tcp_state_change(struct sock *sk)
+{
+	struct rpc_xprt *xprt;
+
+	read_lock(&sk->sk_callback_lock);
+	if (!(xprt = xprt_from_sock(sk)))
+		goto out;
+	dprintk("RPC:      xs_tcp_state_change client %p...\n", xprt);
+	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
+				sk->sk_state, xprt_connected(xprt),
+				sock_flag(sk, SOCK_DEAD),
+				sock_flag(sk, SOCK_ZAPPED));
+
+	switch (sk->sk_state) {
+	case TCP_ESTABLISHED:
+		spin_lock_bh(&xprt->transport_lock);
+		if (!xprt_test_and_set_connected(xprt)) {
+			/* Reset TCP record info */
+			xprt->tcp_offset = 0;
+			xprt->tcp_reclen = 0;
+			xprt->tcp_copied = 0;
+			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
+			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+			xprt_wake_pending_tasks(xprt, 0);
+		}
+		spin_unlock_bh(&xprt->transport_lock);
+		break;
+	case TCP_SYN_SENT:
+	case TCP_SYN_RECV:
+		break;
+	default:
+		xprt_disconnect(xprt);
+		break;
+	}
+ out:
+	read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * xs_udp_write_space - callback invoked when socket buffer space
+ *                             becomes available
+ * @sk: socket whose state has changed
+ *
+ * Called when more output buffer space is available for this socket.
+ * We try not to wake our writers until they can make "significant"
+ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
+ * with a bunch of small requests.
+ */
+static void xs_udp_write_space(struct sock *sk)
+{
+	read_lock(&sk->sk_callback_lock);
+
+	/* from net/core/sock.c:sock_def_write_space */
+	if (sock_writeable(sk)) {
+		struct socket *sock;
+		struct rpc_xprt *xprt;
+
+		if (unlikely(!(sock = sk->sk_socket)))
+			goto out;
+		if (unlikely(!(xprt = xprt_from_sock(sk))))
+			goto out;
+		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+			goto out;
+
+		xprt_write_space(xprt);
+	}
+
+ out:
+	read_unlock(&sk->sk_callback_lock);
+}
+
+/**
+ * xs_tcp_write_space - callback invoked when socket buffer space
+ *                             becomes available
+ * @sk: socket whose state has changed
+ *
+ * Called when more output buffer space is available for this socket.
+ * We try not to wake our writers until they can make "significant"
+ * progress, otherwise we'll waste resources thrashing kernel_sendmsg
+ * with a bunch of small requests.
+ */
+static void xs_tcp_write_space(struct sock *sk)
+{
+	read_lock(&sk->sk_callback_lock);
+
+	/* from net/core/stream.c:sk_stream_write_space */
+	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
+		struct socket *sock;
+		struct rpc_xprt *xprt;
+
+		if (unlikely(!(sock = sk->sk_socket)))
+			goto out;
+		if (unlikely(!(xprt = xprt_from_sock(sk))))
+			goto out;
+		if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
+			goto out;
+
+		xprt_write_space(xprt);
+	}
+
+ out:
+	read_unlock(&sk->sk_callback_lock);
+}
+
+static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
+{
+	struct sock *sk = xprt->inet;
+
+	if (xprt->rcvsize) {
+		sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
+		sk->sk_rcvbuf = xprt->rcvsize * xprt->max_reqs *  2;
+	}
+	if (xprt->sndsize) {
+		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
+		sk->sk_sndbuf = xprt->sndsize * xprt->max_reqs * 2;
+		sk->sk_write_space(sk);
+	}
+}
+
+/**
+ * xs_udp_set_buffer_size - set send and receive limits
+ * @xprt: generic transport
+ * @sndsize: requested size of send buffer, in bytes
+ * @rcvsize: requested size of receive buffer, in bytes
+ *
+ * Set socket send and receive buffer size limits.
+ */
+static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
+{
+	xprt->sndsize = 0;
+	if (sndsize)
+		xprt->sndsize = sndsize + 1024;
+	xprt->rcvsize = 0;
+	if (rcvsize)
+		xprt->rcvsize = rcvsize + 1024;
+
+	xs_udp_do_set_buffer_size(xprt);
+}
+
+/**
+ * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
+ * @task: task that timed out
+ *
+ * Adjust the congestion window after a retransmit timeout has occurred.
+ */
+static void xs_udp_timer(struct rpc_task *task)
+{
+	xprt_adjust_cwnd(task, -ETIMEDOUT);
+}
+
+static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
+{
+	struct sockaddr_in myaddr = {
+		.sin_family = AF_INET,
+	};
+	int err;
+	unsigned short port = xprt->port;
+
+	do {
+		myaddr.sin_port = htons(port);
+		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
+						sizeof(myaddr));
+		if (err == 0) {
+			xprt->port = port;
+			dprintk("RPC:      xs_bindresvport bound to port %u\n",
+					port);
+			return 0;
+		}
+		if (port <= xprt_min_resvport)
+			port = xprt_max_resvport;
+		else
+			port--;
+	} while (err == -EADDRINUSE && port != xprt->port);
+
+	dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
+	return err;
+}
+
+/**
+ * xs_udp_connect_worker - set up a UDP socket
+ * @args: RPC transport to connect
+ *
+ * Invoked by a work queue tasklet.
+ */
+static void xs_udp_connect_worker(void *args)
+{
+	struct rpc_xprt *xprt = (struct rpc_xprt *) args;
+	struct socket *sock = xprt->sock;
+	int err, status = -EIO;
+
+	if (xprt->shutdown || xprt->addr.sin_port == 0)
+		goto out;
+
+	dprintk("RPC:      xs_udp_connect_worker for xprt %p\n", xprt);
+
+	/* Start by resetting any existing state */
+	xs_close(xprt);
+
+	if ((err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) < 0) {
+		dprintk("RPC:      can't create UDP transport socket (%d).\n", -err);
+		goto out;
+	}
+
+	if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+		sock_release(sock);
+		goto out;
+	}
+
+	if (!xprt->inet) {
+		struct sock *sk = sock->sk;
+
+		write_lock_bh(&sk->sk_callback_lock);
+
+		sk->sk_user_data = xprt;
+		xprt->old_data_ready = sk->sk_data_ready;
+		xprt->old_state_change = sk->sk_state_change;
+		xprt->old_write_space = sk->sk_write_space;
+		sk->sk_data_ready = xs_udp_data_ready;
+		sk->sk_write_space = xs_udp_write_space;
+		sk->sk_no_check = UDP_CSUM_NORCV;
+
+		xprt_set_connected(xprt);
+
+		/* Reset to new socket */
+		xprt->sock = sock;
+		xprt->inet = sk;
+
+		write_unlock_bh(&sk->sk_callback_lock);
+	}
+	xs_udp_do_set_buffer_size(xprt);
+	status = 0;
+out:
+	xprt_wake_pending_tasks(xprt, status);
+	xprt_clear_connecting(xprt);
+}
+
+/*
+ * We need to preserve the port number so the reply cache on the server can
+ * find our cached RPC replies when we get around to reconnecting.
+ */
+static void xs_tcp_reuse_connection(struct rpc_xprt *xprt)
+{
+	int result;
+	struct socket *sock = xprt->sock;
+	struct sockaddr any;
+
+	dprintk("RPC:      disconnecting xprt %p to reuse port\n", xprt);
+
+	/*
+	 * Disconnect the transport socket by doing a connect operation
+	 * with AF_UNSPEC.  This should return immediately...
+	 */
+	memset(&any, 0, sizeof(any));
+	any.sa_family = AF_UNSPEC;
+	result = sock->ops->connect(sock, &any, sizeof(any), 0);
+	if (result)
+		dprintk("RPC:      AF_UNSPEC connect return code %d\n",
+				result);
+}
+
+/**
+ * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint
+ * @args: RPC transport to connect
+ *
+ * Invoked by a work queue tasklet.
+ */
+static void xs_tcp_connect_worker(void *args)
+{
+	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+	struct socket *sock = xprt->sock;
+	int err, status = -EIO;
+
+	if (xprt->shutdown || xprt->addr.sin_port == 0)
+		goto out;
+
+	dprintk("RPC:      xs_tcp_connect_worker for xprt %p\n", xprt);
+
+	if (!xprt->sock) {
+		/* start from scratch */
+		if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) {
+			dprintk("RPC:      can't create TCP transport socket (%d).\n", -err);
+			goto out;
+		}
+
+		if (xprt->resvport && xs_bindresvport(xprt, sock) < 0) {
+			sock_release(sock);
+			goto out;
+		}
+	} else
+		/* "close" the socket, preserving the local port */
+		xs_tcp_reuse_connection(xprt);
+
+	if (!xprt->inet) {
+		struct sock *sk = sock->sk;
+
+		write_lock_bh(&sk->sk_callback_lock);
+
+		sk->sk_user_data = xprt;
+		xprt->old_data_ready = sk->sk_data_ready;
+		xprt->old_state_change = sk->sk_state_change;
+		xprt->old_write_space = sk->sk_write_space;
+		sk->sk_data_ready = xs_tcp_data_ready;
+		sk->sk_state_change = xs_tcp_state_change;
+		sk->sk_write_space = xs_tcp_write_space;
+
+		/* socket options */
+		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
+		sock_reset_flag(sk, SOCK_LINGER);
+		tcp_sk(sk)->linger2 = 0;
+		tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+
+		xprt_clear_connected(xprt);
+
+		/* Reset to new socket */
+		xprt->sock = sock;
+		xprt->inet = sk;
+
+		write_unlock_bh(&sk->sk_callback_lock);
+	}
+
+	/* Tell the socket layer to start connecting... */
+	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+			sizeof(xprt->addr), O_NONBLOCK);
+	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
+			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
+	if (status < 0) {
+		switch (status) {
+			case -EINPROGRESS:
+			case -EALREADY:
+				goto out_clear;
+			case -ECONNREFUSED:
+			case -ECONNRESET:
+				/* retry with existing socket, after a delay */
+				break;
+			default:
+				/* get rid of existing socket, and retry */
+				xs_close(xprt);
+				break;
+		}
+	}
+out:
+	xprt_wake_pending_tasks(xprt, status);
+out_clear:
+	xprt_clear_connecting(xprt);
+}
+
+/**
+ * xs_connect - connect a socket to a remote endpoint
+ * @task: address of RPC task that manages state of connect request
+ *
+ * TCP: If the remote end dropped the connection, delay reconnecting.
+ *
+ * UDP socket connects are synchronous, but we use a work queue anyway
+ * to guarantee that even unprivileged user processes can set up a
+ * socket on a privileged port.
+ *
+ * If a UDP socket connect fails, the delay behavior here prevents
+ * retry floods (hard mounts).
+ */
+static void xs_connect(struct rpc_task *task)
+{
+	struct rpc_xprt *xprt = task->tk_xprt;
+
+	if (xprt_test_and_set_connecting(xprt))
+		return;
+
+	if (xprt->sock != NULL) {
+		dprintk("RPC:      xs_connect delayed xprt %p for %lu seconds\n",
+				xprt, xprt->reestablish_timeout / HZ);
+		schedule_delayed_work(&xprt->connect_worker,
+					xprt->reestablish_timeout);
+		xprt->reestablish_timeout <<= 1;
+		if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
+			xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
+	} else {
+		dprintk("RPC:      xs_connect scheduled xprt %p\n", xprt);
+		schedule_work(&xprt->connect_worker);
+
+		/* flush_scheduled_work can sleep... */
+		if (!RPC_IS_ASYNC(task))
+			flush_scheduled_work();
+	}
+}
+
+static struct rpc_xprt_ops xs_udp_ops = {
+	.set_buffer_size	= xs_udp_set_buffer_size,
+	.reserve_xprt		= xprt_reserve_xprt_cong,
+	.release_xprt		= xprt_release_xprt_cong,
+	.connect		= xs_connect,
+	.send_request		= xs_udp_send_request,
+	.set_retrans_timeout	= xprt_set_retrans_timeout_rtt,
+	.timer			= xs_udp_timer,
+	.release_request	= xprt_release_rqst_cong,
+	.close			= xs_close,
+	.destroy		= xs_destroy,
+};
+
+static struct rpc_xprt_ops xs_tcp_ops = {
+	.reserve_xprt		= xprt_reserve_xprt,
+	.release_xprt		= xprt_release_xprt,
+	.connect		= xs_connect,
+	.send_request		= xs_tcp_send_request,
+	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
+	.close			= xs_close,
+	.destroy		= xs_destroy,
+};
+
+/**
+ * xs_setup_udp - Set up transport to use a UDP socket
+ * @xprt: transport to set up
+ * @to:   timeout parameters
+ *
+ */
+int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+	size_t slot_table_size;
+
+	dprintk("RPC:      setting up udp-ipv4 transport...\n");
+
+	xprt->max_reqs = xprt_udp_slot_table_entries;
+	slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
+	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+	if (xprt->slot == NULL)
+		return -ENOMEM;
+	memset(xprt->slot, 0, slot_table_size);
+
+	xprt->prot = IPPROTO_UDP;
+	xprt->port = xprt_max_resvport;
+	xprt->tsh_size = 0;
+	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+	/* XXX: header size can vary due to auth type, IPv6, etc. */
+	xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+
+	INIT_WORK(&xprt->connect_worker, xs_udp_connect_worker, xprt);
+	xprt->bind_timeout = XS_BIND_TO;
+	xprt->connect_timeout = XS_UDP_CONN_TO;
+	xprt->reestablish_timeout = XS_UDP_REEST_TO;
+	xprt->idle_timeout = XS_IDLE_DISC_TO;
+
+	xprt->ops = &xs_udp_ops;
+
+	if (to)
+		xprt->timeout = *to;
+	else
+		xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
+
+	return 0;
+}
+
+/**
+ * xs_setup_tcp - Set up transport to use a TCP socket
+ * @xprt: transport to set up
+ * @to: timeout parameters
+ *
+ */
+int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+	size_t slot_table_size;
+
+	dprintk("RPC:      setting up tcp-ipv4 transport...\n");
+
+	xprt->max_reqs = xprt_tcp_slot_table_entries;
+	slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
+	xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+	if (xprt->slot == NULL)
+		return -ENOMEM;
+	memset(xprt->slot, 0, slot_table_size);
+
+	xprt->prot = IPPROTO_TCP;
+	xprt->port = xprt_max_resvport;
+	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
+	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
+
+	INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt);
+	xprt->bind_timeout = XS_BIND_TO;
+	xprt->connect_timeout = XS_TCP_CONN_TO;
+	xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+	xprt->idle_timeout = XS_IDLE_DISC_TO;
+
+	xprt->ops = &xs_tcp_ops;
+
+	if (to)
+		xprt->timeout = *to;
+	else
+		xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
+
+	return 0;
+}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index cbb0ba3..0db9e57 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1192,46 +1192,6 @@
 
 EXPORT_SYMBOL(xfrm_bundle_ok);
 
-/* Well... that's _TASK_. We need to scan through transformation
- * list and figure out what mss tcp should generate in order to
- * final datagram fit to mtu. Mama mia... :-)
- *
- * Apparently, some easy way exists, but we used to choose the most
- * bizarre ones. :-) So, raising Kalashnikov... tra-ta-ta.
- *
- * Consider this function as something like dark humour. :-)
- */
-static int xfrm_get_mss(struct dst_entry *dst, u32 mtu)
-{
-	int res = mtu - dst->header_len;
-
-	for (;;) {
-		struct dst_entry *d = dst;
-		int m = res;
-
-		do {
-			struct xfrm_state *x = d->xfrm;
-			if (x) {
-				spin_lock_bh(&x->lock);
-				if (x->km.state == XFRM_STATE_VALID &&
-				    x->type && x->type->get_max_size)
-					m = x->type->get_max_size(d->xfrm, m);
-				else
-					m += x->props.header_len;
-				spin_unlock_bh(&x->lock);
-			}
-		} while ((d = d->child) != NULL);
-
-		if (m <= mtu)
-			break;
-		res -= (m - mtu);
-		if (res < 88)
-			return mtu;
-	}
-
-	return res + dst->header_len;
-}
-
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
 	int err = 0;
@@ -1252,8 +1212,6 @@
 			dst_ops->negative_advice = xfrm_negative_advice;
 		if (likely(dst_ops->link_failure == NULL))
 			dst_ops->link_failure = xfrm_link_failure;
-		if (likely(dst_ops->get_mss == NULL))
-			dst_ops->get_mss = xfrm_get_mss;
 		if (likely(afinfo->garbage_collect == NULL))
 			afinfo->garbage_collect = __xfrm_garbage_collect;
 		xfrm_policy_afinfo[afinfo->family] = afinfo;
@@ -1281,7 +1239,6 @@
 			dst_ops->check = NULL;
 			dst_ops->negative_advice = NULL;
 			dst_ops->link_failure = NULL;
-			dst_ops->get_mss = NULL;
 			afinfo->garbage_collect = NULL;
 		}
 	}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9d206c2..8b9a474 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1026,6 +1026,12 @@
 }
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 
+/*
+ * This function is NOT optimal.  For example, with ESP it will give an
+ * MTU that's usually two bytes short of being optimal.  However, it will
+ * usually give an answer that's a multiple of 4 provided the input is
+ * also a multiple of 4.
+ */
 int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 {
 	int res = mtu;
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 2fcb244..0dd9691 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -116,6 +116,15 @@
 clean-files	:= lkc_defs.h qconf.moc .tmp_qtcheck \
 		   .tmp_gtkcheck zconf.tab.c zconf.tab.h lex.zconf.c
 
+# Needed for systems without gettext
+KBUILD_HAVE_NLS := $(shell \
+     if echo "\#include <libint.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \
+     then echo yes ; \
+     else echo no ; fi)
+ifeq ($(KBUILD_HAVE_NLS),no)
+HOSTCFLAGS	+= -DKBUILD_NO_NLS
+endif
+
 # generated files seem to need this to find local include files
 HOSTCFLAGS_lex.zconf.o	:= -I$(src)
 HOSTCFLAGS_zconf.tab.o	:= -I$(src)
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index c3d2578..5fba1fe 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -8,7 +8,13 @@
 
 #include "expr.h"
 
-#include <libintl.h>
+#ifndef KBUILD_NO_NLS
+# include <libintl.h>
+#else
+# define gettext(Msgid) ((const char *) (Msgid))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+#endif
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 457bec2..d1ad405 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -219,6 +219,7 @@
 search_help[] = N_(
 	"\n"
 	"Search for CONFIG_ symbols and display their relations.\n"
+	"Regular expressions are allowed.\n"
 	"Example: search for \"^FOO\"\n"
 	"Result:\n"
 	"-----------------------------------------------------------------\n"
@@ -531,7 +532,7 @@
 	cprint("--title");
 	cprint(_("Search Configuration Parameter"));
 	cprint("--inputbox");
-	cprint(_("Enter Keyword"));
+	cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"));
 	cprint("10");
 	cprint("75");
 	cprint("");
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index f2ee673..e3d144a 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -359,6 +359,13 @@
 	return 1;
 }
 
+static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *alias)
+{
+	strcpy(alias, "i2c:");
+	ADD(alias, "id", 1, i2c->id);
+	return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -443,6 +450,9 @@
         else if (sym_is(symname, "__mod_vio_device_table"))
 		do_table(symval, sym->st_size, sizeof(struct vio_device_id),
 			 do_vio_entry, mod);
+	else if (sym_is(symname, "__mod_i2c_device_table"))
+		do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
+			 do_i2c_entry, mod);
 
 }
 
diff --git a/security/dummy.c b/security/dummy.c
index 9623a61..3ca5f2b 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -377,7 +377,7 @@
 	return 0;
 }
 
-static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
+static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
 {
 	return -EOPNOTSUPP;
 }
@@ -768,7 +768,7 @@
 	return -ENOPROTOOPT;
 }
 
-static inline int dummy_sk_alloc_security (struct sock *sk, int family, int priority)
+static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t priority)
 {
 	return 0;
 }
@@ -803,6 +803,23 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_KEYS
+static inline int dummy_key_alloc(struct key *key)
+{
+	return 0;
+}
+
+static inline void dummy_key_free(struct key *key)
+{
+}
+
+static inline int dummy_key_permission(key_ref_t key_ref,
+				       struct task_struct *context,
+				       key_perm_t perm)
+{
+	return 0;
+}
+#endif /* CONFIG_KEYS */
 
 struct security_operations dummy_security_ops;
 
@@ -954,5 +971,11 @@
 	set_to_dummy_if_null(ops, sk_alloc_security);
 	set_to_dummy_if_null(ops, sk_free_security);
 #endif	/* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_KEYS
+	set_to_dummy_if_null(ops, key_alloc);
+	set_to_dummy_if_null(ops, key_free);
+	set_to_dummy_if_null(ops, key_permission);
+#endif	/* CONFIG_KEYS */
+
 }
 
diff --git a/security/keys/key.c b/security/keys/key.c
index 2182be9..ccde17a 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
 /* key.c: basic authentication token and access key management
  *
- * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/security.h>
 #include <linux/workqueue.h>
 #include <linux/err.h>
 #include "internal.h"
@@ -253,6 +254,7 @@
 	struct key_user *user = NULL;
 	struct key *key;
 	size_t desclen, quotalen;
+	int ret;
 
 	key = ERR_PTR(-EINVAL);
 	if (!desc || !*desc)
@@ -305,6 +307,7 @@
 	key->flags = 0;
 	key->expiry = 0;
 	key->payload.data = NULL;
+	key->security = NULL;
 
 	if (!not_in_quota)
 		key->flags |= 1 << KEY_FLAG_IN_QUOTA;
@@ -315,16 +318,21 @@
 	key->magic = KEY_DEBUG_MAGIC;
 #endif
 
+	/* let the security module know about the key */
+	ret = security_key_alloc(key);
+	if (ret < 0)
+		goto security_error;
+
 	/* publish the key by giving it a serial number */
 	atomic_inc(&user->nkeys);
 	key_alloc_serial(key);
 
- error:
+error:
 	return key;
 
- no_memory_3:
+security_error:
+	kfree(key->description);
 	kmem_cache_free(key_jar, key);
- no_memory_2:
 	if (!not_in_quota) {
 		spin_lock(&user->lock);
 		user->qnkeys--;
@@ -332,11 +340,24 @@
 		spin_unlock(&user->lock);
 	}
 	key_user_put(user);
- no_memory_1:
+	key = ERR_PTR(ret);
+	goto error;
+
+no_memory_3:
+	kmem_cache_free(key_jar, key);
+no_memory_2:
+	if (!not_in_quota) {
+		spin_lock(&user->lock);
+		user->qnkeys--;
+		user->qnbytes -= quotalen;
+		spin_unlock(&user->lock);
+	}
+	key_user_put(user);
+no_memory_1:
 	key = ERR_PTR(-ENOMEM);
 	goto error;
 
- no_quota:
+no_quota:
 	spin_unlock(&user->lock);
 	key_user_put(user);
 	key = ERR_PTR(-EDQUOT);
@@ -556,6 +577,8 @@
 
 	key_check(key);
 
+	security_key_free(key);
+
 	/* deal with the user's key tracking and quota */
 	if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
 		spin_lock(&key->user->lock);
@@ -700,8 +723,8 @@
 	int ret;
 
 	/* need write permission on the key to update it */
-	ret = -EACCES;
-	if (!key_permission(key_ref, KEY_WRITE))
+	ret = key_permission(key_ref, KEY_WRITE);
+	if (ret < 0)
 		goto error;
 
 	ret = -EEXIST;
@@ -711,7 +734,6 @@
 	down_write(&key->sem);
 
 	ret = key->type->update(key, payload, plen);
-
 	if (ret == 0)
 		/* updating a negative key instantiates it */
 		clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
@@ -768,9 +790,11 @@
 
 	/* if we're going to allocate a new key, we're going to have
 	 * to modify the keyring */
-	key_ref = ERR_PTR(-EACCES);
-	if (!key_permission(keyring_ref, KEY_WRITE))
+	ret = key_permission(keyring_ref, KEY_WRITE);
+	if (ret < 0) {
+		key_ref = ERR_PTR(ret);
 		goto error_3;
+	}
 
 	/* search for an existing key of the same type and description in the
 	 * destination keyring
@@ -780,8 +804,8 @@
 		goto found_matching_key;
 
 	/* decide on the permissions we want */
-	perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK;
-	perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK;
+	perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+	perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
 
 	if (ktype->read)
 		perm |= KEY_POS_READ | KEY_USR_READ;
@@ -840,16 +864,16 @@
 	key_check(key);
 
 	/* the key must be writable */
-	ret = -EACCES;
-	if (!key_permission(key_ref, KEY_WRITE))
+	ret = key_permission(key_ref, KEY_WRITE);
+	if (ret < 0)
 		goto error;
 
 	/* attempt to update it if supported */
 	ret = -EOPNOTSUPP;
 	if (key->type->update) {
 		down_write(&key->sem);
-		ret = key->type->update(key, payload, plen);
 
+		ret = key->type->update(key, payload, plen);
 		if (ret == 0)
 			/* updating a negative key instantiates it */
 			clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4c670ee..b7a468f 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -624,8 +624,8 @@
 
 	/* link the resulting key to the destination keyring if we can */
 	if (dest_ref) {
-		ret = -EACCES;
-		if (!key_permission(key_ref, KEY_LINK))
+		ret = key_permission(key_ref, KEY_LINK);
+		if (ret < 0)
 			goto error6;
 
 		ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
@@ -676,8 +676,11 @@
 	key = key_ref_to_ptr(key_ref);
 
 	/* see if we can read it directly */
-	if (key_permission(key_ref, KEY_READ))
+	ret = key_permission(key_ref, KEY_READ);
+	if (ret == 0)
 		goto can_read_key;
+	if (ret != -EACCES)
+		goto error;
 
 	/* we can't; see if it's searchable from this process's keyrings
 	 * - we automatically take account of the fact that it may be
@@ -726,7 +729,7 @@
 	if (uid == (uid_t) -1 && gid == (gid_t) -1)
 		goto error;
 
-	key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+	key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error;
@@ -786,7 +789,7 @@
 	if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
 		goto error;
 
-	key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+	key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
 	if (IS_ERR(key_ref)) {
 		ret = PTR_ERR(key_ref);
 		goto error;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 0639396..e1cc4dd 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/security.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <asm/uaccess.h>
@@ -309,7 +310,9 @@
 	int ret;
 
 	keyring = key_alloc(&key_type_keyring, description,
-			    uid, gid, KEY_POS_ALL | KEY_USR_ALL, not_in_quota);
+			    uid, gid,
+			    (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
+			    not_in_quota);
 
 	if (!IS_ERR(keyring)) {
 		ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
@@ -359,9 +362,11 @@
 	key_check(keyring);
 
 	/* top keyring must have search permission to begin the search */
-	key_ref = ERR_PTR(-EACCES);
-	if (!key_task_permission(keyring_ref, context, KEY_SEARCH))
+        err = key_task_permission(keyring_ref, context, KEY_SEARCH);
+	if (err < 0) {
+		key_ref = ERR_PTR(err);
 		goto error;
+	}
 
 	key_ref = ERR_PTR(-ENOTDIR);
 	if (keyring->type != &key_type_keyring)
@@ -402,8 +407,8 @@
 			continue;
 
 		/* key must have search permissions */
-		if (!key_task_permission(make_key_ref(key, possessed),
-					 context, KEY_SEARCH))
+		if (key_task_permission(make_key_ref(key, possessed),
+					context, KEY_SEARCH) < 0)
 			continue;
 
 		/* we set a different error code if we find a negative key */
@@ -430,7 +435,7 @@
 			continue;
 
 		if (!key_task_permission(make_key_ref(key, possessed),
-					 context, KEY_SEARCH))
+					 context, KEY_SEARCH) < 0)
 			continue;
 
 		/* stack the current position */
@@ -521,7 +526,7 @@
 			    (!key->type->match ||
 			     key->type->match(key, description)) &&
 			    key_permission(make_key_ref(key, possessed),
-					   perm) &&
+					   perm) < 0 &&
 			    !test_bit(KEY_FLAG_REVOKED, &key->flags)
 			    )
 				goto found;
@@ -617,7 +622,7 @@
 				continue;
 
 			if (!key_permission(make_key_ref(keyring, 0),
-					    KEY_SEARCH))
+					    KEY_SEARCH) < 0)
 				continue;
 
 			/* found a potential candidate, but we still need to
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 03db073..e7f579c 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/security.h>
 #include "internal.h"
 
 /*****************************************************************************/
@@ -63,7 +64,11 @@
 
 	kperm = kperm & perm & KEY_ALL;
 
-	return kperm == perm;
+	if (kperm != perm)
+		return -EACCES;
+
+	/* let LSM be the final arbiter */
+	return security_key_permission(key_ref, context, perm);
 
 } /* end key_task_permission() */
 
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index d42d215..566b1cc 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -39,7 +39,7 @@
 	.type		= &key_type_keyring,
 	.user		= &root_key_user,
 	.sem		= __RWSEM_INITIALIZER(root_user_keyring.sem),
-	.perm		= KEY_POS_ALL | KEY_USR_ALL,
+	.perm		= (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
 	.flags		= 1 << KEY_FLAG_INSTANTIATED,
 	.description	= "_uid.0",
 #ifdef KEY_DEBUGGING
@@ -54,7 +54,7 @@
 	.type		= &key_type_keyring,
 	.user		= &root_key_user,
 	.sem		= __RWSEM_INITIALIZER(root_session_keyring.sem),
-	.perm		= KEY_POS_ALL | KEY_USR_ALL,
+	.perm		= (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
 	.flags		= 1 << KEY_FLAG_INSTANTIATED,
 	.description	= "_uid_ses.0",
 #ifdef KEY_DEBUGGING
@@ -666,9 +666,8 @@
 		goto invalid_key;
 
 	/* check the permissions */
-	ret = -EACCES;
-
-	if (!key_task_permission(key_ref, context, perm))
+	ret = key_task_permission(key_ref, context, perm);
+	if (ret < 0)
 		goto invalid_key;
 
 error:
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index e446acb..cbda3b2 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -15,18 +15,10 @@
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
+#include <keys/user-type.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
-static int user_instantiate(struct key *key, const void *data, size_t datalen);
-static int user_duplicate(struct key *key, const struct key *source);
-static int user_update(struct key *key, const void *data, size_t datalen);
-static int user_match(const struct key *key, const void *criterion);
-static void user_destroy(struct key *key);
-static void user_describe(const struct key *user, struct seq_file *m);
-static long user_read(const struct key *key,
-		      char __user *buffer, size_t buflen);
-
 /*
  * user defined keys take an arbitrary string as the description and an
  * arbitrary blob of data as the payload
@@ -42,19 +34,13 @@
 	.read		= user_read,
 };
 
-struct user_key_payload {
-	struct rcu_head	rcu;		/* RCU destructor */
-	unsigned short	datalen;	/* length of this data */
-	char		data[0];	/* actual data */
-};
-
 EXPORT_SYMBOL_GPL(key_type_user);
 
 /*****************************************************************************/
 /*
  * instantiate a user defined key
  */
-static int user_instantiate(struct key *key, const void *data, size_t datalen)
+int user_instantiate(struct key *key, const void *data, size_t datalen)
 {
 	struct user_key_payload *upayload;
 	int ret;
@@ -78,18 +64,20 @@
 	rcu_assign_pointer(key->payload.data, upayload);
 	ret = 0;
 
- error:
+error:
 	return ret;
 
 } /* end user_instantiate() */
 
+EXPORT_SYMBOL_GPL(user_instantiate);
+
 /*****************************************************************************/
 /*
  * duplicate a user defined key
  * - both keys' semaphores are locked against further modification
  * - the new key cannot yet be accessed
  */
-static int user_duplicate(struct key *key, const struct key *source)
+int user_duplicate(struct key *key, const struct key *source)
 {
 	struct user_key_payload *upayload, *spayload;
 	int ret;
@@ -112,6 +100,8 @@
 
 } /* end user_duplicate() */
 
+EXPORT_SYMBOL_GPL(user_duplicate);
+
 /*****************************************************************************/
 /*
  * dispose of the old data from an updated user defined key
@@ -131,7 +121,7 @@
  * update a user defined key
  * - the key's semaphore is write-locked
  */
-static int user_update(struct key *key, const void *data, size_t datalen)
+int user_update(struct key *key, const void *data, size_t datalen)
 {
 	struct user_key_payload *upayload, *zap;
 	int ret;
@@ -163,26 +153,30 @@
 
 	call_rcu(&zap->rcu, user_update_rcu_disposal);
 
- error:
+error:
 	return ret;
 
 } /* end user_update() */
 
+EXPORT_SYMBOL_GPL(user_update);
+
 /*****************************************************************************/
 /*
  * match users on their name
  */
-static int user_match(const struct key *key, const void *description)
+int user_match(const struct key *key, const void *description)
 {
 	return strcmp(key->description, description) == 0;
 
 } /* end user_match() */
 
+EXPORT_SYMBOL_GPL(user_match);
+
 /*****************************************************************************/
 /*
  * dispose of the data dangling from the corpse of a user
  */
-static void user_destroy(struct key *key)
+void user_destroy(struct key *key)
 {
 	struct user_key_payload *upayload = key->payload.data;
 
@@ -190,11 +184,13 @@
 
 } /* end user_destroy() */
 
+EXPORT_SYMBOL_GPL(user_destroy);
+
 /*****************************************************************************/
 /*
  * describe the user key
  */
-static void user_describe(const struct key *key, struct seq_file *m)
+void user_describe(const struct key *key, struct seq_file *m)
 {
 	seq_puts(m, key->description);
 
@@ -202,13 +198,14 @@
 
 } /* end user_describe() */
 
+EXPORT_SYMBOL_GPL(user_describe);
+
 /*****************************************************************************/
 /*
  * read the key data
  * - the key's semaphore is read-locked
  */
-static long user_read(const struct key *key,
-		      char __user *buffer, size_t buflen)
+long user_read(const struct key *key, char __user *buffer, size_t buflen)
 {
 	struct user_key_payload *upayload;
 	long ret;
@@ -228,3 +225,5 @@
 	return ret;
 
 } /* end user_read() */
+
+EXPORT_SYMBOL_GPL(user_read);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b13be15..45c4149 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -122,11 +122,10 @@
 {
 	struct task_security_struct *tsec;
 
-	tsec = kmalloc(sizeof(struct task_security_struct), GFP_KERNEL);
+	tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
 	if (!tsec)
 		return -ENOMEM;
 
-	memset(tsec, 0, sizeof(struct task_security_struct));
 	tsec->magic = SELINUX_MAGIC;
 	tsec->task = task;
 	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
@@ -151,11 +150,10 @@
 	struct task_security_struct *tsec = current->security;
 	struct inode_security_struct *isec;
 
-	isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
+	isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
 
-	memset(isec, 0, sizeof(struct inode_security_struct));
 	init_MUTEX(&isec->sem);
 	INIT_LIST_HEAD(&isec->list);
 	isec->magic = SELINUX_MAGIC;
@@ -193,11 +191,10 @@
 	struct task_security_struct *tsec = current->security;
 	struct file_security_struct *fsec;
 
-	fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
+	fsec = kzalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
 	if (!fsec)
 		return -ENOMEM;
 
-	memset(fsec, 0, sizeof(struct file_security_struct));
 	fsec->magic = SELINUX_MAGIC;
 	fsec->file = file;
 	if (tsec && tsec->magic == SELINUX_MAGIC) {
@@ -227,11 +224,10 @@
 {
 	struct superblock_security_struct *sbsec;
 
-	sbsec = kmalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
+	sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
 	if (!sbsec)
 		return -ENOMEM;
 
-	memset(sbsec, 0, sizeof(struct superblock_security_struct));
 	init_MUTEX(&sbsec->sem);
 	INIT_LIST_HEAD(&sbsec->list);
 	INIT_LIST_HEAD(&sbsec->isec_head);
@@ -262,18 +258,17 @@
 }
 
 #ifdef CONFIG_SECURITY_NETWORK
-static int sk_alloc_security(struct sock *sk, int family, int priority)
+static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
 	struct sk_security_struct *ssec;
 
 	if (family != PF_UNIX)
 		return 0;
 
-	ssec = kmalloc(sizeof(*ssec), priority);
+	ssec = kzalloc(sizeof(*ssec), priority);
 	if (!ssec)
 		return -ENOMEM;
 
-	memset(ssec, 0, sizeof(*ssec));
 	ssec->magic = SELINUX_MAGIC;
 	ssec->sk = sk;
 	ssec->peer_sid = SECINITSID_UNLABELED;
@@ -1483,11 +1478,10 @@
 {
 	struct bprm_security_struct *bsec;
 
-	bsec = kmalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
+	bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
 	if (!bsec)
 		return -ENOMEM;
 
-	memset(bsec, 0, sizeof *bsec);
 	bsec->magic = SELINUX_MAGIC;
 	bsec->bprm = bprm;
 	bsec->sid = SECINITSID_UNLABELED;
@@ -1615,7 +1609,7 @@
 
 	if (tty) {
 		file_list_lock();
-		file = list_entry(tty->tty_files.next, typeof(*file), f_list);
+		file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
 		if (file) {
 			/* Revalidate access to controlling tty.
 			   Use inode_has_perm on the tty inode directly rather
@@ -2211,12 +2205,6 @@
 
 static int selinux_inode_getxattr (struct dentry *dentry, char *name)
 {
-	struct inode *inode = dentry->d_inode;
-	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
-
-	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
-		return -EOPNOTSUPP;
-
 	return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
@@ -2247,33 +2235,54 @@
 	return -EACCES;
 }
 
-static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
+/*
+ * Copy the in-core inode security context value to the user.  If the
+ * getxattr() prior to this succeeded, check to see if we need to
+ * canonicalize the value to be finally returned to the user.
+ *
+ * Permission check is handled by selinux_inode_getxattr hook.
+ */
+static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
 {
 	struct inode_security_struct *isec = inode->i_security;
 	char *context;
 	unsigned len;
 	int rc;
 
-	/* Permission check handled by selinux_inode_getxattr hook.*/
-
-	if (strcmp(name, XATTR_SELINUX_SUFFIX))
-		return -EOPNOTSUPP;
+	if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
 
 	rc = security_sid_to_context(isec->sid, &context, &len);
 	if (rc)
-		return rc;
+		goto out;
 
+	/* Probe for required buffer size */
 	if (!buffer || !size) {
-		kfree(context);
-		return len;
+		rc = len;
+		goto out_free;
 	}
+
 	if (size < len) {
-		kfree(context);
-		return -ERANGE;
+		rc = -ERANGE;
+		goto out_free;
+	}
+
+	if (err > 0) {
+		if ((len == err) && !(memcmp(context, buffer, len))) {
+			/* Don't need to canonicalize value */
+			rc = err;
+			goto out_free;
+		}
+		memset(buffer, 0, size);
 	}
 	memcpy(buffer, context, len);
+	rc = len;
+out_free:
 	kfree(context);
-	return len;
+out:
+	return rc;
 }
 
 static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -2704,8 +2713,7 @@
 	if (rc)
 		return rc;
 
-	if (info && ((unsigned long)info == 1 ||
-	             (unsigned long)info == 2 || SI_FROMKERNEL(info)))
+	if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
 		return 0;
 
 	if (!sig)
@@ -3380,7 +3388,7 @@
 	return err;
 }
 
-static int selinux_sk_alloc_security(struct sock *sk, int family, int priority)
+static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
 	return sk_alloc_security(sk, family, priority);
 }
@@ -3599,11 +3607,10 @@
 	struct task_security_struct *tsec = task->security;
 	struct ipc_security_struct *isec;
 
-	isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
+	isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
 	if (!isec)
 		return -ENOMEM;
 
-	memset(isec, 0, sizeof(struct ipc_security_struct));
 	isec->magic = SELINUX_MAGIC;
 	isec->sclass = sclass;
 	isec->ipc_perm = perm;
@@ -3631,11 +3638,10 @@
 {
 	struct msg_security_struct *msec;
 
-	msec = kmalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
+	msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
 	if (!msec)
 		return -ENOMEM;
 
-	memset(msec, 0, sizeof(struct msg_security_struct));
 	msec->magic = SELINUX_MAGIC;
 	msec->msg = msg;
 	msec->sid = SECINITSID_UNLABELED;
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index 718d7be..b10c34e 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -114,13 +114,12 @@
 	if (likely(netif != NULL))
 		goto out;
 	
-	new = kmalloc(sizeof(*new), GFP_ATOMIC);
+	new = kzalloc(sizeof(*new), GFP_ATOMIC);
 	if (!new) {
 		netif = ERR_PTR(-ENOMEM);
 		goto out;
 	}
 	
-	memset(new, 0, sizeof(*new));
 	nsec = &new->nsec;
 
 	ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index a45cc97..fdc3823 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -105,7 +105,7 @@
 	ssize_t length;
 	int new_value;
 
-	if (count < 0 || count >= PAGE_SIZE)
+	if (count >= PAGE_SIZE)
 		return -ENOMEM;
 	if (*ppos != 0) {
 		/* No partial writes. */
@@ -155,7 +155,7 @@
 	int new_value;
 	extern int selinux_disable(void);
 
-	if (count < 0 || count >= PAGE_SIZE)
+	if (count >= PAGE_SIZE)
 		return -ENOMEM;
 	if (*ppos != 0) {
 		/* No partial writes. */
@@ -242,7 +242,7 @@
 		goto out;
 	}
 
-	if ((count < 0) || (count > 64 * 1024 * 1024)
+	if ((count > 64 * 1024 * 1024)
 	    || (data = vmalloc(count)) == NULL) {
 		length = -ENOMEM;
 		goto out;
@@ -284,7 +284,7 @@
 	if (length)
 		return length;
 
-	if (count < 0 || count >= PAGE_SIZE)
+	if (count >= PAGE_SIZE)
 		return -ENOMEM;
 	if (*ppos != 0) {
 		/* No partial writes. */
@@ -332,7 +332,7 @@
 	if (length)
 		return length;
 
-	if (count < 0 || count >= PAGE_SIZE)
+	if (count >= PAGE_SIZE)
 		return -ENOMEM;
 	if (*ppos != 0) {
 		/* No partial writes. */
@@ -424,15 +424,13 @@
 		return length;
 
 	length = -ENOMEM;
-	scon = kmalloc(size+1, GFP_KERNEL);
+	scon = kzalloc(size+1, GFP_KERNEL);
 	if (!scon)
 		return length;
-	memset(scon, 0, size+1);
 
-	tcon = kmalloc(size+1, GFP_KERNEL);
+	tcon = kzalloc(size+1, GFP_KERNEL);
 	if (!tcon)
 		goto out;
-	memset(tcon, 0, size+1);
 
 	length = -EINVAL;
 	if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
@@ -475,15 +473,13 @@
 		return length;
 
 	length = -ENOMEM;
-	scon = kmalloc(size+1, GFP_KERNEL);
+	scon = kzalloc(size+1, GFP_KERNEL);
 	if (!scon)
 		return length;
-	memset(scon, 0, size+1);
 
-	tcon = kmalloc(size+1, GFP_KERNEL);
+	tcon = kzalloc(size+1, GFP_KERNEL);
 	if (!tcon)
 		goto out;
-	memset(tcon, 0, size+1);
 
 	length = -EINVAL;
 	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -536,15 +532,13 @@
 		return length;
 
 	length = -ENOMEM;
-	scon = kmalloc(size+1, GFP_KERNEL);
+	scon = kzalloc(size+1, GFP_KERNEL);
 	if (!scon)
 		return length;
-	memset(scon, 0, size+1);
 
-	tcon = kmalloc(size+1, GFP_KERNEL);
+	tcon = kzalloc(size+1, GFP_KERNEL);
 	if (!tcon)
 		goto out;
-	memset(tcon, 0, size+1);
 
 	length = -EINVAL;
 	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -595,15 +589,13 @@
 		return length;
 
 	length = -ENOMEM;
-	con = kmalloc(size+1, GFP_KERNEL);
+	con = kzalloc(size+1, GFP_KERNEL);
 	if (!con)
 		return length;
-	memset(con, 0, size+1);
 
-	user = kmalloc(size+1, GFP_KERNEL);
+	user = kzalloc(size+1, GFP_KERNEL);
 	if (!user)
 		goto out;
-	memset(user, 0, size+1);
 
 	length = -EINVAL;
 	if (sscanf(buf, "%s %s", con, user) != 2)
@@ -658,15 +650,13 @@
 		return length;
 
 	length = -ENOMEM;
-	scon = kmalloc(size+1, GFP_KERNEL);
+	scon = kzalloc(size+1, GFP_KERNEL);
 	if (!scon)
 		return length;
-	memset(scon, 0, size+1);
 
-	tcon = kmalloc(size+1, GFP_KERNEL);
+	tcon = kzalloc(size+1, GFP_KERNEL);
 	if (!tcon)
 		goto out;
-	memset(tcon, 0, size+1);
 
 	length = -EINVAL;
 	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -739,7 +729,7 @@
 	if (!filep->f_op)
 		goto out;
 
-	if (count < 0 || count > PAGE_SIZE) {
+	if (count > PAGE_SIZE) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -800,7 +790,7 @@
 	if (!filep->f_op)
 		goto out;
 
-	if (count < 0 || count >= PAGE_SIZE) {
+	if (count >= PAGE_SIZE) {
 		length = -ENOMEM;
 		goto out;
 	}
@@ -858,7 +848,7 @@
 	if (!filep->f_op)
 		goto out;
 
-	if (count < 0 || count >= PAGE_SIZE) {
+	if (count >= PAGE_SIZE) {
 		length = -ENOMEM;
 		goto out;
 	}
@@ -924,7 +914,7 @@
 
 	file_list_lock();
 	list_for_each(p, &sb->s_files) {
-		struct file * filp = list_entry(p, struct file, f_list);
+		struct file * filp = list_entry(p, struct file, f_u.fu_list);
 		struct dentry * dentry = filp->f_dentry;
 
 		if (dentry->d_parent != de) {
@@ -1032,7 +1022,7 @@
 	ssize_t ret;
 	int new_value;
 
-	if (count < 0 || count >= PAGE_SIZE) {
+	if (count >= PAGE_SIZE) {
 		ret = -ENOMEM;
 		goto out;
 	}
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index daf2880..d2737ed 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -220,10 +220,9 @@
 	u32 len;
 	int rc;
 
-	booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
+	booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
 	if (!booldatum)
 		return -1;
-	memset(booldatum, 0, sizeof(struct cond_bool_datum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -321,10 +320,9 @@
 		goto err;
 	}
 
-	list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
+	list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL);
 	if (!list)
 		goto err;
-	memset(list, 0, sizeof(*list));
 
 	list->node = node_ptr;
 	if (!data->head)
@@ -414,11 +412,10 @@
 		if (rc < 0)
 			goto err;
 
-		expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
+		expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
 		if (!expr) {
 			goto err;
 		}
-		memset(expr, 0, sizeof(struct cond_expr));
 
 		expr->expr_type = le32_to_cpu(buf[0]);
 		expr->bool = le32_to_cpu(buf[1]);
@@ -460,10 +457,9 @@
 	len = le32_to_cpu(buf[0]);
 
 	for (i = 0; i < len; i++) {
-		node = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
+		node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
 		if (!node)
 			goto err;
-		memset(node, 0, sizeof(struct cond_node));
 
 		if (cond_read_node(p, node, fp) != 0)
 			goto err;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index d515154..47024a6 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -39,12 +39,11 @@
 	n = src->node;
 	prev = NULL;
 	while (n) {
-		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		new = kzalloc(sizeof(*new), GFP_ATOMIC);
 		if (!new) {
 			ebitmap_destroy(dst);
 			return -ENOMEM;
 		}
-		memset(new, 0, sizeof(*new));
 		new->startbit = n->startbit;
 		new->map = n->map;
 		new->next = NULL;
@@ -150,10 +149,9 @@
 	if (!value)
 		return 0;
 
-	new = kmalloc(sizeof(*new), GFP_ATOMIC);
+	new = kzalloc(sizeof(*new), GFP_ATOMIC);
 	if (!new)
 		return -ENOMEM;
-	memset(new, 0, sizeof(*new));
 
 	new->startbit = bit & ~(MAPSIZE - 1);
 	new->map = (MAPBIT << (bit - new->startbit));
@@ -232,13 +230,12 @@
 			printk(KERN_ERR "security: ebitmap: truncated map\n");
 			goto bad;
 		}
-		n = kmalloc(sizeof(*n), GFP_KERNEL);
+		n = kzalloc(sizeof(*n), GFP_KERNEL);
 		if (!n) {
 			printk(KERN_ERR "security: ebitmap: out of memory\n");
 			rc = -ENOMEM;
 			goto bad;
 		}
-		memset(n, 0, sizeof(*n));
 
 		n->startbit = le32_to_cpu(buf[0]);
 
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 26661fc..24e5ec9 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -15,11 +15,10 @@
 	struct hashtab *p;
 	u32 i;
 
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (p == NULL)
 		return p;
 
-	memset(p, 0, sizeof(*p));
 	p->size = size;
 	p->nel = 0;
 	p->hash_value = hash_value;
@@ -55,10 +54,9 @@
 	if (cur && (h->keycmp(h, key, cur->key) == 0))
 		return -EEXIST;
 
-	newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
+	newnode = kzalloc(sizeof(*newnode), GFP_KERNEL);
 	if (newnode == NULL)
 		return -ENOMEM;
-	memset(newnode, 0, sizeof(*newnode));
 	newnode->key = key;
 	newnode->datum = datum;
 	if (prev) {
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 8e6262d..2f5f539 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -121,12 +121,11 @@
 	int rc;
 	struct role_datum *role;
 
-	role = kmalloc(sizeof(*role), GFP_KERNEL);
+	role = kzalloc(sizeof(*role), GFP_KERNEL);
 	if (!role) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(role, 0, sizeof(*role));
 	role->value = ++p->p_roles.nprim;
 	if (role->value != OBJECT_R_VAL) {
 		rc = -EINVAL;
@@ -851,12 +850,11 @@
 	__le32 buf[2];
 	u32 len;
 
-	perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
+	perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL);
 	if (!perdatum) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(perdatum, 0, sizeof(*perdatum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -893,12 +891,11 @@
 	u32 len, nel;
 	int i, rc;
 
-	comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
+	comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL);
 	if (!comdatum) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(comdatum, 0, sizeof(*comdatum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -950,10 +947,9 @@
 
 	lc = NULL;
 	for (i = 0; i < ncons; i++) {
-		c = kmalloc(sizeof(*c), GFP_KERNEL);
+		c = kzalloc(sizeof(*c), GFP_KERNEL);
 		if (!c)
 			return -ENOMEM;
-		memset(c, 0, sizeof(*c));
 
 		if (lc) {
 			lc->next = c;
@@ -969,10 +965,9 @@
 		le = NULL;
 		depth = -1;
 		for (j = 0; j < nexpr; j++) {
-			e = kmalloc(sizeof(*e), GFP_KERNEL);
+			e = kzalloc(sizeof(*e), GFP_KERNEL);
 			if (!e)
 				return -ENOMEM;
-			memset(e, 0, sizeof(*e));
 
 			if (le) {
 				le->next = e;
@@ -1033,12 +1028,11 @@
 	u32 len, len2, ncons, nel;
 	int i, rc;
 
-	cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
+	cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL);
 	if (!cladatum) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(cladatum, 0, sizeof(*cladatum));
 
 	rc = next_entry(buf, fp, sizeof(u32)*6);
 	if (rc < 0)
@@ -1127,12 +1121,11 @@
 	__le32 buf[2];
 	u32 len;
 
-	role = kmalloc(sizeof(*role), GFP_KERNEL);
+	role = kzalloc(sizeof(*role), GFP_KERNEL);
 	if (!role) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(role, 0, sizeof(*role));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -1188,12 +1181,11 @@
 	__le32 buf[3];
 	u32 len;
 
-	typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
+	typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL);
 	if (!typdatum) {
 		rc = -ENOMEM;
 		return rc;
 	}
-	memset(typdatum, 0, sizeof(*typdatum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -1261,12 +1253,11 @@
 	__le32 buf[2];
 	u32 len;
 
-	usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
+	usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
 	if (!usrdatum) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(usrdatum, 0, sizeof(*usrdatum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -1316,12 +1307,11 @@
 	__le32 buf[2];
 	u32 len;
 
-	levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
+	levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC);
 	if (!levdatum) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(levdatum, 0, sizeof(*levdatum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -1368,12 +1358,11 @@
 	__le32 buf[3];
 	u32 len;
 
-	catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
+	catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC);
 	if (!catdatum) {
 		rc = -ENOMEM;
 		goto out;
 	}
-	memset(catdatum, 0, sizeof(*catdatum));
 
 	rc = next_entry(buf, fp, sizeof buf);
 	if (rc < 0)
@@ -1567,12 +1556,11 @@
 	nel = le32_to_cpu(buf[0]);
 	ltr = NULL;
 	for (i = 0; i < nel; i++) {
-		tr = kmalloc(sizeof(*tr), GFP_KERNEL);
+		tr = kzalloc(sizeof(*tr), GFP_KERNEL);
 		if (!tr) {
 			rc = -ENOMEM;
 			goto bad;
 		}
-		memset(tr, 0, sizeof(*tr));
 		if (ltr) {
 			ltr->next = tr;
 		} else {
@@ -1593,12 +1581,11 @@
 	nel = le32_to_cpu(buf[0]);
 	lra = NULL;
 	for (i = 0; i < nel; i++) {
-		ra = kmalloc(sizeof(*ra), GFP_KERNEL);
+		ra = kzalloc(sizeof(*ra), GFP_KERNEL);
 		if (!ra) {
 			rc = -ENOMEM;
 			goto bad;
 		}
-		memset(ra, 0, sizeof(*ra));
 		if (lra) {
 			lra->next = ra;
 		} else {
@@ -1627,12 +1614,11 @@
 		nel = le32_to_cpu(buf[0]);
 		l = NULL;
 		for (j = 0; j < nel; j++) {
-			c = kmalloc(sizeof(*c), GFP_KERNEL);
+			c = kzalloc(sizeof(*c), GFP_KERNEL);
 			if (!c) {
 				rc = -ENOMEM;
 				goto bad;
 			}
-			memset(c, 0, sizeof(*c));
 			if (l) {
 				l->next = c;
 			} else {
@@ -1743,12 +1729,11 @@
 		if (rc < 0)
 			goto bad;
 		len = le32_to_cpu(buf[0]);
-		newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
+		newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
 		if (!newgenfs) {
 			rc = -ENOMEM;
 			goto bad;
 		}
-		memset(newgenfs, 0, sizeof(*newgenfs));
 
 		newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
 		if (!newgenfs->fstype) {
@@ -1790,12 +1775,11 @@
 				goto bad;
 			len = le32_to_cpu(buf[0]);
 
-			newc = kmalloc(sizeof(*newc), GFP_KERNEL);
+			newc = kzalloc(sizeof(*newc), GFP_KERNEL);
 			if (!newc) {
 				rc = -ENOMEM;
 				goto bad;
 			}
-			memset(newc, 0, sizeof(*newc));
 
 			newc->u.name = kmalloc(len + 1,GFP_KERNEL);
 			if (!newc->u.name) {
@@ -1843,12 +1827,11 @@
 		nel = le32_to_cpu(buf[0]);
 		lrt = NULL;
 		for (i = 0; i < nel; i++) {
-			rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+			rt = kzalloc(sizeof(*rt), GFP_KERNEL);
 			if (!rt) {
 				rc = -ENOMEM;
 				goto bad;
 			}
-			memset(rt, 0, sizeof(*rt));
 			if (lrt)
 				lrt->next = rt;
 			else
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index aecdded..44eb4d7 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1531,12 +1531,11 @@
 	}
 	usercon.user = user->value;
 
-	mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC);
+	mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
 	if (!mysids) {
 		rc = -ENOMEM;
 		goto out_unlock;
 	}
-	memset(mysids, 0, maxnel*sizeof(*mysids));
 
 	ebitmap_for_each_bit(&user->roles, rnode, i) {
 		if (!ebitmap_node_get_bit(rnode, i))
@@ -1566,13 +1565,12 @@
 				mysids[mynel++] = sid;
 			} else {
 				maxnel += SIDS_NEL;
-				mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
+				mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
 				if (!mysids2) {
 					rc = -ENOMEM;
 					kfree(mysids);
 					goto out_unlock;
 				}
-				memset(mysids2, 0, maxnel*sizeof(*mysids2));
 				memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
 				kfree(mysids);
 				mysids = mysids2;
@@ -1714,12 +1712,11 @@
 		goto out;
 	}
 
-	*names = (char**)kmalloc(sizeof(char*) * *len, GFP_ATOMIC);
+	*names = (char**)kcalloc(*len, sizeof(char*), GFP_ATOMIC);
 	if (!*names)
 		goto err;
-	memset(*names, 0, sizeof(char*) * *len);
 
-	*values = (int*)kmalloc(sizeof(int) * *len, GFP_ATOMIC);
+	*values = (int*)kcalloc(*len, sizeof(int), GFP_ATOMIC);
 	if (!*values)
 		goto err;
 
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index b2d5db2..559ead6 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -20,6 +20,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/sizes.h>
 #include <asm/hardware/amba.h>
 
 #include <sound/driver.h>
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 38b20ef..877bb00 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -275,23 +275,23 @@
 	return 0;
 }
 
-static int pxa2xx_ac97_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int pxa2xx_ac97_suspend(struct device *_dev, pm_message_t state)
 {
 	snd_card_t *card = dev_get_drvdata(_dev);
 	int ret = 0;
 
-	if (card && level == SUSPEND_DISABLE)
+	if (card)
 		ret = pxa2xx_ac97_do_suspend(card, PMSG_SUSPEND);
 
 	return ret;
 }
 
-static int pxa2xx_ac97_resume(struct device *_dev, u32 level)
+static int pxa2xx_ac97_resume(struct device *_dev)
 {
 	snd_card_t *card = dev_get_drvdata(_dev);
 	int ret = 0;
 
-	if (card && level == RESUME_ENABLE)
+	if (card)
 		ret = pxa2xx_ac97_do_resume(card);
 
 	return ret;
diff --git a/sound/core/init.c b/sound/core/init.c
index c72a791..59202de 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -676,8 +676,8 @@
 #define SND_GENERIC_NAME	"snd_generic"
 
 #ifdef CONFIG_PM
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
-static int snd_generic_resume(struct device *dev, u32 level);
+static int snd_generic_suspend(struct device *dev, pm_message_t state);
+static int snd_generic_resume(struct device *dev);
 #endif
 
 /* initialized in sound.c */
@@ -818,13 +818,10 @@
 
 #ifdef CONFIG_SND_GENERIC_DRIVER
 /* suspend/resume callbacks for snd_generic platform device */
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level)
+static int snd_generic_suspend(struct device *dev, pm_message_t state)
 {
 	snd_card_t *card;
 
-	if (level != SUSPEND_DISABLE)
-		return 0;
-
 	card = get_snd_generic_card(dev);
 	if (card->power_state == SNDRV_CTL_POWER_D3hot)
 		return 0;
@@ -834,13 +831,10 @@
 	return 0;
 }
 
-static int snd_generic_resume(struct device *dev, u32 level)
+static int snd_generic_resume(struct device *dev)
 {
 	snd_card_t *card;
 
-	if (level != RESUME_ENABLE)
-		return 0;
-
 	card = get_snd_generic_card(dev);
 	if (card->power_state == SNDRV_CTL_POWER_D0)
 		return 0;
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index e72cec7..129abab 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -190,7 +190,7 @@
  *
  * Returns the pointer of the buffer, or NULL if no enoguh memory.
  */
-void *snd_malloc_pages(size_t size, unsigned int gfp_flags)
+void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
 {
 	int pg;
 	void *res;
@@ -235,7 +235,7 @@
 {
 	int pg;
 	void *res;
-	unsigned int gfp_flags;
+	gfp_t gfp_flags;
 
 	snd_assert(size > 0, return NULL);
 	snd_assert(dma != NULL, return NULL);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 67abeba..e97b2d1 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2949,8 +2949,7 @@
 		return NOPAGE_OOM;
 	runtime = substream->runtime;
 	page = virt_to_page(runtime->status);
-	if (!PageReserved(page))
-		get_page(page);
+	get_page(page);
 	if (type)
 		*type = VM_FAULT_MINOR;
 	return page;
@@ -2992,8 +2991,7 @@
 		return NOPAGE_OOM;
 	runtime = substream->runtime;
 	page = virt_to_page(runtime->control);
-	if (!PageReserved(page))
-		get_page(page);
+	get_page(page);
 	if (type)
 		*type = VM_FAULT_MINOR;
 	return page;
@@ -3066,8 +3064,7 @@
 		vaddr = runtime->dma_area + offset;
 		page = virt_to_page(vaddr);
 	}
-	if (!PageReserved(page))
-		get_page(page);
+	get_page(page);
 	if (type)
 		*type = VM_FAULT_MINOR;
 	return page;
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 207c2c5..0e4df88 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -51,7 +51,7 @@
 	gf1_wave_t *wp, *prev;
 	gf1_xwave_t xp;
 	int err;
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 	unsigned int real_size;
 	
 	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
@@ -144,7 +144,8 @@
 	snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
 	gf1_instrument_t *ip;
 	gf1_xinstrument_t ix;
-	int err, gfp_mask;
+	int err;
+	gfp_t gfp_mask;
 
 	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
 		return -EINVAL;
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 67c24c8..7c19fbb 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -129,7 +129,7 @@
 	iwffff_wave_t *wp, *prev;
 	iwffff_xwave_t xp;
 	int err;
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 	unsigned int real_size;
 	
 	gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
@@ -236,7 +236,7 @@
 	iwffff_layer_t *lp, *prev_lp;
 	iwffff_xlayer_t lx;
 	int err;
-	unsigned int gfp_mask;
+	gfp_t gfp_mask;
 
 	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
 		return -EINVAL;
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
index 6183d21..17ab94e 100644
--- a/sound/core/seq/instr/ainstr_simple.c
+++ b/sound/core/seq/instr/ainstr_simple.c
@@ -57,7 +57,8 @@
 	snd_simple_ops_t *ops = (snd_simple_ops_t *)private_data;
 	simple_instrument_t *ip;
 	simple_xinstrument_t ix;
-	int err, gfp_mask;
+	int err;
+	gfp_t gfp_mask;
 	unsigned int real_size;
 
 	if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 9e76bdd..b57519a 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -231,7 +231,7 @@
 		devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
 	if (card)
 		device = card->dev;
-	class_device_create(sound_class, MKDEV(major, minor), device, "%s", name);
+	class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name);
 
 	up(&sound_mutex);
 	return 0;
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index 3ecef46..fd25aca 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -55,6 +55,7 @@
 #include <linux/pci.h>
 #include <linux/ac97_codec.h>
 #include <asm/uaccess.h>
+#include <asm/semaphore.h>
 
 #define CODEC_ID_BUFSZ 14
 
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index a78e48d..6b46a8a 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -35,7 +35,6 @@
 
 #undef DEBUG
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff --git a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c
index d2b9bed..b3ea719 100644
--- a/sound/oss/awe_wave.c
+++ b/sound/oss/awe_wave.c
@@ -6062,7 +6062,7 @@
 	io1 = pnp_port_start(dev,0);
 	io2 = pnp_port_start(dev,1);
 	io3 = pnp_port_start(dev,2);
-	printk(KERN_INFO "AWE32: A PnP Wave Table was detected at IO's %#x,%#x,%#x\n.",
+	printk(KERN_INFO "AWE32: A PnP Wave Table was detected at IO's %#x,%#x,%#x.\n",
 	       io1, io2, io3);
 	setup_ports(io1, io2, io3);
 
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index 6ec308f..7c59e2d 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -195,10 +195,12 @@
 		CS_OUT2(0x15, 0x00);	/* Select logical device 0 (WSS/SB/FM) */
 		CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff);	/* WSS base */
 
-		if (check_region(0x388, 4))	/* Not free */
+		if (!request_region(0x388, 4, "FM"))	/* Not free */
 			CS_OUT3(0x48, 0x00, 0x00)	/* FM base off */
-		else
+		else {
+			release_region(0x388, 4);
 			CS_OUT3(0x48, 0x03, 0x88);	/* FM base 0x388 */
+		}
 
 		CS_OUT3(0x42, 0x00, 0x00);	/* SB base off */
 		CS_OUT2(0x22, irq);		/* SB+WSS IRQ */
diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h
index 9a2f50f..222014c 100644
--- a/sound/oss/dmasound/dmasound.h
+++ b/sound/oss/dmasound/dmasound.h
@@ -116,7 +116,7 @@
     const char *name;
     const char *name2;
     struct module *owner;
-    void *(*dma_alloc)(unsigned int, int);
+    void *(*dma_alloc)(unsigned int, gfp_t);
     void (*dma_free)(void *, unsigned int);
     int (*irqinit)(void);
 #ifdef MODULE
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index 8daaf87..59eb53f 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -114,7 +114,7 @@
 /*** Low level stuff *********************************************************/
 
 
-static void *AtaAlloc(unsigned int size, int flags);
+static void *AtaAlloc(unsigned int size, gfp_t flags);
 static void AtaFree(void *, unsigned int size);
 static int AtaIrqInit(void);
 #ifdef MODULE
@@ -810,7 +810,7 @@
  * Atari (TT/Falcon)
  */
 
-static void *AtaAlloc(unsigned int size, int flags)
+static void *AtaAlloc(unsigned int size, gfp_t flags)
 {
 	return atari_stram_alloc(size, "dmasound");
 }
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 2ceb46f..b2bf8ba 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -271,7 +271,7 @@
 
 /*** Low level stuff *********************************************************/
 
-static void *PMacAlloc(unsigned int size, int flags);
+static void *PMacAlloc(unsigned int size, gfp_t flags);
 static void PMacFree(void *ptr, unsigned int size);
 static int PMacIrqInit(void);
 #ifdef MODULE
@@ -614,7 +614,7 @@
 /*
  * PCI PowerMac, with AWACS, Screamer, Burgundy, DACA or Tumbler and DBDMA.
  */
-static void *PMacAlloc(unsigned int size, int flags)
+static void *PMacAlloc(unsigned int size, gfp_t flags)
 {
 	return kmalloc(size, flags);
 }
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index 558db53..d59f60b 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -69,7 +69,7 @@
 /*** Low level stuff *********************************************************/
 
 
-static void *AmiAlloc(unsigned int size, int flags);
+static void *AmiAlloc(unsigned int size, gfp_t flags);
 static void AmiFree(void *obj, unsigned int size);
 static int AmiIrqInit(void);
 #ifdef MODULE
@@ -317,7 +317,7 @@
 	enable_heartbeat();
 }
 
-static void *AmiAlloc(unsigned int size, int flags)
+static void *AmiAlloc(unsigned int size, gfp_t flags)
 {
 	return amiga_chip_alloc((long)size, "dmasound [Paula]");
 }
diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c
index 92c25a0..1ddaa62 100644
--- a/sound/oss/dmasound/dmasound_q40.c
+++ b/sound/oss/dmasound/dmasound_q40.c
@@ -36,7 +36,7 @@
 /*** Low level stuff *********************************************************/
 
 
-static void *Q40Alloc(unsigned int size, int flags);
+static void *Q40Alloc(unsigned int size, gfp_t flags);
 static void Q40Free(void *, unsigned int);
 static int Q40IrqInit(void);
 #ifdef MODULE
@@ -358,7 +358,7 @@
 
 /*** Low level stuff *********************************************************/
 
-static void *Q40Alloc(unsigned int size, int flags)
+static void *Q40Alloc(unsigned int size, gfp_t flags)
 {
          return kmalloc(size, flags); /* change to vmalloc */
 }
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 95fa81e..d33bb46 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -567,7 +567,7 @@
 		devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
 				S_IFCHR | dev_list[i].mode,
 				"sound/%s", dev_list[i].name);
-		class_device_create(sound_class,
+		class_device_create(sound_class, NULL,
 				    MKDEV(SOUND_MAJOR, dev_list[i].minor),
 				    NULL, "%s", dev_list[i].name);
 
@@ -579,7 +579,7 @@
 						dev_list[i].minor + (j*0x10)),
 					S_IFCHR | dev_list[i].mode,
 					"sound/%s%d", dev_list[i].name, j);
-			class_device_create(sound_class,
+			class_device_create(sound_class, NULL,
 					    MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
 					    NULL, "%s%d", dev_list[i].name, j);
 		}
diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c
index b92ba89..b1a4eeb 100644
--- a/sound/oss/wavfront.c
+++ b/sound/oss/wavfront.c
@@ -2434,7 +2434,7 @@
 	   consumes 16.
 	*/
 
-	if (check_region (io_base, 16)) {
+	if (!request_region (io_base, 16, "wavfront")) {
 		printk (KERN_ERR LOGNAME "IO address range 0x%x - 0x%x "
 			"already in use - ignored\n", dev.base,
 			dev.base+15);
@@ -2466,10 +2466,13 @@
 		} else {
 			printk (KERN_WARNING LOGNAME "not raw, but no "
 				"hardware version!\n");
+			release_region (io_base, 16);
 			return 0;
 		}
 
 		if (!wf_raw) {
+			/* will re-acquire region in install_wavefront() */
+			release_region (io_base, 16);
 			return 1;
 		} else {
 			printk (KERN_INFO LOGNAME
@@ -2489,6 +2492,7 @@
 
 	if (wavefront_hw_reset ()) {
 		printk (KERN_WARNING LOGNAME "hardware reset failed\n");
+		release_region (io_base, 16);
 		return 0;
 	}
 
@@ -2496,6 +2500,8 @@
 
 	dev.has_fx = (detect_wffx () == 0);
 
+	/* will re-acquire region in install_wavefront() */
+	release_region (io_base, 16);
 	return 1;
 }
 
@@ -2804,17 +2810,27 @@
 }
 
 static int __init install_wavefront (void)
-
 {
+	if (!request_region (dev.base+2, 6, "wavefront synth"))
+		return -1;
+
+	if (dev.has_fx) {
+		if (!request_region (dev.base+8, 8, "wavefront fx")) {
+			release_region (dev.base+2, 6);
+			return -1;
+		}
+	}
+
 	if ((dev.synth_dev = register_sound_synth (&wavefront_fops, -1)) < 0) {
 		printk (KERN_ERR LOGNAME "cannot register raw synth\n");
-		return -1;
+		goto err_out;
 	}
 
 #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
 	if ((dev.oss_dev = sound_alloc_synthdev()) == -1) {
 		printk (KERN_ERR LOGNAME "Too many sequencers\n");
-		return -1;
+		/* FIXME: leak: should unregister sound synth */
+		goto err_out;
 	} else {
 		synth_devs[dev.oss_dev] = &wavefront_operations;
 	}
@@ -2827,20 +2843,20 @@
 		sound_unload_synthdev (dev.oss_dev);
 #endif /* OSS_SUPPORT_SEQ */ 
 
-		return -1;
+		goto err_out;
 	}
     
-	request_region (dev.base+2, 6, "wavefront synth");
-
-	if (dev.has_fx) {
-		request_region (dev.base+8, 8, "wavefront fx");
-	}
-
 	if (wavefront_config_midi ()) {
 		printk (KERN_WARNING LOGNAME "could not initialize MIDI.\n");
 	}
 
 	return dev.oss_dev;
+
+err_out:
+	release_region (dev.base+2, 6);
+	if (dev.has_fx)
+		release_region (dev.base+8, 8);
+	return -1;
 }
 
 static void __exit uninstall_wavefront (void)
diff --git a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
index 05203ad..8dae59b 100644
--- a/sound/oss/ymfpci.c
+++ b/sound/oss/ymfpci.c
@@ -107,14 +107,15 @@
  */
 
 static struct pci_device_id ymf_id_tbl[] = {
-#define DEV(v, d, data) \
-  { PCI_VENDOR_ID_##v, PCI_DEVICE_ID_##v##_##d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)data }
-	DEV (YAMAHA, 724,  "YMF724"),
-	DEV (YAMAHA, 724F, "YMF724F"),
-	DEV (YAMAHA, 740,  "YMF740"),
-	DEV (YAMAHA, 740C, "YMF740C"),
-	DEV (YAMAHA, 744,  "YMF744"),
-	DEV (YAMAHA, 754,  "YMF754"),
+#define DEV(dev, data) \
+	{ PCI_VENDOR_ID_YAMAHA, dev, PCI_ANY_ID, PCI_ANY_ID, 0, 0, \
+		(unsigned long)data }
+	DEV (PCI_DEVICE_ID_YAMAHA_724,  "YMF724"),
+	DEV (PCI_DEVICE_ID_YAMAHA_724F, "YMF724F"),
+	DEV (PCI_DEVICE_ID_YAMAHA_740,  "YMF740"),
+	DEV (PCI_DEVICE_ID_YAMAHA_740C, "YMF740C"),
+	DEV (PCI_DEVICE_ID_YAMAHA_744,  "YMF744"),
+	DEV (PCI_DEVICE_ID_YAMAHA_754,  "YMF754"),
 #undef DEV
 	{ }
 };
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index f560dd8..d833349 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -197,7 +197,7 @@
 	spin_unlock(&h->lock);
 
 	if (dstatus & HARMONY_DSTATUS_PN) {
-		if (h->psubs) {
+		if (h->psubs && h->st.playing) {
 			spin_lock(&h->lock);
 			h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
 			h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
@@ -216,7 +216,7 @@
 	}
 
 	if (dstatus & HARMONY_DSTATUS_RN) {
-		if (h->csubs) {
+		if (h->csubs && h->st.capturing) {
 			spin_lock(&h->lock);
 			h->cbuf.buf += h->cbuf.count;
 			h->cbuf.buf %= h->cbuf.size;
@@ -316,6 +316,7 @@
 	case SNDRV_PCM_TRIGGER_STOP:
 		h->st.playing = 0;
 		harmony_mute(h);
+		harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
 		harmony_disable_interrupts(h);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -351,8 +352,9 @@
 		break;
         case SNDRV_PCM_TRIGGER_STOP:
 		h->st.capturing = 0;
-                harmony_mute(h);
-                harmony_disable_interrupts(h);
+		harmony_mute(h);
+		harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
+		harmony_disable_interrupts(h);
 		break;
         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -408,7 +410,8 @@
 	
 	h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
 	h->pbuf.count = snd_pcm_lib_period_bytes(ss);
-	h->pbuf.buf = 0;
+	if (h->pbuf.buf >= h->pbuf.size)
+		h->pbuf.buf = 0;
 	h->st.playing = 0;
 
 	h->st.rate = snd_harmony_rate_bits(rt->rate);
@@ -437,7 +440,8 @@
 
         h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
         h->cbuf.count = snd_pcm_lib_period_bytes(ss);
-        h->cbuf.buf = 0;
+	if (h->cbuf.buf >= h->cbuf.size)
+	        h->cbuf.buf = 0;
 	h->st.capturing = 0;
 
         h->st.rate = snd_harmony_rate_bits(rt->rate);
@@ -712,13 +716,14 @@
 
 	left = (h->st.gain >> shift_left) & mask;
 	right = (h->st.gain >> shift_right) & mask;
-
 	if (invert) {
 		left = mask - left;
 		right = mask - right;
 	}
+	
 	ucontrol->value.integer.value[0] = left;
-	ucontrol->value.integer.value[1] = right;
+	if (shift_left != shift_right)
+		ucontrol->value.integer.value[1] = right;
 
 	spin_unlock_irqrestore(&h->mixer_lock, flags);
 
@@ -738,22 +743,82 @@
 	int old_gain = h->st.gain;
 	unsigned long flags;
 	
-	left = ucontrol->value.integer.value[0] & mask;
-	right = ucontrol->value.integer.value[1] & mask;
-	if (invert) {
-		left = mask - left;
-		right = mask - right;
-	}
-	
 	spin_lock_irqsave(&h->mixer_lock, flags);
 
-	h->st.gain &= ~( (mask << shift_right) | (mask << shift_left) );
- 	h->st.gain |=  ( (left << shift_left) | (right << shift_right) );
+	left = ucontrol->value.integer.value[0] & mask;
+	if (invert)
+		left = mask - left;
+	h->st.gain &= ~( (mask << shift_left ) );
+ 	h->st.gain |= (left << shift_left);
+
+	if (shift_left != shift_right) {
+		right = ucontrol->value.integer.value[1] & mask;
+		if (invert)
+			right = mask - right;
+		h->st.gain &= ~( (mask << shift_right) );
+		h->st.gain |= (right << shift_right);
+	}
+
 	snd_harmony_set_new_gain(h);
 
 	spin_unlock_irqrestore(&h->mixer_lock, flags);
 	
-	return (old_gain - h->st.gain);
+	return h->st.gain != old_gain;
+}
+
+static int 
+snd_harmony_captureroute_info(snd_kcontrol_t *kc, 
+			      snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[2] = { "Line", "Mic" };
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int 
+snd_harmony_captureroute_get(snd_kcontrol_t *kc, 
+			     snd_ctl_elem_value_t *ucontrol)
+{
+	harmony_t *h = snd_kcontrol_chip(kc);
+	int value;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&h->mixer_lock, flags);
+
+	value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1;
+	ucontrol->value.enumerated.item[0] = value;
+
+	spin_unlock_irqrestore(&h->mixer_lock, flags);
+
+	return 0;
+}  
+
+static int 
+snd_harmony_captureroute_put(snd_kcontrol_t *kc, 
+			     snd_ctl_elem_value_t *ucontrol)
+{
+	harmony_t *h = snd_kcontrol_chip(kc);
+	int value;
+	int old_gain = h->st.gain;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&h->mixer_lock, flags);
+
+	value = ucontrol->value.enumerated.item[0] & 1;
+	h->st.gain &= ~HARMONY_GAIN_IS_MASK;
+ 	h->st.gain |= value << HARMONY_GAIN_IS_SHIFT;
+
+	snd_harmony_set_new_gain(h);
+
+	spin_unlock_irqrestore(&h->mixer_lock, flags);
+	
+	return h->st.gain != old_gain;
 }
 
 #define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \
@@ -767,10 +832,25 @@
                    ((mask) << 16) | ((invert) << 24)) }
 
 static snd_kcontrol_new_t snd_harmony_controls[] = {
-	HARMONY_VOLUME("Playback Volume", HARMONY_GAIN_LO_SHIFT, 
+	HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, 
 		       HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
 	HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
 		       HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
+	HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT,
+		       HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Route",
+		.info = snd_harmony_captureroute_info,
+		.get = snd_harmony_captureroute_get,
+		.put = snd_harmony_captureroute_put
+	},
+	HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT,
+		       HARMONY_GAIN_SE_SHIFT, 1, 0),
+	HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT,
+		       HARMONY_GAIN_LE_SHIFT, 1, 0),
+	HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT,
+		       HARMONY_GAIN_HE_SHIFT, 1, 0),
 };
 
 static void __init 
@@ -852,14 +932,14 @@
 	memset(&h->pbuf, 0, sizeof(h->pbuf));
 	memset(&h->cbuf, 0, sizeof(h->cbuf));
 
-	h->hpa = padev->hpa;
+	h->hpa = padev->hpa.start;
 	h->card = card;
 	h->dev = padev;
 	h->irq = padev->irq;
-	h->iobase = ioremap_nocache(padev->hpa, HARMONY_SIZE);
+	h->iobase = ioremap_nocache(padev->hpa.start, HARMONY_SIZE);
 	if (h->iobase == NULL) {
 		printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
-		       padev->hpa);
+		       padev->hpa.start);
 		err = -EBUSY;
 		goto free_and_ret;
 	}
diff --git a/sound/parisc/harmony.h b/sound/parisc/harmony.h
index ef77f9a..526c523 100644
--- a/sound/parisc/harmony.h
+++ b/sound/parisc/harmony.h
@@ -61,7 +61,7 @@
 #define HARMONY_SIZE       64
 
 #define BUF_SIZE     PAGE_SIZE
-#define MAX_BUFS     10
+#define MAX_BUFS     16
 #define MAX_BUF_SIZE (MAX_BUFS * BUF_SIZE)
 
 #define PLAYBACK_BUFS    MAX_BUFS
@@ -101,28 +101,31 @@
 #define HARMONY_SS_MONO         0x00000000
 #define HARMONY_SS_STEREO       0x00000001
 
-#define HARMONY_GAIN_SILENCE    0x00F00FFF
-#define HARMONY_GAIN_DEFAULT    0x0FF00000
+#define HARMONY_GAIN_SILENCE    0x01F00FFF
+#define HARMONY_GAIN_DEFAULT    0x01F00FFF
 
-#define HARMONY_GAIN_HE_SHIFT   27
+#define HARMONY_GAIN_HE_SHIFT   27 /* headphones enabled */
 #define HARMONY_GAIN_HE_MASK    (1 << HARMONY_GAIN_HE_SHIFT)
-#define HARMONY_GAIN_LE_SHIFT   26
+#define HARMONY_GAIN_LE_SHIFT   26 /* line-out enabled */
 #define HARMONY_GAIN_LE_MASK    (1 << HARMONY_GAIN_LE_SHIFT)
-#define HARMONY_GAIN_SE_SHIFT   25
+#define HARMONY_GAIN_SE_SHIFT   25 /* internal-speaker enabled */
 #define HARMONY_GAIN_SE_MASK    (1 << HARMONY_GAIN_SE_SHIFT)
-#define HARMONY_GAIN_IS_SHIFT   24
+#define HARMONY_GAIN_IS_SHIFT   24 /* input select - 0 for line, 1 for mic */
 #define HARMONY_GAIN_IS_MASK    (1 << HARMONY_GAIN_IS_SHIFT)
 
+/* monitor attenuation */
 #define HARMONY_GAIN_MA         0x0f
 #define HARMONY_GAIN_MA_SHIFT   20
 #define HARMONY_GAIN_MA_MASK    (HARMONY_GAIN_MA << HARMONY_GAIN_MA_SHIFT)
 
+/* input gain */
 #define HARMONY_GAIN_IN         0x0f
 #define HARMONY_GAIN_LI_SHIFT   16
 #define HARMONY_GAIN_LI_MASK    (HARMONY_GAIN_IN << HARMONY_GAIN_LI_SHIFT)
 #define HARMONY_GAIN_RI_SHIFT   12
 #define HARMONY_GAIN_RI_MASK    (HARMONY_GAIN_IN << HARMONY_GAIN_RI_SHIFT)
 
+/* output gain (master volume) */
 #define HARMONY_GAIN_OUT        0x3f
 #define HARMONY_GAIN_LO_SHIFT   6
 #define HARMONY_GAIN_LO_MASK    (HARMONY_GAIN_OUT << HARMONY_GAIN_LO_SHIFT)
diff --git a/sound/pci/ac97/ac97_bus.c b/sound/pci/ac97/ac97_bus.c
index becbc42..ec70fad 100644
--- a/sound/pci/ac97/ac97_bus.c
+++ b/sound/pci/ac97/ac97_bus.c
@@ -31,7 +31,8 @@
 	int ret = 0;
 
 	if (dev->driver && dev->driver->suspend)
-		ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
+		ret = dev->driver->suspend(dev, state);
+
 	return ret;
 }
 
@@ -40,7 +41,8 @@
 	int ret = 0;
 
 	if (dev->driver && dev->driver->resume)
-		ret = dev->driver->resume(dev, RESUME_POWER_ON);
+		ret = dev->driver->resume(dev);
+
 	return ret;
 }
 
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 2236c95..01d98ee 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -761,15 +761,18 @@
 
 #define BT_DEVICE(chip, subvend, subdev, rate) \
 	{ .vendor = PCI_VENDOR_ID_BROOKTREE, \
-	  .device = PCI_DEVICE_ID_BROOKTREE_##chip, \
+	  .device = chip, \
 	  .subvendor = subvend, .subdevice = subdev, \
 	  .driver_data = rate }
 
 /* driver_data is the default digital_rate value for that device */
 static struct pci_device_id snd_bt87x_ids[] = {
-	BT_DEVICE(878, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */
-	BT_DEVICE(879, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */
-	BT_DEVICE(878, 0x0070, 0xff01, 44100), /* Viewcast Osprey 200 */
+	/* Hauppauge WinTV series */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000),
+	/* Hauppauge WinTV series */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
+	/* Viewcast Osprey 200 */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 31ea7a4..1681ee1 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -31,14 +31,14 @@
 #include "pmac.h"
 
 struct snd_pmac_beep {
-	int running;	/* boolean */
-	int volume;	/* mixer volume: 0-100 */
+	int running;		/* boolean */
+	int volume;		/* mixer volume: 0-100 */
 	int volume_play;	/* currently playing volume */
 	int hz;
 	int nsamples;
 	short *buf;		/* allocated wave buffer */
 	dma_addr_t addr;	/* physical address of buffer */
-	struct input_dev dev;
+	struct input_dev *dev;
 };
 
 /*
@@ -212,47 +212,55 @@
 int __init snd_pmac_attach_beep(pmac_t *chip)
 {
 	pmac_beep_t *beep;
-	int err;
+	struct input_dev *input_dev;
+	void *dmabuf;
+	int err = -ENOMEM;
 
-	beep = kmalloc(sizeof(*beep), GFP_KERNEL);
-	if (! beep)
-		return -ENOMEM;
-
-	memset(beep, 0, sizeof(*beep));
-	beep->buf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
-					&beep->addr, GFP_KERNEL);
-
-	beep->dev.evbit[0] = BIT(EV_SND);
-	beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-	beep->dev.event = snd_pmac_beep_event;
-	beep->dev.private = chip;
+	beep = kzalloc(sizeof(*beep), GFP_KERNEL);
+	dmabuf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
+				    &beep->addr, GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!beep || !dmabuf || !input_dev)
+		goto fail;
 
 	/* FIXME: set more better values */
-	beep->dev.name = "PowerMac Beep";
-	beep->dev.phys = "powermac/beep";
-	beep->dev.id.bustype = BUS_ADB;
-	beep->dev.id.vendor = 0x001f;
-	beep->dev.id.product = 0x0001;
-	beep->dev.id.version = 0x0100;
+	input_dev->name = "PowerMac Beep";
+	input_dev->phys = "powermac/beep";
+	input_dev->id.bustype = BUS_ADB;
+	input_dev->id.vendor = 0x001f;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
 
+	input_dev->evbit[0] = BIT(EV_SND);
+	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	input_dev->event = snd_pmac_beep_event;
+	input_dev->private = chip;
+	input_dev->cdev.dev = &chip->pdev->dev;
+
+	beep->dev = input_dev;
+	beep->buf = dmabuf;
 	beep->volume = BEEP_VOLUME;
 	beep->running = 0;
-	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip))) < 0) {
-		kfree(beep->buf);
-		kfree(beep);
-		return err;
-	}
+
+	err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip));
+	if (err < 0)
+		goto fail;
 
 	chip->beep = beep;
-	input_register_device(&beep->dev);
+	input_register_device(beep->dev);
 
 	return 0;
+
+ fail:	input_free_device(input_dev);
+	kfree(dmabuf);
+	kfree(beep);
+	return err;
 }
 
 void snd_pmac_detach_beep(pmac_t *chip)
 {
 	if (chip->beep) {
-		input_unregister_device(&chip->beep->dev);
+		input_unregister_device(chip->beep->dev);
 		dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
 				  chip->beep->buf, chip->beep->addr);
 		kfree(chip->beep);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 954f994..394b53e 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -174,7 +174,7 @@
 
 	devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
 			S_IFCHR | mode, s->name);
-	class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
+	class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor),
 			    dev, s->name+6);
 	return r;
 
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index e0d0365..f1a2e2c 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -163,7 +163,7 @@
 /*
  * Submits the URB, with error handling.
  */
-static int snd_usbmidi_submit_urb(struct urb* urb, int flags)
+static int snd_usbmidi_submit_urb(struct urb* urb, gfp_t flags)
 {
 	int err = usb_submit_urb(urb, flags);
 	if (err < 0 && err != -ENODEV)